ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 利用MFC的CFileDialog生成Windows2000文件对话框 (转)

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

原创 Linux操作系统 作者:amyz 时间:2007-10-02 15:47:56 0 删除 编辑
利用MFC的CFileDialog生成Windows2000文件对话框 (转)[@more@]

利用MFC的CFileDialog生成2000对话框


周鸣扬


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

图一

图二

图一是我们最常见的文件对话框(本文称之为老式的文件对话框),图二是在Windows2000中用得普遍的文件对话框(本文称之为新式的文件对话框)。同样都是文件对话框,却有着不同的界面。在图二中,我们可以看到在对话框的左边有一快捷工具栏,它能够帮助我们在中地定位,这在操作上要比图一所示的对话框要方便得多。奇怪的是,图二所示的对话框并非是Windows2000的专利,因为我们在Windows98中运行 2000时,也能够见到图二所示的文件对话框;在Windows2000中,同样也能够见到图一所示的对话框(如VC的使用界面)。而且,更重要的是,我们使用VC的CFileDialog 所生成的文件对话框,并不能够产生图二所示的界面,这是怎么回事?还有一点不能让人理解的是,有些应用程序(如:“记事本”程序)分别在Windows2000和在Windows98下运行时,居然会有不同的文件对话框界面了?这又是怎么回事?带着这些疑问,我仔细查阅了一下MSDN,对对话框界面有一一点初步的认识。下面将我在编写文件对话框程序中的一点心得写出来,与大家共同探讨: 文件对话框是一种特定的窗口,对话框运行时对各种消息的响应是通过对话的“钩子”来完成的。对于对话框的外观,我们可以通过修改“文件对话框模板”来实现;同样,如果要想文件对话实现其它功能(如带文件预览功能的文件对话框),可以通过修改文件对话框的“钩子函数”来完成。在VC中,为我们提供了现成的文件对话框类CFileDialog,利用该类,我们可以很方便地生成的文件对话框。在使用CFileDialog时,其中最重要的工作是对其成员变量m_ofn做初始化工作。 m_ofn实际上是一OPENFILENAME类型的结构(Struct) ,OPENFILENAME的定义如下: typedef struct tagOFN { D lStructSize;// OPENFILENAME结构的大小 DWORD Flags; ………………此处略去具体的成员变量……………………. #if (__WINNT >= 0x0500) void * pvReserved; DWORD dwReserved; DWORD FlagsEx; #endif // (_WIN32_WINNT >= 0x0500) } OPENFILENAME, *LPOPENFILENAME; 由上可以看出,OPENFILENAME中有一Flags成员变量,它决定了对话框的外观,它是一组预定义宏的组合。通过它,我们可以定制个性化的文件对话框。比如,在图一中,“以只读方式打开”这一选项就是因为在Flags中包括了“OFN_READONLY”。 当我们在使用OPENFILENAME结构时,我们已经习惯了用下面的语句来设定lStructSize:   OPENFILENAME dlgFileOpen; 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显示老式的文件对话框,原因是什么?请继续往下看: 我们知道,的版本号已经突破了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)));   // 如果运行的操作系统是/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.odal()==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 = "所有的文件*.*文本文件*.TXT"; ofn.nMaxFile = MAX_PATH; ofn.lpstrFile=lpstrFilename;   if (GetOpenFileName(&ofn)) MessageBox("你所打开的文件是:"+(CString)ofn.lpstrFile); else MessageBox("打开文件出错!"); } 上述程序在我的网页“国税之家” () 中的”个人世界”里可以到。如果你还想进一步修改MFC文件对话框并且让你的系统菜单中的“打开\保存”也能够用上新的文件对话框,你可以去重定义CfileDialog类,具体方法本文不做详细说明,不过,你也可以在上面我提到的网站上去下载。 应该说MFC在处理文件对话上面做得不是很好,如果你去查阅MSDN,你是查不到本文所述内容的.一个本来很简单的问题,却做了这么多工作,这也算得上MFC的“特色”吧!

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752019/viewspace-974572/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
  • 博文量
    3982
  • 访问量
    7512605