Почему диалоговое окно FolderBrowserDialog не прокручивается до выбранной папки?

Как показано на этом снимке экрана, выбранная папка отсутствует в представлении. Чтобы просмотреть выбранную папку, ее нужно прокрутить вниз.

введите описание изображения здесь

В этом же диалоговом окне отображается выбранная папка, видимая на другом компьютере

введите описание изображения здесь

Я запустил его на двух компьютерах, имеющих windows 7. Он работает правильно, но не на 2-м. Что-то выглядит с windowsми, а не с кодом? Может ли кто-нибудь предложить какие-либо исправления?

В коде нет изменений. Я использовал более длинные пути с разных дисков, но результаты одинаковы.

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

Основная проблема – плохое дизайнерское решение в FolderBrowserDialog . Во-первых, нам нужно понять, что FolderBrowserDialog не является FolderBrowserDialog управления .NET, а скорее является Common Dialog и является частью Windows. Дизайнер этого диалога решил не отправлять элемент управления TreeView сообщение TVM_ENSUREVISIBLE после отображения диалогового windows и выбрать начальную папку. Это сообщение заставляет элемент управления TreeView прокручиваться так, чтобы текущий выбранный элемент был виден в окне.

Итак, все, что нам нужно сделать, чтобы исправить это, – это отправить TreeView, который является частью TVM_ENSUREVISIBLE сообщения TVM_ENSUREVISIBLE и все будет замечательно. Правильно? Ну, не так быстро. На самом деле это ответ, но некоторые вещи стоят на нашем пути.

  • Во-первых, поскольку FolderBrowserDialog самом деле не является Controls .NET, он не имеет внутренней коллекции Controls . Это означает, что мы не можем просто найти и получить доступ к дочернему элементу TreeView из .NET.

  • Во-вторых, разработчики classа .NET FolderBrowserDialog решили закрепить этот class. Это неудачное решение не позволяет нам извлечь из него и переопределить обработчик оконных сообщений. Если бы мы смогли это сделать, мы могли бы попытаться TVM_ENSUREVISIBLE сообщение TVM_ENSUREVISIBLE когда мы получили сообщение WM_SHOWWINDOW в обработчике сообщений.

  • Третья проблема заключается в том, что мы не можем отправить сообщение TVM_ENSUREVISIBLE до тех пор, пока элемент управления Tree View фактически не будет существовать как реальное окно, и оно не существует, пока мы не назовем метод ShowDialog . Однако этот метод блокируется, поэтому у нас не будет возможности опубликовать наше сообщение после вызова этого метода.

Чтобы обойти эти проблемы, я создал статический вспомогательный class с помощью одного метода, который можно использовать для отображения FolderBrowserDialog и заставит его прокручиваться до выбранной папки. Я управляю этим, запустив короткий Timer непосредственно перед вызовом метода ShowDialog диалога, а затем отслеживая дескриптор элемента управления TreeView в обработчике Timer (т. TVM_ENSUREVISIBLE отображения диалога) и отправляя наше сообщение TVM_ENSUREVISIBLE .

Это решение не идеально, потому что оно зависит от некоторых предварительных знаний о FolderBrowserDialog . В частности, я нахожу диалог, используя его заголовок windows. Это сломается с неанглийскими установками. Я отслеживаю дочерние элементы управления в диалоге, используя их идентификаторы идентификаторов диалога, а не текст заголовка или имя classа, потому что я чувствовал, что со временем это будет более надежным.

Этот код был протестирован в Windows 7 (64 бит) и Windows XP.

