Programiranje

Prozori u Windowsu

Published on 12/22,2008

U Windows operativnom sistemu prozor predstavlja interfejs za komunikaciju korisnika i procesa kom taj prozor pripada. Jedan proces može imati više prozora. Svaki prozor ima svoj jedinstveni identifikator koji se naziva HANDLE. Srpski prevod HANDLE-a bi bio ručka. Na ETF izvesni LK koristi taj termin... meni se koža ježi od toga, tako da ću ovde koristiti originalni anglosaksonski naziv.

Ukoliko znamo handle nekog prozora, sa tim prozorom možemo softverski raditi bilo šta što hardverski može onaj ko je za računarom, iako taj prozor ne pripada procesu koji se trenutno izvršava ili je sakriven, minimiziran u taskbar ili tray. Windows SDK sadrži jednu funkciju koja obilazi sve prozore koji trenutno postoje, poziva funkciju koju joj mi zadamo i prosleđuje joj handle od svakog prozora koji nađe. Funkcija se zove EnumWindows:

BOOL EnumWindows(WNDENUMPROC Funkcija,  LPARAM Parametri)

Prvi argument je dakle adresa funkcije koju pišemo mi, a koju će EnumWindows() da pozove za svaki prozor. Drugi argument služi za prenos parametara, u ovom članku koji je za početnike, on nije bitan. 

Ovom funkcijom možemo da obiđemo sve prozore koji postoje, da pronađemo prozor sa željenim naslovom (na primer) i da ga pomeramo po ekranu (na primer). Prvo, napravimo novi C++ prazan Console projekat u Visual Studio (ili bilo gde drugde) koji će nam ispisati imena svih prozora koji trenutno postoje. Dodamo novi C modul, napišemo osnovni kostur jednog C programa, uključimo windows.h kako bi mogli da koristimo Windows SDK funkcije. I kad pozovemo EnumWindows, naš kod izgleda ovako:

#include <stdio.h>
#include <windows.h>

main()
{
  EnumWindows(Funkcija, NULL);
}


Sada je potrebno napisati Funkciju kojoj će EnumWindows pozivati svaki put kad pronađe novi prozor. Deklaracija te funkcije je standardna i završena izgleda ovako:

BOOL __stdcall Funkcija(HWND prozor, LPARAM param)
{
 char naziv[1024];  
 
 GetWindowTextA(prozor, naziv, sizeof(naziv));

 printf("%sn", naziv);
 
 return TRUE;
}


Prvo smo definisali promenljivu u koju ćemo smestiti naziv prozora pomoću funkcije GetWindowTextA(). Ovo A na kraju naziva funkcije znači da se tekstualni parametri funkcije posmatraju kao ANSI standardni tekst (u odnosu na GetWindowTextW() koji ih posmatra kao UNICODE). Moguće je koristiti i GetWindowText() što je u stvari makro koji u kod na mesto poziva ugrađuje A ili W verziju funkcije u zavisnosti od podešavanja kompajlera (da li da kompajlira karaktere kao UNICODE ili kao ANSI).

Poziv GetWindowTextA() sadrži handle prozora koji nam je pronašla funkcija EnumWindows(), zatim adresu bafera u koji treba da smesti karaktere koji predstavljaju naziv (naslov) prozora, i koliko tih karaktera najviše može da smesti u bafer. 

Sledeće što treba da uradimo jeste da ispišemo naziv na ekranu. Dobijeni prikaz može izgledati ovako:

Connections Tray
MediaCenter

ActiveMovie Window

NVSVCPMMWindowClass

GDI+ Window


MCI command handling window



GDI+ Window
SysFader
GDI+ Window




Program Manager
Press any key to continue . . .

 

Svaki prazan red predstavlja prozor bez imena. Na to trenutno nećemo obraćati posebnu pažnju, ali vrlo je jednostavno ispisati samo one koji imaju naziv:

if(naziv[0]) printf("%sn", naziv); 

Da bi našli neki poseban prozor, konkretno u ovom primeru Notepad, potrebno je da malo izmenimo Funkciju:

BOOL __stdcall Funkcija(HWND prozor, LPARAM param) 
{
 char naziv[1024];  
 
 GetWindowTextA(prozor, naziv, sizeof(naziv)); 

 if(strstr(naziv, "Notepad")) 
 { 
  MoveWindow(prozor, 0,0,100,100,TRUE);
 }
 
 return TRUE;
}

