Články

Tisk článku Tisk článku

Globální odchytávaní zpráv z klávesnice + simulace stisků kláves

[Zpět na kategorii]

Datum: 13. 6. 2008 10:40       Autor: Hubert Kindermann       Zobrazeno: 10735x

Kategorie: Tipy a triky

Témata: C#

Zjistěte jak jednoduše odposlouchávat globální zprávy z klávesnice a také jak tyto zprávy programově simulovat. Nyní i blokování stisků kláves.


Potřebovali jste někdy pod platformou .NET globálně odchytávat zprávy z klávesnice? Pokud ano, nejspíše jste narazili, protože .NET Framework tyto globální hooky nepodporuje. Právě kvůli tomu se při implementaci naší aplikace nevyhneme použití Platform Invoke. Při využívaní Win API z řízeného prostředí se často můžeme dostat do problémů když hotovou aplikaci, která byla odladěna na 32 bitovém systému, spustíme na 64 bitovém systému a naopak. Naše ukázková aplikace bude napsána tak, že bude fungovat na obou platformách.

Pro ty, kteří neví, co si představit pod pojmem globální odchytávaní zpráv - znamená to, že naše aplikace může běžet na pozadí a i přes to může odchytávat stisky kláves. Tedy například, když budeme psát něco ve Wordu, tak naše aplikace může klidně zapisovat stisklé klávesy do souboru někam na disk.

Ješte než začneme, chtěl bych říct že Win API, které v příkladu využiji jsou velmi komplexní funkce s velmi širokou funkcionalitou - lze je použít k mnoha jiným účelům, protože záleží pouze na volbě hodnot parametrů, kterých je velké množství. Proto kdyby někdo potřeboval jejich podrobnější popis, tak odkazuji na MSDN, kde je Win API popsáno dostatečně detailně.

Odchytávaní zpráv

Tento proces funguje tak, že do určitého modulu přidáme jakýsi "detektor" (hook) zpráv z klávesnice, který právě při zachycení nějaké zprávy zavolá námi definovanou metodu, která nám zároveň předá informace o stisknutých klávesách. Tímto modulem bude knihovna kernel32.dll, která je potřeba při spouštění všech aplikací (to je pouze má úvaha, ale funguje). Nejdříve začneme implementací třídy, která bude deklarovat Win API funkce potřebné k odchytávání zpráv.

 static class api
{
[
DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string name);

[
DllImport("kernel32.dll")]
public static extern void FreeLibrary(IntPtr lib);

[
DllImport("user32.dll")]
public static extern IntPtr SetWindowsHookEx(int hook, LowLevelKeyboardProc callback, IntPtr hMod, uint dwThreadId);

[
DllImport("user32.dll")]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, uint wParam, KeyboardHookStruct lParam);

[
DllImport("user32.dll")]
public static extern bool UnhookWindowsHookEx(IntPtr hInstance);

public delegate IntPtr LowLevelKeyboardProc(int nCode, uint wParam, ref KeyboardHookStruct lParam);

[
StructLayout(LayoutKind.Sequential)]
public struct KeyboardHookStruct
{
public uint vkCode;
public uint scanCode;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}

public const uint WM_KEYFIRST = 0x100;
public const uint WM_SYSKEYDOWN = 0x104;
public const int WH_KEYBOARD_LL = 13;
}

A nyní naimplementujeme vysokoúrovňovější třídu, která bude interně využívat Win API, ale programátor používající tuto třídu již s Win API pracovat nebude. Na venek třída implementuje pouze událost KeyPressed. V callback funkci MyCallbackFunction je uvedena podmínka, která zajišťuje výpis zprávy pouze při stisku. Pokud by tam tato podmínka nebyla tak by se vypisovali i zprávy o zvedání kláves. Zajímavost je, že pokud tato funkce vrátí 1, tak je daná zpráva "zahozena". Pomocí tohoto postupu můžete určité klávesy úplně zablokovat. Náš příklad zablokuje možnost použití klávesy 'D'. Po spuštění této aplikace uvidíte, že Vám přestane úplně fungovat klávesa 'D'.

  public class KeyboardHook
{
private IntPtr hook;
private IntPtr lib;

public KeyboardHook()
{
lib =
api.LoadLibrary("kernel32.dll"); //nahrajeme modul kernel32.dll
hook = api.SetWindowsHookEx(api.WH_KEYBOARD_LL, MyCallbackFunction, lib, 0); //nastavíme hook
}
~KeyboardHook()
{
api.UnhookWindowsHookEx(hook); //odebereme hook
api.FreeLibrary(lib); //uvolníme z paměti nahraný modul
}

//tato metoda bude volána po každém stisku klávesy
private IntPtr MyCallbackFunction(int code, uint wParam, ref api.KeyboardHookStruct lParam)
{
if (wParam == api.WM_KEYFIRST || wParam == api.WM_SYSKEYDOWN) //pouze při stisku
{
if (KeyPressed != null) KeyPressed((int)lParam.vkCode);
}
if (lParam.vkCode == 68) return new IntPtr(1); //pokud stiskneme 'D', tak zpráva bude zahozena
return api.CallNextHookEx(hook, code, wParam, lParam); //zajistí že pokud někde byly nastaveny ještě další hooky, tak se k nim zpráva dostane
}
}

