模态对话框的实现原理

  • 格式:docx
  • 大小:39.49 KB
  • 文档页数:7

下载文档原格式

  / 15
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

MFC 模态对话框的实现原理

1人收藏此文章, 发表于10个月前(2012-09-30 11:20) , 已有471次阅读,共1个评论

1. 模态对话框

在涉及GUI程序开发的过程中,常常有模态对话框以及非模态对话框的概念

模态对话框:在子界面活动期间,父窗口是无法进行消息响应。独占用户输入非模态对话框:各窗口之间不影响

主要区别:非模态对话框与APP共用消息循环,不会独占用户。

模态对话框独占用户输入,其他界面无法响应

在用户层的主要逻辑如下:

TestDlg dlg;

if (dlg.DoModal() == IDOK)

{

//处理完毕后的操作

}

.......//后续处理

在具体实现中,有如下几个步骤:

1. 让父窗口失效EnableWindow(parentWindow, FALSE)

2. 建立模态对话框自己的消息循环(RunModalLoop)

3. 直至接收关闭消息,消息循环终止,并销毁窗口。

INT_PTR CDialog::DoModal()

{

//对话框资源加载

......

//在创建模态窗口之前先让父窗口失效,不响应键盘、鼠标产生的消息

HWND hWndParent = PreModal();

AfxUnhookWindowCreate();

BOOL bEnableParent = FALSE;

if (hWndParent && hWndParent != ::GetDesktopWindow()

&& ::IsWindowEnabled(hWndParent))

{

::EnableWindow(hWndParent, FALSE);

bEnableParent = TRUE;

.......

}

//创建模态窗口,并进行消息循环,若窗口不关闭,则循环不退出

AfxHookWindowCreate(this);

VERIFY(RunModalLoop(dwFlags) == m_nModalResult);

//窗口关闭,销毁窗口

DestroyWindow();

PostModal();

//释放资源,并让父窗口有效

pMainWnd->EnableWindow(TRUE);

//返回

return m_nModalResult;

}

2. 模态窗口中的消息循环

int CWnd::RunModalLoop(DWORD dwFlags)

{

//要检查窗口状态是否是模态窗口

//若状态一直为模态,则一直进行消息循环

for (;;)

{

ASSERT(ContinueModal());

// phase1: check to see if we can do idle work

while (bIdle &&

!::PeekMessage(pMsg, NULL, NULL, NULL,

PM_NOREMOVE))

{

ASSERT(ContinueModal());

// show the dialog when the message queue goes idle

if (bShowIdle)

{

ShowWindow(SW_SHOWNORMAL);

UpdateWindow();

bShowIdle = FALSE;

}

// call OnIdle while in bIdle state

if (!(dwFlags & MLF_NOIDLEMSG) && hWndParent != NULL && lIdleCount == 0)

{

// send WM_ENTERIDLE to the parent

::SendMessage(hWndParent,

WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd);

}

if ((dwFlags & MLF_NOKICKIDLE) ||

!SendMessage(WM_KICKIDLE,

MSGF_DIALOGBOX, lIdleCount++))

{

// stop idle processing next time

bIdle = FALSE;

}

}

//在有消息的情况下取消息处理

do

{

ASSERT(ContinueModal());

// pump message, but quit on WM_QUIT

if (!AfxPumpMessage())

{

AfxPostQuitMessage(0);

return -1;

}

// show the window when certain special messages rec'd

if (bShowIdle &&

(pMsg->message == 0x118 || pMsg->message == WM_SYSKEYDOWN))

{

ShowWindow(SW_SHOWNORMAL);

UpdateWindow();

bShowIdle = FALSE;

}

if (!ContinueModal())