Zpracování scénářů přenosu dat v shell prostředí

Datový objekt prostředí dokument popisuje obecný přístup používaný k přenosu shellových dat pomocí přetažení nebo Schránky. Pokud ale chcete ve své aplikaci implementovat přenos dat Shellu, musíte také pochopit, jak tyto obecné principy a techniky aplikovat na různé způsoby přenosu dat Shellu. Tento dokument představuje běžné scénáře přenosu dat v prostředí Shell a popisuje, jak každý z nich implementovat ve vaší aplikaci.

Poznámka

I když každý z těchto scénářů popisuje konkrétní operaci přenosu dat, mnoho z nich platí pro různé související scénáře. Například hlavní rozdíl mezi většinou přenosů pomocí schránky a přetahováním je způsob, jakým se datový objekt dostane k cíli. Jakmile má cíl ukazatel na rozhraní datového objektu IDataObject, postupy pro extrahování informací jsou z velké části stejné pro oba typy přenosu dat. Některé scénáře jsou ale omezené na konkrétní typ operace. Podrobnosti najdete v jednotlivých scénářích.

 

Obecné pokyny

Každá z následujících částí popisuje jeden, poměrně specifický scénář přenosu dat. Přenosy dat jsou ale často složitější a můžou zahrnovat aspekty několika scénářů. Obvykle nevíte předem, který scénář budete ve skutečnosti potřebovat zpracovat. Tady je několik obecných pokynů, které je potřeba mít na paměti.

Pro zdroje dat:

  • Formáty schránky prostředí Shell, s výjimkou CF_HDROP, nejsou předdefinovány. Každý formát, který chcete použít, musí být registrován voláním RegisterClipboardFormat.
  • Formáty v datových objektech jsou poskytovány v pořadí podle preference ze zdroje. Zobrazení výčtu datového objektu a výběr prvního objektu, který můžete použít.
  • Zahrnout tolik formátů, kolik můžete podporovat. Obecně nevíte, kam se datový objekt zahodí. Tento postup zvyšuje pravděpodobnost, že datový objekt bude obsahovat formát, který může cílový objekt přijmout.
  • Existující soubory by měly být nabízeny ve formátu CF_HDROP.
  • Nabídka dat podobných souborům s CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR formáty Tento přístup umožňuje cíli vytvořit soubor z datového objektu, aniž by museli znát cokoli o podkladovém úložišti dat. Data byste normálně měli prezentovat jako rozhraní IStream. Tento mechanismus přenosu dat je flexibilnější než globální objekt paměti a využívá mnohem méně paměti.
  • Při přetahování položek prostředí Windows by zdroje měly nabízet formát CFSTR_SHELLIDLIST. Datové objekty pro položky lze získat buď pomocí IShellFolder::GetUIObjectOf nebo IShellItem::BindToHandler metody. Zdroje dat mohou vytvořit standardní implementaci datového objektu, která podporuje formát CFSTR_SHELLIDLIST pomocí SHCreateDataObject.
  • Cíle přetažení, které chtějí analyzovat položky při přetahování pomocí programovacího modelu shellových položek, mohou převést objekt IDataObject na IShellItemArray pomocí SHCreateShellItemArrayFromDataObject.
  • Používejte standardní kurzory zpětné vazby.
  • Podporuje přetahování doleva a doprava.
  • Použijte samotný datový objekt z vloženého objektu. Tento přístup umožňuje vaší aplikaci načíst jakékoli další formáty, které datový objekt musí nabídnout, a vyhnout se vytvoření další vrstvy omezení. Například vložený objekt ze serveru A se přetáhne ze serveru nebo kontejneru B a zahodí do kontejneru C. C by měl vytvořit vložený objekt serveru A, nikoli vložený objekt serveru B obsahující vložený objekt serveru A.
  • Nezapomeňte, že Shell může při přesouvání souborů používat optimalizované pohyby nebo operace odstranění při vkládání. Vaše aplikace by měla být schopná tyto operace rozpoznat a správně reagovat.

Pro účely dat:

  • Formáty schránky prostředí Shell, s výjimkou CF_HDROP, nejsou předdefinovány. Každý formát, který chcete použít, musí být registrován voláním RegisterClipboardFormat.
  • Implementujte a zaregistrujte jako cíl přetažení pro OLE. Pokud je to možné, nepoužívejte cíle Windows 3.1 ani zprávu WM_DROPFILES.
  • Formáty obsažené datovým objektem se liší v závislosti na tom, odkud objekt pochází. Vzhledem k tomu, že obecně nevíte, odkud datový objekt pochází, nepředpokládáte, že bude existovat konkrétní formát. Datový objekt by měl vytvořit výčet formátů v pořadí kvality, počínaje nejlepším. Chcete-li tedy získat nejlepší dostupný formát, aplikace obvykle vyčíslují dostupné formáty a používají první formát v výčtu, který mohou podporovat.
  • Podporuje přetahování pravým tlačítkem myši. Místní nabídku přetažení můžete přizpůsobit vytvořením obslužného programu přetažení.
  • Pokud vaše aplikace přijme existující soubory, musí být schopná zpracovat formát CF_HDROP.
  • Obecně platí, že aplikace, které přijímají soubory, by také měly zpracovávat CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR formáty. Zatímco soubory ze systému souborů mají formát CF_HDROP, soubory od poskytovatelů, jako jsou přípony oboru názvů, obecně používají CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR. Mezi příklady patří složky Windows CE, složky FTP (File Transfer Protocol), webové složky a složky CAB. Zdroj obvykle implementuje rozhraní IStream k prezentaci dat z úložiště jako souboru.
  • Nezapomeňte, že Shell může při přesouvání souborů používat optimalizované pohyby nebo operace odstranění při vkládání. Vaše aplikace by měla být schopná tyto operace rozpoznat a správně reagovat.

