现在的位置: 首页 > 综合 > 正文

FolderBrowserdialog 的奇怪问题

2012年12月17日 ⁄ 综合 ⁄ 共 3294字 ⁄ 字号 评论关闭

这个控件其实是 .NET 1.1 新增的一个控件,可以用来浏览文件夹。

对于 1.0 我写过一片文章来介绍如何做这样的一个控件 http://dev.csdn.net/Develop/article/21/article/17/17635.shtm

今天一个同事碰到了一个奇怪的问题,很简单的代码

FolderBrowserDialog dlg=new FolderBrowserDialog();

dlg.ShowDialog();


结果 文件夹选择窗体,显示不正确。结果如图所示

这个问题,其实很容易修复。只要把你当前进程的Appartment State 设置为 STA 就可以了,或者给 Main 函数加上一个属性

[STAThread]

public static void Main()

{

}

出现这个问题,主要是跟 FolderBrowserDialog 的实现有关系,这个.NET 控件其实是 win32 Shell Ole 控件的一个重新包装,你可以通过reflector看到具体的代码

protected override bool RunDialog(IntPtr hWndOwner)

{

      IntPtr ptr1 
= IntPtr.Zero;

      
bool flag1 = false;

      UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, (
intthis.rootFolder, ref ptr1);

      
if (ptr1 == IntPtr.Zero)

      
{

            UnsafeNativeMethods.Shell32.SHGetSpecialFolderLocation(hWndOwner, 
0ref ptr1);

            
if (ptr1 == IntPtr.Zero)

            
{

                  
throw new Exception(SR.GetString("FolderBrowserDialogNoRootFolder"));

            }


      }


      
int num1 = 0x40;

      
if (!this.showNewFolderButton)

      
{

            num1 
+= 0x200;

      }


      Application.OleRequired();

      IntPtr ptr2 
= IntPtr.Zero;

      
try

      
{

            UnsafeNativeMethods.BROWSEINFO browseinfo1 
= new UnsafeNativeMethods.BROWSEINFO();

            IntPtr ptr3 
= Marshal.AllocHGlobal((int) (260 * Marshal.SystemDefaultCharSize));

            IntPtr ptr4 
= Marshal.AllocHGlobal((int) (260 * Marshal.SystemDefaultCharSize));

            UnsafeNativeMethods.BrowseCallbackProc proc1 
= new UnsafeNativeMethods.BrowseCallbackProc(this.FolderBrowserDialog_BrowseCallbackProc);

            browseinfo1.pidlRoot 
= ptr1;

            browseinfo1.hwndOwner 
= hWndOwner;

            browseinfo1.pszDisplayName 
= ptr3;

            browseinfo1.lpszTitle 
= this.descriptionText;

            browseinfo1.ulFlags 
= num1;

            browseinfo1.lpfn 
= proc1;

            browseinfo1.lParam 
= IntPtr.Zero;

            browseinfo1.iImage 
= 0;

            ptr2 
= UnsafeNativeMethods.Shell32.SHBrowseForFolder(browseinfo1);

            
if (ptr2 != IntPtr.Zero)

            
{

                  UnsafeNativeMethods.Shell32.SHGetPathFromIDList(ptr2, ptr4);

                  
this.selectedPathNeedsCheck = true;

                  
this.selectedPath = Marshal.PtrToStringAuto(ptr4);

                  Marshal.FreeHGlobal(ptr4);

                  Marshal.FreeHGlobal(ptr3);

                  flag1 
= true;

            }


      }


      
finally

      
{

            UnsafeNativeMethods.IMalloc malloc1 
= FolderBrowserDialog.GetSHMalloc();

            malloc1.Free(ptr1);

            
if (ptr2 != IntPtr.Zero)

            
{

                  malloc1.Free(ptr2);

            }


      }


      
return flag1;

}


 

而shell32 的申明如下:

[SuppressUnmanagedCodeSecurity, ComVisible(false)]

internal class Shell32

{

      
// Methods

      public Shell32();

      [DllImport(
"shell32.dll", CharSet=CharSet.Auto)]

      
public static extern IntPtr SHBrowseForFolder([In] UnsafeNativeMethods.BROWSEINFO lpbi);

      [DllImport(
"shell32.dll")]

      
public static extern int SHGetMalloc([Out, MarshalAs(UnmanagedType.LPArray)] UnsafeNativeMethods.IMalloc[] ppMalloc);

      [DllImport(
"shell32.dll", CharSet=CharSet.Auto)]

      
public static extern bool SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath);

      [DllImport(
"shell32.dll")]

      
public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, ref IntPtr ppidl);

}


 


 

【上篇】
【下篇】

抱歉!评论已关闭.