基于聊天对话框图片的程序中如何响应WM

文章-1213&
在对话框程序中,我们经常是利用对话框上的子控件进行命令响应来处理一些事件。如果我们想要让对话框(子控件的父窗口)类来响应我们的按键消息,我们可以通过ClassWizard对WM_KEYDOWN消息进行响应,当程序运行后,我们按下键盘上的按键,但对话框不会有任何的反应。这是因为在对话框程序中,某些特定的消息,例如按键消息,它们被Windows内部的对话框过程处理了(即在基类中完成了处理,有兴趣的读者可以查看MFC的源代码),或者被发送给子控件进行处理,所以我们在对话框类中就捕获不到按键的消息了。
既然我们知道了这个处理的过程,我们就可以找到底层处理按键消息的函数,然后在子类中重载它,就可以在对话框程序中处理按键消息了。在MFC中,是利用BOOL ProcessMessageFilter(int code, LPMSG lpMsg)这个虚函数来过滤或响应菜单和对话框的特定Windows消息。下面我们通过程序给大家演示基于对话框的应用程序对WM_KEYDOWN消息的捕获。
第一步:新建一个工程,选择MFC AppWizard (exe),工程名为WinSun,点击ok,进入下一步,选择Dialog based,点击Finish。
第二步:在CWinSunApp类上点击右键,选择Add Member Varialbe,增加一个类型为HWND,变量名m_hwndDlg的public的变量。代码如下:
class CWinSunApp : public CWinApp
&&&&&& HWND m_hwndD
&&&&&& CWinSunApp();
// Overrides
&&&&&& // ClassWizard generated virtual function overrides
&&&&&& //{{AFX_VIRTUAL(CWinSunApp)
&&&&&& public:
&&&&&& virtual BOOL InitInstance();
&&&&&& //}}AFX_VIRTUAL
// Implementation
&&&&&& //{{AFX_MSG(CWinSunApp)
&&&&&&&&&&&&& // NOTE - the ClassWizard will add and remove member functions here.
&&&&&&&&&&&&& //&&& DO NOT EDIT what you see in these blocks of generated code !
&&&&&& //}}AFX_MSG
&&&&&& DECLARE_MESSAGE_MAP()
第三步:在WinSun.cpp(CWinSunApp类)文件中的InitInstance()函数中添加如下代码:
WinSun.cpp
BOOL CWinSunApp::InitInstance()
&&&&&& AfxEnableControlContainer();
&&&&&& // Standard initialization
&&&&&& // If you are not using these features and wish to reduce the size
&&&&&& //& of your final executable, you should remove from the following
&&&&&& //& the specific initialization routines you do not need.
#ifdef _AFXDLL
&&&&&& Enable3dControls();&&&&&&&&&&&&&&&&&&&& // Call this when using MFC in a shared DLL
&&&&&& Enable3dControlsStatic();&&&&& // Call this when linking to MFC statically
&&&&&& CWinSunD
&&&&&& m_pMainWnd = &
&&&&&& int nResponse = dlg.DoModal();
&&&&&& if (nResponse == IDOK)
&&&&&&&&&&&&& // TODO: Place code here to handle when the dialog is
&&&&&&&&&&&&& //& dismissed with OK
&&&&&& else if (nResponse == IDCANCEL)
&&&&&&&&&&&&& // TODO: Place code here to handle when the dialog is
&&&&&&&&&&&&& //& dismissed with Cancel
&&&&&& // Since the dialog has been closed, return FALSE so that we exit the
&&&&&& //& application, rather than start the application's message pump.
&&&&&& m_hwndDlg=NULL;
&&&&&& return FALSE;
第四步:在CWinSunApp类上点击右键,选择Add Virtual Function,在左边一栏里,选择ProcessMessageFilter,在右边按钮上选择Add and Edit,然后加入以下代码:
WinSun.cpp
BOOL CWinSunApp::ProcessMessageFilter(int code, LPMSG lpMsg)
&&&&&& // TODO: Add your specialized code here and/or call the base class
&&&&&& if(m_hwndDlg!=NULL)
&&&&&&&&&&&&& //判断消息,如果消息是从对话框发出的或者其子控件发出的,我们就进行处理。sunxin
&&&&&&&&&&&&& if((lpMsg-&hwnd==m_hwndDlg) || ::IsChild(m_hwndDlg,lpMsg-&hwnd))
&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&& //如果消息是WM_KEYDOWN,我们就弹出一个消息框。sunxin
&&&&&&&&&&&&&&&&&&&& if(lpMsg-&message==WM_KEYDOWN)
&&&&&&&&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&&&&&&&&& AfxMessageBox("捕获WM_KEYDOWN消息成功!");
&&&&&&&&&&&&&&&&&&&& }
&&&&&&&&&&&&& }
&&&&&& return CWinApp::ProcessMessageFilter(code, lpMsg);
第五步:在WinSunDlg.cpp(CWinSunDlg类)中的OnInitialDialog()函数中加入以下代码:
WinSunDlg.cpp
BOOL CWinSunDlg::OnInitDialog()
&&&&&& CDialog::OnInitDialog();
&&&&&& // Add "About..." menu item to system menu.
&&&&&& // IDM_ABOUTBOX must be in the system command range.
&&&&&& ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
&&&&&& ASSERT(IDM_ABOUTBOX & 0xF000);
&&&&&& CMenu* pSysMenu = GetSystemMenu(FALSE);
&&&&&& if (pSysMenu != NULL)
&&&&&&&&&&&&& CString strAboutM
&&&&&&&&&&&&& strAboutMenu.LoadString(IDS_ABOUTBOX);
&&&&&&&&&&&&& if (!strAboutMenu.IsEmpty())
&&&&&&&&&&&&& {
&&&&&&&&&&&&&&&&&&&& pSysMenu-&AppendMenu(MF_SEPARATOR);
&&&&&&&&&&&&&&&&&&&& pSysMenu-&AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
&&&&&&&&&&&&& }
&&&&&& // Set the icon for this dialog.& The framework does this automatically
&&&&&& //& when the application's main window is not a dialog
&&&&&& SetIcon(m_hIcon, TRUE);&&&&&&&&&&&&&&&&& // Set big icon
&&&&&& SetIcon(m_hIcon, FALSE);&&&&&&&&& // Set small icon
&&&&&& // TODO: Add extra initialization here
//将对话框的句柄传递到CWinSunApp类中。sunxin
&&&&&& ((CWinSunApp*)AfxGetApp())-&m_hwndDlg=m_hW
&&&&&& return TRUE;& // return TRUE& unless you set the focus to a control
第六步:在对话框窗口销毁后,将CWinSunApp类中的变量m_hwndDlg置为NULL,为此我们在CWinSunDlg类上点击右键,选择Add Windows Message Handler,在左边一栏中选择WM_DESTROY,在右边按钮上选择Add and Edit,然后加入以下代码:
WinSunDlg.cpp
void CWinSunDlg::OnDestroy()
&&&&&& CDialog::OnDestroy();
&&&&&& // TODO: Add your message handler code here
&&&&&& ((CWinSunApp*)AfxGetApp())-&m_hwndDlg=NULL;
至此,我们的工作就做完了,现在我们可以按Ctrl+F5运行程序,看到我们想要的结果。
阅读(...) 评论() && VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)
VS2010/MFC编程入门之九(对话框:为控件添加消息处理函数)
&&&&&& 在上一讲中已经讲过,这一讲的主要内容是如何为控件添加消息处理函数。&&&&&& 为对话框和控件等定义了诸多,我们对它们操作时会触发消息,这些消息最终由消息处理函数处理。比如我们点击按钮时就会产生BN_CLICKED消息,修改编辑框内容时会产生EN_CHANGE消息等。一般为了让某种操作达到效果,我们只需要实现某个消息的消息处理函数。&&&&&& 一.添加消息处理函数&&&&&& 鸡啄米仍以前面的加法计算器的程序为例,说明怎样为&计算&按钮控件添加消息处理函数。添加方法列出4种:&&&&&& 1.使用Class Wizard添加消息处理函数&&&&&&&用过的6.0的朋友应该对Class Wizard很熟悉了,添加、消息处理函数等经常会用到它,可以说是一个很核心的功能。但从VS2002开始就见不到Class Wizard了,大部分功能都集成到对话框和控件等的属性中了,使用很方便。到,久违的Class Wizard又回来了。但鸡啄米已经习惯了使用属性中的功能了,对于从VC++ 6.0直接转VS2010的朋友可能觉得还是使用Class Wizard比较习惯。&&&&&& 大家应该记得,&计算&按钮的ID为IDC_ADD_BUTTON,上图中Commands标签下,Oject IDs列表中有此ID,因为我们是想实现点击按钮后的消息处理函数,所以在Messages列表中选择BN_CLICKED消息,然后点右上方的Add Handler就可以添加BN_CLICKED消息处理函数OnClickedAddButton了。当然你也可以改名,但一般用的默认的就可以。&&&&&& 2.通过&Add Event Handler...&添加消息处理函数&&&&&&&在&计算&按钮上点右键,然后在右键菜单中选择菜单项&Add Event Handler...&,弹出&Event Handler Wizard&对话框,如下图:&&&&&&&可见&Message type&中默认选中的就是BN_CLICKED消息,函数名和所在类都已经自动给出,直接点&Add and Edit&就可以了。&&&&&&&3.在按钮的属性视图中添加消息处理函数&&&&&&&上面说过,从VS2002开始就主要从属性视图添加消息处理函数了。我们在&计算&按钮上点右键,在右键菜单中选择&Properties&,右侧面板中会显示按钮的属性视图。&&&&&&&我们可以像上图中那样,点属性视图的&Control Events&按钮(类似闪电标志),下面列出了&计算&按钮的所有消息。我们要处理的是BN_CLICKED消息,点其右侧空白列表项,会出现一个带下箭头的按钮,再点此按钮会出现&&Add& OnBnClickedAddButton&选项,最后选中这个选项就会自动添加BN_CLICKED处理函数了。&&&&&& 4.双击按钮添加消息处理函数&&&&&& 最直接最简单的方法就是,双击&计算&按钮,MFC会自动为其在CAdditionDlg类中添加BN_CLICKED消息的处理函数OnBnClickedAddButton()。&&&&&& 二.在消息处理函数中添加自定义功能&&&&&& 在我们使用任意一种方法添加了消息处理函数以后,都只能得到一个空的OnBnClickedAddButton()函数的函数体,要实现我们想要的功能,还需要在函数体中加入自定义功能代码。&&&&&&&在加法计算器程序中,我们想要&计算&按钮实现的功能是,获取被加数和加数的数值,然后计算它们的和并显示到和的编辑框里。那么,OnBnClickedAddButton()的函数体就应修改为:
void&CAdditionDlg::OnBnClickedAddButton() &&
&&&&UpdateData(TRUE); &&
&&&&m_editSum&=&m_editSummand&+&m_editA &&
&&&&UpdateData(FALSE); &&
}&&&&&&&& 鸡啄米在上面的代码中已经添加注释,大家应该很容易理解了。对于UpdateData()函数的说明在上一讲中已经介绍过,如果忘了可以再回上一讲了解了解。&&&&&& 接下来我们运行下此应用程序。在运行结果界面中,输入被加数5.1,加数2.3,然后点&计算&:&&&&&&&在上图中可以看到,点&计算&按钮后,和的编辑框中显示了正确结果:7.4。&&&&&&&鸡啄米简单分析下运行过程:输入被加数和加数,点&计算&按钮后产生点击消息,从而调用OnBnClickedAddButton()函数。进入此函数后,首先由UpdateData(TRUE)函数将被加数的值5.1和加数的值2.3分别保存到变量m_editSummand和m_editAddend,然后通过语句m_editSum&=&m_editSummand&+&m_editA计算出被加数和加数的和为7.4,并把7.4赋值给m_editSum。最后调用UpdateData(FALSE)根据被加数、加数、和的值更新三个编辑框的显示值,就得到了上图中的结果。&&&&&& 到此,一个具有简单的加法运算功能的加法计算器应用程序就基本完成了。如果大家想实现其他功能,可以修改控件资源和消息处理函数来练习下。本节就讲到这里了,有问题欢迎到鸡啄米博客或者我们的编程入门qq群讨论。
除非特别注明,文章均为原创
转载请标明本文地址:
作者:鸡啄米
&&( 22:18:12)&&( 22:15:37)&&( 22:36:0)&&( 23:17:45)&&( 19:46:26)&&( 22:7:57)&&( 23:32:16)&&( 1:53:2)&&( 23:22:54)&&( 22:18:8)
今年的c网络编程的确让我很头疼鸡啄米 于
21:20:23 回复网络编程实际上还是很重要的wanghe 于
15:19:02 回复楼主,怎么将C++几个功能模块连接成一个项目?求指导
博客新手,欢迎围观!共同进步!鸡啄米 于
21:20:47 回复常来常往
来学习一下
来支持新文
基础的必须好好学!鸡啄米 于
21:21:19 回复嗯,基础很重要
不错,好好练习下!
网络程序猿?鸡啄米 于
23:28:59 回复是程序猿
大学生,刚从VC 6.0转到VS2010.从MFC第一章看到现在,主要是熟习了VS 2010的MFC界面操作,顺带复习一下MFC的编程,感觉帮助非常大,非常感谢。鸡啄米 于
19:58:16 回复谢谢认同,以后常来啊
之前在网上看了好多教程都晕头转向的,看了您的豁然开朗啊!多谢大师!
好久没有使用MFC了,来复习下
话说,好像没有将字符串转化成float(int),最终结果只是字符串的连接而已鸡啄米 于
16:07:11 回复那应该是因为你给edit添加的变量是CString类型,应该选float或double型
你们的QQ交流群是多少~~鸡啄米 于
19:50:19 回复见右侧栏eason 于
15:16:09 回复哪里啊eason 于
15:16:40 回复MFC对话框双击控件怎么都没反应
为什么运行后程序的输入框自动有一个数字,-9.255e+061.谢谢InitWaiter 于
19:51:55 回复原因为变量没有初始化。需要响应WM_InitDialog消息,在该消息响应函数OnInitDialog中为三个变量赋初值,通常为0.博主没有提及~~~~
首先很高兴遇到如此有爱的博主!本人新手,按照博主的方法步骤自己动手进行了”计算器程序“的编码,可是最后程序我一按”计算“按钮时,程序就退了,根本没看到计算结果!求博主赐教!谢谢!MagicT 于
21:22:20 回复同求。若旖若旎 于
14:33:18 回复你能出来计算器的窗口不容易了,我出不来窗口,生成都成功了,要出现计算器的窗口只能点测试窗口这个按钮,你是这么做的吗,方便加QQ互相沟通吗?
很详细很好的东西 不过文章中的代码好像没办法复制 要是能给代码就好了鸡啄米 于
23:25:08 回复可能有的浏览器不能复制,ie是没有问题的
添加完变量m_edtSummand后,如何再修改他呢.鸡啄米 于
23:26:10 回复通过UpdateData(TRUE)可以把被加数读到m_editSummand里
每章必看,感谢楼主
学到了很多,多谢米哥
为什么编译时会出现一个error说“UpdateData”找不到标识符?求解
发现打错一个字母了,不好意思
博主讲的真的非常通俗易懂,正在学VC,按照博主讲解已经成功运行加法运算器了,特留言支持下鸡啄米 于
22:23:13 回复加油,欢迎常来交流
自从发现米哥这些个博文,发现自己有救了,怎么就没有早点看到呢!
再顶一个!
我想请教一下,我按着你的步骤做了,但是当我按下“计算”按钮的时候,“和”不会显示出来。这是为什么?落叶 于
00:25:21 回复我也遇到相同情况,你的解决了吗??浅唱清明 于
22:11:56 回复一样…………在查是什么情况艾可 于
19:54:41 回复我也遇到了,有解决的嘛侯侯侯 于
12:58:19 回复111侯侯侯 于
12:59:31 回复请问问题是怎么解决的
讨论的qq群号码是多少呀?
非常详细易懂,努力学习中,不过刚照着您的步骤一直写下来,发现很多个未定义标识符,请问这是怎么回事呢~
IDC_SUMMAND_EDIT
IDC_ADDEND_EDIT
IDC_SUM_EDIT未定义标识符是什么意思Mr.Soda 于
10:56:15 回复我也是在dodataexchange方法里变量没办法被识别不知道为什么明明include&additiondlg&里面有关于public:m_editSum/m_editSummand/m_editAddend三个变量的声明必须在这个方法里在声明一遍才行求指导橘子 于
9:38:45 回复未声明的标识符要怎么解决啊?我运行下来也显示这个
群在哪里没看到
error C2065: '_UNKNOWN_RESOURCE_ID_' : undeclared identifier 求楼主,这是怎么了?
你好,为什么我照着你的坐下来,运行程序显示生成成功,但是为啥点计算按钮没反应,能帮忙解答下吗?min 于
20:12:03 回复我上次也是这样。我是因为创建对话框类的时候基类选了CDialog而不是CDialogEx
可不可以把文章打个包,方便大家下载!求包啊!!!!!出书也行!!!!
谢谢博主,真心有收获。
31楼说得很合我意有木有。博主写得很认真,看得很有收获。谢啦
CWnd::UpdateData(0);只有这么写才行UpdateData(TURE);会报错
十分感谢您这一系列文章,帮助刚入门的我们学习MFC,十分有用,谢谢楼主
我才mfc第一章看过来,楼主太棒了,受益匪浅!
按照楼主的步骤运行成功。断线木偶 于
13:48:28 回复求你代码看看好吗?
运行程序显示生成成功,但是为啥点计算按钮没反应,求博主指教!!!阿萨德 于
2:20:59 回复同求!
楼主一生平安,到处都是6.0的,就只在这里找到VS2010的了,建议楼主出个视频吧
楼主太棒了,大作业有救O(∩_∩)O~,求问点计算不显示和是怎么回事??
我有问题,按照指示操作,然后点了调试以后,计算器不出来,出来的是一个WINDOWS的窗口,左边文件视图中有FakeApp文件,下层有关于FakeApp的源文件头文件和资源文件等,中间是白色的框什么都没有,右边是关于外观字体杂项的选项。不是计算器的那个窗口啊,怎么实现,求回复,我弄了两天了出不来效果,求大神回复。123 于
13:08:11 回复这个……你应该选的单文档吧,初学都会犯……小龟 于
10:16:39 回复我这个问题解决了,最初新建项目时,应用程序的类型要选择“给予对话框”,不是楼主最初介绍篇里选择的单个文档。
今天刚学习vc,通过教程已经可以实现,谢谢楼主断线木偶 于
13:47:23 回复谁有做出来的程序啊
我怎么按着步骤做的
最后点计算整个程序都崩溃了?谁做出来分享下好吗?
如果我想实现,一边输入加数和被加数,一边立即产生计算结果,该怎么做呢?tinycell 于
21:22:28 回复为IDC_EDIT 添加 消息EN_CHANGE与绑定方法OnEnChangeEdit();内容和方法OnBnClickedAddButton() 一样
请问一下博主,程序运行的时候caption全部不显示汉字,都变成了“?”是怎么回事?要怎么修改?我用的是VS2008.
博主,我后悔这么晚才看到你的博文,哎博主好人啊,感谢博主,好人一生平安!
我昨天看到并操作到第八部分,今天继续操作时给 button添加消息处理函数时各种不行,用Class Wizard没有 add handler,用Add Event Handler,没有 Add and Edit,强行双击才进入的。写好相关代码后运行就出错了,显示1个无法解析的外部命令,对应的错误为 #1015。瞎折腾了一阵后发现实在调试不过来就重新建了一个工程重来的,重来后才运行正确。
刚开始学,很棒的入门材料!感谢分享!
请问这个“退出”按钮的消息处理函数应该怎么写啊?yy 于
10:16:04 回复在“退出”按钮的消息处理函数里加下面一句话就行: CDialogEx::OnCancel();
博主,怎么让edit control初始值为空啊?把定义的初值改成null没用啊。我有强迫症,计算器开始不想先把0删了在输入啊
这个教程做的太好了,博主公布个微信号或支付宝吧,我想捐赠,祝越办越好。
很适合初学者。虽然刚接触MFC,但是看了文章,感觉收获很大!支持老师的文章kaysarjan 于
16:44:04 回复51楼,能不能交流一下,我也是初学者,有些地方不是很懂。我qq
为什么我按照你的步骤,点击计算无效,我看了下因为我的VS2010中没有OnBnClickedStaticCalculate,所以用的OnStnClickedStaticCalculate
楼主,为什么我运行后的界面是完全不一样的界面呢?点了运行以后,计算器界面不出来,出来的是一个WINDOWS的窗口,左边显示类视图,下面是FakeApp类,下层有关于FakeApp的源文件头文件和资源文件等,中间是白色的框什么都没有,右边是外观字体杂项的选项。不是计算器的那个窗口啊,上面有人问了同样的问题,有人答复说是选了单文档的问题,但是我没有选单文档也是同样的错误界面,怎么实现,求大神回复。小龟 于
10:12:53 回复我这个问题解决了,最初新建项目时,应用程序的类型要选择“给予对话框”,不是楼主最初介绍篇里选择的单个文档。
小弟初学用的vs2005 是在智能设备上做的mfc应用程序
在编辑框输入数字需要自定义一个键盘吧,楼主有没有相关的课程,感谢楼主的奉献
绝壁好贴呀!!!楼主,爱你!
一期期的都使好文,和其他人得感觉相同,好多其他书啊文章啊看得头疼还不明白,比较看博主的文就是一种享受了,每期解决一个问题,有问题的地方看相应的版块即可。
求解:点击计算无反应!
为什么编译的时候说UpdataData是未定义的表示标识符呢?该怎么声明UpdataData()成员函数?
好贴。喜欢。一切都是好的,能计算。就是初始的框出来显示都为0是怎么弄???daydayup 于
16:40:26 回复你好 请问我为什么按照这个方法点击计算没有反应呢
搞了半天终于算出来了,很奇怪写函数之前明明已经添加了变量,结果显示m_editAddend未定义标识符,于是我又重新去添加了一次
怎么没有变量定义的那段啊,变量怎么弄个的啊
好嘛,在前面的,跳过了
为什么我的数字 都是直接拼接的字符串啊 1.2+1=11.2xiecan 于
16:13:09 回复厉害了,没看到数据类型
写的很全面,最近一直在看。现在遇到了一个问题,关于MFC对话框按钮如何一键打开bat文件,因为bat文件运行时要弹出dos框,需要多次输入参数,这就失去了我要实现的一键启动功能的意义,期待您予以解答或做一期专辑。谢谢!
为什么我完全按步骤来,运行后界面能出来,但点击计算按钮一点反应都没有,到底是哪里出了问题!!??静镜听余生 于
14:55:27 回复我前两天也是这样的情况,后来才发现是没有添加函数的问题,你在检查一下你的函数番茄啊啊啊啊 于
11:43:40 回复为什么我完全按步骤来,运行后界面能出来,但点击计算按钮一点反应都没有?如何添加函数?
原来我点计算没有反应是因为错用了静态文本框添加变量,改过来之后重新生成代码编译之后就好了
非常感谢,而且看得出来这个网页界面也做得很用心!再次致以崇高的敬意!
massage里没有BN_CLICED怎么办
运行后界面能出来但是点击计算没反应!有没有能够qq交流一下原因的啊。。
我在单文档中调用对话框传参数,domodal()了一次,运行后却弹出了两个一样的重叠的对话框,叠在底层的对话框能实现功能,但是在上层的对话框如果不输入数据直接关闭的话,代码行k = abs(dy / dx);旁显示“ 0x 处有未经处理的异常(在 Line.exe 中): 0xC000041D: 用户回调期间遇到未经处理的异常。。”,这是为什么呢???k,dy,dx都是int型。清弦 于
22:41:30 回复前面我说错了,是第一个对话框输入了数据点了确定后才弹出第二个一摸一样的对话框的,不是一次出来两个的
这些 m_editSum 是在哪里定义的啊?初学小白真的不懂
完全随机文章基于MFC对话框的键盘消息响应 WM_KEYDOWN
WM_CHAR消息
PreTranslateMessage作用和使用方法
PreTranslateMessage是消息在送给TranslateMessage函数之前被调用的,绝大多数本窗口的消息都要通过这里,比较常用,当需要在MFC之前处理某些消息时,常常要在这里添加代码.
MFC消息控制流最具特色的地方是CWnd类的虚拟函数PreTranslateMessage(),通过重载这个函数,可以改变MFC的消息控制流程,甚至可以作一个全新的控制流出来。只有穿过消息队列的消息才受PreTranslateMessage()影响,采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息根本不会理睬PreTranslateMessage()的存在。
是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。
传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。可以在该函数中使用(pMsg-&wParam==VK_RETURN)来拦截回车键。wParam中存放的是键盘上字符的虚拟码。
PeekMessage和GetMessage的区别:
GetMessage在没有消息的时候等待消息,cpu当然低
PeekMessage没有消息的时候立刻返回,所以cpu占用率高。
因为游戏不能靠windows消息驱动,所以要用PeekMessage();
PretranslateMessage的实现,不得不谈到MFC消息循环的实现。MFC通过CWinApp类中的Pumpmessage函数实现消息循环,但是实际的消息循环代码位于CWinThread中,CWinApp只是从CWinThread继承过来。其简化后的代码大概如下:
1   BOOL CWinThread::PumpMessage()
3   _AFX_THREAD_STATE *pState = AfxGetThreadState();
5   ::GetMessage(&(pState-&m_msgCur), NULL, NULL, NULL))
7   if (!AfxPreTranslateMessage(&(pState-&m_msgCur)))
9   ::TranslateMessage(&(pState-&m_msgCur)); 10   ::DispatchMessage(&(pState-&m_msgCur)); 11   } 12   return TRUE; 13   }
可以看到,PumpMessage在实际的TranslateMessage和DispatchMessage发生之前会调用AfxPreTranslateMessage,AfxPreTranslateMessage又会调用CWnd::WalkPreTranslateTree(虽然也会调用其他函数,但是这个最为关键),其代码如下:
1 BOOL PASCAL CWnd::WalkPreTranslateTree(HWND hWndStop, MSG* pMsg)
3   ASSERT(hWndStop == NULL || ::IsWindow(hWndStop));
4   ASSERT(pMsg != NULL);
6   // walk from the target window up to the hWndStop window checking
7   // if any window wants to translate this message
9   for (HWND hWnd = pMsg-& hWnd != NULL; hWnd = ::GetParent(hWnd)) 10   { 11   CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); 12   if (pWnd != NULL) 13   { 14   // target window is a C window 15   if (pWnd-&PreTranslateMessage(pMsg)) 16   return TRUE; // trapped by target window (eg: accelerators) 17   } 18    19   // got to hWndStop window without interest 20   if (hWnd == hWndStop) 21   break; 22   } 23   return FALSE; // no special processing 24   }
可以看到,代码还是很直接的。从接受到消息的窗口层层往上遍历,并调用PretranslateMessage看是否返回TRUE,是则结束,否则继续。
  这里有一个地方非常关键:CWnd *pWnd = CWnd::FromHandlePermanent(hWnd) 这一句代码从当前AfxModuleThreadState拿到Permanent句柄表,从而找到hWnd对应的CWnd MFC中PreTranslateMessage是GetMessage(...)函数的下一级操作,即GetMessage(...)从消息队列中获取消息后,交由PreTranslateMessage()处理,若其返回FALSE则再交给TranslateMessage和DispatchMessage处理(进入WindowProc);
如果用SendMessage,
则消息直接交到WindowProc处理,所以GetMessage不会取得SendMessage的消息,当然PreTranslateMessage也就不会被调用。
如果用PostMessage,则消息进入消息队列,由GetMessage取得,PreTranslateMessage就有机会进行处理。
windows消息处理机制是这样的:
首先系统(也就是windows)把来自硬件(鼠标,键盘等消息)和来自应用程序的消息
放到一个系统消息队列中去. 而应用程序需要有自己的消息队列,也就是线程消息队列,每一个线程有自己的消息队列,对于多线程的应用程序就有和线程数目相等的线程消息队列.
windows消息队列把得到的消息发送到线程消息队列,线程消息队列每次取出一条消息发送到指定窗口,不断循环直到程序退出实现的.这个循环就是靠消息环(while(GetMessage())
TranslateMessage();DispatchMessage();.GetMessage()只是从线程消息中取出一条消息,TranslateMessage()把virtue key消息转化成character消息,如VK_F1会转化成WM_HELP,而DispatchMessage
则把取出的消息发送到目的窗口.如果收到WM_CLOSE消息则结束循环,发送postqiutmessage(0),处理WM_DESTROY销毁窗口!
while (GetMessage(&msg, NULL, 0, 0))
//C++ code
TranslateMessage(&msg);
DispatchMessage(&msg);
在 win32 程序中,关于消息有两种传递方式:
MFC 消息, MFC 会把所有的消息一条条放到一个 AFX_MSGMAP_ENTRY 结构中,形成一个数组,该数组存放了所有的消息和与
它们相关的参数。也可以说是放到消息队列里去。
采用 SendMessage() 或其他类似的方式向窗口直接发送的而不经过消息队列的消息。
这两种方式中只有第一种(穿过消息队列的消息)才受 PreTranslateMessage() 影响,
第二种消息并不会理睬 PreTranslateMessage() 的存在。
是否调用 TranslateMessage() 和 DispatchMessage() 是由一个名称为 PreTranslateMessage() 函数的返回值决定的,如果该函数返回
TRUE ,则不会把该消息分发给窗口函数处理。
传给 PreTranslateMessage() 的消息是未经翻译过的消息,它没有经过 TranslateMessage() 处理。可以在该函数中使用
(pMsg-&wParam==VK_RETURN) 来拦截回车键。
在 WindowProc 里不能处理 WM_Char 消息。( WindowProc 函数见 MFC 消息响应机制一文)
SetWindowText 会发送 WM_Char 给窗口。
PeekMessage 和 GetMessage 的区别:
GetMessage 在没有消息的时候等待消息, cpu 当然低
PeekMessage 没有消息的时候立刻返回,所以 cpu 占用率高。因为游戏不能靠 windows 消息驱动,所以要用 PeekMessage();
另一篇文章中:
在一个 WIN32 程序中, WINDOWS 会将消息传递给相应的窗口。但是消息不是立即就被传递给相应的窗口,而是会从整个程序最顶层
的窗口传递到下一级窗 口,再传递到下一级窗口,直到传递给目标窗口。在整个过程中,有些消息,在某些特定的情况下,无法默认传递到目
标窗口的。比如用户在 EDIT 控件中按下回 车键, CANCEL 键等,如果 EDIT 窗口之前有对话框窗口,对话框会默认处理回车消息(即响应
ONOK 函数,然后关闭对话框),然后退出消息传递。所以 EDIT 会收不到。要解决这个问题,可以在 EDIT 窗口之前所有的对话框中重载
PreTranslateMessage 函数,然后在函数内加上:
if (pMsg-&message==WM_KEYDOWN && pMsg-&wParam==VK_RETURN)
// 如果消息类型为WM_KEYDOWN 并且用户按下的是回车
return FALSE;
// 不翻译消息,直接将消息传递下去。具体可查 MSDN 。注意,这里返回值不能为TRUE , TRUE 的意思是翻译消息后退出消
息传递,如此一来虽然也能避开对话框默认处理,但是会退出消息传递,这样 EDIT 控件照样得不到消息。
如此,就可避开对话框默认处理,将消息传递下去。注意:只有对话框才会默认处理按下回车,CANCEL 消息,其他控件窗口则不会,所以在其
他窗口中不必重载 PreTranslateMessage 函数,当然如果重载了也不会错。
附:关于 PreTranslateMessage() 函数的小程序示例:
1 BOOL CSearchuserDlg::PreTranslateMessage(MSG* pMsg)
if (pMsg-&message==WM_KEYDOWN)
// 判断是否有按键按下
switch (pMsg-&wParam)
case VK_DOWN:
// 表示是方向键中的向下的键 15
//add handle code here 17
break ; 19
case VK_UP:
// 表示是方向键中的向上的键 21
//add handle code here 23
break ; 25
default : 27
break ; 29
37 BOOL CMyDlg::PreTranslateMessage(MSG* pMsg) 38 { 39
// TODO: Add your specialized code here and/or call the base class
// 按键相应 42
if (pMsg-&message == WM_KEYDOWN) 43
if (pMsg-&wParam == VK_DOWN) 45
// 向下键按下 47
else if (pMsg-&wParam == VK_RIGHT) 49
// 向右键按下 51
else if (pMsg-&wParam == VK_LEFT) 53
// 向左键按下 55
else if (pMsg-&wParam == VK_UP) 57
// 向上键按下 59
else if (pMsg-&wParam == VK_SHIFT) 61
//VK_LSHIFT 为左 Shift 键按下 63
//Shift 键按下 64
else if (pMsg-&wParam == VK_CONTROL) 66
//Ctrl 键按下 68
else if (pMsg-&wParam&=VK_NUMPAD0 && pMsg-&wParam&=VK_NUMPAD9) 70
// 小键盘数字键按下 72
else if (pMsg-&wParam&=0x30 && pMsg-&wParam&=0x39) 74
// 数字键按下 ( 我记得不能使用 VK_0) 76
else if (pMsg-&wParam&=0x41 && pMsg-&wParam&=0x5A) 78
// 键盘字母键按下 ( 我记得不能使用 VK_A) 80
else if (pMsg-&wParam == VK_BACK) 82
// 退格键按下 84
else if (pMsg-&wParam == VK_DELETE) 86
// 删除键按下 88
else if (pMsg-&wParam == VK_F1) 90
//F1 键按下 92
// 使消息不再进行处理 95
if (pMsg-&message == WM_KEYUP) 98
if (pMsg-&wParam == VK_SHIFT)100
//Shift 键弹起102
else if (pMsg-&wParam == VK_CONTROL)104
//Ctrl 键弹起106
// 使消息不再进行处理108
return CDialog::PreTranslateMessage(pMsg);111 }112 113 // 同时按下 ctrl 键114 BOOL
CDemo_DevStudioView::PreTranslateMessage(MSG*
// 根据键盘上的按键对图形进行相应的操作
if (pMsg-&message==256)
256 有键按下, 46
switch (pMsg-&wParam)
/// 向左键被按下
// 同时按下了 CTRL 键
if (::GetKeyState(VK_CONTROL)
本文转自:
没有更多推荐了,}

我要回帖

更多关于 简约对话框文字壁纸 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信