Autor Beitrag
Frankieboy
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 65



BeitragVerfasst: Mi 02.04.08 14:02 
Hallo,

im Moment verwende ich die Prozedur FPostKey, um den Druck einer Taste des Keyboards in einem Konsolenfenster zu simulieren:

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:
procedure TDosThread.FPostKey(key: Word; const shift: TShiftState; specialkey: Boolean);
  {************************************************************
   * Procedure FPostKey
   *
   * Parameters:
   *  hWindow: target window to be send the keystroke
   *  key    : virtual keycode of the key to send. For printable
   *           keys this is simply the ANSI code (Ord(character)).
   *  shift  : state of the modifier keys. This is a set, so you
   *           can set several of these keys (shift, control, alt,
   *           mouse buttons) in tandem. The TShiftState type is
   *           declared in the Classes Unit.
   *  specialkey: normally this should be False. Set it to True to
   *           specify a key on the numeric keypad, for example.
   *           If this parameter is true, bit 24 of the lparam for
   *           the posted WM_KEY* messages will be set.
   * Description:
   *  This procedure sets up Windows key state array to correctly
   *  reflect the requested pattern of modifier keys and then posts
   *  a WM_KEYDOWN/WM_KEYUP message pair to the target window. Then
   *  Application.ProcessMessages is called to process the messages
   *  before the keyboard state is restored.
   * Error Conditions:
   *  May fail due to lack of memory for the two key state buffers.
   *  Will raise an exception in this case.
   * NOTE:
   *  Setting the keyboard state will not work across applications
   *  running in different memory spaces on Win32 unless AttachThreadInput
   *  is used to connect to the target thread first.
   *Created: 02/21/96 16:39:00 by P. Below
   ************************************************************}

  type
    TBuffers = array [0..1of TKeyboardState;
  var
    pKeyBuffers: ^TBuffers;
    lParam: LongInt;
    hWindow: HWND;

  begin
    hWindow := TargetWindow; {TargetWindow enthält das Handle des Fensters, in dem der Tastendruck simuliert werden soll }
    (* check if the target window exists *)
    if IsWindow(hWindow) then
    begin

    (* set local variables to default values *)
    pKeyBuffers := nil;
    lParam := MakeLong(0, MapVirtualKey(key, 0));

    (* modify lparam if special key requested *)
    if specialkey then
      lParam := lParam or $1000000;

    (* allocate space for the key state buffers *)
    New(pKeyBuffers);
    try
      (* Fill buffer 1 with current state so we can later restore it.
         Null out buffer 0 to get a "no key pressed" state. *)

      GetKeyboardState(pKeyBuffers^[1]);
      FillChar(pKeyBuffers^[0], SizeOf(TKeyboardState), 0);

      (* set the requested modifier keys to "down" state in the buffer*)
      if ssShift in shift then
        pKeyBuffers^[0][VK_SHIFT] := $80;
      if ssAlt in shift then
      begin
        (* Alt needs special treatment since a bit in lparam needs also be set *)
        pKeyBuffers^[0][VK_MENU] := $80;
        lParam := lParam or $20000000;
      end;
      if ssCtrl in shift then
        pKeyBuffers^[0][VK_CONTROL] := $80;
      if ssLeft in shift then
        pKeyBuffers^[0][VK_LBUTTON] := $80;
      if ssRight in shift then
        pKeyBuffers^[0][VK_RBUTTON] := $80;
      if ssMiddle in shift then
        pKeyBuffers^[0][VK_MBUTTON] := $80;

      (* make out new key state array the active key state map *)
      SetKeyboardState(pKeyBuffers^[0]);
      (* post the key messages *)
      if ssAlt in Shift then
      begin
        PostMessage(hWindow, WM_SYSKEYDOWN, key, lParam);
        PostMessage(hWindow, WM_SYSKEYUP, key, lParam or $C0000000);
      end
      else
      begin
        PostMessage(hWindow, WM_KEYDOWN, key, lParam);
        PostMessage(hWindow, WM_KEYUP, key, lParam or $C0000000);
      end;
      (* process the messages *)
      Application.ProcessMessages;

      (* restore the old key state map *)
      SetKeyboardState(pKeyBuffers^[1]);
    finally
      (* free the memory for the key state buffers *)
      if pKeyBuffers <> nil then
        Dispose(pKeyBuffers);
    end;
  end
  else
    raise Exception.Create('Console Window could not be localized!');
end;


Um alle Tasten simulieren zu können, werden der Thread des Fensters und der Programmthreads vorher mit AttachThreadInput verbunden.
So kann man zum Beispiel die Eingabe eines 'A' mit FPostKey(Ord('A'),[ssShift],False) oder die Eingabe eines 'a' mit FPostKey(Ord('A'),[],False) simulieren. 'Enter' geht mit FPostKey(VK_RETURN,[],False) . So weit - so gut.

Allerdings will ich jetzt eine Prozedur FPostLine(ALine: String; Eol: Boolean) entwerfen, die automatisch das "schreiben" eines ganzen Strings simuliert (wenn Eol Wahr ist, wird am Ende das Drücken von Enter simuliert). Der String ALine sollte A-Z, a-z, 0-9 und zumindest die wichtigsten Sonderzeichen enthalten können. Für ein deutsches Tastaturlayout könnte man das ganze ja relativ einfach schreiben.
Für mich wäre allerdings wichtig, dass der String mit jeder (westlichen) Tastatur richtig simuliert wird:
So sollte der String 'LaLa$%(good=' korrekt an die Konsolenanwendung übergeben werden, als hätte man diesen Text auch wirklich so über die Tastatur getippt - egal ob das Windowstastaturlayout Deutsch, Englisch(US) oder z.B. Französisch ist!

Wie übergebe ich das jetzt an FPostKey? Oder gibt es eine andere Möglichkeit?


Wäre für jede Hilfe dankbar,

Frankie
BenBE
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: Mi 02.04.08 15:39 
Schau Dir mal SendKeys an (Ist ne Unit, die früher mal Delphi mit Beilag; stammt aus der VB-Welt).

Grundlegend brauchst Du Dir nur eine Lookup-Tabelle machen, die für jeden Char die zu drückenden Tasten und die Flags enthält.

_________________
Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
Frankieboy Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 65



BeitragVerfasst: Mi 02.04.08 17:06 
Hm, soweit war ich auch schon...

SendKeys brauch ich nicht, da meine PostKey Prozedur gut funktioniert.

Die "Lookup-Tabelle" ist das Problem!
Das Programm ist in Englisch und eigentlich für Distribution in alle Länder gedacht - ich kann doch nicht für jedes 1001 Keyboardlayout, dass es international gibt, eine Tabelle machen :roll: Das hat Microsoft schon erledigt -> Windows-Tastaturlayout oder MS-Deutsch auch "Standard-Eingabegebietschema". Ich bräuchte ne Möglichkeit, diese Daten abzurufen:
z.B Anfrage: Charackter '&' -> Ausgabe: bei verwendeter Tastatur Taste 6 plus Shift

Wie schon gesagt, es geht um "westliche Tastaturen", dh. Keyboards, die zur Sonderzeichen-Eingabe die Tasten Shift und Alt (bzw. Alt Gr) benutzen! Bilderschriften wie CHiensisch oä. bzw. rechts-nachlinks Systeme interessieren erstmal nicht...