Autor Beitrag
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19314
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 28.10.05 11:58 
Hallo!

Es gab ja nun schon viele Fragen zu dem Thema, ich hab aber ein etwas anderes Problem. Ich kann zwar senden, und es scheint auch korrekt anzukommen, nur wird nach der Tastenkombination ein WM_CHAR ausgelöst. Das wird meines Wissens durch TranslateMessage ausgelöst.

Nur funktioniert halt dann die Tastenkombination (in diesem Fall Strg+R) nicht.

Problem: Ich möchte PostMessage benutzen, damit das Fenster auch minimiert oder hinter einem anderen sein kann, das geht mit SendInput oder keybd_event nicht...

Hier der Message-Log für das bestreffende Fenster:
1: so sollte es sein (Tastatureingabe)
2: So funktioniert es (aber das Fenster braucht den Fokus dafür, da ich SendInput benutze)
3: Das passiert bei PostMessage...
4: Das ist wohl das Problem!

Hier das Log:
user defined image

Und hier der Source:
www.buchmanager-berl...eyboardInterface.pas
bzw.
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
uses
  Windows, Messages, SysUtils, JwaWinAble;

type
  TKeyboardInterface = class
  private
    function GetKeyCode(uKeyDesc: String): Integer;
  public
    procedure DoSendKeyStrokes(uWindowCaption: String;
      uKeyStrokes: array of Integer); overload;
    procedure DoPostKeyStrokes(uWindowCaption: String;
      uKeyStrokes: array of Integer); overload;
    procedure SendKeyStrokes(uWindowCaption, uKeyStrokes: String;
      uPost: Boolean); overload;
  end;

implementation

function TKeyboardInterface.GetKeyCode(uKeyDesc: String): Integer;
begin
  uKeyDesc := UpperCase(uKeyDesc);
  if uKeyDesc[1] = '<' then
  begin
    if uKeyDesc[2] = 'f' then
    begin
      Delete(uKeyDesc, 12);
      if Length(uKeyDesc) = 2 then
        Delete(uKeyDesc, 21)
      else
        Delete(uKeyDesc, 31);
      Result := VK_F1 + StrToInt(uKeyDesc) - 1;
    end
    else if uKeyDesc = '<RETURN>' then
      Result := VK_RETURN
    else if uKeyDesc = '<ESCAPE>' then
      Result := VK_ESCAPE
    else if uKeyDesc = '<ESC>' then
      Result := VK_ESCAPE
    else if uKeyDesc = '<SHIFT>' then
      Result := VK_SHIFT
    else if uKeyDesc = '<STRG>' then
      Result := VK_CONTROL
    else if uKeyDesc = '<CONTROL>' then
      Result := VK_CONTROL
    else if uKeyDesc = '<STEUERUNG>' then
      Result := VK_CONTROL
    else if uKeyDesc = '<INS>' then
      Result := VK_INSERT
    else if uKeyDesc = '<INSERT>' then
      Result := VK_INSERT
    else if uKeyDesc = '<DEL>' then
      Result := VK_DELETE
    else if uKeyDesc = '<DELETE>' then
      Result := VK_DELETE
    else
      Result := -1;
  end
  else
    Result := Ord(uKeyDesc[1]);
end;

procedure TKeyboardInterface.DoSendKeyStrokes(uWindowCaption: String;
  uKeyStrokes: array of Integer);

  procedure SendKey(uVirtKey: Word; uFlags: Cardinal);
  var
    tmp: Windows.tagINPUT; //Windows, weil auch in JwaWinAble vorhanden...
  begin
    tmp.Itype := INPUT_KEYBOARD;
    tmp.ki.wVk := uVirtKey;
    tmp.ki.wScan := 0;
    tmp.ki.dwFlags := uFlags;
    tmp.ki.time := 0;
    tmp.ki.dwExtraInfo := 0;
    SendInput(1, @tmp, SizeOf(tmp));
  end;

var
  i: Integer;
  tmpHandle: Cardinal;
begin
  tmpHandle := FindWindow(nil, PChar(uWindowCaption));
  if tmpHandle = 0 then
    Exit;

  BlockInput(True);
    //Ist hier nötig, denn sonst könnte das Fenster nachdem es den Fokus hat
    //diesen durch eine Useraktion wieder verlieren
  SetForegroundWindow(tmpHandle);
  Sleep(100);
  for i := 0 to High(uKeyStrokes) do
    SendKey(uKeyStrokes[i], 0);
  for i := High(uKeyStrokes) downto 0 do
    SendKey(uKeyStrokes[i], KEYEVENTF_KEYUP);
  BlockInput(False);
end;

procedure TKeyboardInterface.DoPostKeyStrokes(uWindowCaption: String;
  uKeyStrokes: array of Integer);
//Funktioniert nur für einzelne Tasten nacheinander, nicht für
//Tastenkombinationen!
var
  i: Integer;
  tmpHandle: Cardinal;
begin
  tmpHandle := FindWindow(nil, PChar(uWindowCaption));
  for i := 0 to High(uKeyStrokes) do
    PostMessage(tmpHandle, WM_KEYDOWN, uKeyStrokes[i], 0);
  for i := High(uKeyStrokes) downto 0 do
    PostMessage(tmpHandle, WM_KEYUP, uKeyStrokes[i], 0);
end;

procedure TKeyboardInterface.SendKeyStrokes(uWindowCaption: String;
  uKeyStrokes: String; uPost: Boolean);
//Funktioniert nur für einzelne Tasten nacheinander, nicht für
//Tastenkombinationen!
var
  tmp: array of Integer;
begin
  SetLength(tmp, 0);
  while uKeyStrokes <> '' do
  begin
    if uKeyStrokes[1] <> '<' then
    begin
      SetLength(tmp, Length(tmp) + 1);
      tmp[High(tmp)] := GetKeyCode(uKeyStrokes[1]);
      Delete(uKeyStrokes, 11);
    end
    else
    begin
      SetLength(tmp, Length(tmp) + 1);
      tmp[High(tmp)] := GetKeyCode(Copy(uKeyStrokes, 1, Pos('>', uKeyStrokes)));
      Delete(uKeyStrokes, 1, Pos('>', uKeyStrokes));
    end;
  end;
  if uPost then
    Self.DoPostKeyStrokes(uWindowCaption, tmp)
  else
    Self.DoSendKeyStrokes(uWindowCaption, tmp);
end;


Für das Beispiel habe ich SendKeyStrokes('Testfenster', '<Strg>R', True) bzw. dasselbe mit False benutzt. Mit False (Bringt das Fenster in den Vordergrund und setzt die Zeichen in den aktuellen Eingabestream) geht es, mit True (benutzt PostMessage, damit das Fenster auch minimiert sein kann) geht es nicht.

Danke schonmal...