Shell-scenario's voor gegevensoverdracht verwerken

Het Shell Data Object document besprak de algemene benadering die wordt gebruikt voor het overdragen van Shell-gegevens met slepen en neerzetten of het Klembord. Als u echter Shell-gegevensoverdracht in uw toepassing wilt implementeren, moet u ook begrijpen hoe u deze algemene principes en technieken toepast op de verschillende manieren waarop Shell-gegevens kunnen worden overgedragen. In dit document worden veelvoorkomende scenario's voor gegevensoverdracht van Shell beschreven en wordt beschreven hoe u deze in uw toepassing implementeert.

Opmerking

Hoewel elk van deze scenario's een specifieke bewerking voor gegevensoverdracht beschrijft, zijn veel van deze scenario's van toepassing op verschillende gerelateerde scenario's. Het belangrijkste verschil tussen de meeste Klembord- en slepen-en-neerzetten-overdrachten is bijvoorbeeld de wijze waarop het gegevensobject bij het doel aankomt. Zodra het doel een verwijzing heeft naar de IDataObject-interface van het gegevensobject, zijn de procedures voor het extraheren van informatie grotendeels hetzelfde voor beide typen gegevensoverdracht. Sommige scenario's zijn echter beperkt tot een specifiek type bewerking. Raadpleeg het afzonderlijke scenario voor meer informatie.

 

Algemene richtlijnen

In elk van de volgende secties wordt een enkel, redelijk specifiek scenario voor gegevensoverdracht besproken. Gegevensoverdrachten zijn echter vaak complexer en kunnen aspecten van verschillende scenario's omvatten. Meestal weet u niet van tevoren welk scenario u daadwerkelijk moet afhandelen. Hier volgen enkele algemene richtlijnen om rekening mee te houden.

Voor gegevensbronnen:

  • De Shell Klembord-indelingen, met uitzondering van CF_HDROP, zijn niet vooraf gedefinieerd. Elke indeling die u wilt gebruiken, moet worden geregistreerd door RegisterClipboardFormat aan te roepen.
  • De indelingen in de gegevensobjecten worden opgegeven in de volgorde van voorkeur van de bron. Inventariseer het gegevensobject en kies het eerste object dat u kunt gebruiken.
  • Neem zoveel indelingen op als u kunt ondersteunen. Over het algemeen weet u niet waar het gegevensobject wordt neergezet. Deze procedure verhoogt de kans dat het gegevensobject een indeling bevat die de doellocatie kan accepteren.
  • Bestaande bestanden moeten worden aangeboden met het CF_HDROP-formaat.
  • Bied bestandachtige gegevens aan met CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR formaten. Met deze methode kan het doel een bestand maken op basis van een gegevensobject zonder dat u iets hoeft te weten over de onderliggende gegevensopslag. Normaal gesproken moet u de gegevens presenteren als een IStream-interface . Dit mechanisme voor gegevensoverdracht is flexibeler dan een globaal geheugenobject en gebruikt veel minder geheugen.
  • Bronbestanden voor slepen moeten het CFSTR_SHELLIDLIST-formaat aanbieden wanneer Shell-items worden gesleept. Data-objecten voor items zijn te verkrijgen via de methoden IShellFolder::GetUIObjectOf of IShellItem::BindToHandler. Gegevensbronnen kunnen een standaardgegevensobject implementeren die ondersteuning biedt voor de CFSTR_SHELLIDLIST-indeling met behulp van SHCreateDataObject.
  • Met behulp van het shell-itemprogrammeringsmodel kunt u doelen verwijderen die reden willen hebben voor het slepen van items, een IDataObject converteren naar een IShellItemArray met shCreateShellItemArrayFromDataObject.
  • Gebruik standaard feedbackcursors.
  • Ondersteuning voor slepen naar links en rechts.
  • Gebruik het gegevensobject zelf van een ingesloten object. Met deze aanpak kan uw toepassing eventuele extra indelingen ophalen die het gegevensobject te bieden heeft en voorkomt u dat er een extra laag insluiting ontstaat. Een ingesloten object van server A wordt bijvoorbeeld vanuit server/container B gesleept en afgezet op container C. C moet een ingesloten object van server A maken, niet een ingesloten object van server B dat een ingesloten object van server A bevat.
  • Houd er rekening mee dat de Shell geoptimaliseerde verplaatsingen of verwijderingsbewerkingen kan gebruiken bij het verplaatsen van bestanden. Uw toepassing moet deze bewerkingen kunnen herkennen en op de juiste manier kunnen reageren.

Voor gegevensdoelen:

  • De Shell Klembord-indelingen, met uitzondering van CF_HDROP, zijn niet vooraf gedefinieerd. Elke indeling die u wilt gebruiken, moet worden geregistreerd door RegisterClipboardFormat aan te roepen.
  • Implementeer en registreer een OLE-neervaldoel. Vermijd het gebruik van Windows 3.1-doelen of het bericht WM_DROPFILES.
  • De indelingen in een gegevensobject variëren, afhankelijk van waar het object vandaan komt. Aangezien u over het algemeen niet van tevoren weet waar een gegevensobject vandaan komt, gaat u er niet van uit dat een bepaalde indeling aanwezig is. Het gegevensobject moet de indelingen opsommen in volgorde van kwaliteit, te beginnen met het beste. Om zo de beste beschikbare indeling te krijgen, inventariseren toepassingen normaal gesproken de beschikbare indelingen en gebruiken ze de eerste indeling in de opsomming die ze kunnen ondersteunen.
  • Ondersteuning voor slepen met de rechtermuisknop. U kunt het snelmenu voor slepen aanpassen door een handler voor slepen en neerzetten te maken.
  • Als uw toepassing bestaande bestanden accepteert, moet deze de CF_HDROP-indeling kunnen verwerken.
  • Over het algemeen moeten toepassingen die bestanden accepteren, ook de CFSTR_FILECONTENTS CFSTR_FILEDESCRIPTOR/ indelingen verwerken. Bestanden uit het bestandssysteem hebben de CF_HDROP-indeling , maar bestanden van providers zoals naamruimteextensies gebruiken doorgaans CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR. Voorbeelden hiervan zijn Windows CE-mappen, FTP-mappen (File Transfer Protocol), webmappen en CAB-mappen. De bron implementeert normaal gesproken een IStream-interface om gegevens uit de opslag als een bestand weer te geven.
  • Houd er rekening mee dat de Shell geoptimaliseerde verplaatsingen kan gebruiken of verwijderen bij plakken bij het verplaatsen van bestanden. Uw toepassing moet deze bewerkingen kunnen herkennen en op de juiste manier kunnen reageren.

