Gestione della ClipBoard di windows

Versione Completa   Stampa   Cerca   Utenti   Iscriviti     Condividi : FacebookTwitter
essenceflare
00venerdì 26 marzo 2004 11:22
In Windows così come in altri ambienti di esecuzione, possiamo considerare la clipboard come una sorta di file il cui contenuto è a disposizione, sia in lettura che in scrittura, di tutti i programmi in esecuzione nel sistema.
La clipboard è quindi uno strumento di comunicazione che funge da contenitore di oggetti, che possono essere letti/scritti anche da programmi fra loro differenti. In Windows, ad esempio, è possibile da WinWord copiare del testo "in" clipboard da poter poi importare "da" clipboard in Excel o in un qualunque altro programma di editing.
L’unico limite sul "formato" dei dati da copiare nella clipboard è nella fantasia del programmatore. Windows, da parte sua, definisce un certo numero di formati standard il cui elenco è riportato nel Listato 1. Essi possono essere di natura testuale, grafica, musicale... insomma la clipboard è anche una risorsa multimediale.
I nomi di questi formati, hanno tutti la forma CF_XXX dove "CF" sta appunto per "Clipboard Format".
Questo articolo descriverà l’API per la gestione della clipboard fornendo nell’esempio allegato l’applicazione pratica delle funzioni descritte.

Lettura e scrittura della clipboard

Per utilizzare la clipboard è necessario innanzitutto richiamare la funzione OpenClipBoard. Sarà quindi possibile prelevarne i dati (ottenendo quindi un handle ad essi) tramite la funzione GetClipboardData. La chiusura della clipboard è altrettanto semplice, e si ottiene richiamando la funzione CloseClipboard.Come ho già detto, nella clipboard possono esserci più dati fra loro differenti, come un bitmap o del semplice testo. È per questo che come unico parametro della GetClipboardData è necessario specificare quale formato si ha intenzione di leggere. Per leggere testo occorre utilizzare il nome CF_TEXT, mentre un formato bitmap è referenziato dal nome CF_BITMAP. Supponendo di voler importare dalla clipboard del testo da stampare poi a video con una funzione del tipo StampaTesto, il semplice codice C necessario è il seguente

HANDLE hMem;
char *lpText;
OpenClipboard(hWnd);
hMem = GetClipboardData(CF_TEXT)
lpText = (char *) GlobalLock(hMem);
StampaTesto(lpText);
GlobalUnlock(hMem);
CloseClipboard();

hWnd rappresenta il puntatore alla finestra che sta utilizzando la clipboard.

Il parametro della OpenClipboard può anche essere impostato a NULL: in questo caso l’utilizzatore "momentaneo" della clipboard è riferito al task del programma in esecuzione.
Infatti l’accesso alla clipboard non è simultaneo, al fine di tutelare la lettura/scrittura dei dati: se qualche altro programma ne cancellasse il contenuto mentre un altro effettuasse in concomitanza una lettura... i risultati sarebbero certamente ambigui o addirittura disastrosi.
La scrittura di dati nella clipboard è un’operazione altrettanto semplice ed è più facile intuirla che descriverla.
In sostanza occorre utilizzare la funzione SetClipboardData passando come primo parametro il nome di un formato di memorizzazione del tipo CF_XXX e, come secondo ed ultimo parametro l’handler ad un puntatore di tipo GMEM_MOVEABLE e GMEM_DDESHARE ottenuto tramite la nota GlobalAlloc; il codice che segue scrive in clipboard il testo "Hello World" utilizzando il formato CF_TEXT:

if( OpenClipboard(hWnd) )
{
char *lpText;
char *p;
HGLOBAL hMem;
p = "Hello World";
hMem = GlobalAlloc(GMEM_MOVEABLE|GMEM_DDESHARE, strlen(p)+1);
if( hMem != NULL) {
lpText = (char *) GlobalLock(hMem);
strcpy(lpText, p);
GlobalUnlock(hMem);
SetClipboardData(CF_TEXT, hMem);
}
CloseClipboard();
}

