对话框和对话框类CDialogWord文件下载.docx

上传人:b****8 文档编号:22272028 上传时间:2023-02-03 格式:DOCX 页数:40 大小:33.83KB
下载 相关 举报
对话框和对话框类CDialogWord文件下载.docx_第1页
第1页 / 共40页
对话框和对话框类CDialogWord文件下载.docx_第2页
第2页 / 共40页
对话框和对话框类CDialogWord文件下载.docx_第3页
第3页 / 共40页
对话框和对话框类CDialogWord文件下载.docx_第4页
第4页 / 共40页
对话框和对话框类CDialogWord文件下载.docx_第5页
第5页 / 共40页
点击查看更多>>
下载资源
资源描述

对话框和对话框类CDialogWord文件下载.docx

《对话框和对话框类CDialogWord文件下载.docx》由会员分享,可在线阅读,更多相关《对话框和对话框类CDialogWord文件下载.docx(40页珍藏版)》请在冰豆网上搜索。

对话框和对话框类CDialogWord文件下载.docx

1无模式对话框

一个无模式对话框是一个有系统菜单、标题栏、边线等的弹出式窗口。

在创建对话框模板时指定WS_POPUP、WS_CAPTION、WS_BORDER和WS_SYSMENU风格。

如果没有指定WS_VISIBLE风格,无模式对话框不会自动地显示出来。

一个无模式对话框既不会禁止所属窗口,也不会给它发送消息。

当创建一个模式对话框时,Windows使它成为活动窗口,但用户或者程序可以随时改变和设置活动窗口。

如果对话框失去激活,那么即使所属窗口是活动的,在Z轴顺序上,它仍然在所属窗口之上。

应用程序负责获取和派发输入消息给对话框。

大部分应用程序使用主消息循环来处理,但是为了用户可以使用键盘在控制窗口之间移动或者选择控制窗口,应用程序应该调用:

IsDialogMessage函数。

这里,顺便解释:

虽然该函数是为无模式对话框设计的,但是任何包含了控制子窗口的窗口都可以调用它,用来实现类似于对话框的键盘选择操作。

当:

IsDialogMessage处理一个消息时,它检查键盘消息并把它们转换成相应对话框的选择命令。

例如,当Tab键被压下时,下一个或下一组控制被选中,当DownArrow键按下后,一组控制中的下一个控制被选择。

IsDialogMessage完成了所有必要的消息转换和消息派发,所以该函数处理的消息一定不要传递给TranslateMessage和DispatchMessage处理。

一个无模式对话框不能像模式对话框那样返回一个值给应用程序。

但是对话框过程可以使用:

SendMessage给所属窗口传递信息。

在应用程序结束之前,它必须销毁所有的无模式对话框。

使用:

DestroyWindow销毁一个无模式对话框,不是使用:

EndDiaLog。

一般来说,对话框过程响应用户输入,如用户选择了“取消”按钮,则调用:

DestroyWindow;

如果用户没有有关动作,则应用程序必须调用:

DestroyWindow。

对话框的MFC实现

在MFC中,对话框窗口的功能主要由CWnd和CDialog两个类实现。

CDialog的设计和实现

MFC通过CDialog来封装对话框的功能。

CDialog从CWnd继承了窗口类的功能(包括CWnd实现的有关功能),并添加了新的成员变量和函数来处理对话框。

CDialog的成员变量

CDialog的成员变量有:

protected:

UINTm_nIDHelp;

//HelpID(0fornone,seeHID_BASE_RESOURCE)

LPCTSTRm_lpszTemplateName;

//nameorMAKEINTRESOURCE

HGLOBALm_hDialogTemplate;

//indirect(m_lpDialogTemplate==NULL)

//indirectif(m_lpszTemplateName==NULL)

LPCDLGTEMPLATEm_lpDialogTemplate;

void*m_lpDialogInit;

//DLGINITresourcedata

CWnd*m_pParentWnd;

//parent/ownerwindow

HWNDm_hWndTop;

//toplevelparentwindow(maybedisabled)

