![]() |
ShellExcecute/FindWindow/MoveWindow
Ich starte mit folgender Prozedur (hier aus dem Forum) ein Programm (C) das eine Anwendung mit Fenster
öffnet:
Delphi-Quellcode:
Die Anwendung /das Fenster taucht planmäßig im Task auf.
procedure RunAndWaitShell(Executable, Parameter: STRING; ShowParameter: INTEGER);
var Info: TShellExecuteInfo; pInfo: PShellExecuteInfo; exitCode: DWord; HANDLE : THANDLE; begin {Pointer to Info} pInfo := @Info; {Fill info} with Info do begin cbSize := SizeOf(Info); fMask := SEE_MASK_NOCLOSEPROCESS; wnd := application.Handle; lpVerb := NIL; lpFile := PChar(Executable); // emperormapper.exe {Parametros al ejecutable} {Executable parameters} lpParameters := PChar(Parameter + #0); lpDirectory := NIL; nShow := ShowParameter; hInstApp := 0; end; {Execute} ShellExecuteEx(pInfo); {Wait to finish} repeat exitCode := WaitForSingleObject(Info.hProcess, 500); Application.ProcessMessages; until (exitCode <> WAIT_TIMEOUT); end; Dann möchte ich das Fenster der Anwendung verschieben:
Delphi-Quellcode:
Geht nicht. Fehlt was?
HANDLE := FindWindow(Nil,'EmperorMapper');
MoveWindow(HANDLE, 600, 600, 400, 400, True); geldis |
AW: ShellExcecute/FindWindow/MoveWindow
Wird denn das Handle gefunden? Hast du den Wert nach dem Aufruf von FindWindow geprüft?
|
AW: ShellExcecute/FindWindow/MoveWindow
Du rufst das Programm auf und wartest auf Beendigung. An welcher Stelle willst du jetzt das Fenster verschieben?
Es könnte schon funktionieren, aber Du musst warten, bis das Programm das Fenster geöffnet hat. Schau Dir mal die API-Funktion WaitForInputIdle an. Wenn das Programm ein Fenster anzeigt und sich nicht direkt wieder beendet, würde ich auch möglichst nicht auf Beendigung des Programms warten. Das ProcessMessages, um Dein Programm nicht einfrieren zu lassen, ist eher schlechter Stil. |
AW: ShellExcecute/FindWindow/MoveWindow
Tja,
das Programm startet, hat den Focus, der Anwender muss eine Datei laden, die wird bearbeitet, dann muss der Anwender sie woandes speichern. Ergo benutze ich das Fenster. Wenn ich jetzt prüfe ob das Fenster bereits vorhanden ist via WaitforInputIdle muss ich das Handle der Anwendung haben. Oder? Gut:
Delphi-Quellcode:
function processExists(exeFileName: string): Boolean;
var ContinueLoop: BOOL; FSnapshotHandle: THandle; FProcessEntry32: TProcessEntry32; begin FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); FProcessEntry32.dwSize := SizeOf(FProcessEntry32); ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32); Result := False; while Integer(ContinueLoop) <> 0 do begin if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpperCase(ExeFileName)) or (UpperCase(FProcessEntry32.szExeFile) = UpperCase(ExeFileName))) then begin Result := True; end; ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32); end; CloseHandle(FSnapshotHandle); end;
Delphi-Quellcode:
RunAndWaitShell(XMLPAth + 'emperormapper.exe','',1);
If ProcessExists('emperormapper.exe') then begin WaitforInputIdle(FSnapshotHandle,10000); HANDLE := FindWindow(Nil,'EmperorMapper'); MoveWindow(HANDLE, 600, 600, 400, 400, True); end; Ich werde jetzt nicht ganz schlau aus dem ProcessExists. Wird da geprüft ob der Process existiert bis er existiert? Jedenfalls geht es so auch nicht. geldis |
AW: ShellExcecute/FindWindow/MoveWindow
Natürlich geht das nicht. Wenn RunAndWaitShell auf Beendigung des Programms wartet, wird Dein weiterer Code erst danach ausgeführt.
Du musst die Funktion RunAndWaitShell ändern und dort nicht auf Beendigung, sondern auf "Input Idle" warten. Das Process-Handle hast Du dort auch bereits und musst es nicht später umständlich mit ProcessExists wieder ermitteln. Aber mal ganz von vorne: Hast Du probiert mit einem kleinen Testprogramm das Fenster der zuvor manuell gestarteten "EmpororMapper.exe" zu verschieben? Wenn das nicht geht, kannst Du Dir den Rest sparen. |
AW: ShellExcecute/FindWindow/MoveWindow
Zitat:
Aber vermutlich wirst du dort gar nicht zur richtigen Zeit ankommen. Das wurde ja schon gesagt. Um das zu prüfen, ist der Debugger genau wichtig. |
AW: ShellExcecute/FindWindow/MoveWindow
Also : ich mache das jetzt so :
Delphi-Quellcode:
Das funktioniert problemlos.
// der Anwender ruft das Programm auf
ShellExecute(self.handle, 'open',Pchar(XMLPAth + 'emperormapper.exe'), '', nil, SW_SHOW); // .. delphi wartet ein bisschen bis der Prozess soweit ist das das Fenster steht .. Sleep(25); // jetzt funzt der Handle Zugriff und damit auch das verschieben If ProcessExists('emperormapper.exe') then begin HANDLE := FindWindow(Nil,'EmperorMapper'); MoveWindow(HANDLE, Left, Top, 461, 430, True); end; // das Delphiprogramm wartet bis der Anwender die emperormapper.exe beendet While ProcessExists('emperormapper.exe') do begin Application.ProcessMessages; end; // es geht weiter Aber Elegant ist das nicht. Gibt es da irgendwelche ernsthaften Probleme? geldis |
AW: ShellExcecute/FindWindow/MoveWindow
Zitat:
Im ersten Beitrag hast du doch selbst Code gezeigt, mit dem du deinen externen Prozess startest, dessen Handle bekommst (Info.hProcess) und dann auf dessen Ende wartest. Was hindert dich denn daran, den Prozess zu starten, dir das Handle zu merken, deine Aktionen durchzuführen und dann genauso auf das Ende des Prozesses zu warten? |
AW: ShellExcecute/FindWindow/MoveWindow
Moin.
Seien wir ehrlich : Das funktioniert problemlos und ich habe es einigermaßen verstanden. Die Abteilung ShellExecute und vor allem die diversen Informationen wie >> FProcessEntry32, Process32First(FSnapshotHandle, FProcessEntry32), FProcessEntry32.szExeFile, WaitForInputIdle ...... und das ganze andere Zeug - das steht jetzt auf der ToDo Liste. Ich muss und möchte das lernen und verstehen. Bis dahin lasse ich das jetzt so. Falls niemand ensthafte Einwände hat. Ich danke jedenfalls allen hier Beteiligten für die Unterstützung und vor allem für die Denkanstösse und Hinweise wo man denn überhaupt mal nachschaut. geldis |
AW: ShellExcecute/FindWindow/MoveWindow
Hier mal ein Beispiel angelehnt an den ursprünglichen Code:
Delphi-Quellcode:
Zur Erklärung:
procedure RunAndWaitShell(const AExecutable, AParameter: string; AShowParameter: Integer; AOnAfterStart: TProc);
var ExecInfo: TShellExecuteInfo; WaitResult: DWord; begin FillChar(ExecInfo, SizeOf(ExecInfo), 0); ExecInfo.cbSize := SizeOf(ExecInfo); ExecInfo.fMask := SEE_MASK_NOCLOSEPROCESS; ExecInfo.Wnd := Application.Handle; ExecInfo.lpVerb := 'open'; ExecInfo.lpFile := PChar(AExecutable); ExecInfo.lpParameters := PChar(AParameter); ExecInfo.lpDirectory := nil; ExecInfo.nShow := AShowParameter; ExecInfo.hInstApp := 0; if ShellExecuteEx(@ExecInfo) then begin WaitResult := WaitForInputIdle(ExecInfo.hProcess, 10000); if WaitResult = WAIT_FAILED then ShowMessage('WaitForInputIdle ist fehlgeschlagen!'); if Assigned(AOnAfterStart) then AOnAfterStart; repeat WaitResult := WaitForSingleObject(ExecInfo.hProcess, 500); Application.ProcessMessages; until WaitResult <> WAIT_TIMEOUT; CloseHandle(ExecInfo.hProcess); end else ShowMessage('Prozess konnte nicht gestartet werden!'); end; // Aufruf: RunAndWaitShell('emperormapper.exe', '', SW_SHOW, procedure var WinHandle: THandle; begin WinHandle := FindWindow(nil, 'EmperorMapper'); MoveWindow(WinHandle, 600, 600, 400, 400, True); end ); Der Prozess wird gestartet. Dann wird gewartet, bis der Prozess alle anstehenden Eingaben abgeschlossen hat und auf Eingaben wartet. Dann wird eine anonyme Methode aufgerufen, in der du deine Aktionen durchführen kannst. Und danach wird gewartet, bis der Prozess beendet ist. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:37 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