Pourquoi le dialogue FolderBrowserDialog ne fait pas défiler vers le dossier sélectionné?

Comme le montre cette capture d'écran, le dossier sélectionné n'est pas dans la vue. Il doit être déroulé pour visualiser le dossier sélectionné.

enter image description here

même dialogue affiche le dossier sélectionné visible sur l'ordinateur différent

enter image description here

Je l'ai lancé sur deux ordinateurs ayant windows 7. Il fonctionne correctement sur l'un mais pas sur la 2e. Il ressemble à quelque chose avec des fenêtres environnement plutôt un problème de code? Quelqu'un peut-il suggérer une correction?

il n'y a pas de changement de code. J'ai utilisé des chemins plus longs à partir de disques différents, mais les résultats sont les mêmes.

private void TestDialog_Click ( object sender, EventArgs e )
        {
            //Last path store the selected path, to show the same directory as selected on next application launch.
            //Properties.Settings.Default.LastPath

            FolderBrowserDialog dlgFolder = new FolderBrowserDialog ();

            dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;

            dlgFolder.SelectedPath = Properties.Settings.Default.LastPath;

            if (dlgFolder.ShowDialog () == System.Windows.Forms.DialogResult.OK)
            {

                Properties.Settings.Default.LastPath = dlgFolder.SelectedPath;               

                Properties.Settings.Default.Save ();
            }

        }
65
demandé sur Paul Ogilvie 2011-08-04 17:19:03

14 réponses

Le problème fondamental est une mauvaise décision de conception dans le FolderBrowserDialog . Tout d'abord, nous devons réaliser que le FolderBrowserDialog n'est pas un contrôle .NET, mais est plutôt le Common Dialog et fait partie de Windows. Le concepteur de cette boîte de dialogue a choisi de ne pas envoyer le message TVM_ENSUREVISIBLE après l'affichage de la boîte de dialogue et la sélection d'un dossier initial. Ce message fait défiler le contrôle TreeView de sorte que l'élément sélectionné soit visible dans la fenêtre.

donc, tout ce que nous devons faire pour corriger cela est d'envoyer la vue sur les arbres qui fait partie du message FolderBrowserDialog le TVM_ENSUREVISIBLE et tout sera grand. Droit? Eh bien, pas si vite. C'est en effet la réponse, mais il y a certaines choses dans nos.

  • tout d'abord, parce que le FolderBrowserDialog n'est pas vraiment un .NET control, il n'a pas une collection interne Controls . Cela signifie que nous ne pouvons pas simplement trouver et accéder au TreeView contrôle de l'enfant .NET.

  • Deuxièmement, les concepteurs de la classe .NET FolderBrowserDialog ont décidé de sceau cette classe. Cette décision malheureuse nous empêche d'en dériver et d'Outrepasser le gestionnaire de messages de fenêtre. Si nous avions pu le faire, nous aurions peut-être essayé de poster le message TVM_ENSUREVISIBLE lorsque nous avons reçu le message WM_SHOWWINDOW dans le gestionnaire de messages.

  • la troisième question Est que nous ne pouvons pas envoyer le message TVM_ENSUREVISIBLE jusqu'à ce que le contrôle de vue D'arbre existe réellement comme une fenêtre réelle, et il n'existe pas jusqu'à ce que nous appelions la méthode ShowDialog . Cependant, cette méthode bloque, de sorte que nous n'aurons pas l'occasion de poster notre message Une fois que cette méthode sera appelée.

pour contourner ces problèmes, j'ai créé une classe d'Assistant statique avec une seule méthode qui peut être utilisée pour montrer un FolderBrowserDialog , et fera défiler vers le dossier sélectionné. Je gère cela en démarrant un court Timer juste avant d'appeler la méthode ShowDialog du dialogue, puis en traquant la poignée de la commande TreeView dans le handler Timer (c.-à-d. après que le dialogue est affiché) et en envoyant notre message TVM_ENSUREVISIBLE .

Cette solution n'est pas parfaite car elle dépend d'une connaissance préalable sur la FolderBrowserDialog . Plus précisément, je trouve l' dialogue utilisant son titre de fenêtre. Ceci rompt avec les installations non-anglaises. Je traque les contrôles de l'enfant dans le dialogue en utilisant leur IDs d'Item de dialogue, plutôt que le texte du titre ou le nom de la classe, parce que je pensais que ce serait plus fiable avec le temps.

