荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: Peter (小飞侠), 信区: Program
标  题: 用VC++定制通用对话框
发信站: BBS 荔园晨风站 (Thu Jan 21 22:41:50 1999), 转信


    对话框概述
    一个通用对话框是由Windows设计和编写的,用于完成某一特定工
作,比如打开一个文件或选择一种颜色等。MFC提供了管理每一通用对
话框类型的类,这些类概括在下表中。表1
    例如:处理File菜单上Open和Save As命令时使用CFileDialog通
用对话框,而处理Prin和Print Setup命令时则使用CPrintDialog通用
对话框。
    用这些对话框构造用户应用是很方便的,但有时这些通用对话框
的外部特性和行为不能满足用户要求,特别是在对话框上需要增加某
些控件或删除某些控件时尤为突出。本文提供给大家一种方法来定制
通用对话框的外部特性和行为,可用自己的代码与MFC提供的类协同处
理这些对话框,以满足用户的不同要求。一方面由于使用了MFC的通用
对话框类,节省了大量的代码编程工作,提高了开发效率;另一方面,采
用自己的代码协同实现,使对话框的功能可以做到灵活多样。本文以F
ile Open命令为例,来阐述这一方法。
    定制File Open通用对话框
    CFileDialog类封装Windows公共文件对话框。公共文件对话框以
一种与Windows标准一致的方式,提供了实现File Open和File Save A
s对话框(及其他文件选择对话框)的简单方法。
    CFileDialog中有一成员变量m_ofn,它是OPENFILENAME类型的结
构。通常,要使用一个F ileDialog对象,需要首先用CFileDialog的构
造函数创建该对象。在对话框被构造之后,且在用DoModal成员函数显
示对话框之前,应用程序可以通过设置m_ofn结构中的值,来对此对话
框中的控件的值或状态进行初始化。例如:应用程序可将m_ofn的lpsz
Title成员设置为所想要的对话框标题;可将m_ofn的指定该对话框的
创建标志Flags成员设置为其各标志位值的多种组合,以达到一定要求
,其中,设置的Flags中的OFN—ALLOWMULTISELECT标志可允许用户选择
多个文件;设置OFN_HIDEREADONLY标志可隐藏Read Only检查框;设置O
FN_OVERWRITEPROMT标志可做到若所选择的文件已存在,则使Save As
对话框产生一个消息框,使用户确认是否重写该文件;等等。有关此结
构的详细说明,包括它的成员列表,参看Windows SDK文档中OPENILE N
AME的介绍。
    从以上所述看,仅改变m_ofn的值只能做到简单的定制,若要对通
用对话框的外观、通用对话框已有控件进行进一步调整(功能改变或
删除),以及给通用对话框增加新的控制,则以上简单定制方法是做不
到的。笔者将为大家提供一种方法,下面以一例子来介绍。
    本例假定一应用程序要读入某一位图文件,要求对要读入的位图
文件进行预览,具体实现是在File Open通用对话框的基础上增加预显
功能,即每当选中一个位图文件时,就在对话框中显示此文件的位图。
为节省编程工作量,可对Windows提供的File Open通用对话框进行定
制。本例定制对话框采取的方案是直接使用CFileDialog类,设法获取
标准通用对话框资源并对其进行修改,然后编写File Open菜单命令处
理程序和一个钩子函数(HOOK)来处理特殊要求。本例在VC++4.0环境
中创建一个DibPreView项目来实现。
    1.获取并改造通用对话框资源
    在使用VC++自动创建的应用程序中,系统菜单File项中的Open项
的处理是调用了系统由CommDll.DLL提供的标准File Open对话框,要
实现对其定制就必须截获Open项的命令,用自己的代码来处理,以替代
系统提供的缺省处理。要做到这点并不困难,只要用ClassWizard在合
适的对象(比如文档类或视窗类等)中增加对ID_FILE-OPEN控制的处理
,即增加OnFileOpen函数,编写此函数就能实现对Open命令的处理。在
此函数中首先要创建一个CFileDialog类的对象,该对象的外观和行为
均同标准的File Open对话框相同,要改变该对象的外形或删除原对话
框中的某些控件或增加某些控件,都必须首先设法获取该对象所对应
的标准资源,然后,对其进行相应的修改。获取资源的方法有两种:
    方法一:
    在Msdev/Include目录中存有以上几个标准通用对话框的资源,以
FileOpen.Dlg、 FotD lg、FindText.Dlg、Color.Dlg和PrnSetup.Dl
g文件方式存在,这些文件其中的一些常量被定义在本目录中的dlgs.h
中。为了定制该对话框,就要以显式方式引用这些资源,要将它们嵌入
到本应用程序的资源中,然后再修改该对话框的资源。具体步骤如下:
    (1)用VC++4.0自动创建项目DibPreView的全部文件;
    (2)以Text方式打开本项目中的资源文件DibPreView.rc,在此文
件中的Dialog段首行前加上语句:
    #include <FileOpen.dlg>
    (3)将Afxres.h文件从Msdev/Mfc/Include目录中复制到本项目目
