关于自封装的消息循环函数的改进问题

Fireway2008 2009-05-29 09:15:44
加精
各位高手, 本人利用AfxBeginThread开辟了一个UI线程,并自写了一个消息循环函数,希望以后可以封装入DLL内。

上网搜索了不少例子,但都感觉讲的不够详细,在此把自己写的贴出来,当然这个函数存在一定的缺陷,感觉有点冗繁,希望大家指正。

改进后也方便其他人学习参考。
如下代码:


BOOL CTestDlg::DoLoop()
{
MSG msg;
BOOL bRet;
while(1)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))// 从Windows消息队列中取出消息
{
bRet = GetMessage(&msg, NULL, 0, 0);
if(bRet != 0)
{
if(bRet == -1)//判断返回值是否有问题
{
AfxMessageBox(_T("Handle the error and possibly exit!"));
break;
}else{//以下分情况讨论获取到的消息对应什么操作
switch(msg.message)
{
case WM_CLOSE:
DestroyWindow();
break;
case WM_DESTROY:
delete this;
PostQuitMessage(0);
break;
default:
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}
}// end of inner if

if(!AfxGetApp()->PreTranslateMessage(&msg))// 如果无法预处理消息
{
::TranslateMessage(&msg);// 转换消息
::DispatchMessage(&msg); // 发送消息
}
}
AfxGetApp()->OnIdle(0);
AfxGetApp()->OnIdle(1);
}// end of while
return TRUE;
}
...全文
961 94 打赏 收藏 转发到动态 举报
写回复
用AI写文章
94 条回复
切换为时间正序
请发表友善的回复…
发表回复
StonesHeart 2012-03-19
  • 打赏
  • 举报
回复
不错,学习了。
clever101 2010-06-09
  • 打赏
  • 举报
回复
这个贴一定要顶的!楼主的好学精神以及下面众位高手的耐心指导都值得学习啊!
Fireway2008 2009-06-24
  • 打赏
  • 举报
回复
补充一下,本人在处理窗口消息的时候,重载了DefWindowProc
应该重载WindowProc才是正确的。


详细请见下边的帖子:WindowProc和DefWindowProc的区别
pysjp 2009-06-13
  • 打赏
  • 举报
回复
帮楼主顶起,好帖子
Fireway2008 2009-06-13
  • 打赏
  • 举报
回复
非常感谢!
看来不能随便乱用AfxGetApp()->OnIdle()



问题解决,感谢各位朋友的参与!!
paerxiushi 2009-06-13
  • 打赏
  • 举报
回复
我已经把改好后的源代码发到你的邮箱里了。
paerxiushi 2009-06-13
  • 打赏
  • 举报
回复
你的每个子窗体的确是在新的UI线程中的,这点没错。

1.主窗体无法响应鼠标消息是因为CtestDlg重载了OnNcLButtonDown函数,代码改成:

void CTestDlg::OnNcLButtonDown(UINT nHitTest, CPoint point)
{
m_bDig = TRUE;
CDialog::OnNcLButtonDown(nHitTest,point); //新添加的代码
}


2.当子窗体显示之后,主窗体无法响应消息是因为AfxGetApp()->OnIdle()占用了CPU,代码改成:

BOOL CHoleDlg::DoLoop()
{
MSG msg;
BOOL bRet=0;
while(1)
{

if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message==WM_QUIT)
break;
if(!AfxGetApp()->PreTranslateMessage(&msg))//如果无法预处理消息
{
::TranslateMessage(&msg);//转换消息
::DispatchMessage(&msg);//发送消息
}
}
else
{
//在这里添加空闲任务处理
Sleep(100);

}


}
return TRUE;
}

Sleep函数会将当前线程挂起,不影响其他 UI线程的运行。
而AfxGetApp()->OnIdle()阻塞了整个进程,在这个方法执行时,其他线程无法响应消息。当UI线程数量超过2个时,会引起死机。每个UI线程占用CPU为100%
paerxiushi 2009-06-10
  • 打赏
  • 举报
