Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren (https://www.delphipraxis.net/185596-zwei-windows-explorer-starten-und-nebeneinander-bildschirmfuellend-positionieren.html)

FarAndBeyond 23. Jun 2015 04:41

Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Hi Leute,

für alle die wie ich Delphi/Lazarus Newbie und ProgrammierNewbie sind...
So kann man mit einem Klick zwei WindowsExplorer starten und nebeneinander anordnen.

Einfach irgendwo hinlegen und den Pfad in die Verknüpfung schreiben.. Ach was? JaJa
Ob das jetzt der ultimativ beste Weg ist wage ich mal zu bezweifeln... grins...

Delphi-Quellcode:
Unit ShowTwoWindowsExplorer;

Interface

 Uses
  Windows, Messages, SysUtils, Classes, Controls, Forms, ShellApi;

 Type
  TForm1 = Class(TForm)
    Procedure FormCreate(Sender: TObject);
    Procedure FormActivate(Sender: TObject);
    Procedure FormShow(Sender: TObject);

   Private
    Procedure WMSysCommand(Var Message: TWMSysCommand); Message WM_SysCommand;
   End;

 Var
  Form1: TForm1;

Implementation
 {$R *.dfm}

// Yes, this is optional or certainly overkill...  hahaha...
Procedure TForm1.WMSysCommand(var Message: TWMSysCommand);
 Begin
  Try
   If Message.CmdType And $FFF0 = SC_MINIMIZE
   Then
    Form1.Hide
   Else
    Inherited;
  Except
   Exit;
  End;
 End;


Procedure TForm1.FormCreate(Sender: TObject);
   Var hwnd_Explorer : HWND;
 Begin
  Try
   Form1.Height := 1;
   Form1.Width := 1;
   Form1.Top   := 0;
   Form1.Left  := 0;
   Form1.AlphaBlend     := True;
   Form1.AlphaBlendValue := 0;

   If DirectoryExists('I:\')
   Then
    Begin
     ShellExecute(Form1.Handle, Nil, PChar('I:\MARTIN\(DOWNLOADS)'), Nil, Nil, SW_SHOW);
     hwnd_Explorer := FindWindow(Nil, 'I:\MARTIN\(DOWNLOADS)');
     MoveWindow(hwnd_Explorer, 0, 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
     SetWindowPos(hwnd_Explorer, HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE);

     ShellExecute(Form1.Handle, Nil, PChar('I:\MARTIN'), Nil, Nil, SW_SHOW);
     hwnd_Explorer := FindWindow(Nil, 'I:\MARTIN');
     MoveWindow(hwnd_Explorer, (Screen.Width div 2), 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
     SetWindowPos(hwnd_Explorer, HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE);
    End
   Else
    Begin
     ShellExecute(Form1.Handle, Nil, PChar('C:\'), Nil, Nil, SW_SHOW);
     hwnd_Explorer := FindWindow(Nil, 'C:\');
     MoveWindow(hwnd_Explorer, 0, 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
     SetWindowPos(hwnd_Explorer, HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE);

     ShellExecute(Form1.Handle, Nil, PChar('D:\'), Nil, Nil, SW_SHOW);
     hwnd_Explorer := FindWindow(Nil, 'D:\');
     MoveWindow(hwnd_Explorer, (Screen.Width div 2), 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
     SetWindowPos(hwnd_Explorer, HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE);
    End;
  Except
   Exit;
  End;
 End;


Procedure TForm1.FormShow(Sender: TObject);
   Var Owner: HWND;
 Begin
  Try
   Owner := GetWindow(Form1.Handle, GW_OWNER);
   ShowWindow(Owner, SW_HIDE);
  Except
   Exit;
  End;
 End;


Procedure TForm1.FormActivate(Sender: TObject);
 Begin
  Try
   Close;
  Except
   FreeAndNil(Form1);
   Exit;
  End;
 End;

End.
Kann man natürlich auch als KonsolenAnwendung erstellen, aber dann muß man das Konsolenfenster ausblenden.
Ist also wahrscheinlich schon egal oder Geschmacksache oder was auch immer...

Ich bin froh, dass das funktioniert und frage mich warum ich das nicht schon früher benutzt habe.
Obwohl Windows7 das (Downloads)-Verzeichnis immer rechts zeigt... sollte eigentlich laut QuellCode links liegen, aber
vielleicht liegt das auch an der Uhrzeit... Ich seh' den Wald vor lauter Bäumen nicht mehr.... grins...
Hat 'ne Weile gedauert bis ich die Sleep(50)-Befehle herausnehmen konnte... Ich hab' SW_ShowNormal statt SW_Show
benutzt und das ging nur mit Sleep und jetzt weis ich auch warum...

Alle bis jetzt ausprobierten Explorer (DoubleCommander, SpeedCommander, TotalCommander, FreeCommander..) starten
deutlich langsamer als der WindowsExplorer und zeigen auch nicht gleichzeitig Details und Bilder an.
Ok, die werden natürlich weiterentwickelt.. vielleicht kann der eine oder andere das ja mittlerweile doch...

Ich bin müde... zugegeben ich wollte nur mal sehen wie man etwas posted...
Ist das überhaupt das richtige Themegebiet ? Na ja, ist vielleicht auch egal...

Weiterhin viel Spaß und gute Unterhaltung...
Gruß Martin

hathor 23. Jun 2015 10:22

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

Jedem Window ein eigenes Handle.
SetWindowPos ist überflüssig.
Ohne Sleep geht es bei mir nicht.
DirectoryExists immer anwenden.
WINDOWS ist - wie üblich - verwirrend:
Pfadname: C:\Users\HATHOR\Documents
Window-Title: Dokumente

Delphi-Quellcode:
   Var hwnd_Explorer1, hwnd_Explorer2 : HWND;

   If DirectoryExists('C:\Users\HATHOR\Documents') then
   BEGIN
     ShellExecute(Form1.Handle, Nil, PChar('C:\Users\HATHOR\Documents'), Nil, Nil, SW_SHOW);
        Application.ProcessMessages; Sleep(500);
     hwnd_Explorer1 := FindWindow(Nil, 'Dokumente');
     MoveWindow(hwnd_Explorer1, 0, 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
//     SetWindowPos(hwnd_Explorer1, HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE);
   END;
//
   If DirectoryExists('F:\TOOLS') then
   BEGIN
     ShellExecute(Form1.Handle, Nil, PChar('F:\TOOLS'), Nil, Nil, SW_SHOW);
        Application.ProcessMessages; Sleep(500);
     hwnd_Explorer2 := FindWindow(Nil, 'F:\TOOLS');
     MoveWindow(hwnd_Explorer2, (Screen.Width div 2), 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
//     SetWindowPos(hwnd_Explorer2, HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE);
   END;
Das ganze lässt sich vereinfachen - mehr braucht man nicht, wenn das Programm sonst nichts tut:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
Var hwnd_Explorer1, hwnd_Explorer2 : HWND;
begin
   If DirectoryExists('C:\Users\HATHOR\Documents') then
   BEGIN
     ShellExecute(Form1.Handle, Nil, PChar('C:\Users\HATHOR\Documents'), Nil, Nil, SW_SHOW);
        Application.ProcessMessages; Sleep(500);
     hwnd_Explorer1 := FindWindow(Nil, 'Dokumente');
     MoveWindow(hwnd_Explorer1, 0, 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
   END;
   If DirectoryExists('F:\TOOLS') then
   BEGIN
     ShellExecute(Form1.Handle, Nil, PChar('F:\TOOLS'), Nil, Nil, SW_SHOW);
        Application.ProcessMessages; Sleep(500);
     hwnd_Explorer2 := FindWindow(Nil, 'F:\TOOLS');
     MoveWindow(hwnd_Explorer2, (Screen.Width div 2), 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
   END;
Application.Terminate;
end;

mm1256 23. Jun 2015 19:12

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

die Idee als solches finde ich ja gut. Die Zähne beisse ich mir aber schon seit über einer Stunde daran aus, das "Sleep" zu ersetzen, weil es ja hardwareabhängig ist.

Der Grundgedanke ist, aus dem ProcessHandle das WindowHandle zu bekommen.

Delphi-Quellcode:
function ShellExecExplorer(aClientHandle: THandle;
                           aParameters: string;
                           var aExplorerHandle: THandle): Boolean;
var
  SEI: TShellExecuteInfo;
begin
  aExplorerHandle := 0;
  FillChar(SEI, SizeOf(SEI), #0);
  SEI.cbSize := SizeOf(SEI);
  SEI.Wnd := aClientHandle;
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  SEI.lpVerb := 'open';
  SEI.lpFile := PChar('explorer.exe');
  SEI.lpParameters := PChar(aParameters);
  SEI.lpDirectory := nil;
  SEI.nShow := SW_SHOWNORMAL;
  Result := ShellExecuteEx(@SEI);
  if Result then begin
    if SEI.hProcess > 32 then begin
      Sleep(1000);
       // WaitForInputIdle(SEI.hProcess, INFINITE); hab ich probiert, tut nicht
    end;
  end;
  CloseHandle(SEI.hProcess);
end;
Vielleicht hat ja jemand eine Idee?

BUG 23. Jun 2015 19:39

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

Zitat von mm1256 (Beitrag 1306319)
das "Sleep" zu ersetzen, weil es ja hardwareabhängig ist.

Was meinst du damit bzw. wo ist das Problem?

mm1256 23. Jun 2015 20:15

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Wenn die Explorer-Instanz nicht innerhalb der Sleep-Zeit gestartet wird, findet FindWindow kein Handle und folglich funzt auch MoveWindow nicht.

In der Zwischenzeit hab ich noch etwas rum gespielt. Schön wär es auch, wenn eine bereits vorhandene Instanz angezeigt und neu positioniert würde. Je länger ich daran "spiele" umso mehr gefällt mir der Gedanke.

Aktueller Stand (ist noch nicht fertig)

Delphi-Quellcode:
const
  TC = ' | ';

function ShellExecExplorer(aClientHandle: THandle;
                           aParameters: string;
                           var aExplorerHandle: THandle): Boolean;
var
  SEI: TShellExecuteInfo;
begin
  aExplorerHandle := 0;
  FillChar(SEI, SizeOf(SEI), #0);
  SEI.cbSize := SizeOf(SEI);
  SEI.Wnd := aClientHandle;
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  SEI.lpVerb := 'open';
  SEI.lpFile := PChar('explorer.exe');
  SEI.lpParameters := PChar(aParameters);
  SEI.lpDirectory := nil;
  SEI.nShow := SW_SHOWNORMAL;
  Result := ShellExecuteEx(@SEI);
  if Result then begin
    if SEI.hProcess > 32 then begin
      Sleep(1000);
//      WaitForInputIdle(SEI.hProcess, 2000{ INFINITE});
    end;
  end;
  CloseHandle(SEI.hProcess);
end;

function EnumWindowsProc(aHandle: HWND; aLST: TStrings): Bool; stdcall; export;
var
  Caption, ClassName: array[0..MAX_PATH] of Char;
begin
  Result := True;
  if IsWindowVisible(aHandle) then begin
    GetClassName(aHandle, ClassName, MAX_PATH);
    if SameText(string(ClassName),'CabinetWClass') then begin
      GetWindowText(aHandle, Caption, MAX_PATH);
      aLST.Add(IntToStr(aHandle)+TC+UpperCase(string(Caption)));
    end;
  end;
end;

function JustDirectory(aDirectory: string): string;
var
  p: integer;
begin
  if (Pos(':',aDirectory) = 0) AND
     (Pos('\',aDirectory) = 0) AND
     (Pos('.',aDirectory) = 0)
  then Exit(aDirectory);
  Result := ExtractFileDir(aDirectory);
  p := Pos(':',Result);
  if p = 0 then exit;
  if Length(Result) <= 3 then SetLength(Result,1) else begin
    Delete(Result,1,3);
    p := Pos('\',Result);
    while p > 0 do begin
      Delete(Result,1,p);
      p := Pos('\',Result);
    end;
  end;
end;

function GetExplorerHandle(aCaption: string): THandle;
var
  i, p: integer;
  LST: TStrings;
begin
  Result := 0;
  LST := TStringList.Create;
  try
    EnumWindows(@EnumWindowsProc, Integer(LST));
    aCaption := UpperCase(JustDirectory(aCaption));
    for i := 0 to Pred(LST.Count) do begin
      if Pos(aCaption, LST[i]) > 0 then begin
        p := Pos(TC,LST[i]) - 1;
        Result := StrToIntDef(Copy(LST[i],1,p),0);
        Break;
      end;
    end;
  finally
    LST.Free;
  end;
end;

procedure WinExplorerStart(aClientHandle: THandle;
                           aLeftFileNameOrDirectory,
                           aRightFileNameOrDirectory : string);
var
  ExplorerHandle: THandle;

  procedure ShowExplorer(aHandle: THandle);
  var
    ForegroundWindowThreadID : Dword;
    WindowThreadID : DWord;
  begin
    if aHandle = GetForegroundWindow then exit;
    ForegroundWindowThreadID := GetWindowThreadProcessId(GetForegroundWindow, nil);
    WindowThreadID := GetWindowThreadProcessId(aHandle, nil);
    if (ForegroundWindowThreadID <> WindowThreadID) then begin
      AttachThreadInput(ForegroundWindowThreadID, WindowThreadID, true);
      SetForegroundWindow(aHandle);
      AttachThreadInput(ForegroundWindowThreadID, WindowThreadID, false);
    end else SetForegroundWindow(aHandle);
    ShowWindow(aHandle, SW_RESTORE);
  end;


  function Start(aCmdLine: string): boolean;
  begin
    Result := false;
    ExplorerHandle := GetExplorerHandle(JustDirectory(aCmdLine));
    if ExplorerHandle = 0 then begin
      if FileExists(aCmdLine)
      then aCmdLine := '/select,' + aCmdLine
      else begin
        aCmdLine := ExcludeTrailingBackslash(aCmdLine);
        // if not DirectoryExists(aCmdLine) then exit;
        // => keine gute Idee weil z.B. "Dokumente" oder "Dieser PC"
        // nicht funktioniert
      end;
      ShellExecExplorer(aClientHandle, aCmdLine, ExplorerHandle);
      ExplorerHandle := GetExplorerHandle(JustDirectory(aCmdLine));
    end else ShowExplorer(ExplorerHandle);
    Result := ExplorerHandle > 0;
  end;

begin
  if Start(aLeftFileNameOrDirectory)
  then MoveWindow(ExplorerHandle, 0, 0, (Screen.Width div 2), Screen.WorkAreaHeight, True);
  if Start(aRightFileNameOrDirectory)
  then MoveWindow(ExplorerHandle, Screen.Width div 2, 0, Screen.Width div 2, Screen.WorkAreaHeight, True);
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
  WinExplorerStart(Handle,'C:\Windows', 'Dokumente');
end;

DeddyH 23. Jun 2015 20:44

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Nur so ein paar Ideen: wenn Du doch eh schon ShellExecuteEx verwendest, hast Du doch auch das Prozesshandle. Das könntest Du erstens dazu benutzen, um mit WaitForInputIdle darauf zu warten, dass der Prozess "befehlsbereit" ist, zum anderen dazu, mit EnumWindows und GetWindowThreadProcessId (oder ähnlichen Funktionen) das oder die Fenster zu ermitteln, die zum gerade gestarteten Prozess gehören (dürfte ja eigentlich nur ein Top-Level-Window je Explorer-Instanz sein, wenn ich keinen Denkfehler mache). Und das passt Du dann eben entsprechend an.

mm1256 23. Jun 2015 21:09

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
"WaitForInputIdle" hab ich ja schon versucht, siehe Kommentar, aber das kommt sofort zurück.

Die grundsätzliche Idee die hinter der Verwendung von ShellExecuteEx steckt ist ja, über das Processhandle auf das WindowHandle zu kommen. Aber wie? Da fehlt mir leider das Basiswissen.

Na ja, wenn es nicht geht, auch nicht schlimm. Ist kein Pflichtprojekt :)

hathor 23. Jun 2015 23:11

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Andere Version - aber die Version in #2 gefällt mir besser...

Delphi-Quellcode:
Function CallFileName( pFileName, pParameter : PChar): THandle;
var SEI: TShellExecuteInfo;
begin
 FillChar(SEI, SizeOf(SEI), 0);
 SEI.cbSize      := SizeOf(SEI);
 SEI.fMask       := SEE_MASK_NOCLOSEPROCESS;
 SEI.Wnd         := GetTopWindow(0);
 SEI.lpVerb      := 'OPEN';
 SEI.lpFile      := pFileName;
 SEI.lpParameters := pParameter;
 SEI.lpDirectory := '';
 SEI.nShow       := SW_SHOWNORMAL;
 SEI.hInstApp    := 0;
 SEI.hProcess    := 0;

 ShellExecuteEx( @SEI );
 Sleep(500);
 Result := SEI.hProcess;
end;

procedure TForm1.Button1Click(Sender: TObject);
var tmpHandle : THandle;
begin
  tmpHandle :=CallFileName(PChar('Explorer.exe'), PChar('F:\TOOLS'));
  MoveWindow(GetForegroundWindow, 0, 0,(Screen.Width div 2), Screen.WorkAreaHeight, True);

  tmpHandle :=CallFileName(PChar('Explorer.exe'), PChar('C:\'));
  MoveWindow(GetForegroundWindow, Screen.Width div 2, 0,(Screen.Width div 2), Screen.WorkAreaHeight, True);
end;

FarAndBeyond 24. Jun 2015 00:24

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Hey, danke für die Antworten und Tipps...
hab' gerade erst wieder etwas Zeit...

@Hathor: Ja das mit dem Handle sollte man wahrscheinlich immer sauber machen, auch wenn es in diesem Beispiel scheinbar egal ist. SetWindowPos hab' ich nur benutzt um das Delphi7 Programm daran zu hindern in den Vordergrund zu kommen nach dem Close in OnActivate. Hab's dann drin gelassen...
Ich glaub' ShellExecute kontrolliert auch das Verzeichnis, aber ich hab' nie ausprobiert welche Reaktion ich dann bekomme wenn ein Verzeichnis nicht ansprechbar ist. Selbst zu prüfen ist wohl auch sauberer. Muß deine letzte Variante gleich mal testen... Zum Thema Windows: Nach ein wenig herumspielen mit Lazarus geht meine kompilierte D7-EXE nicht mehr...
Ich glaub' das jetzt echt nicht... auch nach einem Neustart funktioniert nur noch das Aufrufen, aber nicht mehr das Positionieren. Zumal mir Lazarus 'ne 14.3 MB EXE gebaut hat????
Na ja, ich fang' gerade erst an mit Lazarus, hab' wohl was falsches eingegeben, dachte mir 362 KB ist schon groß genug (D7). Wer es kleiner mag muß wohl KOL oder ASM nehmen.
Aber die Grösse auf der Platte ist nicht so wichtig, die Grösse im RAM ist wichtig...

@mm1256: Danke, einiges aus deinem QuellCode kann ich sicherlich in anderen Projekten verwenden... zumindest wenn ich das mal alles kapiert hab'...
Ich wollte jetzt eigentlich mal CreateProcess + WaitForInputIdle testen, da ich das noch nie benutzt habe, aber nachdem das bei dir nichts gebracht hat, kann ich mir das wohl sparen. Mann ich hab' meine D7-EXE auf meinem mobilen CORE i7 mit ca. 13GB freiem RAM schon 'ne Weile benutzt und gerade ohne Sleep ging das echt geschmeidig und sehr praktisch...
Jetzt nach dem Lazarus Test geht es überhaupt nicht mehr. Windows 7 ist da wohl sehr eigen.. sehr viel mehr als ich vermutet hatte....

Ich war gerade angefangen zu lernen wie ich eine eigene Komponente baue.. TPngForm. Zwecks alphablended translucency... Mann damit kann man ja Sachen bauen... der Hammer (SetWindowLong, UpdateLayeredWindow)... Das haut einem ja den Hintern weg... DAS ROCKT !!! Damit kann ich statt TLabel-Text jetzt jeden HighEnd Text benutzen... Bin gespannt wie lange die CPU braucht von String nach Png...

Jetzt muß ich erstmal den doppelten Explorer wieder zurückbekommen, ich hatte mich schon so daran gewöhnt... Und dabei ist seit Windows 3.1 diese W7_64bit_SP1-Version das allerbeste was ich bis jetzt von MS unterm Hintern hatte... und wohl auch die letzte Version von MS, die ich benutzen werde...
Aber man soll ja nie NIE sagen...

BESTEN DANK NOCHMAL... ich werd' jetzt testen...

FarAndBeyond 27. Jun 2015 04:46

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Hi,
hier noch eine ganz einfache Möglichkeit ohne Sleep. Diese hat bis jetzt unter Windows 7 immer funktioniert.
Zwei einfache Schritte:

(1)
Man schreibt den Pfad zu der aus diesem Quellcode compilierten EXE ins Feld "Ziel" eines QuickLaunch Icons.

Delphi-Quellcode:
Unit ShowTwoWindowsExplorer;

Interface

 Uses
  Windows, Messages, SysUtils, Classes, Controls, Forms, ShellApi;


 Type
  TForm1 = Class(TForm)
    Procedure FormCreate(Sender: TObject);
    Procedure FormActivate(Sender: TObject);
    Procedure FormShow(Sender: TObject);

   Private

   End;

 Var
  Form1: TForm1;

Implementation
 {$R *.dfm}

Procedure TForm1.FormCreate(Sender: TObject);
 Begin
  Try
   Form1.Height := 1;
   Form1.Width := 1;
   Form1.Top   := 0;
   Form1.Left  := 0;
   Form1.AlphaBlend     := True;
   Form1.AlphaBlendValue := 0;

   If DirectoryExists('I:\')
   Then
    Begin
     ShellExecute(Form1.Handle, Nil, PChar('I:\MARTIN'), Nil, Nil, SW_SHOW);
     ShellExecute(Form1.Handle, Nil, PChar('I:\MARTIN\(DOWNLOADS)'), Nil, Nil, SW_SHOW);
    End
   Else
    Begin
     ShellExecute(Form1.Handle, Nil, PChar('C:\'), Nil, Nil, SW_SHOW);
     ShellExecute(Form1.Handle, Nil, PChar('D:\'), Nil, Nil, SW_SHOW);
    End;
  Except
   Exit;
  End;
 End;


Procedure TForm1.FormShow(Sender: TObject);
   Var Owner: HWND;
 Begin
  Try
   Owner := GetWindow(Form1.Handle, GW_OWNER);
   ShowWindow(Owner, SW_HIDE);
  Except
   Exit;
  End;
 End;


Procedure TForm1.FormActivate(Sender: TObject);
 Begin
  Try
   Close;
  Except
   FreeAndNil(Form1);
   Exit;
  End;
 End;

End.
(2)
Man klickt auf das Explorer Icon und startet damit die EXE.
Von den beiden sich öffnenden Explorer-Fenstern schiebt man eins nach ganz rechts und eins nach ganz links, so dass diese sich automatisch bilschirmfüllend positionieren.
Jetzt verkleinert man beide Fenster gleichweit per Maus am oberen Rand um 1 oder 2 Pixel. Der untere Rand wird dabei von Windows 7 automatisch verkleinert.
Sollten beide nicht exakt nebeneinander erscheinen, dann einfach das tiefere Fenster an der Titelleiste nach oben verschieben.
Jetzt schließt man beide Fenster.

Das war's auch schon...

Für alle, die
- Windows 7 verwenden
- einen 21 oder 24 Zoll oder noch größeren Bildschirm benutzen
- per einfachem Klick zwei unterschiedliche Ordner angezeigt haben wollen mit Dateiansicht Detail und Bildvorschau
- die Position der Explorer-Fenster nur selten verändern
- sich nicht an den unteren fehlenden 4 Pixeln stören

Der Windows Explorer versucht ja mit aller Kraft seine letzte Position immer wieder einzunehmen und ob man das in der Registry deaktivieren kann oder auf Default Werte setzen kann, kann ich im Moment noch nicht sagen...

Da ich den Explorer ohne Verzeichnisbaum benutze und die Position eigentlich niemals verändere ist das die für mich schnellste und beste Möglichkeit bis jetzt...
Alle anderen wie QDir, SpeedCommander, DoubleCommander, TotalCommander, FreeCommander und Co. starten zu langsam um mal eben schnell was auch immer zu tun...
Zudem zeigt von denen keiner eine DETAILS-Ansicht und eine Bildvorschau.
Außerdem kann man sich natürlich auch zwei QuickLaunch Icons erstellen. Einmal ein Fenster und einmal zwei nebeneinander. Mit 4 Fenstern hab' ich das noch nicht probiert... grins

Gruß
Martin

mm1256 27. Jun 2015 07:51

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

also wenn ihr schon den Overhead mit einem eigenen Formular bzw. einer VCL-Anwendung gehen wollt, dann nimmt man einfach zwei (oder mehrere) Panels und klatscht da jeweils eine Explorer-Instanz hinein. Das ist nicht mehr als ein 2-Minuten-Programm. 8-)

In Beispiel ist Panel1.Align = alLeft und Panel2.Align = alClient.

Delphi-Quellcode:
unit uWinExplorer2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;

type
  TFrmExplorer2 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    procedure FormShow(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure ExplorerStart(aPanel: TPanel;
                            aDirectory: string);
  end;

var
  FrmExplorer2: TFrmExplorer2;

implementation

{$R *.dfm}

uses ShellApi;

procedure TFrmExplorer2.ExplorerStart(aPanel: TPanel;
                                      aDirectory: string);
var
  SEI: TShellExecuteInfo;
  Style: Integer;
begin
  aPanel.Caption := aDirectory;
  FillChar(SEI, SizeOf(SEI), #0);
  SEI.cbSize := SizeOf(SEI);
  SEI.Wnd := Handle;
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  SEI.lpVerb := 'open';
  SEI.lpFile := PChar('explorer.exe');
  SEI.lpParameters := PChar(aDirectory);
  SEI.lpDirectory := nil;
  SEI.nShow := SW_SHOWMAXIMIZED;
  if ShellExecuteEx(@SEI) then begin
    if SEI.hProcess > 32 then begin
      Sleep(500);
      aPanel.Tag := FindWindow('CabinetWClass',nil);
      if aPanel.Tag > 0 then begin
        Winapi.Windows.SetParent(aPanel.Tag, aPanel.Handle);
        Style := GetWindowLong(aPanel.Tag, GWL_STYLE);
        SetWindowLong(aPanel.Tag, GWL_STYLE, Style and NOT WS_BORDER );
      end;
    end;
  end;
  CloseHandle(SEI.hProcess);
end;

procedure TFrmExplorer2.FormResize(Sender: TObject);
begin
  Panel1.Width := ClientWidth div 2;
  if Panel1.Tag > 0 then MoveWindow(Panel1.Tag, 0, 0, Panel1.Width, Panel1.Height, True);
  if Panel2.Tag > 0 then MoveWindow(Panel2.Tag, 0, 0, Panel2.Width, Panel2.Height, True);
end;

procedure TFrmExplorer2.FormShow(Sender: TObject);
begin
  Caption := 'Windows-Explorer mit zwei Fenstern';
  ExplorerStart(Panel1,'C:\Windows');
  ExplorerStart(Panel2,'C:\Users');
end;

end.

hathor 27. Jun 2015 11:43

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

Delphi-Quellcode:
  SEI.nShow := SW_MINIMIZE;
macht den Bildaufbau ruhiger.

mm1256 27. Jun 2015 16:09

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

Zitat von hathor (Beitrag 1306823)
Vorschlag:

Delphi-Quellcode:
  SEI.nShow := SW_MINIMIZE;
macht den Bildaufbau ruhiger.

DANKE! :thumb:

Ein Problem gibt es noch: Die Explorerfenster haben beim Panel oben einen Rand etwa so hoch wie normalerweise die Titelleiste. Damit wollte ich den Rand eigentlich verhindern, aber irgendwas scheint noch zu fehlen. Hab schon rumprobiert, finde aber keine Lösung.

Delphi-Quellcode:
Style := GetWindowLong(aPanel.Tag, GWL_STYLE);
SetWindowLong(aPanel.Tag, GWL_STYLE, Style and NOT WS_BORDER );
Oder weigert sich der Explorer das anzunehmen?

mm1256 28. Jun 2015 07:16

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Hat keiner eine Idee? Wäre schön, wenn man diesen blöden Rand weg bekommen würde.

hathor 28. Jun 2015 07:59

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Das ist nicht der einzige Schönheitsfehler:

Die beiden Explorer-Instanzen bleiben im RAM als Leichen zurück und können nur im Task-Manager beendet werden.
Ich suche eine Lösung, evtl. mit CreateProcess/TerminateProcess.

mm1256 28. Jun 2015 11:14

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Richtig, da fehlt noch was. Aus dem Grund hab ich mir ja auch die Handles im TPanel.Tag gemerkt.

Delphi-Quellcode:
procedure TFrmExplorer2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Panel1.Tag > 0 then SendMessage(Panel1.Tag, WM_CLOSE, 0, 0);
  if Panel2.Tag > 0 then SendMessage(Panel2.Tag, WM_CLOSE, 0, 0);
end;
Mir unverständlich ist, dass die Explorer-Instanzen erst nach etwa 20 Sekunden aus dem Taskmanager verschwinden

hathor 30. Jun 2015 09:46

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Liste der Anhänge anzeigen (Anzahl: 3)
Zitat:

Zitat von mm1256 (Beitrag 1306925)
Hat keiner eine Idee? Wäre schön, wenn man diesen blöden Rand weg bekommen würde.

Mit Metro UI Tweaker (im Anhang) kriegt man Ribbon weg.
- > Disable Explorer Ribbon

markus5766h 8. Jul 2015 19:29

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Moin aus Hamburg.

Code:
procedure TFrmExplorer2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Panel1.Tag > 0 then SendMessage(Panel1.Tag, WM_CLOSE, 0, 0);
  if Panel2.Tag > 0 then SendMessage(Panel2.Tag, WM_CLOSE, 0, 0);
end;
... PostMessage scheint hier zuverlässiger zu sein.
Selbst nach mehrmaligen Starten werden alle Instanzen gelöscht,
bei SendMessage habe ich immer Leichen mit ca. 8Mb und 6 Threads im Taskmanager

hathor 8. Jul 2015 19:55

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Am Ende eines Programms sollte man immer PostMessage bevorzugen.
Ich habe es ausserdem in die Destroy-Procedure geschrieben.
Aber es dauert trotzdem lange, bis sie aus dem Task-Manager verschwinden.

Delphi-Quellcode:
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Panel1.Tag > 0 then PostMessage(Panel1.Tag, WM_CLOSE, 0, 0);
  if Panel2.Tag > 0 then PostMessage(Panel2.Tag, WM_CLOSE, 0, 0);
end;

markus5766h 8. Jul 2015 20:42

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

Aber es dauert trotzdem lange, bis sie aus dem Task-Manager verschwinden.
ja, stimmt, bei mir ca. 15 bis 20 Sekunden - aber zuverlässig.

hathor 15. Jul 2015 07:21

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Liste der Anhänge anzeigen (Anzahl: 2)
Nach dem gleichen Verfahren lassen sich auch 2 IEXPLORE.exe anzeigen.
Es sind nur geringe Änderungen erforderlich.

Delphi-Quellcode:
unit Unit1; //20150630  20150715

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Winapi.ShellApi, Vcl.StdCtrls, Winapi.ShlObj, Winapi.ActiveX, System.Win.ComObj;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    bnClose: TButton;
    bnMax: TButton;
    bnMin: TButton;
    Button1: TButton;
    Button2: TButton;
    procedure FormShow(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure bnCloseClick(Sender: TObject);
    procedure bnMaxClick(Sender: TObject);
    procedure bnMinClick(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    procedure ExplorerStart(aPanel: TPanel; aDirectory: string);
  protected

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  SetWindowLong(Handle, GWL_STYLE, (GetWindowLong(Handle, GWL_STYLE) and not WS_Caption));
end;

procedure TForm1.bnMaxClick(Sender: TObject);
begin Perform(WM_SYSCOMMAND,SC_MAXIMIZE,0); end;

procedure TForm1.bnMinClick(Sender: TObject);
begin Perform(WM_SYSCOMMAND,SC_MINIMIZE,0); end;

procedure TForm1.Button2Click(Sender: TObject);
begin //
end;

procedure TForm1.ExplorerStart(aPanel: TPanel; aDirectory: string);
var SEI: TShellExecuteInfo;
begin
  aPanel.Caption := aDirectory;
  FillChar(SEI, SizeOf(SEI), #0);
  SEI.cbSize := SizeOf(SEI);
  SEI.Wnd := Handle;
  SEI.fMask := SEE_MASK_NOCLOSEPROCESS;
  SEI.lpVerb := 'open';
  SEI.lpFile := PChar('iexplore.exe'); // <--------------------
  SEI.lpParameters := PChar(aDirectory);
  SEI.lpDirectory := nil;
  SEI.nShow := SW_MINIMIZE;
  if ShellExecuteEx(@SEI) then begin
    if SEI.hProcess > 32 then begin
      Sleep(500);
      aPanel.Tag := FindWindow('IEFrame',nil); // <--------------------
      if aPanel.Tag > 0 then begin
        Winapi.Windows.SetParent(aPanel.Tag, aPanel.Handle);
        SetWindowLongPtr(aPanel.Tag, GWL_STYLE, GetWindowLongPtr(aPanel.Tag, GWL_STYLE)
        and not WS_BORDER);
        SetWindowPos(aPanel.Tag, HWND_TOP, Left, Top, Width, Height, SWP_FRAMECHANGED);
      end;
    end;
  end;
  CloseHandle(SEI.hProcess);
end;
//------------------------------------------------------------------------------
procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Panel1.Tag > 0 then PostMessage(Panel1.Tag, WM_CLOSE, 0, 0);
  if Panel2.Tag > 0 then PostMessage(Panel2.Tag, WM_CLOSE, 0, 0);
end;

procedure TForm1.bnCloseClick(Sender: TObject);
begin Application.Terminate; end;

procedure TForm1.FormResize(Sender: TObject);
begin
  Panel1.Width := ClientWidth div 2;
  if Panel1.Tag > 0 then MoveWindow(Panel1.Tag, 0, 0, Panel1.Width, Panel1.Height, True);
  if Panel2.Tag > 0 then MoveWindow(Panel2.Tag, 0, 0, Panel2.Width, Panel2.Height, True);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  ExplorerStart(Panel1,'-new www.web.de');  // <------------ // Sample
  ExplorerStart(Panel2,'-new www.google.de'); // <------------// Sample
end;

end.

FarAndBeyond 5. Sep 2015 19:13

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Hab' das Ding etwas frisiert... Jetzt läuft das viel besser und stabiler bei mir...ist auch viel praktischer so: nur ein Klick und man hat beide vorne falls schon zwei geöffnet waren.
Ohne Delay oder Sleep.. Blitzschnell... Nur einmal zwei Fenster positionieren und das war's dann...
Leider hab' ich noch immer keine Möglichkeit gefunden das Verhalten des WindowsExplorers abzuschalten.
Delphi-Quellcode:
Unit u2WindowsExplorer;

Interface

 Uses
  Windows, Messages, SysUtils, Classes, Controls, Forms, ShellApi;
 
 Type
  TForm1 = Class(TForm)
   Procedure FormCreate(Sender: TObject);
   Procedure FormActivate(Sender: TObject);
   Procedure FormShow(Sender: TObject);
  End;

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

 Var
  Form1                 : TForm1;
  stringlist_FindWindow : TStringlist;
  WindowHandle         : THandle;
Implementation
 {$R *.dfm}


Procedure ErrorLog(ErrorInfo: String);
  Var
   LogFile       : TStringlist;
   LoadedFile    : TStringlist;
   boolean_Loaded : Boolean;

  Procedure LoadErrorLog;
   Begin
    Try
     boolean_Loaded := False;
     If FileExists('ErrorLog.txt')
     Then
      Begin
       LoadedFile := TStringlist.Create;
       LoadedFile.LoadFromFile('ErrorLog.txt');
       boolean_Loaded := True;
      End;
    Except
     Exit;
    End;
   End;

  Procedure Free_LogFile;
   Begin
    Try
     FreeAndNil(LogFile);
    Except
     Exit;
    End;
   End;

  Procedure Free_LoadedFile;
   Begin
    Try
     FreeAndNil(LoadedFile);
    Except
     Exit;
    End;
   End;

 Begin
  LoadErrorLog;
   Try
    LogFile:= TStringlist.Create;
     Try
      If boolean_Loaded = True
      Then
       Begin
        LogFile.Add(ErrorInfo);
        LogFile.Text := LogFile.Text + LoadedFile.Text;
        Free_LoadedFile;
       End
      Else
       Begin
        LogFile.Add(ErrorInfo);
       End;

      LogFile.SaveToFile('ErrorLog.txt');
     Finally
      Free_LogFile;
     End;
   Except
    Free_LoadedFile;
    Exit;
   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
     ErrorLog('EnumWindowsProc (Free_Memory) Failed');
     Exit;
    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;
            stringlist_FindWindow.Add(IntToStr(hWindow));
           End;
         End;
       End;
     End;
   Finally
    Free_Memory;
   End;
  Except
   ErrorLog('EnumWindowsProc Failed');
   Exit;
  End;
 End;


Function FindAWindow(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
   ErrorLog('FindAWindow Failed');
   Exit;
  End;
 End;


Procedure Start2WindowsExplorer;
 Begin
  Try
   If DirectoryExists('I:\')
   Then
    Begin
     ShellExecute(Form1.Handle, Nil, PChar('I:\MARTIN'), Nil, Nil, SW_SHOW);
     ShellExecute(Form1.Handle, Nil, PChar('I:\MARTIN\(DOWNLOADS)'), Nil, Nil, SW_SHOW);
    End
   Else
    Begin
     ShellExecute(Form1.Handle, Nil, PChar('C:\'), Nil, Nil, SW_SHOW);
     ShellExecute(Form1.Handle, Nil, PChar('D:\'), Nil, Nil, SW_SHOW);
    End;
  Except
   ErrorLog('Start2WindowsExplorer Failed');
   Exit;
  End;
 End;


Procedure Close1WindowsExplorer;

  Procedure Terminate;
   Begin
    Try
     WindowHandle := StrToInt(stringlist_FindWindow[0]);
     PostMessage(WindowHandle, WM_QUIT, 0, 0);
    Except
     ErrorLog('Close1WindowsExplorer (Terminate) Failed');
     Exit;
    End;
   End;

 Begin
  Try
   PostMessage(WindowHandle, WM_CLOSE, 0, 0);
   Start2WindowsExplorer;
  Except
   ErrorLog('Close1WindowsExplorer Failed');
   Terminate;
   Exit;
  End;
 End;


Procedure Bring2WindowsExplorerToFront;
  Var
   i : Integer;
 Begin
  Try
   For i:= 0 To stringlist_FindWindow.Count-1
   Do
    Begin
     WindowHandle := StrToInt(stringlist_FindWindow[i]);
     If IsIconic(WindowHandle)
     Then ShowWindow(WindowHandle, SW_RESTORE)
     Else
      Begin
       ShowWindow(WindowHandle, SW_MINIMIZE);
       ShowWindow(WindowHandle, SW_RESTORE);
      End;
    End;
  Except
   ErrorLog('Bring2WindowsExplorerToFront Failed');
   Exit;
  End;
 End;


Procedure DeleteAllAndStart2WindowsExplorer;
  Var
   i: Integer;
 Begin
  Try
   For i:= 0 To stringlist_FindWindow.Count-1
   Do
    Begin
     WindowHandle := StrToInt(stringlist_FindWindow[i]);
     PostMessage(WindowHandle, WM_CLOSE, 0, 0);
    End;
   Start2WindowsExplorer;
  Except
   ErrorLog('DeleteAllAndStart2WindowsExplorer Failed');
   Exit;
  End;
 End;


Procedure TForm1.FormCreate(Sender: TObject);

  Procedure Free_Stringlist;
   Begin
    Try
     FreeAndNil(stringlist_FindWindow);
    Except
     ErrorLog('FormCreate (Free_Stringlist) Failed');
     Exit;
    End;
   End;

 Begin
  Try
   Form1.Height := 1;
   Form1.Width := 1;
   Form1.Top   := 0;
   Form1.Left  := 0;
   Form1.AlphaBlend     := True;
   Form1.AlphaBlendValue := 0;

   stringlist_FindWindow := TStringlist.Create;
    Try
     FindAWindow(':\', 'CabinetWClass');

     Case stringlist_FindWindow.Count
     Of
      0 : Start2WindowsExplorer;

      1 : Close1WindowsExplorer;

      2 : Bring2WindowsExplorerToFront;
     Else
      Begin
       DeleteAllAndStart2WindowsExplorer;
      End;
     End;
    Finally
     Free_Stringlist;
    End;
  Except
   ErrorLog('FormCreate Failed');
   Exit;
  End;
 End;


Procedure TForm1.FormShow(Sender: TObject);
   Var Owner: HWND;
 Begin
  Try
   Owner := GetWindow(Form1.Handle, GW_OWNER);
   ShowWindow(Owner, SW_HIDE);
  Except
   Exit;
  End;
 End;


Procedure TForm1.FormActivate(Sender: TObject);

  Procedure Terminate;
   Begin
    Try
     Application.Terminate;
    Except
     Exit;
    End;
   End;

 Begin
  Try
   Close;
  Except
   Terminate;
  End;
 End;

End.
WindowsTaste + E kann man problemlos nutzen und das neue Fenster kann man auch problemlos verschieben...
Darin zu suchen ist wahrscheinlich keine so gute Idee, hab' ich noch nicht getestet.

Auf STRG+N sollte man aber verzichten...

Ich hätte niemals gedacht, dass es so nervig sein kann ein Fenster das "wsNormal" ist nach vorne zu holen.
Delphi-Quellcode:
ShowWindow(WindowHandle, SW_Show); // Funktioniert nicht!
ShowWindow(WindowHandle, SW_ShowNormal); // Funktioniert nicht!

SetWindowPos(WindowHandle, HWND_TOP, .... // Funktioniert nicht!
SetWindowPos(WindowHandle, HWND_NoTOPMOST, // Funktioniert nicht!
SetWindowPos(WindowHandle, HWND_TOPMOST, // Das funzt, ist aber bei normaler Shell nicht zu empfehlen, bei eigener Shell vielleicht 'ne Lösung.

ShowWindow(WindowHandle, SW_MINIMIZE); //und gleichzeitig dahinter SW_Restore
ShowWindow(WindowHandle, SW_RESTORE); // Das hat bis jetzt immer geklappt.. zu 100%, auch bei mehreren Fenstern

//Vielleicht sollte ich nochmal WindowState probieren, aber ich meine, ich hätte damit früher schonmal Schwierigkeiten bekommen...
//SetForegroundWindow funzt nur für ein Fenster...
Zwei einfache wsNormal-Fenster wirklich immer nach vorne zu kriegen ohne "Topmost" ist tatsächlich ein kleines Wunder!
Alter Schwede ich kotz gleich in die Ecke...

Sir Rufo 5. Sep 2015 23:08

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Kann es sein, dass du eine "Exception Paranoia" hast?

FarAndBeyond 6. Sep 2015 02:14

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
@Sir Rufo:
Nennt man das jetzt so? ... grins...
Ja mag sein, dass die Bezeichnung ins Schwarze trifft...

Ich hab' jetzt zwar gelernt, wie man es offiziell richtig macht, aber ich kann mich noch nicht so richtig dazu durchringen das umzusetzen. Es gibt da immer noch so eine Stimme die sagt:"Mach das Programm nicht zu geschwätzig, mach 'n ErrorLog für dich und schick' nur die Meldung 'raus, die dem Nutzer auch wirklich weiterhelfen kann.
Ich pendel noch zwischen den Polen und werd' meinen Weg wohl noch finden...

Kann sich nur noch um 100 Jahre handeln...

Ach so, vielleicht hast du auch einfach nur das WM_Quit gesehen... das kann da eigentlich weg... hab' 'n bisschen 'rumgespielt...

Hat aber auch 'was praktisches, ich teste meine Programme meistens außerhalb der IDE, dann muß ich bei 'nem falschen Stringlist Index nicht immer per Taskmanager Delphi7 killen und anschließend wieder neu starten... so weiß ich immer wo es kracht und zwar präzise mit meinen eigenen Worten bzw. Prozeduren...

Gut Ding will Weile haben oder wie war das...

Aviator 6. Sep 2015 11:03

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

Zitat von FarAndBeyond (Beitrag 1314864)
Hat aber auch 'was praktisches, ich teste meine Programme meistens außerhalb der IDE, dann muß ich bei 'nem falschen Stringlist Index nicht immer per Taskmanager Delphi7 killen und anschließend wieder neu starten... so weiß ich immer wo es kracht und zwar präzise mit meinen eigenen Worten bzw. Prozeduren...

Auch bei Delphi 7 konnte man das Programm stoppen wenn ein Fehler aufgetreten ist. Es gibt zwar keinen so schönen Stopp-Button in der ToolBar, aber über das Menü "Start" (so heißt es bei Delphi 2010 und XE3 und XE4 und ... kann man das Programm stoppen. Alternativ über den HotKey STRG + F2. Solltest du mal ausprobieren. Dann kannst du auch den Debugger sinvoll nutzen.

FarAndBeyond 6. Sep 2015 18:29

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
@Aviator:
Ja, das wär' schön... bei kleineren Fehlern, die mal auftreten kann man RESET (STRG+F2) drücken und ist wieder in der IDE. Aber bei sehr vielen StringlistINDEX-Fehlern stoppt Delphi das Programm und zeigt das auch in der Titelleiste an. Dann funktioniert RESET nicht mehr und auch per Taskmanager kann ich das Programm nicht mehr abschießen.
Das Einzige was dann noch geht ist Delphi7 komplett per Taskmanager abzuschießen und das ist nervig, da ich dann alle Units neuladen muss und wieder an die Position wo ich war gehen muss...
Man kann den Ladevorgang zwar automatisieren, aber damit hatte ich schonmal 'ne Menge "Spass" und hab' das dann wieder abgeschaltet.

Ja ich hab' gehört, dass es einen Debugger gibt, hab' ihn noch nie benutzt... vielleicht wird das irgendwann mal interessant, wenn ich genau herausfinden muss was der Prozess genau macht. Normalerweise programmiere ich einfach alles um, schließlich kann man ja eine Sache auf 1000 verschiedene Arten machen und die verschiedensten Befehle dazu nutzen. Also wenn etwas auf eine Art nicht klappt, egal ob es an mir liegt oder daran, dass es einfach so nicht geht, dann mache ich es eben auf eine andere Art...

FarAndBeyond 28. Nov 2015 04:05

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Final Version... :-)

- fehlendes FensterHandle hinzugefügt
- Overkill entfernt
- Exception-Handling minimal informativer gemacht ;-)
- kein Sleep erforderlich

Ergebnis: läuft super schnell und stabil bei mir...
Sollte ich alle paar Monate die Fenster mal wieder neu positionieren müssen wäre mir das auch egal, aber bis jetzt läuft alles sauber...
Läuft auch unter Lazarus // {$Mode Delphi} // oder selber Handanlegen und anpassen

Delphi-Quellcode:
Program TwoWindowsExplorer;

 Uses
  Windows, Messages, Classes, SysUtils, ShellApi;

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

 Var
  FoundWindows: TStringlist;
  WndHandle  : THandle;


Procedure ErrorLog(ErrorInfo: String);
  Var
   LoadErrorLog : TStringlist;
   SaveErrorInfo: TStringlist;
   ErrorLog    : String;

  Procedure Free_LoadErrorLog;
   Begin
    Try
     FreeAndNil(LoadErrorLog);
    Except
    End;
   End;

  Procedure Free_SaveErrorInfo;
   Begin
    Try
     FreeAndNil(SaveErrorInfo);
    Except
    End;
   End;

  Function ErrorLogExists : Boolean;
   Begin
    Try
     Result:= False;
      If FileExists('ErrorLog.txt')
      Then
       Begin
        Try
         LoadErrorLog:= TStringlist.Create;
         LoadErrorLog.LoadFromFile('ErrorLog.txt');
         ErrorLog:= LoadErrorLog.Text;
         Result:= True;
        Finally
         Free_LoadErrorLog;
        End;
       End;
    Except
    End;
   End;

 Begin
  Try
   Try
    SaveErrorInfo:= TStringlist.Create;
     SaveErrorInfo.Add(DateTimeToStr(Now));
     SaveErrorInfo.Add(ErrorInfo);

      If ErrorLogExists
      Then
       Begin
        SaveErrorInfo.Add(' ');
        SaveErrorInfo.Add(Trim(ErrorLog));
       End;

     SaveErrorInfo.SaveToFile('ErrorLog.txt');
   Finally
    Free_SaveErrorInfo;
   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 Failed'+#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;
            FoundWindows.Add(IntToStr(hWindow));
           End;
         End;
       End;
     End;
   Finally
    Free_Memory;
   End;
  Except
   On E: Exception
   Do ErrorLog('EnumWindowsProc Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Function FindAWindow(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('FindAWindow Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Procedure StartTwoExplorer;
 Begin
  Try
   If DirectoryExists('I:\')
   Then
    Begin
     ShellExecute(0, Nil, PChar('I:\MARTIN'),            Nil, Nil, SW_SHOW);
     ShellExecute(0, Nil, PChar('I:\MARTIN\(DOWNLOADS)'), Nil, Nil, SW_SHOW);
    End
   Else
    Begin
     ShellExecute(0, Nil, PChar('C:\'), Nil, Nil, SW_SHOW);
     ShellExecute(0, Nil, PChar('D:\'), Nil, Nil, SW_SHOW);
    End;
  Except
   On E: Exception
   Do ErrorLog('StartTwoExplorer Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Procedure CloseOneExplorer;
 Begin
  Try
   WndHandle:= StrToInt(FoundWindows[0]);
   PostMessage(WndHandle, WM_CLOSE, 0, 0);
   StartTwoExplorer;
  Except
   On E: Exception
   Do ErrorLog('CloseOneExplorer Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Procedure TwoExplorerToFront;
  Var
   I: Integer;
 Begin
  Try

   For I:= 0 To FoundWindows.Count-1
   Do
    Begin
     WndHandle:= StrToInt(FoundWindows[I]);
     If IsIconic(WndHandle)
     Then ShowWindow(WndHandle, SW_RESTORE)
     Else
      Begin
       ShowWindow(WndHandle, SW_MINIMIZE);
       ShowWindow(WndHandle, SW_RESTORE);
      End;
    End;
   
  Except
   On E: Exception
   Do ErrorLog('TwoExplorerToFront Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Procedure CloseAllExplorer;
  Var
   I: Integer;
 Begin
  Try

   For I:= 0 To FoundWindows.Count-1
   Do
    Begin
     WndHandle:= StrToInt(FoundWindows[I]);
     PostMessage(WndHandle, WM_CLOSE, 0, 0);
    End;

   StartTwoExplorer;
  Except
   On E: Exception
   Do ErrorLog('CloseAllExplorer Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Procedure Free_Stringlist;
 Begin
  Try
   FreeAndNil(FoundWindows);
  Except
   On E: Exception
   Do ErrorLog('Free_Stringlist Failed'+#13#10+E.ClassName+#13#10+E.Message);
  End;
 End;


Begin
 Try
  FoundWindows:= TStringlist.Create;
   Try
    FindAWindow('','CabinetWClass');

     Case FoundWindows.Count
     Of
      0 : StartTwoExplorer;
      1 : CloseOneExplorer;
      2 : TwoExplorerToFront;
      Else CloseAllExplorer;
     End;

   Finally
    Free_Stringlist;
   End;
 Except
  On E: Exception
  Do ErrorLog('MainProgram Failed'+#13#10+E.ClassName+#13#10+E.Message);
 End;
End.
Fur alle die Windows 7 mögen und dazu noch den WindowsExplorer hier eine einfache Anleitung:

1.
Quicklaunch einrichten und Icon auswählen, Rechtsklick auf Icon - Eigenschaften: Pfad zur EXE eingeben

2.
Icon klicken und damit die EXE zum ersten Mal starten

3.
Fenster positionieren (Hinweis: Die Fenster müssen von Hand ausgerichet werden. Man kann aber die automatische Andockmöglichkeit unter Windows7 nutzen damit das schneller geht. Ausschließlich Andocken geht nicht, da sich der Explorer dann die Position nicht merkt!

4.
Fenster schließen und erneut auf das eingerichtete Icon klicken: Feintuning vornehmen, so das nur noch 1 Pixel oder wenige Pixel unten unausgefüllt bleiben...
Wer Lust hat zu Fummeln bekommt sicher auch den letzten Pixel noch weg...

5.
Fertig! Ab jetzt nur noch den neuen Button benutzen, egal ob kein Fenster gestartet ist oder nur ein Fenster sichtbar ist oder ob beide Fenster schon im Hintergrund laufen...
Es ist nur noch ein Klick notwendig um die beiden WindowsExplorer-Fenster anzeigen zu lassen.

Hinweis: Es kann sein, dass man bis zu 3 bis 4 Versuche benötigt bis sich der WindowsExplorer die Position gemerkt hat.
Wenn die Position dann einmal drin ist hat man Ruhe und gleichzeitig läuft das Ganze richtig schnell...

Ob das auch unter Windows 8 oder 8.1 läuft kann ich nicht sagen.
Ob das auch mit mehreren Monitoren oder größeren Monitoren und mehr Fenstern geht kann ich auch nicht sagen... TryAndError...for yourself...

FarAndBeyond 5. Jul 2016 23:26

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
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... :P

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...

jaenicke 6. Jul 2016 04:24

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Durch die vollkommen transparenten Fensterränder sieht es unter Windows 10 so aus als sei zwischen den Fenstern Platz. In Wirklichkeit sind das nur die Rahmen aber die sieht man ja nicht.

Leider lässt sich das programmtechnisch auch kaum lösen. Aero Snap ist ja leider per API nicht erreichbar und wenn man die Fenster so platziert, dass kein Abstand dazwischen sichtbar ist, überlappen sie in Wirklichkeit.

Da andere Fenstermanager mittlerweile aber auch Aero Snap Features haben, scheint es auf undokumentiertem Weg evtl. doch zu gehen. Das hätte den Vorteil, dass die Fenster auch wieder ihre normale Größe einnehmen, wenn man sie aus dem doppelt maximierten Zustand herauszieht.

Erdbär 6. Jul 2016 08:34

AW: Zwei Windows Explorer starten und nebeneinander bildschirmfüllend positionieren
 
Finde ich ganz praktisch:

Delphi-Quellcode:
...
...
...

// Sorgt für mehr Übersicht auf dem Desktop:
procedure MinAllWindows;
begin
  KeyBd_Event(VK_LWIN, MapvirtualKey(VK_LWIN, 0), 0, 0);
  KeyBd_Event(Ord('M'), MapvirtualKey(Ord('M'), 0), 0, 0);
  KeyBd_Event(Ord('M'), MapvirtualKey(Ord('M'), 0), KEYEVENTF_KEYUP, 0);
  KeyBd_Event(VK_LWIN, MapvirtualKey(VK_LWIN, 0), KEYEVENTF_KEYUP, 0);
end;
// ^ Minimiert alle Fenster

Procedure StartTwoWinEx;
 Begin
 MinAllWindows; // Eingefügt
  Try
   If DirectoryExists('I:\') And DirectoryExists('I:\(DOWNLOADS)')
   Then ...
...
...
Kompiliert mit Delph7 unter Win10, getestet unter XP/8.1/10. Klappt :thumb:

Danke!

jaenicke 6. Jul 2016 12:13

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.

FarAndBeyond 6. Jul 2016 20:43

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

Durch die vollkommen transparenten Fensterränder sieht es unter Windows 10 so aus als sei zwischen den Fenstern Platz.
Danke für die Info...
Na wenigstens funktioniert das in W10 noch. Wenn der Spalt nicht zu groß ist stört das ja vielleicht nicht so sehr.


Zitat:

procedure MinAllWindows;
Nette Idee... Kann ich vielleicht noch gebrauchen, mir ist nämlich folgendes aufgefallen: Wenn ich den Browser im Vordergrund geöffnet habe und dann den QuickLaunch-Button drücke bei zwei schon geöffneten WinEx-Fenstern, dann bringt er mir nur ein Explorer-Fenster nach vorne.
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:

Dann müsste man nur statt MoveWindow erst das eine Fenster fokussieren, Win + Left schicken, dann das zweite Fokussieren und Win + Right schicken.
Gute Alternative... aber dafür brauchst du auch ein Fensterhandle oder?
Ist wahrscheinlich gehopst wie gesprungen... wenn schon zwei geöffnet sind müssen die erstmal wieder nach vorne...

Luckie 7. Jul 2016 02:23

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:
Procedure Free_slLoad;
   Begin
    Try
     FreeAndNil(slLoad);
    Except
    End;
   End;
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: http://www.nickhodges.com/post/Using-FreeAndNil.aspx

jaenicke 7. Jul 2016 05:56

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

Zitat von FarAndBeyond (Beitrag 1342112)
Gute Alternative... aber dafür brauchst du auch ein Fensterhandle oder?
Ist wahrscheinlich gehopst wie gesprungen... wenn schon zwei geöffnet sind müssen die erstmal wieder nach vorne...

Ich habe es heute Morgen einmal getestet...
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);

FarAndBeyond 7. Jul 2016 06:08

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

Wozu die ganzen Try-Except-Blöcke, wenn sie doch leer sind?
Die sollen doch leer sein. Mein Motto lautet: Geht was schief, dann bitte alles in den ErrorLog... Kann der nicht erstellt werden, dann bitte gar nichts machen.
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:

..Mit SetForegroundWindow lässt sich der Windows Explorer nach vorne holen und dann mit folgendem Code links snappen (und rechts dann analog)..
Interessant, werd' ich nochmal ausprobieren... SetForegroundWindow holt beide Fenster immer wieder nach vorne... ist ja'n Ding... bei mir ging das nur mit "Minimieren" und anschließend "Restore" (ShowWindow).


@Erdbär
Man kann deine Procedure noch etwas verkleinern: :P
Delphi-Quellcode:
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;
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:

Delphi-Quellcode:
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.
Noch'n bisschen mehr und das Ding wird richtig sexy.... (OK, nur wenn man sich das irre Exception-Handling wegdenkt... :-)).

FarAndBeyond 8. Jul 2016 03:58

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:
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;
Dann funzt 32bit und 64bit ... Ohne die Umstellung funzt nur {$Mode Delphi}... aber nur als 32bit-EXE...

EDIT: Uses Interfaces; // oder man compiliert nur mit FPC und läßt den Overkill weg...

jaenicke 8. Jul 2016 06:52

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.

FarAndBeyond 8. Jul 2016 22:07

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:
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.
@ jaenicke:
"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).

Zacherl 11. Jul 2016 14:22

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

Zitat von FarAndBeyond (Beitrag 1342124)
Zitat:

Wozu die ganzen Try-Except-Blöcke, wenn sie doch leer sind?
Die sollen doch leer sein. Mein Motto lautet: Geht was schief, dann bitte alles in den ErrorLog... Kann der nicht erstellt werden, dann bitte gar nichts machen.
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.

Das ist ja auch durchaus legitim, aber dazu reichen einige wenige Exception / Finally Blöcke. Außerdem umschließt du sehr viele Befehle mit Exception Blöcken, bei denen es unmgölich ist, dass überhaupt eine Exception auftritt.

Beim von Luckie schon angesprochenen kontraproduktivem Auslagern von
Delphi-Quellcode:
FreeAndNil
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
Delphi-Quellcode:
Free
gar nicht fehlschlagen. Dass
Delphi-Quellcode:
FreeAndNil
hier unnötigt ist, hat Luckie ja auch schon erwähnt. Konkret wäre dies die korrekte Herangehensweise:
Delphi-Quellcode:
SL := TStringList.Create;
try
  // ..
finally
  SL.Free;
end;
Andere Stelle: MSDN-Library durchsuchenEnumWindows. Darauf dass diese API eine Exception schmeißt, kannst du lange warten. Windows APIs besitzen einen Rückgabewert, der geprüft werden muss und schmeißen generell keine Exceptions (von seltenen CPU-Exceptions vielleicht mal abgesehen).

Dann sind an einigen Stellen die Resourcen-Schutzblöcke falsch positioniert. Die
Delphi-Quellcode:
ErrorLogExists
Funktion sollte beispielsweise eher so aussehen:
Delphi-Quellcode:
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;
Also erst die StringList erzeugen und dann den Resourcen-Schutzblock mit
Delphi-Quellcode:
try
einleiten. Wichtig ist, dass das
Delphi-Quellcode:
Create
nicht mit im Block ist, sonst ist nicht garantiert, dass das
Delphi-Quellcode:
Free
im finally Block funktioniert.

Dieser Artikel könnte für dich auch noch interessant sein:
http://eurekalog.blogspot.de/2010/05...09-and_05.html

FarAndBeyond 11. Jul 2016 16:52

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:
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;
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...
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 13:48 Uhr.
Seite 1 von 2  1 2      

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