12.对话框和对话框类CDialog(4)

2019-02-15 22:03

if (afxTraceFlags & traceCmdRouting) TRACE1(\window.\\n\#endif

ASSERT(pOwner != this);

if (pOwner->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE; }

// 最后,给当前线程对象处理

CWinThread* pThread = AfxGetThread(); if (pThread != NULL) {

#ifdef _DEBUG

if (afxTraceFlags & traceCmdRouting)

TRACE1(\nID); #endif

if (pThread->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE; }

#ifdef _DEBUG

if (afxTraceFlags & traceCmdRouting) {

TRACE2(\dialog.\\n\

GetRuntimeClass()->m_lpszClassName); } #endif return FALSE; }

从上述实现可以看出,CDialog处理命令消息遵循如下顺序:

对话框自身→父窗口→线程对象

例如,模式对话框产生的WM_ENTERIDLE消息就发送给父窗口处理。

从实现中还看到,MFC根据TRACE过滤标识

afxTraceFlags的值,把有关命令消息的派发显示到调试窗口。

CDialog::OnCmdMsg不仅适用于模式对话框,也适用于无模式对话框。

5. 消息预处理和Dialog消息

另外,对话框窗口的消息处理还有一个特点,就是增加了对Dialog消息的处理,如同在介

绍::IsDialogMessage函数时所述。如果是Dialog消息,MFC框架将不会让它进入下一步的消息循环。为此,MFC覆盖了CDialog的虚拟函数

PreTranslateMessage,该函数的实现如下: BOOL CDialog::PreTranslateMessage(MSG* pMsg) {

// 用于无模式或者模式对话框的处理 ASSERT(m_hWnd != NULL); //过滤tooltip messages

if (CWnd::PreTranslateMessage(pMsg)) return TRUE;

//在Shift+F1帮助模式下,不转换Dialog messages CFrameWnd* pFrameWnd = GetTopLevelFrame(); if (pFrameWnd != NULL && pFrameWnd->m_bHelpMode) return FALSE;

//处理Escape键按下的消息

if (pMsg->message == WM_KEYDOWN &&

(pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_CANCEL) &&

(::GetWindowLong(pMsg->hwnd, GWL_STYLE) & ES_MULTILINE) &&

_AfxCompareClassName(pMsg->hwnd, _T(\{

HWND hItem = ::GetDlgItem(m_hWnd, IDCANCEL); if (hItem == NULL || ::IsWindowEnabled(hItem)) {

SendMessage(WM_COMMAND, IDCANCEL, 0); return TRUE; } }

// 过滤来自控制该对话框子窗口的送给该对话框的Dialog消息

return PreTranslateInput(pMsg);

}

从其实现可以看出,如果是Tooltip消息或者Dialog消息,这些消息将在PreTranslateMessage中被处理,不会进入消息发送的处理。

PreTranslateInput是CWnd的成员函数,它调用::IsDialogMessage函数来处理Dialog消息。 PreTranslateMessage的实现不仅用于模式对话框,而且用于无模式对话框。 6. 模式对话框的消息循环

从DoModal的实现可以看出,DoModal调用

CreateDlgIndirect创建的是无模式对话框,MFC如何来接管和控制应用程序的消息队列,实现一个模式对话框的功能呢?

CDialog调用了RunModalLoop来实现模式窗口的消息循环。RunModalLoop是CWnd的成员函数,它和相关函数的实现如下:

int CWnd::RunModalLoop(DWORD dwFlags) {

ASSERT(::IsWindow(m_hWnd)); //窗口必须已经创建且不在模式状态 ASSERT(!(m_nFlags & WF_MODALLOOP)); // 以下变量用于Idle处理 BOOL bIdle = TRUE; LONG lIdleCount = 0;

BOOL bShowIdle = (dwFlags & MLF_SHOWONIDLE) && !(GetStyle() & WS_VISIBLE);

HWND hWndParent = ::GetParent(m_hWnd); m_nFlags |= (WF_MODALLOOP|WF_CONTINUEMODAL); MSG* pMsg = &AfxGetThread()->m_msgCur;

//获取和派发消息直到模式状态结束 for (;;) {

ASSERT(ContinueModal());

//第一阶段,判断是否可以进行Idle处理

while (bIdle &&!::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE)) {

ASSERT(ContinueModal());

//必要的话,当Idle时显示对话框窗口 if (bShowIdle) {

ShowWindow(SW_SHOWNORMAL); UpdateWindow(); bShowIdle = FALSE; }

// 进行Idle处理

//必要的话发送WM_ENTERIDLE消息给父窗口

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

::SendMessage(hWndParent, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)m_hWnd); }


12.对话框和对话框类CDialog(4).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:开放性试题测试

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: