Why FolderBrowserDialog dialog does not scroll to selected folder?

前端 未结 14 1529
失恋的感觉
失恋的感觉 2020-11-30 02:28

As show in this screen shot, the selected folder is not in the view. It needs to be scrolled down to view the selected folder.

相关标签:
14条回答
  • 2020-11-30 02:58

    I run into same problem in c++ /mfc. It worked for me to use ::PostMessage rather than ::SendMessage in the 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;
    }
    
    0 讨论(0)
  • 2020-11-30 03:00

    In response to Marc F's post - I've converted the VB.Net to 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.
            }
        }
    

    Tested this and it works fine. Make sure you reference System.Runtime.InteropServices, System.Threading, an System.Threading.Tasks

    0 讨论(0)
提交回复
热议问题