Programowanie w języku Delphi » FAQ

Wykrywanie zmiany zawartości Schowka

  • 2012-03-04 16:27
  • 10 komentarzy
  • 1746 odsłon
  • Oceń ten tekst jako pierwszy
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:

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:

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-u[...]top/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.


10 komentarzy

srobert1000 2012-03-04 16:24

Zmieniłem wg. MSDN.

damik95 2008-03-08 21:40

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

AklimX 2004-10-02 14:23

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

brodny 2004-09-06 16:00

I czego się czepiasz?? :P

Wolverine 2004-09-06 14:20

baniowe tabelki :D

brodny 2004-09-01 22:13

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

netvalker 2004-09-01 22:12

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


Ale ze mnie lizus :)

brodny 2004-09-01 20:38

Co znaczy "jak zwykle"? :D

netvalker 2004-09-01 18:15

Jak zwykle Miodzio :D