Entwickler-Ecke

Windows API - Postmessage Tastendruck simulieren


Flamefire - Sa 21.02.09 00:02
Titel: Postmessage Tastendruck simulieren
ich will in einem fremden programm einen tastendruck simulieren
u.a. ESC, TAB, F1-F9, 0-9

ich hab es so versucht:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
taste:=VK_ESCAPE;
...

lParam := MapVirtualKey(taste, 0);
    lParam := lParam shl 16+1;

    hwnd:=...;

    PostMessage(hwnd,WM_KEYDOWN,taste,lParam);
    PostMessage(hwnd,WM_KEYUP,taste,lParam and $C0000000);


leider funktioniert es so nicht immer, bzw bekomme ich seltsame ergebnisse:
bei ESC macht er zwar die aktion, die er machen sollte, reagiert aber dann nicht mehr auf (manuelles) F1-F9 bis zum manuellen drücken von ESC
TAB ignoriert er
F1-F9 und 0-9 gehen

kann es sein, dass das Fenster an dass die Nachricht gehen muss nicht das Hauptfenster ist, sondern ein (unsichtbares) Unterfenster?
Ich habe welche gefunden mit Namen: "M" und "Default IME"
was sind das für welche?

müssen wparam/lparam vl anders sein?


Flamefire - Sa 21.02.09 18:44

es klappt wenn ich die WM_KEYUP message bei spezialtasten weglasse...
sehr seltsam


Xentar - Sa 21.02.09 20:03
Titel: Re: Postmessage Tastendruck simulieren
[quote="user profile iconFlamefire"(550547)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
taste:=VK_ESCAPE;
...

lParam := MapVirtualKey(taste, 0);
    lParam := lParam shl 16+1;

    hwnd:=...;

    PostMessage(hwnd,WM_KEYDOWN,taste,lParam);
    PostMessage(hwnd,WM_KEYUP,taste,lParam and $C0000000);
[/quote]
Hab den Aufbau grad nicht so genau im Kopf.. aber wofür isn das da?


jaenicke - Sa 21.02.09 20:34

Die Variable taste hat einen Wert im Bytebereich (Virtual Keys eben). Es sind also nur diese Bits gesetzt maximal:

Quelltext
1:
00000000 00000000 00000000 11111111                    
MapVirtualKey ergibt auch einen solchen Wert im Bytebereich AFAIK, denn du übergibst ja 0, also MAPVK_VK_TO_VSC, und Scancodes sind auch im Bereich 0..255.
Durch das shl 17 sind das dann diese Bits:

Quelltext
1:
00000001 11111110 00000000 00000000                    
Jetzt kommt das lParam and $C0000000:

Quelltext
1:
2:
3:
00000001 11111110 00000000 00000000
and $C0000000 =
11000000 00000000 00000000 00000000
Das ist immer 0, weil die gesetzten Bits niemals überlappen können. Du übergibst dort also immer 0, warum also das and?

Laut Dokumentation [http://msdn.microsoft.com/en-us/library/ms646280.aspx] steht der Scancode bei den Botschaften in lParam ab Bit 16, du verschiebst eins zu viel (um 17).


Flamefire - Sa 21.02.09 21:50

ähm...ich habe "shl 16" nicht "shl 17"

und das mit dem AND stimmt
eine addition funktioniert
außerdem muss lParam vom typ Cardinal sein, nicht Word

das $c0000000 ist dafür da, damit die ersten 2 bits gesetzt sind (cRepeat und noch so was was gesetzt sein muss)

mich wundert aber, dass es durch weglassen von WM_KEYUP funktioniert


jaenicke - Sa 21.02.09 22:24

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
ähm...ich habe "shl 16" nicht "shl 17"
Ach ja, + und shl binden ja genauso stark. :oops:

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
und das mit dem AND stimmt
eine addition funktioniert
Oder der korrekte Weg mit or. ;-)

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
außerdem muss lParam vom typ Cardinal sein, nicht Word
Klar, sonst hast du ja nur 2 Byte, und da shiftest du ja genau über die Grenze hinaus.

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
mich wundert aber, dass es durch weglassen von WM_KEYUP funktioniert
Es kommt ja immer darauf an, wie die andere Anwendung auf welche Botschaft reagiert, also wo die Tastendrücke hin gelangen.


Xentar - So 22.02.09 00:42

Ich kapier zwar grad nicht genau worum es geht.. :D

user profile iconFlamefire hat folgendes geschrieben Zum zitierten Posting springen:
ähm...ich habe "shl 16" nicht "shl 17"

sicher?

Delphi-Quelltext
1:
lParam := lParam shl 16+1;                    

weiß grad nicht, in welcher Reihenfolge das ausgeführt wird.
Aber setz das vielleicht mal in Klammern?


jaenicke - So 22.02.09 01:17

Wie ich dann korrigiert habe: Von links nach rechts, denn beide Operatoren binden genauso stark. Das ist also richtig mit Shift um 16.