Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Text in Eingabefeld beliebiger Anwendungen ersetzen? (https://www.delphipraxis.net/39922-text-eingabefeld-beliebiger-anwendungen-ersetzen.html)

FriFra 9. Feb 2005 08:21


Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Wie stelle ich es am besten an in aktiven Eingabefeldern beliebiger Anwendungen nach einem bestimmten Text zu suchen und diesen automatisch zu ersetzen?

Im Prinzip soll das ganze in jedem Mailprogramm, in Word, im Notepad im IE u.s.w. funktionieren...


Beispiel:
Der User öffner sein Mail, wo automatisch die Signatur "###Hierhin###" eingefügt wird. Nun ersetzt mein Programm "###Hierhin###" durch einen anderen Text.

toms 9. Feb 2005 08:29

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Stichworte: Hier im Forum suchenEnumChildWindows Hier im Forum suchenWM_GETTEXT, Hier im Forum suchenWM_SETTEXT

Sprint 10. Feb 2005 04:44

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Dieses kleine Beispiel ermittelt mit Hilfe von EnumWindows alle TopLevel Fenster. Sollte das Fenster den Klassennamen "Notepad" haben, wird das Kindfenster "Edit" gesucht. Wurde es gefunden, wird es in die TList "List" eingetragen. Mit WM_GETTEXT wird dann der Inhalt von Notepad ausgelesen. StringReplace tauscht dann "###Hierhin###" durch "Neuer Text" aus. Und WM_SETTEXT sorgt dafür, das der bearbeitete Text wieder ins Notepad Fenster gelangt. Ich denke mal, als kleiner Einstieg reicht das und wird dir bestimmt weiterhelfen.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);

  function EnumWindowsProc(Wnd: HWND; lParam: LPARAM): BOOL; stdcall;
  var
    ClassName: String;
    EditHWnd: HWND;
  begin

    SetLength(ClassName, 512);
    SetLength(ClassName, GetClassName(Wnd, PChar(ClassName), Length(ClassName)));
    if ClassName = 'Notepad' then
    begin
      EditHWnd := FindWindowEx(Wnd, 0, 'Edit', nil);
      if IsWindow(EditHWnd) then
        TList(lParam).Add(Pointer(EditHWnd));
    end;
    Result := True;

  end;

var
  List: TList;
  I: Integer;
  S: String;
begin

  List := TList.Create;
  try
    EnumWindows(@EnumWindowsProc, LPARAM(List));
    for I := 0 to List.Count - 1 do
    begin
      SetLength(S, SendMessage(HWND(List.Items[I]), WM_GETTEXTLENGTH, 0, 0) + 1);
      if Length(S) > 1 then
      begin
        SetLength(S, SendMessage(HWND(List.Items[I]), WM_GETTEXT, Length(S), LPARAM(PChar(S))));
        S := StringReplace(S, '###Hierhin###', 'Neuer Text', [rfReplaceAll]);
        SendMessage(HWND(List.Items[I]), WM_SETTEXT, Length(S), LPARAM(PChar(S)));
      end;
    end;
  finally
    List.Free;
  end;

end;

FriFra 11. Feb 2005 00:31

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Danke, das ist natürlich ein Anfang ;) ...
Aber wäre es nicht möglich einfach im gerade aktivem Control (egal welche Anwendung!) nach einem Text zu suchen?
WM_SETTEXT hat auch den unangenehmen Nebeneffekt, dass sich die Cursorposition ändert...

Sprint 11. Feb 2005 00:48

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Zitat:

Zitat von FriFra
Aber wäre es nicht möglich einfach im gerade aktivem Control (egal welche Anwendung!) nach einem Text zu suchen?

Das Problem ist ja, das sich diese Daten in einem anderen Prozess befinden. Und du kannst erst im Text suchen, wenn sich diese in deinem Adressraum befinden.

Zitat:

WM_SETTEXT hat auch den unangenehmen Nebeneffekt, dass sich die Cursorposition ändert...
Dann lese vorher die Cursorposition aus. Und nach WM_SETTEXT, setzt du den Cursor wieder an die alte Position.

Luckie 11. Feb 2005 01:07

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Eine interessante Idee. Aber du wirst einige Hürden zu überwinden haben. Handelt es sich um ein standard Windows Edit-Controll ist es kein großes Problem, wie der Code von Sprint gezeigt hat. Word und andere Anwendungen benutzen aber selbst gebastelte Controlls. So ist das, wo du bei Word deinen Text eingibst bestimmt kein Edit-Controll. Du hast es also im Prinzip mit unendlich vielen Fensterklassen zu tun. OpenOffice wird wieder eine andere eigenen Fensterklasse benutzen usw.

@Sprint. Wenn du mit WM_GETTWEXT den Fenstertext ausliest und ihn in eine Variable deines Programmes schreibst, dann befindet sich der Text doch in einer Varaibel, die in deinem Prozess liegt. Das zeigt doch dein Quellcode? Deswegen verstehe ich deine aussage nicht so ganz.