Kopírování názvů souborů ze schránky do aplikace

Scenario: Uživatel vybere jeden nebo více souborů v průzkumníku Windows a zkopíruje je do schránky. Aplikace extrahuje názvy souborů a vloží je do dokumentu.

Tento scénář můžete použít například k tomu, aby uživatel mohl vytvořit odkaz HTML zkopírováním a vložením souboru do vaší aplikace. Aplikace pak může extrahovat název souboru z datového objektu a zpracovat ho a vytvořit značku ukotvení.

Když uživatel vybere soubor v průzkumníku Windows a zkopíruje ho do schránky, vytvoří prostředí datový objekt. Potom volá OleSetClipboard umístit ukazatel na IDataObject rozhraní objektu dat do schránky.

Když uživatel vybere příkaz Vložit z nabídky nebo panelu nástrojů aplikace:

  1. Pro načtení rozhraní datového objektu IDataObject zavolejte OleGetClipboard.
  2. Volání IDataObject::EnumFormatEtc za účelem vyžádání objektu enumerátoru.
  3. Použijte rozhraní objektu enumerátoru IEnumFORMATETC k vyčíslení formátů obsažených v datovém objektu.

Poznámka

Poslední dva kroky v tomto postupu jsou zahrnuty pro úplnost. Obvykle nejsou nezbytné pro jednoduché přenosy souborů. Všechny datové objekty používané pro tento typ přenosu dat by měly obsahovat formát CF_HDROP, který lze použít k určení názvů souborů obsažených objektem. Pro obecnější přenosy dat byste ale měli vytvořit výčet formátů a vybrat tu nejlepší, kterou vaše aplikace dokáže zpracovat.

 

Extrahování názvů souborů z datového objektu

Dalším krokem je extrakce jednoho nebo více názvů souborů z datového objektu a jejich vložení do aplikace. Všimněte si, že postup probíraný v této části platí jak pro extrahování názvu souboru z datového objektu, tak pro přenosy pomocí metoda přetažení myší.

Nejjednodušší způsob, jak načíst názvy souborů z datového objektu, je formát CF_HDROP:

  1. Volání IDataObject::GetData. Nastavte člen cfFormat struktury FORMATETC na CF_HDROP a člen tymed na TYMED_HGLOBAL. Člen dwAspect je obvykle nastaven na DVASPECT_CONTENT. Pokud ale potřebujete mít cestu k souboru ve krátkém formátu (8,3), nastavte dwAspect na DVASPECT_SHORT.

    Když IDataObject::GetData vrátí, hGlobal člen struktury STGMEDIUM odkazuje na objekt globální paměti, který obsahuje data.

  2. Vytvořte proměnnou HDROP a nastavte ji na hGlobal člena struktury STGMEDIUM. Proměnná HDROP je nyní popisovačem DROPFILES struktuře následovaná dvojitě nulovým ukončeným řetězcem obsahujícím plně kvalifikované cesty ke zkopírovaným souborům.

  3. Určete, kolik cest k souborům je v seznamu voláním DragQueryFile s parametrem iFile nastaveným na 0xFFFFFFFF. Funkce vrátí počet cest k souborům v seznamu. V dalším kroku se k identifikaci konkrétní cesty používá index založený na nule v tomto seznamu.

  4. Extrahujte cesty k souborům z globálního objektu paměti voláním DragQueryFile jednou pro každý soubor s iFile nastavenou na index souboru.

  5. Podle potřeby zpracujte cesty k souborům a vložte je do aplikace.

  6. Volejte ReleaseStgMedium a předejte ukazatel na strukturu STGMEDIUM, kterou jste předali IDataObject::GetData v kroku 1. Jakmile strukturu uvolníte, hodnota HDROP, kterou jste vytvořili v kroku 2, už není platná a neměla by se používat.

Kopírování obsahu vyřazeného souboru do aplikace

Scenario: Uživatel přetáhne jeden nebo více souborů z průzkumníka Windows a zahodí je do okna aplikace. Aplikace extrahuje obsah souboru (s) a vloží ho do aplikace.

Tento scénář používá přetažení k přenosu souborů z Windows Exploreru do aplikace. Před operací musí vaše aplikace:

  1. Pomocí RegisterClipboardFormat zaregistrujte všechny potřebné formáty schránky Shell.
  2. Volání RegisterDragDrop pro registraci cílového okna a rozhraníIDropTarget vaší aplikace.

