MFC技术系列(三)--对话框(2)

 接上节, 对话框(一)

1.1           对话框的创建

对话框和普通窗体最大的区别在于它使用了资源来描述其界面特征。这里的资源编译后被存放在了exe或者dll的“某个位置”,类似的资源还有许多,比如:Icon, Menu, Bitmap, Accelerator, String等。这些资源都有自己的标识,对话框资源的标识为RT_DIALOG。通过下面的方法,可以在编译后的模块中获得它,注意最后需要释放该资源:

     LPCDLGTEMPLATE lpDialogTemplate = NULL;

     HGLOBAL hDialogTemplate = NULL;

     HINSTANCE hInst = AfxFindResourceHandle(lpszTemplateName, RT_DIALOG);

     HRSRC hResource = ::FindResource(hInst, lpszTemplateName, RT_DIALOG);

     hDialogTemplate = LoadResource(hInst, hResource);

     if (hDialogTemplate != NULL)

         lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate);

     ASSERT(lpDialogTemplate != NULL);

    

     //actual do something with the use of the resource handle

 

     // free resource

     UnlockResource(hDialogTemplate);

     FreeResource(hDialogTemplate);

 

围绕上述基本步骤,CDialog类中有许多创建对话框的方法,最终是调用了CreateDlgIndirect API方法。值得注意的是,该方法将不会产生WM_CREATE消息。对话框创建时的消息序列可以参看《窗口消息》一文。

       对对话框而言,通常最先接触的消息就是WM_INITDIALOG。顾名思义,响应它进行初始化,此时,所有控件都已经创建出来。对该消息的默认响应由CDialog类的OnInitDialog虚方法完成。该方法在AfxDlgProc中被调用。AfxDlgProc做为参数,在CreateDlgIndirect API中传入,用来接收发送到对话框的消息。AfxDlgProc方法中,只处理了WM_INITDIALOG消息。所有消息都会经过窗口的WndProcWM_INITDIALOG也不例外。CDialog中使用HandleInitDialog方法响应该消息,并在其中调用CWndDefault方法,实际上就是调用DefWindowProc来处理,而该方法调用了CallWindowProc API(该方法用来处理Subclass 窗口过程未处理的消息,即:使用subclass前的窗口函数来处理,MFC中被称为Super Wnd Proc CWnd中使用m_pfnSuper成员表示),这个super WndProc即为AfxDlgProc

       在《窗口消息》的“MFC消息分发”一节中,讲到消息是如何从消息泵中出来,并在MFC的窗体对象间传递的。其中,AfxCallWndProc是主要的方法之一,也就是在该方法中,消息的目标窗口对象的WndProc方法被调用。同时,我们也注意到,在该方法之前和之后,分别有一个针对WM_INITDIALOG的处理,即:_AfxPreInitDialog_AfxPostInitDialog。它们主要是用来让对话框自动居中的。对话框的风格DS_CENTER, DS_CENTERMOUSE都是表示居中。另外,对话框资源编辑属性中的X PosY Pos可指定对话框左上角的位置。

1.2           对话框的PreTranslateMessage

在该方法中,分为下面的步骤:

1.       调用基类(CWnd)的PreTranslateMessage方法

2.       如果未处理,判断是否为Shift + F1的帮助模式,如果是,那么返回FALSE,表示还需要消息还将进一步处理

3.       如果焦点在一个多行的CEdit控件上,且用户按下了ESC键,那么如果没有Cancel按钮,或者该按钮被Disable了,那么显示发送一个Cancel消息到本对话框,以便能关闭该对话框

4.       进入PreTranslateInput方法。该方法只处理键盘和鼠标消息,且将消息传递给IsDialogMessage方法。这是对话框中处理键盘和鼠标消息的入口。

1.3           DoDataExchangeUpdateData

DoDataExchangeCWnd提供的虚方法,CDialog类实现了它。该方法用来将控件和成员变量绑定,之后,代码中使用UpdateData方法来进行正向和反向的转换。

除此之外,为了方便绑定,MFC提供了许多的DDX前缀的宏(X表示Exchange),比如:DDX_Text, DDX_Check, DDX_Radio, DDX_Control等。它们的定义位于afxdd_.h中。

对于控件数值的校验,MFC提供了DDV前缀的宏。(V表示Validation

DDX_Control往往用来在对话框中定义某个控件对象,可以是标准的,也可以是派生的。该宏主要完成了一个subclass的过程(调用SubclassWindow)。CWnd类也提供了SubclassDlgItem方法,控件可以使用它来完成subclass。我们经常可以在PreSubclassWindow虚方法中来完成这些任务。当然在OnInitDialog中也可以。

1.4           IsDialogMessageWM_GETDLGCODE消息

该方法首先判断一个消息是否是对话框消息,如果是,那么将处理它,即:将其转换成相应的消息,然后将其派发到窗口。这里主要是处理键盘消息。比较典型的有两种键盘操作:TAB键和Down/Up键,它们被用来在对话框的控件之间进行导航。该方法将这些键盘消息转换成相应的控件消息,并发送到该对应控件。

该方法在转换消息时,将发送WM_GETDLGCODE消息,询问控件的处理类型。系统提供了如下处理代码,控件可以重载OnGetDlgCode方法,返回需要的类型:

Value

Meaning

DLGC_BUTTON

Button.

DLGC_DEFPUSHBUTTON

Default push button.

DLGC_HASSETSEL

EM_SETSEL messages.

DLGC_RADIOBUTTON

Radio button.

DLGC_STATIC

Static control.

DLGC_UNDEFPUSHBUTTON

Non-default push button.

DLGC_WANTALLKEYS

All keyboard input.

DLGC_WANTARROWS

Direction keys.

DLGC_WANTCHARS

WM_CHAR messages.

DLGC_WANTMESSAGE

All keyboard input (the application passes this message in the MSG structure to the control).

DLGC_WANTTAB

TAB key.

      

       值得注意的是,该方法并不只适用于对话框,它适用于所有包含控件的窗口。

1.5           对话框的消息路由方法OnCmdMsg

基本步骤如下,直到下面有一个地方处理消息:

1.       调用基类CWndOnCmdMsg方法

2.       调用父窗口的OnCmdMsg方法

3.       调用线程对象(CWinThread)的OnCmdMsg方法

关于该虚方法的详细解释,请参见《窗口消息》中的“MFC的消息分发”一节。

 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值