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

Hubert Kindermann       13.06.2008       C#, WinAPI       16770 zobrazení

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:

 

hodnocení článku

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

 

Mohlo by vás také zajímat

Windows Presentation Foundation (WPF) - díl 8.: Canvas, StackPanel, WrapPanel

Článek se věnuje dalším široce používaným pozicovacím komponentám WPF. Canvas pro absolutní pozicování, StackPanel pro skládání elementů vedle sebe nebo nad sebe a WrapPanel zalamující jejich tok do řádků nebo sloupců.

Práce s časovými pásmy a letním časem v aplikaci a databázi - díl 3.: DateTimeOffset v .NET Frameworku

DateTimeOffset je méně využívanou alternativou struktury DateTime v .NET Frameworku. Navíc dovoluje ukládat časové pásmo a pohodlně s ním pracovat.

Visual Studio 2017, .NET Core a nový formát projektů

 

 

Nový příspěvek

 

vb.net

taky bych tento článek uvítal kdy byl napsaný ve VB.NET.

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

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

Zde uvedený kód pro odchytávání kláves není vždy stabilní a můžu shazovat aplikaci. Správný kód je uveden zde: http://blogs.msdn.com/b/toub/archive/200...

Hlavní problém zde uvedeného kódu je špatná práce s delegátem, která pak způsobuje NullExpection v callbacku a ten pak shazuje celou aplikaci.

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

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

Pekne cecko ,co tak to prepsat pro vbnet, o kterem je tento server?

Bob

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

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#).

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

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.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

... neviem, co si dokazujes ? Jedna vec je, ze podobnych clankov je na nete na tony, ale naco je tuto techniku dobre spristupnovat sirokym masam ?!

... alebo si este momentalne taky naivny, ze predpokladas, len vyuzitie pre dobre ucely ?!

... nerozumiem tvojim pohnutkam, ale nema to nic spolocne ani s taktikou, ani so strategiou, dokonca ani so zivotnou mudrostou !

Fajn, ak tomu nerozumies dnes, o par rokov pochopis !

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

... neviem, co si dokazujes ? Jedna vec je, ze podobnych clankov je na nete na tony, ale naco je tuto techniku dobre spristupnovat sirokym masam ?!

Proč by tato problematika měla být širokým masám skryta? Nehledě na to, že těch pár tisíc zobrazení tohoto článku, to jsou opravdu široké masy.

... alebo si este momentalne taky naivny, ze predpokladas, len vyuzitie pre dobre ucely ?!

Já bych řekl, že Hubert jakožto autor psal o tom, co ho zajímalo, a jak to kdo použije už není jeho starost.

... nerozumiem tvojim pohnutkam, ale nema to nic spolocne ani s taktikou, ani so strategiou, dokonca ani so zivotnou mudrostou !

Fajn, ak tomu nerozumies dnes, o par rokov pochopis ! Tyhlety slinty si běžte psát jinam, tady na ně nikdo není zvědaný.

Věcné připomínky ke článkům či dotazy k tématu vítáme, ale rozhodně tady nepotřebujeme číst nesmyslné výčitky o tom, že píšeme články o tématech, jež by podle vás měla být široké veřejnosti z nějakého důvodu utajena.

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

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.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

1) www stranka ma adresu 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

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

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.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

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.

nahlásit spamnahlásit spam 2 / 4 odpovědětodpovědět

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.

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

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á.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

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

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

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.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

Promiň Bobe, tohle už není diskuze k článku... To už je demence :D

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

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.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

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

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? :-)

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

Č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.

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

A jak by se dala blokovat určitá kombinace kláves? Například typicky alt+ctrl+del nebo alt+F4.

Děkuji za odpověď

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

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

Dobrý den , chtěl bych poradit s věcí okolo Odchytávání zpráv. Chtěl bych si přidat více zkratek, ale vždy mě zastaví chyba v části kódu : 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.

Dokázal by mi někdo poradit jak přidat další zkratky a obejít přitom tuhle chybu? Díky za odpověď

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

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

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

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

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

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... )

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

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

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.

nahlásit spamnahlásit spam 0 / 2 odpovědětodpovědět

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

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.

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

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

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.

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

Bohužel, nevím. Musíte to vyzkoušet.

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

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

Tady existuje lepší kód, nevím tedy jestli funguje pod 32bit i 64bit platformami, ale nevidím důvod proč by neměl:

www.codeproject.com/KB/cs/globalhook.asp...

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

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.

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

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ě

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

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

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

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ů.

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

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á

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

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

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

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é).

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

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

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?

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

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.

nahlásit spamnahlásit spam 0 / 2 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