Pourquoi la boîte de dialog FolderBrowserDialog ne fait pas défiler le dossier sélectionné?

Comme le montre cette capture d’écran, le dossier sélectionné n’est pas dans la vue. Il faut faire défiler pour voir le dossier sélectionné.

entrer la description de l'image ici

La même boîte de dialog affiche le dossier sélectionné visible sur un autre ordinateur

entrer la description de l'image ici

Je l’ai couru sur deux ordinateurs ayant tous deux Windows 7. Il fonctionne correctement sur l’un mais pas sur le second. Cela ressemble à quelque chose avec l’environnement Windows au lieu d’un problème de code? Quelqu’un peut-il suggérer une solution?

Il n’y a pas de changement de code. J’ai utilisé des chemins plus longs à partir de différents lecteurs, 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 (); } } 

    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 plutôt le Common Dialog et fait partie de Windows. Le concepteur de cette boîte de dialog a choisi de ne pas envoyer au contrôle TreeView un message TVM_ENSUREVISIBLE après l’affichage de la boîte de dialog et la sélection d’un dossier initial. Ce message provoque le défilement d’un contrôle TreeView pour que l’élément actuellement sélectionné soit visible dans la fenêtre.

    Donc, tout ce que nous devons faire pour résoudre ce problème est d’envoyer le TreeView qui fait partie du FolderBrowserDialog le message TVM_ENSUREVISIBLE et tout ira bien. Droite? Eh bien, pas si vite. C’est en effet la réponse, mais il y a des choses sur notre chemin.

    • Tout d’abord, le FolderBrowserDialog n’étant pas vraiment un contrôle .NET, il ne possède pas de collection de Controls interne. Cela signifie que nous ne pouvons pas simplement trouver et accéder au contrôle enfant TreeView à partir de .NET.

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

    • Le troisième problème est que nous ne pouvons pas envoyer le message TVM_ENSUREVISIBLE tant que le contrôle Tree View n’existe pas réellement en tant que fenêtre réelle et qu’il n’existe pas tant que nous ShowDialog méthode ShowDialog . Cependant, cette méthode bloque, nous n’aurons donc pas la possibilité de poster notre message une fois cette méthode appelée.

    Pour contourner ces problèmes, j’ai créé une classe d’assistance statique avec une méthode unique qui peut être utilisée pour afficher un FolderBrowserDialog et le faire défiler jusqu’au dossier sélectionné. Je gère cela en démarrant un Timer court juste avant d’appeler la méthode ShowDialog du dialog, puis en suivant le handle du contrôle TreeView dans le gestionnaire Timer (après l’affichage du dialog) et en envoyant notre message TVM_ENSUREVISIBLE .

    Cette solution n’est pas parfaite car elle dépend de connaissances préalables sur le FolderBrowserDialog . Plus précisément, je trouve le dialog en utilisant son titre de fenêtre. Cela va rompre avec les installations non anglaises. Je recherche les contrôles enfants dans le dialog en utilisant leurs ID d’éléments de dialog, plutôt que le texte du titre ou le nom de la classe, car je pensais que cela serait plus fiable avec le temps.

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

    Voici le code: (Vous devrez peut-être: using System.Runtime.InteropServices; )

     public static class FolderBrowserLauncher { ///  /// Using title text to look for the top level dialog window is fragile. /// In particular, this will fail in non-English applications. ///  const ssortingng _topLevelSearchSsortingng = "Browse For Folder"; ///  /// 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. ///  const int _dlgItemBrowseControl = 0; const int _dlgItemTreeView = 100; [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(ssortingng lpClassName, ssortingng 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); ///  /// Some of the messages that the Tree View control will respond to ///  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); ///  /// Constants used to identity specific items in the Tree View control ///  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; ///  /// 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. ///  ///  ///  ///  public static DialogResult ShowFolderBrowser( FolderBrowserDialog dlg, IWin32Window parent = null ) { DialogResult result = DialogResult.Cancel; int resortinges = 10; using (Timer t = new Timer()) { t.Tick += (s, a) => { if (resortinges > 0) { --resortinges; IntPtr hwndDlg = FindWindow((ssortingng)null, _topLevelSearchSsortingng); 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); resortinges = 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; } } 

    J’ai utilisé une solution de contournement à l’ adresse 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 plus belle façon, mais ça marche pour moi.
    Sans le RootFolder il ne fonctionne pas sur le premier appel, mais sur le deuxième et le suivant. Avec ça, ça marche toujours.

    Comme d’autres l’ont observé, cette défaillance dépend du système d’exploitation:
    J’utilise Win 7 Pro x64 SP1

    Je sais que ce thread est WAY old, mais avec les méthodes d’extension, cela peut être ajouté à la méthode FolderBrowserDialog.ShowDialog, puis utilisé à plusieurs resockets si nécessaire.

    L’exemple ci-dessous utilise simplement la méthode facile SendKeys (que je déteste faire, mais dans ce cas, cela fonctionne bien). Lorsque vous utilisez la méthode SendKeys pour accéder au dossier sélectionné dans la boîte de dialog, si vous le déboguez dans Visual Studio, l’appel SendKeys s’applique à la fenêtre en cours, à savoir la fenêtre VS active. Pour être plus infaillible et pour éviter que la fenêtre ne reçoive le message SendKeys, 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); } } 

    J’ai lu sur différents forums que cela pouvait être dû à RootFolder, car SelectedPath et RootFolder s’excluent mutuellement, ce qui signifie que les deux ne peuvent pas coexister, mais avec RootFolder (.Desktop) par défaut. /Dossiers).

    Toutefois, si RootFolder est remplacé par autre que Desktop, vous ne pourrez pas accéder aux chemins UNC.

    Réponse à Hans Passant: J’ai essayé cette extension de dialog, qui contient TextBox, mais pas de chance.

    Personnalisation de la boîte de dialog de recherche de dossier pour afficher le chemin

    sur le code VB.Net, placez simplement cette ligne de code juste avant d’afficher la boîte de dialog.

     SendKeys.Send ("{TAB}{TAB}{RIGHT}") 

    J’ai trouvé que:

    1. Si .SelectedPath se termine par “\”, la boîte de dialog .SelectedPath pour rendre le chemin visible.
    2. Si .SelectedPath ne se termine pas par “\”, le chemin est toujours sélectionné, mais pas assuré visible.

    J’ai calculé quelque chose dans VB.NET, il serait donc facile de le transformer en C #. Je suis française et je suis débutante en VB. Quoi qu’il en soit, vous pouvez essayer ma solution.

    Mon idée est de lancer une tâche asynchrone juste avant d’afficher le folderBrowserDialog .

    Je l’ai trouvé moi-même, mais je me suis inspiré de 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,  ByVal lParam As Ssortingng) As IntPtr Public Declare Function FindWindowExW Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr,  ByVal lpszClass As Ssortingng,  ByVal lpszWindow As Ssortingng) 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.SsortingngBuilder, 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.SsortingngBuilder(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.ToSsortingng = "#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 sortingck, 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 connais pas C #.

    Je rencontre le même problème en c ++ / mfc. Il a fonctionné pour moi d’utiliser :: PostMessage plutôt que :: SendMessage dans le rappel BFFM_INITIALIZED pour placer le msg TVM_ENSUREVISIBLE

      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; } 

    dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;

    n’est pas la même que

    dlgFolder.RootFolder = Environment.SpecialFolder.Desktop;

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

    Le thread lié indique qu’en tant que chemin, ils obtiennent le même résultat. Mais ils ne sont pas identiques, l’un étant un chemin logique et l’autre un chemin physique.

    J’ai trouvé lorsque l’un ou l’autre est assigné au dossier racine de la boîte de dialog de dossier ouvert, le comportement résultant peut être différent.

    En tant qu’affectation de .RootFolder, certaines versions de Windows, comme win7, traitent l’une des deux comme “Desktop”. Autrement dit, vous pouvez voir la sous-entrée “Ordinateur” et ouvrez-la pour voir les lettres de lecteur individuelles. Le .SelectedPath est sélectionné dans les deux cas, mais le chemin sélectionné n’est visible que lorsque le chemin logique du bureau est atsortingbué au dossier .RootFolder.

    Pire encore, lorsque vous utilisez la boîte de dialog du dossier de navigation dans la pré-version de win10, il semble que “DesktopDirectory” ne soit que cela, le contenu du répertoire Desktop uniquement, sans aucun lien avec le répertoire du bureau logique. Et ne pas énumérer les sous-éléments en dessous. Très frustrant si une application écrite pour win7 essaie d’être utilisée avec win10.

    Je pense que le problème rencontré par l’OP est qu’ils ont utilisé le bureau physique comme racine, alors qu’ils auraient dû utiliser le bureau logique.

    Je n’ai pas d’explication sur la réponse différente des deux machines de l’OP. Je suppose que deux versions différentes du framework .NET sont installées.

    Le fait que Win10 prerelease présente le problème “Stuck on Desktop” avec la boîte de dialog du dossier de navigation peut être dû au plus récent framework .NET fourni avec une version préliminaire de win10. Malheureusement, je rest ignorant de tous les faits dans cette affaire (Win10), car je n’ai pas encore mis à jour.

    PS J’ai trouvé que win8 éprouve également le symptôme “Stuck on Desktop”:

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

    La solution de contournement était de sélectionner l’interface graphique alternative dans win8. Peut-être que quelque chose de similaire peut être fait dans une version préliminaire de Win10.

    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 le contrôle TreeView dans la boîte de dialog SHBrowseForFolder et envoyer à cette fenêtre le message TVM_ENSUREVISIBLE . Ce qui suit en C

     #include  #include  #include  #include  #include  #include  // // 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]= '\0'; SHGetMalloc(&pMalloc); pMalloc->lpVtbl->Free(pMalloc,pidl); // deallocate item pMalloc->lpVtbl->Release(pMalloc); return (TRUE); } return (FALSE); } 

    Merci beaucoup à Gary Beene .

    En réponse au message de Marc F – j’ai converti le VB.Net en 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)] ssortingng 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)] ssortingng lpszClass, [MarshalAs(UnmanagedType.LPWStr)] ssortingng 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.SsortingngBuilder lpClassName, int nMaxCount); private void FolderBrowserDialog_EnsureVisible(FolderBrowserDialog FB, IntPtr _Owner) { IntPtr hwnd = System.IntPtr.Zero; System.Text.SsortingngBuilder sClassname = new System.Text.SsortingngBuilder(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.ToSsortingng() == "#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. } } 

    Testé cela et ça marche bien. Assurez-vous de référencer System.Runtime.InteropServices, System.Threading, un System.Threading.Tasks

    Ce lien a une réponse simple qui a fonctionné pour moi bien (j’ai Windows 8.1 )

    FolderBrowserDialog: extension du répertoire sélectionné

    cela fonctionne pour moi

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

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

    La meilleure approche, du moins la plus fiable, consiste à créer votre propre boîte de dialog de classe de navigateur. Le problème du défilement des arbres est douloureux depuis de nombreuses années – il ne sera jamais résolu!

    Si vous savez comment rendre dans la peinture, il n’y a pas grand chose à faire.

    Le premier endroit que je chercherais est le code source open source sur GitHub, dans la version de votre choix .Net, pour la classe de dialog que vous souhaitez améliorer. Vous pourriez être surpris de ce que vous pouvez accomplir avec un petit effort et suivre. Il suffit de dupliquer le contrôle et de déboguer au point où l’erreur se produit et de corriger – c’est ce que fait Microsoft, vous aussi!

    Comme il s’agit d’un ancien thread et que la publication d’échantillons n’est jamais lisible. Il ferait plus depuis pour poster si demandé.

    Pourtant, pour quelqu’un qui cherche à résoudre un problème tel que le défilement des arborescences vers le répertoire “attendu”, voici quelques conseils solides. Si un problème existe avec un contrôle ou une bibliothèque sans solution immédiate, créez votre propre version, si possible, étendez l’original et corrigez le problème. J’ai tout réorganisé de la classe Windows.Form.Control aux bibliothèques Win32 dans le seul but d’obtenir des résultats prévisibles et précis.

    La bonne nouvelle est que, avec C #, il y a beaucoup de contrôle de bas niveau disponible pour atteindre presque n’importe quel objective raisonnable et le C aussi.

    Dans le passé, j’ai passé beaucoup trop de temps à chercher une solution à un problème où je venais de recréer ce qui ne fonctionnait pas, beaucoup de temps aurait été économisé.