分享
 
 
 

利用MFC的CFileDialog生成Windows2000文件对话框

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

利用MFC的CFileDialog生成Windows2000文件对话框

周鸣扬

自Windows2000推出以后,其新的用户界面使我们有了一次大换口味的机会。比如,其淡入浅出的动画菜单、透明的窗口,另外一个变化就是其文件对话框外观的改变,在程序中打开保存文件时出现的对话框就要比原来在Windows98下面的要“亲热”得多:先看看以下两幅图片:

图一

图二

图一是我们最常见的文件对话框(本文称之为老式的文件对话框),图二是在Windows2000中用得普遍的文件对话框(本文称之为新式的文件对话框)。同样都是文件对话框,却有着不同的界面。在图二中,我们可以看到在对话框的左边有一快捷工具栏,它能够帮助我们在计算机中快速地定位,这在操作上要比图一所示的对话框要方便得多。奇怪的是,图二所示的对话框并非是Windows2000的专利,因为我们在Windows98中运行Office2000时,也能够见到图二所示的文件对话框;在Windows2000中,同样也能够见到图一所示的对话框(如VC的使用界面)。而且,更重要的是,我们使用VC的CFileDialog 所生成的文件对话框,并不能够产生图二所示的界面,这是怎么回事?还有一点不能让人理解的是,有些应用程序(如:“记事本”程序)分别在Windows2000和在Windows98下运行时,居然会有不同的文件对话框界面了?这又是怎么回事?带着这些疑问,我仔细查阅了一下MSDN,对对话框界面有一一点初步的认识。下面将我在编写文件对话框程序中的一点心得写出来,与大家共同探讨:

文件对话框是一种特定的窗口,对话框运行时对各种消息的响应是通过对话的“钩子函数”来完成的。对于对话框的外观,我们可以通过修改“文件对话框模板”来实现;同样,如果要想文件对话实现其它功能(如带文件预览功能的文件对话框),可以通过修改文件对话框的“钩子函数”来完成。在VC中,系统为我们提供了现成的文件对话框类CFileDialog,利用该类,我们可以很方便地生成的文件对话框。在使用CFileDialog时,其中最重要的工作是对其成员变量m_ofn做初始化工作。

m_ofn实际上是一OPENFILENAME类型的结构(Struct) ,OPENFILENAME的定义如下:

typedef struct tagOFN {

DWORD lStructSize;// OPENFILENAME结构的大小

DWORD Flags;

………………此处略去具体的成员变量…………………….

#if (_WIN32_WINNT >= 0x0500)

void * pvReserved;

DWORD dwReserved;

DWORD FlagsEx;

#endif // (_WIN32_WINNT >= 0x0500)

} OPENFILENAME, *LPOPENFILENAME;

由上可以看出,OPENFILENAME中有一Flags成员变量,它决定了对话框的外观,它是一组预定义宏的组合。通过它,我们可以定制个性化的文件对话框。比如,在图一中,“以只读方式打开”这一选项就是因为在Flags中包括了“OFN_READONLY”。

当我们在使用OPENFILENAME结构时,我们已经习惯了用下面的语句来设定lStructSize:

OPENFILENAMEdlgFileOpen;

dlgFileOpen.lStructSize=sizeof(OPENFILENAME);

//注:无论是在Windows98或是Windows2000下运行,lStructSize的值只会是76

实际上,我们如果仔细算一下,76只是#if (_WIN32_WINNT >= 0x0500)前所有成员变量的长度,如果加上#if (_WIN32_WINNT >= 0x0500)以后的三个变量(pvReserved、dwReserved、FlagsEx)的长度, lSstructSize的值应该是76+3*4=88。正是由于这个习惯性的操作,我们才在无意中有意让Windows2000显示老式的文件对话框,原因是什么?请继续往下看:

我们知道,Windows 2000的版本号已经突破了5。如果你使用_WIN32_WINNT = 0x0500进行程序的编译,#if (_WIN32_WINNT >= 0x0500)后的头两个成员参数被当成了保留值,剩下和一个成员参数FlagsEx,就有了一个新的标志值可供选择:OFN_EX_NOPLACESBAR,正是因为OFN_EX_NOPLACESBAR,你才不能够在你所编写的程序中见到快捷工具栏。奇怪的是,和OFN_EX_NOPLACESBAR相比,VC并未提供“OFN_EX_SHOWPLACESBAR”之类的选择。

之所以对lStructSize的值算来算去,是因为在Windows2000中使用MFC的CFileDialog所生成的对话框时,lStructSize的值直接影响着对文件对话框对快捷工具栏显示与否。如果OPENFILENAME的大小是76,则文件对话框不显示快捷工具栏;如果OPENFILENAME的大小是88,文件对话框显示快捷工具栏。当然,这种说法是有一定前提条件的,在以下的叙述中,你会对此有更深刻的了解。

如果Windows 2000 仅仅通过判别OPENFILENAME 的lStructSize值来确定显示文件对话框的方式,那么,为什么有些在Windows98 下运行的程序在Windows 2000下依然能够显示新型的文件对话框(如Windows98中的“记事本”程序)? 很明显,Windows98下的lStructSize值一定是76, 所以Windows 2000一定还有另一种方式来决定使用何种形式来显示文件对话框,是什么呢?

