您的位置:首页 > 其它

window程序一个线程中可以有几个消息队列?和几个消息循环

2015-05-04 20:13 627 查看
参看:http://wenku.baidu.com/link?url=Z9UcZPaN0lf9u4MwtkSvt4do3kCPuHISedW3CLyzXsr2uDvhZauc0ziwsYTOK_F2r_ffbnI6myevV7WxaD1WKzD8u1QYTOjh7H86rXdtkQy

在windows中一个线程只有一个消息队列(PostMessage消息队列),非模态对话框的消息在主线程的消息循环中处理,对于模态对话框,其先禁止主窗口,然后自己建立一个消息循环进行消息处理,对话框结束后,停止对话框自己的消息循环,然后enable主窗口。

所以,一个线程中只有一个消息队列(PostMessage消息队列),但是可能存在主线程消息循环外的其他局部消息循环,但是他们不会并行执行。

模态对话框与非模态对话框的内部机制区别:

非模态对话框与APP共用消息循环,不会独占用户 ;模态对话框独占用户输入,其他界面无法响应,有自己的消息循环;

模态对话框的具体实现有以下步骤:

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;
}


模态对话框中的消息循环:

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())
goto ExitModal;
// reset "no idle" state after pumping "normal" message
if (AfxIsIdleMessage(pMsg))
{
bIdle = TRUE;
lIdleCount = 0;
}
}
while (::PeekMessage(pMsg, NULL, NULL, NULL, PM_NOREMOVE));
}

ExitModal:
m_nFlags &= ~(WF_MODALLOOP | WF_CONTINUEMODAL);
return m_nModalResult;
}


线程主消息循环:

//thrdcore.cpp
// main running routine until thread exits
int  CWinThread::Run()
{
// for tracking the idle time state
BOOL bIdle = TRUE;
LONG lIdleCount = 0;

//消息读取乃至分发 当为WM_QUIT时,退出循环
for (;;)
{
//检查是否为空闲时刻
while (bIdle &&!::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE))
{
// call OnIdle while in bIdle state
if (!OnIdle(lIdleCount++))
bIdle = FALSE; // assume "no idle" state
}

//有消息,读消息并分发
do
{
// pump message, but quit on WM_QUIT
if (!PumpMessage())
return ExitInstance();

// reset "no idle" state after pumping "normal" message
if (IsIdleMessage(&m_msgCur))
{
bIdle = TRUE;
lIdleCount = 0;
}

}
while (::PeekMessage(&m_msgCur, NULL, NULL, NULL, PM_NOREMOVE));
}
}


主消息循环与模态对话框中的局部消息循环之间的关系:



当模态对话框显示时,进入模态对话框的消息循环,除非将模态对话框关闭,否则APP的DispatchMessage函数一直出不来。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