SaeidMo7
SaeidMo7

Reputation: 1304

The CBN_SELCHANGE notification not works when i use the function ComboBox_SetCurSel

I have a ComboBox in a window and i want to execute a function after changing selected item. When i change the selected item of the combobox by mouse or keyboard, the CBN_SELCHANGE event in the window message WM_COMMAND works well and my function execute.

But if i use the function ComboBox_SetCurSel for changing the selected item ,it not works.

What window message WM_**** and combox notification do i use for processing the event changing selected item.

Upvotes: 4

Views: 2442

Answers (1)

Cody Gray
Cody Gray

Reputation: 244981

In general, when you programmatically manipulate a control, the corresponding notification is not sent to its parent. The notification only gets sent when the user manipulates the control.

So, when you call ComboBox_SetCurSel (which is a macro that performs the same task as sending the CB_SETCURSEL message), that programmatically changes the control's current selection and therefore does not send the CBN_SELCHANGE notification. However, CBN_SELCHANGE does get sent if the user changes the combobox's selection.

This is called out explicitly in the "Remarks" section of the documentation for CBN_SELCHANGE:

The CBN_SELCHANGE notification code is not sent when the current selection is set using the CB_SETCURSEL message.

To work around this, you can do one of two things:

  1. Call your event-handler method directly. For example, in MFC, you would have the framework attach an OnCbnSelChange member function to handle the combobox's CBN_SELCHANGE notification. After your code that called ComboBox_SetCurSel, you would simply call that OnCbnSelChange member function manually:

    ComboBox_SetCurSel(hwndComboBox, 0);  // select 1st item
    this->OnCbnSelChange();               // invoke the change event-handler
    

    Your GUI framework undoubtedly has something similar.

  2. Manually send the CBN_SELCHANGE notification to the control's parent. I don't really know why you would ever do this, because the default window procedure doesn't do anything interesting upon receipt of this notification; you would be much better off just calling your own handler directly.

    ::PostMessage(hwndParent,
                  WM_COMMAND,
                  MAKEWPARAM(IDC_COMBOBOX, CBN_SELCHANGE),
                  reinterpret_cast<LPARAM>(hwndComboBox);
    

    Or, if you were doing this from a subclass of the combobox:

    HWND hwndParent = ::GetAncestor(hwndComboBox, GA_PARENT);
    int  ctrlID     = static_cast<int>(::GetWindowLongPtr(hwndComboBox, GWLP_ID));
    ::PostMessage(hwndParent,
                  WM_COMMAND,
                  MAKEWPARAM(ctrlID, CBN_SELCHANGE),
                  reinterpret_cast<LPARAM>(hwndComboBox));
    

Upvotes: 5

Related Questions