Bestandsnamen van het Klembord naar een toepassing kopiëren

Scenario: Een gebruiker selecteert een of meer bestanden in Windows Explorer en kopieert deze naar het Klembord. Uw toepassing extraheert de bestandsnamen en plakt deze in het document.

Dit scenario kan bijvoorbeeld worden gebruikt om een gebruiker toe te staan een HTML-koppeling te maken door het bestand in uw toepassing te knippen en te plakken. Uw toepassing kan vervolgens de bestandsnaam uit het gegevensobject extraheren en verwerken om een ankertag te maken.

Wanneer een gebruiker een bestand in Windows Explorer selecteert en naar het Klembord kopieert, maakt de Shell een gegevensobject. Vervolgens wordt OleSetClipboard aangeroepen om een aanwijzer te plaatsen naar de IDataObject-interface van het gegevensobject op het Klembord.

Wanneer de gebruiker de opdracht Plakken selecteert in het menu of de werkbalk van uw toepassing:

  1. Roep OleGetClipboard aan om de IDataObject-interface van het gegevensobject op te halen.
  2. Roep IDataObject::EnumFormatEtc aan om een enumerator-object aan te vragen.
  3. Gebruik de IEnumFORMATETC-interface van het enumerator-object om de indelingen in het gegevensobject op te sommen.

Opmerking

De laatste twee stappen in deze procedure zijn opgenomen voor volledigheid. Ze zijn doorgaans niet nodig voor eenvoudige bestandsoverdrachten. Alle gegevensobjecten die voor dit type gegevensoverdracht worden gebruikt, moeten de CF_HDROP-indeling bevatten, die kan worden gebruikt om de namen van de bestanden in het object te bepalen. Voor meer algemene gegevensoverdrachten moet u echter de indelingen inventariseren en het beste selecteren dat uw toepassing kan verwerken.

 

Bestandsnamen extraheren uit het gegevensobject

De volgende stap is het extraheren van een of meer bestandsnamen uit het gegevensobject en deze in uw toepassing plakken. Houd er rekening mee dat de in deze sectie besproken procedure voor het extraheren van een bestandsnaam uit een gegevensobject evenzeer van toepassing is op slepen en neerzetten.

De eenvoudigste manier om bestandsnamen op te halen uit een gegevensobject is de CF_HDROP indeling:

  1. Roep IDataObject::GetData aan. Stel het cfFormat-lid van de structuur FORMATETC in op CF_HDROP en het gekoppelde lid op TYMED_HGLOBAL. Het dwAspect-lid is normaal gesproken ingesteld op DVASPECT_CONTENT. Als u echter het pad van het bestand in korte indeling (8.3) moet hebben, stelt u dwAspect in op DVASPECT_SHORT.

    Wanneer IDataObject::GetData retourneert, verwijst het hGlobal-lid van de STGMEDIUM-structuur naar een globaal geheugenobject dat de gegevens bevat.

  2. Maak een HDROP-variabele en stel deze in op het hGlobal-lid van de STGMEDIUM-structuur . De HDROP-variabele is nu een ingang naar een DROPFILES-structuur , gevolgd door een dubbel null-beëindigde tekenreeks die de volledig gekwalificeerde bestandspaden van de gekopieerde bestanden bevat.

  3. Bepaal hoeveel bestandspaden in de lijst staan door DragQueryFile aan te roepen met de parameter iFile ingesteld op 0xFFFFFFFF. De functie retourneert het aantal bestandspaden in de lijst. De op nul gebaseerde index van het bestandspad in deze lijst wordt in de volgende stap gebruikt om een bepaald pad te identificeren.

  4. Pak de bestandspaden uit het globale geheugenobject uit door DragQueryFile eenmaal voor elk bestand aan te roepen, waarbij iFile is ingesteld op de index van het bestand.

  5. Verwerk de bestandspaden indien nodig en plak deze in uw toepassing.

  6. Roep ReleaseStgMedium aan en geef de aanwijzer door naar de STGMEDIUM-structuur die u hebt doorgegeven aan IDataObject::GetData in stap 1. Zodra u de structuur hebt vrijgegeven, is de HDROP-waarde die u in stap 2 hebt gemaakt, niet meer geldig en mag deze niet worden gebruikt.

De inhoud van een verwijderd bestand naar een toepassing kopiëren

Scenario: Een gebruiker sleept een of meer bestanden uit Windows Explorer en zet deze neer in het venster van uw toepassing. De toepassing extraheert de inhoud van het bestand (s) en plakt deze in de toepassing.