成员变量保存了创建对话框的模板资源、对话框父窗口对象、顶层窗口句柄等信息。

三个关于模板资源的成员变量m_lpszTemplateName、m_hDialogTemplate、m_lpDialogTemplate对应了三种模板资源,但在创建对话框时,只要一个模板资源就可以了,可以使用其中的任意一类。

1CDialog的成员函数:

2构造函数:

CDialog(LPCTSTRlpszTemplateName,CWnd*pParentWnd=NULL);

CDialog(UINTnIDTemplate,CWnd*pParentWnd=NULL);

CDialog();

CDialog重载了三个构造函数。

其中,第三个是缺省构造函数;

第一个和第二个构造函数从指定的对话框模板资源创建,pParentWnd指定了父窗口或所属窗口,若空则设置父窗口为应用程序主窗口。

3初始化函数

BOOLCreate(LPCTSTRlpszTemplateName,CWnd*pParentWnd=NULL);

BOOLCreate(UINTnIDTemplate,CWnd*pParentWnd=NULL);

BOOLCreateIndirect(LPCDLGTEMPLATElpDialogTemplate,CWnd*pParentWnd=NULL);

BOOLCreateIndirect(HGLOBALhDialogTemplate,CWnd*pParentWnd=NULL);

BOOLInitModalIndirect(LPCDLGTEMPLATElpDialogTemplate,CWnd*pParentWnd=NULL);

BOOLInitModalIndirect(HGLOBALhDialogTemplate,CWnd*pParentWnd=NULL);

Create用来根据模板创建无模式对话框;

CreateInDirect用来根据内存中的模板创建无模式对话框;

InitModalIndirect用来根据内存中的模板创建模式对话框。

它们都提供了两个重载版本。

4对话框操作函数

voidMapDialogRect(LPRECTlpRect)const;

voidNextDlgCtrl()const;

voidPrevDlgCtrl()const;

voidGotoDlgCtrl(CWnd*pWndCtrl);

voidSetDefID(UINTnID);

voidSetHelpID(UINTnIDR);

voidEndDialog(intnResult);

5虚拟函数

virtualintDoModal();

virtualBOOLOnInitDialog();

virtualvoidOnSetFont(CFont*pFont);

virtualvoidOnOK();

virtualvoidOnCancel();

MFC模式对话框的实现

从前面的介绍可以知道,Win32SDK编程下的模式对话框使用了Windows提供给对话框窗口的窗口过程和自己的对话框过程,对话框过程将被窗口过程调用。

但在MFC下,所有的窗口类都使用了同一个窗口过程,CDialog也不例外。

CDialog对象在创建Windows对话框时,采用了类似于CWnd的创建函数过程,采用子类化的手段将Windows提供给对话框的窗口过程取代为AfxWndProc或者AfxBaseWndProc,同时提供了对话框过程AfxDlgProc。

那么,这些“过程”是如何实现或者协调的呢?

下文将予以分析。

MFC对话框过程

MFC对话框过程AfxDlgProc的原型和实现如下:

BOOLCALLBACKAfxDlgProc(HWNDhWnd,

UINTmessage,PARAM,LPARAM)

{

if(message==WM_INITDIALOG)

//处理WM_INITDIALOG消息

CDialog*pDlg=DYNAMIC_DOWNCAST(CDialog,

CWnd:

FromHandlePermanent(hWnd));

if(pDlg!

=NULL)

returnpDlg->

OnInitDialog();

else

return1;

}

return0;

由上可以看出,MFC的对话框函数AfxDlgProc仅处理消息WM_INITDIALOG,其他都留给对话框窗口过程处理。

因此,它不同于SDK编程的对话框过程。

程序员在SDK的对话框过程处理消息和事件,实现自己的对话框功能。

AfxDlgProc处理WM_INITDIALOG消息时调用虚拟函数OnInitDialog,给程序员一个机会处理对话框的初始化。

模式对话框窗口过程

本小节讨论对话框的窗口过程。

AfxWndProc是所有的MFC窗口类使用的窗口过程,它取代了模式对话框原来的窗口过程(Windows提供),那么,MFC如何完成Win32下对话框窗口的功能呢?

