Hook woes
-
I have set up an application hook procedure. This hook is looking for WM_INITMENUPOPUP, WM_MEASUREITEM and WM_DRAWITEM messages so that I can make all menus shown by the application ownerdrawn. The hook does catch these as required, but its the actual processing of the message I am having trouble with. For example. My WM_MEASUREITEM handler correctly measures the menu item and returns the correct size, yet when I get to the WM_DRAWITEM message to draw it, the size comes through as 12 * 16, which is the default size of a menu item which has not been measured (not processed WM_MEASUREITEM). It looks like I cannot modiy the MEASUREITEM struct members in the hook procedure and have the application use these values. I have tried both the WH_CALLWNDPROC and WH_CALLWNDPROCRET hook methods for before/after porcessing of the message, but regardless the system is not using the sizes I measure for the items. Anyone know of this problem or how to get around it? The docs on hooks are pretty sparse. I would also like to know whether is possible from within the hook procedure to stop the application processing the message as I have already done the work in the hook procedure. If you vote me down, my score will only get lower
-
I have set up an application hook procedure. This hook is looking for WM_INITMENUPOPUP, WM_MEASUREITEM and WM_DRAWITEM messages so that I can make all menus shown by the application ownerdrawn. The hook does catch these as required, but its the actual processing of the message I am having trouble with. For example. My WM_MEASUREITEM handler correctly measures the menu item and returns the correct size, yet when I get to the WM_DRAWITEM message to draw it, the size comes through as 12 * 16, which is the default size of a menu item which has not been measured (not processed WM_MEASUREITEM). It looks like I cannot modiy the MEASUREITEM struct members in the hook procedure and have the application use these values. I have tried both the WH_CALLWNDPROC and WH_CALLWNDPROCRET hook methods for before/after porcessing of the message, but regardless the system is not using the sizes I measure for the items. Anyone know of this problem or how to get around it? The docs on hooks are pretty sparse. I would also like to know whether is possible from within the hook procedure to stop the application processing the message as I have already done the work in the hook procedure. If you vote me down, my score will only get lower
Are you assigning lpMeasureItemStruct->itemHeight the new height?
void CMyView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) { ... ... ... lpMeasureItemStruct->itemHeight = nNewHeight; ... ... ... }
-
Are you assigning lpMeasureItemStruct->itemHeight the new height?
void CMyView::OnMeasureItem(int nIDCtl, LPMEASUREITEMSTRUCT lpMeasureItemStruct) { ... ... ... lpMeasureItemStruct->itemHeight = nNewHeight; ... ... ... }
Yes I am. I TRACE out the values in the hook function after the OnMeasureItem() has been called. This is a variation of my owner drawn menu plug-in article so I know all the measureitem/draw item stuff works. I am just chaning it from a plug in to a hook so that it will work for all standard WIN32 programs. If I get it working it will become another article. Here is some of the code:
LRESULT CALLBACK CODMenu::HookFunction(int code, WPARAM wParam, LPARAM lParam)
{
CWPSTRUCT * cwpStruct = (CWPSTRUCT*)(lParam);ASSERT(m\_activeObject != NULL); switch (cwpStruct->message) { case WM\_MEASUREITEM: { LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)(cwpStruct->lParam); m\_activeObject->OnMeasureItem(cwpStruct->wParam, lpMIS); TRACE("Measure Item is %1d by %1d\\n", lpMIS->itemWidth, lpMIS->itemHeight); } break; case WM\_DRAWITEM: { m\_activeObject->OnDrawItem(cwpStruct->wParam, (LPDRAWITEMSTRUCT)(cwpStruct->lParam)); TRACE("WM\_DRAWITEM\\n"); } break; } return ::CallNextHookEx(m\_hookHandle, code, wParam, lParam);
}
LRESULT CALLBACK CODMenu::HookFunctionAfter(int code, WPARAM wParam, LPARAM lParam)
{
CWPRETSTRUCT * cwpretStruct = (CWPRETSTRUCT*)(lParam);ASSERT(m\_activeObject != NULL); switch (cwpretStruct->message) { case WM\_INITMENUPOPUP: { m\_activeObject->OnInitMenuPopup(CMenu::FromHandle((HMENU)cwpretStruct->wParam), LOWORD(cwpretStruct->lParam), (BOOL)HIWORD(cwpretStruct->lParam)); TRACE("WM\_INITMENUPOPUP\\n"); } break; case WM\_MEASUREITEM: { LPMEASUREITEMSTRUCT lpMIS = (LPMEASUREITEMSTRUCT)(cwpretStruct->lParam); TRACE("After Measure Item is %1d by %1d\\n", lpMIS->itemWidth, lpMIS->itemHeight); } break; } return ::CallNextHookEx(m\_hookHandleAfter, code, wParam, lParam);
}
And the TRACE output is
WM_INITMENUPOPUP
Measure Item is 99 by 19
Warning: unknown WM_MEASUREITEM for menu item 0xE100.
After Measure Item is 0 by 16
Measure Item is 116 by 19
Warning: unknown WM_MEASUREITEM for menu item 0xE101.
After Measure Item is 0 by 16
Measure Item is 66 by 19
Warning: unknown WM_MEASUREITEM for menu item 0xE102.
After Measure Item is 0 by 16
Measure Item is 102 by 19
Warning: unknown WM_MEASUREITEM for menu item 0xE103.
After Measure Item is 0 by 16
Measure Item is 94 -
I have set up an application hook procedure. This hook is looking for WM_INITMENUPOPUP, WM_MEASUREITEM and WM_DRAWITEM messages so that I can make all menus shown by the application ownerdrawn. The hook does catch these as required, but its the actual processing of the message I am having trouble with. For example. My WM_MEASUREITEM handler correctly measures the menu item and returns the correct size, yet when I get to the WM_DRAWITEM message to draw it, the size comes through as 12 * 16, which is the default size of a menu item which has not been measured (not processed WM_MEASUREITEM). It looks like I cannot modiy the MEASUREITEM struct members in the hook procedure and have the application use these values. I have tried both the WH_CALLWNDPROC and WH_CALLWNDPROCRET hook methods for before/after porcessing of the message, but regardless the system is not using the sizes I measure for the items. Anyone know of this problem or how to get around it? The docs on hooks are pretty sparse. I would also like to know whether is possible from within the hook procedure to stop the application processing the message as I have already done the work in the hook procedure. If you vote me down, my score will only get lower
To stop further processing of the message, have your hook procedure return 1 (one) instead of calling CallNextHook
LRESULT CALLBACK MyHook(int nCode, WPARAM wp, LPARAM lp)
{
...
return 1;
}
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
-
To stop further processing of the message, have your hook procedure return 1 (one) instead of calling CallNextHook
LRESULT CALLBACK MyHook(int nCode, WPARAM wp, LPARAM lp)
{
...
return 1;
}
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
Hi PJ, I have tried what you suggested. It does stop any further hook procedures being called, but it does not stop the target window from processing the message which is what I really need to do in this case. If I can do this, then it should clear up my main problem which is that the hook intercept WM_MEASUREITEM and returns the size of the menu item in the LPMEASUREITEMSTRUCT object. The thing is, the CWnd default handler gets a different LPMEASURITEM struct pointer to the hook procedure which means that in effect what I return in the hook is ignored. If I can suppress the target window processing WM_MEASUREITEM then I think it would accept the values returned by the hook and fix my problem. Cheers for any sugesstions If you vote me down, my score will only get lower
-
Hi PJ, I have tried what you suggested. It does stop any further hook procedures being called, but it does not stop the target window from processing the message which is what I really need to do in this case. If I can do this, then it should clear up my main problem which is that the hook intercept WM_MEASUREITEM and returns the size of the menu item in the LPMEASUREITEMSTRUCT object. The thing is, the CWnd default handler gets a different LPMEASURITEM struct pointer to the hook procedure which means that in effect what I return in the hook is ignored. If I can suppress the target window processing WM_MEASUREITEM then I think it would accept the values returned by the hook and fix my problem. Cheers for any sugesstions If you vote me down, my score will only get lower
According to MSDN, you can not modify the messages via the WH_CALLWNDPROC and WH_CALLWNDPROCRET hooks. I have used the method I suggested (return 1) in my CWindowScroller[^] class to supress user input, so I just assumed it should work for you also. Have you tried using the WH_MSGFILTER hook instead? According to MSDN you can change things via this hook.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
-
According to MSDN, you can not modify the messages via the WH_CALLWNDPROC and WH_CALLWNDPROCRET hooks. I have used the method I suggested (return 1) in my CWindowScroller[^] class to supress user input, so I just assumed it should work for you also. Have you tried using the WH_MSGFILTER hook instead? According to MSDN you can change things via this hook.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
I have tried WH_GETMESSAGE, but it doesn't get the WM_DRAWITEM and WM_MEASUREITEM messages. I eneded up going with a combination hook/WndProc replacement technique which works correctly. I should get an article up in the next few days about a new ownerdrawn menu method using 2 lines of code. An include and declaration of an object. Thanks for the help. If you vote me down, my score will only get lower
-
I have tried WH_GETMESSAGE, but it doesn't get the WM_DRAWITEM and WM_MEASUREITEM messages. I eneded up going with a combination hook/WndProc replacement technique which works correctly. I should get an article up in the next few days about a new ownerdrawn menu method using 2 lines of code. An include and declaration of an object. Thanks for the help. If you vote me down, my score will only get lower
You solved your problem, so this post is probably useless, but I have to answer anyway. From my understanding of MSDN, WH_GETMESSAGE monitors messages posted to the message queue and is called whenever the GetMessage or PeekMessage functions are called. What is probably happening is that the WM_DRAWITEM and WM_MEASUREITEM messages are never posted to the queue, but rather sent directly via the SendMessage function. The WH_MSGFILTER hook is supposed to work with menus, among others, but I do not know if it catches those two messages. Looking forward to the article.:)
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
-
You solved your problem, so this post is probably useless, but I have to answer anyway. From my understanding of MSDN, WH_GETMESSAGE monitors messages posted to the message queue and is called whenever the GetMessage or PeekMessage functions are called. What is probably happening is that the WM_DRAWITEM and WM_MEASUREITEM messages are never posted to the queue, but rather sent directly via the SendMessage function. The WH_MSGFILTER hook is supposed to work with menus, among others, but I do not know if it catches those two messages. Looking forward to the article.:)
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03 "Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04 Within you lies the power for good - Use it!
I posted it last night, so should be found on the front page. If you vote me down, my score will only get lower