Jakmile uživatel zahájí operaci tak, že vybere jeden nebo více souborů a začne je přetahovat:

  1. Windows Explorer vytvoří datový objekt a načte do něj podporované formáty.
  2. Windows Explorer volá DoDragDrop k zahájení smyčky přetažení.
  3. Když obrázek přetažení dosáhne cílového okna, systém vás upozorní voláním IDropTarget::D ragEnter.
  4. Chcete-li zjistit, co datový objekt obsahuje, zavolejte metodu objektu dat IDataObject::EnumFormatEtc. Použijte enumerator objekt vrácený metodou k vytvoření výčtu formátů obsažených datovým objektem. Pokud vaše aplikace nechce přijmout žádný z těchto formátů, vraťte DROPEFFECT_NONE. Pro účely tohoto scénáře by vaše aplikace měla ignorovat všechny datové objekty, které neobsahují formáty používané k přenosu souborů, například CF_HDROP.
  5. Když uživatel data pustí, systém volá IDropTarget::Drop.
  6. Pomocí rozhraní IDataObject extrahujte obsah souborů.

Existuje několik různých způsobů, jak extrahovat obsah shell objektu z datového objektu. Obecně použijte následující pořadí:

  • Pokud soubor obsahuje CF_TEXT formát, jsou data textEM ANSI. Formát CF_TEXT můžete použít k extrakci dat, nikoli k otevření samotného souboru.
  • Pokud soubor obsahuje propojený nebo vložený objekt OLE, datový objekt obsahuje CF_EMBEDDEDOBJECT formát. K extrakci dat použijte standardní techniky OLE. soubory výstřižků vždy obsahují formát CF_EMBEDDEDOBJECT.
  • Pokud je objekt Shellu ze systému souborů, datový objekt obsahuje CF_HDROP formát s názvy souborů. Extrahujte název souboru z CF_HDROP a zavolejte OleCreateFromFile vytvořit nový propojený nebo vložený objekt. Pro diskuzi o postupu, jak načíst název souboru z formátu CF_HDROP, viz Kopírování názvů souborů ze schránky do aplikace.
  • Pokud datový objekt obsahuje formát CFSTR_FILEDESCRIPTOR, můžete obsah souboru extrahovat z CFSTR_FILECONTENTS formátu souboru. Diskuzi o tomto postupu naleznete v tématu Použití formátu CFSTR_FILECONTENTS k extrakci dat ze souboru.
  • Před Shell verzí 4.71aplikace indikovala, že přenáší typ souborového zástupce nastavením FD_LINKUI v dwFlags členu struktury FILEDESCRIPTOR. Ve novějších verzích Shellu je upřednostňovaným způsobem, jak označit, že se přenášejí zástupci, použití formátu CFSTR_PREFERREDDROPEFFECT nastaveného na DROPEFFECT_LINK. Tento přístup je mnohem efektivnější než extrakce struktury FILEDESCRIPTOR pouze ke kontrole příznaku.

Pokud bude proces extrakce dat zdlouhavý, můžete operaci provést asynchronně ve vlákně na pozadí. Primární vlákno pak může pokračovat bez zbytečných zpoždění. Pro podrobnosti o zpracování asynchronní extrakce dat viz Přetahování a upouštění shellových objektů asynchronně.

Extrakce dat ze souboru pomocí formátu CFSTR_FILECONTENTS

Formát CFSTR_FILECONTENTS poskytuje velmi flexibilní a výkonný způsob přenosu obsahu souboru. Ani není nutné, aby se data ukládaly jako jeden soubor. To vše, co je vyžadováno pro tento formát, je, že datový objekt prezentuje data cíli, jako by se jednalo o soubor. Skutečná data můžou být například oddíl textového dokumentu nebo blok dat extrahovaných z databáze. Cíl může s daty zacházet jako se souborem a nemusí o základním mechanismu úložiště nic vědět.

Rozšíření oboru názvů obvykle používají CFSTR_FILECONTENTS k přenosu dat, protože tento formát nepředpokládá žádný konkrétní mechanismus úložiště. Rozšíření oboru názvů může používat jakýkoli mechanismus úložiště, který je vhodný, a pomocí tohoto formátu prezentovat své objekty aplikacím, jako by se jednalo o soubory.

Mechanismus přenosu dat pro CFSTR_FILECONTENTS je obvykle TYMED_ISTREAM. Přenos ukazatele rozhraní IStream vyžaduje mnohem méně paměti než načtení dat do globálního objektu paměti a IStream je jednodušší způsob reprezentace dat než IStorage.

Formát CFSTR_FILECONTENTS je vždy doprovázen formátem CFSTR_FILEDESCRIPTOR. Nejprve je nutné prozkoumat obsah tohoto formátu. Pokud se přenáší více než jeden soubor, datový objekt bude ve skutečnosti obsahovat více CFSTR_FILECONTENTS formátů, jeden pro každý soubor. Formát CFSTR_FILEDESCRIPTOR obsahuje název a atributy každého souboru a poskytuje hodnotu indexu pro každý soubor potřebný k extrahování CFSTR_FILECONTENTS formátu konkrétního souboru.