Simulace stisku klávesy

Simulování stisku kláves je na jednu stranu jednoduší, ale bohužel je tu problém s již zmiňovanou kompatibilitou 32 a 64 bitových operačních systémů. Naštěstí lze programově velmi snadno zjistit pod kterou z uvedených platforem zrovna pracujeme, takže vše bude ošetřeno interně v naší třídě a programátor, který ji bude použivat se už o nic nebude muset starat. Naše simulace bude opět fungovat na globální úrovni. To znaméná, že se to bude chovat jako kdybychom skutečně mačkali tlačítka na klávesnici.

Opět začneme deklaracemi jednotlivých Win API funkcí a struktur, které budeme potřebovat. Můžete si povšimnout že rozdíl mezi strukturami pro 32 a 64 bitové OS je v jejich velikosti a atributu FieldOffset. 64 bitové struktury jsou o 4 byty větší protože obsahují jednu strukturu IntPtr, jejíž velikost zavisí právě na aktuální platformě.

 static class api
{
public const int INPUT_KEYBOARD = 1;
public const uint KEYEVENTF_KEYUP = 0x0002;

[
DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, Input_32bitSyst[] pInputs, int cbSize);

[
DllImport("user32.dll", SetLastError = true)]
public static extern uint SendInput(uint nInputs, Input_64bitSyst[] pInputs, int cbSize);

[
StructLayout(LayoutKind.Explicit)]
public struct Input_32bitSyst
{
[
FieldOffset(0)]
public int type;
[
FieldOffset(4)]
public KeyboardInput_32bitSyst ki;
}

[
StructLayout(LayoutKind.Sequential, Size = 24)]
public struct KeyboardInput_32bitSyst
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}


[
StructLayout(LayoutKind.Explicit)]
public struct Input_64bitSyst
{
[
FieldOffset(0)]
public int type;
[
FieldOffset(8)]
public KeyboardInput_64bitSyst ki;
}

[
StructLayout(LayoutKind.Sequential, Size = 28)]
public struct KeyboardInput_64bitSyst
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
}
Nyní přestoupíme k zapouzdření Win API do vysokoúrovňovější třídy. Nejdříve ale k tomu jak poznáme pod jakou platformou pracujeme. K tomu využijeme struktury IntPtr reprezentující ukazatel na paměť. Víme, že 32 bitové OS adresují paměť pomocí 32 bitů, to znamená, že struktura IntPtr bude mít velikost 4 byty. A analogicky na 64 bitových OS bude mít struktura 8 bytů. Situaci nám činí ještě jednodušší skutečnost, že struktura IntPtr implementuje vlastnost Size, která nabývá pravě hodnot 4 nebo 8.
 public static class KeyboardSimulation
{
public static void Simulate(params ushort[] keys)
{
if (IntPtr.Size == 4)
{
//32 bitová verze
api.Input_32bitSyst[] input = new api.Input_32bitSyst[keys.Length]; //pole kódů kláves
for (int i = 0; i < keys.Length; i++)
{
input[i].type =
api.INPUT_KEYBOARD; //jde o stisknutí
input[i].ki.wVk = keys[i]; //o kterou klávesu se jedná
}
api.SendInput(3, input, Marshal.SizeOf(typeof(api.Input_32bitSyst))); //odešleme zprávu o stisknutí všech kláves v poli

for (int i = 0; i < keys.Length; i++)
{
input[i].ki.dwFlags =
api.KEYEVENTF_KEYUP; //jde o zvednutí klávesy
}
api.SendInput(3, input, Marshal.SizeOf(typeof(api.Input_32bitSyst))); //odešleme zprávu o zvednutí všech kláves v poli
}
else
{
//64 bitová verze
api.Input_64bitSyst[] input = new api.Input_64bitSyst[keys.Length]; //pole kódů kláves
for (int i = 0; i < keys.Length; i++)
{
input[i].type =
api.INPUT_KEYBOARD; //jde o stisknutí
input[i].ki.wVk = keys[i]; //o kterou klávesu se jedná
}
api.SendInput(3, input, Marshal.SizeOf(typeof(api.Input_64bitSyst))); //odešleme zprávu o stisknutí všech kláves v poli

for (int i = 0; i < keys.Length; i++)
{
input[i].ki.dwFlags =
api.KEYEVENTF_KEYUP; //jde o zvednutí klávesy
}
api.SendInput(3, input, Marshal.SizeOf(typeof(api.Input_64bitSyst))); //odešleme zprávu o zvednutí všech kláves v poli
}
}

Kód pro 32 i 64 bitovou platformu je stejný pouze s tím rozdílem, že používáme jinou strukturu pro uchování dat o stisknuté klávese. Metoda Simulate přebírá jako parametr pole kódů jednotlivých kláves.

Použití vytvořených tříd

Nejdříve si ukážeme program pro odchytávání stisků kláves a jejich výpis do konzole. (Musíme kompilovat jako konzolovou aplikaci, abychom viděli kozoli.)