录中,并打开新复制的Afxres.h文件,将下面的语句添加到文件行首:
    #include <dlgs.h>
    方法二:
    在VC++安装盘中的Msdev\Sample\Mfc\General\Clipart目录中存
有资源文件Commdlg.c ,此文件含有Color、File、Open(或Save As)
、Find、Font、Print、Print Setup、Replce 几个通用对话框的资
源,为了以显式方式引用这些资源,可利用VC++的资源编辑器,将所需
的通用对话框资源复制到本例项目资源文件中。
    按以上两方法处理完后,在本项目的资源目录列表中的Dialog项
中,出现一标识符为FIE OPENORD的对话框资源,然后利用资源编辑器
对此标准File Open对话框(即FILEOPENORD标识的)进行改造。主要是
在原对话框中增加一大的自画Button,为预显位图之用,定义ID号为I_
view,如下图:
    标准的File Open对话框:
图1
    定制过的File Open对话框:
图2
    注:变动如下:
    (1)边框加长;
    (2)删除"read only"项;
    (3)移动"OK"、"Cancel"、"Help"按钮;
    (4)增加一大自画按钮button1。

    2.编写处理代码
    VC++自动生成的程序框架已为Open命令提供了缺省的处理函数,
为定制该对话框就需重写Open命令的处理函数。用ClassWizard在文
档类中添加一个菜单处理函数OnOpenFile(),具体程序如下:
    void CDibPreViewDoc::OnFileOpen()
    {
    //TODO:Add your command handler code here
    char FileNameString[]="*.dib";
    char FilterString[]="DIB file(*.dib)|*.dib|BMP file(*.bm
p)|*.bmp|All file(. *)|*.*||";
    CFileDialog FileDialog(TRUE,NULL,(LPSTR)FileNameString,O
FN--HIDEREAD|OFN-OE RWRITEPROMPT,(LPSTR)FilterString);
    FileDialog.m-ofn.Flags=OFN—SHOWHELP|OFN—ENABLEHOOK|OFN
—HIDEREADONLY|OFN—ENABLETEMPLATE;
    FileDialog.m-ofn.lpfnHook=(LPOFNHOOKPROC)MakeProcInstanc
e(FileOpenHookProcN ULL);
    FileDialog.m—ofn.lpTemplateName=(LPSTR)MAKEINTRESOURCE(
FILEOPENORD);
    if(FileDialog.DoModal()==IDOK)
    }
    ……
    }
    }
    另外,为了定制CFileDialog的行为,我们定义一个钩子函数FileO
penHookProc()来截获发给CFileDialog的全部消息,并对其进行筛选,
选取自己需要进行处理。对自己不处理的消息或自己处理完后仍要交
给MFC处理的消息,钩子函数返回FALSE;对自己处理完后而不需要F C
处理的消息,钩子函数返回TRUE。由于篇幅所限,仅提供本例程序框架

    BOOL CALLBACK FileOpenHookProc(
    HWND hDlg,
    /*window handle of the dialog box*/
    UINT message,  /*type of message */
    WPARAM wParam, /*message_specific information */
    LPARAM lParam)
    {
    switch(message)
    {
    case WM—INITDIALOG:
    //初始化工作
    ……
    break;
    case WM—COMMAND:
    //判断是否为文件列表框中选择结果发生改变时发出的消息
       if(LOWORD(wParam)==lstl &&HIWORD(wParam)==LBN—SELCHA
NGE)
    /* lstl是文件列表框的ID号*/
    {
    //获取列表框现行的选中项的序号
    int nItem=SendDlgItemMessage(hDlg,lst1,LB—GETCURSEL,(WP
ARAM) 0,(LPARAM) 0
     //获取列表框现行的选中项的字符串的长度
    int tmpLength=SendDlgItemMessage(hDlg,ist1,LB—GETTEXTLE
N,(WPARAM) nItem,(P ARAM) 0);
    //获取列表框现行的选中项的字符串
      ::SendDlgItemMessage(hDlg,lst1,LB—GETTEXT,(WPARAM) nI
tem,(LPARAM) &Filea me);
    FileName[tmpLength]=0;
      //获取增加的Button的窗口句柄
      HWND staticItem=::GetDlgItem(hDlg,IDC—view);
      if(!staticItem)
      MessaageBox(hDlg,"Can not find HWND","Error",MB-OK);
      //要求刷新增加的Button的窗口
      ::InvalidateRect(staticItem,NULL,TRUE);
      ::UpdateWindow(staticItem);
      }
      break;
      case WM—DRAWITEM:
     LPDRAWITEMSTRUC lpdis=(LPDRAWI TEMSTRUCT) lParam;
     HDC hdcMem=lpdis—>hDC;
      //判断是否为要求刷新buttonl窗口而发出的消息
      if(wParam==IDC_view)
      //IDC_view是新增加的buttonl的ID号
      {
      //刷新增加的Buttonl窗口(在buttonl上显示位图)
      ……
      }
    break;
    }
    return(FALSE);
    }

--
※ 来源:.BBS 荔园晨风站 bbs.szu.edu.cn.[FROM: 192.168.1.3]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店