rene1976
Goto Top

FolderBrowserDialog - SelectedPath in sichtbaren Bereich anzeigen

Hallo,

Wir haben beim FolderBrowserDialog mit vb.net über SelectedPath einen Netzwerkpfad voreingestellt.
Dieser ist leider nie im sichtbaren Bereich des Dialoges.
Der Dialog fängt immer oben mit Desktop an.
Man muss immer weit herunterscrollen um zum vorausgewählten Ordner zu kommen.

Kennt jemand einen Trick wie man den vorausgewählten Ordner automatisch zentriert in den sichtbaren Bereich der Liste bekommt?
Der Standard .net FolderBrowserDialog hat so gut wie keine Einstellungsmöglichkeiten.

Noch dazu würde ich gerne auch die Unterordner sofort sehen können, FALLS es in dem vorausgewählten Ordner überhaupt Unterordner gibt.
Also den TreeView im SelectedPath sofort komplett aufklappen.

Weiß jemand wie man das implementiert?

Und warum gibt es das nicht schon seit Jahren standardmäßig?
Das kann doch jeder mal gebrauchen.

Gruß,

Rene

Content-Key: 282543

Url: https://administrator.de/contentid/282543

Printed on: April 19, 2024 at 23:04 o'clock

Member: emeriks
Solution emeriks Sep 11, 2015, updated at Sep 16, 2015 at 13:49:39 (UTC)
Goto Top
Hi,
daran sind schon andere verzweifelt. Ich selbst habe uns dafür eigene Controls entworfen. Andere greifen auf vorhandene im Web zurück.
Such mal bei Google. da kommen z.B.
http://stackoverflow.com/questions/6942150/why-folderbrowserdialog-dial ...
http://stackoverflow.com/questions/12429477/folderbrowserdialog-showing ...
http://stackoverflow.com/questions/12429477/folderbrowserdialog-showing ...

Keine Ahnung, ob die fruchten. Nur so als Hinweis.

E.
Member: Rene1976
Rene1976 Sep 11, 2015 at 09:20:15 (UTC)
Goto Top
Danke für die schnelle Antwort.
Wenigstens bin ich nicht allein.
Das ist schon ein Trauerspiel.
Member: colinardo
Solution colinardo Sep 12, 2015, updated at Sep 16, 2015 at 13:45:43 (UTC)
Goto Top
Hallo René,
das lässt sich mit einer kleinen AutoIt-EXE machen:
#NoTrayIcon
$path = "Desktop|Computer|Daten (D:)|Eigene Bilder"  
$hwnd = WinWaitActive("Ordner suchen",10)  
ControlTreeView($hwnd,"","[CLASS:SysTreeView32; INSTANCE:1]","Select",$path)  
ControlTreeView($hwnd,"","[CLASS:SysTreeView32; INSTANCE:1]","Expand",$path)  
Den Pfad zum gewünschten Ordner musst du in Zeile 2 anpassen. Siehe dazu:
https://www.autoitscript.com/autoit3/docs/functions/ControlTreeView.htm

Und dann so in deine Anwendung einbauen:
Dim f As New FolderBrowserDialog
With f
    .RootFolder = Environment.SpecialFolder.Desktop
    .SelectedPath = "D:\Bilder"  
    Process.Start("C:\script.exe")  
    .ShowDialog()
End With
Das ganze lässt sich natürlich mit etwas Aufwand und der Win32-API nachbauen und direkt in VB.Net einbauen.

Grüße Uwe
Member: colinardo
Solution colinardo Sep 12, 2015, updated at Sep 16, 2015 at 13:45:33 (UTC)
Goto Top
Das ganze lässt sich natürlich mit etwas Aufwand und der Win32-API nachbauen und direkt in VB.Net einbauen.
So habe mir das gerade mal in dieser Hinsicht angeschaut und dir was mit VB.Net zusammengecodet. Läuft hier testweise unter Windows 7 x64 und Windows 10 x64 :
Unter Windows 10 wurde das Verhalten aber schon behoben. Was natürlich verwundert ist das es ja bereits eine MSG_ID für genau das Verhalten gibt was man eigentlich erwartet, nämlich TVM_ENSUREVISIBLE das den selektierten Knoten ins Sichtfeld scrollt. Das macht mein Code in diesem Fall, und zusätzlich wird der Knoten noch expanded wenn es Unterordner gibt.

Das Beispiel besteht jetzt nur aus einer Form mit einem einzigen Button (Name: btnOpenFolderBrowser)
Imports System.Runtime.InteropServices