ce code a été testé sur Windows 7 (64 bits), et Windows XP.

voici le code: (Vous pourriez avoir besoin de: using System.Runtime.InteropServices; )

public static class FolderBrowserLauncher
{
    /// <summary>
    /// Using title text to look for the top level dialog window is fragile.
    /// In particular, this will fail in non-English applications.
    /// </summary>
    const string _topLevelSearchString = "Browse For Folder";

    /// <summary>
    /// These should be more robust.  We find the correct child controls in the dialog
    /// by using the GetDlgItem method, rather than the FindWindow(Ex) method,
    /// because the dialog item IDs should be constant.
    /// </summary>
    const int _dlgItemBrowseControl = 0;
    const int _dlgItemTreeView = 100;

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// Some of the messages that the Tree View control will respond to
    /// </summary>
    private const int TV_FIRST = 0x1100;
    private const int TVM_SELECTITEM = (TV_FIRST + 11);
    private const int TVM_GETNEXTITEM = (TV_FIRST + 10);
    private const int TVM_GETITEM = (TV_FIRST + 12);
    private const int TVM_ENSUREVISIBLE = (TV_FIRST + 20);

    /// <summary>
    /// Constants used to identity specific items in the Tree View control
    /// </summary>
    private const int TVGN_ROOT = 0x0;
    private const int TVGN_NEXT = 0x1;
    private const int TVGN_CHILD = 0x4;
    private const int TVGN_FIRSTVISIBLE = 0x5;
    private const int TVGN_NEXTVISIBLE = 0x6;
    private const int TVGN_CARET = 0x9;


    /// <summary>
    /// Calling this method is identical to calling the ShowDialog method of the provided
    /// FolderBrowserDialog, except that an attempt will be made to scroll the Tree View
    /// to make the currently selected folder visible in the dialog window.
    /// </summary>
    /// <param name="dlg"></param>
    /// <param name="parent"></param>
    /// <returns></returns>
    public static DialogResult ShowFolderBrowser( FolderBrowserDialog dlg, IWin32Window parent = null )
    {
        DialogResult result = DialogResult.Cancel;
        int retries = 10;

        using (Timer t = new Timer())
        {
            t.Tick += (s, a) =>
            {
                if (retries > 0)
                {
                    --retries;
                    IntPtr hwndDlg = FindWindow((string)null, _topLevelSearchString);
                    if (hwndDlg != IntPtr.Zero)
                    {
                        IntPtr hwndFolderCtrl = GetDlgItem(hwndDlg, _dlgItemBrowseControl);
                        if (hwndFolderCtrl != IntPtr.Zero)
                        {
                            IntPtr hwndTV = GetDlgItem(hwndFolderCtrl, _dlgItemTreeView);

                            if (hwndTV != IntPtr.Zero)
                            {
                                IntPtr item = SendMessage(hwndTV, (uint)TVM_GETNEXTITEM, new IntPtr(TVGN_CARET), IntPtr.Zero);
                                if (item != IntPtr.Zero)
                                {
                                    SendMessage(hwndTV, TVM_ENSUREVISIBLE, IntPtr.Zero, item);
                                    retries = 0;
                                    t.Stop();
                                }
                            }
                        }
                    }
                }

                else
                {
                    //
                    //  We failed to find the Tree View control.
                    //
                    //  As a fall back (and this is an UberUgly hack), we will send
                    //  some fake keystrokes to the application in an attempt to force
                    //  the Tree View to scroll to the selected item.
                    //
                    t.Stop();
                    SendKeys.Send("{TAB}{TAB}{DOWN}{DOWN}{UP}{UP}");
                }
            };

            t.Interval = 10;
            t.Start();

            result = dlg.ShowDialog( parent );
        }

        return result;
    }
}
73
répondu Brad Oestreicher 2017-02-23 16:10:06

j'ai utilisé une solution de contournement de https://www.daniweb.com/software-development/csharp/threads/300578/folderbrowserdialog-expanding-the-selected-directory -