回复
你发过来的附件是0字节的,重新发一遍,就用rar压缩包的格式好了。
Fireway2008 2009-06-10
  • 打赏
  • 举报
回复
[Quote=引用 85 楼 cnzdgs 的回复:]
从消息循环上已经看不出有什么问题,估计与窗口的创建及消息响应有关,建议你另做一个简单的测试程序来分析这个问题。
[/Quote]

OK, I will try .
Thank you !
cnzdgs 2009-06-10
  • 打赏
  • 举报
回复
从消息循环上已经看不出有什么问题,估计与窗口的创建及消息响应有关,建议你另做一个简单的测试程序来分析这个问题。
Fireway2008 2009-06-10
  • 打赏
  • 举报
回复
原打算封装好一个函数留以后方便使用,
没想到有这么多的禁忌和漏洞,
创建窗体后问题多多……



希望大家继续关注此帖。
cnzdgs 2009-06-09
  • 打赏
  • 举报
回复
看了一下DoLoop的代码,下面这段代码有些问题,先注释掉看看。
if(!AfxGetApp()->PreTranslateMessage(&msg))// 如果无法预处理消息
{
::TranslateMessage(&msg);// 转换消息
::DispatchMessage(&msg); // 发送消息
}
}
AfxGetApp()->OnIdle(0);
AfxGetApp()->OnIdle(1);
Fireway2008 2009-06-09
  • 打赏
  • 举报
回复
To paerxiushi :
代码已经打包发送,本人邮箱diy64@163.com
请查收!


To wangask00 :

本人非IT专业工作者,但对编程很有兴趣,学习VC 2年。




感谢2位对我帖子的关注。


Fireway2008 2009-06-09
  • 打赏
  • 举报
回复
[Quote=引用 76 楼 simon031187 的回复:]
LZ贴了大把代码,但是没看到AfxBeginThread是怎么调用的,有没有把子对话框完全包在子线程里
如果DoLoop函数在主线程里面调用,就抢占了主对话框的消息调度,主对话框八成要假死
还有贴代码时请加上代码样式,别欺负俺眼神不好
[/Quote]

呵呵,这位朋友,
我在20楼已经贴好了调用的代码。
wangask00 2009-06-09
  • 打赏
  • 举报
回复
paerxiushi
真是个热心的好人啊,想问下paerxiushi是从事哪个方面工作的,工作多长时间了
Fireway2008 2009-06-09
  • 打赏
  • 举报
回复
[Quote=引用 72 楼 cnzdgs 的回复:]
看了一下DoLoop的代码,下面这段代码有些问题,先注释掉看看。
if(!AfxGetApp()->PreTranslateMessage(&msg))// 如果无法预处理消息
{
::TranslateMessage(&msg);// 转换消息
::DispatchMessage(&msg); // 发送消息
}
}
AfxGetApp()->OnIdle(0);
AfxGetApp()->OnIdle(1);
[/Quote]

已经修改过了,可是主窗口M 无法响应鼠标的情况还是会出现……
其他类型的书写方法也尝试过了,但是还是不行……


目前DoLoop 按如下代码书写:
BOOL CHoleDlg::DoLoop()

{
MSG msg;
BOOL bRet=0;
while(1)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
if(msg.message == WM_QUIT)
{
MessageBox(_T("已调用过PostQuitMessage(0)"),_T("注意了"),MB_OK);
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
AfxGetApp()->OnIdle(0);
AfxGetApp()->OnIdle(1);
}
}// 可以保证,关闭对话框X后,退出了while 循环
return TRUE;
}

我只是打算在新UI线程中创建一个非模态对话框 而已,虽然用继承CWinThread的方法已经实现,但是用上了
工作线程+ 非模式对话框类的消息循环
却出现了这么多问题,


不知各位在实现这个功能的时候,消息循环是如何书写的?
应该不会很复杂吧。

simon031187 2009-06-09
  • 打赏
  • 举报
回复
居然没有自动缩进
simon031187 2009-06-09
  • 打赏
  • 举报