Вот код: (Вам может понадобиться: 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 string _topLevelSearchString = "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(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); ///  /// 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 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; } } 

Я использовал обходной путь из 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 (); 

Это не самый приятный способ, но он работает для меня.
Без RootFolder он НЕ работает при первом вызове, а на втором и следующем. С его помощью он работает всегда.

Как наблюдали другие, этот отказ зависит от операционной системы:
Я использую Win 7 Pro x64 SP1

Я знаю, что этот stream WAY старый, но с помощью методов расширения, это можно добавить к методу FolderBrowserDialog.ShowDialog, а затем повторно использовать там, где это необходимо.

Образец (ниже) просто использует простой метод SendKeys (который я ненавижу, но в этом случае он работает хорошо). При использовании метода SendKeys для перехода к выбранной папке в диалоговом окне, если вы отлаживаете это в Visual Studio, тогда вызов SendKeys применяется к текущему окну, который будет активным окном VS. Чтобы быть более надежным и избегать неправильного windows от получения сообщения SendKeys, метод расширения будет содержать вызовы внешних методов для отправки сообщений в конкретное окно, аналогичное тому, что было опубликовано Marc F, но переведено на 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); } } 

Я читал на разных форумах, что это может быть связано с RootFolder, потому что SelectedPath и RootFolder являются взаимоисключающими, что означает, что оба не могут сосуществовать, но с по умолчанию RootFolder (.Desktop). Он позволяет, по крайней мере, подниматься по дереву (перемещаться по диску / папки).

Однако, если RootFolder изменен на другое, кроме рабочего, вы не сможете перейти к UNC-путям.

Ответ на Hans Passant: Я пробовал это расширение Dialog, которое имеет TextBox, но не повезло.

Настройка диалогового windows просмотра папки для отображения пути

на коде VB.Net, просто поместите эту строку кода прямо перед отображением диалога.

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

Я обнаружил, что:

  1. Если .SelectedPath заканчивается на «\», Диалог будет прокручиваться вниз, чтобы сделать путь видимым.
  2. Если .SelectedPath не заканчивается .SelectedPath «\», путь по-прежнему выбран, но не отображается видимым.

Я вычислил что-то в VB.NET, поэтому было бы легко преобразовать его в C #. Я французский, и я новичок в VB. В любом случае, вы можете попробовать мое решение.

Моя идея – запустить асинхронную задачу перед показом folderBrowserDialog .

Я нашел это сам, но меня вдохновил пост Брэда. Вот мой код:

 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 String) As IntPtr Public Declare Function FindWindowExW Lib "user32.dll" (ByVal hWndParent As IntPtr, ByVal hWndChildAfter As IntPtr,  ByVal lpszClass As String,  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 

Я жду ваших предложений. И кто-то может перевести его на C #, потому что я не знаю C #.

Я столкнулся с той же проблемой в c ++ / mfc. Это помогло мне использовать :: PostMessage, а не :: SendMessage в BFFM_INITIALIZED обратном вызове, чтобы разместить 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; } 

dlgFolder.RootFolder = Environment.SpecialFolder.DesktopDirectory;

это не то же самое, что

dlgFolder.RootFolder = Environment.SpecialFolder.Desktop;

В чем разница между SpecialFolder.Desktop и SpecialFolder.DesktopDirectory?

Связанный stream указывает, что в качестве пути они получают одинаковый результат. Но они не то же самое, как один логический путь, а другой – физический путь.

Я обнаружил, что когда один из них назначен RootFolder в диалоговом окне открытой папки, результирующее поведение может быть другим.

В качестве назначения .RootFolder некоторые версии окон, например win7, рассматривают один из них как «Рабочий стол». То есть вы можете увидеть под-запись «Компьютер» и открыть ее, чтобы увидеть отдельные буквы диска. Выбор .SelectedPath выбирается в любом направлении, но выбранный путь становится видимым только тогда, когда логический путь рабочего стола назначается .RootFolder.

Хуже того, при использовании диалогового windows папки просмотра в предварительном выпуске win10, кажется, что «DesktopDirectory» как раз это, содержимое только Desktop Directory, без какой-либо ссылки на каталог логического рабочего стола. И не перечислять подделки под ним. Очень неприятно, если приложение, написанное для win7, пытается использоваться с win10.

Я думаю, проблема, с которой сталкивается OP, заключается в том, что они использовали физический рабочий стол в качестве корня, когда они должны были использовать логический рабочий стол.

