为什么对话框不响应WM_TIMER消息?

时间:2021-11-30 18:10:30
我是一个基于对话框的程序,主对话框叫parentDlg,然后再对话框中添加了一个Button的按钮,我的目的是点击Button按钮,然后创建一个提示框(提示框用非模态对话框WaitDlg),提示“Please Wait...”,然后继续执行任务,在执行任务的过程中,不断刷新"Please Wait..."后面的点,感觉是动画的效果,这个打算在OnTimer()里实现,但是我查了N多资料,怎么弄程序就进不到OnTimer()里去,崩溃了要,救救我啊。。。。程序段如下:

void CParentDlg::OnButton() 
{
// TODO: Add your control notification handler code here

CWaitDlg *pDlg=new CWaitDlg;

pDlg->Create(IDD_WAITING_DIALOG,this);//IDD_WAITING_DIALOG已经创建好
pDlg->ShowWindow(SW_SHOW);
         pDlg->SetTimer(1,2000,NULL);

//SetTimer(1,2000,NULL);//用这个,父窗口的OnTimer()也不进不去

for (long i=0;i<800000000;i++){}//为了延时,Sleep(5000);也不行

pDlg->KillTimer(1);
         //KillTimer(1);
pDlg->DestroyWindow();

return;
}

void CWaitDlg::OnTimer(UINT_PTR nIDEvent)//总是进不到这个处理函数
{
// TODO: Add your message handler code here and/or call default
if (1 == nIDEvent)
{
AfxMessageBox("now, OK!");
}

CDialog::OnTimer(nIDEvent);
}

18 个解决方案

#1


不会吧!
是不是没有在 BEGIN_MESSAGE_MAP中加ON_WM_TIMER()?

#2


加了,是Class Wizard加的,不会错的:

BEGIN_MESSAGE_MAP(CWaitDlg, CDialog)
ON_WM_TIMER()
END_MESSAGE_MAP()

setimer()都成功的,返回值是1,但是就是进不去Ontimer(),没有框框弹出来就返回了

怎么也搞不定,头都大了。。。。

#3


引用楼主 yihuizyh 的回复:
...,提示“Please Wait...”,然后继续执行任务,在执行任务的过程中,不断刷新"Please Wait..."...


界面线程创建这个提示框,继续执行任务?

执行这句,界面线程都阻塞在这里了
for (long i=0;i <800000000;i++){}//为了延时,Sleep(5000);也不行

如果是这样,执行任务这段时间当然不能响应所有的窗口消息(包括WM_TIMER)

#4


楼主是用
for (long i=0;i <800000000;i++){}//为了延时,Sleep(5000);也不行 

这句来延迟等待对话框生存时间?

#5


对!
楼主的KillTimer应该放在
void CParentDlg::OnButton() 
外面,由其他某个事件触发。

引用 3 楼 stjay 的回复:
引用楼主 yihuizyh 的回复:
 ...,提示“Please Wait...”,然后继续执行任务,在执行任务的过程中,不断刷新"Please Wait..."...

 界面线程创建这个提示框,继续执行任务?

 执行这句,界面线程都阻塞在这里了
 for (long i=0;i  <800000000;i++){}//为了延时,Sleep(5000);也不行

 如果是这样,执行任务这段时间当然不能响应所有的窗口消息(包括WM_TIMER)

#6


我的本意是
for (long i=0;i  <800000000;i++){}//为了延时,Sleep(5000);也不行
只是代表我正在处理的任务,因为我有个计算任务要花费比较长的时间,所以弹出个Please Wait提示一下,再搞点动画,动画就用OnTimer实现,等任务处理完了,自然就把这个提示框销毁,定时器关闭。

如果消息都阻塞在
for (long i=0;i  <800000000;i++){}//为了延时,Sleep(5000);
这个任务里了,那我用什么机制才可以实现啊?
谢谢各位了!

#7


你这个用多线程吧

#8


用多线程,不要在界面线程里面做Sleep之类的操作,因为会导致界面无法刷新和无法处理消息之类的。自己新建一个工作者线程,可以用AfxBeginThread,这样就可以了,你SetTimer那部分没错的。主要就是不要塞住界面线程。