Sprint 11. Feb 2005 01:21

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Zitat:

Zitat von Luckie
Wenn du mit WM_GETTWEXT den Fenstertext ausliest und ihn in eine Variable deines Programmes schreibst, dann befindet sich der Text doch in einer Varaibel, die in deinem Prozess liegt. Das zeigt doch dein Quellcode? Deswegen verstehe ich deine aussage nicht so ganz.

FriFra wollte auf WM_SETTEXT verzichten. Das bedeutet für mich, das er auch auf WM_GETTEXT verzichten will. Darum meine Antwort mit dem Prozess/Adressraum.

FriFra 11. Feb 2005 01:55

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Wäre es nicht irgendwie möglich geziehlt das Control zu bekommen, welches gerade den Focus hat?

Sprint 11. Feb 2005 02:18

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Zitat:

Zitat von FriFra
Wäre es nicht irgendwie möglich geziehlt das Control zu bekommen, welches gerade den Focus hat?

Doch natürlich. Das ist kein Problem.
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  AppHWnd: HWND;
  ThreadId: DWORD;
  FocusHWnd: HWND;
begin

  FocusHWnd := GetFocus;
  if not IsWindow(FocusHWnd) then
  begin
    AppHWnd := GetForegroundWindow;
    if AppHWnd <> Self.Handle then
    begin
      ThreadId := GetWindowThreadProcessId(AppHWnd, nil);
      if ThreadId <> 0 then
        if AttachThreadInput(GetCurrentThreadId, ThreadId, True) then
        begin
          FocusHWnd := GetFocus;
          AttachThreadInput(GetCurrentThreadId, ThreadId, False);
        end;
    end;
  end;

  ListBox1.ItemIndex := ListBox1.Items.Add('Das Fensterhandle $' + IntToHex(FocusHWnd, 8) + ' hat den Fokus');

end;

FriFra 11. Feb 2005 08:23

Re: Text in Eingabefeld beliebiger Anwendungen ersetzen?
 
Also, jetzt klappt es eigentlich schon ganz gut, wenn es ein Edit oder ein Button ist... bei einigen Controls bekomme ich jedoch noch nicht einmal den Klassennamen :?

Ich hab mir jetzt erst einmal eine Funktion gebastelt, die mir onTimer1 den gerade aktiven Klassennamen und den dazu gehörenden Text in eine ListView schreibt:
Delphi-Quellcode:
procedure TForm1.Timer1Timer(Sender: TObject);
var
  AppHWnd: HWND;
  ThreadId: DWORD;
  FocusHWnd: HWND;
  ClassName: string;
  S0, S1: string;
begin
  Timer1.Enabled := False;
  FocusHWnd := GetFocus;
  if not IsWindow(FocusHWnd) then
  begin
    AppHWnd := GetForegroundWindow;
    if AppHWnd <> Self.Handle then
    begin
      ThreadId := GetWindowThreadProcessId(AppHWnd, nil);
      if ThreadId <> 0 then
        if AttachThreadInput(GetCurrentThreadId, ThreadId, True) then
        begin
          FocusHWnd := GetFocus;
          AttachThreadInput(GetCurrentThreadId, ThreadId, False);

          SetLength(ClassName, 512);
          SetLength(ClassName, GetClassName(FocusHWnd, PChar(ClassName),
            Length(ClassName)));

          SetLength(S0, SendMessage(FocusHWnd, WM_GETTEXTLENGTH, 0, 0) + 1);
          if Length(S0) > 1 then
          begin
            Application.ProcessMessages;
            SetLength(S0, SendMessage(FocusHWnd, WM_GETTEXT, Length(S0),
              LPARAM(PChar(S0))));
            S1 := StringReplace(S0, '###Hierhin###', 'Neuer Text',
              [rfReplaceAll]);

            if S0 <> S1 then
              SendMessage(FocusHWnd, WM_SETTEXT, Length(S1), LPARAM(PChar(S1)));
          end;
        end;
    end;
  end;

  if (ListView1.Items.Count = 0) or (ListView1.Items[ListView1.Items.Count -
    1].Caption <> IntToStr(FocusHWnd) + '[' + ClassName + ']="' + Trim(S0) + '"')
      then
  begin
    ListView1.Items.BeginUpdate;
    ListView1.Items.Add;
    ListView1.Items[ListView1.Items.Count - 1].Caption := IntToStr(FocusHWnd) +
      '[' + ClassName + ']="' + Trim(S0) + '"';
    ListView1.Items[ListView1.Items.Count - 1].MakeVisible(False);
    ListView1.Items.EndUpdate;
  end;
  Timer1.Enabled := True;
end;
Klassen wo es nicht funzt:
"_WwG" (Word XP)
"TEditControl" (Delphi2005, Code)
"Internet Exploerer_Server" (IE)


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:43 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz