Zwischenablagevorgänge
Ein Fenster sollte beim Ausschneiden, Kopieren oder Einfügen von Daten die Zwischenablage verwenden. In einem Fenster werden Daten für Ausschneiden- und Kopiervorgänge in der Zwischenablage platziert und Daten aus der Zwischenablage für Einfügevorgänge abgerufen. In den folgenden Abschnitten werden diese Vorgänge und verwandte Probleme beschrieben.
Um Daten aus der Zwischenablage zu platzieren oder daten aus der Zwischenablage abzurufen, muss ein Fenster zuerst die Zwischenablage mithilfe der OpenClipboard--Funktion öffnen. Nur ein Fenster kann die Zwischenablage gleichzeitig geöffnet haben. Um herauszufinden, welches Fenster die Zwischenablage geöffnet hat, rufen Sie die GetOpenClipboardWindow-Funktion auf. Nach Abschluss des Vorgangs muss das Fenster die Zwischenablage schließen, indem die CloseClipboard--Funktion aufgerufen wird.
Die folgenden Themen werden in diesem Abschnitt behandelt.
- Ausschneiden und Kopieren
- Einfügevorgänge
- Besitz der Zwischenablage
- verzögertes Rendering
- Arbeitsspeicher und die Zwischenablage
Ausschneiden und Kopieren
Zum Platzieren von Informationen in der Zwischenablage löscht ein Fenster zunächst alle vorherigen Zwischenablageinhalte mithilfe der funktion EmptyClipboard. Diese Funktion sendet die WM_DESTROYCLIPBOARD Nachricht an den vorherigen Besitzer der Zwischenablage, gibt Ressourcen frei, die Daten in der Zwischenablage zugeordnet sind, und weist dem Fenster, in dem die Zwischenablage geöffnet ist, den Besitz der Zwischenablage zu. Um herauszufinden, welches Fenster die Zwischenablage besitzt, rufen Sie die GetClipboardOwner-Funktion auf.
Nach dem Leeren der Zwischenablage platziert das Fenster Daten in der Zwischenablage so viele Zwischenablageformate wie möglich, sortiert vom beschreibendsten Zwischenablageformat bis zum am wenigsten beschreibenden Format. Für jedes Format ruft das Fenster die SetClipboardData--Funktion auf, wobei der Formatbezeichner und ein globaler Speicherhandle angegeben werden. Das Speicherhandle kann NULL sein, was angibt, dass das Fenster die Daten auf Anforderung rendert. Weitere Informationen finden Sie unter verzögertes Rendering.
Einfügevorgänge
Zum Abrufen von Einfügeinformationen aus der Zwischenablage bestimmt ein Fenster zuerst das abzurufende Zwischenablageformat. In der Regel listet ein Fenster die verfügbaren Zwischenablageformate mithilfe der EnumClipboardFormats Funktion auf und verwendet das erste zu erkennene Format. Diese Methode wählt das beste verfügbare Format gemäß der Priorität aus, die festgelegt wurde, als die Daten in der Zwischenablage platziert wurden.
Alternativ kann ein Fenster die GetPriorityClipboardFormat--Funktion verwenden. Diese Funktion identifiziert das beste verfügbare Zwischenablageformat gemäß einer angegebenen Priorität. Ein Fenster, das nur ein Zwischenablageformat erkennt, kann einfach bestimmen, ob dieses Format mithilfe der funktion IsClipboardFormatAvailable verfügbar ist.
Nach dem Bestimmen des zu verwendenden Zwischenablageformats ruft ein Fenster die GetClipboardData--Funktion auf. Diese Funktion gibt das Handle an ein globales Speicherobjekt zurück, das Daten im angegebenen Format enthält. Ein Fenster kann das Speicherobjekt kurz sperren, um die Daten zu untersuchen oder zu kopieren. Ein Fenster sollte das Objekt jedoch nicht freigeben oder es für einen längeren Zeitraum gesperrt lassen.
Besitz der Zwischenablage
Der Besitzer der Zwischenablage ist das Fenster, das den Informationen in der Zwischenablage zugeordnet ist. Ein Fenster wird zum Besitzer der Zwischenablage, wenn daten in der Zwischenablage platziert werden, insbesondere, wenn die funktion EmptyClipboard aufgerufen wird. Das Fenster bleibt der Besitzer der Zwischenablage, bis es geschlossen ist oder ein anderes Fenster die Zwischenablage leert.
Wenn die Zwischenablage geleert wird, empfängt der Besitzer der Zwischenablage eine WM_DESTROYCLIPBOARD Nachricht. Im Folgenden sind einige Gründe aufgeführt, warum ein Fenster diese Meldung verarbeiten kann:
- Das Fenster hat das Rendern eines oder mehrerer Zwischenablageformate verzögert. Als Reaktion auf die WM_DESTROYCLIPBOARD Nachricht kann das Fenster Ressourcen freigeben, die es zugewiesen hatte, um Daten auf Anforderung zu rendern. Weitere Informationen zum Rendern von Daten finden Sie unter Verzögertes Rendering.
- Das Fenster hat Daten in der Zwischenablage in einem privaten Zwischenablageformat platziert. Die Daten für private Zwischenablageformate werden vom System nicht freigegeben, wenn die Zwischenablage geleert wird. Daher sollte der Besitzer der Zwischenablage die Daten beim Empfang der WM_DESTROYCLIPBOARD Nachricht freigeben. Weitere Informationen zu privaten Zwischenablageformaten finden Sie unter Zwischenablageformate.
- Das Fenster platziert Daten in der Zwischenablage mithilfe des CF_OWNERDISPLAY Zwischenablageformats. Als Reaktion auf die WM_DESTROYCLIPBOARD Nachricht kann das Fenster Ressourcen freigeben, die zum Anzeigen von Informationen im Anzeigefenster der Zwischenablage verwendet wurden. Weitere Informationen zu diesem alternativen Format finden Sie unter Owner Display Format.
Verzögertes Rendering
Beim Platzieren eines Zwischenablageformats in der Zwischenablage kann ein Fenster das Rendern der Daten in diesem Format verzögern, bis die Daten benötigt werden. Dazu kann eine Anwendung NULL- für den hData--Parameter der SetClipboardData--Funktion angeben. Dies ist nützlich, wenn die Anwendung mehrere Zwischenablageformate unterstützt, von denen einige oder alle zeitaufwändig zum Rendern sind. Durch Übergeben eines NULL- Handle rendert ein Fenster komplexe Zwischenablageformate nur, wenn und wenn sie erforderlich sind.
Wenn ein Fenster das Rendern eines Zwischenablageformats verzögert, muss es bereit sein, das Format auf Anforderung so lange wie der Besitzer der Zwischenablage zu rendern. Das System sendet dem Zwischenablagebesitzer eine WM_RENDERFORMAT Nachricht, wenn eine Anforderung für ein bestimmtes Format empfangen wird, das nicht gerendert wurde. Beim Empfang dieser Nachricht sollte das Fenster die SetClipboardData--Funktion aufrufen, um ein globales Speicherhandle in der Zwischenablage im angeforderten Format zu platzieren.
Eine Anwendung darf die Zwischenablage nicht öffnen, bevor sie SetClipboardData- als Reaktion auf die WM_RENDERFORMAT Nachricht aufruft. Das Öffnen der Zwischenablage ist nicht erforderlich, und jeder Versuch, dies zu tun, schlägt fehl, da die Zwischenablage derzeit von der Anwendung geöffnet wird, die das Zu rendern des Formats angefordert hat.
Wenn der Besitzer der Zwischenablage ungefähr zerstört werden soll und das Rendern einiger oder aller Zwischenablageformate verzögert wurde, empfängt er die WM_RENDERALLFORMATS Nachricht. Beim Empfang dieser Nachricht sollte das Fenster die Zwischenablage öffnen, überprüfen Sie, ob es sich weiterhin um den Besitzer der Zwischenablage mit der GetClipboardOwner--Funktion handelt, und platzieren Sie dann gültige Speicherhandles in der Zwischenablage für alle von ihr bereitgestellten Zwischenablageformate. Dadurch wird sichergestellt, dass diese Formate nach dem Löschen des Zwischenablagebesitzers verfügbar bleiben.
Im Gegensatz zu WM_RENDERFORMATsollte eine Anwendung, die auf WM_RENDERALLFORMATS reagiert, die Zwischenablage öffnen, bevor sie SetClipboardData- aufruft, um alle globalen Speicherhandles in der Zwischenablage zu platzieren.
Alle Formate der Zwischenablage, die nicht als Reaktion auf die WM_RENDERALLFORMATS Nachricht gerendert werden, sind nicht mehr für andere Anwendungen verfügbar und werden von den Zwischenablagefunktionen nicht mehr aufgezählt.
Richtlinien für verzögertes Rendering
Das verzögerte Rendern ist ein Leistungsfeature, das es einer Anwendung ermöglicht, zu verhindern, dass Die Zwischenablagedaten in einem Format gerendert werden, das möglicherweise nie angefordert wird. Die Verwendung verzögerter Renderings umfasst jedoch die folgenden Nachteile, die berücksichtigt werden sollten:
- Durch die Verwendung des verzögerten Renderings wird der Anwendung eine gewisse Komplexität hinzugefügt, sodass zwei Renderingfenstermeldungen verarbeitet werden müssen, wie oben beschrieben.
- Die Verwendung des verzögerten Renderings bedeutet, dass die Anwendung die Option verliert, die Benutzeroberfläche reaktionsfähig zu halten, wenn das Rendern der Daten genügend Zeit benötigt, um dem Benutzer erkennbar zu sein. Bei verzögertem Rendern muss das Fenster die Daten bei der Verarbeitung einer Renderfenstermeldung rendern, wie oben beschrieben. Wenn die Daten daher sehr zeitaufwändig zum Rendern sind, kann die Anwendung während des Renderns sichtbar nicht mehr reagieren (hängend) werden, da während des Renderns keine anderen Fenstermeldungen verarbeitet werden können, während die Renderfenstermeldung verarbeitet wird. Eine Anwendung, die das verzögerte Rendering nicht verwendet, kann stattdessen festlegen, dass Daten in einem Hintergrundthread gerendert werden, um die UI-Antwort während des Renderings beizubehalten, z. B. die Bereitstellung von Fortschritts- oder Abbruchoptionen, die bei Verwendung des verzögerten Renderings nicht verfügbar sind.
- Durch die Verwendung des verzögerten Renderings wird ein geringer Aufwand verursacht, wenn die Daten letztendlich benötigt werden. Bei Verwendung des Verzögerungsrenderings ruft ein Fenster zunächst die SetClipboardData--Funktion mit einem NULL- Handle auf, und wenn die Daten später benötigt werden, muss das Fenster auf eine Fenstermeldung reagieren und die SetClipboardData- Funktion ein zweites Mal mit einem Handle für die gerenderten Daten aufrufen, wie oben beschrieben. Wenn die Daten letztendlich benötigt werden, addiert die Verwendung des verzögerten Renderings die Kosten für die Verarbeitung einer Fensternachricht und das Aufrufen der SetClipboardData Funktion ein zweites Mal. Diese Kosten sind klein, aber nicht null. Wenn eine Anwendung nur ein einzelnes Zwischenablageformat unterstützt und die Daten immer angefordert werden, fügt das verzögerte Rendering lediglich diesen geringen Mehraufwand hinzu (die Kosten variieren je nach Hardware; eine Schätzung liegt zwischen 10 und 100 Mikrosekunden). Wenn die Daten jedoch gering sind, kann der Mehraufwand für die Verwendung von verzögerten Renderings die Kosten zum Rendern der Daten überschreiten, was den Zweck der Verwendung verzögerter Renderings zur Verbesserung der Leistung beeinträchtigen könnte. (Bei Daten, die sich bereits in ihrer endgültigen Form befinden, hat der Mehraufwand für die Verwendung des verzögerten Renderings die Kosten zum Kopieren der Daten in die Zwischenablage überschritten, wenn die Daten 100 KiB oder weniger waren. Diese Tests umfassen nicht die Kosten zum Rendern von Daten, nur um sie nach dem Rendern zu kopieren.)
- Verzögertes Rendering ist ein Leistungsvorteil, wenn es mehr Zeit spart, als es mehr Aufwand verursacht. Um den Aufwand des verzögerten Renderings zu ermitteln, ist die Messung am besten, aber 10 bis 100 Mikrosekunden ist eine Schätzung. Um die Einsparungen bei der Verwendung des verzögerten Renderings für jedes Zwischenablageformat zu berechnen, messen Sie die Kosten zum Rendern der Daten in diesem Format und bestimmen, wie häufig dieses Format schließlich angefordert wird (basierend auf den oben beschriebenen Fenstermeldungen). Multiplizieren Sie die Kosten für das Rendern der Daten mit dem Prozentsatz der Zeit, die die Daten nicht letztendlich angefordert werden (bevor die Zwischenablage geleert wird oder sich der Inhalt ändert), um die Einsparungen des verzögerten Renderings für jedes Zwischenablageformat zu bestimmen. Verzögertes Rendern ist ein Nettoleistungsvorteil, wenn die Einsparungen die Mehrkosten überschreiten.
- Als konkrete Richtlinie sollten Anwendungen, die nur ein einzelnes Zwischenablageformat unterstützen, z. B. Text, bei dem die Daten nicht wesentlich teuer zu rendern sind, in Betracht ziehen, die Daten direkt in die Zwischenablage zu platzieren, wenn die Größe der Daten 4 KiB oder weniger beträgt.
Arbeitsspeicher und Zwischenablage
Ein Speicherobjekt, das in der Zwischenablage platziert werden soll, sollte mithilfe der GlobalAlloc--Funktion mit dem GMEM_MOVEABLE-Flag zugewiesen werden.
Nachdem ein Speicherobjekt in der Zwischenablage platziert wurde, wird der Besitz dieses Speicherhandles an das System übertragen. Wenn die Zwischenablage geleert wird und das Speicherobjekt eines der folgenden Zwischenablageformate aufweist, gibt das System das Speicherobjekt frei, indem die angegebene Funktion aufgerufen wird:
Funktion zum Freigeben des Objekts | Format der Zwischenablage |
---|---|
DeleteMetaFile- |
CF_DSPENHMETAFILE CF_DSPMETAFILEPICT CF_ENHMETAFILE CF_METAFILEPICT |
DeleteObject- |
CF_BITMAP CF_DSPBITMAP CF_PALETTE |
GlobalFree- |
CF_DIB CF_DIBV5 CF_DSPTEXT CF_OEMTEXT CF_TEXT CF_UNICODETEXT |
nichts |
CF_OWNERDISPLAY Wenn die Zwischenablage eines CF_OWNERDISPLAY Objekts geleert wird, muss die Anwendung selbst das Speicherobjekt freigeben. |