Entwickler-Ecke

Windows API - Text in ein Feld einer externen Anwendung einfügen


Ivo@CoMRoK - Di 20.01.09 17:07
Titel: Text in ein Feld einer externen Anwendung einfügen
Hi, Leute.
So ich hab mich seid Ewigkeiten hier nichmehr sehen lassen, hatte das Forum schon richtig vergessen, da ich auch länger nix mehr mit Delphi gemacht habe. Jetzt hab ich was angefangen soweit so gut. N paar Sachen wusst ich nich hab ich hier aber im Forum gefunden :) Eins schaff ich aber doch nicht vll könnt ihr mir ja helfen? ^^

Also ich will mirn Programm schreiben mit dem ich den aktuellen Track aus Winamp im aktiven Fenster reinschreiben kann. Ich lese also den Titel aus (wies geht hab ich schon rausgefunden) speicher das als Text im Clipboard (is auch kein Problem ^^) jetzt hab ich allerdings das Problem mit dem Einfügen ich hab hier [http://www.delphi-forum.de/viewtopic.php?t=56959&highlight=zwischenablage+schreiben] schonmal nen interessanten Thread gefunden, habe es auf "V" umgeschrieben und gehofft es würde dann also "Strg"+"V" senden, wenn ich es ausprobiere funktioniert es allerdings nicht. Der Einachheit halber habe ich das Programm mal nur als Konsolenanwendung laufen.

Hier mal der Code:


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:
program Project3;
{$APPTYPE CONSOLE}

uses
   Forms, Messages, Windows, StdCtrls, clipbrd;

{$R *.res}

procedure FindActiveControl;
var hWindow: HWND;
    Pid1, Pid2: Cardinal;
    lParam: LongInt;
    ksNew, ksOld: TKeyboardState;
begin
  Pid1 := GetWindowThreadProcessId(Application.Handle);
  Pid2 := GetWindowThreadProcessId(GetForeGroundWindow);

  if AttachThreadInput(Pid1, Pid2, True) then
  begin
    hWindow := GetFocus;
    lParam := MakeLong(0, MapVirtualKey($430));
    ksNew[VK_CONTROL] := $80;
    GetKeyboardState(ksOld);
    SetKeyboardState(ksNew);
    PostMessage(hWindow, WM_KEYDOWN, $56, lParam);
    PostMessage(hWindow, WM_KEYUP, $56, lParam or $C0000000);
    Application.ProcessMessages;
    SetKeyboardState(ksOld);
  end;
  AttachThreadInput(Pid1, Pid2, False);
end;



function GetWinampFilename(data:Integer): String;
var Text: String;
    hwndWinamp, TempHandle : THandle;
    dat2: array[0..500of Char;
    TrackPos: Integer;
    temp, MPointer: Cardinal;
begin
  hwndWinamp:= FindWindow('Winamp v1.x',nil);
  if data<0 then TrackPos:= SendMessage(hwndWinamp,WM_USER,0 , 125else TrackPos:=data;
  MPointer:= SendMessage(hwndWinamp,WM_USER,TrackPos , 212);
  GetWindowThreadProcessId(hwndWinamp,TempHandle);
  hwndWinamp:= OpenProcess(PROCESS_ALL_ACCESS,False,TempHandle);
  ReadProcessMemory(hwndWinamp, Pointer(MPointer), @dat2,500,temp);
  CloseHandle(hwndWinamp);
  Result:= dat2;  // ;-)
end;

begin
  while (getasynckeystate(27) = 0do
  begin
    if (getasynckeystate(13) <> 0and (getasynckeystate(17) <> 0and (getasynckeystate(18) <> 0then
    begin
      writeln ( GetWinampFilename(-1) );
      clipboard.astext := GetWinampFilename(-1);
      FindActiveControl;
    end;
    repeat
    until (getasynckeystate(13) = 0or (getasynckeystate(17) = 0or (getasynckeystate(18) = 0);
  end;
end.


Ich würd mich freuen wenn mir wer helfen kann, obwohl ich mich so lange hier nicht hab blicken lassen. Ich würd gern wieder mehr machen muss aber mindestens warten bis ich Abi rum hab, vll bin ich dann ja wieder mehr on.
mfg Ivo

edit: also ich hatte jetzt den Verdacht dasses daran liegt dass ich ne andere Kombination hab und nochma aufs wesentliche geändert:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
repeat until (getasynckeystate(18) <> 0);
  repeat until (getasynckeystate(18) = 0);
  sleep(1000);
  writeln ( GetWinampFilename(-1) );
  clipboard.astext := GetWinampFilename(-1);
  FindActiveControl;
  sleep(1000);


So. Ich hab noch das Sleep reingemacht dasses nich doch zuner Kombo kommt. Geht aber doch nicht :( Ich hab jetzt echt keinen Plan mehr.


JayEff - Di 20.01.09 19:11

Nimm X-Spy [http://www.x-spy.net/] um FindWindow-Code für das entsprechende Edit-Feld zu finden, dann nutze folgenden Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
//wnd sei das Handle des Editfeldes
//P ist ein PChar
//song ist dein Songtitel als String
P := PChar(song);
SendMessage(wnd, WM_SETTEXT, 0, Cardinal(P));

Sollte funktionieren :zustimm:


Ivo@CoMRoK - Di 20.01.09 19:15

Danke für die Antwort, die auch gar nicht so lange gedauert hat, naja aber um ehrlich zu sein ^^:
Ich wollte das ganze für ICQ machen, da ich nicht MIranda und ähnliches draufmachen will xD
und die Einzelnen Fenster sind dann unterschiedlich bezeichnet, weshalbt ich wirklich das AKTIVE Element auswählen will. Trotzdem danke ^^


JayEff - Di 20.01.09 19:19

user profile iconIvo@CoMRoK hat folgendes geschrieben Zum zitierten Posting springen:
das AKTIVE Element auswählen will. Trotzdem danke ^^
Schonmal mit der von dir genutzten Variable "hWindow" versucht? :nixweiss: Kann auch sein, dass du mit FindWindowEx noch das Eingabefeld von hWindow suchen musst.


Ivo@CoMRoK - Di 20.01.09 20:23

Hmmmm, eigentlich keine schlechte Idee. Puhhh ich hab lange nicht mehr mit HWNDs gearbeitet.
Es müsste doch eigentlich gehen, dass ich den Namen aus hWindow nehme und in Findwindow eintrage oder?

Beziehungsweise: Mache ich das überhaupt bis jetzt richtig, dass ich das aktive Fenster aktiviere?


JayEff - Di 20.01.09 22:00

user profile iconJayEff hat folgendes geschrieben Zum zitierten Posting springen:
Nimm X-Spy [http://www.x-spy.net/] um FindWindow-Code für das entsprechende Edit-Feld zu finden
:!:
Mit deinem GetFocus erhälst du ja das aktuell aktive Fenster, dann nutzt du FindWindowEx auf gerade erhaltene Handle und schaust dir den von x-Spy generierten Code an, in dem siehst du, wie du das Handle des Eingabefeldes bekommst.


Ivo@CoMRoK - Mi 21.01.09 00:42

Okay. das mit dem findwondow ex hab ich hinbekommen, es funktioniert trotzdem nicht. Tut mir leid dass ich so nerve aber ich kriegs halt nicht hin.
Also mein Code sieht jetzt so aus:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
.
.
.
  if AttachThreadInput(Pid1, Pid2, True) then
  begin
    hWindow := GetFocus;
    hWindow :=  FindWindowEx(hWindow, 0'__oxFrame.class__'nil);
    hWindow :=  FindWindowEx(hWindow, 0'Internet Explorer_Server'nil);
    lParam := MakeLong(0, MapVirtualKey($560));
    //ksNew[VK_CONTROL] := $80;     ich hab mir gedacht vll stört ne normal etastenkombination dashalb hab ich strg v statt zuzu schicken das strg gleich ma in die abfrage eingebaut
    //GetKeyboardState(ksOld);
    //SetKeyboardState(ksNew);
    PostMessage(hWindow, WM_KEYDOWN, $56, lParam);
.
.
.



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
  while (getasynckeystate(27) = 0do
  begin         // in der abfrage wird jetzt strg abgefragt
    if (getasynckeystate(17) <> 0{and }{(getasynckeystate(13) <> 0)} {and }{(getasynckeystate(18) <> 0) }then
    begin
      writeln ( GetWinampFilename(-1) );
      clipboard.astext := GetWinampFilename(-1);
      FindActiveControl;
      sleep(1000);
    end;
    repeat
    until (getasynckeystate(17) = 0{or }{(getasynckeystate(13) = 0)}{ or} {(getasynckeystate(18) = 0)};
  end;


Tut mir echt leid ich hab überhaupt keinen plan mehr was jetzt noch fehlen könnte.


JayEff - Mi 21.01.09 02:33

aber mit WM_SETTEXT hast du es auch schon versucht? Normalerweise nutzt man diese Methode um irgendwo Text einzufügen. Wer weiß ob der user grad was Wichtiges im Clipboard hat, das wär dann weg...


Ivo@CoMRoK - Mi 21.01.09 13:22

Hmm hört sich interessant an. also ich hab mir gleich dazu n paar threads durchgelesen.
Ich habs jetzt so geändert:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
procedure FindActiveControl(Text: String);
var hWindow: HWND;
    Pid1, Pid2: Cardinal;
    lParam: LongInt;
    ksNew, ksOld: TKeyboardState;
begin
  Pid1 := GetWindowThreadProcessId(Application.Handle);
  Pid2 := GetWindowThreadProcessId(GetForeGroundWindow);

  if AttachThreadInput(Pid1, Pid2, True) then
  begin
    hWindow := GetFocus;
    //hWindow :=  FindWindowEx(hWindow, 0, '__oxFrame.class__', nil);
    //hWindow :=  FindWindowEx(hWindow, 0, 'Internet Explorer_Server', nil);
    SendMessage(hwindow, WM_SETTEXT, 0, Integer(PChar(text)));
    Application.ProcessMessages;
    sleep(100);
  end;
  AttachThreadInput(Pid1, Pid2, False);
end;


Es funktioniert trotzdem nicht auch wenn ich die // weglasse. Hab ich das jetzt richtig verwendet?

edit: ich habs auch hiermit probiert: http://www.swissdelphicenter.ch/de/showcode.php?id=220

sieht jetzt so aus in der abfrage nach strg:


Delphi-Quelltext
1:
2:
3:
4:
writeln ( GetWinampFilename(-1) );
clipboard.astext := GetWinampFilename(-1);
PostKeyEx32(Ord('V'), [ssctrl, ssAlt], False);
sleep(1000);


GTA-Place - Mi 21.01.09 17:44

Bist du sicher, dass du auch die richtigen Handles gefunden hast, denn was hat Internet Explorer_Server mit ICQ zu tun?