#9


你在非模态对话框WaitDlg提示框中作一个函数SetDlgTimer来设置SetTimer(),然后在来调用SetDlgTimer试试。

#10


楼上的,我试过了不行,看来只能用多线程了
主要是我还是菜鸟,还没用过多线程

#11


SetDlgTimer这个函数在非模态对话框WaitDlg提示框中的OnInitDialog调用就可以。

#12


引用 11 楼 qiaozhiyuan 的回复:
SetDlgTimer这个函数在非模态对话框WaitDlg提示框中的OnInitDialog调用就可以。


但是生成对话框没有用到OnInitDialog函数啊,这个函数也不需要重载吧?
我试了下重载这个函数,然后再里面设置setimer,还是不行。。。。

#13


界面线程中Sleep,常常都会引起界面线程的阻塞,这在用户要求及时响应时,一般都是不允许的。
你可以修改为将CWaitDlg *pDlg=new CWaitDlg; 这个局部的指针变量转换为成员指针变量,在需要时将其new,create等,此时你可以调用OnTimer;不需要时就窗口destroy,delete等,此时调用KillTimer.
这样子,你需要的提示功能应该可以实现吧。

#14


引用 12 楼 yihuizyh 的回复:
引用 11 楼 qiaozhiyuan 的回复:
SetDlgTimer这个函数在非模态对话框WaitDlg提示框中的OnInitDialog调用就可以。


但是生成对话框没有用到OnInitDialog函数啊,这个函数也不需要重载吧?
我试了下重载这个函数,然后再里面设置setimer,还是不行。。。。
那你能不能把你的代码涉及到这一部分的摘出来,或者做个简单的测试你就知道了。我都试了,可以的。

#15


比较变态的方法是:在主窗体的OnTimer消息处理函数中,通过::PostMessage(m_pDlg->GetSafeHwnd(),WM_TIMER,nIDEvent,0);把这个消息转发到子窗体中,这样子窗体的OnTimer事件就被触发了

#16


这个问题难道真的这么崩溃啊,求简单点的方法啊。。。。。
多线程的话我用AfxBeginThread开了一个线程,然后在线程里面创建子对话框WaitDlg,但是这样不能把父窗口指针搞进去,即使进去了也不能正常运行,而且我还不知道当任务处理完了如何在OnButton()里面销毁这个线程,用ThreadTerminate和AfxEndThread好像都不行

求高手啊,给个简单可行的方法,Timer真的这么复杂嘛?

#17


可以创建UI线程解决。

#18


能具体给些示例代码吗?特别是创建线程时需要传递父对话框指针不?如何在OnButton函数销毁线程?

引用 17 楼 jenf 的回复:
可以创建UI线程解决。


#1


不会吧!
是不是没有在 BEGIN_MESSAGE_MAP中加ON_WM_TIMER()?

#2


加了,是Class Wizard加的,不会错的:

BEGIN_MESSAGE_MAP(CWaitDlg, CDialog)
ON_WM_TIMER()
END_MESSAGE_MAP()

setimer()都成功的,返回值是1,但是就是进不去Ontimer(),没有框框弹出来就返回了

怎么也搞不定,头都大了。。。。

#3


引用楼主 yihuizyh 的回复:
...,提示“Please Wait...”,然后继续执行任务,在执行任务的过程中,不断刷新"Please Wait..."...


界面线程创建这个提示框,继续执行任务?

执行这句,界面线程都阻塞在这里了
for (long i=0;i <800000000;i++){}//为了延时,Sleep(5000);也不行

如果是这样,执行任务这段时间当然不能响应所有的窗口消息(包括WM_TIMER)

#4


楼主是用
for (long i=0;i <800000000;i++){}//为了延时,Sleep(5000);也不行 

这句来延迟等待对话框生存时间?

#5


对!
楼主的KillTimer应该放在
void CParentDlg::OnButton() 
外面,由其他某个事件触发。

