PreTranslateMessage详解

PreTranslateMessage详解

原文链接

1.函数原型:(MSDN)

Override this function to filter window messages before they are dispatched to the Windows functions

TranslateMessageand DispatchMessageThe default implementation performs accelerator-key translation,

so you must call theCWinApp::PreTranslateMessagemember function in youroverridden version.


virtualBOOLPreTranslateMessage(MSG*pMsg);

Parameters

pMsg :A pointer to a MSG structure that contains the message to process.

Return Value

Nonzero if the message was fully processed inPreTranslateMessageand should not be processed further.

Zero if the message should be processed in the normal way.

重载该函数可以实现窗口消息在派发给窗口函数TrnaslateMessage和DispatchMessae()之前的过滤.缺省的实现是完成加

速键的翻译.因为您必须在你的重载版本中调用CWinApp:PreTranslateMessage()函数.在MFC中,PreTranslateMessage

是虚函数,我们可以重载它来处理键盘和鼠标消息。在sdk中,这又有所不同,我们必须在回调函数中

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)处理消息:

它和PreTranslateMessage起的作用是类似的。只是MFC封装的更好而已


2.说明:

该函数表示在消息处理(TranslateMessge()DispatchMessage()等)前所作的操作,如果函数返回值为TRUE,那么消息处理即终止,

不会调用TranslateMessge()DispatchMessage()来翻译和分发消息给相应的窗口;若返回值为FALSE,才会调用翻译和分发消息函数。

该函数是MFC消息控制流最具特色的地方,它是CWnd类的虚拟函数,通过重载这个函数,我们可以改变MFC的消息控制流程,甚至可

以作一个全新的控制流出来。


win32程序中,关于消息有两种传递方式:

1.MFC消息,MFC会把所有的消息一条条放到一个AFX_MSGMAP_ENTRY结构中,形成一个数组,该数组存放了所有的消息和与

它们相关的参数。也可以说是放到消息队列里去。

2.采用SendMessage()或其他类似的方式向窗口直接发送的而不经过消息队列的消息。


这两种方式中只有第一种(穿过消息队列的消息)才受PreTranslateMessage()影响,

第二种消息并不会理睬PreTranslateMessage()的存在。

1)是否调用TranslateMessage()和DispatchMessage()是由一个名称为PreTranslateMessage()函数的返回值决定的,如果该函数返回

TRUE,则不会把该消息分发给窗口函数处理。

2)传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。可以在该函数中使用

(pMsg->wParam==VK_RETURN)来拦截回车键。

3)在WindowProc里不能处理WM_Char消息。(WindowProc函数见MFC消息响应机制一文)

4)SetWindowText会发送WM_Char给窗口。

5)PeekMessage和GetMessage的区别:

6)GetMessage在没有消息的时候等待消息,cpu当然低

7)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()函数的小程序示例:

BOOL CSearchuserDlg::PreTranslateMessage(MSG* pMsg)

{

if(pMsg->message==WM_KEYDOWN)//判断是否有按键按下

{

switch(pMsg->wParam)

{

caseVK_DOWN://表示是方向键中的向下的键

//add handle code here

break;

caseVK_UP://表示是方向键中的向上的键

//add handle code here

break;

default:

break;

}

}

}

BOOL CMyDlg::PreTranslateMessage(MSG* pMsg)

{

// TODO: Add your specialized code here and/or call the base class

//按键相应

if(pMsg->message == WM_KEYDOWN)

{

if(pMsg->wParam == VK_DOWN)

{

//向下键按下

}

elseif(pMsg->wParam == VK_RIGHT)

{

//向右键按下

}

elseif(pMsg->wParam == VK_LEFT)

{

//向左键按下

}

elseif(pMsg->wParam == VK_UP)

{

//向上键按下

}

elseif(pMsg->wParam == VK_SHIFT)

{

//VK_LSHIFT为左Shift键按下

//Shift键按下

}

elseif(pMsg->wParam == VK_CONTROL)

{

//Ctrl键按下

}

elseif(pMsg->wParam>=VK_NUMPAD0 && pMsg->wParam<=VK_NUMPAD9)

{

//小键盘数字键按下

}

elseif(pMsg->wParam>=0x30 && pMsg->wParam<=0x39)

{

//数字键按下(我记得不能使用VK_0)

}

elseif(pMsg->wParam>=0x41 && pMsg->wParam<=0x5A)

{

//键盘字母键按下(我记得不能使用VK_A)

}

elseif(pMsg->wParam == VK_BACK)

{

//退格键按下

}

elseif(pMsg->wParam == VK_DELETE)

{

//删除键按下

}

elseif(pMsg->wParam == VK_F1)

{

//F1键按下

}

//return true;//使消息不再进行处理

}

if(pMsg->message == WM_KEYUP)

{

if(pMsg->wParam == VK_SHIFT)

{

//Shift键弹起

}

elseif(pMsg->wParam == VK_CONTROL)

{

//Ctrl键弹起

}

//return true;//使消息不再进行处理

}

returnCDialog::PreTranslateMessage(pMsg);

}

//同时按下ctrl

BOOLCDemo_DevStudioView::PreTranslateMessage(MSG*pMsg)//根据键盘上的按键对图形进行相应的操作

{

if(pMsg->message==256)//256有键按下,46DEL

{

switch(pMsg->wParam)

{

///向左键被按下

case37:

{

//同时按下了CTRL

if(::GetKeyState(VK_CONTROL)<0)

{

}

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值