WinDuos

Anwendungen, Tools, Userlibs und anderes nützliches.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

@Kiffi:
Wie wäre es denn, wenn du einfach nach den beiden versteckten
Explorer-Fenstern suchst und den Titel einfach ignorierst? Normalerweise
wird kein Explorerfenster von dieser Windowclass versteckt sein, oder?

Das gute daran wird sein, dass auch schon geöffnete Explorerfenster
miteinbezogen werden.

Also anstatt zu vergleichen, welche Handles dazugekommen sind, würde ich
einfach die zwei versteckten Explorer suchen und sie benutzen.

PS.: Die besten Ideen kommen einem immer, wenn man schon fast schläft. :wink:
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

scholly hat geschrieben:Nach Programmende hat Explorer aber ein Problem festgestellt, fragt ob
ich den Problembericht senden will, beendet sich dann und startet sich
neu.
:shock: Also, dass der Explorer abstürzt, ist höchst unfein. Ich muss mal
schauen, woran das liegen könnte. Erstmal vielen Dank für Dein Feedback!
NicTheQuick hat geschrieben:@Kiffi:
Wie wäre es denn, wenn du einfach nach den beiden versteckten
Explorer-Fenstern suchst und den Titel einfach ignorierst?
das mit der Suche nach versteckten Explorern ist eine gute Idee! Somit
werden zumindest nicht allzuviele Items in die LinkedList geschrieben ;-)

Allerdings kann ich den Titel nicht so einfach ignorieren, weil ich eine
Unterscheidung zwischen linken und rechtem Fenster machen muss. Wenn
also jemand einstellt, dass er links "C:" und rechts "D:" sehen will, soll
es beim nächsten Aufruf nicht umgekehrt sein.

Ich bin da jetzt mal pragmatisch und verwende FindString(). Allerdings
besteht dann die Gefahr der Verwechslung bei so Sachen wie "C:\Sourcen"
und "D:\Sourcen" (Welches "Sourcen" gehört wohin?)

Ich habe da noch eine andere Vorgehensweise im Sinn, muss aber erst
einmal heute mittag schauen, ob die sich verwirklichen lässt.

Vielen Dank für Deinen Tipp & Grüße ... Kiffi

Nachfolgender Code funktioniert nun auch bei mir, wenn ich den
kompletten Pfad nicht in der Titelleiste anzeigen lasse.

Wäre nett, wenn Ihr das noch einmal testen könntet. Once again:

Code: Alles auswählen

; WinDuos

EnableExplicit

Enumeration ; Windows
  #frmMain
EndEnumeration
Enumeration ; Gadgets
  
  #frmMain_TB
  
  #frmMain_Container_1
  #frmMain_Container_2
  #frmMain_Splitter
  #frmMain_SB
  
  #frmMain_Menu
  #frmMain_Menu_Quit
  #frmMain_Menu_AddFolders
  #frmMain_Menu_EditFolders
  #frmMain_Menu_Help
  #frmMain_Menu_Info
  
  #frmMain_FavoritenFolder_Item ; Muss als letztes stehen
  
EndEnumeration

Structure s_Explorer
  
  Description.s
  LeftPath.s
  RightPath.s
  LefthWnd.l
  RighthWnd.l
  
  LeftAddressbarhWnd.l
  RightAddressbarhWnd.l
  
EndStructure

#AppName = "WinDuos"

Global Explorer.s_Explorer
Global AddressBarhWnd.l

#BufferSize = 2048

Global NewList Windows()
Global NewList Favoriten.s_Explorer()

Procedure GetAddressBarhWnd(hwnd.l, void.l)
  Protected a.s = Space(200)
  GetClassName_(hwnd, @a, 199)
  If a="Edit"
    AddressBarhWnd = hwnd
    ProcedureReturn 0
  EndIf
  ProcedureReturn 1
EndProcedure

Procedure SetStyles(ExplorerHandle.l)
  
  SetWindowLong_(ExplorerHandle, #GWL_EXSTYLE, GetWindowLong_(ExplorerHandle, #GWL_EXSTYLE) &~ #WS_EX_CLIENTEDGE )
  SetWindowLong_(ExplorerHandle, #GWL_EXSTYLE, GetWindowLong_(ExplorerHandle, #GWL_EXSTYLE) &~ #WS_EX_WINDOWEDGE )
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_DLGFRAME)
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_THICKFRAME)
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_OVERLAPPED )
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_BORDER)
  
EndProcedure

