2

I'm using the following code to create a button and change it's proc:

INT_PTR CALLBACK Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    //switch( LOWORD(wParam) )
    //switch( HIWORD(wParam) )
    switch (message)
    {
    case 200:
    case BN_CLICKED:
        MessageBox(NULL,NULL,NULL,NULL);
        break;

    default: return oldproc(hDlg, message, wParam, lParam);
    }
    return (INT_PTR)FALSE;
}

and

HWND handle = CreateWindowEx( NULL,
        L"button",
        L"TEXT",
        WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
        50,
        50,
        500,
        500,
        hWnd,
        (HMENU)200,
        hInstance,
        nullptr);

    oldproc = (WNDPROC)SetWindowLong(handle, GWL_WNDPROC, (LONG)Proc);

The problem is that no matter how I handle messages in Proc no messagebox is being created.

Note: commenting last line and handling it in the window proc like so:

case WM_COMMAND:
    wmId    = LOWORD(wParam);
    wmEvent = HIWORD(wParam);
    switch (wmId)
    {
    case 200:
         if(wmEvent == BN_CLICKED)
            MessageBox(NULL,NULL,NULL,NULL);
... }

works fine but I can't use this due to how I designed things.

Is there a way to get this working?

2 Answers 2

5

You don't see your message box because BM_CLICK is not a message that the button receives. It is a message you send to the button when you want it to simulate a click action.

What you are looking for is the BN_CLICKED notification instead. However, BN_CLICKED is wrapped inside of a WM_COMMAND message that is sent to the button's parent window, not to the button itself. So you need to subclass the parent window in order to receive it.

If that is not an option, then you can use a thread-specific message hook via SetWindowsHookEx() instead and have that callback look for messages being sent to the button's parent window. For example:

HWND hBtn, hBtnParent;
HHOOK hHook;

LRESULT CALLBACK BtnMsgProc(int iCode, WPARAM wParam, LPARAM lParam)
{
    if ((iCode == HC_ACTION) && (wParam == PM_REMOVE))
    {
        MSG *msg = reinterpret_cast<MSG*>(lParam);
        if ((msg->hwnd == hBtnParent) &&
            (msg->message == WM_COMMAND) &&
            (HIWORD(msg->wParam) == BN_CLICKED) &&
            (reinterpret_cast<HWND>(msg->lParam) == hBtn))
        {
            // button has been clicked...
        }
    }

    return CallNextHookEx(hHook, iCode, wParam, lParam);
}

.

hBtnParent = hWnd;
hBtn = CreateWindowEx(
    NULL,
    L"button",
    L"TEXT",
    WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON,
    50,
    50,
    500,
    500,
    hWnd,
    (HMENU)200,
    hInstance,
    NULL);

hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)BtnMsgProc, NULL, GetCurrentThreadId());
...
UnhookWindowsHookEx(hHook);
DestroyWindow(hBtn);
Sign up to request clarification or add additional context in comments.

1 Comment

1. was a typo, sorry 2. could you provide an example usage of SetWindowsHookEx ?
2

For your question about an example for SetWindowsHookEx: MSDN

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.