OPENFILENAME结构中有一Flags值,这个值决定着文件对话框的外观。 Windows 2000就是通过这值来从另一方面来决定使用何种形式来显示文件对话框(准确地说,如果你使用的是MFC的CFileDialog所生成的对话框)是同时通过Flags和lStructSize来决定使用何种形式来显示文件对话框。如果Flags值包含了OFN_ENABLEHOOK(启用钩子函数),且lStructSize值是88,显示新的文件对话框;如果Flags不含OFN_ENABLEHOOK(注意:CFileDialog的Flags必须要含OFN_ENABLEHOOK),那么,不管lStructSize的值是多少,显示新的文件对话框;如果OPENFILENAME使用了对话框钩子函数,且lStructSize的值是76, Windows 2000 显示老式的文件对话框;这种显示机制解释了利用MFC的CFileDialog的应用程序在Windows 2000 下运行时总是显示老式的文件对话框。因为, MFC在文件对话框中都使用了对话框钩子函数,不信,你去看看CFileDialog类的实现源程序Dlgfile.cpp第76行:ASSERT(m_ofn.Flags & OFN_ENABLEHOOK),这从根本上说明,MFC的对话框必须使用钩子函数!而且,我们所习惯的“dlgFileOpen.lStructSize=sizeof(OPENFILENAME)”这种操作只会强制地要求Windows2000显示老式的文件对话框。这就注定了使用CFileDialog类的文件对话框在Windows 2000下必定被显示成老式的文件对话框。

问题很明显了,归纳一下上面所述内容,我们可以得出以下结论:1、如果是在Windows98下,你用MFC的CFileDialog类生成的对话框是不能实现新式对话框的显示。也许你会问,Windows98中运行Office2000时,系统照样能够显示新型的文件对话框,笔者在此做猜测,那是因为Office2000的文件对话框根本未使用MFC的对话显示原理,如果非要在Windows98中显示新的文件对话框,你得重新定义一个文件对话框类。2、显然,并不是所有的文件对话框程序都是由MFC的CFileDialog所生成的。如果你不用CFileDialog对话框,你根本不用考虑文件对话框的外观,新产生的对话框外观将自动随操作系统而自动地在新式与老式之间进行转换。3、在Windows 2000下,使用MFC生成的对话框,如果你能够确认文件对话框未使用对话框钩子函数(如GetOpenFileName()函数),那么,你开发的程序一定能够显示出新的对话框(而不必在乎OPENFILENAME中lStructSizer的值),而且这种程序在使用时不必在乎运行的操作系统平台,这也不难理解 “记事本”程序在Windows98和Windows2000下运行时会有不同的文件对话框界面了;如果MFC文件对话框使用钩子函数,那么,有且仅有的办法是修改OPENFILENAME的大小,当OPENFILENAME的大小是88时,Window2000显示新型的文件对话框,否则显示老式的文件对话框。同时要提到的是:将OPENFILENAME的值强行设为88,这样的程序在Windows98下面是不能正常运行的(你根本见不到对话框),你得在程序中加入对应用程序的运行平台的判断代码了。

有了上述的认识,我们也可以利用MFC做出适应系统平台的文件对话框了,正如“写字板”那样:在Windows98下面显示老式的文件对话框,而在Windows2000中,则显示新型的文件对话框。试试下面的程序:

在VC中新建一单文档(SDI)项目,在资源编辑器中分别加入两项菜单项:“用CFileDialog产生对话框”和“用GetOpenFileName产生对话框”,同时加入对该两项菜单COMMAND事件的响应函数,如下:

void CMainFrame::OnCfiledialog()

{

CFileDialog dlgFileOpen(TRUE);

int structsize=0;

DWORD dwVersion,dwWindowsMajorVersion,dwWindowsMinorVersion;

//检测目前的操作系统,GetVersion具体用法详见MSDN

dwVersion = GetVersion();

dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));

dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));

// 如果运行的操作系统是Windows NT/2000

if (dwVersion < 0x80000000)

structsize =88;//显示新的文件对话框

else

//运行的操作系统Windows 95/98

structsize =76;//显示老的文件对话框

dlgFileOpen.m_ofn.lStructSize=structsize;

TCHAR lpstrFilename[MAX_PATH] = "";

dlgFileOpen.m_ofn.lpstrFile=lpstrFilename;

if(dlgFileOpen.DoModal()==IDOK)

MessageBox("你所打开的文件是:"+(CString)dlgFileOpen.m_ofn.lpstrFile);

else

MessageBox("打开文件出错!");

}

void CMainFrame::OnGetopenfilename()

{

OPENFILENAME ofn;

//设定文件的名称储存空间

TCHAR lpstrFilename[MAX_PATH] = "";

//清空OPENFILENAME

ZeroMemory(&ofn, sizeof(ofn));

ofn.lStructSize = sizeof(OPENFILENAME);//lStructSize的返回值是是76

//设定父窗口

ofn.hwndOwner = this->m_hWnd;

///设定打开文件的类型

ofn.lpstrFilter = "所有的文件\0*.*\0文本文件\0*.TXT\0";

ofn.nMaxFile = MAX_PATH;

ofn.lpstrFile=lpstrFilename;

if (GetOpenFileName(&ofn))

MessageBox("你所打开的文件是:"+(CString)ofn.lpstrFile);

else

MessageBox("打开文件出错!");

}

上述程序在我的网页“国税之家” (http://nationaltax.home.chinaren.com) 中的”个人世界”里可以下载到。如果你还想进一步修改MFC文件对话框并且让你的系统菜单中的“打开\保存”也能够用上新的文件对话框,你可以去重定义CfileDialog类,具体方法本文不做详细说明,不过,你也可以在上面我提到的网站上去下载。

应该说MFC在处理文件对话上面做得不是很好,如果你去查阅MSDN,你是查不到本文所述内容的.一个本来很简单的问题,却做了这么多工作,这也算得上MFC的“特色”吧!

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
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- 王朝網路 版權所有