Škodoradostné WIN API

Václav Antošík       14. 4. 2008       VB.NET, WinAPI       7817 zobrazení

Článok ukazuje základy použitia Windows Api vo Visual Basic .NET

Úvod

V tomto článku si ukážeme, ako používať vo Visual Basic .NET funkcie z knižníc Windows Application Interface(WIN API). Pre názornú ukážku som naprogramoval jednoduchú škodoradostnú aplikáciu, ktorá po spustení roztrasie všetky otvorené okná v systéme, pričom svoje okno nezobrazí ani na ploche ani na taskbare. Pri pokuse o zavretie okna aplikácie program zachytí event a nastaví e.cancel = true. Čiže stornuje zavretie okna.

image

Technické riešenie

Vytvoríme si prázdnu štandardnú aplikáciu vo Visual Studiu. Hneď pod deklaráciu triedy okna vpíšeme deklaráciu funkcií WIN API, ktoré budeme používať. Pri deklarovaní API funkcie sa používajú rezervované slová

Declare Function <menoFunkcie> Lib <menoDllKniznice> (<atr1>,<atr2>,<atr3>,<…>) as <typ>

Pre naše potreby si teda deklarujeme nasledujúce dve funkcie :

  Declare Function MoveWindow Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal x As Integer, ByVal y As Integer, ByVal Width As Integer, ByVal Height As Integer, ByVal Repaint As Integer) As Integer
Declare Function GetWindowRect Lib "user32.dll" (ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Integer

Ako vidno obe sa nachádzajú v knižnici user32.dll. Funkcia MoveWindow presunie okno na pozície zadané v argumentoch tejto funkcie. Čiže x – Xová pozícia ľavého horného rohu okna, y – Ynová pozícia ľavého horného rohu okna, width – Šírka okna v pixeloch rátaná od premennej x, height – Výška okna v pixeloch rátaná od premennej y. Pozorný čitateľ si určite všimol, že som nespomenul argument hwnd. Urobil som tak naschvál lebo mu bude venovaný nasledujúci odstavec.

 

Window handle

Operačný systém Windows dostal názov aký má pravdepodobne preto, že sa skladá celý z okien. Pričom oknom nie je iba okno aplikácie, ale pri troche nadhľadu môžeme oknom pomenovať každý kontrol, ktorý je v systéme(napr. aj každé tlačítko má svoje vlastné hwnd). Aby sme vedeli s jednotlivými oknami rozumne pracovať potrebujeme aby každý prvok mal svoj jedinečný identifikátor. Tým je window handle, číslo, ktoré jednoznačne identifikuje okno v systéme. Takže do prvého parametru funkcie MoveWindow zadáme postupne identifikátory všetkých spustených okien.

Druhá WIN API funkcia, ktorú sme si zadeklarovali je GetWindowRect, ktorá nám zistí aktuálnu pozíciu otvoreného okna. Ako prvý parameter ide už teraz známi hwnd. S druhým parametrom je to trošku komplikovanejšie. Vstupom do tohto argumentu je štruktúra RECT, ktorá vypadá nasledovne.

 

 Public Structure RECT
Public left As Integer
Public top As Integer
Public right As Integer
Public bottom As Integer
End Structure

 

Zaujímavé ďalej je, že štruktúra vstupuje do funkcie s ByRef, čo znamená, že čokoľvek WIN API funkcia zmení v našej štruktúre ostane zmenené aj po dobehnutí funkcie. Jednoducho povedané funkcia naplní do štruktúry polohu okna.

Left – pozícia ľavého rohu okna od ľavého rohu monitora v pixeloch

Right – pozícia pravého rohu okna od ľavého rohu monitora v pixeloch

Top – pozícia horného rohu okna od horného rohu monitora v pixeloch

Bottom – pozícia dolného rohu okna od horného rohu monitora v pixeloch

Ďalšou vecou, čo musíme ešte na začiatku programu zadefinovať je timer, ktorý nám bude zabezpečovať nekonečnú slučku. Zadefinujeme ho cez rezervované slovo WithEvents aby sme dokázali zachytiť udalosť tiknutia timera.

 Private WithEvents timer As System.Windows.Forms.Timer

Štartujeme

Vytvoríme si metódu, ktorá zachytáva udalosť nášho formulára Load. Ako prvé pri štarte aplikácie nastavíme formuláru aby sa nezobrazil v lište nastavením jeho vlastnosti ShowInTaskBar na false a následne ho skryjeme aby užívateľ nemohol kliknúť na krížik pomocou jeho metódy Hide. Následne vytvoríme timer a nastavíme mu opakovanie tikania každú 1 milisekundu a spustíme ho. Timer.Enabled = True.

 Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Me.ShowInTaskbar = False
Me.Hide()
timer =
New System.Windows.Forms.Timer
timer.Interval = 1
timer.Enabled =
True
End Sub

Jadro aplikácie

Jadrom našej škodoradostnej aplikácie je určite metóda timer_Tick, ktorá sa vykoná pri každom tiknutí časovača. Ako teda celé jadro funguje. Najprv si vytvoríme zoznam všetkých procesov, ktoré sú v systéme. Pomocou cyklu prechádzame celý zoznam pričom zaujímavé sú pre nás iba tie procesy, ktoré majú okno s vyplneným titulkom. Ak sa nájde také okno vygeneruje sa náhodné číslo od -5 po 5 a uloží sa do premennej ranNum. Pomocou funkcie GetWindowRect zistíme aktuálnu polohu okna a uložíme ju do štruktúry r. Nakoniec zavoláme funkciu MoveWindow a do parametrov jej zadáme položky zo štruktúry r a pričítame náhodne vygenerované číslo. V poslednom argumente funkcie je zadané číslo jedna. Tento argument totiž môže nadobúdať iba dva stavy. Nula a Jedna. Nula znamená, že pri presune okna sa jeho stará pozícia neprekreslí a vykreslí sa len nová. V praxi to potom vypadá tak, akoby okno za sebou nechávalo pás. Keď nastavíme argument na jednotku okno sa štandardne pri presune prekresľuje. Keď túto operáciu opakujeme rýchlo a často vytvára sa efekt akoby okno kmitalo okolo určitého miesta.

 

  Private Sub timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles timer.Tick
Dim processes() As Process = Process.GetProcesses 'Nacitame vsetky procesy v systeme
Dim r As RECT, random As New Random, ranNum As Integer
For i As Integer = 0 To processes.Length - 1 'Cyklus cez vsetky procesy
If Not processes(i).MainWindowTitle = String.Empty Then 'Ak ma okno procesu vyplneny titulok
ranNum = random.Next(-5, 5) 'Vygenerujeme nahodne cislo
GetWindowRect(processes(i).MainWindowHandle, r) 'Do r nahrame aktualnu poziciu okna
'Presunieme okno
MoveWindow(processes(i).MainWindowHandle, r.left + ranNum, r.top + ranNum, r.right - r.left + ranNum, r.bottom - r.top + ranNum, 1)
End If
Next
End Sub

Nedám sa zavrieť

Cieľom našej škodoradostnej aplikácie je ostať čo najdlhšie v behu. To znamená nedať sa zatvoriť. V metóde Form1_FormClosing potom nastavíme CancelArgument rovné True. To spôsobí, že sa aplikácia pri požiadavke systému o zavretie nezavrie.

 Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
e.Cancel =
True
End Sub

Záver

Naša aplikácia je hotová a pripravená na poslanie mailom neskúsenému kamarátovi alebo na predvedenie v školských učebniach :-). Dúfam, že som aspoň načrtol cestu ako sa dá pracovať vo Visual Basic .NET s Windows Application Interface.