Procedure.s GetClassName(Handle.l)
  Protected ClassName.s = Space(#BufferSize)
  GetClassName_(Handle, @ClassName, #BufferSize)
  ProcedureReturn ClassName
EndProcedure
Procedure.s GetTitle(Handle.l)
  Protected Title.s = Space(#BufferSize)
  GetWindowText_(Handle, @Title, #BufferSize)
  ProcedureReturn Title
EndProcedure
Procedure EnumProc(Handle.l, lParam.l)
  
  Protected ClassName.s = GetClassName(Handle)
  
  If ClassName = "CabinetWClass" Or ClassName = "ExplorerWClass"
    If Not IsWindowVisible_(Handle)  ; Nur unsichtbare Fenster suchen
      AddElement(Windows())
      Windows()=Handle
    EndIf
  EndIf
  
  ProcedureReturn #True
  
EndProcedure

Procedure.l StartExplorer(LeftPath.s, RightPath.s)
  
  If LCase(LeftPath) = LCase(RightPath)
    MessageRequester(#AppName, "Linker und rechter Pfad dürfen nicht identisch sein.")
    ProcedureReturn #False
  EndIf
  
  LeftPath =Trim(LeftPath)
  RightPath=Trim(RightPath)
  
  Debug LeftPath
  Debug RightPath
  
  ; Anpassung der Pfade
  ; Erlaubt "C:"          (mit abschliessendem Backslash)
  ; Erlaubt "C:\Programme" (ohne Backslash)
  ; dito mit UNC-Pfaden
  
  If Left(LeftPath, 2) = "\"
    If CountString(LeftPath, "") => 3
      If Right(LeftPath, 1) = ""
        LeftPath=Left(LeftPath, Len(LeftPath)-1)
      EndIf
    EndIf
  Else
    If CountString(LeftPath, "") => 2
      If Right(LeftPath, 1) = ""
        LeftPath=Left(LeftPath, Len(LeftPath)-1)
      EndIf
    EndIf
  EndIf
  
  If Left(RightPath, 2) = "\"
    If CountString(RightPath, "") => 3
      If Right(RightPath, 1) = ""
        RightPath=Left(RightPath, Len(RightPath)-1)
      EndIf
    EndIf
  Else
    If CountString(RightPath, "") => 2
      If Right(RightPath, 1) = ""
        RightPath=Left(RightPath, Len(RightPath)-1)
      EndIf
    EndIf
  EndIf
  
  Debug LeftPath
  Debug RightPath
  
  Protected ReturnValue.l
  Protected TimeOut.l
  
  NewList W_Before()
  NewList W_After()
  
  ; Enumeration der bereits vorhandenen Fenster
  
  ClearList(Windows())
  EnumWindows_(@EnumProc(), 0)
  
  ForEach Windows()
    AddElement(W_Before())
    W_Before()=Windows()
  Next
  
  Explorer\LeftPath  = LeftPath
  Explorer\RightPath = RightPath
  
  ReturnValue = RunProgram("explorer.exe", Explorer\LeftPath,  "", #PB_Program_Hide)
  ReturnValue = RunProgram("explorer.exe", Explorer\RightPath, "", #PB_Program_Hide)
  
  TimeOut = AddDate(Date(), #PB_Date_Second, 5) ; 5 Sekunden als Timeout (müsste eigentlich reichen)
  
  Repeat
    
    ; Enumeration der Fenster nach RunProgram()
    
    ClearList(Windows())
    EnumWindows_(@EnumProc(), 0)
    
    ClearList(W_After())
    ForEach Windows()
      AddElement(W_After())
      W_After()=Windows()
    Next
    
    If CountList(W_Before()) + 2 = CountList(W_After()) ; 2 neue Fenster hinzugekommen?
      
      ; Nun alte Fensterliste mit neuer vergleichen
      ; identische Fenster werden aus W_After() entfernt
      
      ForEach W_Before()
        ForEach W_After()
          If W_Before()=W_After()
            DeleteElement(W_After())
          EndIf
        Next
      Next
      
      ; Nun sind im Idealfall in W_After nur die von WinDuos
      ; gestarteten Explorer vorhanden
      
      ForEach W_After()
        
        ; Hier wird nur FindString() verwendet, da in der Titelleiste 
        ; nicht zwangsläufig der komplette Pfad steht
        
        If FindString(Explorer\LeftPath, GetTitle(W_After()), 1)
          Explorer\LefthWnd=W_After()
          DeleteElement(W_After())
        ElseIf FindString(Explorer\RightPath, GetTitle(W_After()), 1)
          Explorer\RighthWnd=W_After()
          DeleteElement(W_After())
        EndIf
        
      Next
      
      If Explorer\LefthWnd And Explorer\RighthWnd 
        Break
      EndIf
      
    EndIf
    
    Delay(100)
    
    If Date() => TimeOut : Break : EndIf ; Timeout abgelaufen -> Raus aus der Schleife
    
  ForEver
  
  If Explorer\LefthWnd And Explorer\RighthWnd 
    
    SetParent_(Explorer\LefthWnd,  GadgetID(#frmMain_Container_1))
    SetParent_(Explorer\RighthWnd, GadgetID(#frmMain_Container_2))
    
    SetStyles(Explorer\LefthWnd)
    SetStyles(Explorer\RighthWnd)
    
    ; Adressen der Explorer-Adressleiste ermitteln
    
    AddressBarhWnd = 0 : EnumChildWindows_(Explorer\LefthWnd,  @GetAddressBarhWnd(), 0) : Explorer\LeftAddressbarhWnd  = AddressBarhWnd
    AddressBarhWnd = 0 : EnumChildWindows_(Explorer\RighthWnd, @GetAddressBarhWnd(), 0) : Explorer\RightAddressbarhWnd = AddressBarhWnd
    
    If Explorer\LeftAddressbarhWnd And Explorer\RightAddressbarhWnd
      
      ShowWindow_(Explorer\LefthWnd,  #SW_MAXIMIZE)
      ShowWindow_(Explorer\RighthWnd, #SW_MAXIMIZE)
      
      ProcedureReturn #True
      
    Else
      
      MessageRequester(#AppName, "Adressleiste ist nicht angeschaltet.")
      
    EndIf
    
  Else
    
    MessageRequester(#AppName, "Mindestens ein Explorer konnte nicht gestartet werden.")
    
  EndIf
  
EndProcedure
  
Procedure ChangePathes()
  
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_SETTEXT, 0, @Explorer\LeftPath)
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_LBUTTONDOWN ,#MK_LBUTTON, 0)
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_LBUTTONUP ,#MK_LBUTTON, 0) 
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_KEYDOWN, #VK_RETURN, 0) 
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_KEYUP, #VK_RETURN, 0) 
  
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_SETTEXT, 0, @Explorer\RightPath)
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_LBUTTONDOWN ,#MK_LBUTTON, 0)
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_LBUTTONUP ,#MK_LBUTTON, 0) 
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_KEYDOWN, #VK_RETURN, 0) 
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_KEYUP, #VK_RETURN, 0) 
  
EndProcedure
  
Procedure LoadSettings()
  
  Protected Counter.l
  Protected Description.s
  Protected LeftPath.s
  Protected RightPath.s
  
  OpenPreferences("winduos.ini")
  
  ClearList(Favoriten())
  
  Repeat
    
    Counter + 1
    
    Description = ReadPreferenceString("description" + Str(Counter), "")
    LeftPath    = ReadPreferenceString("leftpath"    + Str(Counter), "")
    RightPath   = ReadPreferenceString("rightpath"   + Str(Counter), "")
    
    If Description And LeftPath And RightPath
      
      AddElement(Favoriten())
      
      Favoriten()\Description = Description
      Favoriten()\LeftPath    = LeftPath
      Favoriten()\RightPath   = RightPath
      
    EndIf
    
  Until Counter = 100
  
  ClosePreferences()
  
EndProcedure
Procedure SaveSettings()
  
  Protected Counter.l
  
  If CreatePreferences("winduos.ini")
    
    ForEach Favoriten()
      
      Counter + 1
      
      WritePreferenceString("description" + Str(Counter), Favoriten()\Description)
      WritePreferenceString("leftpath"    + Str(Counter), Favoriten()\LeftPath)
      WritePreferenceString("rightpath"   + Str(Counter), Favoriten()\RightPath)
      
    Next
    
    ClosePreferences()
    
  EndIf
  
EndProcedure

Procedure.l frmMain_Open()
  
  Protected WindowFlags.l
  
  WindowFlags | #PB_Window_SystemMenu
  WindowFlags | #PB_Window_MinimizeGadget
  WindowFlags | #PB_Window_MaximizeGadget
  WindowFlags | #PB_Window_SizeGadget
  WindowFlags | #PB_Window_Invisible
  WindowFlags | #PB_Window_ScreenCentered
  
  If OpenWindow(#frmMain, #PB_Ignore, #PB_Ignore, 800, 600, #AppName, WindowFlags)
    If CreateGadgetList(WindowID(#frmMain))
      
      If CreateToolBar(#frmMain_TB, WindowID(#frmMain))
        
        If CreateStatusBar(#frmMain_SB, WindowID(#frmMain))
          
          ContainerGadget(#frmMain_Container_1, 0, 0, 0, 0) : CloseGadgetList()
          ContainerGadget(#frmMain_Container_2, 0, 0, 0, 0) : CloseGadgetList()
          
          SetWindowLong_(GadgetID(#frmMain_Container_1), #GWL_STYLE, GetWindowLong_(GadgetID(#frmMain_Container_1), #GWL_STYLE) | #WS_CLIPCHILDREN) 
          SetWindowLong_(GadgetID(#frmMain_Container_2), #GWL_STYLE, GetWindowLong_(GadgetID(#frmMain_Container_2), #GWL_STYLE) | #WS_CLIPCHILDREN) 
          
          SplitterGadget(#frmMain_Splitter, 0, ToolBarHeight(#frmMain_TB), WindowWidth(#frmMain), WindowHeight(#frmMain) - ToolBarHeight(#frmMain_TB) - StatusBarHeight(#frmMain_SB), #frmMain_Container_1, #frmMain_Container_2, #PB_Splitter_Vertical)
          
          SetWindowLong_(GadgetID(#frmMain_Splitter), #GWL_STYLE, GetWindowLong_(GadgetID(#frmMain_Splitter), #GWL_STYLE) | #WS_CLIPCHILDREN) 
          
          SetWindowLong_(WindowID(#frmMain), #GWL_STYLE, GetWindowLong_(WindowID(#frmMain), #GWL_STYLE) | #WS_CLIPCHILDREN) 

          SmartWindowRefresh(#frmMain, #True)
          
          ProcedureReturn #True
          
        EndIf
      EndIf
    EndIf
  EndIf
  
EndProcedure

Procedure ResizeGadgets()
  
  If Explorer\LefthWnd
    MoveWindow_(Explorer\LefthWnd,  0, 0, GadgetWidth(#frmMain_Container_1), GadgetHeight(#frmMain_Container_1), #True)
  EndIf
  If Explorer\RighthWnd
    MoveWindow_(Explorer\RighthWnd, 0, 0, GadgetWidth(#frmMain_Container_2), GadgetHeight(#frmMain_Container_2), #True)
  EndIf
  
EndProcedure
  
Procedure.s GetSpecialFolder(Folder.l)
  Protected *itemid.ITEMIDLIST = #Null
  If SHGetSpecialFolderLocation_ (0, Folder, @*itemid) = #NOERROR
    Protected location.s = Space (#MAX_PATH)
    If SHGetPathFromIDList_ (*itemid, @location)
      If Right(location, 1) <> "" : location + "" : EndIf
      ProcedureReturn location
    EndIf
  EndIf
EndProcedure

Procedure RebuildMenue()
  
  If CreateMenu(#frmMain_Menu, WindowID(#frmMain))
    
    MenuTitle("Datei")
    MenuItem(#frmMain_Menu_Quit, "Beenden")
    
    MenuTitle("Ordner")
    ForEach Favoriten()
      MenuItem(#frmMain_FavoritenFolder_Item + ListIndex(Favoriten()), Favoriten()\Description)  
    Next
    
    MenuBar()
    MenuItem(#frmMain_Menu_AddFolders, "Aktuelle Ordneransicht hinzufügen")
    MenuItem(#frmMain_Menu_EditFolders, "Favoriten bearbeiten")

    MenuTitle("Hilfe")
    MenuItem(#frmMain_Menu_Help, "Hilfe...")
    MenuItem(#frmMain_Menu_Info, "Über...")
    
  EndIf
  
EndProcedure

Procedure AddFolders()
  
  Protected Description.s
  Protected TextLen.l
  Protected LeftPath.s
  Protected RightPath.s
  
  Description = InputRequester("Favorit hinzufügen", "Bitte geben Sie eine Bezeichnung ein.", "")
  
  If Description
    
    TextLen = SendMessage_(Explorer\LeftAddressbarhWnd, #WM_GETTEXTLENGTH, 0, 0)
    If TextLen
      TextLen + 1
      LeftPath = Space(TextLen)
      SendMessage_(Explorer\LeftAddressbarhWnd, #WM_GETTEXT, TextLen, @LeftPath)
    EndIf
    
    TextLen = SendMessage_(Explorer\RightAddressbarhWnd, #WM_GETTEXTLENGTH, 0, 0)
    If TextLen
      TextLen + 1
      RightPath = Space(TextLen)
      SendMessage_(Explorer\RightAddressbarhWnd, #WM_GETTEXT, TextLen, @RightPath)
    EndIf
    
    Debug LeftPath
    Debug RightPath
    
    AddElement(Favoriten())
    
    Favoriten()\Description = Description
    Favoriten()\LeftPath    = LeftPath
    Favoriten()\RightPath   = RightPath
    
    RebuildMenue()
    
    SaveSettings()
    
  EndIf
  
EndProcedure

Procedure EditFolders()
  
  Protected Text.s
  
  Text + "Momentan können die Favoriten nur in der INI-Datei geändert werden." + #CRLF$
  Text + #CRLF$
  Text + "Soll die INI-Datei nun geöffnet werden?" + #CRLF$
  
  If MessageRequester(#AppName, Text, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
    
    Text = "Bitte denken Sie daran, dass die geänderten Favoriten erst" + #CRLF$
    Text + "nach einem Neustart von " + #AppName + " zur Verfügung stehen" + #CRLF$
    Text + "und in dem Zeitraum zwischen den Änderungen in der INI und dem" + #CRLF$
    Text + "Neustart kein Favorit über die Menüleiste hinzugefügt werden sollte." + #CRLF$
    
    MessageRequester(#AppName, Text)
    
    RunProgram("winduos.ini")
    
  EndIf
  
EndProcedure

Procedure Main()
  
  Protected WWE.l
  Protected Quit.l
  
  LoadSettings()
  
  If Not frmMain_Open() : End : EndIf
  
  RebuildMenue()
  
  If Not StartExplorer(GetSpecialFolder(#CSIDL_PROFILE), GetSpecialFolder(#CSIDL_PROGRAM_FILES)) : End : EndIf
  
  While WindowEvent() : Wend
  
  HideWindow(#frmMain, #False)
  
  Repeat
    
    WWE=WaitWindowEvent()
    
    Select WWE
      
      Case #PB_Event_SizeWindow
        ResizeGadget(#frmMain_Splitter, #PB_Ignore, ToolBarHeight(#frmMain_TB), WindowWidth(#frmMain), WindowHeight(#frmMain) - ToolBarHeight(#frmMain_TB) - StatusBarHeight(#frmMain_SB) - MenuHeight())
        ResizeGadgets()
        
      Case #PB_Event_Gadget
        
        Select EventGadget()
          
          Case #frmMain_Splitter
            ResizeGadgets()
            
        EndSelect
        
      Case #PB_Event_Menu
        
        Select EventMenu()
          
          Case #frmMain_Menu_Quit : Quit = #True
            
          Case #frmMain_Menu_AddFolders  : AddFolders()
          Case #frmMain_Menu_EditFolders : EditFolders()
          Case #frmMain_Menu_Help : MessageRequester(#AppName, "Sorry, Hilfe gibt es derzeit noch nicht.")
          Case #frmMain_Menu_Info : MessageRequester(#AppName, "Copyright (c) 2007" + #CRLF$ + "Peter Tübben" + #CRLF$ + "http://www.tuebben.de/tools")
            
          Default
            
            ForEach Favoriten()
              If EventMenu() = #frmMain_FavoritenFolder_Item + ListIndex(Favoriten())
                Explorer\LeftPath  = Favoriten()\LeftPath
                Explorer\RightPath = Favoriten()\RightPath
                ChangePathes()
                Break
              EndIf
            Next
            
        EndSelect
        
      Case #PB_Event_CloseWindow : Quit = #True
        
    EndSelect
    
  Until Quit = #True
  
  CloseWindow(#frmMain)
  
EndProcedure
  
Main()
a²+b²=mc²
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Der letzte Code lässt den Explorer nach dem Schließen abrauchen,
das hat mir jetzt den Crysis Demo Download versaut weil Firefox gleich mit abgeschmiert ist /:->
Naja warn ja erst 4 Prozent :wink:
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
scholly
Beiträge: 793
Registriert: 04.11.2005 21:30
Wohnort: Düsseldorf

Beitrag von scholly »

milan1612 hat geschrieben:Der letzte Code lässt den Explorer nach dem Schließen abrauchen
Bestätigt, allerdings laufen bei mir Firefox und VirtualDub (beim Encoden) problemlos weiter...
Ich bin blutiger PB-Anfänger.
seit 17.12.08: PB 4.3 unter XP Home(SP3)
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

milan1612 hat geschrieben:Der letzte Code lässt den Explorer nach dem Schließen abrauchen,
sorry for that! :oops:

Das Problem ist, dass leider nicht weiß, woran das liegt. Es könnte daran
liegen, dass der Explorer es mir übel nimmt, wenn ich ihn mit SetParent_()
in meine Applikation entführe und zu Programmschluss einfach das
Parent-Window unter seinem Hintern wegschieße.

In nachfolgendem Code setze ich den Explorer zum Programmende wieder
in seinen ursprünglichen Parent und schicke ihm dann ein WM_CLOSE.
Vielleicht funktioniert es nun?

Benutzung auf eigene Gefahr! ;-)

Code: Alles auswählen

; WinDuos

EnableExplicit

Enumeration ; Windows
  #frmMain
EndEnumeration
Enumeration ; Gadgets
  
  #frmMain_TB
  
  #frmMain_Container_1
  #frmMain_Container_2
  #frmMain_Splitter
  #frmMain_SB
  
  #frmMain_Menu
  #frmMain_Menu_Quit
  #frmMain_Menu_AddFolders
  #frmMain_Menu_EditFolders
  #frmMain_Menu_Help
  #frmMain_Menu_Info
  
  #frmMain_FavoritenFolder_Item ; Muss als letztes stehen
  
EndEnumeration

Structure s_Explorer
  
  Description.s
  LeftPath.s
  RightPath.s
  LefthWnd.l
  RighthWnd.l
  
  LeftAddressbarhWnd.l
  RightAddressbarhWnd.l
  
EndStructure

#AppName = "WinDuos"

Global Explorer.s_Explorer
Global AddressBarhWnd.l

#BufferSize = 2048

Global NewList Windows()
Global NewList Favoriten.s_Explorer()

; SetParentEx(), ResetParent() und GetOldParentWnd():
; http://www.aboutvb.de/khw/artikel/khwsetparentex.htm
Procedure.l SetParentEx(ChildWnd.l, NewParentWnd.l)
  Protected nOldParentWnd.l
  Protected nUserData.l
  nOldParentWnd = SetParent_(ChildWnd, NewParentWnd)
  nUserData = GetWindowLong_(ChildWnd, #GWL_USERDATA)
  If nUserData = 0 
    SetWindowLong_(ChildWnd, #GWL_USERDATA, nOldParentWnd)
  Else
    ProcedureReturn nOldParentWnd
  EndIf
EndProcedure
Procedure.l ResetParent(ChildWnd.l, OldParentWnd.l = 0)
  Protected nOldParentWnd.l
  If OldParentWnd > 0
    nOldParentWnd = OldParentWnd
  Else
    nOldParentWnd = GetWindowLong_(ChildWnd, #GWL_USERDATA)
    SetWindowLong_(ChildWnd, #GWL_USERDATA, 0)
  EndIf
  If nOldParentWnd
    SetParent_(ChildWnd, nOldParentWnd)
  Else
    ProcedureReturn #True
  EndIf
EndProcedure
Procedure.l GetOldParentWnd(ChildWnd.l)
  ProcedureReturn GetWindowLong_(ChildWnd, #GWL_USERDATA)
EndProcedure

Procedure GetAddressBarhWnd(hwnd.l, void.l)
  Protected a.s = Space(200)
  GetClassName_(hwnd, @a, 199)
  If a="Edit"
    AddressBarhWnd = hwnd
    ProcedureReturn 0
  EndIf
  ProcedureReturn 1
EndProcedure

Procedure SetStyles(ExplorerHandle.l)
  
  SetWindowLong_(ExplorerHandle, #GWL_EXSTYLE, GetWindowLong_(ExplorerHandle, #GWL_EXSTYLE) &~ #WS_EX_CLIENTEDGE )
  SetWindowLong_(ExplorerHandle, #GWL_EXSTYLE, GetWindowLong_(ExplorerHandle, #GWL_EXSTYLE) &~ #WS_EX_WINDOWEDGE )
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_DLGFRAME)
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_THICKFRAME)
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_OVERLAPPED )
  SetWindowLong_(ExplorerHandle, #GWL_STYLE,   GetWindowLong_(ExplorerHandle, #GWL_STYLE)   &~ #WS_BORDER)
  
EndProcedure

Procedure.s GetClassName(Handle.l)
  Protected ClassName.s = Space(#BufferSize)
  GetClassName_(Handle, @ClassName, #BufferSize)
  ProcedureReturn ClassName
EndProcedure
Procedure.s GetTitle(Handle.l)
  Protected Title.s = Space(#BufferSize)
  GetWindowText_(Handle, @Title, #BufferSize)
  ProcedureReturn Title
EndProcedure
Procedure EnumProc(Handle.l, lParam.l)
  
  Protected ClassName.s = GetClassName(Handle)
  
  If ClassName = "CabinetWClass" Or ClassName = "ExplorerWClass"
    If Not IsWindowVisible_(Handle)  ; Nur unsichtbare Fenster suchen
      AddElement(Windows())
      Windows()=Handle
    EndIf
  EndIf
  
  ProcedureReturn #True
  
EndProcedure

Procedure CloseExplorer()
  
  If Explorer\LefthWnd
    ; Explorer verstecken
    ShowWindow_(Explorer\LefthWnd,   #SW_HIDE)
    ; Ursprüngliche Parents wiederherstellen
    ResetParent(Explorer\LefthWnd)
    ; Explorer schliessen
    PostMessage_(Explorer\LefthWnd,  #WM_CLOSE, 0, 0)
    ; Solange warten, bis die Explorer nicht mehr da sind
    While IsWindow_(Explorer\LefthWnd)  : Delay(10) : Wend
  EndIf
  
  If Explorer\RighthWnd
    ; Explorer verstecken
    ShowWindow_(Explorer\RighthWnd,  #SW_HIDE)
    ; Ursprüngliche Parents wiederherstellen
    ResetParent(Explorer\RighthWnd)
    ; Explorer schliessen
    PostMessage_(Explorer\RighthWnd, #WM_CLOSE, 0, 0)
    ; Solange warten, bis die Explorer nicht mehr da sind
    While IsWindow_(Explorer\RighthWnd) : Delay(10) : Wend
  EndIf
  
EndProcedure

Procedure.s CorrectPath(sPath.s)
  
  ; Anpassung der Pfade
  ; Erlaubt "C:"          (mit abschliessendem Backslash)
  ; Erlaubt "C:\Programme" (ohne Backslash)
  ; dito mit UNC-Pfaden

  If Left(sPath, 2) = "\"
    If CountString(sPath, "") => 3
      If Right(sPath, 1) = "" : sPath = Left(sPath, Len(sPath)-1) : EndIf
    EndIf
  Else
    If CountString(sPath, "") => 2
      If Right(sPath, 1) = "" : sPath = Left(sPath, Len(sPath)-1) : EndIf
    EndIf
  EndIf
  
  ProcedureReturn sPath
  
EndProcedure

Procedure.l StartExplorer(LeftPath.s, RightPath.s)
  
  ; Debug LeftPath
  ; Debug RightPath
  
  LeftPath  = CorrectPath(Trim(LeftPath))
  RightPath = CorrectPath(Trim(RightPath))
  
  ; Debug LeftPath
  ; Debug RightPath
  
  If LCase(LeftPath) = LCase(RightPath)
    MessageRequester(#AppName, "Linker und rechter Pfad dürfen nicht identisch sein.")
    ProcedureReturn #False
  EndIf
  
  Protected ReturnValue.l
  Protected TimeOut.l
  
  NewList W_Before()
  NewList W_After()
  
  ; Enumeration der bereits vorhandenen Fenster
  
  ClearList(Windows())
  EnumWindows_(@EnumProc(), 0)
  
  ForEach Windows()
    AddElement(W_Before())
    W_Before()=Windows()
  Next
  
  Explorer\LeftPath  = LeftPath
  Explorer\RightPath = RightPath
  
  ReturnValue = RunProgram("explorer.exe", Explorer\LeftPath,  "", #PB_Program_Hide)
  ReturnValue = RunProgram("explorer.exe", Explorer\RightPath, "", #PB_Program_Hide)
  
  TimeOut = AddDate(Date(), #PB_Date_Second, 5) ; 5 Sekunden als Timeout (müsste eigentlich reichen)
  
  Repeat
    
    ; Enumeration der Fenster nach RunProgram()
    
    ClearList(Windows())
    EnumWindows_(@EnumProc(), 0)
    
    ClearList(W_After())
    ForEach Windows()
      AddElement(W_After())
      W_After()=Windows()
    Next
    
    If CountList(W_Before()) + 2 = CountList(W_After()) ; 2 neue Fenster hinzugekommen?
      
      ; Nun alte Fensterliste mit neuer vergleichen
      ; identische Fenster werden aus W_After() entfernt
      
      ForEach W_Before()
        ForEach W_After()
          If W_Before()=W_After()
            DeleteElement(W_After())
          EndIf
        Next
      Next
      
      ; Nun sind im Idealfall in W_After nur die von WinDuos
      ; gestarteten Explorer vorhanden
      
      ForEach W_After()
        
        ; Hier wird nur FindString() verwendet, da in der Titelleiste 
        ; nicht zwangsläufig der komplette Pfad steht
        
        If FindString(Explorer\LeftPath, GetTitle(W_After()), 1)
          Explorer\LefthWnd=W_After()
          DeleteElement(W_After())
        ElseIf FindString(Explorer\RightPath, GetTitle(W_After()), 1)
          Explorer\RighthWnd=W_After()
          DeleteElement(W_After())
        EndIf
        
      Next
      
      If Explorer\LefthWnd And Explorer\RighthWnd : Break : EndIf
      
    EndIf
    
    Delay(100)
    
    If Date() => TimeOut : Break : EndIf ; Timeout abgelaufen -> Raus aus der Schleife
    
  ForEver
  
  If Explorer\LefthWnd And Explorer\RighthWnd 
    
    AddressBarhWnd = 0 : EnumChildWindows_(Explorer\LefthWnd,  @GetAddressBarhWnd(), 0) : Explorer\LeftAddressbarhWnd  = AddressBarhWnd
    AddressBarhWnd = 0 : EnumChildWindows_(Explorer\RighthWnd, @GetAddressBarhWnd(), 0) : Explorer\RightAddressbarhWnd = AddressBarhWnd
    
    ; Adressen der Explorer-Adressleiste ermitteln
    
    If Explorer\LeftAddressbarhWnd And Explorer\RightAddressbarhWnd
      
      SetParentEx(Explorer\LefthWnd,  GadgetID(#frmMain_Container_1))
      SetParentEx(Explorer\RighthWnd, GadgetID(#frmMain_Container_2))
    
      SetStyles(Explorer\LefthWnd)
      SetStyles(Explorer\RighthWnd)
    
      ShowWindow_(Explorer\LefthWnd,  #SW_MAXIMIZE)
      ShowWindow_(Explorer\RighthWnd, #SW_MAXIMIZE)
      
      ProcedureReturn #True
      
    Else
      
      MessageRequester(#AppName, "Adressleiste ist nicht angeschaltet.")
      CloseExplorer()
      
    EndIf
    
  Else
    
    MessageRequester(#AppName, "Mindestens ein Explorer konnte nicht gestartet werden.")
    CloseExplorer()
    
  EndIf
  
EndProcedure
  
Procedure ChangePathes()
  
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_SETTEXT, 0, @Explorer\LeftPath)
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_LBUTTONDOWN ,#MK_LBUTTON, 0)
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_LBUTTONUP ,#MK_LBUTTON, 0) 
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_KEYDOWN, #VK_RETURN, 0) 
  SendMessage_(Explorer\LeftAddressbarhWnd, #WM_KEYUP, #VK_RETURN, 0) 
  
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_SETTEXT, 0, @Explorer\RightPath)
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_LBUTTONDOWN ,#MK_LBUTTON, 0)
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_LBUTTONUP ,#MK_LBUTTON, 0) 
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_KEYDOWN, #VK_RETURN, 0) 
  SendMessage_(Explorer\RightAddressbarhWnd, #WM_KEYUP, #VK_RETURN, 0) 
  
EndProcedure

Procedure RebuildMenue()
  
  If CreateMenu(#frmMain_Menu, WindowID(#frmMain))
    
    MenuTitle("Datei")
    MenuItem(#frmMain_Menu_Quit, "Beenden")
    
    MenuTitle("Ordner")
    ForEach Favoriten()
      MenuItem(#frmMain_FavoritenFolder_Item + ListIndex(Favoriten()), Favoriten()\Description)  
    Next
    
    MenuBar()
    MenuItem(#frmMain_Menu_AddFolders, "Aktuelle Ordneransicht hinzufügen")
    MenuItem(#frmMain_Menu_EditFolders, "Favoriten bearbeiten")
    
    MenuTitle("Hilfe")
    MenuItem(#frmMain_Menu_Help, "Hilfe...")
    MenuItem(#frmMain_Menu_Info, "Über...")
    
  EndIf
  
EndProcedure

Procedure LoadSettings()
  
  Protected Counter.l
  Protected Description.s
  Protected LeftPath.s
  Protected RightPath.s
  
  OpenPreferences("winduos.ini")
  
  ClearList(Favoriten())
  
  Repeat
    
    Counter + 1
    
    Description = ReadPreferenceString("description" + Str(Counter), "")
    LeftPath    = ReadPreferenceString("leftpath"    + Str(Counter), "")
    RightPath   = ReadPreferenceString("rightpath"   + Str(Counter), "")
    
    If Description And LeftPath And RightPath
      
      AddElement(Favoriten())
      
      Favoriten()\Description = Description
      Favoriten()\LeftPath    = LeftPath
      Favoriten()\RightPath   = RightPath
      
    EndIf
    
  Until Counter = 100
  
  ClosePreferences()
  
EndProcedure
Procedure SaveSettings()
  
  Protected Counter.l
  
  If CreatePreferences("winduos.ini")
    
    ForEach Favoriten()
      
      Counter + 1
      
      WritePreferenceString("description" + Str(Counter), Favoriten()\Description)
      WritePreferenceString("leftpath"    + Str(Counter), Favoriten()\LeftPath)
      WritePreferenceString("rightpath"   + Str(Counter), Favoriten()\RightPath)
      
    Next
    
    ClosePreferences()
    
  EndIf
  
EndProcedure

Procedure AddFolders()
  
  Protected Description.s
  Protected TextLen.l
  Protected LeftPath.s
  Protected RightPath.s
  
  Description = InputRequester("Favorit hinzufügen", "Bitte geben Sie eine Bezeichnung ein.", "")
  
  If Description
    
    TextLen = SendMessage_(Explorer\LeftAddressbarhWnd, #WM_GETTEXTLENGTH, 0, 0)
    If TextLen
      TextLen + 1
      LeftPath = Space(TextLen)
      SendMessage_(Explorer\LeftAddressbarhWnd, #WM_GETTEXT, TextLen, @LeftPath)
    EndIf
    
    TextLen = SendMessage_(Explorer\RightAddressbarhWnd, #WM_GETTEXTLENGTH, 0, 0)
    If TextLen
      TextLen + 1
      RightPath = Space(TextLen)
      SendMessage_(Explorer\RightAddressbarhWnd, #WM_GETTEXT, TextLen, @RightPath)
    EndIf
    
    ; Debug LeftPath
    ; Debug RightPath
    
    AddElement(Favoriten())
    
    Favoriten()\Description = Description
    Favoriten()\LeftPath    = LeftPath
    Favoriten()\RightPath   = RightPath
    
    RebuildMenue()
    
    SaveSettings()
    
  EndIf
  
EndProcedure
Procedure EditFolders()
  
  Protected Text.s
  
  Text + "Momentan können die Favoriten nur in der INI-Datei geändert werden." + #CRLF$
  Text + #CRLF$
  Text + "Soll die INI-Datei nun geöffnet werden?" + #CRLF$
  
  If MessageRequester(#AppName, Text, #PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes
    
    Text = "Bitte denken Sie daran, dass die geänderten Favoriten erst" + #CRLF$
    Text + "nach einem Neustart von " + #AppName + " zur Verfügung stehen" + #CRLF$
    Text + "und in dem Zeitraum zwischen den Änderungen in der INI und dem" + #CRLF$
    Text + "Neustart kein Favorit über die Menüleiste hinzugefügt werden sollte." + #CRLF$
    
    MessageRequester(#AppName, Text)
    
    RunProgram("winduos.ini")
    
  EndIf
  
EndProcedure

Procedure.l frmMain_Open()
  
  Protected WindowFlags.l
  
  WindowFlags | #PB_Window_SystemMenu
  WindowFlags | #PB_Window_MinimizeGadget
  WindowFlags | #PB_Window_MaximizeGadget
  WindowFlags | #PB_Window_SizeGadget
  WindowFlags | #PB_Window_Invisible
  WindowFlags | #PB_Window_ScreenCentered
  
  If OpenWindow(#frmMain, #PB_Ignore, #PB_Ignore, 800, 600, #AppName, WindowFlags)
    If CreateGadgetList(WindowID(#frmMain))
      
      If CreateToolBar(#frmMain_TB, WindowID(#frmMain))
        
        If CreateStatusBar(#frmMain_SB, WindowID(#frmMain))
          
          ContainerGadget(#frmMain_Container_1, 0, 0, 0, 0) : CloseGadgetList()
          ContainerGadget(#frmMain_Container_2, 0, 0, 0, 0) : CloseGadgetList()
          
          SetWindowLong_(GadgetID(#frmMain_Container_1), #GWL_STYLE, GetWindowLong_(GadgetID(#frmMain_Container_1), #GWL_STYLE) | #WS_CLIPCHILDREN) 
          SetWindowLong_(GadgetID(#frmMain_Container_2), #GWL_STYLE, GetWindowLong_(GadgetID(#frmMain_Container_2), #GWL_STYLE) | #WS_CLIPCHILDREN) 
          
          SplitterGadget(#frmMain_Splitter, 0, ToolBarHeight(#frmMain_TB), WindowWidth(#frmMain), WindowHeight(#frmMain) - ToolBarHeight(#frmMain_TB) - StatusBarHeight(#frmMain_SB), #frmMain_Container_1, #frmMain_Container_2, #PB_Splitter_Vertical)
          
          SetWindowLong_(GadgetID(#frmMain_Splitter), #GWL_STYLE, GetWindowLong_(GadgetID(#frmMain_Splitter), #GWL_STYLE) | #WS_CLIPCHILDREN) 
          
          SetWindowLong_(WindowID(#frmMain), #GWL_STYLE, GetWindowLong_(WindowID(#frmMain), #GWL_STYLE) | #WS_CLIPCHILDREN) 

          SmartWindowRefresh(#frmMain, #True)
          
          ProcedureReturn #True
          
        EndIf
      EndIf
    EndIf
  EndIf
  
EndProcedure

Procedure ResizeGadgets()
  
  If Explorer\LefthWnd
    MoveWindow_(Explorer\LefthWnd,  0, 0, GadgetWidth(#frmMain_Container_1), GadgetHeight(#frmMain_Container_1), #True)
  EndIf
  If Explorer\RighthWnd
    MoveWindow_(Explorer\RighthWnd, 0, 0, GadgetWidth(#frmMain_Container_2), GadgetHeight(#frmMain_Container_2), #True)
  EndIf
  
EndProcedure
  
Procedure.s GetSpecialFolder(Folder.l)
  Protected *itemid.ITEMIDLIST = #Null
  If SHGetSpecialFolderLocation_ (0, Folder, @*itemid) = #NOERROR
    Protected location.s = Space (#MAX_PATH)
    If SHGetPathFromIDList_ (*itemid, @location)
      If Right(location, 1) <> "" : location + "" : EndIf
      ProcedureReturn location
    EndIf
  EndIf
EndProcedure



Procedure Main()
  
  Protected WWE.l
  Protected Quit.l
  
  LoadSettings()
  
  If Not frmMain_Open() : End : EndIf
  
  RebuildMenue()
  
  If Not StartExplorer(GetSpecialFolder(#CSIDL_PROFILE), GetSpecialFolder(#CSIDL_PROGRAM_FILES)) : End : EndIf
  
  While WindowEvent() : Wend
  
  HideWindow(#frmMain, #False)
  
  Repeat
    
    WWE=WaitWindowEvent()
    
    Select WWE
      
      Case #PB_Event_SizeWindow
        ResizeGadget(#frmMain_Splitter, #PB_Ignore, ToolBarHeight(#frmMain_TB), WindowWidth(#frmMain), WindowHeight(#frmMain) - ToolBarHeight(#frmMain_TB) - StatusBarHeight(#frmMain_SB) - MenuHeight())
        ResizeGadgets()
        
      Case #PB_Event_Gadget
        
        Select EventGadget()
          
          Case #frmMain_Splitter
            ResizeGadgets()
            
        EndSelect
        
      Case #PB_Event_Menu
        
        Select EventMenu()
          
          Case #frmMain_Menu_Quit : Quit = #True
            
          Case #frmMain_Menu_AddFolders  : AddFolders()
          Case #frmMain_Menu_EditFolders : EditFolders()
          Case #frmMain_Menu_Help : MessageRequester(#AppName, "Sorry, Hilfe gibt es derzeit noch nicht.")
          Case #frmMain_Menu_Info : MessageRequester(#AppName, "Copyright (c) 2007" + #CRLF$ + "Peter Tübben" + #CRLF$ + "http://www.tuebben.de/tools")
            
          Default
            
            ForEach Favoriten()
              If EventMenu() = #frmMain_FavoritenFolder_Item + ListIndex(Favoriten())
                Explorer\LeftPath  = Favoriten()\LeftPath
                Explorer\RightPath = Favoriten()\RightPath
                ChangePathes()
                Break
              EndIf
            Next
            
        EndSelect
        
      Case #PB_Event_CloseWindow : Quit = #True
        
    EndSelect
    
  Until Quit = #True
  
EndProcedure
  
Main()

HideWindow(#frmMain, #True)

CloseExplorer()
a²+b²=mc²
Benutzeravatar
D@nte
Beiträge: 324
Registriert: 24.04.2007 15:33
Wohnort: Berlin

Beitrag von D@nte »

Läuft auf den ersten Blick ohne Probleme
Benutzeravatar
scholly
Beiträge: 793
Registriert: 04.11.2005 21:30
Wohnort: Düsseldorf

Beitrag von scholly »

Bestätigt, einmal flackern, aber sonst nix auffälliges.
Ich bin blutiger PB-Anfänger.
seit 17.12.08: PB 4.3 unter XP Home(SP3)
Benutzeravatar
milan1612
Beiträge: 810
Registriert: 15.04.2007 17:58

Beitrag von milan1612 »

Wenn ich es jetzt beende, schließt sich das Fenster und das Programm hängt sich auf.
Wenn ich den Prozess beende wird der Explorer wieder mitgekillt /:->
Gottseidank hab ich Crysis (<- Geil) fertig geladen :wink:
Bin nur noch sehr selten hier, bitte nur noch per PN kontaktieren
Benutzeravatar
dige
Beiträge: 1239
Registriert: 08.09.2004 08:53

Beitrag von dige »

:allright: vor allem die Idee ist genial
"Papa, ich laufe schneller - dann ist es nicht so weit."
Benutzeravatar
Kiffi
Beiträge: 10714
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Beitrag von Kiffi »

dige hat geschrieben::allright: vor allem die Idee ist genial
Danke! :-)
milan1612 hat geschrieben:Wenn ich es jetzt beende, schließt sich das Fenster und das Programm hängt sich auf.
mh, das Aufhängen liegt vermutlich daran, dass die Schleife in
CloseExplorer() nicht verlassen wird. Infolgedessen würde ich vermuten,
dass PostMessage_(Explorer\[handle], #WM_CLOSE, 0, 0) bei Dir nicht
ordnungsgemäß ausgeführt wird.

Kannst Du bitte noch einmal den Code starten? Zuvor solltest Du testweise
mal SetStyles(Explorer\LefthWnd) und SetStyles(Explorer\RighthWnd)
auskommentieren.

Danke & Grüße ... Kiffi
a²+b²=mc²
Antworten