FolderBrowserDialog^ oFBD = gcnew FolderBrowserDialog;
oFBD->RootFolder = Environment::SpecialFolder::MyComputer;
oFBD->SelectedPath = i_sPathImport;
oFBD->ShowNewFolderButton = false;     // use if appropriate in your application
SendKeys::Send ("{TAB}{TAB}{RIGHT}");  // <<-- Workaround
::DialogResult oResult = oFBD->ShowDialog ();

ce n'est pas la meilleure façon, mais ça marche pour moi.

Sans le RootFolder il ne fonctionne PAS sur le premier appel, mais sur le 2ème et suivants. Avec elle, il fonctionne toujours.

comme d'autres l'ont fait remarquer, cette défaillance est dépendant du système d'exploitation:

J'utilise Win 7 Pro x64 SP1

7
répondu Tobias Knauss 2015-04-17 06:32:50

je sais que ce fil est très ancien, mais avec les méthodes d'extension, cela peut être ajouté au FolderBrowserDialog.Méthode ShowDialog, puis utilisée à plusieurs reprises si nécessaire.

l'échantillon (ci-dessous) utilise simplement la méthode easy SendKeys (ce que je déteste faire, mais dans ce cas, cela fonctionne bien). Lorsque vous utilisez la méthode SendKeys pour passer au dossier sélectionné dans la boîte de dialogue, si vous déboguez cela dans Visual Studio, alors l'appel SendKeys s'applique à la fenêtre courante, qui serait la fenêtre de VS active. Pour être plus infaillible et pour éviter que la mauvaise fenêtre n'obtienne le message SendKeys, alors la méthode d'extension contiendrait les appels de méthode externes pour envoyer des messages à la fenêtre spécifique similaire à ce que Marc F a posté, mais traduit en C#.

internal static class FolderBrowserDialogExtension
{
    public static DialogResult ShowDialog(this FolderBrowserDialog dialog, bool scrollIntoView)
    {
        return ShowDialog(dialog, null, scrollIntoView);
    }

    public static DialogResult ShowDialog(this FolderBrowserDialog dialog, IWin32Window owner, bool scrollIntoView)
    {
        if (scrollIntoView)
        {
            SendKeys.Send("{TAB}{TAB}{RIGHT}");
        }

        return dialog.ShowDialog(owner);
    }
}
6
répondu Brien Halstead 2016-09-10 04:07:21

j'ai lu dans différents forums que cela pourrait être dû à RootFolder parce que SelectedPath et RootFolder sont mutuellement exclusifs, ce qui signifie que les deux ne peuvent pas coexister mais avec rootFolder par défaut(.Desktop), il permet, au moins, l'escalade de l'arbre(naviguer le lecteur/dossiers).

cependant, si RootFolder est changé à autre que le bureau, vous ne seriez pas en mesure de naviguer à chemins UNC.

réponse à Hans Passant: J'ai essayé cette Extension de dialogue, qui a TextBox, mais pas de chance.

personnaliser le dialogue Parcourir pour le dossier pour afficher le chemin

3
répondu Munawar 2017-05-23 11:47:19

sur VB.Net code, il suffit de mettre cette ligne de code juste avant d'afficher la boîte de dialogue.

SendKeys.Send ("{TAB}{TAB}{RIGHT}")
3
répondu Loi Condes 2016-08-08 20:05:55

j'ai trouvé que:

  1. si .SelectedPath se termine par"\", le dialogue défilera vers le bas pour rendre le chemin visible.
  2. si .SelectedPath ne se termine pas par"\", le chemin est toujours sélectionné, mais n'est pas garanti visible.
2
répondu René 2015-01-12 10:01:50

j'ai calculé quelque chose en VB.NET il serait donc facile de le transformer en C#. Je suis français, et je suis débutant en VB. De toute façon, vous pouvez essayer ma solution.

Mon idée est de lancer une tâche asynchrone juste avant de montrer la folderBrowserDialog .

j'ai trouvé cela moi-même, mais J'ai été inspiré par Brad post. Voici mon code:

Imports System.Threading.Tasks
Imports Microsoft.VisualBasic.FileIO.FileSystem

Public Enum GW
    HWNDFIRST = 0
    HWNDLAST = 1
    HWNDNEXT = 2
    HWNDPREV = 3
    OWNER = 4
    CHILD = 5
    ENABLEDPOPUP = 6
End Enum