У меня нет объяснений, почему разные машины OP реагируют по-разному. Я бы предположил, что у них установлены две разные версии .NET framework.

Тот факт, что предварительная предварительная версия win10 имеет проблему «Застрял на рабочем столе» с диалогом windows просмотра, может быть связана с более поздней платформой .NET, поставляемой с предварительной загрузкой win10. К сожалению, я по-прежнему не осведомлен о всех фактах в этом случае (win10), поскольку я еще не обновлялся.

PS Я обнаружил, что win8 также испытывает симптом «Stuck on Desktop»:

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

Обходной путь состоял в том, чтобы выбрать альтернативный графический интерфейс в win8. Возможно, что-то подобное можно сделать в предварительном выпуске win10.

Я прочитал приведенные выше обсуждения и решения. Особенно Брат Oestreicher поставить меня в правильном направлении. По сути, мы должны сначала найти элемент управления TreeView в диалоговом окне SHBrowseForFolder и отправить это окно в сообщение TVM_ENSUREVISIBLE . Следующее делает это в 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); } значение #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); } 

Большое спасибо Гэри Бин .

В ответ на сообщение Марка Ф – я превратил 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. } } 

Протестировал это, и он отлично работает. Убедитесь, что вы ссылаетесь на System.Runtime.InteropServices, System.Threading, System.Threading.Tasks

У этой ссылки есть простой ответ, который работал для меня отлично (у меня есть windows 8.1 )

FolderBrowserDialog: расширение выбранного каталога

это работает для меня

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

но только после второго использования диалога

Наилучший подход, по крайней мере, самый надежный способ – создать собственное диалоговое окно classа браузера. Проблема прокрутки дерева была болью в течение многих лет – она ​​никогда не будет исправлена!

Если вы знаете, как рисовать в краске, вы не можете этого сделать … быстро в краске, это еще одна история.

Первое, что я хотел бы посмотреть, это исходный исходный код .Net на GitHub в вашей .Net-версии выбора для интересующего вас диалогового classа. Вы можете быть удивлены тем, чего вы можете добиться, приложив немного усилий и проследите. Просто дублируйте элемент управления и отладки до точки, где происходит ошибка, и патч – это то, что делает Microsoft, и вы тоже!

Так как это старая нить, и образцы публикации никогда не могут быть прочитаны. Это сделало бы больше, поскольку после отправки, если его спросят.

Тем не менее, для тех, кто ищет решение такой проблемы, как с прокруткой дерева в «ожидаемый» каталог, вот несколько твердых советов. Если существует проблема с элементом управления или библиотекой, которая не имеет немедленного решения, создайте свою собственную версию, когда это возможно, расширьте оригинал и исправьте проблему. Я обновил все из classа Windows.Form.Control до библиотек Win32 с единственной целью получения outlookируемых и точных результатов.

Хорошей новостью является то, что с C # существует много контроля низкого уровня, доступных для достижения практически любой разумной цели, а также C.

В прошлом я потратил слишком много часов на поиск решения проблемы, когда я только что воссоздал то, что не работало много времени, было бы спасено.

  • Преобразование RGB-данных в bitmap в Objective-C ++ Cocoa
  • Какая лучшая библиотека шифрования в C / C ++?
  • Как вернуть анонимный тип из метода c #, который использует LINQ to SQL
  • Цвет фона для Wpf
  • Функция с тем же именем, но другая подпись в производном classе
  • C ++ 11 make_pair с указанными параметрами шаблона не компилируется
  • Как я могу использовать «sizeof» в макросе препроцессора?
  • Как создать события таймера с помощью C ++ 11?
  • Почему .ToString () в нулевой строке вызывает нулевую ошибку, когда .ToString () отлично работает в nullable int с нулевым значением?
  • Qt - удалить все виджеты из макета?
  • Что вызывает fragmentацию памяти в .NET.
  • Давайте будем гением компьютера.