 class Program
{
static void Main()
{
KeyboardHook hook = new KeyboardHook(); //vytvoříme instanci naší třídy
hook.KeyPressed += new KeyboardHook.HookHandler(hook_KeyPressed); //inicializujeme událost po stisknutí tlačítk
System.Windows.Forms.Application.Run(); //spustíme program
}

static void hook_KeyPressed(int key)
{
Console.WriteLine(key);
}
}
A nakonec program, který po spuštění vyvolá aplikaci Správce úloh pomocí simulace klávesové zkratky Ctrl+Shift+Esc. 162=Ctrl, 160=Shift, 27=Ecs
 class Program
{
static void Main()
{
KeyboardSimulation.Simulate(162, 160, 27);
}
}

Hodnoty kódů jednotlivých kláves můžeme zjistit pomocí předchozí aplikace.

Jak můžete vidět, použití tříd KeyboardHook a KeyboardSimulation je naprosto jednoduché a elegantní. Bohužel při testování jsem zjistil, že pokud jste uživately Windows Vista tak tyto aplikace musíte spouštět jako administrátor. Testoval jsem na Windows Vista 64bit, Windows Vista 32bit a Windows XP 32bit.

Ke stažení projekt pro VS 2008 Express:


> Na začátek

 

Hodnocení:

Hlasů: 17
Zvolte své hodnocení

Hubert Kindermann

Zajímají mě především technologie .NET, C# a XNA.

Související články

Žádné související články nebyly nalezeny.

RSS Feed RSS Feed

Diskuse

Pekne c !

Datum: 14.6.2008 10:54
Autor: Bob
Hodnocení autora: -32
Příspěvků: 5
Pekne cecko ,co tak to prepsat pro vbnet, o kterem je tento server?

Bob
 
           [Odpovědět]
 
Hodnocení: -7 Čekejte, prosím...

Re: Pekne c !

Datum: 14.6.2008 12:14
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Bohužel nemáte pravdu. Kód není psán v C ale v C#. Tento server je také hlavně o technologii .NET a C# byl Microsoftem představen jako hlavní jazyk pro vývoj aplikací pod .NET Frameworkem (samozřejmě i další jazyky, např. VB.NET a J#).
 
           [Odpovědět]
 
Hodnocení: 5 Čekejte, prosím...

Re: Pekne c !

Datum: 14.6.2008 17:47
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
C# je hlavním jazykem pro vývoj v .NETu jenom posledních pár let, ze začátku byl hlavní VB.NET, protože C# byl úplně nový a VB znají miliony programátorů po celém světě. Dnes se vyvíjí hlavně C# a VB.NET a z hlediska podpory jsou naprosto rovnocenné, J# šel tak nějak do pryč.
Nicméně toto je server o .NETu, takže článek o C# je naprosto v pořádku a důležitá je jeho nesporná informační hodnota.
 
           [Odpovědět]
 
Hodnocení: 1 Čekejte, prosím...

Re: Pekne c !

Datum: 14.6.2008 17:44
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
A co takhle použít nějaký konvertor, který většinu z toho umí převést a se zbytkem mu pomůžete? Anebo si tady u nás najděte článek o rozdílech mezi VB.NET a C# a budete schopen rozumět jazykům oběma.
 
           [Odpovědět]
 
Hodnocení: 2 Čekejte, prosím...

Re: Pekne c !

Datum: 14.6.2008 22:39
Autor: Bob
Hodnocení autora: -32
Příspěvků: 5
1) www stranka ma adresu http://www.vbnet.cz
Coz uz samo osobe napovida, ze bych ocekaval zdrojaky ve vb.netu

2) C# urcite neni 100% rovnocene vb.netu. Vb.net ma sve omezeni v nemanazovatelnem kodu predpokladam, ze i C# ma sve omezeni z prevodu z VB.netu.

Je pravda , ze muzu udelat soucastne 2 projekty treba C# a VB.net a prirozene pouzivat oba jazyky najednou v jednom programu, ale to je jina kapitola.

Prevodniky znam aspon zakladni:

http://www.developerfusion.co.uk/utiliti...

