Operazioni degli Appunti

Una finestra deve utilizzare gli Appunti per tagliare, copiare o incollare i dati. Una finestra inserisce i dati negli Appunti per le operazioni taglia e copia e recupera i dati dagli Appunti per le operazioni incollate. Le sezioni seguenti descrivono queste operazioni e i problemi correlati.

Per inserire o recuperare dati dagli Appunti, una finestra deve prima aprire gli Appunti usando la funzione OpenClipboard. Una sola finestra può avere gli Appunti aperti alla volta. Per scoprire quale finestra ha gli Appunti aperti, chiamare la funzione GetOpenClipboardWindow. Al termine, la finestra deve chiudere gli Appunti chiamando la funzione CloseClipboard.

In questa sezione vengono illustrati gli argomenti seguenti.

Operazioni taglia e copia

Per inserire informazioni negli Appunti, una finestra cancella innanzitutto qualsiasi contenuto degli Appunti precedente usando la funzione EmptyClipboard. Questa funzione invia il messaggio di WM_DESTROYCLIPBOARD al proprietario degli Appunti precedente, libera le risorse associate ai dati negli Appunti e assegna la proprietà degli Appunti alla finestra con gli Appunti aperti. Per individuare la finestra proprietaria degli Appunti, chiamare la funzione GetClipboardOwner.

Dopo aver svuotato gli Appunti, la finestra inserisce i dati negli Appunti nel maggior numero possibile di formati degli Appunti, ordinati dal formato degli Appunti più descrittivo al meno descrittivo. Per ogni formato, la finestra chiama la funzione SetClipboardData , specificando l'identificatore di formato e un handle di memoria globale. L'handle di memoria può essere NULL, a indicare che la finestra esegue il rendering dei dati su richiesta. Per altre informazioni, vedere Rendering ritardato.

Operazioni Incolla

Per recuperare le informazioni incolla dagli Appunti, una finestra determina innanzitutto il formato degli Appunti da recuperare. In genere, una finestra enumera i formati degli Appunti disponibili usando la funzione EnumClipboardFormats e usa il primo formato riconosciuto. Questo metodo seleziona il formato migliore disponibile in base al set di priorità impostato quando i dati sono stati inseriti negli Appunti.

In alternativa, una finestra può usare la funzione GetPriorityClipboardFormat. Questa funzione identifica il formato degli Appunti migliore disponibile in base a una priorità specificata. Una finestra che riconosce un solo formato degli Appunti può semplicemente determinare se il formato è disponibile tramite la funzione IsClipboardFormatAvailable.

Dopo aver determinato il formato degli Appunti da usare, una finestra chiama la funzione GetClipboardData. Questa funzione restituisce l'handle a un oggetto memoria globale contenente i dati nel formato specificato. Una finestra può bloccare brevemente l'oggetto memoria per esaminare o copiare i dati. Tuttavia, una finestra non deve liberare l'oggetto o lasciarlo bloccato per un lungo periodo di tempo.

Proprietà degli Appunti

Il proprietario degli Appunti è la finestra associata alle informazioni negli Appunti. Una finestra diventa il proprietario degli Appunti quando inserisce i dati negli Appunti, in particolare quando chiama la funzione EmptyClipboard. La finestra rimane il proprietario degli Appunti fino a quando non viene chiusa o un'altra finestra svuota gli Appunti.

Quando gli Appunti vengono svuotati, il proprietario degli Appunti riceve un messaggio di WM_DESTROYCLIPBOARD . Di seguito sono riportati alcuni motivi per cui una finestra potrebbe elaborare questo messaggio:

  • Il rendering ritardato della finestra di uno o più formati degli Appunti. In risposta al messaggio di WM_DESTROYCLIPBOARD , la finestra potrebbe liberare risorse allocate per eseguire il rendering dei dati su richiesta. Per altre informazioni sul rendering dei dati, vedere Rendering ritardato.
  • La finestra ha inserito i dati negli Appunti in un formato privato degli Appunti. I dati per i formati degli Appunti privati non vengono liberati dal sistema quando gli Appunti vengono svuotati. Pertanto, il proprietario degli Appunti deve liberare i dati quando riceve il messaggio di WM_DESTROYCLIPBOARD . Per altre informazioni sui formati degli Appunti privati, vedere Formati degli Appunti.
  • La finestra ha inserito i dati negli Appunti usando il formato degli Appunti CF_OWNERDISPLAY . In risposta al messaggio di WM_DESTROYCLIPBOARD , la finestra potrebbe liberare risorse usate per visualizzare le informazioni nella finestra del visualizzatore appunti. Per altre informazioni su questo formato alternativo, vedere Formato di visualizzazione proprietario.