Public Declare Function SendMessageW Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal msg As UInteger, ByVal wParam As Integer, <MarshalAs(UnmanagedType.LPWStr)> ByVal lParam As String) As IntPtr
Public Declare Function FindWindowExW Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszClass As String, <MarshalAs(UnmanagedType.LPWStr)> ByVal lpszWindow As String) As IntPtr
Public Declare Function GetWindow Lib "user32" (ByVal hwnd As IntPtr, ByVal wCmd As Long) As Long
Public Declare Function GetDesktopWindow Lib "user32" () As IntPtr
Public Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As IntPtr, ByVal lpClassName As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer

Private Sub FolderBrowserDialog_EnsureVisible(FB As FolderBrowserDialog, _Owner As IntPtr)
    Dim hwnd As IntPtr
    Dim sClassname As New System.Text.StringBuilder(256)
    Thread.Sleep(50)                                     'necessary to let FolderBrowserDialog construct its window
    hwnd = GetDesktopWindow()                            'Desktop window handle.
    hwnd = GetWindow(hwnd, GW.CHILD)                     'We will find all children.
    Do Until hwnd = 0
        If GetWindow(hwnd, GW.OWNER) = _Owner Then       'If one window is owned by our main window...
            GetClassName(hwnd, sClassname, 255)
            If sClassname.ToString = "#32770" Then       'Check if the class is FolderBrowserDialog.
                Exit Do                                  'Then we found it.
            End If
        End If
        hwnd = GetWindow(hwnd, GW.HWNDNEXT)              'Next window.
    Loop                                                 'If no found then exit.
    If hwnd = 0 Then Exit Sub
    Dim hChild As IntPtr = 0
    Dim hTreeView As IntPtr = 0
    Dim i As Integer = 0
    Do
        i += 1
        If i > 1000 Then Exit Sub                                       'Security to avoid infinite loop.
        hChild = FindWindowExW(hwnd, hChild, Nothing, Nothing)          'Look for children windows of FolderBrowserDialog.
        hTreeView = FindWindowExW(hChild, 0, "SysTreeView32", Nothing)  'Look for treeview of FolderBrowserDialog.
        Thread.Sleep(5)                                                 'delay necessary because FolderBrowserDialog is in construction, then treeview maybe not yet exist.
    Loop While hTreeView = 0
    If SendMessageW(hwnd, &H46A, 1, FB.SelectedPath) = 0 Then           'Send message BFFM_SETEXPANDED to FolderBrowserDialog.
        SendMessageW(hTreeView, &H7, 0, Nothing)                        'Send message WM_SETFOCUS to the treeeview.
    End If
End Sub


Dim My_save_dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) & "\My-Saves"

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim FolderBrowserDialog1 As New FolderBrowserDialog
    FolderBrowserDialog1.Description = "Choose your save files path."
    If Directory.Exists(My_save_dir) Then
        FolderBrowserDialog1.SelectedPath = My_save_dir
    Else
        FolderBrowserDialog1.SelectedPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
    End If

    Dim Me_handle = Me.Handle         'Store the main handle to compare after with each windows owner.
    Task.Run(Sub() FolderBrowserDialog_EnsureVisible(FolderBrowserDialog1, Me_handle))      'Here's the trick, run an asynchronous task to modify the folderdialog.
    If FolderBrowserDialog1.ShowDialog(Me) = System.Windows.Forms.DialogResult.OK Then
        My_save_dir = FolderBrowserDialog1.SelectedPath
    End If
End Sub

j'attends vos suggestions. Et quelqu'un peut le traduire en C# parce que je ne le fais pas connaître le C#.

2
répondu Marc F 2015-07-13 16:18:58