na: http://www.tangiblesoftwaresolutions.com
hledejte "Demo_Instant_VB" - uzasne.

3)Jinak klavesy se daji chytat pro aplikaci i prostredky vb.netu

zdroj nametu:http://dn.codegear.com/article/30129

nutne casti:
1) Implements IMessageFilter
2) Application.AddMessageFilter(Me)

3)

Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
         'tady zpracuj m (message)
End Function
 

Priklad:

Public Function PreFilterMessage(ByRef m As System.Windows.Forms.Message) As Boolean Implements System.Windows.Forms.IMessageFilter.PreFilterMessage
        Const WM_KEYDOWN As Integer = &H100
        If (m.Msg = WM_KEYDOWN) Then
            Stop
        End If
End Function
 


s pozdravem
Bob

 
           [Odpovědět]
 
Hodnocení: -7 Čekejte, prosím...

Re: Pekne c !

Datum: 14.6.2008 23:17
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
Zaprvé, to, že jsme na serveru vbnet.cz ještě neznamená, že zde nesmí padnout ani zmínka o jiném jazyce. Pokud se uzavřeme pouze na VB.NET, nebudeme mít tolik čtenářů, zdaleka ne všichni, kteří náš web pravidelně čtou, dělají ve VB.NET. To, že byste čekal zdrojáky ve VB.NET nemusí být nutně kompatibilní s tím, co zde najdete.
Ano, VB.NET neumí unsafe věci, o kterých ale na našem serveru nepíšeme, to už ale ani není příliš věc .NET frameworku. Co se týče managed rozhraní, jsou tyto jazyky opravdu rovnocenné.
Články na našem serveru nejsou koncipovány tak, aby každý přišel, okopíroval zdrojáky a použil je ve svém projektu (jinak si nedovedu vysvětlit takovou vehemenci požadování zdrojáků ve VB.NET). Z článku je patrný princip, jak se taková věc dělá, a to je cílem.
Z vlastní zkušenosti můžu říct, že psát článek a ukázky dělat v obou jazycích (jak C#, tak VB.NET), je dost náročné a náchylné na chyby.
A jinak klávesy se dají chytat mnoha způsoby, pro většinu případů stačí i API funkcí RegisterHotkey zaregistrovat určitou klávesovou zkratku a pak ji detekovat zachycením zprávy WM_HOTKEY, ale jak říkám, záleží, co člověk potřebuje, možností je více.
 
           [Odpovědět]
 
Hodnocení: 2 Čekejte, prosím...

Re: Pekne c !

Datum: 15.6.2008 1:37
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Prosím, dříve než sem napíšete kus kódu s tím, že to jde udělat mnohem jednodušeji, tak ho otestujte, nebo si alespoň přečtěte dokumentaci k dané funkci. Mluvím o Vámi zmiňované metodě Application.AddMessageFilter(...), která v žádném případě neposkytuje stejnou funkcionalitu jako můj postup. Název článku je totiž GLOBÁLNÍ odchytávaní zpráv. Metoda Application.AddMessageFilter(...) funguje pouze pro aktuální vlákno.
 
           [Odpovědět]
 
Hodnocení: 3 Čekejte, prosím...

Re: Pekne c !

Datum: 15.6.2008 9:10
Autor: Bob
Hodnocení autora: -32
Příspěvků: 5
Panove nebudu toto tema jiz vice rozvirovat, tak jen poznamky.
1)K C# a jinym jazykum urcire co do vypovedi myslenky nemam zadne namitky.
To jste si spatne vylozili.
Sam jsem se na C# hodne naucil a aplikoval to v VB.net.

Mam zkusenosti prevodu z C# na VB.net a neni to vzdycky tak ruzove jak si myslite, ze by prekladac vzdy udelal 100% praci.

To je taky duvod proc vyzkouseny kod ve vb.netu vitam.
(Na siti je ho zalostne malo, zejmena pokud hledate nejake specialitky)

2)K poznamce o autora (nebudu komentovat jeho lenivost mit zdrojaky na tomto serveru ve vb.netu pokud to jde ), ze moje kraticka ukazka filtrovanych zprav pro zachytavani treba klavesnice se tyka jen me spustene aplikace. V tomto priklade ma samozdrejme pravdu.

Je to dano pouzitym filtrem "Me" :
Application.AddMessageFilter(Me)  

Zkuste si chytnout bez Api funkci treba stisky klaves sve aplikace. Napriklad sipky kurzoru a budete mit problem.
A to nemluvim o tom, ze to potrebujete vetsinou chytit drive nez zacne reagovat cely Vas program.

Proto, ze jsem si hral s OpenGL (viz.nehe.ceske-hry.cz)
mam do vb.netu vlastno rucne plne prevedenych 22 lekci.