考查模式对话框的创建过程。

CDialog:

DoModal用来创建模式对话框窗口并执行有关任务,和DoModal相关的是MFC内部使用的成员函数CDialog:

PreModal和CDialog:

PostModal。

下面分别讨论它们的实现。

HWNDCDialog:

PreModal()

//cannotcallDoModalonadialogalreadyconstructedasmodeless

ASSERT(m_hWnd==NULL);

//allowOLEserverstodisablethemselves

AfxGetApp()->

EnableModeless(FALSE);

//得到父窗口

CWnd*pWnd=CWnd:

GetSafeOwner(m_pParentWnd,&

m_hWndTop);

//如同CWnd处理其他窗口的创建,设置一个窗口创建HOOK

AfxHookWindowCreate(this);

//返回父窗口的句柄

returnpWnd->

GetSafeHwnd();

voidCDialog:

PostModal()

//取消窗口创建前链接的HOOK

AfxUnhookWindowCreate();

//justincase

//MFC对话框对象和对应的Windows对话框窗口分离

Detach();

//m_hWndTop是当前对话框的父窗口或所属窗口,则恢复它

if(:

IsWindow(m_hWndTop))

EnableWindow(m_hWndTop,TRUE);

m_hWndTop=NULL;

EnableModeless(TRUE);

intCDialog:

DoModal()

//canbeconstructedwitharesourcetemplateorInitModalIndirect

ASSERT(m_lpszTemplateName!

=NULL||

m_hDialogTemplate!

=NULL||m_lpDialogTemplate!

=NULL);

//加载对话框资源

LPCDLGTEMPLATElpDialogTemplate=m_lpDialogTemplate;

HGLOBALhDialogTemplate=m_hDialogTemplate;

HINSTANCEhInst=AfxGetResourceHandle();

//查找资源(见9.5.2节),找到了就加载它

