Beispiel #1
0
        /// <summary>
        /// Callback method for the handling of messages to be sent to/from the folder browser dialog.
        /// </summary>
        /// <param name="hwnd"></param>
        /// <param name="msg"></param>
        /// <param name="lParam"></param>
        /// <param name="lpData"></param>
        /// <returns></returns>
        private int FolderBrowserDialog_BrowseCallbackProc(IntPtr hwnd, int msg, IntPtr lParam, IntPtr lpData)
        {
            switch (msg)
            {
            case NativeWindowCommon.BFFM_INITIALIZED:
                // We get in here when the dialog is first displayed. If an initial directory
                // has been specified we will make this the selection now, and also make sure
                // that directory is expanded.
                if (this.selectedPath.Length != 0)
                {
                    NativeWindowCommon.SendMessage(hwnd, NativeWindowCommon.BFFM_SETSELECTIONW, 1, this.selectedPath);
                }
                break;

            case NativeWindowCommon.BFFM_SELCHANGED:
            {
                IntPtr pidl = lParam;
                if (pidl != IntPtr.Zero)
                {
                    StringBuilder sb   = new StringBuilder(MAX_PATH * Marshal.SystemDefaultCharSize);
                    bool          flag = NativeWindowCommon.SHGetPathFromIDList(pidl, sb);
                    NativeWindowCommon.SendMessage(hwnd, NativeWindowCommon.BFFM_ENABLEOK, 0, flag ? 1 : 0);
                }

                if (!doneScrolling)
                {
                    IntPtr hbrowse = NativeWindowCommon.FindWindowEx(hwnd, IntPtr.Zero, "SHBrowseForFolder ShellNameSpace Control", null);
                    IntPtr htree   = NativeWindowCommon.FindWindowEx(hbrowse, IntPtr.Zero, "SysTreeView32", null);
                    IntPtr htis    = NativeHeader.SendMessage(htree, NativeWindowCommon.TVM_GETNEXTITEM, NativeWindowCommon.TVGN_CARET, IntPtr.Zero);

                    IntPtr htir = NativeHeader.SendMessage(htree, NativeWindowCommon.TVM_GETNEXTITEM, NativeWindowCommon.TVGN_ROOT, IntPtr.Zero);
                    IntPtr htic = NativeHeader.SendMessage(htree, NativeWindowCommon.TVM_GETNEXTITEM, NativeWindowCommon.TVGN_CHILD, htir);

                    //we actually go into the BFFM_SELCHANGED case three times when the dialog is first shown, and it's only on the third one that we actually scroll,
                    //since before this htic is always zero, so you need to cope with this
                    //- i.e. don't set 'doneScrolling' flag until htic has been non - zero(or until you've gone into the BFFM_SELCHANGED three times).
                    if ((int)htic != 0)
                    {
                        doneScrolling = true;
                        //The only solution I've found that works consistently is to send a TVM_ENSUREVISIBLE to the tree, using TVM_GETNEXTITEM/TVGN_CARET, from BFFM_SELCHANGED.
                        //That works. Every time.
                        NativeHeader.SendMessage(htree, NativeWindowCommon.TVM_ENSUREVISIBLE, 0, htis);

                        //Active the tree view control window inside the folder browser dialog to set the focus on it.
                        NativeWindowCommon.SendMessage(htree, NativeWindowCommon.WM_ACTIVATE, 1, 0);
                    }
                }
            }
            break;
            }
            return(0);
        }
Beispiel #2
0
        /// <summary>
        /// Shows the folder browser dialog box with the specified owner window.
        /// </summary>
        protected override bool RunDialog(IntPtr hWndOwner)
        {
            IntPtr pidlRoot = IntPtr.Zero;
            bool   flag     = false;

            // Get the IDL for the specific startLocation. e.g. Environment.SpecialFolder.Desktop
            NativeWindowCommon.SHGetSpecialFolderLocation(hWndOwner, (int)this.rootFolder, ref pidlRoot);

            if (pidlRoot == IntPtr.Zero)
            {
                // Get the IDL for the default startLocation.
                NativeWindowCommon.SHGetSpecialFolderLocation(hWndOwner, 0, ref pidlRoot);
                if (pidlRoot == IntPtr.Zero)
                {
                    throw new InvalidOperationException();
                }
            }

            int flags = GetFlags();

            if ((flags & (int)NativeWindowCommon.BffStyles.NewDialogStyle) != 0)
            {
                if (System.Threading.ApartmentState.MTA == Application.OleRequired())
                {
                    flags = flags & (~(int)NativeWindowCommon.BffStyles.NewDialogStyle);
                }
            }

            IntPtr pidl    = IntPtr.Zero;
            IntPtr hglobal = IntPtr.Zero;

            try
            {
                hglobal = Marshal.AllocHGlobal((int)(MAX_PATH * Marshal.SystemDefaultCharSize));

                this.callback = new NativeWindowCommon.BrowseCallbackProc(this.FolderBrowserDialog_BrowseCallbackProc);
                NativeWindowCommon.BROWSEINFO lpbi = new NativeWindowCommon.BROWSEINFO
                {
                    pidlRoot       = pidlRoot,
                    hwndOwner      = hWndOwner,
                    pszDisplayName = hglobal,
                    lpszTitle      = this.descriptionText,
                    ulFlags        = flags,
                    lpfn           = this.callback,
                    lParam         = IntPtr.Zero,
                    iImage         = 0
                };

                // Show the dialog.
                pidl = NativeWindowCommon.SHBrowseForFolder(ref lpbi);

                if (pidl != IntPtr.Zero)
                {
                    // Retrieve the path from the IDList.
                    StringBuilder sb = new StringBuilder(MAX_PATH * Marshal.SystemDefaultCharSize);

                    NativeWindowCommon.SHGetPathFromIDList(pidl, sb);
                    this.selectedPathNeedsCheck = true;
                    this.selectedPath           = sb.ToString();
                    flag = true;
                }
            }
            finally
            {
                NativeWindowCommon.IMalloc malloc = GetSHMalloc();

                //Free the memory allocated for getting the ID list for the specific startLocation.
                malloc.Free(pidlRoot);

                if (pidl != IntPtr.Zero)
                {
                    //Free the memory allocated for getting the ID list for the showing the SHBrowseForFolder.
                    malloc.Free(pidl);
                }

                // Free the buffer you've allocated on the global heap.
                if (hglobal != IntPtr.Zero)
                {
                    Marshal.FreeHGlobal(hglobal);
                }

                //Reset the callback function to null.
                this.callback = null;
            }

            return(flag);
        }