1. 程式人生 > 其它 >MFC中非模態對話方塊不響應PreTranslateMessage函式的解決方法 (勾子)

MFC中非模態對話方塊不響應PreTranslateMessage函式的解決方法 (勾子)

MFC中非模態對話方塊不響應PreTranslateMessage函式的解決方法

EffortForever

於 2015-10-26 22:37:17 釋出

MFC


程式設計師真心不容易啊,為了一個好的使用者體驗真可謂是操碎了心。今天由於專案需要,需要在非模態對話方塊上,當滑鼠處於某個位置的時候有提示框顯示。
實現這個功能本來很簡單,但是卻遇到了一個鬱悶的問題:PreTranslateMessage函式沒響應。於是各種度娘,可惜度娘非谷歌,找了一個小時終於在一個隱蔽的地方找到了解決方法。

首先我介紹下當滑鼠處於特定位置的時候有提示資訊顯示的實現方法。

需要使用MFC的CToolTipCtrl控制元件。

1.首先在Dialog類中新增一個成員物件

 

//訊息提示框
CToolTipCtrl m_toolTip;</span></span>

2.在OnInitDialog()函式中建立訊息提示框

//建立訊息提示框
EnableToolTips(TRUE);//enable use it
BOOL bRet = m_toolTip.Create(this, TTS_ALWAYSTIP | WS_CHILD | WS_VISIBLE);
m_toolTip.AddTool(this);
m_toolTip.Activate(TRUE);
m_toolTip.SetDelayTime(150);</span></span>

3.捕獲滑鼠的移動訊息OnMouseMove,當滑鼠處在某一特定區域的時候,彈出訊息提示框。切換訊息內容使用CToolTipCtrl::UpdateTipText函式。

void CDisplayPicDlg::OnMouseMove(UINT nFlags, CPoint point)
{
//如果滑鼠在矩形所在區域,需要把箭頭滑鼠變成手型的
int iSel = GetSelectCameraNo(point);
if(-1 != iSel)
{
SetCursor(LoadCursor(NULL, IDC_HAND));
m_toolTip.UpdateTipText(m_stMonitorCamera[iSel].szCamereName, this);
}
else//還原成箭頭滑鼠形式
{
SetCursor(LoadCursor(NULL, IDC_ARROW));
m_toolTip.UpdateTipText("", this);
}
if(-1 != m_lCameraIdPre)
{
SetCursor(LoadCursor(NULL, IDC_ARROW) );
}
//.....................
}
4.重寫基類的PreTranslateMessage函式

BOOL CDisplayPicDlg::PreTranslateMessage(MSG* pMsg)
{
m_toolTip.RelayEvent(pMsg);
return CDialog::PreTranslateMessage(pMsg);
}
<span style="font-family:Arial;BACKGROUND-COLOR: #ffffff"></span>
好了,做到這四部就基本完成了。當自己滿懷資訊一執行發現根本沒有彈出提示資訊。經過除錯發現,PreTranslateMessage函式並沒有被呼叫,於是引出了重要的主題,非模態對話方塊如何響應PreTranslateMessage函式的問題。經過一番百度,終於找到了解決方法。

在MFC的App類中需要用Hook來勾取訊息,需要注意的是GetMessageProc是個回撥函式,所以我們需要將它設成類的靜態成員函式。

即:

class CStaticMapGPSApp : public COleControlModule
{
public:
BOOL InitInstance();
int ExitInstance();
static LRESULT CALLBACK GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam);

HHOOK m_hHook;
protected:

};

LRESULT CALLBACK CStaticMapGPSApp::GetMessageProc(int nCode, WPARAM wParam, LPARAM lParam)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
LPMSG lpMsg = (LPMSG) lParam;

if(AfxGetApp()->PreTranslateMessage(lpMsg))
{
lpMsg->message = WM_NULL;
lpMsg->lParam = 0L;
lpMsg->wParam = 0;
}

// Passes the hook information to the next hook procedure in
// the current hook chain.
return ::CallNextHookEx(theApp.m_hHook, nCode, wParam, lParam);
}

// CStaticMapGPSApp::InitInstance - DLL initialization

BOOL CStaticMapGPSApp::InitInstance()
{
BOOL bInit = COleControlModule::InitInstance();

if (bInit)
{
// TODO: Add your own module initialization code here.
m_hHook = ::SetWindowsHookEx(
WH_GETMESSAGE,
GetMessageProc,
AfxGetInstanceHandle(),
GetCurrentThreadId());

ASSERT (hHook);
return CWinApp::InitInstance();
}

return bInit;
}



// CStaticMapGPSApp::ExitInstance - DLL termination

int CStaticMapGPSApp::ExitInstance()
{
// TODO: Add your own module termination code here.
UnhookWindowsHookEx((HHOOK)m_hHook);
return COleControlModule::ExitInstance();
}

此時才算是打工告成,資訊彈出框如願以償的彈出了。
————————————————
版權宣告:本文為CSDN博主「EffortForever」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處連結及本宣告。
原文連結:https://blog.csdn.net/lqlblog/article/details/49430721