K extrahování formátu CFSTR_FILECONTENTS:

  1. Extrahujte formát CFSTR_FILEDESCRIPTOR jako hodnotu TYMED_HGLOBAL.
  2. hGlobal člen vrácené struktury STGMEDIUM odkazuje na objekt globální paměti. Uzamkněte tento objekt předáním hodnoty hGlobalGlobalLock.
  3. Přetypujte ukazatel vrácený GlobalLock na FILEGROUPDESCRIPTOR ukazatel. Bude odkazovat na FILEGROUPDESCRIPTOR strukturu následovanou jednou nebo více FILEDESCRIPTOR strukturami. Každá FILEDESCRIPTOR struktura obsahuje popis souboru, který je obsažen v jednom z doprovodných formátů CFSTR_FILECONTENTS.
  4. Prozkoumejte struktury FILEDESCRIPTOR a určete, který soubor odpovídá souboru, který chcete extrahovat. Index založený na nule FILEDESCRIPTOR se používá k identifikaci formátu CFSTR_FILECONTENTS souboru. Vzhledem k tomu, že velikost globálního bloku paměti není přesná bajtově, použijte členy struktury nFileSizeLow a nFileSizeHigh k určení, kolik bajtů představuje soubor v objektu globální paměti.
  5. Volání IDataObject::GetData s členem cfFormat struktury FORMATETC nastaveným na hodnotu CFSTR_FILECONTENTS a členem lIndex nastaveným na index, který jste určili v předchozím kroku. "Člen tymed je obvykle nastaven na TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ISTORAGE." Datový objekt pak může zvolit svůj upřednostňovaný mechanismus přenosu dat.
  6. Struktura STGMEDIUM, která IDataObject::GetData vrátí, bude obsahovat ukazatel na data souboru. Prozkoumejte tymed parametr struktury a určete mechanismus přenosu dat.
  7. Pokud je tymed nastaven na TYMED_ISTREAM nebo TYMED_ISTORAGE, použijte rozhraní pro extrahování dat. Pokud je tymed nastaven na TYMED_HGLOBAL, data jsou obsažena v objektu globální paměti. Diskuzi o extrahování dat z globálního objektu paměti najdete v tématu Extrahování globálního paměťového objektu z datového objektu oddílu Objekt dat prostředí.
  8. Voláním GlobalLock odemkněte objekt globální paměti, který jste zamkli v kroku 2.

Zpracování optimalizovaných operací přesunu

Scénář: soubor se přesune ze systému souborů do rozšíření pro obor názvů pomocí optimalizovaného přesunu.

V konvenční operaci přesunutí cíl vytvoří kopii dat a zdroj odstraní původní. Tento postup může být neefektivní, protože vyžaduje dvě kopie dat. U velkých objektů, jako jsou databáze, nemusí být běžná operace přesunutí ani praktická.

Díky optimalizovanému přesunu cíl používá své znalosti o tom, jak jsou data ukládána, aby zvládl celou operaci přesunu. Nikdy není k dispozici druhá kopie dat a není nutné, aby zdroj odstranil původní data. Data Shell jsou vhodná pro optimalizované přesuny, protože cíl dokáže zpracovat celou operaci pomocí rozhraní Shell API. Typickým příkladem je přesouvání souborů. Jakmile má cíl cestu k souboru, který se má přesunout, může k jeho přesunutí použít SHFileOperation. Není potřeba odstranit původní soubor.

Poznámka

Shell obvykle používá optimalizovaný přesun k přesouvání souborů. Aby mohla aplikace správně zpracovávat přenos dat v Shellu, musí být schopná detekovat a zpracovávat optimalizovaný přesun.

 

Optimalizované přesuny se zpracovávají následujícím způsobem:

  1. Zdroj volá DoDragDrop s parametrem dwEffect nastaveným na DROPEFFECT_MOVE označující, že zdrojové objekty lze přesunout.

  2. Cíl obdrží hodnotu DROPEFFECT_MOVE prostřednictvím jedné z jeho IDropTarget metod, což znamená, že přesunutí je povoleno.

  3. Cíl buď zkopíruje objekt (neoptimalizované přesunutí), nebo přesune objekt (optimalizovaný přesun).

  4. Cíl pak zdroji řekne, jestli potřebuje odstranit původní data.

    Optimalizovaný přesun je výchozí operace s daty odstraněnými cílem. Informovat zdroj, že byl proveden optimalizovaný přesun:

      • Cíl nastaví hodnotu pdwEffect, kterou přijal prostřednictvím metody IDropTarget::Drop, na jinou hodnotu než DROPEFFECT_MOVE. Obvykle je nastavená na DROPEFFECT_NONE nebo DROPEFFECT_COPY. Hodnota bude vrácena ke zdroji DoDragDrop.
      • Cíl také volá metodu objektu dat IDataObject::SetData a předá ji identifikátor formátu CFSTR_PERFORMEDDROPEFFECT nastavený na DROPEFFECT_NONE. Toto volání metody je nezbytné, protože některé cílové objekty přetažení nemusí vždy správně nastavit pdwEffect parametr DoDragDrop. Formát CFSTR_PERFORMEDDROPEFFECT představuje spolehlivý způsob, jak označit, že proběhl optimalizovaný přesun.

    Pokud cíl provedl neoptimalizovaný přesun, musí být data odstraněna zdrojem. Abychom informovali původce, že došlo k neoptimálnímu přesunutí:

      • Cíl nastaví hodnotu pdwEffect, kterou přijala prostřednictvím metody IDropTarget::Drop, na DROPEFFECT_MOVE. Hodnota bude vrácena ke zdroji DoDragDrop.
      • Cíl také volá IDataObject::SetData metodu datového objektu a předá jí identifikátor formátu CFSTR_PERFORMEDDROPEFFECT nastavený na DROPEFFECT_MOVE. Toto volání metody je nezbytné, protože některé cílové objekty přetažení nemusí vždy správně nastavit pdwEffect parametr DoDragDrop. Formát CFSTR_PERFORMEDDROPEFFECT je spolehlivý způsob, jak označit, že došlo k neoptimalizovanému přesunu.
  5. Zdroj zkontroluje dvě hodnoty, které může cíl vrátit. Pokud jsou oba nastaveny na DROPEFFECT_MOVE, dokončí neoptimalizovaný přesun odstraněním původních dat. Jinak cíl provedl optimalizovaný krok a původní data byla smazána.