Si osservi l’if utilizzato per testare il valore di ritorno della OpenClipboard, che fallisce se qualche altra finestra, o più in generale un’altra applicazione, sta utilizzando la clipboard.Per "saperne di più" nel caso che la chiamata a OpenClipboard fallisca, è possibile utilizzare la funzione GetOpenClipboardWindow che ritorna al chiamante il puntatore alla finestra che utilizza la clipboard, o NULL se nessuna finestra è associata alla clipboard (caso di una DLL ad esempio). Ovviamente, sempre dopo l’apertura, è possibile svuotare completamente il contenuto della clipboard: la funzione preposta è EmptyClipboard.È necessario capire che l’operazione di scrittura in clipboard è distruttiva e che dunque l’ultima scrittura di un generico formato CF_XXX sovrascrive la precedente; questo è un buon motivo per effettuare una copia dei dati letti con la GetClipboardData. Si osservi inoltre come il fatto di racchiudere ogni lettura/scrittura fra la Open e la Close, renda l’accesso alla clipboard un’operazione atomica e dunque mutuamente semaforizzata; la clipboard è una risorsa shared visibile da tutti.

Il Delayed Rendering

Quando i dati da copiare nella clipboard hanno una dimensione eccessiva, è necessario ricorrere ad una tecnica conosciuta col nome di "Delayed Rendering".Tale tecnica consiste in pratica nel sollevare il sistema operativo dalla gestione della clipboard, in quanto sarà l’applicazione stessa a preoccuparsi di inserirvi un valido handler non appena una seconda applicazione ne farà richiesta (tramite il richiamo della GetClipboardData).In tal caso, il gestore della clipboard riceverà il messaggio WM_RENDERFORMAT il cui unico parametro (passato tramite wParam) rappresenta il nome numerico del formato da copiare nella clipboard.In pratica, dopo aver ricevuto tale messaggio il processo dovrà preoccuparsi di allocare i dati nel formato richiesto in un handler da mettere poi nella clipboard tramite la SetClipboardData.Attenzione: per questa operazione è necessario non richiamare la Open e la CloseClipboard.Il "proprietario" della clipboard è la finestra che per ultima ha invocato la funzione EmptyClipboard ed è per questo motivo che, in occasione del set-up dei dati per il Delayed Rendering, è necessario passare alla OpenClipboard un handler di finestra valido (ossia diverso da NULL).Il Delayed Rendering ha una struttura concettuale tipica di un servizio Client/Server, dove un client richiede un servizio che un Server è tenuto a soddisfare.Quando un’applicazione richiama la funzione EmptyClipboard, il sistema invia il messaggio WM_DESTROYCLIPBOARD alla finestra che precedentemente era la proprietaria della clipboard.

Formati di memorizzazione e loro enumerazione

Il contenuto della clipboard è per ovvie ragioni dinamico: essa può contenere contemporaneamente del testo (CF _TEXT), un metafile (CF_ENHMETAFILE) ed un bitmap (CF_BITMAP).Può quindi essere utile conoscere il formato dei dati contenuti dopo averla aperta (per scegliere ad esempio se preferire l’importazione di un’immagine bitmap piuttosto di un metafile).Tale operazione è chiamata "enumerazione", e permette di scorrere il contenuto della clipboard per i vari nomi CF_XXX dei dati memorizzati.Si analizzi il seguente codice:

iNumero = CountClipboardFormats();
if( iNumeroFormati ) {
if( OpenClipboard(NULL) ) {
uFormato = 0;
for( j = 0; j < iNumero; j++ ) {
uFormato = EnumClipboardFormats(uFormato);
stampaNome(uFormato);
}
CloseClipboard();
}
}

