作者:刘树伟
当我们超类化,或者使用Hook来修改菜单的时候,是和菜单的窗口句柄HWND打交道,但这时候,很难得到菜单的句柄HMENU。MFC也没有提供菜单窗口句柄HWND与菜单句柄HMENU的转换函数。
但通过分析CMenu::TrackPopupMenu的源代码,我们发现,虽然没办法直接互转HWND与HMENU,但由于TrackPopupMenu是同步阻塞模式,所以我们可以通过AfxGetThreadState,来完成这一角色互换。
BOOL CMenu::TrackPopupMenu(UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect)
{
ASSERT(m_hMenu != NULL);
_AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
HWND hWndOld = pThreadState->m_hTrackingWindow;
HMENU hMenuOld = pThreadState->m_hTrackingMenu;
pThreadState->m_hTrackingWindow = pWnd->GetSafeHwnd();
pThreadState->m_hTrackingMenu = m_hMenu;
BOOL bOK = ::TrackPopupMenu(m_hMenu, nFlags, x, y, 0, pThreadState->m_hTrackingWindow, lpRect);
pThreadState->m_hTrackingWindow = hWndOld;
pThreadState->m_hTrackingMenu = hMenuOld;
return bOK;
}
当超类化或使用Hook修改菜单的时候,在菜单窗口处理函数中处理HWND时,或者在处理WM_INITMENUPOPUP消息时。我们就可以通过AfxGetThreadState得到的_AFX_THREAD_STATE指针,来实现HWND与HMENU的互转。
pThreadState->m_hTrackingWindow:menu的宿主窗口
pThreadState->m_hTrackingMenu:menu句柄