用VC6打开XP风格通用文件对话框

   一般地,VC6中使用CFileDialog来打开windows通用打开文件对话框和保存文件对话框。但,遗憾地是,很多人告诉我(包括我头头),也许也会这么告诉你,CFileDialog只能打开win98风格的对话框,如下图一。

 

图一,标准文件打开对话框

   但我们是不会满足的,看着别人程序里漂亮的XP风格对话框,难道我们只能扩展CFileDialog,自己实现(所有我认识的人都是这么告诉我的)?

   其实,只需简单的一步,就可以用VC6的CFileDialog来打开XP风格文件对话框,如图二,

 


图二 XP风格的通用文件对话框,带左侧"我的电脑"按钮

 

目前,在VC6.0中, 我知道有四种方法可以实现调用XP风格通用文件对话框:

一。设置CFileDialog的 m_ofn 成员变量的 lStructSize 值

  1. CFileDialog   dlg(TRUE);
  2. dlg.m_ofn.lStructSize = 88;//76将是win98风格

    但请注意,1. 不能设置 m_ofn.Flags 的 OFN_ENABLEHOOK 标志和 m_ofn.lpfnHook 变量,否则还将是98风格。2.这个方法好像只适合Win2000及winXP版本windows,不支持95和98.

   这是因为,新的Open对话框是用一个新版本的commdlg.dll实现的,显示它的函数是GetOpenFileName,与在Windows   9x   和Windows   NT下使用的相同。然而,GetOpenFileName现在使用一个新版本的OPENFILENAME;9x下该结构的size是76,很不幸,进入NT时代,它被扩展成88。另一方面,“如果OPENFILENAME有旧的大小,Windows   2000使用OFN_ENABLEHOOK来决定运行哪个对话框。如果OPENFILENAME使用hook过程(或者设置了ORN_ENABLETEMPLATE),Windows   2000按照旧的风格显示对话框;否则,显示新的对话框。”

 