In dit scenario wordt gebruikgemaakt van slepen en neerzetten om de bestanden van Windows Explorer over te dragen naar de toepassing. Voordat de bewerking wordt uitgevoerd, moet uw toepassing het volgende doen:

  1. Roep RegisterClipboardFormat aan om de benodigde Shell Klembord-indelingen te registreren.
  2. Roep RegisterDragDrop aan om een doelvenster en de IDropTarget-interface van uw toepassing te registreren.

Nadat de gebruiker de bewerking heeft gestart door een of meer bestanden te selecteren en ze te slepen:

  1. Windows Explorer maakt een gegevensobject en laadt de ondersteunde indelingen erin.
  2. Windows Explorer roept DoDragDrop aan om de sleeplus te starten.
  3. Wanneer de sleepafbeelding het doelvenster bereikt, meldt het systeem u door IDropTarget::D ragEnter aan te roepen.
  4. Als u wilt bepalen wat het gegevensobject bevat, roept u de methode IDataObject::EnumFormatEtc van het gegevensobject aan. Gebruik het enumerator-object dat door de methode wordt geretourneerd om de indelingen op te sommen die zijn opgenomen in het gegevensobject. Als uw toepassing geen van deze indelingen wil accepteren, retourneert u DROPEFFECT_NONE. Voor dit scenario moet uw toepassing alle gegevensobjecten negeren die geen indelingen bevatten die worden gebruikt om bestanden over te dragen, zoals CF_HDROP.
  5. Wanneer de gebruiker de gegevens verwijdert, roept het systeem IDropTarget::D rop aan.
  6. Gebruik de interface IDataObject om de inhoud van de bestanden te extraheren.

Er zijn verschillende manieren om de inhoud van een Shell-object uit een gegevensobject te extraheren. Gebruik in het algemeen de volgende volgorde:

Als het proces voor gegevensextractie lang duurt, kunt u de bewerking asynchroon uitvoeren op een achtergrondthread. Uw primaire thread kan vervolgens zonder onnodige vertragingen doorgaan. Zie Shell-objecten asynchroon slepen en neerzetten voor een discussie over het afhandelen van asynchrone gegevensextractie.

De CFSTR_FILECONTENTS-indeling gebruiken om gegevens uit een bestand te extraheren

De CFSTR_FILECONTENTS-indeling biedt een zeer flexibele en krachtige manier om de inhoud van een bestand over te dragen. Het is zelfs niet nodig dat de gegevens als één bestand worden opgeslagen. Het enige dat is vereist voor deze indeling, is dat het gegevensobject de gegevens aan het doel presenteert alsof het een bestand is. De werkelijke gegevens kunnen bijvoorbeeld een sectie van een tekstdocument zijn of een blok gegevens dat uit een database is geëxtraheerd. Het doel kan de gegevens behandelen als een bestand en hoeft niets te weten over het onderliggende opslagmechanisme.

Naamruimteextensies gebruiken normaal gesproken CFSTR_FILECONTENTS om gegevens over te dragen, omdat in deze indeling geen bepaald opslagmechanisme wordt aangenomen. Een naamruimteextensie kan elk opslagmechanisme gebruiken en deze indeling gebruiken om de objecten aan toepassingen te presenteren alsof het bestanden zijn.

Het mechanisme voor gegevensoverdracht voor CFSTR_FILECONTENTS is normaal TYMED_ISTREAM. Het overdragen van een IStream-interfaceaanwijzer vereist veel minder geheugen dan het laden van de gegevens in een globaal geheugenobject en IStream is een eenvoudigere manier om gegevens weer te geven dan IStorage.

Een CFSTR_FILECONTENTS-indeling wordt altijd vergezeld van een CFSTR_FILEDESCRIPTOR-indeling . U moet eerst de inhoud van deze indeling bekijken. Als er meer dan één bestand wordt overgedragen, bevat het gegevensobject daadwerkelijk meerdere CFSTR_FILECONTENTS indelingen, één voor elk bestand. De CFSTR_FILEDESCRIPTOR-indeling bevat de naam en kenmerken van elk bestand en biedt een indexwaarde voor elk bestand dat nodig is om de CFSTR_FILECONTENTS-indeling van een bepaald bestand te extraheren.

Een CFSTR_FILECONTENTS-indeling extraheren:

  1. Pak het CFSTR_FILEDESCRIPTOR-formaat uit als een TYMED_HGLOBAL-waarde.
  2. Het hGlobal-lid van de geretourneerde STGMEDIUM-structuur verwijst naar een globaal geheugenobject. Vergrendel dat object door de hGlobal-waarde door te geven aan GlobalLock.
  3. Cast de aanwijzer die door GlobalLock wordt geretourneerd naar een FILEGROUPDESCRIPTOR-aanwijzer . Deze verwijst naar een FILEGROUPDESCRIPTOR-structuur , gevolgd door een of meer FILEDESCRIPTOR-structuren . Elke FILEDESCRIPTOR-structuur bevat een beschrijving van een bestand dat is opgenomen in een van de bijbehorende CFSTR_FILECONTENTS indelingen.
  4. Bekijk de FILEDESCRIPTOR-structuren om te bepalen welke overeenkomt met het bestand dat u wilt extraheren. De op nul gebaseerde index van die FILEDESCRIPTOR-structuur wordt gebruikt om de CFSTR_FILECONTENTS-indeling van het bestand te identificeren. Omdat de grootte van een globaal geheugenblok niet byte-nauwkeurig is, gebruikt u de nFileSizeLow en nFileSizeHigh-leden van de structuur om te bepalen hoeveel bytes het bestand in het globale geheugenobject vertegenwoordigen.
  5. Roep IDataObject::GetData aan met het cfFormat-lid van de structuur FORMATETC ingesteld op de CFSTR_FILECONTENTS-waarde en het lIndex-lid ingesteld op de index die u in de vorige stap hebt bepaald. Het tymed-lid is doorgaans ingesteld op TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ISTORAGE. Het gegevensobject kan vervolgens het voorkeursmechanisme voor gegevensoverdracht kiezen.
  6. De STGMEDIUM-structuur die IDataObject::GetData retourneert, bevat een aanwijzer naar de gegevens van het bestand. Bekijk het tymed element van de structuur om het mechanisme voor gegevensoverdracht te bepalen.
  7. Als tymed is ingesteld op TYMED_ISTREAM of TYMED_ISTORAGE, gebruikt u de interface om de gegevens te extraheren. Als tymed is ingesteld op TYMED_HGLOBAL, bevinden de gegevens zich in een globaal geheugenobject. Voor een bespreking over het extraheren van gegevens uit een globaal geheugenobject, zie de sectie Globaal geheugenobject uit een gegevensobject extraheren in Shell Data Object.
  8. Roep GlobalLock aan om het globale geheugenobject te ontgrendelen dat u in stap 2 hebt vergrendeld.

