montaque

小碗喝酒,小口吃肉

博客园 首页 新随笔 联系 订阅 管理

这个控件其实是 .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);
}

 

 

posted on 2004-12-18 11:39  montaque  阅读(3059)  评论(4)    收藏  举报