if(m_lpszTemplateName!

hInst=AfxFindResourceHandle(m_lpszTemplateName,RT_DIALOG);

HRSRChResource=

FindResource(hInst,m_lpszTemplateName,RT_DIALOG);

hDialogTemplate=LoadResource(hInst,hResource);

//锁定加载的资源

if(hDialogTemplate!

lpDialogTemplate=(LPCDLGTEMPLATE)LockResource(hDialogTemplate);

//return-1incaseoffailuretoloadthedialogtemplateresource

if(lpDialogTemplate==NULL)

return-1;

//创建对话框前禁止父窗口,为此要调用PreModal得到父窗口句柄

HWNDhWndParent=PreModal();

CWnd*pParentWnd=CWnd:

FromHandle(hWndParent);

BOOLbEnableParent=FALSE;

if(hWndParent!

=NULL&

&

:

IsWindowEnabled(hWndParent))

EnableWindow(hWndParent,FALSE);

bEnableParent=TRUE;

//创建对话框,注意是无模式对话框

TRY

//链接一个HOOK到HOOK链以处理窗口创建,

//如同4.4.1节描述的CWnd类窗口创建一样

//CreateDlgIndirect间接调用:

CreateDlgIndirect,

//最终调用了:

CreateWindowEX来创建对话框窗口。

//HOOK过程_AfxCbtFilterHook用子类化的方法

//取代原来的窗口过程为AfxWndProc。

if(CreateDlgIndirect(lpDialogTemplate,CWnd:

FromHandle(hWndParent),hInst))

if(m_nFlags&

WF_CONTINUEMODAL)

//entermodalloop

DWORDdwFlags=MLF_SHOWONIDLE;

//RunModalLoop接管整个应用程序的消息处理

if(GetStyle()&

DS_NOIDLEMSG)

dwFlags|=MLF_NOIDLEMSG;

VERIFY(RunModalLoop(dwFlags)==m_nModalResult);

//hidethewindowbeforeenablingtheparent,etc.

if(m_hWnd!

SetWindowPos(NULL,0,0,0,0,SWP_HIDEWINDOW|

SWP_NOSIZE|SWP_NOMOVE|

SWP_NOACTIVATE|SWP_NOZORDER);

CATCH_ALL(e)

DELETE_EXCEPTION(e);

m_nModalResult=-1;

END_CATCH_ALL

//Enable并且激活父窗口

if(bEnableParent)

EnableWindow(hWndParent,TRUE);

GetActiveWindow()==m_hWnd)

SetActiveWindow(hWndParent);

//:

EndDialog仅仅关闭了窗口,现在销毁窗口

DestroyWindow();

PostModal();

//必要的话,解锁/释放资源

=NULL||m_hDialogTemplate!

UnlockResource(hDialogTemplate);

FreeResource(hDialogTemplate);

returnm_nModalResult;

从DoModal的实现可以看出:

它首先Disable对话框窗口的父窗口;

然后使用:

CreateIndrectDialog创建对话框窗口,使用子类化的方法用AfxWndProc(或者AfxBaseProc)替换了原来的窗口过程,并把原来的窗口过程保存在CWnd的成员变量m_pfnSuper中。

原来的窗口过程就是:

DialogBox等创建对话框窗口时指定的,是Windows内部提供的对话框“窗口类”的窗口过程。

取代(Subclass)原来“窗口类”的窗口过程的方法如同4.4.1节描述的CWnd:

Create。

在:

CreateIndirectDialog创建对话框窗口后,会发送WM_INITDIALOG消息给对话框的对话框过程(必要的话,还有WM_SETFONT消息)。

但是MFC取代了原来的对话框窗口过程,这两个消息如何送给对话框过程呢?

处理方法如下节所描述。

使用原对话框窗口过程作消息的缺省处理

对话框的消息处理过程和其他窗口并没有什么不同。

这里主要分析的是如何把一些消息传递给对话框原窗口过程处理。

下面,通过解释MFC对WM_INITDIALOG消息的处理来解释MFC窗口过程和原对话框窗口过程的关系及其协调作用。

MFC提供了WM_INITDIALOG消息的处理函数CDialog:

HandleInitDialog,WM_INITDIALOG消息按照标准Windows的处理送给HandleInitDialog处理。

HandleInitDialog调用缺省处理过程Default,导致CWnd的Default函数被调用。

Default的实现如下:

LRESULTCWnd:

Default()

//callDefWindowProcwiththelastmessage

_AFX_THREAD_STATE*pThreadState=_afxThreadState.GetData();

returnDefWindowProc(pThreadState->

m_lastSentMsg.message,

pThreadState->

m_lastSentMsg.wParam,

m_lastSentMsg.lParam);

顺便指出,从Default的实现可以看出线程状态的一个用途:

它把本线程最新收到和处理的消息记录在成员变量m_lastSentMsg中。

在Default的实现中,CWnd的DefWindowsProc被调用,其实现如下:

DefWindowProc(UINTnMsg,

WPARAMwParam,LPARAMlParam)

//若“窗口超类(SuperClass)”的窗口过程m_pfnSuper非空,则调用它

if(m_pfnSuper!

return:

CallWindowProc(m_pfnSuper,m_hWnd,nMsg,wParam,lParam);

//在MFC中,GetSuperWndProcAddr的作用就是返回m_pfnSuper,为什么还

//要再次调用呢?

因为虽然该函数现在是Obsolete,但原来曾经是有用的。

//果返回非空,就调用该窗口过程进行处理,否则,由Windows进行缺省处理。

WNDPROCpfnWndProc;

if((pfnWndProc=*GetSuperWndProcAddr())==NULL)

DefWindowProc(m_hWnd,nMsg,wParam,lParam);

CallWindowProc(pfnWndProc,m_hWnd,nMsg,wParam,lParam);

综合上述分析,HandleInitDialog最终调用了窗口过程m_pfnSuper,即Windows提供给“对话框窗口类”的窗口过程,于是该窗口过程调用了对话框过程AfxDlgProc,导致虚拟函数OnInitDialog被调用。

顺便提一下,CWnd:

AfxCallWndProc在处理WM_INITDIAL

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1