j'ai rencontré le même problème en c++ /mfc. Il a fonctionné pour moi d'utiliser:: PostMessage plutôt que:: SendMessage dans le bffm_initialized callback to place the TVM_ENSUREVISIBLE msg

    case BFFM_INITIALIZED: 
{
// select something
::SendMessage(m_hDialogBox, BFFM_SETSELECTION, TRUE, (LPARAM) pszSelection);


// find tree control
m_hTreeCtrl = 0;
HWND hchild = GetWindow(hWnd, GW_CHILD) ;
while (hchild != NULL)
{
  VS_TChar classname[200] ;
  GetClassName(hchild, classname, 200) ;

  if (VS_strcmp(classname, _T("SHBrowseForFolder ShellNameSpace Control")) == 0)
  {
    HWND hlistctrl = GetWindow(hchild, GW_CHILD) ;
    do
    { 
      GetClassName(hlistctrl, classname, 200) ;
      if (lstrcmp(classname, _T("SysTreeView32")) == 0)
      {
        m_hTreeCtrl = hlistctrl;
        break ;   
      }

      hlistctrl = GetWindow(hlistctrl, GW_HWNDNEXT) ;
    } while (hlistctrl != NULL);
  }      
  if (m_hTreeCtrl)
    break;
  hchild = GetWindow(hchild, GW_HWNDNEXT);      
}

if (m_hTreeCtrl)
{
  int item = ::SendMessage(m_hTreeCtrl, TVM_GETNEXTITEM, TVGN_CARET, 0);
  if (item != 0)             
    ::PostMessage(m_hTreeCtrl, TVM_ENSUREVISIBLE,0,item);
}
break;
}
2
répondu Stefan_l_01 2016-01-29 16:54:58

dlgFolder.RootFolder = Environnement.SpecialFolder.DesktopDirectory;

n'est pas la même chose que

dlgFolder.RootFolder = Environnement.SpecialFolder.De bureau;

Quelle est la différence entre SpecialFolder.De bureau et SpecialFolder.DesktopDirectory?

Le fil lié indique qu'en chemin, ils obtiennent le même résultat. Mais ils ne sont pas les mêmes, car l'un est chemin logique, et l'autre est un chemin d'accès physique.

j'ai trouvé que lorsque l'un ou l'autre est assigné au RootFolder de la boîte de dialogue Ouvrir un dossier, le comportement résultant peut être différent.

comme A.RootFolder affectation, certaines versions de windows, comme win7, traiter l'un ou l'autre comme "bureau". C'est-à-dire, vous pouvez voir la sous-entrée "ordinateur", et ouvrez cela pour voir les lettres individuelles de lecteur. Le. SelectedPath est sélectionné, mais le chemin d'accès sélectionné est seulement rendu visible lorsque le chemin logique du bureau est assigné au .RootFolder.

pire, lors de l'utilisation de la boîte de dialogue parcourir le dossier dans win10 pré-publication, Il apparaît que "DesktopDirectory" comme juste cela, le contenu du répertoire de bureau seulement, sans lien du tout au répertoire de bureau logique. Et ne pas énumérer de sous-Articles. Très frustrant si une application écrite pour win7 essaye d'être utilisée avec win10.

Je pense que le problème que L'OP A est qu'ils ont employé le bureau physique comme la racine, alors qu'ils auraient dû employer le bureau logique.

Je n'ai pas d'explication pour expliquer pourquoi les deux machines différentes de L'OP répondent différemment. Je suppose qu'ils ont deux versions différentes du .net framework installé.

le fait que win10 prerelease a la question" coincé sur le bureau " avec la boîte de dialogue parcourir le dossier peut être due à la plus récent. Network framework livré avec win10 prerelease. Malheureusement, je reste ignorant de tous les faits dans cette affaire (win10), comme je ne l'ai pas encore mis à jour.

P. S. j'ai trouvé que win8 connaît aussi le symptôme" coincé sur le bureau":

https://superuser.com/questions/869928/windows-8-1-folder-selection-dialog-missing-my-computer-and-sub-items

la solution était de sélectionner l'interface graphique alternative dans win8. Peut-être que quelque chose de similaire peut être fait dans win10 prerelease.

0
répondu an odder guest 2017-05-23 12:18:18

j'ai lu la discussion et les solutions ci-dessus. En particulier Brat Oestreicher m'a mis dans la bonne direction. Essentiellement, nous devons d'abord trouver la commande TreeView dans la boîte de dialogue SHBrowseForFolder et envoyer à cette fenêtre le message TVM_ENSUREVISIBLE . Ce qui suit fait ceci en C.

