Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Titelloses Fenster eines Fremdprogrammes positionieren? (https://www.delphipraxis.net/130450-titelloses-fenster-eines-fremdprogrammes-positionieren.html)

PeterPanino 8. Mär 2009 21:40


Titelloses Fenster eines Fremdprogrammes positionieren?
 
Hallo! Alle mir bekannten Utilities zur Positionierung von Fremdprogrammen auf dem Desktop verwenden zur Identifizierung eines bestimmten Programmes, dessen Bildschirmposition verändert werden soll, den Titeltext (Caption) des betreffenden Programmfensters. Nun habe ich aber den Fall eines GUI-Programmes, das keinen Fenstertitel hat. Wie kann ein solches Programm identifiziert und dann seine Bildschirmposition verändert werden?

HalloDu 8. Mär 2009 21:41

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Eventuell ist das über den Fensterklassennamen möglich. WinSpy oder ähnliches sollte da helfen.

quendolineDD 8. Mär 2009 21:42

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Eventuell an dem Namen des Prozesses? Daran kannst du doch die Prozess-Id ermitteln und weiterführend davon die Fenster. Oder liege ich falsch?

PeterPanino 8. Mär 2009 21:54

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
In WinSpy++ wird bei Class "#32770 (Unicode)" angezeigt. Ist das ein temporärer Wert oder kann dies einer Fensterklasse explizit zugeordnet werden?

Aus dem Prgrammnamen das Fensterhandle ermitteln? Werde dem mal nachgehen. Sollte jemand da schon eine fertige Lösung haben, wäre das natürlich erst mal positiv ...!

PeterPanino 8. Mär 2009 23:12

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Hallo, ich habe es jetzt geschafft, die PID und das Fensterhandle vom Programmnamen zu bekommen:

Delphi-Quellcode:
program RepositionWindowFromExeName;

{$APPTYPE CONSOLE}

uses
  Dialogs, // debug
  JclSysInfo,
  SysUtils, Windows;

var
  APID: Cardinal;
  AHandle: THandle;
  rc: TRect;

begin
  try
    APID := GetPidFromProcessName('QGet.exe'); // 11424
    if APID <> INVALID_HANDLE_VALUE then
    begin
      AHandle := GetMainAppWndFromPid(APID);
      MessageDlg(GetWindowCaption(AHandle), mtInformation, [mbOK], 0); // leer!
      GetWindowRect(AHandle, rc);
      MessageDlg(IntToStr(rc.Left)  + #13#10 +
                 IntToStr(rc.Top)   + #13#10 +
                 IntToStr(rc.Right) + #13#10 +
                 IntToStr(rc.Bottom) + #13#10
                 , mtInformation, [mbOK], 0);
    end;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
GetWindowCaption:
http://img255.imageshack.us/img255/7...dowcaption.gif

GetWindowRect:
http://img24.imageshack.us/img24/5908/getwindowrect.gif

Wie man sieht, funktioniert das Erfassen der Fensterkoordinaten nicht. Könnte jemand weiterhelfen?

Luckie 8. Mär 2009 23:41

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Nicht nur das Erfassen funktioniert nicht. Hast du denn schon mal geguckt, ob das Fensterhandle überhaupt gütig ist? nd woher kommt die Funktion GetMainAppWndFromPid? Kommt die aus Jcl? hast du diese schon mal debuggt und geguckt, was da passiert?

Was hast du überhaupt schon unternommen, um den Fehler zu finden?

PeterPanino 9. Mär 2009 00:28

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Zitat:

Zitat von Luckie
Nicht nur das Erfassen funktioniert nicht. Hast du denn schon mal geguckt, ob das Fensterhandle überhaupt gütig ist? nd woher kommt die Funktion GetMainAppWndFromPid? Kommt die aus Jcl? hast du diese schon mal debuggt und geguckt, was da passiert?

Was hast du überhaupt schon unternommen, um den Fehler zu finden?

Eine ganze Menge! Ich bitte dich außerdem, einen anderen Ton mir gegenüber zu verwenden! Wenn du etwa glauben solltest, dass ich nur Fragen stelle ohne selbst etwas zu tun (s. paralleler Thread), dann hast du dich gründlich getäuscht! Ich habe für dieses Forum schon eine Menge eigenen Code geschrieben! Bitte lass deine Vorurteile an jemand anderem aus!

Um wieder zum Thema zurückzukehren: Es ist mir jetzt gelungen, die Koordinaten des Fensters herauszufinden:

Delphi-Quellcode:
program RepositionWindowFromExeName;

{$APPTYPE CONSOLE}

uses
  Dialogs, // debug
  JclSysInfo,
  SysUtils, Windows;

var
  AHandle: THandle;
  rc: TRect;

begin
  try
    AHandle := FindWindow('#32770', nil);

    GetWindowRect(AHandle, rc);

    MessageDlg(IntToStr(rc.Left)  + #13#10 +
               IntToStr(rc.Top)   + #13#10 +
               IntToStr(rc.Right) + #13#10 +
               IntToStr(rc.Bottom) + #13#10
               , mtInformation, [mbOK], 0);

  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;
end.
Jetzt muss ich nur noch eine Methode finden, die Koordinaten des Fensters zu ändern.

Luckie 9. Mär 2009 00:38

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Also ich wüßte nicht, was an meinem neutralen Ton daneben war. Und die Frage. was du schon probiert hast, habe ich nur gestellt, damit wir nicht Vorschläge machen, die du schon alle probiert hast.

Den Klassennamen in diesem Fall zu verwende ist schlecht. Jedes mit der MFC erzeugte Fenster hat diesen Klassennmane, er ist also nicht unbedingt eindeutig.

verwirrt 9. Mär 2009 01:09

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Zitat:

Zitat von PeterPanino
Jetzt muss ich nur noch eine Methode finden, die Koordinaten des Fensters zu ändern.

SetWindowRect

PeterPanino 9. Mär 2009 01:21

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Zitat:

Zitat von Luckie
Also ich wüßte nicht, was an meinem neutralen Ton daneben war. Und die Frage. was du schon probiert hast, habe ich nur gestellt, damit wir nicht Vorschläge machen, die du schon alle probiert hast.

Nichts für ungut, ich habe vielleicht etwas überreagiert.

Zitat:

Zitat von Luckie
Den Klassennamen in diesem Fall zu verwende ist schlecht. Jedes mit der MFC erzeugte Fenster hat diesen Klassennmane, er ist also nicht unbedingt eindeutig.

Du meinst, dass der Klassenname '#32770' womöglich bei mehreren Programmen vorkommt? Und wie kann man sonst über die PID an das fenster-handle kommen?

PeterPanino 9. Mär 2009 02:14

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Zitat:

Zitat von verwirrt
Zitat:

Zitat von PeterPanino
Jetzt muss ich nur noch eine Methode finden, die Koordinaten des Fensters zu ändern.

SetWindowRect

Mhm, über SetWindowRect habe ich im Zusammenhang mit Delphi nichts Ergiebiges gefunden, wohl aber bei SetWindowPos:

Delphi-Quellcode:
SetWindowPos(AHandle,
             HWND_TOPMOST,
             rc.Left, rc.Top-100, rc.Right - rc.Left, rc.Bottom - rc.Top,
             SWP_NOSIZE or SWP_NOACTIVATE or SWP_SHOWWINDOW);
Mit diesem Code kann ich zwar ein anderes Fenster bewegen, aber - wie Luckie bemerkt hat - funktioniert offensichtlich das Identifizieren des gesuchten Fensters mit "FindWindow('#32770', nil)" nicht, da ein anderes Fenster bewegt wird und nicht dasjenige, für das ich mit WinSpy++ den Class Name gefunden habe. Also wieder zurück an den Start und mit einer anderen Methode das gewünschte Fensterhandle finden.

PeterPanino 9. Mär 2009 03:15

Re: Titelloses Fenster eines Fremdprogrammes positionieren?
 
Ich hab's jetzt endlich geschafft, das richtige Fensterhandle und die richtigen Fensterkoordinaten zu bekommen. Dazu musste ich die Funktion GetMainAppWndFromPid etwas ändern:

Delphi-Quellcode:
function GetMainAppWndFromPid(PID: DWORD): THandle;
type
  PSearch = ^TSearch;
  TSearch = record
    PID: DWORD;
    Wnd: THandle;
  end;
var
  SearchRec: TSearch;

  function EnumWindowsProc(Wnd: THandle; Res: PSearch): Boolean; stdcall;
  var
    WindowPid: DWORD;
  begin
    WindowPid := 0;
    GetWindowThreadProcessId(Wnd, @WindowPid);
    if (WindowPid = Res^.PID) then //and IsMainAppWindow(Wnd) then // <--- <--- <---
    begin
      Res^.Wnd := Wnd;
      Result := False;
    end
    else
      Result := True;
  end;

begin
  SearchRec.PID := PID;
  SearchRec.Wnd := 0;
  EnumWindows(@EnumWindowsProc, Integer(@SearchRec));
  Result := SearchRec.Wnd;
end;
Ich habe die Bedingung and IsMainAppWindow(Wnd) rausgenommen (s. oben), weil mein gesuchtes Fenster kein Hauptfenster hat. Die Frage ist jetzt aber, wie ich diese Funktion so verallgemeinern kann, dass sie mit allen Fenstertypen funktioniert?


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:30 Uhr.

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