Zpracování operací odstranění při vložení

Scenario: Jeden nebo více souborů se vyjme ze složky v Průzkumníku Windows a vloží se do rozšíření oboru názvů. Průzkumník Windows nechá soubory zvýrazněné, dokud neobdrží zpětnou vazbu na výsledek operace vložení.

Tradičně, když uživatel řezá data, okamžitě zmizí ze zobrazení. To nemusí být efektivní a může vést k problémům s použitelností, pokud se uživatel obává, co se stalo s daty. Alternativním přístupem je použití operace odstranění při vložení.

Při operaci odstranění při vložení se vybraná data okamžitě neodeberou ze zobrazení. Zdrojová aplikace ji místo toho označí jako vybranou, třeba změnou písma nebo barvy pozadí. Jakmile cílová aplikace vloží data, upozorní zdroj na výsledek operace. Pokud cíl provedl optimalizovaný pohyb, zdroj může jednoduše aktualizovat zobrazení. Pokud cíl provedl běžný přesun, musí zdroj také odstranit svou kopii dat. Pokud se vložení nezdaří, zdrojová aplikace obnoví vybraná data do původního vzhledu.

Poznámka

Shell obvykle používá mazání při vložení, když se k přesunutí souborů používá operace vyjmutí a vložení. Operace odstranění při vložení s objekty Shell obvykle používají optimalizovaný přesun souborů. Aby bylo možné správně zpracovávat přenos dat Shellu, musí být vaše aplikace schopná detekovat a zpracovávat operace odstranění při vložení.

 

Zásadním požadavkem pro funkci odstranění při vložení je, že cílová jednotka musí zpětně oznámit výsledek operace zdroji. Standardní techniky Clipboardu však nelze použít k implementaci odstranění při vložení, protože neposkytují způsob, jak by cíl mohl komunikovat se zdrojem. Místo toho cílová aplikace používá metodu IDataObject::SetData metodu datového objektu k hlášení výsledku datového objektu. Datový objekt pak může komunikovat se zdrojem prostřednictvím privátního rozhraní.

Základní postup operace smazání při vložení je následující:

  1. Zdroj označí obrazovku s vybranými daty.
  2. Zdroj vytvoří datový objekt. Označuje operaci vyjmutí přidáním formátu CFSTR_PREFERREDDROPEFFECT s datovou hodnotou DROPEFFECT_MOVE.
  3. Zdroj umístí datový objekt do Schránky pomocí OleSetClipboard.
  4. Cíl načte datový objekt ze schránky pomocí OleGetClipboard.
  5. Cíl extrahuje data CFSTR_PREFERREDDROPEFFECT. Pokud je nastavená pouze DROPEFFECT_MOVE, cíl může buď provést optimalizovaný přesun, nebo jednoduše zkopírovat data.
  6. Pokud cíl neprovádí optimalizovaný přesun, zavolá metodu IDataObject::SetData s formátem CFSTR_PERFORMEDDROPEFFECT nastaveným na DROPEFFECT_MOVE.
  7. Po dokončení vložení cíl volá metodu IDataObject::SetData s formátem CFSTR_PASTESUCCEEDED nastaveným na DROPEFFECT_MOVE.
  8. Pokud je volána metoda IDataObject::SetData s formátem CFSTR_PASTESUCCEEDED nastaveným na DROPEFFECT_MOVE, musí zkontrolovat, jestli také obdržela formát CFSTR_PERFORMEDDROPEFFECT nastavený na DROPEFFECT_MOVE. Pokud cíl odešle oba formáty, zdroj bude muset odstranit data. Pokud je přijat pouze CFSTR_PASTESUCCEEDED formát, zdroj může jednoduše odebrat data z jeho zobrazení. Pokud přenos selže, zdroj aktualizuje zobrazení na původní vzhled.

Přenos dat do a z virtuálních složek

Scénář: Uživatel přetáhne objekt z virtuální složky nebo ho zahodí do virtuální složky.

Virtuální složky obsahují objekty, které obecně nejsou součástí systému souborů. Některé virtuální složky, například Koš, mohou představovat data uložená na pevném disku, ale ne jako běžné objekty systému souborů. Některé můžou představovat uložená data, která jsou ve vzdáleném systému, jako je kapesní počítač nebo server FTP. Jiné, například složka Tiskárny, obsahují objekty, které vůbec nepředstavují uložená data. Zatímco některé virtuální složky jsou součástí systému, můžou vývojáři také vytvářet a instalovat vlastní virtuální složky implementací rozšíření oboru názvů.