#include <windows.h>
#include <objbase.h>
#include <objidl.h>
#include <Shlobj.h>
#include <Dsclient.h>
#include <wchar.h>
// 
//  EnumCallback - Callback function for EnumWindows 
// 
static BOOL CALLBACK EnumCallback(HWND hWndChild, LPARAM lParam)
{
   char szClass[MAX_PATH];
   HTREEITEM hNode;
   if (GetClassName(hWndChild, szClass, sizeof(szClass))
   &&  strcmp(szClass,"SysTreeView32")==0) {
      hNode = TreeView_GetSelection(hWndChild);    // found the tree view window
      TreeView_EnsureVisible (hWndChild, hNode);   // ensure its selection is visible
      return(FALSE);   // done; stop enumerating
   }
   return(TRUE);       // continue enumerating
}
// 
//  BrowseCallbackProc - Callback function for SHBrowseForFolder 
// 
static INT CALLBACK BrowseCallbackProc (HWND hWnd, UINT uMsg, LPARAM lParam, LPARAM lpData) 
{
    switch (uMsg) 
    { 
        case BFFM_INITIALIZED:
            SendMessage (hWnd, BFFM_SETEXPANDED, TRUE, lpData);    // expand the tree view
            SendMessage (hWnd, BFFM_SETSELECTION, TRUE, lpData);   // select the item
            break;
        case BFFM_SELCHANGED:
            EnumChildWindows(hWnd, EnumCallback,0);
            break;
    } 
    return 0; 
} 
// 
//  SelectDirectory - User callable entry point 
// 
int SelectDirectory (HWND hWndParent, char *path, int pathSize) 
{ 
    BROWSEINFO bi = {0};
    LPITEMIDLIST pidl = NULL;
    wchar_t ws[MAX_PATH];

    CoInitialize(0);
    if (pathSize < MAX_PATH) return(FALSE);

    swprintf(ws, MAX_PATH, L"%hs", path);

    bi.hwndOwner = hWndParent; 
    bi.lpszTitle = "Select Directory"; 
    bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
    bi.lpfn = BrowseCallbackProc;
    bi.lParam = (LPARAM) ws;

    pidl = SHBrowseForFolder (&bi); 
    if (pidl != NULL) 
    { 
        LPMALLOC pMalloc = NULL; 
        SHGetPathFromIDList (pidl, path);
        path[pathSize-1]= '"151900920"';

        SHGetMalloc(&pMalloc);
        pMalloc->lpVtbl->Free(pMalloc,pidl);    // deallocate item 
        pMalloc->lpVtbl->Release(pMalloc);

        return (TRUE);
    } 
    return (FALSE);
} 

merci Beaucoup Gary Esté .

0
répondu Paul Ogilvie 2018-01-19 13:43:15