Geoptimaliseerde verplaatsingsbewerkingen verwerken

Scenario: Een bestand wordt verplaatst van het bestandssysteem naar een naamruimte-extensie met behulp van een geoptimaliseerde verplaatsing.

In een conventionele verplaatsingsbewerking maakt de doellocatie een kopie van de gegevens en verwijdert de bron het origineel. Deze procedure kan inefficiënt zijn omdat er twee kopieën van de gegevens nodig zijn. Bij grote objecten zoals databases is een conventionele verplaatsingsbewerking mogelijk niet eens praktisch.

Door een geoptimaliseerde verhuizing gebruikt het doelwit zijn inzicht in hoe de gegevens worden opgeslagen voor de gehele verplaatsingsoperatie. Er is nooit een tweede kopie van de gegevens en de bron hoeft de oorspronkelijke gegevens niet te verwijderen. Shell-gegevens zijn geschikt voor geoptimaliseerde verplaatsingen, omdat het doel de hele bewerking kan verwerken met behulp van de Shell-API. Een typisch voorbeeld is het verplaatsen van bestanden. Zodra het doel het pad van een bestand heeft dat moet worden verplaatst, kan het SHFileOperation gebruiken om het te verplaatsen. De bron hoeft het oorspronkelijke bestand niet te verwijderen.

Opmerking

De Shell gebruikt normaal gesproken een geoptimaliseerde methode om bestanden te verplaatsen. Als u shell-gegevensoverdracht correct wilt verwerken, moet uw toepassing een geoptimaliseerde verplaatsing kunnen detecteren en verwerken.

 

Geoptimaliseerde verplaatsingen worden op de volgende manier verwerkt:

  1. De bron roept DoDragDrop aan met de dwEffect-parameter ingesteld op DROPEFFECT_MOVE om aan te geven dat de bronobjecten kunnen worden verplaatst.

  2. Het doel ontvangt de DROPEFFECT_MOVE waarde via een van de IDropTarget-methoden , waarmee wordt aangegeven dat een verplaatsing is toegestaan.

  3. Het doelobject kopieert het object (ongeoptimaliseerde verplaatsing) of verplaatst het object (geoptimaliseerde verplaatsing).

  4. Het doel vertelt vervolgens de bron of de oorspronkelijke gegevens moeten worden verwijderd.

    Een geoptimaliseerde verplaatsing is de standaardbewerking, waarbij de gegevens door het doel worden verwijderd. Om de bron te informeren dat er een geoptimaliseerde verplaatsing is uitgevoerd:

      • Het doel stelt de pdwEffect-waarde die het heeft ontvangen via de methode IDropTarget::Drop in op een andere waarde dan DROPEFFECT_MOVE. Deze is doorgaans ingesteld op DROPEFFECT_NONE of DROPEFFECT_COPY. De waarde wordt door DoDragDrop geretourneerd naar de bron.
      • Het doel roept ook de IDataObject::SetData-methode van het gegevensobject aan en geeft deze een CFSTR_PERFORMEDDROPEFFECT-indeling-ID die is ingesteld op DROPEFFECT_NONE. Deze methode-aanroep is nodig omdat sommige drop-doelen mogelijk niet de pdwEffect-parameter van DoDragDrop correct instellen. De CFSTR_PERFORMEDDROPEFFECT-indeling is de betrouwbare manier om aan te geven dat er een geoptimaliseerde verplaatsing heeft plaatsgevonden.

    Als het doel een niet-geoptimaliseerde verplaatsing heeft uitgevoerd, moeten de gegevens door de bron worden verwijderd. De bron informeren dat er een niet-geoptimaliseerde verplaatsing is uitgevoerd:

  5. De bron inspecteert de twee waarden die door het doel kunnen worden geretourneerd. Als beide zijn ingesteld op DROPEFFECT_MOVE, wordt de niet-geoptimaliseerde verplaatsing voltooid door de oorspronkelijke gegevens te verwijderen. Anders heeft het doel een geoptimaliseerde verplaatsing uitgevoerd en zijn de oorspronkelijke gegevens verwijderd.

Bewerkingen voor verwijderen bij plakken verwerken

Scenario: Een of meer bestanden worden uit een map in Windows Explorer geknipt en in een naamruimteextensie geplakt. Windows Explorer laat de bestanden gemarkeerd totdat deze feedback ontvangt over het resultaat van de plakbewerking.