Public Class Form1
    WithEvents tm As New Timer

    Const TV_FIRST As Integer = &H1100
    Const TVGN_ROOT As Integer = &H0
    Const TVGN_NEXT As Integer = &H1
    Const TVGN_CHILD As Integer = &H4
    Const TVGN_FIRSTVISIBLE As Integer = &H5
    Const TVGN_NEXTVISIBLE As Integer = &H6
    Const TVGN_CARET As Integer = &H9
    Const TVM_SELECTITEM As Integer = (TV_FIRST + 11)
    Const TVM_GETNEXTITEM As Integer = (TV_FIRST + 10)
    Const TVM_GETITEM As Integer = (TV_FIRST + 12)
    Const TVM_ENSUREVISIBLE As Long = (TV_FIRST + 20)
    Const TVM_EXPAND As Long = (TV_FIRST + 2)
    Const TVE_EXPAND As Integer = &H2

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _  
    Public Shared Function FindWindowEx(ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As IntPtr
    End Function
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _  
    Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
    End Function
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _  
    Public Shared Function SendMessage(hWnd As IntPtr, Msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
    End Function
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _  
    Public Shared Function GetWindowThreadProcessId(hwnd As IntPtr, lpdwProcessId As IntPtr) As IntPtr
    End Function


    Private Sub btnOpenFolderBrowser_Click(sender As System.Object, e As System.EventArgs) Handles btnOpenFolderBrowser.Click
        Dim fBrowser As New FolderBrowserDialog
        tm.Interval = 200
        With fBrowser
            .SelectedPath = "C:\Windows\system32"  
            tm.Start()
            .ShowDialog()
            tm.Stop()
        End With
    End Sub

    Private Sub tm_Tick(sender As Object, e As System.EventArgs) Handles tm.Tick
        'Get TreeView Control on Dialog  
        Dim controlHwnd As IntPtr = getTVHandle(IntPtr.Zero)

        If (controlHwnd <> 0) Then
            'Get selected node  
            Dim selectedNode As IntPtr = SendMessage(controlHwnd, TVM_GETNEXTITEM, TVGN_CARET, IntPtr.Zero)
            'scroll selected item into view  
            SendMessage(controlHwnd, TVM_ENSUREVISIBLE, IntPtr.Zero, selectedNode)
            'expand node  
            SendMessage(controlHwnd, TVM_EXPAND, TVE_EXPAND, selectedNode)
            'stop timer  
            tm.Stop()
        End If
    End Sub

    Function getTVHandle(handle As IntPtr) As IntPtr
        Dim parent As IntPtr, returnTVHandle As Boolean
        If handle = IntPtr.Zero Then
            parent = FindWindow("#32770", Nothing)  
            If Not isFromSameThread(parent) Then
                Return getTVHandle(parent)
            Else
                returnTVHandle = True
            End If
        Else
            parent = FindWindowEx(IntPtr.Zero, handle, "#32770", Nothing)  
            If Not isFromSameThread(parent) Then
                Return getTVHandle(parent)
            Else
                returnTVHandle = True
            End If
        End If
        If returnTVHandle Then
            'Get Control handle  
            Dim subWin As IntPtr = FindWindowEx(parent, IntPtr.Zero, "SHBrowseForFolder ShellNameSpace Control", Nothing)  
            Dim controlHwnd As IntPtr = FindWindowEx(subWin, IntPtr.Zero, "SysTreeView32", Nothing)  
            Return controlHwnd
        End If
    End Function

    Function isFromSameThread(handle As IntPtr) As Boolean
        Dim cID As Integer = AppDomain.GetCurrentThreadId()
        Dim fID As Integer = GetWindowThreadProcessId(handle, IntPtr.Zero)
        Return (cID = fID)
    End Function
End Class

Hier noch die kompilierte EXE zum testen, sie öffnet den FolderBrowser im Beispiel mit dem initialen Pfad C:\Windows\system32 mit aufgeklappten Unterordnern:
FolderBrowserWithScrollIntoView_282543.exe

Grüße Uwe

Falls der Beitrag gefällt, seid so nett und unterstützt mich durch eine kleine Spende / If you like my contribution please support me and donate
Member: Rene1976
Rene1976 Sep 16, 2015 at 13:45:29 (UTC)
Goto Top
Hi Uwe,

danke für die die Mühe.
Ich hab deine .exe mal auf meinem PC unter Win 8.1 ausprobiert.
Wie ich auch schon gelesen habe, gibt es bei unterschiedlichen Windows Versionen bei anderen Versuchen Probleme.
Bei uns muss sie unter Win 7, 8.1 und 10 jeweils unter x32 und x64 laufen, ggf. sogar noch auf drei Win XP PCs.
Dein Code läuft auf Win 8.1 so wie gewollt und wie MS es von Anfang an hätte zur verfügen stellen sollen.
Ich werde deinen Code in den nächsten Tagen bei mir versuchen einzubauen und zu testen.

Besten Dank.

Rene
Member: colinardo
colinardo Sep 16, 2015, updated at Sep 17, 2015 at 07:22:56 (UTC)
Goto Top
Zitat von @Rene1976:
Wie ich auch schon gelesen habe, gibt es bei unterschiedlichen Windows Versionen bei anderen Versuchen Probleme.
Ich kann dir auch sagen warum, weil unter XP der Dialog noch anderst aufgebaut ist.
In den neueren Dialogen ist das TreeView Control verschachtelter im Dialog untergebracht (Unterfenster, kannst du mit Tools wie Spy++ sehr schön sehen), was unter XP noch nicht der Fall ist, aber das ließe sich noch in dem Code unterbringen wenn das erforderlich ist.

NACHTRAG: Unter XP SP3 wurde der Code ebenfalls erfolgreich getestet.