V kombinaci s taoframeworkem , staci nepatrna zmena a muzete to mit v CsGL - OpenGL .NET
zdroje:
nehe.ceske-hry.cz
http://sourceforge.net/projects/csgl/
http://www.taoframework.com/Downloads
(ladeno s Tao-1.3.0-1.zip)
http://nehe.gamedev.net/

Tam jsem resil podobny problem a jedna verze je i s pouzitim api funkci ,kde jsem zjistil ,ze je nekdy , a to hodne casto nutne odlisit ,ktere aplikaci ty stisky klaves vlastne patri.
Me se hodila podminka, pri ktere jsem filtroval, ze toto jsou stisky klaves, kdyz jsem fokusovan na svou aplikaci.
O tom se autor nezminuje , asi tuto potrebu nikdy nemel resit.


Myslim, ze jsem se v prikladu pustil docela peknou PERLU spojenou s jinym pristupem v jazyku
(A muzu rict, ze jsem ji hledal docela dloho, jak zachytit zpravy vlastnimi prostredy vbnetu.
a to nemluvim o tom, ze na formularich je

Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        'tady bych ocekaval ,ze chytnu vsechny  ve zpravy sve aplikace , ale ouha je to orezane 
End Sub 

pekne fronta zprav ocesana. )

, kterou bezne nenajdete a autor ji zametl bez myslenkovite pod stul s docela neprijemnym hodnocenim.

Neni to "GLOBÁLNÍ odchytávaní zpráv" autor se vubec nezamyslel ,ze je to jiny smer mysleni, ze ktereho se ma moznost neco naucit.
Zejmena pokud se podival na zdroj( viz.zdroj nametu , ktery je v C#), ze ktereho jsem vytahl to podstatne a nebyl jsem lenivy to dat v prikladu ve tvaru vb.netu

3)Na zaver doporuceni pokud je zdrojovy kod jiny nez vb.net
doporucoval bych , aby v hlavicce nazvu prispevku byla nekde poznamka napriklad C# pro lepsi prehled.
 
           [Odpovědět]
 
Hodnocení: -10 Čekejte, prosím...

Re: Pekne c !

Datum: 15.6.2008 9:46
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
Nikdo neříká, že převaděče kód převedou na 100%, ale většinu zvládnou a zbytek doděláte.
Pořád nechápu, co vám vadí na ukázkách kódu v C#, pokud vím, autor článku ani ve VB.NET nepíše (nebo se pletu?). Tyto jazyky jsou víceméně stejné, rozdíl je jen v syntaxi a v pár detailech. Poznámky o lenivosti autora si nechte pro sebe, co jste pro tento server udělal vy? Pokud máte něco kvalitního, sem s tím, pokud ne, tak laskavě nebuzerujte.

Zkuste si chytnout bez Api funkci treba stisky klaves sve aplikace.
No to byste člověče ten .NET framework musel znát, ale na tohle prostředky .NET frameworku stačí. Metoda KeyDown zachytí většinu kláves, některé nezachytává, protože nejsou definovány jako vstupní, což krásně změníte tak, že ve formuláři overridente proceduru IsInputKey a na dotyčné klávesy, které chcete chytat navíc (třeba pro Tab je to nutnost) to zaonačíte tak, aby metoda vrátila True. Pak chytnete i kurzorové šipky i tabulátor a další klávesy, které se v základním nastavení nevolají, protože dělají něco jiného. Stejně tak když v proceduře OnKeyněco nastavíte e.Handled na True, tak tím označíte klávesu za vyřízenou a aplikace už nic dalšího pro tuto klávesu dělat nebude. Ono stačí mít trochu přehled a nemusíte blbnout se zprávami. Pokud se tedy omezíte na svoji aplikaci.
Tento článek je o globálním odchytávání kláves, nehledejte v něm to, co do tohoto tématu nespadá.
 
           [Odpovědět]
 
Hodnocení: 1 Čekejte, prosím...

Re: Pekne c !

Datum: 15.6.2008 15:19
Autor: Bob
Hodnocení autora: -32
Příspěvků: 5
buzerovat=šikanovat, obtěžovat, nutit k nesmyslnému plnění povinností
viz.http://www.slovnik-cizich-slov.cz/buzero...

Je hezke jaky pouzivate slovnik v beznem foru.

Vlastne rikate ze Vas otravuje s nekym komunikovat, pak se nedivte ,ze pocet novych prispevku jde spise do nuly, az na par svetlych vyjimek.

Na to ,ze patrite k hlavnim akterum tohoto techto WWW stranek by jste se mel naucit ovladat,
a vybirat si z informaci jen to, co je pro Vas popripade pro Vase stranky prinosem.
Je vhodne ostatni informace ignorovat , protoze nemaji pro Vas zadny prinos a prirozene zaniknou pokud nebudou prinosem pro nikoho dalsiho.

