Thread: Buttons

  1. #1
    Banned
    Join Date
    Oct 2004
    Posts
    250

    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;
    }

  2. #2
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    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.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  3. #3
    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
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  4. #4
    Banned
    Join Date
    Oct 2004
    Posts
    250
    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;
    }

  5. #5
    Banned
    Join Date
    Oct 2004
    Posts
    250
    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

  6. #6
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    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.
    Last edited by Ken Fitlike; 11-27-2004 at 05:29 AM. Reason: typos
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 04-09-2009, 02:31 AM
  2. Ownerdraw buttons (2)
    By maes in forum Windows Programming
    Replies: 7
    Last Post: 09-11-2003, 05:50 AM
  3. Radio Buttons in Visual C++ 6
    By Ripper1 in forum Windows Programming
    Replies: 22
    Last Post: 05-16-2003, 07:54 AM
  4. (Ken Fitlike) buttons
    By jdinger in forum C++ Programming
    Replies: 4
    Last Post: 03-15-2002, 01:21 PM
  5. Grouping radio buttons
    By Bazz in forum Windows Programming
    Replies: 1
    Last Post: 08-28-2001, 07:15 AM