Delphi FAQ

Wykrywanie zmiany zawartości Schowka

brodny

Wydaje mi się, że tego jeszcze nie było, więc...

Często spotykane jest uaktualnianie odpowiednich przycisków, np. Wklej w procedurze obsługi Timer'a. Taki kod wygląda zazwyczaj następująco:

```delphi btnPaste.Enabled := Clipboard.HasFormat(CF_TEXT); // np. ```

Takie rozwiązanie jest jednak nieefektywne, zwłaszcza, że sam system może nas poinformować o zmianie zawartości Schowka. No dobra, ale jak osiagnąć taki efekt? Rozwiązaniem jest kolejka przeglądowa Schowka (Clipboard Viewer Chain). Po dołączeniu okna do tej kolejki przy każdej zmianie zawartości Schowka do rzeczonego okna wysyłany jest komunikat WM_DRAWCLIPBOARD. Przykładowy kod formularza dodanego do kolejki przegladowej Schowka:

```delphi type TMainFrm = class(TForm) // ... btnPaste: TButton; // przykładowy przycisk służacy do wklejania // metody zdarzeniowe procedure FormCreate(Sender: TObject); // zdarzenie OnCreate procedure FormDestroy(Sender: TObject); // zdarzenie OnDestroy private FOldClipViewHwnd: HWND; // uchwyt poprzedniego okna // w kolejce przeglądowej Schowka protected procedure WMDrawClipboard(var Msg: TWMDrawClipBoard); message WM_DRAWCLIPBOARD; procedure WMChangeCBChain(var Msg: TWMChangeCBChain); message WM_CHANGECBCHAIN; end; implementation uses ClipBrd; //... procedure TMainFrm.FormCreate(Sender: TObject); // ta metoda jest metodą obsługi zdarzenia OnCreate formularza begin // Dodanie formularza do kolejki przeglądowej Schowka. // Zapamiętywany jest uchwyt następnego okna w kolejce, // wykorzystywany przy wycofywaniu z niej okna // wykonywanego przy użyciu pomocy procedury Win32 API // ChangeClipboardChain() FOldClipViewHwnd := SetClipBoardViewer(Handle); end; procedure TMainFrm.FormDestroy(Sender: TObject); // ta metoda jest metodą obsługi zdarzenia OnDestroy formularza begin // usuń okno formularza z kolejki przeglądowej Schowka ChangeClipBoardChain(Handle, FOldClipViewHwnd); end; procedure TMainFrm.WMDrawClipboard(var Msg: TWMDrawClipBoard); // ta procedura obsługi komunikatu zastępuje nam cykającą // często procedurkę obsługi zdarzenia OnTimer komponentu Timer :) begin btnPaste.Enabled := Clipboard.HasFormat(CF_TEXT); // np. // odesłanie komunikatu do następnego okna w kolejce przeglądowej SendMessage(FOldClipViewHwnd, WM_DRAWCLIPBOARD, 0, 0); end; procedure TMainFrm.WMChangeCBChain(var Msg: TWMChangeCBChain); begin if Msg.Remove = FOldClipViewHwnd then // w przypadku, gdy okno znajdujące się na następnej pozycji w kolejce // zostaje usunięte, do zmiennej FOldClipViewHwnd przypisujemy uchwyt // następnego okna w kolejce przeglądowej FOldClipViewHwnd := Msg.Next else // w przeciwnym wypadku odsyłamy komunikat do następnego okna // w kolejce przeglądowej SendMessage(FOldClipViewHwnd, WM_CHANGECBCHAIN, Msg.Remove, Msg.Next); Msg.Result := 0; end; ```

Mam nadzieję, że ta krótka :) porada powstrzyma korzystających ze Schowka od sprawdzania zmiany jego zawartości za pomocą komponentu klasy TTimer. Zyskuje na tym zarówno efektywność programu, gdyż nie wykonuje on co chwila takiego samego kodu, który może zostać wykonany po poinformowaniu programu przez system operacyjny oraz projektant - nie musi umieszczać komponentu TTimer w formularzu :)

Na podstawie Delphi 4. Vademecum profesjonalisty. Tom I S. Teixeira & X. Pacheco Wydawnictwo Helion, i MSDN http://msdn.microsoft.com/en-[...]op/ms649025%28v=vs.85%29.aspx
PS. Formatowanie zerżnąłem z artykułu Sheitara pt. "Wskaźniki. Listy jedno i dwukierunkowe" (może mi wybaczy, ale naprawdę mi się podoba kod w tabelkach :) ) i będę je konsekwentnie stosował (a przynajmniej taką mam nadzieję :) ). URL: Wskaźniki. Listy jedno i dwukierunkowe.
FAQ

10 komentarzy

Zmieniłem wg. MSDN.

Działa, ale prościej jest zainstalować sobie JVCL i użyć komponentu JvClipboardMonitor(zakładka JV System)

też mi się podoba kod w rameczkach, tylko że u Ciebie tło jest jakby trochę za ciemne...

I czego się czepiasz?? :P

baniowe tabelki :D

Hehe, nie przesadzajmy :) To w końcu oparte na dobrym źródle :)

A to znaczy tyle że każdy zamieszczony przez Ciebie Art jest godny uwagi :D


Ale ze mnie lizus :)

Co znaczy "jak zwykle"? :D

Jak zwykle Miodzio :D