Podle Vaseho navodu jsem si dovolil otestovat "IsInputKey" , abych se priznal tesil jsem se na to , se dozvim neco noveho funkcniho.
(Presto, ze jste to psal v hnevu)

Zalozil jsem projekt s formularem ,ktery obsahuje jen jeden Textbox1
( Friend WithEvents TextBox1 As System.Windows.Forms.TextBox)

a pridal
Protected Overrides Function IsInputKey(ByVal keyData As System.Windows.Forms.Keys) As Boolean
        Select Case keyData
            Case Keys.Left, Keys.Right, Keys.Down, Keys.Up, Keys.Tab
                TextBox1.Text = keyData.ToString
        End Select
    End Function 

po spusteni program fokusuje kurzor na textbox1 a ani jednou pro klavesy sipka nahoru,sipka dolu,sipka doleva,sipka doprava, tabelator
neprojde testem = zadna zmena obsahu TextBox1.
Coz znamena ,ze zpracovani techto klaves se do IsInputKey vubec nedostane.
Kde delam chybu kdyz Vam to funguje? (testovano ve vb.net 2003)

Autorovi tohoto clanku se omlouvam, ze jsem tet reagoval mimo tema clanku jen pro pana Hercega.

Mozna by bylo zajimave zalozit obecne tema ,kde se muze probrat ovladani zprav , klavesnice, mysi a podobne.

S pozdravem Bob
 
           [Odpovědět]
 
Hodnocení: -9 Čekejte, prosím...

Re: Pekne c !

Datum: 15.6.2008 16:59
Autor: Tomáš Herceg
Hodnocení autora: 1673
Příspěvků: 3536
Stojím si za tím, co jsem napsal, zbytečně jste autora buzeroval, tedy nutil k nesmyslnému plnění povinnosti (psaní ukázek ve VB.NET). Nikomu kromě vás to nevadilo a jako šéfredaktor oficiálně tvrdím, že je vše v pořádku, přestože se náš server jmenuje VbNet.CZ. Tečka. Dále se to nebude řešit.
Ovládat se umím, ale nesnáším, když kritizujete a nic jste zatím nepředvedl. Dusno tady děláte vy. Mimo jiné porušujete pravidla našeho fóra, protože píšete bez diakritiky; a navíc před čárkou se mezera nepíše, píše se jen za čárkou. Zameťte si laskavě před vlastním prahem, než se pustíte do kritiky, vypadá to mimořádně hloupě.

To IsInputKey samozřejmě funguje, ale váš test je špatný. Pokud má focus TextBoxu (a když na formuláři není jiná komponenta, tak TextBox focus dostane automaticky), chytají se klávesy v TextBoxu. Což znamená, že můžete stokrát overridnout IsInputKey ve formuláři, ale stejně je to špatně, protože musíte overridnout tu v tom TextBoxu.
Nejlépe tak, že si napíšete třídu, která dědí z třídy TextBox a v ní tu metodu overridnete. Pak to bude fungovat tak, jak má. Uznávám, že to není ideální řešení, na druhou stranu chytat tyto speciální klávesy není potřeba v běžných situacích a tak, kde to potřeba je (např. hry), tak tam se to stejně dělá jinak (například přes Direct Input). Když si v .NETu píšete vlastní komponentu, která má s klávesami pracovat, typicky se jí právě přetíží IsInputKey.
 
           [Odpovědět]
 
Hodnocení: 1 Čekejte, prosím...

Re: Pekne c !

Datum: 12.2.2011 22:07
Autor: neregistrovaný (212.158.155.12)
Hodnocení autora: není
Příspěvků: 0
Promiň Bobe, tohle už není diskuze k článku... To už je demence :D
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Pekne c !

Datum: 15.6.2008 12:11
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Abych se vyjádřil k Vašemu druhému bodu "2)K poznamce o autora", tak se opět mýlíte. Není to dáno filtrem "Me", ale je to odvislé od toho, na kterém vlákně tuto metodu zavoláte. Navíc jak psal Tomáš Herceg ve VB.NET jsem nikdy neprogramoval. Také když jste psal o tom, že C# zvládate, nevím proč se tady čílíte nad tím že ukázka je v C# - k pochopení funkcionality Vám to stačit musí. Tu si pak můžete sám naimplementovat ve VB.NET.
Metodu WndProc samozřejmě znám a už sem jí mnohokrát použil, ale stále nevím proč to sem taháte, když se stále jedná pouze o LOKÁLNÍ odchytávaní zpráv. A to opravdu není jiný směr myšlení, ze kterého se podle Vás něco můžu přiučit. A tento směr sem navíc nepatří. A právě proto, že Vámi zmíněné postupy nesplňují potřebu globálního odchytávaní, tak z toho důvodu tento článek vznikl.
 
           [Odpovědět]
 