Bez ohledu na typ dat nebo způsob jejich uložení jsou objekty složek a souborů obsažené ve virtuální složce prezentovány prostředím, jako by šlo o normální soubory a složky. Je odpovědností virtuální složky vzít veškerá data, která obsahuje, a odpovídajícím způsobem je předat prostředí Shellu. Tento požadavek znamená, že virtuální složky normálně podporují přenosy dat přetažením a schránkou.

Existují tedy dvě skupiny vývojářů, kteří se musí zabývat přenosem dat do a z virtuálních složek:

  • Vývojáři, jejichž aplikace potřebují přijímat data přenášená z virtuální složky.
  • Vývojáři, jejichž rozšíření jmenného prostoru potřebují podporu přenosu dat.

Příjem dat z virtuální složky

Virtuální složky můžou představovat prakticky jakýkoli typ dat a můžou tato data ukládat jakýmkoli způsobem, který si vyberou. Některé virtuální složky můžou ve skutečnosti obsahovat normální soubory a složky systému souborů. Ostatní můžou například zabalit všechny své objekty do jednoho dokumentu nebo databáze.

Pokud je objekt systému souborů přenesen do aplikace, datový objekt obvykle obsahuje CF_HDROP formát s plně kvalifikovanou cestou objektu. Aplikace může extrahovat tento řetězec a pomocí normálních funkcí systému souborů otevřít soubor a extrahovat jeho data. Vzhledem k tomu, že virtuální složky obvykle neobsahují normální objekty systému souborů, obvykle nepoužívají CF_HDROP.

Místo CF_HDROPse data obvykle přenášejí z virtuálních složek s formáty CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS. Formát CFSTR_FILECONTENTS má oproti CF_HDROPdvě výhody:

  • Nepředpokládá se žádná konkrétní metoda úložiště dat.
  • Formát je flexibilnější. Podporuje tři mechanismy přenosu dat: globální objekt paměti, rozhraní IStream nebo rozhraní IStorage.

Globální paměťové objekty se zřídka používají k přenosu dat do nebo z virtuálních objektů, protože data se musí zkopírovat do paměti v celém rozsahu. Přenos ukazatele rozhraní vyžaduje téměř žádnou paměť a je mnohem efektivnější. U velmi velkých souborů může být jediným praktickým mechanismem přenosu dat ukazatel rozhraní. Data jsou obvykle reprezentována ukazatelem IStream, protože toto rozhraní je poněkud flexibilnější než IStorage. Cíl extrahuje ukazatel z datového objektu a pomocí metod rozhraní extrahuje data.

Další informace o tom, jak zpracovávat formáty CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS, najdete v tématu Použití formátu CFSTR_FILECONTENTS k extrakci dat ze souboru.

Přenos dat do a z rozšíření NameSpace

Při implementaci rozšíření oboru názvů budete normálně chtít podporovat možnosti přetažení. Postupujte podle doporučení pro odstraňování zdrojů a cílů probíraných v obecných pokynech. Rozšíření oboru názvů musí konkrétně:

  • Dokáže zpracovat formáty CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS. Tyto dva formáty se obvykle používají k přenosu objektů do a z rozšíření oboru názvů.
  • Schopen zvládnout optimalizované přesuny . Shell očekává, že objekty Shellu budou přesunuty optimalizovaným způsobem.
  • Dokáže zpracovat operaci odstranění při vložení. Shell používá příkaz delete-on-paste, když se objekty přesunou z Shellu pomocí operace vyjmutí/vložení.
  • Být schopen zpracovat přenos dat prostřednictvím rozhraní IStream nebo IStorage. Přenos dat do nebo z virtuální složky se obvykle zpracovává přenosem jednoho z těchto dvou ukazatelů rozhraní, obvykle IStream ukazatel. Cíl pak zavolá metody rozhraní pro extrahování dat:
      • Jako zdroj dat musí rozšíření jmenného prostoru extrahovat data z úložiště a předat je prostřednictvím tohoto rozhraní do cíle.
      • Jako cíl přetažení musí rozšíření oboru názvů přijímat data ze zdroje prostřednictvím tohoto rozhraní a správně je ukládat.

Vyřazení souborů do koše

scénář : Uživatel zahodí soubor do koše . Vaše aplikace nebo přípona oboru názvů odstraní původní soubor.

Koš je virtuální složka, která se používá jako úložiště pro soubory, které již nejsou potřebné. Dokud koš nevyprázdníte, uživatel může později soubor obnovit a vrátit ho do systému souborů.

Ve většině případů funguje přenos objektů Shell do koše podobně jako jakákoli jiná složka. Když ale uživatel zahodí soubor do koše , zdroj musí odstranit původní, i když zpětná vazba ze složky indikuje operaci kopírování. Za normálních okolností nemá zdroj stahování žádný způsob, jak vědět, na kterou složku byl jeho datový objekt upuštěn. U systémů Windows 2000 a novějších však při přetažení datového objektu do Recycle Bin systém Shell zavolá metodu IDataObject::SetData s formátem CFSTR_TARGETCLSID nastaveným na identifikátor třídy koše (CLSID) (CLSID_RecycleBin). Aby bylo možné správně zpracovat případ koše, měl by datový objekt rozpoznat tento formát a sdělit informace zdroji prostřednictvím privátního rozhraní.

