Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Dokumentet Shell Data Object beskrev den allmänna metod som används för att överföra Shell-data med dra och släpp eller Urklipp. Men för att implementera Shell-dataöverföring i ditt program måste du också förstå hur du tillämpar dessa allmänna principer och tekniker på de olika sätt som Shell-data kan överföras på. Det här dokumentet beskriver vanliga scenarier för Shell-dataöverföring och beskriver hur du implementerar var och en i ditt program.
- Allmänna riktlinjer
- Kopiera filnamn från Urklipp till ett program
- Kopiera innehållet i en borttagen fil till ett program
- Hantera optimerade flyttåtgärder
- Hantera åtgärder för att ta bort vid klistra in
- Överföra data till och från virtuella mappar
- Släppa filer på papperskorgen
- Skapa och importera skrotfiler
- Dra och släppa gränssnittsobjekt asynkront
Anmärkning
Även om var och en av dessa scenarier diskuterar en specifik dataöverföringsåtgärd gäller många av dem för en mängd olika relaterade scenarier. Till exempel är den primära skillnaden mellan de flesta Urklipp-överföringar och dra och släpp är hur dataobjektet når målet. När målet har en pekare till dataobjektets IDataObject-gränssnitt är procedurerna för att extrahera information i stort sett desamma för båda typerna av dataöverföring. Vissa scenarier är dock begränsade till en viss typ av åtgärd. Mer information finns i det enskilda scenariot.
Allmänna riktlinjer
Vart och ett av följande avsnitt beskriver ett enda, ganska specifikt dataöverföringsscenario. Dataöverföringar är dock ofta mer komplexa och kan omfatta aspekter av flera scenarier. Du vet vanligtvis inte i förväg vilket scenario du faktiskt behöver hantera. Här följer några allmänna riktlinjer att tänka på.
För datakällor:
- Shell Urklippsformat, med undantag för CF_HDROP, är inte fördefinierade. Varje format som du vill använda måste registreras genom att anropa RegisterClipboardFormat.
- Formaten i dataobjekten anges i prioritetsordning från källan. Räkna upp dataobjektet och välj det första som du kan använda.
- Inkludera så många format som du kan stödja. Du vet vanligtvis inte var dataobjektet kommer att släppas. Den här metoden förbättrar oddsen för att dataobjektet ska innehålla ett format som släppmålet kan acceptera.
- Befintliga filer bör erbjudas med CF_HDROP format.
- Erbjud filliknande data med CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR format. Med den här metoden kan målet skapa en fil från ett dataobjekt utan att behöva veta något om den underliggande datalagringen. Du bör normalt presentera data som ett IStream-gränssnitt . Den här dataöverföringsmekanismen är mer flexibel än ett globalt minnesobjekt och använder mycket mindre minne.
- Dragkällor bör erbjuda formatet CFSTR_SHELLIDLIST när Shell-objekt dras. Dataobjekt för objekt kan hämtas via metoderna IShellFolder::GetUIObjectOf eller IShellItem::BindToHandler . Datakällor kan skapa en standardimplementering av dataobjekt som stöder CFSTR_SHELLIDLIST format med hjälp av SHCreateDataObject.
- Släpp mål som vill resonera om de objekt som dras med hjälp av programmeringsmodellen för gränssnittsobjekt kan konvertera en IDataObject till en IShellItemArray med hjälp av SHCreateShellItemArrayFromDataObject.
- Använd vanliga feedbackmarkörer.
- Stöd vänster och höger dra.
- Använd själva dataobjektet från ett inbäddat objekt. Med den här metoden kan ditt program hämta eventuella extra format som dataobjektet har att erbjuda och undviker att skapa ett extra lager av inneslutning. Till exempel dras ett inbäddat objekt från server A från server/container B och släpps på container C. C bör skapa ett inbäddat objekt av server A, inte ett inbäddat objekt i server B som innehåller ett inbäddat objekt i server A.
- Kom ihåg att när du flyttar filer kan Shell använda optimerade flyttningar eller radera vid inklistring. Programmet bör kunna identifiera dessa åtgärder och svara på rätt sätt.
För datamålgrupper:
- Shell Urklippsformat, med undantag för CF_HDROP, är inte fördefinierade. Varje format som du vill använda måste registreras genom att anropa RegisterClipboardFormat.
- Implementera och registrera ett OLE-släppmål. Undvik att använda Windows 3.1-mål eller meddelandet WM_DROPFILES om möjligt.
- Formaten som ingår i ett dataobjekt varierar beroende på var objektet kommer ifrån. Eftersom du vanligtvis inte vet i förväg var ett dataobjekt kommer ifrån, förutsätter du inte att ett visst format kommer att finnas. Dataobjektet bör räkna upp formaten efter kvalitet, från och med det bästa. För att få bästa tillgängliga format räknar program normalt upp de tillgängliga formaten och använder det första formatet i den uppräkning som de kan stödja.
- Stöd för högerklicksdragning Du kan anpassa snabbmenyn för dra och släpp genom att skapa en dra-och-släpp-hanterare.
- Om ditt program accepterar befintliga filer måste det kunna hantera CF_HDROP format.
- I allmänhet bör program som accepterar filer också hantera CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR format. Filer från filsystemet har CF_HDROP format, men filer från leverantörer som namnområdestillägg använder vanligtvis CFSTR_FILECONTENTS/CFSTR_FILEDESCRIPTOR. Exempel är Windows CE-mappar, FTP-mappar (File Transfer Protocol), webbmappar och CAB-mappar. Källan implementerar normalt ett IStream-gränssnitt för att presentera data från lagringen som en fil.
- Kom ihåg att Shell kan använda sig av optimerade flyttningar eller borttagning vid inklistring när du flyttar filer. Programmet bör kunna identifiera dessa åtgärder och svara på rätt sätt.
Kopiera filnamn från Urklipp till ett program
Scenario: En användare väljer en eller flera filer i Windows Explorer och kopierar dem till Urklipp. Programmet extraherar filnamnen och klistrar in dem i dokumentet.
Det här scenariot kan till exempel användas för att tillåta en användare att skapa en HTML-länk genom att klippa ut och klistra in filen i ditt program. Programmet kan sedan extrahera filnamnet från dataobjektet och bearbeta det för att skapa en fästpunktstagg.
När en användare väljer en fil i Windows Explorer och kopierar den till Urklipp skapar Shell ett dataobjekt. Den anropar sedan OleSetClipboard för att placera en pekare till dataobjektets IDataObject-gränssnitt i Urklipp.
När användaren väljer kommandot Klistra in från programmets meny eller verktygsfält:
- Anropa OleGetClipboard för att hämta dataobjektets IDataObject-gränssnitt .
- Anropa IDataObject::EnumFormatEtc för att begära ett uppräkningsobjekt.
- Använd uppräkningsobjektets IEnumFORMATETC-gränssnitt för att räkna upp de format som ingår i dataobjektet.
Anmärkning
De sista två stegen i den här proceduren ingår för fullständighet. De är vanligtvis inte nödvändiga för enkla filöverföringar. Alla dataobjekt som används för den här typen av dataöverföring ska innehålla CF_HDROP format, som kan användas för att fastställa namnen på filerna som ingår i objektet. För mer allmänna dataöverföringar bör du dock räkna upp formaten och välja det bästa som programmet kan hantera.
Extrahera filnamnen från dataobjektet
Nästa steg är att extrahera ett eller flera filnamn från dataobjektet och klistra in dem i programmet. Observera att proceduren som beskrivs i det här avsnittet för att extrahera ett filnamn från ett dataobjekt gäller lika bra för dra och släpp-överföringar.
Det enklaste sättet att hämta filnamn från ett dataobjekt är det CF_HDROP formatet:
Anropa IDataObject::GetData. Ange cfFormat-medlemmen i FORMATETC-strukturen till CF_HDROP och tymed-medlemmen till TYMED_HGLOBAL. DwAspect-medlemmen är normalt inställd på DVASPECT_CONTENT. Men om du behöver ha filens sökväg i kort format (8.3) anger du dwAspect till DVASPECT_SHORT.
När IDataObject::GetData returnerar pekar hGlobal-medlemmen i STGMEDIUM-strukturen på ett globalt minnesobjekt som innehåller data.
Skapa en HDROP-variabel och ange den till hGlobal-medlemmen i STGMEDIUM-strukturen . HDROP-variabeln är nu ett handtag till en DROPFILES-struktur följt av en dubbel-nullterminerad sträng som innehåller de fullständigt kvalificerade filsökvägarna för de kopierade filerna.
Avgör hur många filsökvägar som finns i listan genom att anropa DragQueryFile med parametern iFile inställd på 0xFFFFFFFF. Funktionen returnerar antalet filsökvägar i listan. Filsökvägens nollbaserade index i den här listan används i nästa steg för att identifiera en viss sökväg.
Extrahera filsökvägarna från det globala minnesobjektet genom att anropa DragQueryFile en gång för varje fil, med iFile inställt på filens index.
Bearbeta filsökvägarna efter behov och klistra in dem i ditt program.
Anropa ReleaseStgMedium och skicka pekaren till STGMEDIUM-strukturen som du skickade till IDataObject::GetData i steg 1. När du har släppt strukturen är HDROP-värdet som du skapade i steg 2 inte längre giltigt och bör inte användas.
Kopiera innehållet i en borttagen fil till ett program
Scenario: En användare drar en eller flera filer från Windows Explorer och släpper dem i programmets fönster. Ditt program extraherar innehållet i filen (s) och klistrar in det i programmet.
I det här scenariot används dra och släpp för att överföra filerna från Windows Explorer till programmet. Innan åtgärden måste programmet:
- Anropa RegisterClipboardFormat för att registrera alla nödvändiga Shell Urklippsformat.
- Anropa RegisterDragDrop för att registrera ett målfönster och programmets IDropTarget-gränssnitt .
När användaren har initierat åtgärden genom att välja en eller flera filer och börja dra dem:
- Windows Explorer skapar ett dataobjekt och läser in de format som stöds i det.
- Windows Explorer anropar DoDragDrop för att initiera dra-loopen.
- När dra-avbildningen når målfönstret meddelar systemet dig genom att anropa IDropTarget::D ragEnter.
- Om du vill ta reda på vad dataobjektet innehåller anropar du dataobjektets IDataObject::EnumFormatEtc-metod . Använd uppräkningsobjektet som returneras av metoden för att räkna upp de format som ingår i dataobjektet. Om programmet inte vill acceptera något av dessa format returnerar du DROPEFFECT_NONE. I det här scenariot bör ditt program ignorera alla dataobjekt som inte innehåller format som används för att överföra filer, till exempel CF_HDROP.
- När användaren släpper data anropar systemet IDropTarget::Drop.
- Använd IDataObject-gränssnittet för att extrahera innehållet i filerna.
Det finns flera olika sätt att extrahera innehållet i ett Shell-objekt från ett dataobjekt. Använd i allmänhet följande ordning:
- Om filen innehåller ett CF_TEXT format är data ANSI-text. Du kan använda CF_TEXT format för att extrahera data i stället för att öppna själva filen.
- Om filen innehåller ett länkat eller inbäddat OLE-objekt innehåller dataobjektet ett CF_EMBEDDEDOBJECT format. Använd ole-standardtekniker för att extrahera data. Skrotfiler innehåller alltid ett CF_EMBEDDEDOBJECT format.
- Om Shell-objektet kommer från filsystemet innehåller dataobjektet ett CF_HDROP format med namnen på filerna. Extrahera filnamnet från CF_HDROP och anropa OleCreateFromFile för att skapa ett nytt länkat eller inbäddat objekt. En diskussion om hur du hämtar ett filnamn från ett CF_HDROP format finns i Kopiera filnamn från Urklipp till ett program.
- Om dataobjektet innehåller ett CFSTR_FILEDESCRIPTOR format kan du extrahera en fils innehåll från filens CFSTR_FILECONTENTS format. En diskussion om den här proceduren finns i Använda CFSTR_FILECONTENTS format för att extrahera data från en fil.
- Före Shell version 4.71 angav ett program att det överförde en genvägsfiltyp genom att ange FD_LINKUI i dwFlags-medlemmen i FILEDESCRIPTOR-strukturen . För senare versioner av Shell är det bästa sättet att ange att genvägar överförs att använda formatet CFSTR_PREFERREDDROPEFFECT inställt på DROPEFFECT_LINK. Den här metoden är mycket effektivare än att extrahera FILEDESCRIPTOR-strukturen bara för att kontrollera en flagga.
Om dataextraheringsprocessen blir lång kanske du vill utföra åtgärden asynkront på en bakgrundstråd. Din primära tråd kan sedan fortsätta utan onödiga fördröjningar. En diskussion om hur du hanterar asynkron dataextrahering finns i Dra och släppa gränssnittsobjekt asynkront.
Använda CFSTR_FILECONTENTS format för att extrahera data från en fil
Det CFSTR_FILECONTENTS formatet ger ett mycket flexibelt och kraftfullt sätt att överföra innehållet i en fil. Det är inte ens nödvändigt att data lagras som en enda fil. Allt som krävs för det här formatet är att dataobjektet presenterar data för målet som om det vore en fil. Faktiska data kan till exempel vara ett avsnitt i ett textdokument eller ett datablock som extraherats från en databas. Målet kan behandla data som en fil och behöver inte veta något om den underliggande lagringsmekanismen.
Namnområdestillägg använder normalt CFSTR_FILECONTENTS för att överföra data eftersom det här formatet inte förutsätter någon särskild lagringsmekanism. Ett namnområdestillägg kan använda vilken lagringsmekanism som helst och använda det här formatet för att presentera sina objekt för program som om de vore filer.
Dataöverföringsmekanismen för CFSTR_FILECONTENTS är normalt TYMED_ISTREAM. Överföring av en IStream-gränssnittspekare kräver mycket mindre minne än att läsa in data i ett globalt minnesobjekt, och IStream är ett enklare sätt att representera data än IStorage.
Ett CFSTR_FILECONTENTS format åtföljs alltid av ett CFSTR_FILEDESCRIPTOR format. Du måste först granska innehållet i det här formatet. Om mer än en fil överförs innehåller dataobjektet faktiskt flera CFSTR_FILECONTENTS format, ett för varje fil. Formatet CFSTR_FILEDESCRIPTOR innehåller namn och attribut för varje fil och ger ett indexvärde för varje fil som behövs för att extrahera en viss fils CFSTR_FILECONTENTS format.
Så här extraherar du ett CFSTR_FILECONTENTS format:
- Extrahera CFSTR_FILEDESCRIPTOR format som ett TYMED_HGLOBAL värde.
- HGlobal-medlemmen i den returnerade STGMEDIUM-strukturen pekar på ett globalt minnesobjekt. Lås objektet genom att skicka hGlobal-värdet till GlobalLock.
- Kasta pekaren som returnerades av GlobalLock till en FILEGROUPDESCRIPTOR-pekare . Den pekar på en FILEGROUPDESCRIPTOR-struktur följt av en eller flera FILEDESCRIPTOR-strukturer . Varje FILEDESCRIPTOR-struktur innehåller en beskrivning av en fil som finns i något av de tillhörande CFSTR_FILECONTENTS formaten.
- Granska FILEDESCRIPTOR-strukturerna för att avgöra vilken som motsvarar den fil som du vill extrahera. Det nollbaserade indexet för filedescriptor-strukturen används för att identifiera filens CFSTR_FILECONTENTS format. Eftersom storleken på ett globalt minnesblock inte är byte-exakt använder du strukturens nFileSizeLow - och nFileSizeHigh-medlemmar för att avgöra hur många byte som representerar filen i det globala minnesobjektet.
- Anropa IDataObject::GetData med cfFormat-medlemmen i FORMATETC-strukturen inställd på värdet CFSTR_FILECONTENTS och lIndex-medlemmen inställd på det index som du fastställde i föregående steg. Medlemmen tymed är vanligtvis inställd på TYMED_HGLOBAL | TYMED_ISTREAM | TYMED_ISTORAGE. Dataobjektet kan sedan välja önskad mekanism för dataöverföring.
- STGMEDIUM-strukturen som IDataObject::GetData returnerar innehåller en pekare till filens data. Granska tymed-medlemmen i strukturen för att fastställa dataöverföringsmekanismen.
- Om tymed är inställt på TYMED_ISTREAM eller TYMED_ISTORAGE använder du gränssnittet för att extrahera data. Om tymed är inställt på TYMED_HGLOBAL finns data i ett globalt minnesobjekt. En diskussion om hur du extraherar data från ett globalt minnesobjekt finns i avsnittet Extrahera ett globalt minnesobjekt från ett dataobjekt i Shell Data Object.
- Anropa GlobalLock för att låsa upp det globala minnesobjekt som du låste i steg 2.
Hantera optimerade flyttåtgärder
Scenario: En fil flyttas från filsystemet till ett namnområdestillägg med en optimerad flytt.
I en konventionell flyttoperation skapar målet en kopia av data och källan tar bort originalet. Den här proceduren kan vara ineffektiv eftersom den kräver två kopior av data. Med stora objekt som databaser kanske en konventionell flyttåtgärd inte ens är praktisk.
Med en optimerad flytt använder målet sin förståelse för hur data lagras för att hantera hela flyttprocessen. Det finns aldrig en andra kopia av data och källan behöver inte ta bort de ursprungliga data. Shell-data passar bra för optimerade flyttningar eftersom målet kan hantera hela åtgärden med hjälp av Shell-API:et. Ett typiskt exempel är att flytta filer. När målet har sökvägen till en fil som ska flyttas kan den använda SHFileOperation för att flytta den. Källan behöver inte ta bort den ursprungliga filen.
Anmärkning
Shell använder normalt en optimerad flytt för att flytta filer. För att kunna hantera Shell-dataöverföringen korrekt måste programmet kunna identifiera och hantera en optimerad flytt.
Optimerade rörelser hanteras på följande sätt:
Källan anropar DoDragDrop med parametern dwEffect inställd på DROPEFFECT_MOVE för att indikera att källobjekten kan flyttas.
Målet tar emot DROPEFFECT_MOVE-värdet via någon av dess IDropTarget-metoder , vilket anger att en flytt tillåts.
Målet kopierar antingen objektet (icke-optimerad flytt) eller överför objektet (optimerad flytt).
Målet anger sedan för källan om den behöver ta bort de ursprungliga data.
En optimerad flytt är standardåtgärden, där data raderas vid målet. Så här informerar du källan om att en optimerad flytt utfördes:
-
- Målet anger det pdwEffect-värde som det tog emot via IDropTarget::Drop-metoden till ett annat värde än DROPEFFECT_MOVE. Den är vanligtvis inställd på antingen DROPEFFECT_NONE eller DROPEFFECT_COPY. Värdet returneras till källan av DoDragDrop.
- Målet anropar också dataobjektets IDataObject::SetData-metod och skickar den en CFSTR_PERFORMEDDROPEFFECT formatidentifierare inställd på DROPEFFECT_NONE. Det här metodanropet är nödvändigt eftersom vissa släppmål kanske inte anger parametern pdwEffect för DoDragDrop korrekt. Det CFSTR_PERFORMEDDROPEFFECT formatet är det tillförlitliga sättet att indikera att en optimerad flytt har ägt rum.
Om målet gjorde en icke-optimerad förflyttning måste källan ta bort data. Så här informerar du källan om att en ooptimerad flytt utfördes:
-
- Målet anger det pdwEffect-värde som det tog emot via dess IDropTarget::D rop-metod till DROPEFFECT_MOVE. Värdet returneras till källan av DoDragDrop.
- Målet anropar också dataobjektets IDataObject::SetData-metod och skickar den en CFSTR_PERFORMEDDROPEFFECT formatidentifierare inställd på DROPEFFECT_MOVE. Det här metodanropet är nödvändigt eftersom vissa släppmål kanske inte anger parametern pdwEffect för DoDragDrop korrekt. Det CFSTR_PERFORMEDDROPEFFECT formatet är det tillförlitliga sättet att indikera att en ooptimerad flytt har ägt rum.
-
Källan inspekterar de två värden som kan returneras av målet. Om båda är inställda på DROPEFFECT_MOVE slutförs den ooptimerade flytten genom att de ursprungliga data tas bort. Annars gjorde målet en optimerad flytt och de ursprungliga data har tagits bort.
Hantera åtgärder för att ta bort vid klistra in
Scenario: En eller flera filer klipps ut från en mapp i Windows Explorer och klistras in i ett namnområdestillägg. Windows Explorer lämnar filerna markerade tills de får feedback om resultatet av inklistringsåtgärden.
Traditionellt, när en användare klipper data försvinner den omedelbart från vyn. Detta kanske inte är effektivt, och det kan leda till användbarhetsproblem om användaren blir orolig för vad som har hänt med data. En annan metod är att använda en delete-on-paste-åtgärd.
Med en delete-on-paste-åtgärd tas inte de markerade data bort direkt från vyn. I stället markerar källprogrammet det som markerat, kanske genom att ändra teckensnittet eller bakgrundsfärgen. När målprogrammet har klistrat in data meddelar det källan om resultatet av åtgärden. Om målet utförde en optimerad flytt kan källan helt enkelt uppdatera sin visning. Om målet utförde en normal flytt måste källan också ta bort sin kopia av data. Om klistra in misslyckas återställer källprogrammet de valda data till sitt ursprungliga utseende.
Anmärkning
Shell använder normalt delete-on-paste när en utklipps-/inklistringsåtgärd används för att flytta filer. Åtgärder för att ta bort vid klistra in med Shell-objekt använder normalt en optimerad flytt för att flytta filerna. För att kunna hantera Shell-dataöverföringen korrekt måste programmet kunna identifiera och hantera åtgärder för att ta bort vid klistra in.
Det grundläggande kravet för radera vid inklistring är att målet måste rapportera resultatet av operationen till källan. Standardtekniker för Urklipp kan dock inte användas för att implementera delete-on-paste eftersom de inte ger ett sätt för målet att kommunicera med källan. I stället använder målprogrammet dataobjektets IDataObject::SetData-metod för att rapportera resultatet till dataobjektet. Dataobjektet kan sedan kommunicera med källan via ett privat gränssnitt.
Den grundläggande proceduren för en delete-on-paste-åtgärd är följande:
- Källan markerar skärmvisningen av valda data.
- Källan skapar ett dataobjekt. Det indikerar en klippoperation genom att lägga till formatet CFSTR_PREFERREDDROPEFFECT med ett datavärde av DROPEFFECT_MOVE.
- Källan placerar dataobjektet i Urklipp med OleSetClipboard.
- Målet hämtar dataobjektet från Urklipp med OleGetClipboard.
- Målet extraherar data från CFSTR_PREFERREDDROPEFFECT. Om det bara är inställt på DROPEFFECT_MOVE kan målet antingen utföra en optimerad flyttning eller helt enkelt kopiera data.
- Om målet inte gör en optimerad flytt anropas metoden IDataObject::SetData med CFSTR_PERFORMEDDROPEFFECT format inställt på DROPEFFECT_MOVE.
- När inklistring är klar anropar målet metoden IDataObject::SetData med CFSTR_PASTESUCCEEDED format inställt på DROPEFFECT_MOVE.
- När källans IDataObject::SetData-metod anropas med CFSTR_PASTESUCCEEDED format inställt på DROPEFFECT_MOVE, måste den kontrollera om den också har fått CFSTR_PERFORMEDDROPEFFECT format inställt på DROPEFFECT_MOVE. Om båda formaten skickas av målet måste källan ta bort data. Om endast det CFSTR_PASTESUCCEEDED formatet tas emot kan källan helt enkelt ta bort data från dess visning. Om överföringen misslyckas uppdaterar källan visningen till sitt ursprungliga utseende.
Överföra data till och från virtuella mappar
Scenario: En användare drar ett objekt från eller släpper det i en virtuell mapp.
Virtuella mappar innehåller objekt som vanligtvis inte ingår i filsystemet. Vissa virtuella mappar, till exempel papperskorgen, kan representera data som lagras på hårddisken men inte som vanliga filsystemobjekt. Vissa kan representera lagrade data som finns i ett fjärrsystem, till exempel en handhållen dator eller en FTP-plats. Andra, till exempel mappen Skrivare, innehåller objekt som inte representerar lagrade data alls. Vissa virtuella mappar ingår i systemet, men utvecklare kan också skapa och installera anpassade virtuella mappar genom att implementera ett namnområdestillägg.
Oavsett vilken typ av data eller hur de lagras, visas mappen och filobjekten som finns i en virtuell mapp av Gränssnittet som om de vore vanliga filer och mappar. Det är den virtuella mappens ansvar att ta de data som den innehåller och presentera dem för Gränssnittet på rätt sätt. Det här kravet innebär att virtuella mappar normalt stöder överföring av dra och släpp-data och Urklippsdata.
Det finns alltså två grupper av utvecklare som behöver sysslar med dataöverföring till och från virtuella mappar:
- Utvecklare vars program måste acceptera data som överförs från en virtuell mapp.
- Utvecklare vars namnområdestillägg måste ha korrekt stöd för dataöverföring.
Acceptera data från en virtuell mapp
Virtuella mappar kan representera praktiskt taget alla typer av data och kan lagra dessa data på valfritt sätt. Vissa virtuella mappar kan faktiskt innehålla vanliga filsystemfiler och mappar. Andra kan till exempel packa alla sina objekt i ett enda dokument eller en databas.
När ett filsystemobjekt överförs till ett program innehåller dataobjektet normalt ett CF_HDROP format med objektets fullständigt kvalificerade sökväg. Ditt program kan extrahera den här strängen och använda de vanliga filsystemfunktionerna för att öppna filen och extrahera dess data. Men eftersom virtuella mappar vanligtvis inte innehåller normala filsystemobjekt använder de vanligtvis inte CF_HDROP.
I stället för CF_HDROP överförs data normalt från virtuella mappar med CFSTR_FILEDESCRIPTOR CFSTR_FILECONTENTS/ format. Formatet CFSTR_FILECONTENTS har två fördelar jämfört med CF_HDROP:
- Ingen särskild metod för datalagring antas.
- Formatet är mer flexibelt. Det stöder tre mekanismer för dataöverföring: ett globalt minnesobjekt, ett IStream-gränssnitt eller ett IStorage-gränssnitt .
Globala minnesobjekt används sällan för att överföra data till eller från virtuella objekt eftersom data måste kopieras till minnet i sin helhet. Överföring av en gränssnittspekare kräver nästan inget minne och är mycket mer effektivt. Med mycket stora filer kan en gränssnittspekare vara den enda praktiska dataöverföringsmekanismen. Data representeras vanligtvis av en IStream-pekare eftersom gränssnittet är något mer flexibelt än IStorage. Målet extraherar pekaren från dataobjektet och använder gränssnittsmetoderna för att extrahera data.
Mer information om hur du hanterar CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS format finns i Använda CFSTR_FILECONTENTS format för att extrahera data från en fil.
Överföra data till och från ett NameSpace-tillägg
När du implementerar ett namnområdestillägg vill du normalt ha stöd för dra och släpp-funktioner. Följ rekommendationerna för släppkällor och mål som beskrivs i allmänna riktlinjer. I synnerhet måste ett namnområdestillägg:
- Kunna hantera CFSTR_FILEDESCRIPTOR/CFSTR_FILECONTENTS format. Dessa två format används normalt för att överföra objekt till och från namnområdestillägg.
- Kunna hantera optimerade rörelser. Shell förväntar sig att Shell-objekt ska flyttas med en optimerad process.
- Kunna hantera en delete-on-paste-åtgärd . Shell använder delete-on-paste när objekt flyttas från gränssnittet med en utklipps-/inklistringsåtgärd.
- Kunna hantera dataöverföring via ett IStream- eller IStorage-gränssnitt . Dataöverföring till eller från en virtuell mapp hanteras normalt genom överföring av en av dessa två gränssnittspekare, vanligtvis en IStream-pekare . Målet anropar sedan gränssnittsmetoderna för att extrahera data:
-
- Som en släppkälla måste namnområdestillägget extrahera data från lagringen och skicka dem via det här gränssnittet till målet.
- Som ett släppmål måste ett namnområdestillägg acceptera data från en källa via det här gränssnittet och lagra dem korrekt.
-
Släpp filer i papperskorgen
Scenario: Användaren släpper en fil på papperskorgen. Programmet eller namnområdestillägget tar bort den ursprungliga filen.
Papperskorgen är en virtuell mapp som används som lagringsplats för filer som inte längre behövs. Så länge papperskorgen inte har tömts kan användaren senare återställa filen och returnera den till filsystemet.
För det mesta fungerar överföring av Shell-objekt till papperskorgen ungefär som alla andra mappar. Men när en användare släpper en fil på papperskorgen måste källan ta bort originalet, även om feedbacken från mappen anger en kopieringsåtgärd. Normalt har en släppkälla inget sätt att veta vilken mapp dess dataobjekt har släppts på. Men för Windows 2000 och senare system, när ett dataobjekt släpps på Recycle Bin, Shell anropar dataobjektets IDataObject::SetData-metod med ett CFSTR_TARGETCLSID format inställt på Papperskorgens klassidentifierare (CLSID) (CLSID_RecycleBin). För att hantera papperskorgen korrekt bör dataobjektet kunna känna igen det här formatet och kommunicera informationen till källan via ett privat gränssnitt.
Anmärkning
När IDataObject::SetData anropas med ett CFSTR_TARGETCLSID format inställt på CLSID_RecycleBin, bör datakällan stänga alla öppna referenser till de objekt som överförs innan de returneras från metoden. Annars kan du skapa delningsöverträdelser.
Skapa och importera skrotfiler
Scenario: En användare drar vissa data från ett OLE-programs datafil och släpper dem på skrivbordet eller Windows Explorer.
Windows tillåter användare att dra ett objekt från ett OLE-programs datafil och släppa det på skrivbordet eller en filsystemmapp. Den här åtgärden skapar en skrotfil som innehåller data eller en länk till data. Filnamnet hämtas från det kortnamn som har registrerats för CLSID för objektet och datan för CF_TEXT. För att Shell ska kunna skapa en skrotfil som innehåller data måste programmets IDataObject-gränssnitt ha stöd för CF_EMBEDSOURCE Urklippsformat. Om du vill skapa en fil som innehåller en länk måste IDataObject ha stöd för CF_LINKSOURCE format.
Det finns också tre valfria funktioner som ett program kan implementera för att stödja skrotfiler:
- Stöd för tur och retur
- Cachelagrade dataformat
- Fördröjd återgivning
Support tur och retur
En tur och retur-resa innebär att överföra ett dataobjekt till en annan container och sedan tillbaka till det ursprungliga dokumentet. En användare kan till exempel överföra en grupp celler från ett kalkylblad till skrivbordet och skapa en skrotfil med data. Om användaren sedan överför skrotet tillbaka till kalkylbladet måste data integreras i dokumentet som det var före den ursprungliga överföringen.
När Shell skapar skrotfilen representerar den data som ett inbäddningsobjekt. När skrotet överförs till en annan container överförs det som ett inbäddningsobjekt, även om det returneras till det ursprungliga dokumentet. Ditt program ansvarar för att fastställa dataformatet i skrotet och föra tillbaka data i sitt ursprungliga format om det behövs.
För att upprätta formatet för det inbäddade objektet fastställer du dess CLSID genom att hämta objektets CF_OBJECTDESCRIPTOR format. Om CLSID anger ett dataformat som tillhör programmet bör det överföra inbyggda data i stället för att anropa OleCreateFromData.
Cache-lagrade dataformat
När Shell skapar en skrotfil kontrollerar den registret efter listan över tillgängliga format. Som standard finns det två tillgängliga format: CF_EMBEDSOURCE och CF_LINKSOURCE. Det finns dock ett antal scenarier där program kan behöva ha skrotfiler i olika format:
- För att tillåta att rester överförs till icke-OLE-containrar, som inte kan acceptera inbäddade objektformat.
- För att tillåta programsviter att kommunicera med ett privat format.
- För att göra tur och retur enklare att hantera.
Applikationer kan lägga till format i utkastet genom att cachelagra dem i registret. Det finns två typer av cachelagrade format:
- Cacheformat för prioritet. För dessa format kopieras data i sin helhet till utklippet från dataobjektet.
- Fördröjningsrenderade format För dessa format kopieras inte dataobjektet till skrotet. I stället fördröjs återgivningen tills målet begär data. Fördröjd rendering beskrivs mer detaljerat i nästa avsnitt.
Om du vill lägga till en prioritetscache eller ett fördröjningsutgivet format skapar du en DataFormat-undernyckel under CLSID-nyckeln för programmet som är datakällan. Under den undernyckeln skapar du undernyckeln PriorityCacheFormats eller DelayRenderFormats . För varje prioriterad cache eller format för fördröjd rendering skapar du en numrerad undernyckel som börjar med noll. Ange värdet för den här nyckeln till antingen en sträng med det registrerade namnet på formatet eller ett #X värde, där X representerar formatnumret för ett standardformat för Urklipp.
Följande exempel visar cachelagrade format för två program. MyProg1-programmet har riktextformatet som ett prioriterat cacheformat och ett privat format "Mitt format" som ett format som renderas senare. MyProg2-programmet har CF_BITMAP format (#8") som ett prioriterat cacheformat.
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
Ytterligare format kan läggas till genom att skapa ytterligare numrerade undernycklar.
Fördröjd återgivning
Med ett fördröjt återgivningsformat kan ett program skapa en skrotfil, men fördröja kostnaden för att återge data tills det begärs av ett mål. IDataObject-gränssnittet för ett skrot erbjuder fördröjda återgivningsformat till målet tillsammans med interna och cachelagrade data. Om målet begär ett fördröjt återgivningsformat kör Shell programmet och tillhandahåller data till målet från det aktiva objektet.
Anmärkning
Eftersom fördröjd återgivning är något riskfylld bör den användas med försiktighet. Det fungerar inte om servern inte är tillgänglig eller på program som inte är OLE-aktiverade.
Dra och släppa gränssnittsobjekt asynkront
Scenario: En användare överför ett stort datablock från källa till mål. För att undvika att blockera båda programmen under en betydande tid extraherar målet data asynkront.
Normalt är dra och släpp en synkron åtgärd. I korthet:
- Släppkällan anropar DoDragDrop och blockerar dess primära tråd tills funktionen returnerar. Blockering av den primära tråden blockerar normalt UI-bearbetning.
- När målets IDropTarget::D rop-metod anropas extraherar målet data från dataobjektet i den primära tråden. Den här proceduren blockerar normalt målets användargränssnittsbearbetning under hela extraheringsprocessen.
- När data har extraherats returnerar målet IDropTarget::D rop-anropet , systemet returnerar DoDragDrop och båda trådarna kan fortsätta.
Kort och kort kan synkron dataöverföring blockera de primära trådarna i båda programmen under en betydande tid. I synnerhet måste båda trådarna vänta medan målet extraherar data. För små mängder data är den tid som krävs för att extrahera data liten och synkron dataöverföring fungerar ganska bra. Men synkront extrahera stora mängder data kan orsaka långa fördröjningar och störa användargränssnittet för både mål och källa.
Gränssnittet IAsyncOperation/IDataObjectAsyncCapability är ett valfritt gränssnitt som kan implementeras av ett dataobjekt. Det ger släppmålet möjlighet att extrahera data från dataobjektet asynkront på en bakgrundstråd. När dataextraheringen har överlämnats till bakgrundstråden kan de primära trådarna i båda programmen fortsätta.
Använda IASyncOperation/IDataObjectAsyncCapability
Anmärkning
Gränssnittet hette ursprungligen IAsyncOperation, men detta ändrades senare till IDataObjectAsyncCapability. Annars är de två gränssnitten identiska.
Syftet med IAsyncOperation/IDataObjectAsyncCapability är att tillåta att släppkällan och släppmålet förhandlar om data kan extraheras asynkront. Följande procedur beskriver hur släppkällan använder gränssnittet:
- Skapa ett dataobjekt som exponerar IAsyncOperation/IDataObjectAsyncCapability.
- Anropa SetAsyncMode med fDoOpAsync inställt på VARIANT_TRUE för att indikera att en asynkron åtgärd stöds.
- När DoDragDrop har returnerats anropar du InOperation:
- Om InOperation misslyckas eller returnerar VARIANT_FALSE har en normal synkron dataöverföring ägt rum och dataextraheringsprocessen är klar. Källan bör göra alla rensningar som krävs och fortsätta.
- Om InOperation returnerar VARIANT_TRUE extraheras data asynkront. Rensningsåtgärder ska hanteras av EndOperation.
- Frigör dataobjektet.
- När den asynkrona dataöverföringen är klar meddelar dataobjektet normalt källan via ett privat gränssnitt.
Följande procedur beskriver hur släppmålet använder gränssnittet IAsyncOperation/IDataObjectAsyncCapability för att extrahera data asynkront:
- När systemet anropar IDropTarget::D rop anropar du IDataObject::QueryInterface och begär ett IAsyncOperation/IDataObjectAsyncCapability-gränssnitt (IID_IAsyncOperation/IID_IDataObjectAsyncCapability) från dataobjektet.
- Anropa GetAsyncMode. Om metoden returnerar VARIANT_TRUE stöder dataobjektet asynkron dataextrahering.
- Skapa en separat tråd för att hantera extrahering av data och anropa StartOperation.
- Returnera IDropTarget::Drop-samtalet, precis som för en normal dataöverföringsåtgärd. DoDragDrop returnerar och avblockerar släppkällan. Anropa inte IDataObject::SetData för att ange resultatet av en optimerad flytt- eller delete-on-paste-åtgärd. Vänta tills åtgärden är klar.
- Extrahera data på bakgrundstråden. Målets primära tråd är avblockerad och kan fortsätta.
- Om dataöverföringen var en optimerad flytt- eller delete-on-paste-åtgärd anropar du IDataObject::SetData för att ange resultatet.
- Meddela dataobjektet att extraheringen är klar genom att anropa EndOperation.