当前位置: 首页 > 图文教程 > 开发语言 > VC++ > 再谈 Windows 2000 “打开”文件对话框

VC++
用VC++创建自定义向导程序
自定义 CRichEditCtrl 控件
Office 2000 风格的停泊、智能型菜单
黑客攻击手段之偷梁换柱
完善 CPopupText 类
让工具条显示256色图像
定制编辑框的上下文菜单
列表控件排序功能的实现
一个优秀的网格控件CGridCtrl
如何用代码动态添加控件
如何在编辑框中使用IAutoComplete接口
应用程序中添加“Coolbars”的简单方法
介绍一个有Toolbar功能的可重用类 CPopupText
在工具栏按钮上添加文本标签
类似Dreamweaver的颜色选择器
如何设置ListView控件的完全行(Full Row)选项
如何enable/disable菜单项
关于CEdit控件的透明 --作者:monsoon
动态菜单项、状态条提示、工具条提示问题
CAnimateCtrl::Open的使用问题

VC++ 中的 再谈 Windows 2000 “打开”文件对话框


出处:互联网   整理: 软晨网(RuanChen.com)   发布: 2009-10-30   浏览: 227 ::
收藏到网摘: n/a

再谈 Windows 2000 “打开”文件对话框

编译/zxn

本文代码例子

    不久以前,VC知识库曾探讨过如何在MFC应用中打开Windows 2000风格的“文件/打开”对话框(类似Outlook Express左边的Places Bar)。最近又有许多人问及这方面的问题,也许我在那篇文章中讲的不是很清楚,所以这次在本文中重申这个问题。
     Windows 2000有个新的“Open”对话框(图一),这个对话框的左边有一个Places Bar,要想让这个对话框出现,必须在::GetOpenFileName函数中传递OPENFILENAME结构,这个结构隐藏在MFC的CFileDialog类中。问题是这个结构最新的版本(即Windows 2000中的5.0及以后的版本)有附加的成员,增加它的尺寸。当你(或MFC)调用::GetOpenFileName之前,你必须初始化结构OPENFILENAME的第一个成员-lStructSize-它决定了OPENFILENAME结构的大小。如果你在Windows 2000(_WIN32_WINNT >= 0x0500)中编译,你会得到结构的最新尺寸;如果你在较早的Windows版本中编译,你却得到旧的结构尺寸。

图一 新的“打开”对话框

     当你在Windows 95, Windows 98或Windows NT 4.0运行应用程序的时候,你必须使用旧的结构尺寸。而在Windows 2000中,你既可以使用旧的结构尺寸,也可以使用最新的结构尺寸。如果lStructSize是新的尺寸,Windows 2000打开新风格的对话框。如果lStructSize是旧的尺寸,Windows 2000还检查结构OPENFILENAME中其它的信息:即如果对话框有“钩子”(hook)功能标志(OFN_ENABLEHOOK)或模板标志(OFN_ENABLETEMPLATE),Windows 2000打开旧风格的对话框,否则打开新风格的对话框。这多少使人感觉有些混乱。无论你如何做,MFC42.DLL都被用旧的结构尺寸编译,并且MFC使用一个吊钩过程(OFN_ENABLEHOOK)将对话框连接到你的消息映射......。
     天无绝人之路,一位名叫Michael Lemley哥儿们给了我一个问题的解决方案,其基本思路是:在MFC的CFileDialog中增加一个新成员-m_ofnEx,诱使MFC使用这个成员。为了保证代码能在所有的Windows版本中运行,lStructSize 结构成员必须根据实际运行的Windows版本被正确初始化。Michael的方法有两个地方值得商榷:一个是拷贝大量的MFC代码;一个是运行时检查操作系统版本。修改工作是在新类CFileDialogEx中进行的,

// OPENFILENAME 结构的 Windows 2000 版本struct OPENFILENAMEEX : public OPENFILENAME { void * pvReserved; DWORD dwReserved; DWORD FlagsEx;};// CFileDialog 类的 Windows 2000 版本class CFileDialogEx : public CFileDialog {protected: OPENFILENAMEEX m_ofnEx; // 新增成员};
    OPENFILENAME 的定义在commdlg.h文件中,而 OPENFILENAMEEX 是模仿 OPENFILENAME 的本地(局部)定义。OPENFILENAMEEX有三个新成员。为了使用这个新结构,CFileDialogEx 重写 DoModal。你必须从CFileDialog 拷贝整个函数到 CFileDialogEx,代码细节如下:
添加 m_ofnEx int CFileDialogEx::DoModal(){...... // 前面是 MFC 代码 // 拷贝 m_ofn ==> m_ofnEx 并设置 memset(&m_ofnEx, 0, sizeof(m_ofnEx)); memcpy(&m_ofnEx, &m_ofn, sizeof(m_ofn)); if (IsWin2000()) m_ofnEx.lStructSize = sizeof(m_ofnEx); // 使用 m_ofnEx 运行 "打开"或"保存"对话框 int nResult; if (m_bOpenFileDialog) nResult = ::GetOpenFileName((OPENFILENAME*)&m_ofnEx); else nResult = ::GetSaveFileName((OPENFILENAME*)&m_ofnEx); // 回拷 m_ofnEx ==> m_ofn memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn)); m_ofn.lStructSize = sizeof(m_ofn);......}
    上述代码的基本思路是在调用 GetOpenFileName 或 GetSaveFileName 之前先将 m_ofn 拷贝到 m_ofnEx,调用完成后再拷回去。其中最重要的是其第一个结构成员----lStructSize 按照实际运行的操作系统版本被初始化。获取操作系统版本参见 IsWin2000 函数:
IsWin2000函数实现////////////////////////////////////////////////////////////////// 检测操作系统版本(Windows 2000 或以后)的函数//BOOL IsWin2000 () { OSVERSIONINFOEX osvi; BOOL bOsVersionInfoEx; // 尝试调用 GetVersionE