winapi BN_CLICKED how to identify which button was clicked?

11,937

Solution 1

Give each button it's own ID, and pass it to CreateWindowEx in the hMenu parameter, which is used for that:

A handle to a menu, or specifies a child-window identifier, depending on the window style.

#define BTN_PLUS  100
#define BTN_EQUAL 101

CreateWindowEx( 0, L"BUTTON", L"+", WS_CHILD | WS_VISIBLE, 130, 240, 35, 30,
                hwnd, ( HMENU )BTN_PLUS, GetModuleHandle( NULL ), NULL );

CreateWindowEx( 0, L"BUTTON", L"=", WS_CHILD | WS_VISIBLE, 170, 205, 65, 65,
               hwnd, ( HMENU )BTN_EQUAL , GetModuleHandle( NULL ), NULL );

Then, in WM_COMMAND, you can test for the ID:

case WM_COMMAND: {
    if ( LOWORD( wParam ) == BTN_PLUS ) {
        [...]
    }
    [...]
    break;
}

Solution 2

You just need to look at the lParam it's the button handle:

if ((HWND)lParam == hPlus)
{
    // "plus" clicked ... etc.
}

Though in your code, you'll need to keep the HWND's in global variables to do the comparison.

// somewhere global
HWND hPlus = NULL;
HWND hEquals = NULL;

// in your WndProc ...

case: WM_CREATE:
    hPlus = CreateWindowEx( 0, L"BUTTON", L"+", WS_CHILD | WS_VISIBLE, 130, 240, 35, 30, hwnd, ( HMENU )IDC_MENU, GetModuleHandle( NULL ), NULL );
    hEquals = CreateWindowEx( 0, L"BUTTON", L"=", WS_CHILD | WS_VISIBLE, 170, 205, 65, 65, hwnd, ( HMENU )IDC_MENU, GetModuleHandle( NULL ), NULL );
break;

case WM_COMMAND:
    switch( HIWORD( wParam ) )
    {
        case BN_CLICKED:
            // see which button was clicked
            if ((HWND)lParam == hPlus)
            {
                MessageBox( hwnd, L"hPlus was clicked", "OK", MB_OK );
            }
            break;
    }
    break;

You get the idea, I'm sure....

Share:
11,937
Vince
Author by

Vince

Updated on July 24, 2022

Comments

  • Vince
    Vince almost 2 years

    I'm creating a simple win32 program using c++, although I think i'm only using c in this app. I need to determine which HWND button was pressed on the app. I've searched msdn reference and it only told me HIWORD is the notification code, and LOWORD is the identifier, for the BN_CLICKED message. I've managed to get as far as determining when a button is clicked, but it only applies for all buttons. All my buttons are created in the WM_CREATE message. This is what i managed to whip up so far:

    case: WM_CREATE:
        HWND hPlus = CreateWindowEx( 0, L"BUTTON", L"+", WS_CHILD | WS_VISIBLE, 130, 240, 35, 30, hwnd, ( HMENU )IDC_MENU, GetModuleHandle( NULL ), NULL );
        HWND hEquals = CreateWindowEx( 0, L"BUTTON", L"=", WS_CHILD | WS_VISIBLE, 170, 205, 65, 65, hwnd, ( HMENU )IDC_MENU, GetModuleHandle( NULL ), NULL );
    break;
    
    case WM_COMMAND:
        switch( HIWORD( wParam ) )
        {
            case BN_CLICKED:
                MessageBox( hwnd, L"OK", "OK", MB_OK );
                break;
        }
        break;
    

    I've tried comparing hEquals to LOWORD( wParam ) but that gave me an error when compiling. I think I also tried comparing it to HIWORD and LOWORD of lParam as well, which also didn't compile. Now I'm clueless for what to do next.

  • Vince
    Vince over 10 years
    Isn't bad practice to have a lot of global variables though? In a lot of c++ tutorials i've watched, they say its not good to have a lot of global variables.
  • Vince
    Vince over 10 years
    Wow, I never knew that. I always thought the menu was for the actual menu for the window, ex. File, Edit, Window, Help, ect.
  • Roger Rowland
    Roger Rowland over 10 years
    @Vince yes, perfectly true, but that wasn't your original problem and it's difficult to judge how much to put in a single specific answer. I just gave you the minimum code changes to get over the initial issue.
  • Vince
    Vince over 10 years
    I did try it that way before, but I didn't compare it to (HWND)hPlus or anything. Instead what I was trying to do was ( HIWORD )hPlus, then ( LOWORD )hPlus...completly forgot it had to be converted to HWND.
  • Jonathan Potter
    Jonathan Potter over 10 years
    @Vince: Top-level windows have menus, child windows have control IDs. The parameter is used for both.
  • Remy Lebeau
    Remy Lebeau over 10 years
    And that fact is clearly stated in the documentation.