Rendering ritardato

Quando si posiziona un formato degli Appunti negli Appunti, una finestra può ritardare il rendering dei dati in tale formato fino a quando non sono necessari i dati. A tale scopo, un'applicazione può specificare NULL per il parametro hData della funzione SetClipboardData. Ciò è utile se l'applicazione supporta diversi formati degli Appunti, alcuni o tutti richiedono molto tempo per il rendering. Passando un handle NULL , una finestra esegue il rendering di formati complessi degli Appunti solo quando e se sono necessari.

Se una finestra ritarda il rendering di un formato degli Appunti, è necessario prepararsi a eseguire il rendering del formato su richiesta, purché sia il proprietario degli Appunti. Il sistema invia al proprietario degli Appunti un messaggio di WM_RENDERFORMAT quando viene ricevuta una richiesta per un formato specifico di cui non è stato eseguito il rendering. Dopo aver ricevuto questo messaggio, la finestra deve chiamare la funzione SetClipboardData per posizionare un handle di memoria globale negli Appunti nel formato richiesto.

Un'applicazione non deve aprire gli Appunti prima di chiamare SetClipboardData in risposta al messaggio di WM_RENDERFORMAT . L'apertura degli Appunti non è necessaria e qualsiasi tentativo di eseguire questa operazione avrà esito negativo perché gli Appunti sono attualmente aperti dall'applicazione che ha richiesto il rendering del formato.

Se il proprietario degli Appunti sta per essere eliminato definitivamente e ha ritardato il rendering di alcuni o tutti i formati degli Appunti, riceve il messaggio WM_RENDERALLFORMATS. Dopo aver ricevuto questo messaggio, la finestra dovrebbe aprire gli Appunti, verificare che sia ancora il proprietario degli Appunti con la funzione GetClipboardOwner e quindi posizionare handle di memoria validi negli Appunti per tutti i formati degli Appunti forniti. In questo modo si garantisce che questi formati rimangano disponibili dopo che il proprietario degli Appunti viene eliminato definitivamente.

A differenza di WM_RENDERFORMAT, un'applicazione che risponde a WM_RENDERALLFORMATS dovrebbe aprire gli Appunti prima di chiamare SetClipboardData per posizionare qualsiasi handle di memoria globale negli Appunti.

Tutti i formati degli Appunti di cui non viene eseguito il rendering in risposta al messaggio WM_RENDERALLFORMATS cessano di essere disponibili per altre applicazioni e non vengono più enumerati dalle funzioni degli Appunti.

Linee guida per il rendering ritardato