Normaal gesproken verdwijnt het, wanneer een gebruiker gegevens verwijdert, onmiddellijk uit de weergave. Dit is mogelijk niet efficiënt en kan leiden tot bruikbaarheidsproblemen als de gebruiker zich zorgen maakt over wat er met de gegevens is gebeurd. Een alternatieve methode is het gebruik van een delete-on-paste-bewerking.

Met een verwijderen-bij-plakken bewerking worden de geselecteerde gegevens niet direct uit de weergave verwijderd. In plaats daarvan markeert de brontoepassing deze als geselecteerd, mogelijk door het lettertype of de achtergrondkleur te wijzigen. Nadat de doeltoepassing de gegevens heeft geplakt, wordt de bron op de hoogte gebracht van het resultaat van de bewerking. Als het doel een geoptimaliseerde verplaatsing heeft uitgevoerd, kan de bron de weergave ervan gewoon bijwerken. Als het doel een normale verplaatsing heeft uitgevoerd, moet de bron ook de kopie van de gegevens verwijderen. Als het plakken mislukt, worden de geselecteerde gegevens door de brontoepassing hersteld naar het oorspronkelijke uiterlijk.

Opmerking

De Shell maakt normaal gesproken gebruik van delete-on-paste wanneer een knip-/plakbewerking wordt gebruikt om bestanden te verplaatsen. Bewerkingen voor verwijderen bij plakken met Shell-objecten gebruiken normaal gesproken een geoptimaliseerde verplaatsing om de bestanden te verplaatsen. Als u Shell-gegevensoverdracht correct wilt verwerken, moet uw toepassing in staat zijn om verwijderingsbewerkingen bij plakken te detecteren en te verwerken.

 

De essentiële vereiste voor verwijderen bij plakken is dat het doel het resultaat van de bewerking moet rapporteren aan de bron. Standaard klembordtechnieken kunnen echter niet worden gebruikt om delete-on-paste te implementeren, omdat ze geen manier bieden om het doel te laten communiceren met de bron. In plaats daarvan gebruikt de doeltoepassing de IDataObject::SetData-methode van het gegevensobject om het resultaat aan het gegevensobject te rapporteren. Het gegevensobject kan vervolgens communiceren met de bron via een privéinterface.

De basisprocedure voor een delete-on-paste-bewerking is als volgt:

  1. De bron markeert de schermweergave van de geselecteerde gegevens.
  2. De bron maakt een gegevensobject. Het geeft een knipbewerking aan door de CFSTR_PREFERREDDROPEFFECT-indeling toe te voegen met een gegevenswaarde van DROPEFFECT_MOVE.
  3. De bron plaatst het gegevensobject op het Klembord met behulp van OleSetClipboard.
  4. Het doel haalt het gegevensobject op van het Klembord met behulp van OleGetClipboard.
  5. Het doel extraheert de CFSTR_PREFERREDDROPEFFECT gegevens. Als deze is ingesteld op alleen DROPEFFECT_MOVE, kan het doel een geoptimaliseerde verplaatsing uitvoeren of gewoon de gegevens kopiëren.
  6. Als het doel geen geoptimaliseerde verplaatsing uitvoert, wordt de methode IDataObject::SetData aangeroepen met de CFSTR_PERFORMEDDROPEFFECT-indeling ingesteld op DROPEFFECT_MOVE.
  7. Wanneer het plakken is voltooid, roept het doel de methode IDataObject::SetData aan met de CFSTR_PASTESUCCEEDED-indeling ingesteld op DROPEFFECT_MOVE.
  8. Wanneer de methode IDataObject::SetData van de bron wordt aangeroepen met de CFSTR_PASTESUCCEEDED-indeling die is ingesteld op DROPEFFECT_MOVE, moet deze controleren of deze ook de CFSTR_PERFORMEDDROPEFFECT-indeling heeft ontvangen die is ingesteld op DROPEFFECT_MOVE. Als beide indelingen door het doel worden verzonden, moet de bron de gegevens verwijderen. Als alleen de CFSTR_PASTESUCCEEDED-indeling is ontvangen, kan de bron de gegevens gewoon uit de weergave verwijderen. Als de overdracht mislukt, wordt de weergave bijgewerkt naar het oorspronkelijke uiterlijk.

Gegevens overdragen naar en van virtuele mappen

Scenario: Een gebruiker sleept een object van of zet het neer in een virtuele map.

Virtuele mappen bevatten objecten die over het algemeen geen deel uitmaken van het bestandssysteem. Sommige virtuele mappen, zoals de Prullenbak, kunnen gegevens vertegenwoordigen die zijn opgeslagen op de harde schijf, maar niet als gewone bestandssysteemobjecten. Sommige kunnen opgeslagen gegevens vertegenwoordigen die zich op een extern systeem bevinden, zoals een handheld-pc of een FTP-site. Andere, zoals de map Printers, bevatten objecten die helemaal geen opgeslagen gegevens vertegenwoordigen. Hoewel sommige virtuele mappen deel uitmaken van het systeem, kunnen ontwikkelaars ook aangepaste virtuele mappen maken en installeren door een naamruimte-extensie te implementeren.

Ongeacht het type gegevens of hoe deze worden opgeslagen, worden de map- en bestandsobjecten die zijn opgenomen in een virtuele map weergegeven door de Shell alsof ze normale bestanden en mappen zijn. Het is de verantwoordelijkheid van de virtuele map om alle gegevens te nemen die deze bevat en deze op de juiste wijze aan de Shell te presenteren. Deze vereiste betekent dat virtuele mappen normaal gesproken ondersteuning bieden voor gegevensoverdracht via slepen en neerzetten en het Klembord.

