none
有关CFileDialog/GetOpenFileName的几个问题 RRS feed

  • 问题

  • 一般的文件打开对话框是这样的:

    http://hiphotos.baidu.com/doomsdayer/pic/item/2080e3af8b6c3ab4faed5051.jpg

    一般的目录选择对话框是这样的:

    http://hiphotos.baidu.com/doomsdayer/pic/item/2080e3af8bd13ab4faed50d4.jpg

     

    我看到有把这两者结合起来的新式的目录选择对话框:

    http://hiphotos.baidu.com/doomsdayer/pic/item/a8c44b1f3de51a2cf724e4db.jpg

     

    请问这种对话框是怎么做出来的呢?我研究了很久CFileDialog, OPENFILENAME, SHBrowseForFolder可还是得不到答案....

     

    还有一个问题,我看到有些自定义风格的CFileDialog/GetOpenFileName,比如notapad的打开文件对话框:

    http://hiphotos.baidu.com/doomsdayer/pic/item/d10f10777c1bc154b051b9b8.jpg

    下面添加了ComboBox,我研究了一下,发现可以考虑对OPENFILENAME设置OFN_ENABLETEMPLATEHANDLE或OFN_ENABLEHOOK。

    但问题是,这两个标记位都不能和OFN_EXPLORER共存,一旦设置上面的两个标记位,对话框就会变为这个样子:

    http://hiphotos.baidu.com/doomsdayer/pic/item/249a8f7a919b38a22f73b366.jpg

    请问应该怎样才能做出notepad的那种打开文件对话框?

     

    2011年1月5日 12:41

答案

  •       您可以这样来研究这个问题。 我们知道,这种Windows 的公共对话框,是放在一个动态库中的。 这个动态库就是comdlg32.dll,位置在C:\Windows\System32\ 路径下。 您可以用Visual Studio 打开这个comdlg32.dll。 在资源视图中,找到Dialog 节点,以Windows 7 为例,资源1562、1563、1565,就是您上面提到的那三个打开/保存 文件对话框的资源。 也就是说,Windows 提供了三种Windows 打开/保存 文件对话框供程序调用。

          但是,如果使用Denpends.exe 查看comdlg32.dll 的导出函数列表,看不到有可供调用的导出函数。但是我们可以看到DllCanUnloadNow 这个函数, 熟悉COM 的一定会想到,这个DLL 里面可能有COM 对象。 但是,如果使用OLE-Object Viewer 去查看这个DLL, 又无法读取IDL 信息。

          这里可以取一个捷径,看看.NET 是怎么做的? 如果写一个简单的.NET 程序,用OpenFileDialog 类型的一个实例,显示一个打开文件对话框, 那么发现是http://hiphotos.baidu.com/doomsdayer/pic/item/d10f10777c1bc154b051b9b8.jpg 这种情况,也就是楼主提到的Notepad 的打开文件对话框类型。这就好办了,用Reflector 打开System.Windows.Forms.dll 看看OpenFileDialog 类是如何实现的。 实际上,是FileDialogNative 这个类实现了各种打开/保存文件对话框的显示。 再往里看,就可以发现有IFileDialog 接口,还有IFileOpenDialog 等等接口。

          在MSDN 里面查一下IFileOpenDialog 接口,发现这个接口的OS 最小支持版本就是Windows Vista,那么就确定实现这个接口的代码,就是那个打开文件对话框无疑了(因为那种简单的打开文件对话框,Win98 以后都支持)。

          实现的方法就简单了,直接CoCreateInstance COM 对象,然后QueryInterface IFileOpenDialog 接口,再然后调用IFileOpenDialog::Show() 即可。

         Codeproject 上面有一篇文章,专门讲这个:

    http://www.codeproject.com/KB/vista/VGFileDialogs.aspx

     

    祝你好运!

     


    Would you know my name, if I saw you in heaven......
    • 已标记为答案 Doomsdayer 2011年1月6日 1:38
    2011年1月5日 14:39
    版主

全部回复

  •       您可以这样来研究这个问题。 我们知道,这种Windows 的公共对话框,是放在一个动态库中的。 这个动态库就是comdlg32.dll,位置在C:\Windows\System32\ 路径下。 您可以用Visual Studio 打开这个comdlg32.dll。 在资源视图中,找到Dialog 节点,以Windows 7 为例,资源1562、1563、1565,就是您上面提到的那三个打开/保存 文件对话框的资源。 也就是说,Windows 提供了三种Windows 打开/保存 文件对话框供程序调用。

          但是,如果使用Denpends.exe 查看comdlg32.dll 的导出函数列表,看不到有可供调用的导出函数。但是我们可以看到DllCanUnloadNow 这个函数, 熟悉COM 的一定会想到,这个DLL 里面可能有COM 对象。 但是,如果使用OLE-Object Viewer 去查看这个DLL, 又无法读取IDL 信息。

          这里可以取一个捷径,看看.NET 是怎么做的? 如果写一个简单的.NET 程序,用OpenFileDialog 类型的一个实例,显示一个打开文件对话框, 那么发现是http://hiphotos.baidu.com/doomsdayer/pic/item/d10f10777c1bc154b051b9b8.jpg 这种情况,也就是楼主提到的Notepad 的打开文件对话框类型。这就好办了,用Reflector 打开System.Windows.Forms.dll 看看OpenFileDialog 类是如何实现的。 实际上,是FileDialogNative 这个类实现了各种打开/保存文件对话框的显示。 再往里看,就可以发现有IFileDialog 接口,还有IFileOpenDialog 等等接口。

          在MSDN 里面查一下IFileOpenDialog 接口,发现这个接口的OS 最小支持版本就是Windows Vista,那么就确定实现这个接口的代码,就是那个打开文件对话框无疑了(因为那种简单的打开文件对话框,Win98 以后都支持)。

          实现的方法就简单了,直接CoCreateInstance COM 对象,然后QueryInterface IFileOpenDialog 接口,再然后调用IFileOpenDialog::Show() 即可。

         Codeproject 上面有一篇文章,专门讲这个:

    http://www.codeproject.com/KB/vista/VGFileDialogs.aspx

     

    祝你好运!

     


    Would you know my name, if I saw you in heaven......
    • 已标记为答案 Doomsdayer 2011年1月6日 1:38
    2011年1月5日 14:39
    版主
  • 参考CSDN上的同一个问题



    The following is signature, not part of post
    Please mark the post answered your question as the answer, and mark other helpful posts as helpful, so they will appear differently to other users who are visiting your thread for the same problem.
    Visual C++ MVP
    2011年1月5日 22:23
    版主
  • 对您的精彩回答表示感谢!作为一名初级vc程序员,目前我还处于熟悉VC/WINDOWS API的阶段,而且不幸的一点是,因为条件所限,目前我还只能使用VC6进行开发,如果IFileOpenDialog只支持VISTA以上的操作系统的话,我就必须为XP考虑老版本的对话框实现。相信通过对您所提到知识的学习后,我可以根据操作系统不同而实现不同的对话框效果来。

    再次感谢您的精彩回答!

    2011年1月6日 1:42
  • 谢谢您的解答,不过我在原帖中忘记说明的一点是,我用的是VC6....

    所以没有办法用CFolderPickerDialog,不过还是谢谢您的提醒!

    2011年1月6日 1:44