Entwickler-Ecke

Windows API - Aktives TWinControl anhand Handle finden...


erich.wanker - Di 27.05.08 19:52
Titel: Aktives TWinControl anhand Handle finden...
Hallo

wenn ich mich mit einem anderen Programm "verbinde", das im Vordergrund läuft:

Delphi-Quelltext
1:
2:
AttachThreadInput(meinProgramm, deinProgramm, true);
Fokus_HWnd := GetFocus;

dann hab ich ein Handle auf´s fremde Fenster.

wie find ich nun das Control, das gerade aktiv ist, damit ich via WM_GETTEXTLENGTH, dann WM_GETTEXT und
EM_GETSEL auf dessen markierten Text zugreifen kann?

P.S.: Im notepad klapp´s schon - aber bei z.B.: WinWord oder Acrobat find ich einfach das Control nicht... (die beiden Programme sind nur als Beispiel genannt..)

Vielen Dank

Erich

Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt und Punktits kuriert


erich.wanker - Mi 28.05.08 10:18
Titel: Handle finden...
Hallo Leute...

ich glaub ich muß meine Frage besser formulieren... ;-)

Wenn ich in einer x-beliebigen Anwendung einen Text markiere, soll der markierte Text ausgelesen werden. Klappt in verschiedenen Situationen einwandfrei - in manchen Situationen gar nicht.
Klappt bei: Notepad, Icontext Desktop, IExplorer Adressfeld ect...
Klappt nicht bei: Word, Excel, Dokumente im IExplorer..

Ich hol mir meine ThreadID, die ThreadID der aktiven Fremdanwendung, verbinde mich mit der Fremdanwendung, hol mir ein Handle auf die Fremdanwendung, und frag mal an, was das Teil so markiert hat ;-)
Wenn die Fremdanwendung MDIChild´s oder IFrames ect.. besitzt, find ich den richtigen Handle nicht mehr..

Es ist ja möglich! Manche Übersetzungsprogramme arbeiten ja auch so.. Text in irgendeiner Anwendung markieren - translaten - fertig !

Das OS kennt das GetForegroundWindow
Das OS kennt das Control, das grad aktiv ist
Das OS weiß, was selected wurde - da die Markierung vom selectierten text ja (fast immer) vom OS gezeichnet wird und "WM_Copy/Paste" ja auch auf dieses Ziel zugreifen

(Lösungsanzätze mit OCR, Clippboard als Zwischenlager,Tastatur Hooks ect.. will ich eigentlich nicht verwenden...)

Hat jemand eine Lösung ?

vielen Dank

Erich


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:
procedure Tmain.Timer3Timer(Sender: TObject);
var
SelfId : DWord;
ThreadId: DWord;
Attached: Boolean;
Fokus : HWnd;
TextLen : LResult;
Text : PChar;
SelStart, SelEnd : Integer;
aPoint  : TPoint;
begin

Timer3.Enabled := False;
// die eigene Thread-Id holen
SelfId := GetCurrentThreadId;
// die Thread-Id des Hauptfensters mit dem eingabefokus holen
ThreadId := GetWindowThreadProcessId(GetForegroundWindow, nil);
// Flag initialisieren
Attached := False;
// prüfen, ob die Ziel-Thread-Id gültig und nicht die eigene ist
if (ThreadId <> 0and (ThreadId <> SelfId) then
// mit dem Ziel-Thread verbinden (die Message-Queues)
Attached := AttachThreadInput(SelfId, ThreadId, True);
// prüfen ob wir verbunden, (x)oder es selbst sind
if Attached xor (ThreadId = SelfId) then
try


// ******************************************************************
// hier fängt das Problem an... :-( 
// Ansätze: Active Accessibility
// http://support.microsoft.com/kb/210210/de
// (Word) - class "_WwF" it's not responding to WM_GETTEXT...
Fokus := GetFocus;  // GetFocus;//GetActiveChildWindow;//GetActiveChildWindow;//GetActiveWindow ;// Screen.ActiveControl.Handle; //GetFocus;

// Nachricht versenden, um die aktuelle Textlänge zu bekommen
TextLen := SendMessage(Fokus, WM_GETTEXTLENGTH, 00);
// Fokus prüfen - und wir starten hier unsere Aktion,
if (TextLen >= 0)  then  //and (TextLen < 1024)    (Fokus <> 0) and
begin
// Speicher anfordern (+ 1 jeweils für abschließende 0 und '*')
GetMem(Text, TextLen + 2);
try
// Speicher initialisieren
FillChar(Text^, TextLen + 20);
// Text holen
TextLen := SendMessage(Fokus, WM_GETTEXT, TextLen + 1, LParam(@Text[0]));
if TextLen >= 0 then
begin
// Text setzen
SendMessage(Fokus, EM_GETSEL, Integer(@SelStart), Integer(@SelEnd));
helplabel.Caption:='Von Position:'+Inttostr(SelStart)+'  bis Position:'+ Inttostr(SelEnd)+'Text:  '+copy(text,SelStart+1,SelEnd-SelStart);
end;
finally
// Speicher wieder freigeben
FreeMem(Text);
end;
end;
finally
// wenn verbuden, dann wieder trennen
if Attached then
AttachThreadInput(SelfId, ThreadId, False);
end;
Timer3.Enabled := True;
end;


Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Calyptus - Di 07.10.08 20:36

hast du inzwischen eine Lösung für dieses Problem? Denn ich habe genau die gleiche Frage.