Er zijn dus twee groepen ontwikkelaars die zich bezig moeten houden met gegevensoverdracht naar en van virtuele mappen:

  • Ontwikkelaars van wie toepassingen gegevens moeten accepteren die worden overgedragen vanuit een virtuele map.
  • Ontwikkelaars van wie de naamruimteextensies gegevensoverdracht correct moeten ondersteunen.

Gegevens uit een virtuele map accepteren

Virtuele mappen kunnen vrijwel elk type gegevens vertegenwoordigen en die gegevens op elke gewenste manier opslaan. Sommige virtuele mappen bevatten mogelijk normale bestandssysteembestanden en -mappen. Anderen kunnen bijvoorbeeld al hun objecten in één document of database inpakken.

Wanneer een bestandssysteemobject wordt overgebracht naar een toepassing, bevat het gegevensobject normaal gesproken een CF_HDROP-indeling met het volledig gekwalificeerde pad van het object. Uw toepassing kan deze tekenreeks extraheren en de normale bestandssysteemfuncties gebruiken om het bestand te openen en de bijbehorende gegevens te extraheren. Omdat virtuele mappen doorgaans geen normale bestandssysteemobjecten bevatten, gebruiken ze doorgaans geen CF_HDROP.

In plaats van CF_HDROP worden gegevens normaal gesproken overgebracht uit virtuele mappen met de CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS indelingen. De CFSTR_FILECONTENTS-indeling heeft twee voordelen ten opzichte van CF_HDROP:

  • Er wordt geen specifieke methode voor gegevensopslag aangenomen.
  • De indeling is flexibeler. Het ondersteunt drie mechanismen voor gegevensoverdracht: een globaal geheugenobject, een IStream-interface of een IStorage-interface .

Globale geheugenobjecten worden zelden gebruikt om gegevens over te dragen naar of van virtuele objecten, omdat de gegevens in zijn geheel in het geheugen moeten worden gekopieerd. Het overbrengen van een interfaceaanwijzer vereist bijna geen geheugen en is veel efficiënter. Met zeer grote bestanden kan een interfaceaanwijzer het enige praktische mechanisme voor gegevensoverdracht zijn. Gegevens worden doorgaans vertegenwoordigd door een IStream-aanwijzer , omdat die interface iets flexibeler is dan IStorage. Het doel extraheert de aanwijzer uit het gegevensobject en gebruikt de interfacemethoden om de gegevens te extraheren.

Zie De CFSTR_FILECONTENTS-indeling gebruiken om gegevens uit een bestand te extraheren voor meer informatie over het afhandelen van de /CFSTR_FILECONTENTS-indelingen.

Gegevens overdragen van en naar een Naamruimte-extensie

Wanneer u een naamruimte-extensie implementeert, wilt u normaal gesproken slepen en neerzetten ondersteunen. Volg de aanbevelingen voor het verwijderen van bronnen en doelen die worden besproken in algemene richtlijnen. Met name een naamruimte-extensie moet:

  • De CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS indelingen kunnen verwerken. Deze twee indelingen worden normaal gesproken gebruikt voor het overdragen van objecten naar en van naamruimte-extensies.
  • Kan geoptimaliseerde verplaatsingen afhandelen. De Shell verwacht dat Shell-objecten op een geoptimaliseerde manier worden verplaatst.
  • Een delete-on-paste-bewerking kunnen verwerken. De Shell maakt gebruik van delete-on-paste wanneer objecten vanuit de Shell worden verplaatst met een knip-/plakbewerking.
  • Kan gegevensoverdracht verwerken via een IStream - of IStorage-interface . Gegevensoverdracht naar of van een virtuele map wordt normaal gesproken verwerkt door een van deze twee interfaceaanwijzers over te brengen, meestal een IStream-aanwijzer . Het doel roept vervolgens de interfacemethoden aan om de gegevens te extraheren:
      • Als drop-bron moet de naamruimte-extensie de gegevens uit de opslag extraheren en deze via deze interface aan het doel overdragen.
      • Als doellocatie voor neerzetten moet een naamruimte-extensie gegevens van een bron accepteren via deze interface en deze correct opslaan.

Bestanden in de Prullenbak neerzetten

Scenario: De gebruiker verwijdert een bestand in de Prullenbak. De extensie voor uw toepassing of naamruimte verwijdert het oorspronkelijke bestand.

De Prullenbak is een virtuele map die wordt gebruikt als opslagplaats voor bestanden die niet meer nodig zijn. Zolang de Prullenbak niet is geleegd, kan de gebruiker het bestand later herstellen en terugzetten naar het bestandssysteem.

Voor het grootste deel werkt het overbrengen van Shell-objecten naar de Prullenbak, net als elke andere map. Wanneer een gebruiker echter een bestand in de Prullenbak verwijdert, moet de bron het origineel verwijderen, zelfs als de feedback uit de map een kopieerbewerking aangeeft. Normaal gesproken heeft een drop-bron geen manier om te achterhalen op welke map zijn gegevensobject is neergezet. Voor systemen van Windows 2000 en hoger geldt echter dat wanneer een gegevensobject wordt neergezet op de Recycle Bin, roept de Shell de methode IDataObject::SetData aan met het formaat CFSTR_TARGETCLSID ingesteld op de klasse-id van de Prullenbak (CLSID) (CLSID_RecycleBin). Om de Prullenbak correct te verwerken, moet uw gegevensobject deze indeling kunnen herkennen en de informatie via een private interface aan de bron kunnen doorgeven.

