首 页 ┆ 源码下载 ┆ IT学院 ┆ 字体下载 ┆ 模板下载 ┆ 源码发布 ┆ 广告合作 ┆ 网站地图
► 设为首页
► 加入收藏
► 联系我们
源码下载 >> ASP源码 | PHP源码 | ASP.net源码 | JSP源码 | CGI源码 | VC/C++源码 | VB源码 | Delphi源码 | Flash源码
文章学院 >> 网络编程 | 网页设计 | 图形图象 | 数据库 | 服务器 | 网络媒体 | 网络安全 | 操作系统 | 办公软件 | 软件开发 | 黑客知识
字体下载 >> 精制字体 | 非英字体 | 艺术字体 | 著名字体 | 哥特式 | 简单字体 | 手写体 | 节假日 | 图案字体 | 精度像素 | 中文字体
模板下载 >> 企业门户 | 数码网络 | 休闲娱乐 | 影视音乐 | 旅游名胜 | 文化艺术 | 电子商务 | 个性展示 | 登陆导航 | Flash模板
►►您当前的位置:源码园 → IT学院 → 软件开发 → VC编程 → 文章内容

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

作者:佚名  来源:网上收集  发布时间:2007-3-27 10:18:50

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

编译/zxn

本文代码例子

    不久以前,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;   // 尝试调用 GetVersionEx 函数,使用 OSVERSIONINFOEX 结构,   // 它被Windows 2000支持.   //   // 如果调用失败, 尝试使用 OSVERSIONINFO 结构.   ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX));   osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);   if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) )   {      // 如果 OSVERSIONINFOEX 不行, 就用 OSVERSIONINFO.      osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);      if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) )          return FALSE;   }   switch (osvi.dwPlatformId)   {      case VER_PLATFORM_WIN32_NT:         if ( osvi.dwMajorVersion >= 5 )            return TRUE;         break;   }   return FALSE; }

    为了让代码正确运行,CFileDialogEx 还重写了另一个虚函数 OnNotify。当在文件对话框中发生某事件时,Windows发送一个 WM_NOTIFY 消息以及 OPENFILENAME 结构中更新的信息。因为该消息处理函数和其它的MFC代码都希望获悉存储在m_ofn中的信息,而不是m_ofnEx中的信息,OnNotify 截获通知并实现另一拷贝。

BOOL CFileDialogEx::OnNotify(...){    memcpy(&m_ofn, &m_ofnEx, sizeof(m_ofn));    m_ofn.lStructSize = sizeof(m_ofn);    return CFileDialog::OnNotify( wParam, lParam, pResult);}

下面是CFileDialogEx类最终的代码:

FileDialogEx 的头文件和实现文件/////////////////////////////////////////////////////////////// FileDialogEx.h // #pragma once// OPENFILENAME的 Windows 2000 版本.// 新版本多处三个成员.// 从commdlg.h文件中拷贝.struct OPENFILENAMEEX : public OPENFILENAME {   void *        pvReserved;  DWORD         dwReserved;  DWORD         FlagsEx;};//////////////////////////////////////////////////////////////////

[1] [2] [3]  下一页

[] [返回上一页] [打 印]
  • 上一篇文章:VC6中使用CHtmlView在对话框控制中显示HTML文件
  • 下一篇文章:Windows2000新型Open对话框的使用

  • 相关文章:
  • [图文]再谈 Windows 2000 “打开”文件对话框
  • [组图]Windows 文件对话框使用技巧集锦
关于本站 - 网站帮助 - 广告合作 - 下载声明 - 友情连接 - 网站地图 - 源码发布
Copyright © 2003-2009 Ymyasp.Com. All Rights Reserved .
备案序号:粤ICP备07029071号