-
Buttons
how would i get this working i tried using BN_CLICKED to check if the button has been clicked but it does not work
Code:
#include <windows.h>
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
//create a default push button
CreateWindowEx(0, //more or 'extended' styles
TEXT("BUTTON"), //'class' of control to create
TEXT("Start"), //the control caption
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON, //control style: how it looks
10, //control position: left
10, //control position: top
200, //control width
30, //control height
hwnd, //parent window handle
NULL, //control's ID
NULL, //application instance
NULL);
return 0;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case BN_CLICKED:
MessageBox(NULL,"Clicked","Message", MB_OK);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
-
The BN_CLICKED notification message is sent to the control's parent window as a WM_COMMAND message so it can't be handled in the way you are attempting.
Read this thread in reverse order for more specific information.
-
Hello,
I would recommend using the WM_COMMAND case. WindowProc sends WM_COMMAND messages down a different fork along the message routing interstate.
WM_COMMAND is an unfortunately overloaded message. Windows sends it whenever the user invokes a command, either through the menu or an accelerator key. WPARAM tells which. But controls also use WM_COMMAND to send notifications, for example when a button sends BN_CLICKED or an edit control sends EN_ CHANGED. When this happens, the control's HWND, notification code, and ID are packed like sardines into WPARAM and LPARAM, leaving no room for additional information. How they're packed depends on whether you're using 16-bit Windows or Win32.
Overloading WM_COMMAND like this has one nice benefit: pressing a button looks to your app much like invoking a menu command. But conceptually, they're entirely different events. A command means "do something," whereas a control notification means "something happened."
Here is a brief example of WM_COMMAND:
Code:
case WM_COMMAND: { // Window Command
switch (LOWORD(wParam)) { // switch wParam for button window access
case BTN_xxx: // If BTN_xxx button pressed
// Do something...
break;
}
break;
}
- Stack Overflow
-
thanks alot i got it working :)
but when i try and use 2 buttons it wont
Code:
#include <windows.h>
#define BUTTON 101
#define BUTTON 102
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
CreateWindowEx(0,
TEXT("BUTTON"),
TEXT("Start"),
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
50,
50,
200,
30,
hwnd,
NULL,
NULL,
NULL);
CreateWindowEx(0,
TEXT("BUTTON"),
TEXT("Start2"),
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
10,
10,
200,
30,
hwnd,
NULL,
NULL,
NULL);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case BUTTON_101:
MessageBox(NULL,"Button1 Clicked","Message", MB_OK);
break;
case BUTTON_102:
MessageBox(NULL,"Button2 Clicked","Message", MB_OK);
break;
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
// Step 3: The Message Loop
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
-
so can anyone help me, im going to make a calculator and if i have more than one button on the program it doesnt work :(
-
Short answer:
You have already been given all the information you need. Here's the direct link I referred to earlier - read the 2nd post for information that ensures that your WM_COMMAND handler handles the exact notification message for a particular control.
Long answer:
From that and the information given under the description for the BN_CLICKED notification you should see that two pieces of information are packed into the wParam of the WM_COMMAND notification message, namely the type of notification (in your example, BN_CLICKED) and the individual control identifier. You should set the control identifier as the HMENU parameter passed to CreateWindowEx when you create the control. These values are usually #defined (which you seem to have done) but enumerations are common too. You should also make sure you give the application instance when you create your buttons. Also note that the BS_DEFPUSHBUTTON style should only be given to one button control that you intend to use as a 'default' button; just use BS_PUSHBUTTON for normal buttons (you can actually omit this as it's implied with the 'button' control class name).
For example,
Code:
case WM_CREATE:
CreateWindowEx(0,
TEXT("BUTTON"),
TEXT("Start"),
WS_CHILD|WS_VISIBLE|BS_DEFPUSHBUTTON,
50,
50,
200,
30,
hwnd,
(HMENU)BUTTON_101, //attach control identifier
GetModuleHandle(0), //use the application instance
NULL);
CreateWindowEx(0,
TEXT("BUTTON"),
TEXT("Start2"),
WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,
10,
10,
200,
30,
hwnd,
(HMENU)BUTTON_102,
GetModuleHandle(0),
NULL);
return 0;
Now, while this will probably make your current WM_COMMAND handler work as you intended, you should still modify it as previously described because it should enable you to avoid future errors caused by notification message handling code mis-firing ('it works' is no substitute for 'correct').
MSDN button control reference.