Opmerking

Wanneer IDataObject::SetData wordt aangeroepen met een CFSTR_TARGETCLSID-indeling die is ingesteld op CLSID_RecycleBin, moet de gegevensbron geopende ingangen sluiten voor de objecten die worden overgedragen voordat ze worden geretourneerd vanuit de methode. Anders kunt u delen schenden veroorzaken.

 

Scrap Files maken en importeren

Scenario: Een gebruiker sleept bepaalde gegevens uit het gegevensbestand van een OLE-toepassing en zet deze neer op het bureaublad of Windows Explorer.

Windows kunnen gebruikers een object uit het gegevensbestand van een OLE-toepassing slepen en neerzetten op het bureaublad of een bestandssysteemmap. Met deze bewerking maakt u een scrap-bestand dat de gegevens of een koppeling naar de gegevens bevat. De bestandsnaam wordt opgehaald uit de korte naam die is geregistreerd voor de CLSID van het object en de CF_TEXT gegevens. Om te zorgen dat de Shell een knipselbestand met gegevens kan maken, moet de IDataObject-interface van de toepassing het CF_EMBEDSOURCE Klembordformaat ondersteunen. Als u een bestand met een koppeling wilt maken, moet IDataObject de CF_LINKSOURCE-indeling ondersteunen.

Er zijn ook drie optionele functies die een toepassing kan implementeren ter ondersteuning van scrap-bestanden:

  • Ondersteuning voor rondreis
  • Gegevensindelingen in cache
  • Vertraagde rendering

Ondersteuning voor een rondreis

Een retour omvat het overdragen van een gegevensobject naar een andere container en vervolgens terug naar het oorspronkelijke document. Een gebruiker kan bijvoorbeeld een groep cellen van een spreadsheet naar het bureaublad overbrengen, waardoor een knipselbestand met de gegevens wordt gemaakt. Als de gebruiker vervolgens het restmateriaal weer overdraagt naar het werkblad, moeten de gegevens in het document geïntegreerd worden zoals ze waren vóór de oorspronkelijke overdracht.

Wanneer de Shell het scrap-bestand maakt, vertegenwoordigt het de gegevens als een insluitobject. Wanneer het knipsel wordt overgedragen naar een andere container, wordt het overgedragen als een insluitobject, zelfs als het wordt geretourneerd naar het oorspronkelijke document. Uw toepassing is verantwoordelijk voor het bepalen van de gegevensindeling in het knipsel en het terugzetten van de gegevens in de oorspronkelijke indeling, indien nodig.

Als u de indeling van het ingesloten object wilt bepalen, bepaalt u de CLSID door de CF_OBJECTDESCRIPTOR-indeling van het object op te halen. Als de CLSID een gegevensindeling aangeeft die deel uitmaakt van de toepassing, moet deze de systeemeigen gegevens overdragen in plaats van OleCreateFromData aan te roepen.

Gegevensindelingen in cache

Wanneer de Windows Shell een scrap-bestand maakt, controleert het het Windows-register op de lijst met beschikbare indelingen. Er zijn standaard twee indelingen beschikbaar: CF_EMBEDSOURCE en CF_LINKSOURCE. Er zijn echter een aantal scenario's waarin toepassingen mogelijk scrap-bestanden in verschillende indelingen moeten hebben:

  • Om toe te staan dat scraps worden overgedragen naar containers die geen OLE ondersteunen, die geen ingesloten objectformaten kunnen accepteren.
  • Om toepassingspakketten te laten communiceren met een privaat formaat.
  • Om rondreizen makkelijker te maken.

Toepassingen kunnen opmaak toevoegen aan het klembord door ze in het register in de cache op te slaan. Er zijn twee typen indelingen in de cache:

  • Prioriteitscacheindelingen. Voor deze formaten worden de gegevens volledig gekopieerd naar het knipsel van het gegevensobject.
  • Indelingen met vertragingsweergave. Voor deze indelingen wordt het gegevensobject niet gekopieerd naar de knipsel. In plaats daarvan wordt rendering vertraagd totdat een doel de gegevens aanvraagt. Vertraging bij renderen wordt uitvoeriger besproken in de volgende sectie.

Als u een prioriteitscache of vertraagde indeling wilt toevoegen, maakt u een DataFormat-subsleutel onder de CLSID-sleutel van de toepassing die de bron van de gegevens is. Maak onder deze subsleutel een subsleutel PriorityCacheFormats of DelayRenderFormats. Maak voor elke prioriteitscache of vertragingsweergave een genummerde subsleutel die begint met nul. Stel de waarde van deze sleutel in op een tekenreeks met de geregistreerde naam van de notatie of een #X waarde, waarbij X het notatienummer van een standaard Klembord-indeling vertegenwoordigt.