Hodnocení: 3 Čekejte, prosím...

Nutnost admina

Datum: 14.6.2008 17:57
Autor: Jakub Čermák
Hodnocení autora: 50
Příspěvků: 164
Velmi zajímavý článek.
Mohl bych se zeptat, která funkce konkrétně vyžaduje na Vistě oprávnění admina? A pod Windows XP pod normálním uživatelem aplikace běží nebo také ne?
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Nutnost admina

Datum: 15.6.2008 2:09
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
V simulaci stisků kláves je problém s funkcí SendInput(...). Na MSDN se o tomto problému píše, že tato funkce na Win Vista selže pokud je zablokována pomocí User Interface Privilege Isolation (UIPI).

U odposlechu kláves jsem na to bohužel nepřišel, testoval jsem jednotlivá volání funkcí, ale všechna se bezchybně ukončila. Bez administrátorských práv dojde k jediné změně a to k tomu, že se nikdy nezavolá námi nadefinovaná callback funkce.

Pod Win XP jsem bohužel testoval pouze pod administrátorským účtem, ale nevidím žádný důvod pro to, aby aplikace nefungovala pod běžným účtem.
 
           [Odpovědět]
 
Hodnocení: 2 Čekejte, prosím...

Zachytávání klávesy Alt

Datum: 16.6.2008 10:19
Autor: neregistrovaný (212.158.144.250)
Hodnocení autora: není
Příspěvků: 0
Uvedený kód bohužel nezachytává stisk klávesy Alt (např. přepíná oken Alt+Tab, zavření okna Alt+F4, klávesových zkratkách pro tlačítka apod.). Lze to nějak jednoduše dodělat?

Neplánujete ještě článek na téma odchytávání a simulování myši? :-)
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: Zachytávání klávesy Alt

Datum: 16.6.2008 12:59
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Článek i kód jsem už opravil a nyní to funguje pro všechny klávesy (problém byl v podmínce která filtrovala zprávy). A navíc jsem přidal návod jak jednoduše zablokovat klávesy:-).
O článku o odchytávání a simulování myši jsem už přemýšlel a řekl bych, že něco napíšu, ale nic neslibuji.
 
           [Odpovědět]
 
Hodnocení: 6 Čekejte, prosím...

pepe

Datum: 28.8.2008 18:26
Autor: neregistrovaný (88.83.168.240)
Hodnocení autora: není
Příspěvků: 0
Tady existuje lepší kód, nevím tedy jestli funguje pod 32bit i 64bit platformami, ale nevidím důvod proč by neměl:
http://www.codeproject.com/KB/cs/globalh...
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 28.8.2008 19:30
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Můžu se zeptat v čem je lepší? Využívá naprosto stejného postupu jako můj kód. A navíc neposkytuje možnost simulace stisků kláves.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 28.8.2008 21:16
Autor: neregistrovaný (88.83.168.240)
Hodnocení autora: není
Příspěvků: 0
Lepší zapouzdření do událostí, takže pak můžeš používat uživatel používat krásně KeyEventArgs místo odečítání kódu znaku. Dále podpora e.handled, dále možnost zastavit snímání. A hlavně podpora i pro myš. Je toho hodně
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 28.8.2008 21:20
Autor: neregistrovaný (88.83.168.240)
Hodnocení autora: není
Příspěvků: 0
Mimochodem, simulace stisku kláves do global hook nepatří, a navíc už je výborně implementována v bezpečném a řízeném prostředí .NET frameworku: je to třída System.Windows.Forms.SendKeys
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 28.8.2008 22:56
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Mým cílem, ale nebylo napsat sofistikovanou knihovnu, kterou si každý pouze stáhne a začne ji ihned používat, bez toho aniž by rozuměl tomu jak to funguje. Chtěl jsem lidem ukázat a vysvětlit jak to funguje uvnitř. Vámi zmiňované lepší zapouzdření bych samozřejmně byl schopný naimplementovat, ale jak jsem říkal to nebylo mým cílem.

K tomu, že simulace stisku kláves do global hook nepatří - nikdy jsem neřekl, že ano, pouze mi to přišlo vhodné ukázat k doplnění tématu (když se mluví o odchytávaní, tak proč nezmínit také simulaci).

A nakonec k Vámi zmiňované třídě System.Windows.Forms.SendKeys, tak teď jsem jí vyzkoušel a máte pravdu, je to lepší řešení pro simulaci klávesových stisků.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 29.8.2008 10:32
Autor: neregistrovaný (88.83.168.240)
Hodnocení autora: není
Příspěvků: 0
Já vím že nebylo, to já netvrdím. Ale dal jsem to sem pro úplnost kdo by měl zájem. Zazněli tu totiž i požadavky na mouse hook. Samozřejmě, že ta tvoje je pro výukové účely dobrá
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 28.10.2008 20:21
Autor: Martin Bodocky
Hodnocení autora: 0
Příspěvků: 1
Chcel by som sa spytat ako by sme s takehoto programu urobili deamona(Sluzbu), ktora by bezala v pozadi. Rozmyslal som na dvoch variantach :
1.) Jej aktivitu by indikovala ikona v TaskBare
2.) Iba proces

