Einzelnen Beitrag anzeigen

FarAndBeyond
(Gast)

n/a Beiträge
 
#28

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren

  Alt 6. Jul 2016, 00:26
Finally ....

Ich hab's !!! Man kann den Windows-Explorer doch völlig problemlos positionieren mit "MoveWindow" und das Ganze ohne "Sleep".
Zuerst hatte ich an zwei Stellen "Sleep(10)", dachte das wäre notwendig, aber wenn ich das weglasse funzt es genauso.
Also weg damit... nicht das 20ms irgend eine Rolle gespielt hätten...

Und wo liegt jetzt die Magie???

Here it comes: ...and the winner is:
"die Repeat-Schleife" ... gepriesen sei die heilige Repeat-Schleife für ihre Existenz...
Delphi-Quellcode:
Repeat
 slFoundWnd.Clear;
 FindAllWindows('','CabinetWClass');
Until slFoundWnd.Count >= 2;
Das die Lösung so einfach ist hätte mir ruhig mal einer von euch "stecken" können... ... den Wald vor lauter Bäumen...

Und hier das ganze Ding:
Da mir das BringToFront mit "Minimize" und "Restore" zu nervig war hab' ich einfach alles weggelassen und lösche jetzt einfach immer alle Fenster. Somit gibt es nur noch eine Prozedur "StartTwoWinEx"... ist auch gleich viel übersichtlicher... Ich brauche eh nur zwei Fenster...

Jetzt kann man die beiden Windows-Explorer-Fenster drehen, biegen, zerknüddeln... ohne das sich irgendwas an der erneuten Darstellung ändert. Schon beim nächsten Klick auf den QuickLaunch-Button sieht alles wieder sauber und gerade aus (bildschirmfüllend) und ich brauche die TaskbarButton überhaupt nicht mehr benutzen... sehr schön ...
Delphi-Quellcode:
PROGRAM TwoWindowsExplorer;

 USES
  Windows, Messages, Classes, Forms, SysUtils, ShellApi;

 TYPE
  PFindWindowStruct = ^TFindWindowStruct;
  TFindWindowStruct = Record
   Caption : String;
   ClassName : String;
   WindowHandle: THandle;
  End;

 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 EnumWindowsProc(hWindow: HWND; lParam: LongInt): Boolean; StdCall;
  Var
   lpBuffer : PChar;
   WindowCaptionFound: Boolean;
   ClassNameFound : Boolean;

  Procedure Free_Memory;
   Begin
    Try
     FreeMem(lpBuffer, SizeOf(lpBuffer^));
    Except
     On E: Exception
     Do ErrorLog('EnumWindowsProc: Free_Memory'+#13#10+E.ClassName+#13#10+E.Message);
    End;
   End;

 Begin
  Try
   GetMem(lpBuffer, 255);
   Result := True;
   WindowCaptionFound:= False;
   ClassNameFound := False;
   Try
    If GetWindowText(hWindow, lpBuffer, 255) > 0
    Then
     Begin
      If PFindWindowStruct(lParam).Caption = ''
      Then WindowCaptionFound:= True
      Else
       Begin
        If Pos(PFindWindowStruct(lParam).Caption, StrPas(lpBuffer)) > 0
        Then WindowCaptionFound:= True;
       End;

      If PFindWindowStruct(lParam).ClassName = ''
      Then ClassNameFound:= True
      Else
       Begin
        If GetClassName(hWindow, lpBuffer, 255) > 0
        Then
         Begin
          If Pos(PFindWindowStruct(lParam).ClassName, StrPas(lpBuffer)) > 0
          Then ClassNameFound:= True;

          If (WindowCaptionFound And ClassNameFound)
          Then
           Begin
            PFindWindowStruct(lParam).WindowHandle:= hWindow;
            slFoundWnd.Add(IntToStr(hWindow));
           End;
         End;
       End;
     End;
   Finally
    Free_Memory;
   End;
  Except
   On E: Exception
   Do ErrorLog('EnumWindowsProc'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Function FindAllWindows(WinCaption: String; WinClassName: String): THandle;
  Var
   WindowInfo: TFindWindowStruct;
 Begin
  Try
   WindowInfo.Caption := WinCaption;
   WindowInfo.ClassName := WinClassName;
   WindowInfo.WindowHandle:= 0;

   EnumWindows(@EnumWindowsProc, LongInt(@WindowInfo));
   Result:= WindowInfo.WindowHandle;
  Except
   On E: Exception
   Do ErrorLog('FindAllWindows'+#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;
       FindAllWindows('','CabinetWClass');
       // Sleep(10);
      Until slFoundWnd.Count >= 2;

       // Sleep(10);
     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;
       FindAllWindows('','CabinetWClass');
      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
    FindAllWindows('','CabinetWClass');
     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;
    StartTwoWinEx;
   Finally
    Free_slFoundWnd;
   End;
 Except
  On E: Exception
  Do ErrorLog('MAIN PRG'+#13#10+E.ClassName+#13#10+E.Message);
 End;
End.
Getestet mit D7 und W7x64 Sp1...
Auf älteren Lazarus-Versionen lieft das im Delphi-Mode sehr gut, aber Version 1.6 mag den PFindWindowStruct TypeCast 4->8 wohl nicht... Wenn ich auch noch nicht kapiert hab' was der Compiler damit eigentlich meint... egal das finde ich auch noch 'raus...

Natürlich kann man das Ganze auch umbauen auf 4 oder 8 oder 150 Mio Fenster.... (Wer hätte das gedacht...)

Ach ja, ich hatte keine Lust das übertriebene Exception-Handling zu löschen... Nein.. niemand muß das so nachmachen...
Ich wußte das geht irgendwie und ich wußte ich krieg' das hin... hahaha....

Hat jemand von euch Lust das mal unter W8 oder W10 zu testen... Verhält sich der Explorer dort genauso ???
Muß auch nicht unbedingt, ich bin nur neugierig...
  Mit Zitat antworten Zitat