I've created a button with the following code:
HWND hwndButton = CreateWindow(
"BUTTON", // Predefined class;
"Options", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
250, // x position
0, // y position
50, // Button width
30, // Button height
hwnd, // Parent window
NULL, // No menu.
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
NULL);
I'm aware that messages from buttons can be received in the window procedure of the parent window by doing a switch
with WM_COMMAND
and the name of the control as the case, for example, IDC_BUTTON
. However, that's only when I create buttons on dialog boxes graphically using Visual Studio's editor. When I create a button using CreateWindow
, as above, there isn't a 'name' for the control to put into a case statement.
What message is sent to the parent window when the button is pressed?
CodePudding user response:
You can specify the button's identifier value (as in the IDC_BUTTON1
control resource ID, for example, in a dialog box) as the hMenu
argument in the call to CreateWindow
.
Here's a suitably modified version of your code:
HWND hwndButton = CreateWindow(
"BUTTON", // Predefined class;
"Options", // Button text
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, // Styles
250, // x position
0, // y position
50, // Button width
30, // Button height
hwnd, // Parent window
(HMENU)(IDC_BUTTON1), // With WS_CHILD, this is an ID, not a menu
(HINSTANCE)GetWindowLongPtr(hwnd, GWLP_HINSTANCE),
NULL);
From the description of the hMenu
parameter in the docs (bold emphasis mine):
A handle to a menu, or specifies a child-window identifier depending on the window style. For an overlapped or pop-up window, hMenu identifies the menu to be used with the window; it can be
NULL
if the class menu is to be used. For a child window, hMenu specifies the child-window identifier, an integer value used by a dialog box control to notify its parent about events. The application determines the child-window identifier; it must be unique for all child windows with the same parent window.
Then, when the parent receives the WM_COMMAND
message, that identifier value will be part (the low word) of the wParam
argument (the high word will be the BN_CLICKED
notification code). (docs)
So, assuming you have the IDC_BUTTON1
token defined somewhere, and pass that as the hMenu
argument as described above, then your parent window can have something along the following lines as part of the message-handler's switch
statement:
//...
case WM_COMMAND:
if (LOWORD(wParam) == IDC_BUTTON1 && HIWORD(wParam) == BN_CLICKED) {
MessageBox(NULL, "Clicked My Button!", "Testing...", MB_OK);
// <Place your actual code here ...>
return 0; // If handled, we should return zero.
}
break;
//...