Pod otazka , ako sa da prepisat meno procesu pri jeho spusteni.

Dakujem MB
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: pepe

Datum: 28.10.2008 21:09
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Ad 1) Pouze program upravíte, tak aby na začatku nevytvářel okno, ale pouze ikonu v taskbaru.
Ad 2) Nevím co tim myslíte. Nevím zda lze změnit jméno procesu za běhu, ale určitě můžete změnit jméno spustelného souboru, který spouštíte(jméno procesu pak bude stejné).
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

A co ACPI klávesy

Datum: 22.11.2008 11:54
Autor: neregistrovaný (93.91.144.55)
Hodnocení autora: není
Příspěvků: 0
Zdravím.
Potřebuju si napsat prográmek na ovládání hlasitosti na notebooku. V té souvislosti bych se chtěl zeptat, zda jde podobným způsobem zachytávat ACPI kódy, které jsou generovány v případě stisku tlačítek napájení, speciálních kláves pro spuštění IE, kalkulačky, apod a také ruzných funkčí, které se běžně volají pomocí FN + klávesa.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Re: A co ACPI klávesy

Datum: 22.11.2008 12:32
Autor: Hubert Kindermann
Hodnocení autora: 21
Příspěvků: 18
Bohužel, nevím. Musíte to vyzkoušet.
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...

Problém s pádem aplikace

Datum: 11.12.2008 13:56
Autor: neregistrovaný (147.230.154.223)
Hodnocení autora: není
Příspěvků: 0
Aplikace KeyboardHook po čase spadne. Stačí spustit a mít nějakou chvíli (někdy pár sekund, někdy 2 minuty) stisknutou na klávesnici třeba šipku dolů.

Debuger napíše:
"CallbackOnCollectedDelegate was detected"

http://img148.imageshack.us/my.php?image...

A v konzoli:

Neošetřená výjimka: System.AccessViolationException: Došlo k pokusu o čtení nebo zápis v chráněné paměti. Zpravidla se jedná o ind ikaci, že došlo k poškození další paměti.
v System.Windows.Forms.UnsafeNativeMethods.PeekMessage(MSG& msg, HandleRef hwnd, Int32 msgMin, Int32 msgMax, Int32 remove)
v System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageL
oop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
v System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
v System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
v System.Windows.Forms.Application.Run()
v KeyboardHook.Program.Main() v E:\Dokumenty_Hubert\Programing\C#\VBNET.cz\KeyboardHook\KeyboardHook\Program.cs:řádek 12

Netušíte někdo, co s tím? Zakládal jsem na tom aplikaci na změnu hlasitosti klávesovými zkratkami a zpětně jsem došel k tomuto problému.
 
           [Odpovědět]
 
Hodnocení: -2 Čekejte, prosím...

Konvertování

Datum: 21.10.2009 7:55
Autor: Aleš Stárek
Hodnocení autora: 1
Příspěvků: 24
Asi sem děsná lama, ale nedaří se mi konvertovat řádek
hook.KeyPressed += new KeyboardHook.HookHandler(hook_KeyPressed);
do VS.NET
Prosím alespoň o nápovědu.
 
           [Odpovědět]
 
Hodnocení: 1 Čekejte, prosím...

Globální posílání

Datum: 26.11.2009 12:44
Autor: Ondřej Ondryáš
Hodnocení autora: 100
Příspěvků: 237
Ta simulace jde udělat mnohem jednodušeji:
(omlouvám se za VB.NET)

Dim WshShell As Object = CreateObject("WScript.Shell")
WshShell.SendKeys("{NUMLOCK}")
 

a je to GLOBÁLNĚ!
( viz. http://www.vbnet.cz/forum-tema--3295-vyp... )
 
           [Odpovědět]
 
Hodnocení: 1 Čekejte, prosím...

Převod čísla na znak

Datum: 15.1.2010 17:00
Autor: neregistrovaný (62.245.116.37)
Hodnocení autora: není
Příspěvků: 0
Dobrý den, poradil by mi někdo jak převést číslo, které to vrací na znak a pokud možno tak s českou diakritikou?

Děkuji
 
           [Odpovědět]
 
Hodnocení: 0 Čekejte, prosím...
 

VBNET.CZ | © 2007 Tomáš Herceg, Tomáš Jecha | Kopírování a přejímání jakéhokoliv obsahu z tohoto webu je bez písemného svolení autorů zakázáno.