![]() |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Funktioniert KeyBd_Event vielleicht auch mit Win + Left und Win + Right?
Dann müsste man nur statt MoveWindow erst das eine Fenster fokussieren, Win + Left schicken, dann das zweite Fokussieren und Win + Right schicken. |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Zitat:
Na wenigstens funktioniert das in W10 noch. Wenn der Spalt nicht zu groß ist stört das ja vielleicht nicht so sehr. Zitat:
Also muß ich doch wieder zurück zu "MoveTwoWinExToFront" mit Hilfe von Minimize und Restore.... Eigenartigerweise ist das aber nicht immer der Fall, manchmal funzt es und beide Fenster kommen nach vorne. Oder ich probier mal deine Prozedur... wenn alle Fenster vorher minimiert werden, dann würde man in dem Fall auch das zweite Fenster sehen. Windows ist da offenbar etwas eigensinnig ... Interessant unter XP und 8.1 geht das also auch... gut zu wissen... Zitat:
Ist wahrscheinlich gehopst wie gesprungen... wenn schon zwei geöffnet sind müssen die erstmal wieder nach vorne... |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Wozu die ganzen Try-Except-Blöcke, wenn sie doch leer sind?
Insbesondere hier:
Delphi-Quellcode:
Und warum das Auslagern in eine eigene Prozedur? Das suggeriert, dass hier noch mehr passiert, tut es aber nicht. Davon abgesehen bitte mal dies zu FreeAndNil lesen:
Procedure Free_slLoad;
Begin Try FreeAndNil(slLoad); Except End; End; ![]() |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Zitat:
Es funktioniert tatsächlich problemlos. Mit SetForegroundWindow lässt sich der Windows Explorer nach vorne holen und dann mit folgendem Code links snappen (und rechts dann analog):
Delphi-Quellcode:
keybd_event(VK_LWIN, MapVirtualKey(VK_LWIN, 0), 0, 0);
keybd_event(VK_LEFT, MapVirtualKey(VK_LEFT, 0), 0, 0); keybd_event(VK_LEFT, MapVirtualKey(VK_LEFT, 0), KEYEVENTF_KEYUP, 0); keybd_event(VK_LWIN, MapVirtualKey(VK_LWIN, 0), KEYEVENTF_KEYUP, 0); |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Zitat:
Wenn etwas nicht so läuft wie ich es erwarte, dann habe ich alles an einer Stelle im ErrorLog, sehe ich keinen, dann konnte er wohl nicht erstellt werden. Jetzt noch 'ne Exception, die mir sagt, dass der Log nicht erstellt werden konnte ist mir zuviel... schließlich hab' ich's ja versucht... das reicht mir dann... Ja.. ja, das ist das was ich im Moment mache... morgen oder übermorgen mache ich es vielleicht schon ganz anders... Danke für den Blog-Link... kannte ich aber schon und benutze immer noch FreeAndNil... ist wohl die Gewohnheit... :-) Zitat:
@Erdbär Man kann deine Procedure noch etwas verkleinern: :P
Delphi-Quellcode:
Danke nochmal für den Tipp... ich hab's mal mit eingebaut... Außerdem war die FensterSuche wohl für diesen Zweck etwas überdimensioniert... hab' sie deutlich kleiner gemacht:
Procedure TForm1.Button3Click(Sender: TObject);
Begin Keybd_event(VK_LWIN, 0, 0, 0); Keybd_event(Byte('M'), 0, 0, 0); Keybd_event(Byte('M'), 0, KEYEVENTF_KEYUP, 0); Keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); End;
Delphi-Quellcode:
Noch'n bisschen mehr und das Ding wird richtig sexy.... (OK, nur wenn man sich das irre Exception-Handling wegdenkt... :-)).
PROGRAM TwoWinEx;
USES Windows, Messages, Classes, Forms, SysUtils, ShellApi; VAR slFoundWnd: TStringlist; WndHandle : THandle; I : Integer; Procedure ErrorLog(ErrorInfo: String); Var slLoad : TStringlist; slSave : TStringlist; strErrorLog: String; Procedure Free_slLoad; Begin Try FreeAndNil(slLoad); Except End; End; Procedure Free_slSave; Begin Try FreeAndNil(slSave); Except End; End; Function ErrorLogExists: Boolean; Begin Try Result:= False; If FileExists('ErrorLog.txt') Then Begin Try slLoad:= TStringlist.Create; slLoad.LoadFromFile('ErrorLog.txt'); strErrorLog:= slLoad.Text; Result:= True; Finally Free_slLoad; End; End; Except End; End; Begin Try Try slSave:= TStringlist.Create; slSave.Add(DateTimeToStr(Now)); slSave.Add(ErrorInfo); If ErrorLogExists Then Begin slSave.Add(' '); slSave.Add(Trim(strErrorLog)); End; slSave.SaveToFile('ErrorLog.txt'); Finally Free_slSave; End; Except End; End; Function SearchCallback(Wnd: HWND; sl:TStringlist): BOOL; StdCall; Var ClassName: Array[0..255] Of Char; Begin Try If GetClassName(Wnd, ClassName, 255) > 0 Then Begin If Pos('CabinetWClass', String(ClassName)) <> 0 Then sl.Add(IntToStr(Wnd)); End; Result:= True; Except On E: Exception Do ErrorLog('SearchCallback'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure SearchWnd; Begin Try EnumWindows(@SearchCallback, lParam(slFoundWnd)); Except On E: Exception Do ErrorLog('SearchWnd'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure MinAllWnds; Begin Try Keybd_event(VK_LWIN, 0, 0, 0); Keybd_event(Byte('M'), 0, 0, 0); Keybd_event(Byte('M'), 0, KEYEVENTF_KEYUP, 0); Keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); Except On E: Exception Do ErrorLog('MinAllWnds'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure StartTwoWinEx; Begin Try If DirectoryExists('I:\') And DirectoryExists('I:\(DOWNLOADS)') Then Begin ShellExecute(0, Nil, PChar('I:\'), Nil, Nil, SW_SHOW); ShellExecute(0, Nil, PChar('I:\(DOWNLOADS)'), Nil, Nil, SW_SHOW); Repeat slFoundWnd.Clear; SearchWnd; Until slFoundWnd.Count >= 2; MoveWindow(StrToInt(slFoundWnd[0]), 0, 0, (Screen.WorkAreaWidth Div 2), Screen.WorkAreaHeight, True); MoveWindow(StrToInt(slFoundWnd[1]), (Screen.WorkAreaWidth Div 2), 0, (Screen.WorkAreaWidth Div 2), Screen.WorkAreaHeight, True); End Else Begin ShellExecute(0, Nil, PChar('C:\'), Nil, Nil, SW_SHOW); ShellExecute(0, Nil, PChar('D:\'), Nil, Nil, SW_SHOW); Repeat slFoundWnd.Clear; SearchWnd; Until slFoundWnd.Count >= 2; MoveWindow(StrToInt(slFoundWnd[0]), 0, 0, (Screen.WorkAreaWidth Div 2), Screen.WorkAreaHeight, True); MoveWindow(StrToInt(slFoundWnd[1]), (Screen.WorkAreaWidth Div 2), 0, (Screen.WorkAreaWidth Div 2), Screen.WorkAreaHeight, True); End; Except On E: Exception Do ErrorLog('StartTwoWinEx'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure Free_slFoundWnd; Begin Try FreeAndNil(slFoundWnd); Except On E: Exception Do ErrorLog('Free_slFoundWnd'+#13#10+E.ClassName+#13#10+E.Message); End; End; Begin Try slFoundWnd:= TStringlist.Create; Try SearchWnd; If slFoundWnd.Count >= 1 Then Begin For I:= 0 To slFoundWnd.Count-1 Do Begin WndHandle:= StrToInt(slFoundWnd[I]); SendMessage(WndHandle, WM_CLOSE, 0, 0); End; End; MinAllWnds; StartTwoWinEx; Finally Free_slFoundWnd; End; Except On E: Exception Do ErrorLog('MAIN PRG'+#13#10+E.ClassName+#13#10+E.Message); End; End. |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Nur so als kleine Info...
Wenn man das in Lazarus mit {$Mode ObjFpc}{$H+} compilieren möchte, dann muß man die Fenstersuche als PtrInt deklarieren:
Delphi-Quellcode:
Dann funzt 32bit und 64bit ... Ohne die Umstellung funzt nur {$Mode Delphi}... aber nur als 32bit-EXE...
Function SearchCallback(Wnd: HWND; lParam: PtrInt): BOOL; StdCall;
Var ClassName: Array[0..255] Of Char; Begin Try If GetClassName(Wnd, ClassName, 255) > 0 Then Begin If Pos('CabinetWClass', String(ClassName)) <> 0 Then slFoundWnd.Add(IntToStr(Wnd)); End; Result:= True; Except On E: Exception Do ErrorLog('SearchCallback'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure SearchWnd; Begin Try EnumWindows(@SearchCallback, 0); Except On E: Exception Do ErrorLog('SearchWnd'+#13#10+E.ClassName+#13#10+E.Message); End; End; EDIT: Uses Interfaces; // oder man compiliert nur mit FPC und läßt den Overkill weg... |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Es funktioniert mit SetForegroundWindow und Win + Left / Win + R übrigens, ich habe den Quelltext gestern Abend kurz statt MoveWindow eingesetzt. Allerdings geht es erst einmal nur mit einem Sleep(1000) zwischen den Schritten, das scheint daran zu liegen, dass Windows 10 bei der Tastenkombi die anderen Fenster als Vorschlag anzeigt, damit man nur das Fenster für die andere Seite anklicken muss.
Vielleicht lässt sich das auch lösen, indem man mit GetForegroundWindow prüft wann das passende Fenster wirklich den Fokus hat. |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
So geht's am besten:
"StartTwoWinEx" gekürzt und WorkArea selber eingebaut, so braucht man "Forms" nicht einbinden und die EXE ist kleiner (90,5 kb statt 362 kb). Jetzt kann man das Programm mit Delphi7 kompilieren und mit Lazarus und mit FreePascal (Einfach in Lazarus "Project".."Neues Project".. "Einfaches Programm" öffnen und {$APPTYPE GUI} eingeben und LongInt ersetzen mit PtrInt. Ohne LCL und LCLBase bekommt die EXE dann folgende Grösse: 32bit = 246 kb, 64bit = 335 kb; In den Projekt-Einstellungen Win32App-Box deaktivieren. Die D7-EXE ist natürlich schwer zu schlagen... es sei denn man nimmt API-Only oder KOL... :)
Delphi-Quellcode:
@ jaenicke:
PROGRAM TwoWinEx;
//{$APPTYPE GUI} //nur für FPC (Kein cmd-Fenster) USES Windows, Messages, Classes, SysUtils, ShellApi; VAR slFoundWnd: TStringlist; WndHandle : THandle; I : Integer; Procedure ErrorLog(ErrorInfo: String); Var slLoad : TStringlist; slSave : TStringlist; strErrorLog: String; Procedure Free_slLoad; Begin Try FreeAndNil(slLoad); Except End; End; Procedure Free_slSave; Begin Try FreeAndNil(slSave); Except End; End; Function ErrorLogExists: Boolean; Begin Try Result:= False; If FileExists('ErrorLog.txt') Then Begin Try slLoad:= TStringlist.Create; slLoad.LoadFromFile('ErrorLog.txt'); strErrorLog:= slLoad.Text; Result:= True; Finally Free_slLoad; End; End; Except End; End; Begin Try Try slSave:= TStringlist.Create; slSave.Add(DateTimeToStr(Now)); slSave.Add(ErrorInfo); If ErrorLogExists Then Begin slSave.Add(' '); slSave.Add(Trim(strErrorLog)); End; slSave.SaveToFile('ErrorLog.txt'); Finally Free_slSave; End; Except End; End; Function SearchCallback(Wnd: HWND; lParam: LongInt): BOOL; StdCall; //FPC: PtrInt Var ClassName: Array[0..255] Of Char; Begin Try If GetClassName(Wnd, ClassName, 255) > 0 Then Begin If Pos('CabinetWClass', String(ClassName)) <> 0 Then slFoundWnd.Add(IntToStr(Wnd)); End; Result:= True; Except On E: Exception Do ErrorLog('SearchCallback'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure SearchWnd; Begin Try EnumWindows(@SearchCallback, 0); Except On E: Exception Do ErrorLog('SearchWnd'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure MinAllWnds; Begin Try Keybd_event(VK_LWIN, 0, 0, 0); Keybd_event(Byte('M'), 0, 0, 0); Keybd_event(Byte('M'), 0, KEYEVENTF_KEYUP, 0); Keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0); Except On E: Exception Do ErrorLog('MinAllWnds'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure StartTwoWinEx; Var Path1, Path2: String; WorkArea : TRect; Begin Try If DirectoryExists('I:\') And DirectoryExists('I:\(DOWNLOADS)') Then Begin Path1:= 'I:\'; Path2:= 'I:\(DOWNLOADS)'; End Else Begin Path1:= 'C:\'; Path2:= 'D:\'; End; ShellExecute(0, Nil, PChar(Path1), Nil, Nil, SW_SHOW); ShellExecute(0, Nil, PChar(Path2), Nil, Nil, SW_SHOW); Repeat slFoundWnd.Clear; SearchWnd; Until slFoundWnd.Count >= 2; SystemParametersInfo(SPI_GETWORKAREA, 0, @WorkArea,0) ; MoveWindow(StrToInt(slFoundWnd[0]), WorkArea.Left, WorkArea.Top, ((WorkArea.Right-WorkArea.Left) Div 2), (WorkArea.Bottom-WorkArea.Top), True); MoveWindow(StrToInt(slFoundWnd[1]), ((WorkArea.Right-WorkArea.Left) Div 2), WorkArea.Top, ((WorkArea.Right-WorkArea.Left) Div 2), (WorkArea.Bottom-WorkArea.Top), True); Except On E: Exception Do ErrorLog('StartTwoWinEx'+#13#10+E.ClassName+#13#10+E.Message); End; End; Procedure Free_slFoundWnd; Begin Try FreeAndNil(slFoundWnd); Except On E: Exception Do ErrorLog('Free_slFoundWnd'+#13#10+E.ClassName+#13#10+E.Message); End; End; Begin Try slFoundWnd:= TStringlist.Create; Try SearchWnd; If slFoundWnd.Count >= 1 Then Begin For I:= 0 To slFoundWnd.Count-1 Do Begin WndHandle:= StrToInt(slFoundWnd[I]); SendMessage(WndHandle, WM_CLOSE, 0, 0); End; End; MinAllWnds; StartTwoWinEx; Finally Free_slFoundWnd; End; Except On E: Exception Do ErrorLog('MAIN PRG'+#13#10+E.ClassName+#13#10+E.Message); End; End. "Sleep 1000" ist zwar nicht die Ewigkeit, aber besser wäre natürlich ohne... "MoveWindow" ist doch uralt oder? Das hatten doch schon die ersten Win9x-Versionen im Programm?? Ist doch gar nicht schlecht wenn man das überall verwenden kann. Ich probier jetzt nochmal "SetForegroundWindow" und Restore & Co. .. mal sehen wie das optisch wirkt... (mal ohne MinAllWnds). |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
Zitat:
Beim von Luckie schon angesprochenen kontraproduktivem Auslagern von
Delphi-Quellcode:
in eine extra Methode platzierst du beispielsweise einen leeren try..except Block, der niemals greifen kann. Deine StringList erzeugst du ja vorher schon in einem try..finally Resourcen-Schutzblock. Sprich: Die List ist auf jeden Fall erstellt, also kann
FreeAndNil
Delphi-Quellcode:
gar nicht fehlschlagen. Dass
Free
Delphi-Quellcode:
hier unnötigt ist, hat Luckie ja auch schon erwähnt. Konkret wäre dies die korrekte Herangehensweise:
FreeAndNil
Delphi-Quellcode:
Andere Stelle:
SL := TStringList.Create;
try // .. finally SL.Free; end; ![]() Dann sind an einigen Stellen die Resourcen-Schutzblöcke falsch positioniert. Die
Delphi-Quellcode:
Funktion sollte beispielsweise eher so aussehen:
ErrorLogExists
Delphi-Quellcode:
Also erst die StringList erzeugen und dann den Resourcen-Schutzblock mit
function ErrorLogExists: Boolean;
begin Result := false; if FileExists('ErrorLog.txt') then begin slLoad := TStringlist.Create; try slLoad.LoadFromFile('ErrorLog.txt'); strErrorLog := slLoad.Text; Result := true; finally slLoad.Free; end; end; end;
Delphi-Quellcode:
einleiten. Wichtig ist, dass das
try
Delphi-Quellcode:
nicht mit im Block ist, sonst ist nicht garantiert, dass das
Create
Delphi-Quellcode:
im finally Block funktioniert.
Free
Dieser Artikel könnte für dich auch noch interessant sein: ![]() |
AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
@Zacherl:
Ja, du hast ja Recht.... Hab' die ganze Procedure neu gebaut und jetzt ist sie viel besser:
Delphi-Quellcode:
Natürlich ist da immer noch zu viel TryExceptEnd (was ich generell zu übertrieben benutze..) drin... ich brauche halt nur 'nen ErrorLog und möchte weiter nichts sehen...
Procedure ErrorLog(ErrorInfo: String);
Var slSave: TStringlist; Begin Try slSave:= TStringlist.Create; Try If FileExists('ErrorLog.txt') Then Begin Try slSave.LoadFromFile('ErrorLog.txt'); Except End; End; slSave.Text:= DateTimeToStr(Now)+#13#10+ ErrorInfo+#13#10+ ''+#13#10+ slSave.Text; slSave.SaveToFile('ErrorLog.txt'); Finally slSave.Free; End; Except End; End; Danke für die Info mit der Windows-Api... hab' nie groß darüber nachgedacht... Warum ich das nicht gleich gesehen hab' weiß der Kuckuck... EDIT: Ok, das TryExceptEnd hinter Finally ist wirklich quatsch.... (Warum sollte es beim Speicherfreigeben Probleme geben... wahrscheinlich unwahrscheinlich :-)). Der erste generelle TryExceptEnd-Block sichert das SaveToFile... (und das Erstellen der Stringlist, wenn ich auch nicht wüßte was da schiefgehen sollte..) hat also zumindest einen Sinn... |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19:23 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