In questo esempio viene richiamata tante volte la EnumClipboardFormats per quanti sono i formati memorizzati nella clipboard (tale informazione è ottenuta dalla funzione CountClipboardFormats).Il meccanismo di enumerazione ha un innesco "concettualmente" ricorsivo che si concretizza passando come parametro alla EnumClipboardFormats il valore ritornato dalla precedente sua chiamata.A proposito del contenuto della clipboard, esistono due funzioni di utilità certamente utili.IsClipboardFormatAvailable torna al chiamante il valore boolenano TRUE se nella clipboard esiste il formato CF_XXX passatogli come parametro, mentre la GetPriorityClipboardFormat è più generica rispetto alla precedente perché come parametro attende un array di formati CF_XXX e torna al chiamante il valore zero se almeno uno dei formati passati in argomento è presente in clipboard o -1 in caso contrario.Tale funzione è utilizzata spesso come sorta di filtro: un programma di grafica potrebbe essere interessato ad importare solo dati di tipo grafico come i bitmap o i metafile, trascurando invece informazioni testuali di tipo CF_TEXT.Ma non è tutto: nella clipboard è possibile copiare dati "privati", ossia dati il cui formato non è riconosciuto ufficialmente da Windows sotto forma di none CF_XXX. Una tale opportunità è spesso utilizzata nei programmi di editing per permettere lo scambio di oggetti/dati fra due istanze differenti dello stesso prodotto.Ecco perché fra le funzioni per la gestione della clipboard esiste la GetClipboardFormatName che torna in una stringa passatagli in argomento il "nome" del formato privato memorizzato, appunto, in clipboard. Per dichiarare un "nuovo" formato di registrazione la funzione da utilizzare è la RegisterClipboardFormat che, ricevendo come unico parametro una stringa contenente il nome del "nuovo" formato, ritorna al chiamante un intero senza segno (in un range di valori compreso fra 0xC000 e 0xFFFF) da utilizzare allo stesso modo in cui si impiega un classico CF_XXX.
La funzione GetClipboardFormatName ritorna invece al chiamante il valore zero se il nome passatogli in argomento appartiene ai nomi CF_XXX.
È da tenere presente che Windows si preoccupa (quando occorre) di convertire autonomamente un formato di memorizzazione in un altro "simile" - come ad esempio per la copia di testo CF_TEXT che Windows rielabora inserendo in clipboard "anche" la stessa stringa in formato CF_OEMTEXT.
È la stessa cosa che accade nella memorizzazione dei metafile, che Windows trasforma in Enhanced Metafile se un’applicazione a 16 bit copia un vecchio formato di memorizzazione in clipboard e/o viceversa. Fortunatamente questo genere di conversioni è gestito direttamente da Windows.

Conclusioni e considerazioni

Un’accortezza da non sottovalutare qualora si pensi di sviluppare un nuovo "controllo" di editing, riguarda i messaggi WM_CUT, WM_COPY e WM_PASTE che un’applicazione può inviare al controllo stesso (ad esempio con una SendMessage) in un qualunque momento per selezionare dati da copiare in clipboard o per forzarne la lettura.È importante anche prevedere più formati di memorizzazione di una stessa selezione, per migliorare la qualità di esportazione: già il semplice programma PAINT.EXE, per l’export in clipboard di porzioni di disegno, prevede diverse alternative come il CF_BITMAP o il CF_ENHMETAFILE.La clipboard è dunque uno strumento di lavoro da non sottovalutare... tanto importante che il tipico menu "Modifica" di un editor vi dedica addirittura una intera sezione.

Zen
00venerdì 26 marzo 2004 14:06
Re:
Non ce l'ho fatta a leggere tutto. Mi sembra che riguardi lo sviluppo.
Hmmm, interessante. [SM=x39924]

Lo leggerò più tardi con più calma. [SM=x39851]
Questa è la versione 'lo-fi' del Forum Per visualizzare la versione completa clicca qui
Tutti gli orari sono GMT+01:00. Adesso sono le 04:42.
Copyright © 2000-2024 FFZ srl - www.freeforumzone.com