引用 3 楼 stjay 的回复:
引用楼主 yihuizyh 的回复:
 ...,提示“Please Wait...”,然后继续执行任务,在执行任务的过程中,不断刷新"Please Wait..."...

 界面线程创建这个提示框,继续执行任务?

 执行这句,界面线程都阻塞在这里了
 for (long i=0;i  <800000000;i++){}//为了延时,Sleep(5000);也不行

 如果是这样,执行任务这段时间当然不能响应所有的窗口消息(包括WM_TIMER)

#6


我的本意是
for (long i=0;i  <800000000;i++){}//为了延时,Sleep(5000);也不行
只是代表我正在处理的任务,因为我有个计算任务要花费比较长的时间,所以弹出个Please Wait提示一下,再搞点动画,动画就用OnTimer实现,等任务处理完了,自然就把这个提示框销毁,定时器关闭。

如果消息都阻塞在
for (long i=0;i  <800000000;i++){}//为了延时,Sleep(5000);
这个任务里了,那我用什么机制才可以实现啊?
谢谢各位了!

#7


你这个用多线程吧

#8


用多线程,不要在界面线程里面做Sleep之类的操作,因为会导致界面无法刷新和无法处理消息之类的。自己新建一个工作者线程,可以用AfxBeginThread,这样就可以了,你SetTimer那部分没错的。主要就是不要塞住界面线程。

#9


你在非模态对话框WaitDlg提示框中作一个函数SetDlgTimer来设置SetTimer(),然后在来调用SetDlgTimer试试。

#10


楼上的,我试过了不行,看来只能用多线程了
主要是我还是菜鸟,还没用过多线程

#11


SetDlgTimer这个函数在非模态对话框WaitDlg提示框中的OnInitDialog调用就可以。

#12


引用 11 楼 qiaozhiyuan 的回复:
SetDlgTimer这个函数在非模态对话框WaitDlg提示框中的OnInitDialog调用就可以。


但是生成对话框没有用到OnInitDialog函数啊,这个函数也不需要重载吧?
我试了下重载这个函数,然后再里面设置setimer,还是不行。。。。

#13


界面线程中Sleep,常常都会引起界面线程的阻塞,这在用户要求及时响应时,一般都是不允许的。
你可以修改为将CWaitDlg *pDlg=new CWaitDlg; 这个局部的指针变量转换为成员指针变量,在需要时将其new,create等,此时你可以调用OnTimer;不需要时就窗口destroy,delete等,此时调用KillTimer.
这样子,你需要的提示功能应该可以实现吧。

#14


引用 12 楼 yihuizyh 的回复:
引用 11 楼 qiaozhiyuan 的回复:
SetDlgTimer这个函数在非模态对话框WaitDlg提示框中的OnInitDialog调用就可以。


但是生成对话框没有用到OnInitDialog函数啊,这个函数也不需要重载吧?
我试了下重载这个函数,然后再里面设置setimer,还是不行。。。。
那你能不能把你的代码涉及到这一部分的摘出来,或者做个简单的测试你就知道了。我都试了,可以的。

#15


比较变态的方法是:在主窗体的OnTimer消息处理函数中,通过::PostMessage(m_pDlg->GetSafeHwnd(),WM_TIMER,nIDEvent,0);把这个消息转发到子窗体中,这样子窗体的OnTimer事件就被触发了

#16


这个问题难道真的这么崩溃啊,求简单点的方法啊。。。。。
多线程的话我用AfxBeginThread开了一个线程,然后在线程里面创建子对话框WaitDlg,但是这样不能把父窗口指针搞进去,即使进去了也不能正常运行,而且我还不知道当任务处理完了如何在OnButton()里面销毁这个线程,用ThreadTerminate和AfxEndThread好像都不行

求高手啊,给个简单可行的方法,Timer真的这么复杂嘛?

#17


可以创建UI线程解决。

#18


能具体给些示例代码吗?特别是创建线程时需要传递父对话框指针不?如何在OnButton函数销毁线程?

引用 17 楼 jenf 的回复:
可以创建UI线程解决。