您的位置:首页 > 其它

PreTranslateMessage作用和使用方法

2012-06-02 16:37 435 查看
PreTranslateMessage作用和使用方法

函数原型:virtual BOOL PreTranslateMessage( MSG *pMsg)

1、在MFC中,PreTranslateMessage是虚函数,是用来截获消息的。我们可以通过重载它来处理键盘和鼠标消息。在sdk中,这有所不同,我们必须在回调函数 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)中处理消息。它和PreTranslateMessage起的作用是类似的,只是MFC封装的更好而已。

2、重载该函数可以实现窗口消息在派发给窗口函数TranslateMessage()和DispatchMessae()之前的过滤,缺省的实现是完成加速键的翻译。

3、 该函数表示在消息处理(TranslateMessge()和DispatchMessage()等)前所作的操作,如果函数返回值为TRUE,那么消息 处理即终止,不会调用TranslateMessge()和DispatchMessage()来翻译和分发消息给相应的窗口;若返回值为FALSE,才 会调用翻译和分发消息函数。

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

a. MFC消息,MFC会把所有的消息一条条放到一个AFX_MSGMAP_ENTRY结构中,形成一个数组,该数组存放了所有的消息和与它们相关的参数。也可以说消息是放到消息队列里去了。

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

这两种方式中只有第一种(穿过消息队列的消息)才受PreTranslateMessage()影响,第二种消息并不会理睬PreTranslateMessage()的存在。

一、是否调用TranslateMessage()和DispatchMessage()是由PreTranslateMessage()函数的返回值决定的,如果该函数返回TRUE,则不会把该消息分发给窗口函数处理。

二、传给PreTranslateMessage()的消息是未经翻译过的消息,它没有经过TranslateMessage()处理。例如:可以在该函数中使用(pMsg->wParam == VK_RETURN)来拦截回车键,其中wParam中存放的是键盘上字符的虚拟码。

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

BOOL CSearchuserDlg::PreTranslateMessage(MSG* pMsg)

{

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

{

switch(pMsg->wParam)

{

case VK_DOWN: //表示是方向键中的向下的键

//add handle code here

break;

case VK_UP: //表示是方向键中的向上的键

//add handle code here

break;

default:

break;

}

}

}

**********************************************************************

PeekMessage 一般是用来重载消息循环,避免程序停止响应。

举例:

MSG msg;

if(::PeekMessage(&msg,NULL,0,0,PM_REMOVE)){

if(msg.message==WM_QUIT)

{

::PostQuitMessage(-1);

}

if(!AfxGetApp()->PreTranslateMessage(&msg))

{

::TranslateMessage(&msg);

::DispatchMessage(&msg);

}

}

******************************************************************************

界面上有很多个控件,如edit,如何知道当前的焦点是在哪个控件上面?

1. GetFocus()可以得到当前控件的句柄, 你再枚举子窗口句柄判断, 跟得到的句柄一致的即为哪个被点中。

2. CWnd* pCtrl = CWnd::GetFocus();

int iCtrlID = pCtrl->GetDlgCtrlID();

if(iCtrlID == IDC_EDIT1)

{

}

else if(iCtrlID == IDC_EDIT2)

{

}

...

3. GetFocus() 功能:确定当前焦点位于哪个控件上。函数执行成功时返回当前得到焦点控件的窗口句柄,发生错误时返回无效引用。

用法: 应用程序利用IsValid()函数可以检测GetFocus()是否返回有效的控件引用。同时,使用TypeOf()函数可以确定控件的类型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: