分享
 
 
 

Windows2000新型Open对话框的使用

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

Windows2000新型Open对话框的使用

编译/zxn

问题的提出:

我刚刚在几台机器上安装了Windows® 2000,不知道如何在MFC应用中打开具有新的Outlook风格栏目的Open对话框(见图一)。

图一 新的 Open 对话框

我能否只设置一个标志,或者我是否需要一个新的头文件和一个新的公共对话框的DLL?我注意到一些旧的应用程序如Notepad好像可以打开新的Open对话框而无须重新编译,但它们不是MFC应用。理想情况,我希望在Windows

9x 和Windows NT®下得到一个使用旧对话框的应用,而在Windows 2000下使用新的对话框。

这个问题恐怕没有令你高兴的答复。Windows 2000新的“打开”对话框是用一个新版本的commdlg.dll实现的,其中包含一个叫做“Places

Bar”的东东。显示它的函数是GetOpenFileName,这个函数与在Windows

9x 和Windows NT®下使用的相同。然而,GetOpenFileName现在使用一个新版本的OPENFILENAME结构,这是一个在你的应用和对话框之间传递信息的结构。新的结构有一些额外的成员:

typedef struct tagOFN {

DWORD lStructSize; // 很重要!

•••

// as you''ve always known and loved it

#if (_WIN32_WINNT >= 0x0500)

void* pvReserved;

DWORD dwReserved;

DWORD FlagsEx;

#endif // (_WIN32_WINNT >= 0x0500)

} OPENFILENAME, *LPOPENFILENAME;

Windows 2000是Windows的第5个版本,用16进制表示是0x500。如果你用_WIN32_WINNT = 0x0500编译程序,OPENFILENAME就会得到3个新成员。前两个是保留的,第三个标志域

是 FlagsEx,有一个新的OFN_EX_NOPLACESBAR标志,它屏蔽了Places栏目。Windows——或者更准确的说,commdlg.dll——使用OPENFILENAME第一个成员lStructSize来决定显示那个对话框,根据微软的说法:如果lStructSize是76(旧的大小),Windows就运行旧的对话框。如果是76+3x4=88(新的大小),它就运行新的对话框。但在实际的研究中,会发现不完全是这么回事。

但是在我详细说明之前,先让我们走马观花地看一下MFC。讨论另外一个问题。在MFC应用中,通常并不直接调用GetOpenFileName,而是使用CFileDialog——或者框架使用CFileDialog。当用户调用File

| Open,控制稀里哗啦的一路经过CWinApp::OnFileOpen和几个其它的函数,最终到达CDocManager::DoPromptFileName,这个函数创建一个CFileDialog。CFileDialog具有一个OPENFILENAME结构的数据成员:

class CFileDialog : public CCommonDialog {

OPENFILENAME m_ofn;

•••

};

这个结构的大小是当编译MFC42.DLL时OPENFILENAME的大小;换句话说,旧的大小。而且,如果你正在进行一个静态连接,MFC代码在MFC42.DLL或NAFXCW.LIB里是被冻结的,你不能仅仅设置m_ofn.lStructSize为新的大小,因为CFileDialog除m_ofn外还有其它数据成员,它们将被新的OPENFILENAME的成员覆盖。

不再耽搁了,我开始使用极端的方法避开这个问题。我考虑可以做些什么,类似于MFC中使用CPropertyPage那样。PROPSHEETPAGE和PROPSHEETHEADER的大小在从Windows

95到Windows 98的过程中的某处增加了,这是为了支持wizard风格的页面。为了支持新膨胀的结构,MFC提供了CPropertyPageEx和CPropertySheetEx。最初的类(不带Ex的)仍然使用旧的结构;而新的类使用新的结构。这是一种杂凑,尤其是因为afxdlgs.h具有自己的旧的结构的定义(AFX_

OLDPROPSHEETPAGE和AFX_OLDPROPSHEETHEADER),但是这样却行得通。

我对CFileDialog做了同样的事情。首先我派生一个新的CFileDialogEx类,它带有一个新的m_ofn,包含着新的OPENFILENAMEEX结构,我模仿0x500版本加以定义。我加入这3个新的成员并且使用m_ofn.重写了CFileDialog函数。不幸的是,因为大多数的MFC代码是固定的,没有任何虚拟功能,这就意味着复制原来的整个类。但是我已经下了决心。

在我认为已经找到了m_ofn出现的所有地方以后,我重写了它,高高兴兴的编译了我的代码(在Windows 98上),然后运行——结果发现我得到的仍是旧风格的对话框。而且,有一个谜团我忘了考虑:如果Windows

2000使用lStructSize来决定运行那个Open对话框,为什么Windows 98的应用程序(象Notepad)在Windows 2000下运行时得到了新的对话框呢?啊!随Windows

98出现的NOTEPAD.EXE显然在lStructSize 上有旧的OPENFILENAME的大小,因此Windows 2000必须使用lStructSize之外的某种东西来决定运行那个对话框。到这里,我决定回过头去重新考虑问题。我将MFC放到一边,尝试直接调用GetOpenFileName。我重写了我的应用程序的OnFileOpen:

void CMyApp::OnFileOpen()

{

OPENFILENAME ofn; // older version

memset(&ofn, 0, sizeof(ofn));

ofn.lStructSize = sizeof(ofn);

int nResult = ::GetOpenFileName(&ofn);

}

因为贯穿本练习,我使用了旧的0x400版本的SDK文件(因为我希望应用程序既可以在Windows 2000上运行,也可以在Windows 9x上运行),ofn.lStructSize就有了旧的大小。当我编译并运行时,我在Windows

98上得到了旧的对话框,而在Windows 2000上得到了新的对话框——就象Notepad一样!因此可以说,实际上,Windows 2000足够精明的为旧的应用使用新的对话框——但不是旧的MFC应用。它毫无意义。一个MFC应用的不同之处在哪里呢?

一定是标志。为了发现真相,我在OPENFILENAME结构中手工添加了不同的标志,直到我的程序产生了不带Places bar的旧风格的窗口。你瞧,只要我为ofn.Flags加入标志OFN_ENABLEHOOK,对话框就回到了从前。我将此奇怪的行为报告给Redmond,他们证实“这种行为是设计的”。

那么,Windows 2000判断OPENFILENAME的大小以及对话框是否使用hook过程。如果OPENFILENAME有旧的大小,Windows

2000使用OFN_ENABLEHOOK来决定运行哪个对话框。如果OPENFILENAME使用hook过程(或者设置了ORN_ENABLETEMPLATE),Windows

2000按照旧的风格显示对话框;否则,显示新的对话框。这就解释了为什么MFC应用显示了旧的对话框——因为CFileDialog,就象所有MFC的公用对话框一样,使用hook过程。这是MFC将公用对话框嵌入它的消息映射系统的方式,它用同样的方式使用AfxWndProc嵌入其它的窗口。现在你看到了结果:你给迷惑了。在一个MFC应用中得到新风格的对话框的唯一的办法是完全绕开CFileDialog,直接调用GetOpenFileName,并且不使用hook过程。即使你用新的SDK文件和WINVER

= 0x500编译你的应用,你仍不能使用MFC,因为它的库和DLLs有旧的大小。你可以使用WINVER = 0x500自行编译MFC,但是谁知道那将怎么样呢?而且如果你真的BUILD了新的MFC,你将不得不将新的DLL和你的应用一块发布,给它起个不同的名字,因为你的新的MFC

DLL肯定不会与其它的希望使用CFileDialog 和其它结构的旧的大小的MFC应用兼容。或者,你可以重新生成MFC,然后静态的连接,这将极大的增加你的可执行文件的大小,如果你不重新实现Windows的话。

到截稿时间为止,我从Redmond听说在即将发布的新的Visual

C++®中,将会有一个不同名字的新版本的MFC DLL。新版本的MFC将支持Windows 2000中出现的新的UI和APIs。下表是在最新的SDK文档中列出的 Windows目标版本宏:

(表一)

系统最小需求

宏定义

Windows 95 和 Windows NT

4.0

WINVER=0x0400

Windows 98 和 Windows NT

4.0

_WIN32_WINDOWS=0x0410 和

WINVER=0x0400

Windows NT 4.0

_WIN32_WINNT=0x0400 和

WINVER=0x0400

Windows 98 和 Windows 2000

WINVER=0x0500

Windows 2000

_WIN32_WINNT=0x0500 和

WINVER=0x0500

Internet Explorer 3.0

_WIN32_IE=0x0300

Internet Explorer 4.0

_WIN32_IE=0x0400

Internet Explorer 5.0

_WIN32_IE=0x0500

注:将 WINVER

设置为 0x0500 意味着 _WIN32_IE=0x0400

,“Header File 规范”提供了解决 Windows 版本问题的钥匙。它向你说明:为了达到某个版本的Windows和Microsoft® Internet

Explorer的目标你必须使用SDK头文件定义哪些宏。努力吧,不要跌倒在生活的快车道上。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有