Všetky konštruktívne otázky, poznámky a opravy k článku sú vítané.

Celý zdrojový kód si môžete stiahnuť tu

 

hodnocení článku

1 bodů / 1 hlasů       Hodnotit mohou jen registrované uživatelé.

 

Mohlo by vás také zajímat

Řešené příklady v ASP.NET - díl 3.: Aplikace pro zamlouvání sedadel (část 3)

V této části si ukážeme, jak vygenerovat a naplnit tabulku, a jak napsat komponentu, která má vlastní serverové události. Nakonec si ukážeme, jak aktualizovat jen část stránky pomocí komponenty UpdatePanel.

Windows Presentation Foundation (WPF) - díl 7.: Grid

Grid je jedna z nejdůležitější a nejpoužívanějších pozicovacích komponent ve WPF. Ulehčuje návrh formulářů a své uplatnění nachází v řadě scénářů.

Práce s časovými pásmy a letním časem v aplikaci a databázi - díl 1.: Úvod do časových pásem a letního času

Ve článku se snažím popsat úskalí, která přináší konverze času přes více časových pásem a pravidel pro počítání letního času.

 

 

Nový příspěvek

 

Diskuse: Škodoradostné WIN API

Toto je prvý článok v ktorom je API podané po lopate. Ja som spokojný. Poväčšinou nikdy nekopírujem použitý "učebný" materiál, radšej si vždy nájdem využitie na vlastnom nápade. Boli tu už aj užitočnejšie ukážky a tiež by im bolo možné čo to vytknúť. Myslím, že je dôležité podporiť všetkých, ktorí si nájdu čas a majú vôľu niečo "prezradiť". Niekedy aj v triviálnom programe sa nájdu veci užitočné alebo praktické.

Dík za ponúknuté informácie...

P.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Škodoradostné WIN API

Mě hlavně fascinuje ten totální nedostatek invence. Nedala by se namísto škodolibé aplikace napsat - s využitím stejných postupů - aplikace nějakým způsobem užitečná?

nahlásit spamnahlásit spam -3 / 3 odpovědětodpovědět

Áno skutočne by sa dala. Nech sa páči s chuťou do toho. Aplikácia v článku je na ilustračné účely. Na podobné pripomienky už nebudem reagovať.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Já si myslím, že článek hezky popisuje princip využívání API v .NETu. Díky.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Diskuse: Škodoradostné WIN API

Měl bych několik dotazů k vašemu zdrojovému kódu:

- Z jakého důvodu voláte funkci Randomize() v metodě Form1_Load? Volání této funkce je zcela zbytečné, má smysl pouze v případě, že používáte zastaralou funkci Rnd, inicializace generátoru náhodných čísel proběhne automaticky v konstruktoru třídy Random...

- Z jakého důvodu přepisujete funkčnost metody OnClosing, když můžete použít událost FormClosing?

- Z jakého důvodu deklarujete timer jako Public?

Mimochodem zkratka API znamená Application Programming Interface a netýká se pouze Windows.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Článok prejde úpravou. Ďakujem za pripomienky.

To, že sa API týka výhradne windows tuším v článku nie je spomenuté.

nahlásit spamnahlásit spam 3 / 3 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.

Nyní zakládáte pod článkem nové diskusní vlákno.
Pokud chcete reagovat na jiný příspěvek, klikněte na tlačítko "Odpovědět" u některého diskusního příspěvku.

Nyní odpovídáte na příspěvek pod článkem. Nebo chcete raději založit nové vlákno?

 

  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:  
Heslo:  

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback