MFC,计时器和模式消息框 [英] MFC, timers and modal message boxes

查看:102
本文介绍了MFC,计时器和模式消息框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好.
我会尽量简化.

我创建了一个具有未排序列表框(m_loglist)的基于MFC对话框的应用程序
我在CTimerTestingDlg类中添加了一个计时器.计时器每秒钟滴答一声.
我还创建了一个将初始值设置为0的int计数器.
在OnTimer处理程序中,我添加以下代码.

Hello to everyone.
I''ll try to be as simple as possible.

I created an MFC dialog based application with am unsorted listbox (m_loglist)
I added a timer in the CTimerTestingDlg class. The timer ticks every second.
I also created an int counter with initial value set to 0.
In the OnTimer handler, i add the following code.

void CTimerTestingDlg::OnTimer(UINT_PTR nIDEvent)
{
    // TODO: Add your message handler code here and/or call default
    counter++;

    CString value;
    value.Format(L"%d", counter);

    if (counter==5)
    {
        AfxMessageBox(L"five seconds",MB_OK | MB_SYSTEMMODAL);
        
    }
    m_loglist.AddString(value);

    CDialog::OnTimer(nIDEvent);
}




输出为:
1
2
3
4
(此处出现一个消息框,显示五秒钟")
6
7
8
9
5(我单击确定",因此出现缺少的"5"值)
10
11
12
.....等

我试图了解允许这种情况发生的机制.

问题是:

1)由于消息框是模态的,在响应到来之前,是否不应该阻塞MFC的消息泵?这意味着,直到我按下确定"按钮时,才出现6或更高的值..

2)在书目中没有提到AfxMessageBox函数调用启动新线程.如果我们假设这是(1)的答案,我们将在中间留下CTimerTestingDlg对象的OnTimer方法的实例.(=由于消息框而尚未键入值"5"的对象)
当计时器再次计时时,似乎上面的实例在中间,再次调用了同一CTimerTestingDlg对象的OnTimer方法!我说的对吗?如果是的话,这怎么可能呢?

3)当我单击确定"时,继续执行中间剩下的OnTimer实例,并键入缺少的"5"值. (在我的示例中为"9"之后).这个OnTimer实例存储在哪里?在堆栈中吗?

谢谢您的时间,我试图理解下面的内容.




The output is:
1
2
3
4
(here a message box appears saying "five seconds")
6
7
8
9
5 (I clicked OK so the missing "5" value appears)
10
11
12
..... and so on

Im trying to understand the mechanism that allows this to happen.

The questions are:

1) Since the message box is modal, shouldn''t the message pump of MFC be blocked until the response comes? This means, the values of 6 and above shouldnt appear until i press the OK button..

2)Nowhere in the bibliography is mentioned that the AfxMessageBox function call launches a new thread. If we assume that this is the answer to (1), we have an instance of the OnTimer method of the CTimerTestingDlg object left in the middle.(= the one that hasnt typed the value "5" yet due to the message box)
When the timer ticks again, it seems that the OnTimer method of same CTimerTestingDlg object is called again, while the instance above is in the middle! Im i right? if yes, how can this ever be possible?

3) When i click OK, the execution of the OnTimer instance that was left in the middle continues and types the missing "5" value. (after "9" in my example). Where was this OnTimer instance stored? In the stack?

Thank you for your time, im trying to understand what lies beneath here.

推荐答案

完全可以理解,不需要魔术和/或线程.

OnTimer()函数是在收到"WM_TIMER" Windows消息时调用的事件.该消息由MFC提供的消息泵"调度.在发送到OnTimer()之前,已从消息队列中删除了这条WM_TIMER消息.

AfxMessageBox()完成该操作,然后等待单击确定"按钮(或其他按钮).为了检测点击,它需要自己处理Windows消息,因此它提供了自己的消息泵".即使此消息泵由消息框本身提供,它仍将处理此应用程序/线程系列的* any * Windows消息.

随之而来的是下一秒的另一条"WM_TIMER"消息,并被分派到相同的OnTimer()函数.

通常,当您处理事件时,要先完成处理,然后再返回消息泵的分发"部分,因此您不会看到这些工件(在其中而不是消息框内放置10或20秒的Sleep())您会看到一个更可预测的序列).在这种情况下,AfxMessageBox()需要一个消息泵来完成其工作,而您正在处理它的计时器滴答声.

如果您出于任何原因要中断滴答声,则应明智地使用KillTimer()和SetTimer().

(为回答问题的另一部分而编辑)

Perfectly understandable and doesn''t require magic and/or threads.

The OnTimer() function is an event called upon the receipt of the "WM_TIMER" windows message. This message is dispatched by the MFC provided "message pump". This single WM_TIMER message was removed from the message queue prior to dispatch to OnTimer().

AfxMessageBox() does it''s thing and waits for the "OK" button (or whatever) to be clicked. To detect the click, it needs to process windows messages for itself hence it provides it''s own "message pump". Even though this message pump is provided by the message box itself, it will process *any* windows message for this application / thread family.

Along comes another "WM_TIMER" message for the next second and is dispatched to the same OnTimer() function.

Generally, when you are processing events, you run the processing to completion before returning to the "dispatch" portion of the message pump so you do not see these artifacts (throw a 10 or 20 second Sleep() in there instead of the message box and you''ll see a more predictable sequence). In this case, AfxMessageBox() needed a message pump to complete it''s work and you''re timer ticks got processed by it.

Judicious use of KillTimer() and SetTimer() should be used if you want to interrupt the flow of ticks for whatever reason.

(Edited to answer another part of your question)

dlavrantonis写道:
dlavrantonis wrote:

此OnTimer实例存储在哪里?在堆栈中吗?

Where was this OnTimer instance stored? In the stack?


是的,在出现消息框后,在m_loglist.AddString(value);语句上设置断点.您会到达那里的电话号码> 5.在那里,向后检查堆栈/调用框架,最终将找到对编号5的另一个OnTimer()调用.当您单击确定"时,您要做的就是返回


Yup, set a breakpoint on the m_loglist.AddString(value); statement *after* the message box appears. You''ll get there for some number > 5. When you are there, examine the stack / call frame backwards, you''ll eventually find the other call to OnTimer() for number 5. When you click on "OK", all you''re doing is returning up through the stack.


对于每次调用OnTimer函数,计时器似乎启动了一个不同的线程.

It looks like the timer launches a different thread, for each call of the OnTimer function.


这篇关于MFC,计时器和模式消息框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