In het volgende voorbeeld ziet u indelingen in de cache voor twee toepassingen. De MyProg1-toepassing heeft de rich-text-indeling als prioriteitscache-indeling en een eigen indeling "Mijn indeling" als een vertragingsweergave-indeling. De toepassing MyProg2 heeft de CF_BITMAP-indeling (#8) als een prioriteitscache-indeling.

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

Er kunnen extra indelingen worden toegevoegd door extra genummerde subsleutels te maken.

Vertraagde rendering

Met een vertraagde renderingindeling kan een toepassing een tijdelijk bestand maken, maar de kosten van gegevensweergave uitstellen totdat deze door een doel worden aangevraagd. De IDataObject-interface van een scrap biedt de vertraagde renderingindelingen aan het doel, samen met systeemeigen en in de cache opgeslagen gegevens. nl-NL: Als de doelcomputer een vertraagd renderingformaat aanvraagt, zal de Shell de toepassing uitvoeren en de gegevens vanuit het actieve object aan de doelcomputer verstrekken.

Opmerking

Omdat vertraagde rendering enigszins riskant is, moet het met voorzichtigheid worden gebruikt. Het werkt niet als de server niet beschikbaar is of voor toepassingen die niet zijn ingeschakeld voor OLE.

 

Shell-objecten asynchroon slepen en neerzetten

Scenario: Een gebruiker draagt een groot blok gegevens over van de bron naar het doel. Om te voorkomen dat beide toepassingen gedurende een aanzienlijke tijd worden geblokkeerd, haalt het doel de gegevens asynchroon op.

Normaal gesproken is slepen en neerzetten een synchrone bewerking. Kortom:

  1. De drop source roept DoDragDrop aan en blokkeert de primaire thread totdat de functie terugkeert. Het blokkeren van de primaire thread blokkeert normaal gesproken de verwerking van de gebruikersinterface.
  2. Nadat de methode IDropTarget::D rop van het doel is aangeroepen, haalt het doel de gegevens uit het gegevensobject op de primaire thread op. Deze procedure blokkeert normaal gesproken de gebruikersinterfaceverwerking van het doelwit gedurende het extractieproces.
  3. Zodra de gegevens zijn geëxtraheerd, retourneert het doel de IDropTarget::D rop-aanroep , retourneert het systeem DoDragDrop en kunnen beide threads doorgaan.

Kortom, synchrone gegevensoverdracht kan de primaire threads van beide toepassingen gedurende een aanzienlijke tijd blokkeren. Met name moeten beide threads wachten terwijl het doel de gegevens extraheert. Voor kleine hoeveelheden gegevens is de tijd die nodig is om gegevens te extraheren klein en werkt synchrone gegevensoverdracht behoorlijk goed. Het synchroon extraheren van grote hoeveelheden gegevens kan echter langdurige vertragingen veroorzaken en de gebruikersinterface van zowel het doel als de bron verstoren.

De interface IAsyncOperation/IDataObjectAsyncCapability is een optionele interface die kan worden geïmplementeerd door een gegevensobject. Het biedt het neerzetdoel de mogelijkheid om asynchroon op een achtergrondthread gegevens uit het gegevensobject te extraheren. Zodra gegevensextractie is overgedragen aan de achtergrondthread, zijn de primaire threads van beide toepassingen vrij om door te gaan.

IASyncOperation/IDataObjectAsyncCapability gebruiken

Opmerking

De interface heette oorspronkelijk IAsyncOperation, maar dit is later gewijzigd in IDataObjectAsyncCapability. Anders zijn de twee interfaces identiek.

 

Het doel van IAsyncOperation/IDataObjectAsyncCapability is om de bron en het doel in staat te stellen te onderhandelen over de vraag of gegevens asynchroon kunnen worden geëxtraheerd. In de volgende procedure wordt beschreven hoe de drag-and-drop-bron de interface gebruikt.

  1. Maak een gegevensobject dat IAsyncOperation/IDataObjectAsyncCapability beschikbaar maakt.
  2. Roep SetAsyncMode aan met fDoOpAsync ingesteld op VARIANT_TRUE om aan te geven dat een asynchrone bewerking wordt ondersteund.
  3. Nadat DoDragDrop is geretourneerd, roept u InOperation aan:
    • Als InOperation mislukt of VARIANT_FALSE retourneert, is er een normale synchrone gegevensoverdracht uitgevoerd en is het proces voor gegevensextractie voltooid. De bron moet alle vereiste opschoning uitvoeren en doorgaan.
    • Als InOperationVARIANT_TRUE retourneert, worden de gegevens asynchroon geëxtraheerd. Opschoningsbewerkingen moeten worden verwerkt door EndOperation.
  4. Laat het gegevensobject los.
  5. Wanneer de asynchrone gegevensoverdracht is voltooid, meldt het gegevensobject normaal gesproken de bron via een privéinterface.

In de volgende procedure wordt beschreven hoe het dropdoel gebruikmaakt van de interface IAsyncOperation/IDataObjectAsyncCapability om gegevens asynchroon te extraheren:

  1. Wanneer het systeem IDropTarget::D rop aanroept, roept u IDataObject::QueryInterface aan en vraagt u een IAsyncOperation/IDataObjectAsyncCapability-interface (IID_IAsyncOperation/IID_IDataObjectAsyncCapability) aan vanuit het gegevensobject.
  2. Roep GetAsyncMode aan. Als de methode VARIANT_TRUE retourneert, ondersteunt het gegevensobject asynchrone gegevensextractie.
  3. Maak een afzonderlijke thread om gegevensextractie af te handelen en StartOperation aan te roepen.
  4. Retourneer de IDropTarget::D rop-aanroep , zoals u zou doen voor een normale gegevensoverdracht. DoDragDrop retourneert en maakt de bron van de slepen-en-neerzetten-actie vrij. Roep IDataObject::SetData niet aan om het resultaat van een geoptimaliseerde verplaatsing of delete-on-paste-bewerking aan te geven. Wacht totdat de bewerking is voltooid.
  5. Haal de gegevens op de achtergrondthread uit. De primaire thread van het doel wordt gedeblokkeerd en is gratis om door te gaan.
  6. Als de gegevensoverdracht een geoptimaliseerde verplaatsing of verwijderen-bij-plakken operatie was, roep IDataObject::SetData aan om het resultaat aan te geven.
  7. Informeer het gegevensobject dat extractie is voltooid door EndOperation aan te roepen.