Il rendering ritardato è una funzionalità di prestazioni che consente a un'applicazione di evitare di eseguire il rendering dei dati degli Appunti in un formato che potrebbe non essere mai richiesto. Tuttavia, l'uso del rendering ritardato comporta i compromessi seguenti da prendere in considerazione:

  • L'uso del rendering ritardato aggiunge una certa complessità all'applicazione, richiedendo la gestione di due messaggi della finestra di rendering, come descritto in precedenza.
  • L'uso del rendering ritardato significa che l'applicazione perde l'opzione per mantenere reattiva l'interfaccia utente se il rendering dei dati richiede tempo sufficiente per l'utente. Con il rendering ritardato, se i dati sono eventualmente necessari, la finestra deve eseguire il rendering dei dati durante l'elaborazione di un messaggio della finestra di rendering, come descritto in precedenza. Di conseguenza, se i dati richiedono molto tempo per il rendering, l'applicazione può diventare visibilmente non rispondente (bloccata) durante il rendering, perché non è possibile elaborare altri messaggi di finestra durante l'elaborazione del messaggio della finestra di rendering. Un'applicazione che non usa il rendering ritardato potrebbe invece scegliere di eseguire il rendering dei dati in un thread in background per mantenere la risposta dell'interfaccia utente durante il rendering, fornendo ad esempio opzioni di avanzamento o annullamento, che non sono disponibili quando si usa il rendering ritardato.
  • L'uso del rendering ritardato consente di aggiungere una piccola quantità di overhead se i dati sono eventualmente necessari. Quando si usa il rendering ritardato, una finestra chiama inizialmente la funzione SetClipboardData con un handle NULL e, se i dati sono necessari in un secondo momento, la finestra deve rispondere a un messaggio di finestra e chiamare la funzione SetClipboardData una seconda volta con un handle per i dati di cui è stato eseguito il rendering, come descritto in precedenza. Di conseguenza, se i dati sono eventualmente necessari, l'uso del rendering ritardato aggiunge il costo di elaborazione di un messaggio di finestra e la chiamata alla funzione SetClipboardData una seconda volta. Questo costo è ridotto ma non zero. Se un'applicazione supporta solo un singolo formato degli Appunti e se i dati vengono sempre richiesti, l'uso del rendering ritardato aggiunge solo questa piccola quantità di overhead (il costo varia in base all'hardware; una stima è compresa tra 10 e 100 microsecondi). Tuttavia, se i dati sono di piccole dimensioni, il sovraccarico dell'uso del rendering ritardato può superare il costo per il rendering dei dati, che potrebbe sconfiggere lo scopo di usare il rendering ritardato per migliorare le prestazioni. Durante il test, per i dati già presenti nella forma finale, il sovraccarico dell'uso del rendering ritardato ha superato in modo coerente il costo per copiare i dati negli Appunti se i dati erano di 100 KiB o meno. Questo test non include il costo per il rendering dei dati, ma solo per copiarlo una volta eseguito il rendering.
  • Il rendering ritardato è un vantaggio netto delle prestazioni se consente di risparmiare più tempo rispetto all'overhead. Per determinare l'overhead del rendering ritardato, la misurazione è ottimale, ma da 10 a 100 microsecondi è una stima. Per calcolare il risparmio di utilizzo del rendering ritardato per ogni formato degli Appunti, misurare il costo per il rendering dei dati in tale formato e determinare la frequenza con cui il formato viene richiesto (in base ai messaggi della finestra descritti in precedenza). Moltiplicare il costo del rendering dei dati in base alla percentuale di tempo in cui i dati non vengono infine richiesti (prima che gli Appunti vengano svuotati o modificati i relativi contenuti) per determinare il risparmio di rendering ritardato per ogni formato degli Appunti. Il rendering ritardato è un vantaggio netto delle prestazioni se il risparmio supera il costo di overhead.
  • Come linea guida concreta, per le applicazioni che supportano solo un singolo formato degli Appunti, ad esempio il testo, in cui i dati non sono significativamente costosi da eseguire per il rendering, è consigliabile inserire i dati direttamente negli Appunti se le dimensioni dei dati sono pari o inferiori a 4 KiB.

Memoria e Appunti

Un oggetto memoria che deve essere posizionato negli Appunti deve essere allocato usando la funzione GlobalAlloc con il flag GMEM_MOVEABLE.

Dopo che un oggetto memoria viene posizionato negli Appunti, la proprietà dell'handle di memoria viene trasferita al sistema. Quando gli Appunti vengono svuotati e l'oggetto memoria ha uno dei formati degli Appunti seguenti, il sistema libera l'oggetto memoria chiamando la funzione specificata:

Funzione per liberare un oggetto Formato Appunti
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
Nessuno
CF_OWNERDISPLAY
Quando gli Appunti vengono svuotati di un oggetto CF_OWNERDISPLAY , l'applicazione stessa deve liberare l'oggetto memoria.