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

2016-01-29 11:50 14 1 收藏

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

【 tulaoshi.com - C语言心得技巧 】

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

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com)

编译/zxn

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com) 本文代码例子

    不久以前,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
                        

来源:http://www.tulaoshi.com/n/20160129/1483516.html

延伸阅读
问:程序是基于对话框的,我显示两个对话框,一个在另一个后面,下面是我的做法: CMyApp::InitInstance () { ... CMyDialog1 dlg1; m_hMainWnd = &dlg1; int result = dlg1.DoModal (); CMyDialog2 dlg2; result = dlg2.DoModal (); ... } 在上面的代码中,首先一个对话框得到了适当地调用...
在c++Builder控件板上的Dialogs页上的VCL控件包括了Windows常用的对话框。换句话说,VCL并没有提供对话框,那些对话框都是Windows的一部分。VCL只是使得使用这些对话框变得轻易些。在一些应用中,你可能想改变打开对话框中打开按钮的标题,例如,变成表示你的程序答应用户添加文件到文档中,这中情况下,你可能想打开按钮上的标题自己的标题而不...
标签: 办公软件
    Excel 2000 新增的在对话框中输入区域引用可以折叠的按钮,这样用户在工作表上选定所需的区域时,对话框就不会阻挡视线。对这类对话框的操作是,在折叠按钮上单击可以将其折叠,再次单击则返回到对话框,图2-9和图2-10分别显示了折叠前后的效果。
Windows SDK笔记(四):模式对话框 作者:冯明德 一、概述 对话框是一种特殊的窗口,它依据对话框模板资源而建立。 它与一般的窗口有些不同,很多过程由系统完成了,虽然用户还是要提供一个消息处理函数,但在此消息处理函数中,不需要将不关心的消息交由缺省消息处理函数。 实际...
1、意图 有时候我们希望将非模态窗口显示为模态窗口。比如在IE的“文件”菜单下选择“打印”,弹出的“打印”对话框就是非模态的(也许我们不太清楚Microsoft的设计意图,一般来说这里的“打印”对话框应该是模态的)。这种情况下如何将“打印”对话框显示为模态的呢(这个对话框对我们来说是Black Box)? 2、简单实现 简单...

经验教程

412

收藏

77
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部