Poznámka

Při IDataObject::SetData je volána s formátem CFSTR_TARGETCLSID nastaveným na CLSID_RecycleBin, zdroj dat by měl zavřít všechny otevřené popisovače na objekty, které se před vrácením z metody přenesou. Jinak můžete vytvořit porušení sdílení.

 

Vytváření a import souborů výstřižků

Scenario: Uživatel přetáhne některá data z datového souboru aplikace OLE a zahodí je na plochu nebo Windows Exploreru.

Windows umožňuje uživatelům přetáhnout objekt z datového souboru aplikace OLE a umístit ho na plochu nebo do složky systému souborů. Tato operace vytvoří výstřižkový soubor, který obsahuje data nebo odkaz na data. Název souboru je převzat z krátkého názvu registrovaného pro CLSID objektu a CF_TEXT data. Aby prostředí Shell vytvořilo soubor výstřižku obsahující data, musí rozhraní IDataObject aplikace podporovat formát schránky CF_EMBEDSOURCE. Pokud chcete vytvořit soubor obsahující odkaz, IDataObject musí podporovat formát CF_LINKSOURCE.

Existují také tři volitelné funkce, které může aplikace implementovat pro podporu souborů výstřižků:

  • Podpora obousměrné komunikace
  • Formáty dat uložených v mezipaměti
  • Zpožděné vykreslování

Podpora zpáteční cesty

zpáteční cesta zahrnuje přenos datového objektu do jiného kontejneru a potom zpět do původního dokumentu. Uživatel může například přenést skupinu buněk z tabulky na plochu a vytvořit soubor šrotu s daty. Pokud pak uživatel přenese výstřižek zpět do tabulky, musí být data integrovaná do dokumentu, jak tomu bylo před původním přenosem.

Když shell vytvoří soubor výstřižku, představuje data jako vložený objekt. Když se výstřižek přenese do jiného kontejneru, přenese se jako vložený objekt, i když se vrátí do původního dokumentu. Vaše aplikace zodpovídá za určení formátu dat obsaženého ve výstřižku a vložení dat zpět do nativního formátu v případě potřeby.

Chcete-li vytvořit formát vloženého objektu, určete jeho CLSID načtením CF_OBJECTDESCRIPTOR formátu objektu. Pokud CLSID označuje formát dat, který patří do aplikace, měl by přenést nativní data místo volání OleCreateFromData.

Formáty dat uložených v mezipaměti

Když Shell vytvoří soubor výstřižku, zkontroluje registr seznam dostupných formátů. Ve výchozím nastavení jsou k dispozici dva formáty: CF_EMBEDSOURCE a CF_LINKSOURCE. Existuje ale řada scénářů, ve kterých můžou aplikace potřebovat soubory v různých formátech:

  • Chcete-li umožnit, aby se šroty přenesly do kontejnerů jiných než OLE, které nemohou přijmout vložené formáty objektů.
  • Aby mohly sady aplikací komunikovat s privátním formátem.
  • Aby bylo snazší zvládnout zpáteční cesty.

Aplikace můžou do výstřižku přidávat formáty tím, že je uloží do mezipaměti v registru. Existují dva typy formátů uložených v mezipaměti:

  • Prioritní formáty mezipaměti Pro tyto formáty se data zkopírují v plném rozsahu do výstřižku z datového objektu.
  • Formáty zpožděného vykreslení U těchto formátů se datový objekt nezkopíruje do výstřižku. Místo toho se vykreslování zpozdí, dokud cílový prvek nevyžádá si data. Zpožděné vykreslování je podrobněji popsáno v další části.

Pokud chcete přidat formát mezipaměti s prioritou nebo zpožděně vykreslený formát, vytvořte podklíč DataFormat pod klíčem CLSID aplikace, která je zdrojem dat. Pod tímto podklíčem vytvořte PriorityCacheFormats nebo DelayRenderFormats podklíč. Pro každou prioritní mezipaměť nebo zpožděně vykreslený formát vytvořte číslovaný podklíč, který začíná nulou. Nastavte hodnotu tohoto klíče na řetězec s registrovaným názvem formátu nebo hodnotou #X, kde X představuje číslo formátu standardního formátu schránky.

