Probabil că ştiţi că în Windows totul se bazează pe ferestre … era destul de evident, nu ?
Să vedem cum am putea afla câte ceva legat de ferestrele vizibile şi cum am putea să le ascundem, să le dezactivăm, etc, totul din Borland Delphi, folosind funcţii API.
Pentru început, să vedem cum aflăm ce fereastră avem sub cursorul de mouse.
Pentru asta ne trebuie să ştim poziţia cursorului, care se poate afla folosind funcţia GetCursorPos, din care putem afla handle-ul ferestrei de sub cursor, folosind funcţia WindowFromPointSă vedem nişte cod.
var hWindow : Longint; P : TPoint; ... GetCursorPos(P); hWindow := WindowFromPoint(P);
Destul de simplu, nu ? În variabila hWindow avem acum handle-ul care ne interesează.
Pentru a “vedea” în timp real ce fereastra e sub cursor, punem codul acesta într-un TTimer.
Să vedem cum afişăm informaţiile găsite, cum ar fi titlul ferestrei, clasa ferestrei (adică tipul componentei) şi handle-ul asociat părintelui ei, din TTimer. Pentru asta avem nevoie (în cazul acesta) de patru TEdit-uri.
procedure TForm1.Timer1Timer(Sender: TObject); var hWindow : Longint; P : TPoint; buff : Array[0..255] of char; begin GetCursorPos(P); hWindow := WindowFromPoint(P); Edit2.Text := '$' + IntToHex(hWindow, 8); GetWindowText(StrToInt(Edit2.Text), Buff, 255); Edit1.Text := Buff; GetClassName(StrToInt(Edit2.Text), Buff, 255); Edit3.Text := Buff; If GetParent(StrToInt(Edit2.Text)) > 0 then Edit4.Text := '$' + IntToHex(GetParent(StrToInt(Edit2.Text)), 8) else Edit4.Text := 'None'; end;
GetWindowText returnează titlul ferestrei (sau textul din fereastră, dacă e vorba de un TEdit), GetClassName returnează tipul componentei, iar GetParent handle-ul părintelui. Simplu, nu ? ![]()
Păcat că momentan tot ce aflăm sunt lucruri destul de puţin importante şi deloc atrăgătoare. Nişte numere şi ceva text care oricum se vedea şi fără un asemenea program. Să încercăm ceva mai atrăgător.
Pentru început vom ascunde / reafişa fereastra, apelând funcţia ShowWindow, care are nevoie de doi parametri: handle-ul ferestrei şi un parametru care specifică dacă vrem să afişăm sau să ascundem fereastra.
Afişare fereastră:
ShowWindow(wHandle, SW_SHOW);
Ascundere fereastră:
ShowWindow(wHandle, SW_HIDE);
Alt lucru care-l putem face : vom seta ca fereastra selectată să devină fereastră de top-level şi înapoi. Pentru acest lucru vom folosi funcţia SetWindowPos pentru a ne defini o procedură apelabilă cu un parametru de tip Boolean care să ştie modifica stilul ferestrei în ambele moduri, al doilea parametru fiind handle-ul ferestrei care vrem s-o modificăm.
procedure SetTop(Top : Boolean; Handle : HWnd); Begin If Top Then Begin SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW + SWP_NOMOVE + SWP_NOSIZE); SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW + SWP_NOMOVE + SWP_NOSIZE); End Else SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_SHOWWINDOW + SWP_NOMOVE + SWP_NOSIZE); End;
Acum nu mai avem decât să apelăm procedura asta din butonul corespunzător.
Ştiind handle-ul ferestrei, o putem şi activa / dezactiva folosind EnableWindow, care necesită specificarea handle-ului ferestrei şi un parametru logic care determină activarea / dezactivarea ei.
Codul pentru cele şase butoane de până acum:
procedure TForm1.bShowClick(Sender: TObject); begin hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1)); ShowWindow(hWindow, SW_SHOW); end; procedure TForm1.bHideClick(Sender: TObject); begin hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1)); ShowWindow(hWindow, SW_HIDE); end; procedure TForm1.bTopClick(Sender: TObject); begin hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1)); SetTop(True, hWindow); end; procedure TForm1.bPotClick(Sender: TObject); begin hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1)); SetTop(False, hWindow); end; procedure TForm1.bEnableClick(Sender: TObject); begin hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1)); EnableWindow(hWindow, True); end; procedure TForm1.bDisableClick(Sender: TObject); begin hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1)); EnableWindow(hWindow, False); end;
Probabil că aţi remarcat linia
hWindow := HexToInt(Copy(Edit2.Text, 2, Length(Edit2.Text) - 1));
, despre care nu am scos nici un cuvânt până acum. Este inversa funcţiei IntToHex din Delphi, şi este definită mai jos.
function HexToInt(S : String): Longint; var B : Byte; C : Char; Begin Result := 0; s := UpperCase(s); For B := 1 To Length(s) Do Begin Result := Result * 16; c := S[B]; Case c Of '0'..'9': Inc(Result, Ord(c) - Ord('0')); 'A'..'F': Inc(Result, Ord(c) - Ord('A') + 10); Else Begin Result := 0; Exit; End; End; End; End;
Puteam folosi variabila hWindow ca variabilă globală şi atunci scăpam de nevoia folosirii acestei funcţii, nu ? Dar ce se întâmpla dacă la utilizarea programului se voia reafişarea unei ferestre căreia îi ştim handle-ul ? În acest fel tot ce avem de făcut este editarea celei de-a doua căsuţe text cu handle-ul respectiv şi putem face orice, altfel putând lucra doar cu ferestrele vizibile pe ecran.
Cam acesta ar fi codul necesar pentru o mini-aplicaţie de lucru cu ferestrele … dar stai … e o problemă … dacă verificarea ferestrei de sub mouse se face în timp real, înseamnă că … da, dacă selectez butonul de “ascundere fereastră”, îmi va ascunde tocmai respectivul buton. Damn, nu e bine.
Trebuie să programăm o metodă de a opri scanarea ferestrelor în timp real, o dată ce am selectat fereastra cu care vrem să lucrăm, fără să mişcăm mouse-ul. Pentru asta ne vom defini o combinaţie de taste globală, folosind funcţia RegisterHotKey, care primeşte patru parametri: handle-ul ferestrei căreia să-i trimită mesaj în caz că s-a apăsat combinaţia noastră de taste, un identificator pentru combinaţie, definit de noi, şi combinaţia de taste, definită prin doi parametri – primul, care defineşte dacă tastele CTRL, ALT, SHIFT sau WIN sunt apăsate, şi al doilea, care defineşte o tastă normală (cum ar fi “R”
. Apelul funcţiei, pentru a ne defini combinaţia CTRL + F8, este :
const StopKey = 100000; ... RegisterHotKey(Handle, StopKey, MOD_CONTROL, VK_F8);
Această linie trebuie apelată chiar la începutul rulării programului, în FormCreate.
Atenţie : StopKey este o constantă ce trebuie definită global, înaintea secţiunii implementation.
Pentru a fi anunţaţi când este apăsată combinaţia noastră de taste ne vom defini o procedură care să primească mesajul trimis de sistem, interceptând mesajul WM_HOTKEY.
type TForm1 = class(TForm) ... private { Private declarations } procedure WMHotKey(var Message: TMessage); message WM_HOTKEY; ...
Codul procedurii :
procedure TForm1.WMHotKey(var Message: TMessage); begin If Message.WParam = StopKey Then Timer1.Enabled := not Timer1.Enabled; end;
Practic, la fiecare apăsare a combinaţiei, TTimer-ul nostru se va opri / reporni. Pentru a nu lăsa mizerie după rularea programului, va trebui să distrugem această combinaţie de taste la oprire. Pentru acest lucru, în FormCloseQuery vom apela :
UnregisterHotKey(Handle, StopKey);
Cam asta ar fi tot codul.
Pentru a nu vă pune să lucraţi cu copy / paste şi să vă faceţi griji de componente şi asignări de evenimente, aveţi mai jos sursele şi executabilul arhivate.
Download : Sursa :: Executabil
DarkByte is
Email this author | All posts by DarkByte | Subscribe to Entries (RSS)


August 31st, 2009 at 5:21 PM
sal, imi poti spune cum pot face sa aflu pozitia unui classname?
August 31st, 2009 at 6:02 PM
Da-mi detalii despre ce vrei sa faci.
ClassName-ul poate fi “ToolbarWindow32″ … dar poate fi in mai multe locuri pe ecran. Te referi la o anumita fereastra sau la ce ?
August 31st, 2009 at 7:55 PM
intr-adevar classname-ul meu e de 2 ori pe ecran, vreau sa inlocuiesc patratul cu avatarul de pe mess cu propria fereastra.
August 31st, 2009 at 11:15 PM
Nu sunt sigur ca inteleg ce vrei sa faci, pentru ca esti destul de criptic.
Daca vrei sa pui un control (fereastra, buton, etc) in Yahoo! Messenger (sau in alt program, for that matter) peste un control care deja exista, trebuie sa afli handle-ul ferestrei parinte, iar controlului tau ii vei da ca parinte acel handle. De acolo mai departe e doar o chestie de pozitionat controlul si de avut grija la eventuri.
Spor !
September 1st, 2009 at 12:02 PM
am trecut de acele faze, am reusit sa pozitionez un handle din aplicatia mea dar nu si inversul (sa aiba aplicatia mea coordonatele handle-ului).Daca o sa aflu voi posta…poate mai intereseaza pe cineva
.multumesc
September 1st, 2009 at 12:35 PM
Ehm … vrei pozitia ferestrei care o gasesti ? Daca da, foloseste GetWindowRect.
Daca nici asta nu e ce vrei tu, da-mi, te rog, mai multe detalii.
September 1st, 2009 at 4:51 PM
salut, mi-am gasit raspunsul aici: http://www.swissdelphicenter.ch/torry/showcode.php?id=347
bafta
September 3rd, 2009 at 8:49 AM
Adica, GetWindowRect, cum am si spus … daca vroiai pozitia taskbarului, puteai spune asa si-ti dadeam direct cod. Cum am spus mai sus, esti foarte criptic.