|
|
|
|
Forum
Please
Log In
to post a new message or reply to an existing one. If you are not registered, please
register.
NOTE: Some forums may be read-only if you are not currently subscribed to
our technical support services.
Subject |
Author |
Date |
|
Ed Nafziger
|
May 3, 2010 - 8:39 PM
|
I want to install a keyboard hook to override accelerators and menu hotkeys.
If I install a keyboard hook using SetWindows HookEx, or use CExtHookSpy, and return true instead of calling CallNextHookEx or CExtHookSpy::OnHookSpyPreTranslateMessage( pMsg ), some keyboard combinations activate the main frame menu, even if I return true to indicate I want to discard the message.
For example, if I add the following to MDIDOCVIEW sample:
added to CMainFrame::CMainFrame()
HookSpyRegister( __EHSEF_KEYBOARD | __EHSEF_PRE_TRANSLATION );
added to CMainFrame::~CMainFrame()
HookSpyUnregister( __EHSEF_KEYBOARD | __EHSEF_PRE_TRANSLATION );
added
bool CMainFrame::OnHookSpyPreTranslateMessage( MSG* pMsg )
{
if( (GetKeyState(VK_MENU) & 0x80) && pMsg->wParam == ’E’ ) // ALT+E
return true;
return CExtHookSpy::OnHookSpyPreTranslateMessage( pMsg );
}
and if I press ALT+E, the "File" item in the main frame menu gains focus and becomes activated. Shouldn’t returning true discard the entire series of keyboard up/down messages? Same thing happens for OnHookPostTranslateMessage. What am I doing wrong? Thanks...
|
|
Technical Support
|
May 4, 2010 - 1:53 PM
|
Here is the condition for the ALT key state checking:
bool bAltKeyIsPressed = ( ( HIWORD(pMsg->lParam) & KF_ALTDOWN ) == 0 ) ? false : true;
|
|
Ed Nafziger
|
May 4, 2010 - 3:20 PM
|
The issue occurs regardless of the method used to detect the ALT key press. If I replace (GetKeyState(VK_MENU) & 0x80) with ( HIWORD(pMsg->lParam) & KF_ALTDOWN ) the same issue occurs. Please see my reply mentioning the use of CMyMenuBar::g_bCancelNearestAltUp to bypass this issue. Thanks.
|
|
Technical Support
|
May 5, 2010 - 12:33 PM
|
The menu bar is not based on thread hooks. All the keyboard processing is implemented in the CExtMenuControlBar::TranslateMainFrameMessage() method which is typically invoked from the CMainFrame::PreTranslateMessage() virtual method. So, any thread wide keyboard hooks must receive the keyboard notifications earlier than menu bar will receive them. That’s why the CMyMenuBar::g_bCancelNearestAltUp flag can be set to true in your CMainFrame::OnHookSpyKeyMsg() method. But you can do the same in the CMainFrame::PreTranslateMessage() virtual method before invoking the CExtMenuControlBar::TranslateMainFrameMessage() method. I.e. you don’t need thread wide hooks.
But you also can do the same using hooks. Please take a look at the source code of the CMainFrame::OnHookSpyKeyMsg() message posted in this forum thread. We think the following line of code:
if( WM_KEYFIRST <= pMsg->message <= WM_KEYLAST )
Should be replaced with the following one: if( WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST )
|
|
Ed Nafziger
|
May 4, 2010 - 1:27 PM
|
I have a workaround that seems to fix this. I had to add CMyMenuBar::g_bCancelNearestAltUp = true before returning true in CMainFrame::OnHookSpyKeyMsg and before returning true from translating the accelerators in CMFCApp::PreTranslateMessage.
bool CMainFrame::OnHookSpyKeyMsg( MSG* pMsg )
{
if( bMacroEnable )
{
if( WM_KEYFIRST <= pMsg->message <= WM_KEYLAST )
{
if( KeyboardHookProc(HC_ACTION, pMsg->wParam, pMsg->lParam ) ) // my function to do stuff
{
CMyMenuBar::g_bCancelNearestAltUp = true; // <<-----
return true;
}
}
}
return CExtHookSpy::OnHookSpyKeyMsg( pMsg );
}
BOOL CMFCApp::PreTranslateMessage( MSG* pMsg )
{
if( TranslateMDISysAccel(hwndMDIClient, pMsg) )
{
CMyMenuBar::g_bCancelNearestAltUp = true; // <<-----
return TRUE;
}
if( TranslateAccelerator(hwndFrame, (HACCEL)hAccel, pMsg) )
{
CMyMenuBar::g_bCancelNearestAltUp = true; // <<-----
return TRUE;
}
if( ::IsDialogMessage(hWrkDlg, pMsg) )
return TRUE;
return __super::PreTranslateMessage( pMsg );
}
is there a better way to fix this?
|
|