Následující ukázka ukazuje formáty uložené v mezipaměti pro dvě aplikace. Aplikace MyProg1 má formát RTF jako prioritní formát mezipaměti a soukromý formát „Můj formát“ jako formát se zpožděním vykreslení. Aplikace MyProg2 má formát CF_BITMAP (#8) jako formát mezipaměti s prioritou.

HKEY_CLASSES_ROOT
   CLSID
      {GUID}
         (Default) = MyProg1
         DataFormats
            PriorityCacheFormats
               0
                  (Default) = Rich Text Format
            DelayRenderFormats
               0
                  (Default) = My Format
      {GUID}
         (Default) = MyProg2
         DataFormats
            PriorityCacheFormats
               0
                  (Default) = #8

Další formáty lze přidat vytvořením dalších číslovaných podklíčů.

Zpožděné vykreslování

Zpožděný formát vykreslování umožňuje aplikaci vytvořit soubor výstřižku, ale zpozdit náklady na vykreslení dat, dokud nebude požadován cílem. Rozhraní IDataObject výstřižku nabídne cíli formáty zpožděného vykreslování spolu s nativními a uloženými daty v mezipaměti. Pokud cíl požaduje zpožděný formát vykreslování, shell spustí aplikaci a poskytne data cíli z aktivního objektu.

Poznámka

Vzhledem k tomu, že opožděné vykreslování je poněkud rizikové, mělo by se používat s opatrností. Nebude fungovat, pokud server není k dispozici nebo v aplikacích, které nejsou povolené technologií OLE.

 

Asynchronní přetahování shell objektů

Scénář: Uživatel přenese velký blok dat ze zdroje do cíle. Aby se zabránilo blokování obou aplikací po dlouhou dobu, cíl extrahuje data asynchronně.

Za normálních okolností je přetahování synchronní operace. Ve stručnosti:

  1. Zdroj přetažení volá DoDragDrop a blokuje své primární vlákno, dokud se funkce nevrátí. Blokování primárního vlákna obvykle blokuje zpracování uživatelského rozhraní.
  2. Po zavolání metody IDropTarget::Drop cíl extrahuje data z datového objektu v primárním vlákně. Tento postup obvykle blokuje zpracování uživatelského rozhraní cíle po dobu trvání procesu extrakce.
  3. Jakmile jsou data extrahována, cíl vrátí IDropTarget::Drop volání, systém vrátí DoDragDropa obě vlákna mohou pokračovat.

Stručně řečeno, synchronní přenos dat může blokovat primární vlákna obou aplikací po dlouhou dobu. Konkrétně musí obě vlákna čekat, než cíl extrahuje data. U malých objemů dat je doba potřebná k extrakci dat malá a synchronní přenos dat funguje poměrně dobře. Synchronní extrakce velkých objemů dat ale může způsobit zdlouhavé zpoždění a narušit uživatelské rozhraní cíle i zdroje.

Rozhraní IAsyncOperation/IDataObjectAsyncCapability je volitelné rozhraní, které lze implementovat datovým objektem. Poskytuje cílovému objektu schopnost asynchronně extrahovat data z datového objektu na vlákně pozadí. Jakmile se extrakce dat předá vláknu na pozadí, primární vlákna obou aplikací mohou pokračovat.

Použití IASyncOperation/IDataObjectAsyncCapability

Poznámka

Rozhraní bylo původně pojmenováno IAsyncOperation, ale to bylo později změněno na IDataObjectAsyncCapability. V opačném případě jsou obě rozhraní identická.

 

Účelem IAsyncOperation/IDataObjectAsyncCapability je umožnit, aby zdroj a cíl přesunu vzájemně vyjednaly, zda lze data extrahovat asynchronně. Následující postup popisuje, jak zdroj drop používá rozhraní:

  1. Vytvořte datový objekt, který zpřístupňuje IAsyncOperation/IDataObjectAsyncCapability.
  2. Volání SetAsyncMode s fDoOpAsync nastaveno na VARIANT_TRUE, což naznačuje, že je podporována asynchronní operace.
  3. Po návratu DoDragDrop volejte InOperation:
    • Pokud InOperation selže nebo vrátí VARIANT_FALSE, proběhl normální synchronní přenos dat a proces extrakce dat je dokončen. Zdroj by měl provést veškeré potřebné vyčištění a pokračovat.
    • Pokud InOperation vrátí VARIANT_TRUE, data se extrahují asynchronně. Operace čištění by měly být zpracovány EndOperation.
  4. Uvolněte datový objekt.
  5. Po dokončení asynchronního přenosu dat datový objekt obvykle upozorní zdroj prostřednictvím privátního rozhraní.

Následující postup popisuje, jak cíl přetažení používá rozhraní IAsyncOperation/IDataObjectAsyncCapability pro asynchronní extrakci dat:

  1. Když systém volá IDropTarget::Drop, zavolejte IDataObject::QueryInterface a požádejte o rozhraní IAsyncOperation/IDataObjectAsyncCapability (IID_IAsyncOperation/IID_IDataObjectAsyncCapability) z datového objektu.
  2. Volání GetAsyncMode. Pokud metoda vrátí VARIANT_TRUE, datový objekt podporuje asynchronní extrakci dat.
  3. Vytvořte samostatné vlákno pro zpracování extrakce dat a volání StartOperation.
  4. Vraťte IDropTarget::Drop výzvu, stejně jako při normální operaci přenosu dat. DoDragDrop se vrátí a odblokuje zdroj přetažení. Nevolejte IDataObject::SetData k indikaci výsledku optimalizované operace přesunutí nebo odstranění při vkládání. Počkejte, až se operace dokončí.
  5. Extrahujte data ve vlákně na pozadí. Primární vlákno cíle je odblokované a může pokračovat.
  6. Pokud byl přenos dat optimalizovaný přesun nebo operace odstranění při vložení, zavolejte IDataObject::SetData k označení výsledku.
  7. Upozorněte objekt dat, že extrakce je dokončena voláním EndOperation.