Autor Beitrag
N8Falter74
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 53

Win XP
D7 Prof
BeitragVerfasst: Mo 06.03.06 12:57 
Hallo Forum,

bevor jetzt wieder einige auf die Suche verweisen, die habe ich jetzt mehr als 30 min benutzt und noch nicht den richtigen tipp gefunden.

Also folgendes Problem:

Ich möchte mit einem kleinen Tool auf ein bestimmtes HotKey reagieren (STRG+S) und dann eine Datenbanksuche ausführen.
Das klappt auch soweit schon. Der Suchbegriff soll das aktuell markierte Wort/Satz usw. in der aktiven Anwendung sein.
Beispiel: In einer eMail markiere ich eine Telefonnummer und mit STRG+S sucht meine Anwendung zB. den Namen des Inhabers raus.

Zuerst habe ich das so versucht:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure FindActiveControl;
var hWindow: HWND;
    Pid1, Pid2: Cardinal;
begin
  Pid1 := GetWindowThreadProcessId(Application.Handle);
  Pid2 := GetWindowThreadProcessId(GetForeGroundWindow);
  if AttachThreadInput(Pid1, Pid2, True) then
  begin
    hWindow := GetFocus;
    SendMessage(hWindow, WM_COPY, 00);
    memo1.PasteFromClipboard;
  end;
  AttachThreadInput(Pid1, Pid2, False);
end;


Doch leider reagieren nur Edits und Comboboxen auf die Windows Message WM_COPY. Ich könnte jetzt natürlich alle Controls extra behandeln, aber das ist ja nie vollständig. Deshalb möchte lieber ein STRG+C an das Control senden, das ist zwar nicht so richtig professionell aber jedes Control das STRG+C unterstützt, sollte dann funktionieren.

Ich habe dann das SendMessage(hWindow, WM_COPY, 0, 0); durch folgendes ersetzt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
    SendMessage(hWindow, WM_KEYDOWN, VK_CONTROL, 0);
    SendMessage(hWindow, WM_KEYDOWN, Ord('C'), 0);
    SendMessage(hWindow, WM_KEYUP, Ord('C'), 0);
    SendMessage(hWindow, WM_KEYUP, VK_CONTROL, 0);


Das funktioniert aber so nicht. Hat jemand eine Idee warum? Oder wie ich das eleganter lösen kann? :gruebel:

grüße
Sebastian
digi_c
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1905

W98, XP
D7 PE, Lazarus, WinAVR
BeitragVerfasst: Mo 06.03.06 15:03 
Die werden doch nacheinander gesendet und nicht STRG+C gleichzeit, oder?
N8Falter74 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 53

Win XP
D7 Prof
BeitragVerfasst: Mo 06.03.06 15:44 
user profile icondigi_c hat folgendes geschrieben:
Die werden doch nacheinander gesendet und nicht STRG+C gleichzeit, oder?


Sorry aber wie meinst du das :?:

Wenn ich einen Text irgendwo markiere und möchte den in die Zwischenablage kopieren, dann muß ich doch STRG drücken, dann dazu die Taste 'C' und dann beide loslassen. Oder?

Das wollte ich jedenfalls so simulieren.

Ich bin beim googlen darauf gestoßen, dass die KeyDown und KeyUp Messages nur als Reaktion auf einen Tastendruck in die Message Queue gestellt werden, das Fenster/Control selber reagiert aber nicht auf diese Messages. Ob das so richtig ist, habe ich leider auch nicht feststellen können. Das Platform SDK ist jedenfalls nicht gerade einfach zu lesen :-)

Es gibt auch noch eine WM_HOTKEY Message, aber diese bringt auch nicht die gewünschte Reaktion. Weder auf das Handle des Applications Fenster noch auf das Fensterhandle des Controls. :-(

Man kann wohl auch per SendInput direkt in den Tastaturpuffer schreiben, aber das wollte ich nur als letzte Möglichkeit verwenden, da man dabei nicht mehr das empfangende Fenster festlegen kann.

Hat jemand noch eine idee?

grüße
Sebastian
N8Falter74 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 53

Win XP
D7 Prof
BeitragVerfasst: Mo 06.03.06 17:07 
Ich hab eine Lösung gefunden:

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:
procedure FindActiveControl;
var hWindow: HWND;
    Pid1, Pid2: Cardinal;
    lParam: LongInt;
    ksNew, ksOld: TKeyboardState;
begin
  // PIDs von Quell und Zielanwendung finden
  Pid1 := GetWindowThreadProcessId(Application.Handle);
  Pid2 := GetWindowThreadProcessId(GetForeGroundWindow);
  
  // beide Thread-Message-Queues zusammenschalten
  if AttachThreadInput(Pid1, Pid2, True) then
  begin
    // aktives Fenster/Control finden
    hWindow := GetFocus;  
    // lParam mit Virtuellen Tastencode 'c' vorbereiten
    lParam := MakeLong(0, MapVirtualKey($430));
    // Neuen Keyboardstate STRG-gedrückt vorbereiten
    ksNew[VK_CONTROL] := $80;
    // alten Keyboardstate sichern
    GetKeyboardState(ksOld);
    // neuen Keyboardstate setzen
    SetKeyboardState(ksNew);
    // Taste 'C' wurde gedrückt - senden
    PostMessage(hWindow, WM_KEYDOWN, $43, lParam);
    // Taste 'C' wurde losgelassen - senden ($C0000000 setzt auch diesen Status für lParam)
    PostMessage(hWindow, WM_KEYUP, $43, lParam or $C0000000);
    // Anwendung soll Message-Queue verarbeiten
    Application.ProcessMessages;
    // zur Sicherheit nochmal 100ms warten (kann ggf. entfernt werden)
    Sleep(100);
    // Zwischenablage in Memo-Kopieren
    memo1.PasteFromClipboard;
    // alten Keyboardstate wiederherstellen
    SetKeyboardState(ksOld);
  end;
  // Threads-Messages-Queues wieder trennen
  AttachThreadInput(Pid1, Pid2, False);
end;


Hab ich natürlich nicht komplett alleine gefunden ;-) Dank dem Board, dem Platform SDK und diesem Link www.delphi-forum.de/...ighlight=sendmessage war es dann doch ganz einfach :grin:

grüße
Sebastian