回复
LZ贴了大把代码,但是没看到AfxBeginThread是怎么调用的,有没有把子对话框完全包在子线程里
如果DoLoop函数在主线程里面调用,就抢占了主对话框的消息调度,主对话框八成要假死
还有贴代码时请加上代码样式,别欺负俺眼神不好

BOOL CTestDlg::DoLoop()
{
MSG msg;
BOOL bRet;
while(1)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))// 从Windows消息队列中取出消息
{
bRet = GetMessage(&msg, NULL, 0, 0);
if(bRet != 0)
{
if(bRet == -1)//判断返回值是否有问题
{
AfxMessageBox(_T("Handle the error and possibly exit!"));
break;
}else{//以下分情况讨论获取到的消息对应什么操作
switch(msg.message)
{
case WM_CLOSE:
DestroyWindow();
break;
case WM_DESTROY:
delete this;
PostQuitMessage(0);
break;
default:
TranslateMessage(&msg);
DispatchMessage(&msg);
break;
}
}
}// end of inner if

if(!AfxGetApp()->PreTranslateMessage(&msg))// 如果无法预处理消息
{
::TranslateMessage(&msg);// 转换消息
::DispatchMessage(&msg); // 发送消息
}
}
AfxGetApp()->OnIdle(0);
AfxGetApp()->OnIdle(1);
}// end of while
return TRUE;
}
paerxiushi 2009-06-09
  • 打赏
  • 举报
回复
回69楼:
我想实现的是:

1.在新UI线程中的模态对话框

or

2.在新UI线程中的非模态对话框
---------------------
如果说是按照MFC的方式,创建UI线程:
1.定义一个线程类,让它继承CWinThread,比如:CUIThread
2.在这个类中的InitInstance函数中使用Create创建非模态对话框,使用DoModal创建模态对话框,然后将对话框指针赋给类的成员m_pMainWnd
3.将要创建UIThread线程时,使用
CWinThread* m_pUIThread=AfxBeginThread(RUNTIME_CLASS(CUIThread),THREAD_PRIORITY_BELOW_NORMAL,0,0,NULL);

如果说是按照SDK方式,创建UI线程:
1.使用CreateThread创建线程
2.线程回调函数中,使用CreateDialog创建非模态对话框,使用DialogBox创建模态对话框,对于非模态对话框,需要在回调函数中加入消息循环,模态的,则不需要



动用AfxBeginThread + 对话框对象X + create 就是创建了一个非模态的对话框,然后在X
内添加DoLoop就可以实现其UI线程的循环
------------------

如果说是AfxBeginThread真正创建了UI线程,那么为了创建一个非模态的对话框,DoLoop函数显得多余了。




LZ把源代码发给我看一下,我的邮箱是:paerxiushi@163.com
Fireway2008 2009-06-09
  • 打赏
  • 举报
回复
[Quote=引用 71 楼 wangask00 的回复:]
我感觉你的思维很乱,我觉得你应该找本mfc的书系统的看一下,重点搞清楚windows的消息机制,你对windows的消息机制还没搞清楚

不过我也解释不清楚你的问题

你的PreTranslateMessage函数处理鼠标左键,跟按键消息是没错

后来又,只是无法响应鼠标消息
却可以相应 键盘消息……
[/Quote]

