Search code examples
c++windowsuser-interfacewxwidgets

How to distinguish a button and a checkbox message on Windows?


I have the Windows event values that for example the DefWindowsProc() gets -- i.e. hWnd, MsgId, wParam, lParam. Is it possible to distinguish whether the WM_COMMAND event with notification code BN_CLICKED comes or from a push button, or from a check box (or possibly from some other)?

Motivation: I am rewriting the GUI implementation and message handling in a bigger application. The final goal is wxWidgets, but I have to do it gradually. I do mimick the BEGIN_EVENT_TABLE/END_EVENT_TABLE macros and the related EVT_BUTTON, EVT_CHECKBOX (..., EVT_SIZE, EVT_PAINT and the like). I am also mimicking classes like wxCommandEvent, and I would like to set its type to the equivalent of wxEVT_COMMAND_BUTTON_CLICKED or wxEVT_COMMAND_CHECKBOX_CLICKED when the event is captured by the original code.

For example: I have a macro like this

#define EVT_CHECKBOX(id, func) \
    if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \
    { \
        CAppCommandEvent evt(hWnd, uMsg, wParam, lParam); \
        ATLASSERT(evt.GetEventType() == appEVT_COMMAND_CHECKBOX_CLICKED); \
        func(evt); \
        lResult = evt.GetLResult(); \
        if (!evt.GetSkipped()) \
            return TRUE; \
    }

The wxEVT_COMMAND_CHECKBOX_CLICKED is intentionally renamed to appEVT_.... I want to be able to check whether the EVT_CHECKBOX macro was not used (by mistake) for a button. If yes, the assert command must make it visible for the debug version of the program.


Solution

  • Nothing in the message itself can serve you to identify the type of button. However, in theory you should still be able to find it out indirectly. The lParam gives you the window handle of the control, which you can use with GetWindowLong to obtain the button style.

    LONG style = ::GetWindowLong(lParam, GWL_STYLE);
    if (style & BS_CHECKBOX) {
        // It's a checkbox
    }