Ovde koristimo standardnu bibliotečku funkciju strstr() koja proverava da li je zadati drugi parametar, podstring prvog parametra. I ako jeste, sa MoveWindow() pomeramo taj prozor na koordinate (0,0) i postavljamo mu veličinu na (100x100).

Otvorite nekoliko notepad-a i pokrenite ovaj program. Svi notepadi će se skloniti u gornji ćošak ekrana i smanjiće se na 100x100 piksela.

Naravno, sledeći notepad koji otvorite neće mrdnuti, jer je naš program prestao sa radom. Ukoliko bi želeli nekoga da iznerviramo i da mu svaki notepad koji otvori sklonimo u ćošak, moramo da obezbedimo da naš proces stalno poziva EnumWindows():

main()
{
 while(1)
 {
  EnumWindows(Funkcija, NULL);
  Sleep(100);
 }
}

Ova beskonačna petlja će na svakih 100 milisekundi pozivati EnumWindows(). Funkcija Sleep uspavljuje pozivajući proces na određeno vreme, kako bi drugi procesi mogli da koriste procesor. Da nema ovoga, Windows bi se zablokirao ili usporio na jednoprocesorskim računarima.

Ako sad pokrenete program, pa onda neki notepad, on će automatski da se pomeri u desni gornji ćošak i da se smanji na 100x100 piksela. Ukoliko pokušate da mu razvučete neku ivicu i time ga proširite nećete uspeti, jer će naš program na svakih 100ms sve prozore koji u svom imenu sadrže Notepad, da pošalje u desni ugao ekrana.

Naravno, primećujete da je prozor konzole stalno otvoren. Ako bi nekoga želeli da nervirate ovim, konzola bi predstavljala veliko dugme STOP, koje ne želite da imate. Potrebno je ga sakrijemo. Prvo funkcijom GetConsoleTitleA() nađemo naziv prozora konzole, zatim da nađemo handle prozora sa tim nazivom sa FindWindowA() i da sa ShowWindow() prikažemo prozor konzole sa uključenim flegom SW_HIDE. Onda će naša main funkcija izgledati ovako:

main()
{
  HWND konzola;  
  char naziv[1024];
 
  GetConsoleTitleA(naziv, 1024);
  konzola=FindWindowA(NULL, naziv);
  ShowWindow(konzola,SW_HIDE);
 
 while(1)
 {
  EnumWindows((WNDENUMPROC)Funkcija, NULL);
  Sleep(100);
 }
}

Konzola predstavlja handle prozora koji vraća funkcija FindWindowA(). HWND je tip za handle. Ponovo, svaka funkcija u Windows SDK koja koristi stringovne (tekstualne) parametre ima dve verzije, jednu sa W na kraju i jednu sa A i makro sa čistim imenom funkcije. Ovde i svugde koristimo A jer su nam nazivi prozora u ANSI formatu.

Ako sad pokrenete program (poželjno je u Debug modu), konzola če se sakriti i program će beskonačno da pomera sve prozore koji u nazivu imaju Notepad. Da bi ga ugasili, stopirajte Debug. Ili ako ste ga samo pokrenuli, otvorite task manager i ugasite proces programa.

Ako ste malo kreativni, možete napraviti svoje animacije prozora, posebne izglede, možete hronološki čuvati sadržaj otvorenih prozora (kao neki špijunski program), itd... i to sve počevši od ovoga.

Primeri za neke kreativnije poduhvate, biće okačeni na ovom blogu, so stay tuned! xD

 

Ceo kod programa: 

#include <stdio.h>
#include <windows.h>

BOOL __stdcall Funkcija(HWND prozor, LPARAM param) 
{
 char naziv[1024];  
 
 GetWindowTextA(prozor, naziv, sizeof(naziv)); 

 if(strstr(naziv, "Notepad")) 
 { 
  MoveWindow(prozor, 0,0,100,100,TRUE);
 }
 
 return TRUE;
}

main()
{
  HWND konzola;  
  char naziv[1024];
 
  GetConsoleTitleA(naziv, 1024);
  konzola=FindWindowA(NULL, naziv);
  ShowWindow(konzola,SW_HIDE); 
 
 while(1)
 {
  EnumWindows((WNDENUMPROC)Funkcija, NULL);
  Sleep(100);
 }
}

 

 

 

 


Leave a Reply

Dodaj komentar





Zapamti me

Comments