说的是阿,我这个方面的知识很是欠缺……
加载更多回复(72)
《程序设计方法》以Scheme语言为基础介绍计算和程序设计的一般理论和实践。《程序设计方法》由8个部分和7个独立的章节(第8、13、18、24、29、33、38章)组成。8个部分主要讨论程序设计,独立章节则介绍一些与程序设计和计算相关的话题。《程序设计方法》第1至第3部分介绍了基于数据驱动的程序设计基础。第4部分介绍了程序设计中的抽象问题。第5部分和第6部分是与递归及累积相关的内容。《程序设计方法》的最后两部分说明了设计程序的意义,阐述了如何应用前6个部分所描述的程序设计诀窍,以及使用赋值语句必须特别小心的一些问题。 《程序设计方法》可作为高等院校计算机科学与技术专业“程序设计导论”和“计算导论”的教材和教学参考书,也可作为函数式语言和Scheme语言的入门教材。 目录 · · · · · · 第一部分 简单数据的处理 第1章 学生、教师和计算机 3 第2章 数、表达式和简单程序 5 2.1 数和算术运算 5 2.2 变量和程序 6 2.3 字处理问题 9 2.4 错误 10 2.5 设计程序 12 第3章 程序就是函数加上变量定义 15 3.1 函数复合 15 3.2 变量定义 17 3.3 函数复合练习 18 第4章 条件表达式和函数 20 4.1 布尔类型和关系 20 4.2 函数和条件测试 22 4.3 条件和条件函数 25 4.4 条件函数的设计 27 第5章 符号信息 31 第6章 复合数据之一:结构体 34 6.1 结构体 34 6.2 补充练习:绘制简单图形 36 6.3 结构体定义 38 6.4 数据定义 41 6.5 设计处理复合数据的函数 43 6.6 补充练习:圆和长方形的移动 46 6.7 补充练习:刽子手游戏 49 第7章 数据的多样性 52 7.1 数据混合与区分 52 7.2 设计处理混合数据的函数 55 7.3 再论函数复合 58 7.4 补充练习:图形的移动 60 7.5 输入错误 61 第8章 语法和语义 63 8.1 Scheme的词汇 63 8.2 Scheme的文法 64 8.3 Scheme的含义 65 8.4 错误 68 8.5 布尔值表达式 70 8.6 变量定义 71 8.7 结构体的定义 72 第二部分 任意数目数据的处理 第9章 复合数据类型之二:表 77 9.1 表 77 9.2 任意长的表的数据定义 80 9.3 处理任意长的表 82 9.4 设计自引用数据定义的函数 84 9.5 更多关于简单表的例子 86 第10章 表的进一步处理 90 10.1 返回表的函数 90 10.2 包含结构体的表 93 10.3 补充练习:移动图片 98 第11章 自然数 100 11.1 定义自然数 100 11.2 处理任意大的自然数 101 11.3 补充练习:创建表,测试函数 103 11.4 自然数的另一种数据定义 104 11.5 更多与自然数有关的性质 108 第12章 三论函数复合 110 12.1 设计复杂的程序 110 12.2 递归的辅助函数 111 12.3 问题泛化与函数泛化 114 12.4 补充练习:字母的重新排列 117 第13章 用list构造表 119 第三部分 再论任意大数据的处理 第14章 再论自引用数据定义 125 14.1 结构体中的结构体 125 14.2 补充练习:二叉搜索树 131 14.3 表中的表 135 14.4 补充练习:Scheme求值 137 第15章 相互引用的数据定义 139 15.1 由结构体组成的表与结构体中的表 139 15.2 为相互引用的定义设计函数 144 15.3 补充练习:网页再谈 145 第16章 反复精化设计 147 16.1 数据分析 147 16.2 定义数据类型,再改进它们 148 16.3 改进函数和程序 150 第17章 处理两种复杂数据片段 152 17.1 同时处理两个表:第一种情况 152 17.2 同时处理两个表:第二种情况 154 17.3 同时处理两个表:第三种情况 156 17.4 函数的简化 159 17.5 设计读入两个复杂输入的函数 160 17.6 处理两个复杂输入的练习 161 17.7 补充练习:Scheme求值之二 164 17.8 相等与测试 165 第18章 局部定义和辖域 172 18.1 用local组织程序 172 18.2 辖域和块结构 183 第四部分 抽象设计 第19章 定义的相似性 189 19.1 函数的类似之处 189 19.2 数据定义的类似之处 195 第20章 函数也是值 199 20.1 语法和语义 199 20.2 抽象函数和多态函数的合约 200 第21章 抽象设计的例子 204 21.1 从实例中抽象 204 21.2 抽

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