二。设置m_ofn的Flags

    使m_ofn.Flags值包含 OFN_EXPLORER  | OFN_ALLOWMULTISELECT,但不能包含OFN_ENABLEHOOK ,否则将仍是旧风格对话框。

   遗憾的是,因为不含有 OFN_ENABLEHOOK 标记,在 CFileDialog.DoModal()时,将会ASSERT,因为有如下判断:

  1. int CFileDialog::DoModal()
  2. {
  3.     ASSERT_VALID(this);
  4.     ASSERT(m_ofn.Flags & OFN_ENABLEHOOK);
  5.     ASSERT(m_ofn.lpfnHook != NULL);

   但因为是ASSERT,说明在release版本下是没问题的,仅Debug版下会ASSERT,当然,若你愿意,您也可以点忽略继续执行。

 

三。直接使用API函数GetOpenFileName

    CFileDialog也是调用的SDK中的GetOpenFileName API函数,可以直接设置它的Flags,这个我未试过,请参考MSDN。

 

四。派生CFileDialog类

   这个解决方案来自MSDN,http://msdn.microsoft.com/zh-cn/magazine/cc301412(en-us).aspx

 

  由CFileDialog类 派生一个CFileDialogEx类,貌似该类可以在9x系统下弹出XP风格的对话框;遗憾地是,从我有记忆起,我仅高中阶段用过95/98;现在是找一个来测试都困难。。。

    完整代码附录如下,编译测试通过:

  1. // FileDialogEx.h : header file
  2. //
  3. //   Windows   2000   version   of   OPENFILENAME.   
  4. //   The   new   version   has   three   extra   members.   
  5. //   This   is   copied   from   commdlg.h   
  6. //  
  7. #if !defined(AFX_FILEDIALOGEX_H__A7F5E19C_B48A_481E_94D9_7922B9E2449E__INCLUDED_)
  8. #define AFX_FILEDIALOGEX_H__A7F5E19C_B48A_481E_94D9_7922B9E2449E__INCLUDED_
  9. #if _MSC_VER > 1000
  10. #pragma once
  11. #endif // _MSC_VER > 1000
  12. struct   OPENFILENAMEEX   :   public   OPENFILENAME   {     
  13.     void   *                 pvReserved;   
  14.     DWORD                   dwReserved;   
  15.     DWORD                   FlagsEx;   
  16. };   
  17. /   
  18. //   CFileDialogEx:   Encapsulate   Windows-2000   style   open   dialog.   
  19. //   
  20. class   CFileDialogEx   :   public   CFileDialog   {   
  21.     DECLARE_DYNAMIC(CFileDialogEx)   
  22. public:   
  23.     CFileDialogEx(BOOL   bOpenFileDialog,   //   TRUE   for   open,   FALSE   for   FileSaveAs   
  24.         LPCTSTR   lpszDefExt   =   NULL,   
  25.         LPCTSTR   lpszFileName   =   NULL,   
  26.         DWORD   dwFlags   =   OFN_HIDEREADONLY   |   OFN_OVERWRITEPROMPT,   
  27.         LPCTSTR   lpszFilter   =   NULL,   
  28.         CWnd*   pParentWnd   =   NULL);   
  29.     
  30.     //   override   
  31.     virtual   int   DoModal();   
  32.     
  33. protected:   
  34.     OPENFILENAMEEX   m_ofnEx; //   new   Windows   2000   version   of   OPENFILENAME   
  35.     
  36.     virtual   BOOL   OnNotify(WPARAM   wParam,   LPARAM   lParam,   LRESULT*   pResult);   
  37.     
  38.     //   virtual   fns   that   handle   various   notifications   
  39.     virtual   BOOL   OnFileNameOK();   
  40.     virtual   void   OnInitDone();   
  41.     virtual   void   OnFileNameChange();   
  42.     virtual   void   OnFolderChange();   
  43.     virtual   void   OnTypeChange();   
  44.     
  45.     DECLARE_MESSAGE_MAP()   
  46.         //{{AFX_MSG(CFileDialogEx)   
  47.         //}}AFX_MSG   
  48. };   
  49. //{{AFX_INSERT_LOCATION}}
  50. // Microsoft Visual C++ will insert additional declarations immediately before the previous line.
  51. #endif // !defined(AFX_FILEDIALOGEX_H__A7F5E19C_B48A_481E_94D9_7922B9E2449E__INCLUDED_)
CFileDialogEx.cpp
  1. //   MSDN   --   August   2000   
  2. //   If   this   code   works,   it   was   written   by   Paul   DiLascia.   
  3. //   If   not,   I   don't   know   who   wrote   it.   
  4. //   Largely   based   on   original   implementation   by   Michael   POSThttp://expert.csdn.net/Expert/reply.C++   6.0,   runs   on   Windows   98   and   probably   NT   too.   
  5. //   
  6. //   CFileDialogEx   implements   a   CFileDialog   that   uses   the   new   Windows   
  7. //   2000   style   open/save   dialog.   Use   companion   class   CDocManagerEx   in   an   
  8. //   MFC   framework   app.   
  9. //   
  10. #include   "stdafx.h"   
  11. #include   <afxpriv.h>   
  12. #include   "FileDialogEx.h"   
  13. #ifdef   _DEBUG   
  14. #define   new   DEBUG_NEW   
  15. #undef   THIS_FILE   
  16. static   char   THIS_FILE[]   =   __FILE__;   
  17. #endif   
  18. static   BOOL   IsWin2000();   
  19. IMPLEMENT_DYNAMIC(CFileDialogEx,   CFileDialog)   
  20. CFileDialogEx::CFileDialogEx(BOOL   bOpenFileDialog,   LPCTSTR   lpszDefExt,   
  21.                              LPCTSTR   lpszFileName,   DWORD   dwFlags,   LPCTSTR   lpszFilter,   CWnd*   pParentWnd)   :   
  22. CFileDialog(bOpenFileDialog,   lpszDefExt,   lpszFileName,   
  23.             dwFlags,   lpszFilter,   pParentWnd)   
  24. {   
  25. }   
  26. BEGIN_MESSAGE_MAP(CFileDialogEx,   CFileDialog)   
  27. //{{AFX_MSG_MAP(CFileDialogEx)   
  28. //}}AFX_MSG_MAP   
  29. END_MESSAGE_MAP()   
  30. BOOL   IsWin2000()     
  31. {   
  32.     OSVERSIONINFOEX   osvi;   
  33.     BOOL   bOsVersionInfoEx;   
  34.     
  35.     //   Try   calling   GetVersionEx   using   the   OSVERSIONINFOEX   structure,   
  36.     //   which   is   supported   on   Windows   2000.   
  37.     //   
  38.     //   If   that   fails,   try   using   the   OSVERSIONINFO   structure.   
  39.     
  40.     ZeroMemory(&osvi,   sizeof(OSVERSIONINFOEX));   
  41.     osvi.dwOSVersionInfoSize   =   sizeof(OSVERSIONINFOEX);   
  42.     
  43.     if(   !(bOsVersionInfoEx   =   GetVersionEx   ((OSVERSIONINFO   *)   &osvi))   )   
  44.     {   
  45.         //   If   OSVERSIONINFOEX   doesn't   work,   try   OSVERSIONINFO.   
  46.         
  47.         osvi.dwOSVersionInfoSize   =   sizeof   (OSVERSIONINFO);   
  48.         if   (!   GetVersionEx   (   (OSVERSIONINFO   *)   &osvi)   )     
  49.             return   FALSE;   
  50.     }   
  51.     
  52.     switch   (osvi.dwPlatformId)   
  53.     {   
  54.     case   VER_PLATFORM_WIN32_NT:   
  55.         
  56.         if   (   osvi.dwMajorVersion   >=   5   )   
  57.             return   TRUE;   
  58.         
  59.         break;   
  60.     }   
  61.     return   FALSE;     
  62. }   
  63. //   
  64. //   DoModal   override   copied   mostly   from   MFC,   with   modification   to   use   
  65. //   m_ofnEx   instead   of   m_ofn.   
  66. //   
  67. int   CFileDialogEx::DoModal()   
  68. {   
  69.     ASSERT_VALID(this);   
  70.     ASSERT(m_ofn.Flags   &   OFN_ENABLEHOOK);   
  71.     ASSERT(m_ofn.lpfnHook   !=   NULL);   //   can   still   be   a   user   hook   
  72.     
  73.     //   zero   out   the   file   buffer   for   consistent   parsing   later   
  74.     ASSERT(AfxIsValidAddress(m_ofn.lpstrFile,   m_ofn.nMaxFile));   
  75.     DWORD   nOffset   =   lstrlen(m_ofn.lpstrFile)+1;   
  76.     ASSERT(nOffset   <=   m_ofn.nMaxFile);   
  77.     memset(m_ofn.lpstrFile+nOffset,   0,   (m_ofn.nMaxFile-nOffset)*sizeof(TCHAR));   
  78.     
  79.     //   WINBUG:   This   is   a   special   case   for   the   file   open/save   dialog,   
  80.     //     which   sometimes   pumps   while   it   is   coming   up   but   before   it   has   
  81.     //     disabled   the   main   window.   
  82.     HWND   hWndFocus   =   ::GetFocus();   
  83.     BOOL   bEnableParent   =   FALSE;   
  84.     m_ofn.hwndOwner   =   PreModal();   
  85.     AfxUnhookWindowCreate();   
  86.     if   (m_ofn.hwndOwner   !=   NULL   &&   ::IsWindowEnabled(m_ofn.hwndOwner))   
  87.     {   
  88.         bEnableParent   =   TRUE;   
  89.         ::EnableWindow(m_ofn.hwndOwner,   FALSE);   
  90.     }   
  91.     
  92.     _AFX_THREAD_STATE*   pThreadState   =   AfxGetThreadState();   
  93.     ASSERT(pThreadState->m_pAlternateWndInit   ==   NULL);   
  94.     
  95.     if   (m_ofn.Flags   &   OFN_EXPLORER)   
  96.         pThreadState->m_pAlternateWndInit   =   this;   
  97.     else   
  98.         AfxHookWindowCreate(this);   
  99.     
  100.     memset(&m_ofnEx,   0,   sizeof(m_ofnEx));   
  101.     memcpy(&m_ofnEx,   &m_ofn,   sizeof(m_ofn));   
  102.     if   (IsWin2000())   
  103.         m_ofnEx.lStructSize   =   sizeof(m_ofnEx);   
  104.     
  105.     int   nResult;   
  106.     if   (m_bOpenFileDialog)   
  107.         nResult   =   ::GetOpenFileName((OPENFILENAME*)&m_ofnEx);   
  108.     else   
  109.         nResult   =   ::GetSaveFileName((OPENFILENAME*)&m_ofnEx);   
  110.     
  111.     memcpy(&m_ofn,   &m_ofnEx,   sizeof(m_ofn));   
  112.     m_ofn.lStructSize   =   sizeof(m_ofn);   
  113.     
  114.     if   (nResult)   
  115.         ASSERT(pThreadState->m_pAlternateWndInit   ==   NULL);   
  116.     pThreadState->m_pAlternateWndInit   =   NULL;   
  117.     
  118.     //   WINBUG:   Second   part   of   special   case   for   file   open/save   dialog.   
  119.     if   (bEnableParent)   
  120.         ::EnableWindow(m_ofnEx.hwndOwner,   TRUE);   
  121.     if   (::IsWindow(hWndFocus))   
  122.         ::SetFocus(hWndFocus);   
  123.     
  124.     PostModal();   
  125.     return   nResult   ?   nResult   :   IDCANCEL;   
  126. }   
  127. //   
  128. //   When   the   open   dialog   sends   a   notification,   copy   m_ofnEx   to   m_ofn   in   
  129. //   case   handler   function   is   expecting   updated   information   in   the   
  130. //   OPENFILENAME   struct.   
  131. //   
  132. BOOL   CFileDialogEx::OnNotify(WPARAM   wParam,   LPARAM   lParam,   LRESULT*   pResult)   
  133. {   
  134.     memcpy(&m_ofn,   &m_ofnEx,   sizeof(m_ofn));   
  135.     m_ofn.lStructSize   =   sizeof(m_ofn);   
  136.     
  137.     return   CFileDialog::OnNotify(   wParam,   lParam,   pResult);   
  138. }   
  139.    
  140. //   The   following   functions   are   provided   for   testing   purposes,   to   
  141. //   demonstrate   that   they   in   fact   called;   ie,   that   MFC's   internal   dialog   
  142. //   proc   is   hooked   up   properly.   Delete   them   if   you   like.   
  143. //   
  144. BOOL   CFileDialogEx::OnFileNameOK()   
  145. {   
  146.     TRACE(_T("CFileDialogEx::OnFileNameOK/n"));   
  147.     return   CFileDialog::OnFileNameOK();   
  148. }   
  149. void   CFileDialogEx::OnInitDone()   
  150. {   
  151.     TRACE(_T("CFileDialogEx::OnInitDone/n"));   
  152.     CFileDialog::OnInitDone();   
  153. }   
  154. void   CFileDialogEx::OnFileNameChange()   
  155. {   
  156.     TRACE(_T("CFileDialogEx::OnFileNameChange/n"));   
  157.     CFileDialog::OnFileNameChange();   
  158. }   
  159. void   CFileDialogEx::OnFolderChange()   
  160. {   
  161.     TRACE(_T("CFileDialogEx::OnFolderChange/n"));   
  162.     CFileDialog::OnFolderChange();   
  163. }   
  164. void   CFileDialogEx::OnTypeChange()   
  165. {   
  166.     TRACE(_T("OnTypeChange(),   index   =   %d/n"),   m_ofn.nFilterIndex);   
  167.     CFileDialog::OnTypeChange();   
  168. }   

    然后直接调用CFileDialogEx类即可(VC6 SP6 + WinXP测试通过):

  1. CFileDialogEx d(TRUE);
  2. d.DoModal();

   本文写作过程中查阅了大量资料,向这些同行们表示敬意和感谢!最后,骂一句CSDN的Programmer,MD,贴两张图片都让我累死。FK。

 

===================================

非注明转载的文章和blog在未特殊声明情况下一般为本人原创或整理,
原创文章版权归沙漠孤狐(lonefox)所有;转载文章版权归原作者所有;

http://blog.csdn.net/boythl

欢迎转载,但请注明出处,保留作者和版权信息。

===================================

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
VC6界面类编程小实例\A Drag and Drop List Control.doc ...................\MFC窗口位置管理详细分析及实例.doc ...................\Toolbar制作菜单条过程详解.doc ...................\VC++6.0定制窗口的方法.doc ...................\VC++中MFC窗口对象的清除.doc ...................\VC++任务栏提示区图标的实现.doc ...................\VC++动态加入和删除菜单的方法.doc ...................\VC++环境下浮动工具条的编程.doc ...................\VC++环境下菜单和工具栏的动态修改技术.doc ...................\VC中如何捕获和释放鼠标.doc ...................\VC控件 TreeCtrl 与 ListCtrl 演示.doc ...................\VC界面编程总结.doc ...................\VC编程中如何在界面上实现3D文字.doc ...................\VC编程实现IE风格的界面.doc ...................\VC编程实现IE风格的界面之叙述.doc ...................\VC设计分割视图通用创建框架.doc ...................\VC通用控件编程之CImageList控件.doc ...................\Visual C++中位图按钮的新颖设计.doc ...................\Visual C++中实现对图像数据的读取显示.doc ...................\Visual C++中的图形特技.doc ...................\Visual C++模态对话框消息处理机制的分析.doc ...................\Visual C++窗体设计技巧集.doc ...................\Visual C++窗口标题改变的几种方法.doc ...................\Windows 界面设计:拉帘按钮设计.doc ...................\XListBox-自画条目背景和文字颜色的listbox控件.doc ...................\XP风格控件界面库.doc ...................\一个功能强大的MFC界面处理扩展库:CJ60Lib.doc ...................\一个屏幕捕捉的例子.doc ...................\一段使窗口透明的代码(仅适用于2000).doc ...................\一种漂亮的自绘菜单.doc ...................\为CListBox加上智能水平滚动条.doc ...................\为列表控件添加水平滚动条.doc ...................\为对话框程序添加工具条和状态栏.doc ...................\从资源中加载皮肤, 使用免费界面库 AppFace For VC 0.2 美化您的软件.doc ...................\位图文件读写综述.doc ...................\使用CRectTracker类进行对象动态定位.doc ...................\使用CTabCtrl控件实现属性页功能.doc ...................\使用测试优先方法开发用户界面.doc ...................\关于内存DC绘图防止屏幕闪烁说明.doc ...................\创建有个性的对话框之MFC篇.doc ...................\利用VC编程在界面上实现3D文字.doc ...................\利用钩子实现菜单阴影效果.doc ...................\制作 MSN、QQ 的消息提示窗口.doc ...................\单文档与多视的实现方法.doc ...................\图像平滑滚动效果的VC实现.doc ...................\在(CListView)列表视图中添加右键菜单.doc ...................\在ATL Browser Helper对象中使用WTL TreeView.doc ...................\在SDI MDI程序的工具条上加入漂亮的标题头.doc ...................\在VC++6.0开发中实现全屏显示.doc ...................\在VC下显示JPEG、GIF格式图像的一种简便方法.doc ...................\在VC中用CMenuXP使应用程序拥有Office XP风格的界面.doc ...................\在VC中透明浮动按键的实现.doc ...................\在Windows95,98中实现苹果窗口界面.doc ...................\在单文档中添加系统菜单项.doc ...................\在单文档程序中动态切换多个窗体.doc ...................\在对话框上加超链接.doc ...................\在类VC的界面实现中加入目录树.doc ...................\在视图中同步显示鼠标的位置.doc ...................\如何创建一个不规则形状的窗口.doc ...................\如何创建无模式对话框.doc ...................\如何创建有模式对话框.doc ...................\如何制作弹出式菜单.doc ...................\如何在VC中改变控件的背景色.doc ...................\如何在状态条中加入图像.doc ...................\如何模拟《WORD》的窗口形式.doc ...................\如何编写类似于Word97的工具栏.doc ...................\如何隐藏显示在任务栏中的对话框程序.doc ...................\实现带阴影弹出的窗口.doc ...................\实现真正的Windows屏幕保护程序.doc ...................\对CXPStyleButtonST的改造.doc ...................\对话框隐藏的几种方法.doc ...................\带有菜单的EDIT控件实现.doc ...................\平面、带图片的按钮.doc ...................\扩展COleDropTarget类来支持任意窗口拖放.doc ...................\拖拉机客户端任务书.doc ...................\数据库开发之窗体编程.doc ...................\文档与视图的建立和关联.doc ...................\无闪烁刷屏技术的实现.doc ...................\显示作为窗口或对话框背景的位图.doc ...................\最简单的界面增强库EasySkin.doc ...................\树视控件在多文档中的使用.doc ...................\根据文本串的长度改变窗口的大小.doc ...................\用MFC对话框做无闪烁图片重绘.doc ...................\用SDK实现分隔条.doc ...................\用VC++制作有滚动字幕效果的软件封面.doc ...................\用VC设计托盘图标程序.doc ...................\用Visual C++实现带阴影弹出窗口的技术.doc ...................\用户界面设计的技巧与技术.doc ...................\百叶窗式面板组.doc ...................\窗口类的诞生.doc ...................\类似Vc和Outlook的界面.doc ...................\编程打开特殊的系统窗口.doc ...................\自绘菜单的实现.doc ...................\自绘边框窗口.doc ...................\让对话框显示背景图.doc ...................\谈VC++中的Progress控件的使用.doc

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值