en réponse au post de Marc F-j'ai converti le VB.Net à C#

    public enum GW
    {
        HWNDFIRST = 0,
        HWNDLAST = 1,
        HWNDNEXT = 2,
        HWNDPREV = 3,
        OWNER = 4,
        CHILD = 5,
        ENABLEDPOPUP = 6
    }

    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessageW", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr SendMessageW(IntPtr hWnd, uint msg, int wParam, [MarshalAs(UnmanagedType.LPWStr)] string lParam);
    [System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "FindWindowExW", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr FindWindowExW(IntPtr hWndParent, IntPtr hWndChildAfter, [MarshalAs(UnmanagedType.LPWStr)] string lpszClass, [MarshalAs(UnmanagedType.LPWStr)] string lpszWindow);
    [System.Runtime.InteropServices.DllImport("user32", EntryPoint = "GetWindow", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern UInt32 GetWindow(IntPtr hwnd, UInt32 wCmd);
    [System.Runtime.InteropServices.DllImport("user32", EntryPoint = "GetDesktopWindow", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr GetDesktopWindow();
    [System.Runtime.InteropServices.DllImport("user32", EntryPoint = "GetClassNameA", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern int GetClassName(IntPtr hwnd, System.Text.StringBuilder lpClassName, int nMaxCount);

    private void FolderBrowserDialog_EnsureVisible(FolderBrowserDialog FB, IntPtr _Owner)
    {
        IntPtr hwnd = System.IntPtr.Zero;
        System.Text.StringBuilder sClassname = new System.Text.StringBuilder(256);
        Thread.Sleep(50); //necessary to let FolderBrowserDialog construct its window
        hwnd = GetDesktopWindow(); //Desktop window handle.
        hwnd = (System.IntPtr)GetWindow(hwnd, (UInt32)GW.CHILD); //We will find all children.
        while (!(hwnd == (System.IntPtr)0))
        {
            if (GetWindow(hwnd, (UInt32)GW.OWNER) == (UInt32)_Owner) //If one window is owned by our main window...
            {
                GetClassName(hwnd, sClassname, 255);
                if (sClassname.ToString() == "#32770") //Check if the class is FolderBrowserDialog.
                {
                    break; //Then we found it.
                }
            }
            hwnd = (System.IntPtr)GetWindow(hwnd, (UInt32)GW.HWNDNEXT); //Next window.
        } //If no found then exit.
        if (hwnd == (System.IntPtr)0)
        {
            return;
        }
        IntPtr hChild = (System.IntPtr)0;
        IntPtr hTreeView = (System.IntPtr)0;
        int i = 0;
        do
        {
            i += 1;
            if (i > 1000) //Security to avoid infinite loop.
            {
                return;
            }
            hChild = FindWindowExW(hwnd, hChild, null, null); //Look for children windows of FolderBrowserDialog.
            hTreeView = FindWindowExW(hChild, (System.IntPtr)0, "SysTreeView32", null); //Look for treeview of FolderBrowserDialog.
            Thread.Sleep(5); //delay necessary because FolderBrowserDialog is in construction, then treeview maybe not yet exist.
        } while (hTreeView == (System.IntPtr)0);
        if (SendMessageW(hwnd, 0x46A, 1, FB.SelectedPath) == (System.IntPtr)0) //Send message BFFM_SETEXPANDED to FolderBrowserDialog.
        {
            SendMessageW(hTreeView, 0x7, 0, null); //Send message WM_SETFOCUS to the treeeview.
        }
    }

L'a testé et ça marche très bien. Assurez-vous que vous Système de référence.Runtime.InteropServices, System.Threading, un système.Le filetage.Tâches

0
répondu MC9000 2018-03-13 02:33:51

ce lien a une réponse simple qui a fonctionné pour moi très bien (j'ai windows 8.1 )

FolderBrowserDialog: extension du répertoire sélectionné

0
répondu user1760527 2018-03-13 03:33:39

cela fonctionne pour moi

folderBrowserDialog1.Reset();  
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
folderBrowserDialog1.SelectedPath = WorkingFolder;

mais seulement après la deuxième utilisation du dialogue

-1
répondu user3458105 2014-08-28 10:47:59

la meilleure approche, au moins la plus fiable est de créer votre propre boîte de dialogue de classe de navigateur. Le problème de défilement des arbres est douloureux depuis de nombreuses années - il ne sera jamais réparé!

si vous savez rendre dans la peinture il n'y a pas beaucoup que vous ne pouvez pas faire.. rapide dans la peinture et bien, c'est une autre histoire.

le premier endroit où je voudrais regarder est le code source open source .Net sur GitHub, dans votre version .Net de choix, pour la classe de dialogue vous êtes qui souhaitent s'améliorer. Vous pouvez être surpris de ce que vous pouvez accomplir avec un peu d'effort et de suivi. Il suffit de dupliquer le contrôle et déboguer au point où l'erreur se produit et patch - that'a ce que Microsoft fait, donc aussi pouvez-vous!

Puisqu'il s'agit d'un vieux fil et en affichant des échantillons peuvent ne jamais être lus. Il serait plus depuis de poster si demandé.

pourtant pour quelqu'un qui cherche à résoudre un tel problème comme avec le défilement de l'arbre à la " prévu" répertoire, voici quelques conseils. Si un problème existe avec un contrôle ou une bibliothèque qui n'a pas de solution immédiate, créez votre propre version, si possible, étendez l'original et corrigez le problème. J'ai tout réorganisé depuis les fenêtres.Forme.Classe de contrôle aux bibliothèques Win32 dans le seul but d'obtenir des résultats prévisibles et précis.

la bonne nouvelle est qu'avec C# il y a beaucoup de contrôle de bas niveau disponible pour atteindre presque n'importe quel objectif raisonnable et le C est en trop.

Dans le passé, j'ai dépensé beaucoup trop d'heures à chercher une solution à un problème où j'avais juste recréé ce qui n'était pas de travailler beaucoup de temps aurait été sauvé.

-1
répondu Jamie 2018-06-23 00:41:04