OLE clipboard format

0

Witam grupowiczów.
Hostuję kontrolkę WebBrowser2 w okienku. Dodałem w programie kilka features m.in. drag-drop (custom IDropTarget, bo DragAcceptFiles pozwala tylko na lokalne pliki).
Problem w tym że nie znam ani nie mogę znaleźć danych na temat formatu danych dostępnych w IDataSource podczas "upuszczania" linków (anchorów) z jednego browsera do innego
Drop'ując pojedynczy link i wybierając tylko TYMED_HGLOBAL w IEnumFormatETC mam m.in. takie dane:

FORMATETC.cfFormat = 0xC0B7
STGMEDIUM.tymed = TYMED_HGLOBAL
STGMEDIUM.data = http://blah.com (pełnowartościowy url)

gdzie STGMEDIUM.data to wynik z GlobalLock(.hGlobal)
Stałej 0xC0B7 nie mogę znaleźć w żadnym .h, nawet dopisując zera i konwertując do systemu dziesiętnego.

cfFormat przybiera jeszcze kika innych postaci: standardowy CF_TEXT, CF_HGLOBAL, jak i jakieś ole-prywatne gdzie data jest w formacie tekstu html(0xC0B2) lub rtf(0xC0E0)

Pytanie: kto wie gdzie szukać info o tych formatach?

0

Nie wszystkie formaty schowka muszą być zdefiniowane w plikach H. (vide RegisterClipboardFormat). Spróbuj wyciągnąć nazwę formatu funkcją GetClipboardFormatName.

0

pokazało mi UniformResourceLocator (dla anchorów).
Po przeskanowaniu /include znalazłem interface i const string, nic poza tym.
Ok, przestałem szukać i owy typ (zawartość) schowka wpakowałem do struktury DROPFILES i posłałem do okna... działa :)
Jeszcze brakuje cyferek dla wersji unicode

0

No tak, tylko musisz wiedzieć, że ta liczba może się zmieniać (o ile nie jest to format predefiniowany przez system) ;) U mnie oznacza co innego (coś-tam-automation).

0

Oj to źle jeśli u Ciebie jest inna nazwa tego formatu; czyżbym musiał porównywać te formaty według nazwy ?
Prawdę mówiąc RegisterClipboardFormat zwraca losowe wartości, więc raczej tak.

Yup, napisałem to tak:

IDropTargetNoRefs :: DragEnter(IDataObject *pDataObj,DWORD grfKeyState,POINTL *pt,DWORD *pdwEffect),HRESULT
{
   STGMEDIUM medium;

   if FindFormat(pDataObj, medium)
   {
      ReleaseStgMedium(medium);
      return S_OK;
   }
   pdwEffect = DROPEFFECT_NONE;

   return S_FALSE;
}

IDropTargetNoRefs :: Drop(IDataObject *pDataObj,DWORD grfKeyState,POINTL *pt,DWORD *pdwEffect),HRESULT
{
   LRESULT not_processed = 1;
   STGMEDIUM medium;

   if FindFormat(pDataObj, medium)
   {
      not_processed = SendMessage(m_hwndParent, WM_DROPFILES, medium.hGlobal, 0);
      if (not_processed) ReleaseStgMedium(medium);
   }
   return S_OK;
}

// custom named constant (ansi version)
//#define CF_UniformResourceLocator 0xC0B7

// custom method
IDropTargetNoRefs :: FindFormat(IDataObject *pDataObj, /*out*/STGMEDIUM outmedium),BOOL
{
   IEnumFORMATETC *penumFormatetc;
   FORMATETC etc;
   STGMEDIUM medium;

   if(!pDataObj->EnumFormatEtc(DATADIR_GET, &penumFormatetc))
   {
      ULONG celtFetched;
      while (!penumFormatetc->Next(1, etc, &celtFetched))
      {
         if (etc.cfFormat == CF_HDROP)
         {
            // a local file
            if (!pDataObj->GetData(etc, outmedium)) return true;
         }
         char cf_name[128];
         GetClipboardFormatName(etc.cfFormat, cf_name, 128)
         if (!strcmp(&cf_name, "UniformResourceLocator"))
         {
            // a anchor
            if (!pDataObj->GetData(etc, medium))
            {
               string *data = GlobalLock(medium.hGlobal);
               void *hdf = GlobalAlloc(GMEM_MOVEABLE, strlen(*data) + 1 + sizeof(DROPFILES));
               if (hdf)
               {
                  DROPFILES *df  = GlobalLock(hdf);
                  if (df)
                  {
                     outmedium.tymed = TYMED_HGLOBAL;
                     outmedium.hGlobal = hdf;
                     outmedium.pUnkForRelease = null;
                     df->pFiles = sizeof(DROPFILES);
                     df->fWide  = false;
                     strcpy(df+sizeof(DROPFILES), data);
                     GlobalUnlock(hdf);
                     GlobalUnlock(medium.hGlobal);
                     return true;
                  }
                  else GlobalFree(hdf);
               }
               GlobalUnlock(medium.hGlobal);
            }
         }
      }
      penumFormatetc->Release();
   }
   return false;
}
0

czyżbym musiał porównywać te formaty według nazwy ?

A po co??? Wystarczy żebyś miał poprawną nazwę formatu, którą wpuszczasz do RegisterClipboardFormat. Wtedy ID formatu możesz uzyskać/zarejestrować przy starcie aplikacji.

Zdefiniuj:

#define CF_UNIFORMRESOURCELOCATOR "UniformResourceLocator"

i zrób np. tak:

...
while (!penumFormatetc->Next(1, etc, &celtFetched))
{
         if (etc.cfFormat == CF_HDROP)
         {
            // a local file
            if (!pDataObj->GetData(etc, outmedium)) return true;
         }
         UINT cfURLID=RegisterClipboardFormat(CF_UNIFORMRESOURCELOCATOR);
         if (etc.cfFormat!=cfURLID)
         {
          ...
         }
    ...
}

Prawdę mówiąc RegisterClipboardFormat zwraca losowe wartości, więc raczej tak.

No nie takie losowe bo: If a registered format with the specified name already exists, a new format is not registered and the return value identifies the existing format

0

Może niezakładając nowego threadu spytam tutaj o bardziej zaawansowane hostowanie browsera.
Otóż jest problem z messageboxem gdy jakiś objekt na stronie jest NULL'em, bo msgbox się pokazuje. Wchodząc na jakąś stronę ze skryptami ściąganymi ze zbanowanych hostów (reklamy google,gemius,hitstat, adbrite...) rozlega się wspaniały sound MB_ICONSTOP jeśli jakaś funkcja na stronie odwołuje się do nieistniejącego obiektu.

Box z informacją o błędzie skryptu ubijam w implementacji IOleCommandTarget.
W dokumentacji pisze że w metodzie IDocHostShowUI::ShowMessage zwracając S_OK, MSHTML nie wywala swojego okienka, ale tak się nie dzieje; nawet ta metoda nie jest wykonana przed faktem.
Nawigując do pliku ze skryptem external.blah("hello ole!"); i jednocześnie blokując external w containerze - wywala msgboxa z informacją że external is null or no object.
W opcjach IE można to zablokować, więc w prostym programiku też gdzieś się da

Zeby nie było niejasności - każda klasa containera ma pointer do głównej klasy IUnknown gdzie rozdzielam interface, więc prawie wszystko czego browser chce to dostaje. IID_IDocHostShowUI jest sprawdzane i odpowiednia klasa jest zwracana.

Czego może brakować?

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.