Comme le montre cette capture d'écran, le dossier sélectionné n'est pas dans la vue. Il faut faire défiler l'écran pour afficher le dossier sélectionné.
La même boîte de dialogue affiche le dossier sélectionné visible sur un ordinateur différent
Je l'ai couru sur deux ordinateurs ayant Windows 7. Cela fonctionne correctement sur un, mais pas sur 2nd. Il semble quelque chose avec l'environnement Windows à la place 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 la variable FolderBrowserDialog
. Premièrement, nous devons réaliser que la 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 dialogue a choisi de ne pas envoyer de message TVM_ENSUREVISIBLE
au contrôle TreeView après l'affichage de la boîte de dialogue et la sélection d'un dossier initial. Ce message fait défiler un contrôle TreeView afin que l'élément actuellement sélectionné soit visible dans la fenêtre.
Donc, tout ce que nous avons à faire pour résoudre ce problème est d’envoyer le TreeView qui fait partie du message FolderBrowserDialog
le TVM_ENSUREVISIBLE
et tout ira bien. Droite? Eh bien, pas si vite. C’est effectivement la solution, mais certaines choses nous en empêchent.
Tout d’abord, parce que FolderBrowserDialog
n’est pas vraiment un contrôle .NET, il n’a pas de collection Controls
interne. Cela signifie que nous ne pouvons pas simplement rechercher et accéder au contrôle enfant TreeView à partir de .NET.
Deuxièmement, les concepteurs de la classe .NET FolderBrowserDialog
ont décidé de seal cette classe. Cette décision malheureuse nous empêche d’en dériver et d’ignorer le gestionnaire de messages de fenêtre. Si nous avions pu le faire, nous aurions peut-être tenté de poster le message TVM_ENSUREVISIBLE
lorsque nous aurions 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 en tant que fenêtre réelle et il n’existe pas tant que nous n’appelons pas la méthode ShowDialog
. Cependant, cette méthode est bloquante et nous n’aurons donc pas l’opportunité de poster notre message une fois cette méthode appelée.
Pour résoudre ces problèmes, j'ai créé une classe d'assistance statique avec une seule méthode qui peut être utilisée pour afficher une variable FolderBrowserDialog
et la faire défiler jusqu'au dossier sélectionné. Je parviens à cela en démarrant une Timer
courte juste avant d'appeler la méthode ShowDialog
du dialogue, puis en recherchant le handle du contrôle TreeView
dans le gestionnaire Timer
(c'est-à-dire après l'affichage de la boîte de dialogue) et l'envoi de notre message TVM_ENSUREVISIBLE
.
Cette solution n’est pas parfaite car elle dépend de connaissances préalables sur FolderBrowserDialog
. Plus précisément, je trouve le dialogue en utilisant son titre de fenêtre. Cela rompra avec les installations non anglaises. Je traque les contrôles enfants dans le dialogue en utilisant leurs ID d'élément de dialogue, plutôt que le texte du titre ou le nom de la classe, car j'estimais que ce serait plus fiable au fil du temps.
Ce code a été testé sur Windows 7 (64 bits) et Windows XP.
Voici le code: (Vous aurez peut-être 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;
}
}
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 la RootFolder
, cela ne fonctionnera PAS au premier appel, mais au 2e et suivants. Avec ça, ça marche toujours.
Comme d’autres ont observé que cette défaillance dépend du système d’exploitation:
J'utilise Win 7 Pro x64 SP1
Je sais que ce fil est WAY old, mais avec les méthodes d'extension, cela peut être ajouté à la méthode FolderBrowserDialog.ShowDialog, puis utilisé à plusieurs reprises si nécessaire.
L'exemple (ci-dessous) utilise simplement la méthode facile SendKeys (ce que je n'aime pas 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 dialogue, si vous procédez au débogage dans Visual Studio, l'appel SendKeys s'applique à la fenêtre actuelle, qui serait la fenêtre VS active. Pour être plus sûr et éviter que le message SendKeys ne soit envoyé à la mauvaise fenêtre, la méthode d'extension contiendrait les appels de méthode externes pour envoyer des messages à la fenêtre spécifique, similaires à ce que Marc F a posté, mais traduits 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);
}
}
sur le code VB.Net, il suffit de mettre cette ligne de code juste avant d'afficher le dialogue.
SendKeys.Send ("{TAB}{TAB}{RIGHT}")
J'ai lu sur différents forums que cela pourrait être dû à RootFolder parce que SelectedPath et RootFolder sont mutuellement exclusifs, cela signifie que les deux ne peuvent pas coexister, mais avec RootFolder (.Desktop) par défaut. Cela permet au moins de gravir l'arbre /Dossiers).
Toutefois, si vous remplacez RootFolder par autre que le bureau, vous ne pourrez pas accéder aux chemins UNC.
Réponse à Hans Passant: J'ai essayé cette extension de dialogue, qui a TextBox, mais pas de chance.
Personnalisation de la boîte de dialogue de recherche de dossier pour afficher le chemin d'accès
J'ai calculé quelque chose dans 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, tu peux essayer ma solution.
Mon idée est de lancer une tâche asynchrone juste avant d’afficher le folderBrowserDialog
.
J'ai trouvé cela moi-même, mais Brad m'a inspiré… .. 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 connais pas.
J'ai trouvé que:
.SelectedPath
se termine par "\", le dialogue défilera vers le bas pour rendre le chemin visible..SelectedPath
ne se termine pas par "\", le chemin est toujours sélectionné, mais n'est pas visible visible.Je rencontre le même problème dans c ++/mfc. Cela fonctionnait pour moi d'utiliser :: PostMessage plutôt que :: SendMessage dans le rappel BFFM_INITIALIZED pour placer le message 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;
}
J'ai lu la discussion et les solutions ci-dessus. En particulier, Brat Oestreicher m'a mis dans la bonne direction. En substance, nous devons d'abord trouver le contrôle TreeView dans la boîte de dialogue SHBrowseForFolder
et envoyer à cette fenêtre le message TVM_ENSUREVISIBLE
. Ce qui suit fait cela 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]= '\0';
SHGetMalloc(&pMalloc);
pMalloc->lpVtbl->Free(pMalloc,pidl); // deallocate item
pMalloc->lpVtbl->Release(pMalloc);
return (TRUE);
}
return (FALSE);
}
Merci beaucoup à Gary Beene .
Ce lien a une réponse simple qui a bien fonctionné pour moi (j'ai Windows 8.1
)
dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;
n'est pas la même chose que
dlgFolder.RootFolder = Environment.SpecialFolder.Desktop;
Quelle est la différence entre SpecialFolder.Desktop et SpecialFolder.DesktopDirectory?
Le fil 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 constaté que lorsque l'un ou l'autre est affecté au dossier racine du dossier ouvert, le comportement résultant peut être différent.
En tant qu’affectation .RootFolder, certaines versions de Windows, telles que win7, traitent l’une ou l’autre comme "Bureau". C'est-à-dire que vous pouvez voir la sous-entrée "Ordinateur" et l'ouvrir pour voir les lettres de lecteur individuelles. Le chemin .SelectedPath est sélectionné d'une manière ou d'une autre, mais le chemin sélectionné n'est rendu visible que lorsque le chemin logique du bureau est affecté au dossier .RootFolder.
Pire encore, lors de l’utilisation de la boîte de dialogue Parcourir le dossier dans la version préliminaire de Win10, il apparaît que "DesktopDirectory" n’est que cela, le contenu du répertoire du bureau 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 des 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 raison pour laquelle les deux machines du PO répondent différemment. Je supposerais qu'ils ont deux versions différentes du framework .NET installé.
Le fait que win10 prerelease ait le problème "Stuck on Desktop" avec la boîte de dialogue de navigation dans le dossier de navigation est peut-être dû au framework .NET plus récent fourni avec win10 prerelease. Malheureusement, je reste ignorant de tous les faits dans cette affaire (win10), car je n'ai pas encore mis à jour.
P.S. J'ai trouvé que win8 éprouve également le symptôme "Stuck on Desktop":
La solution de contournement consistait à sélectionner l'interface graphique de remplacement dans win8. Peut-être que quelque chose de similaire peut être fait dans la version préliminaire de win10.
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)] 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.
}
}
Testé cela et cela fonctionne bien. Assurez-vous de bien référencer System.Runtime.InteropServices, System.Threading, System.Threading.Tasks.
ça marche pour moi
folderBrowserDialog1.Reset();
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
folderBrowserDialog1.SelectedPath = WorkingFolder;
mais seulement après la deuxième utilisation du dialogue