How to send a CBN_SELCHANGE message when using CB_SETCURSEL?

后端 未结 3 358
醉酒成梦
醉酒成梦 2021-01-20 09:55

When using the CB_SETCURSEL message, the CBN_SELCHANGE message is not sent.

How to notify a control that the selection was changed

相关标签:
3条回答
  • 2021-01-20 10:21

    This might help the next person out:

    [DllImport("User32.dll", EntryPoint = "SendMessage")]
    private static extern int SendMessage(IntPtr hwnd, int msg, int wParam, int lParam);
    
    [DllImport("user32.dll", EntryPoint = "GetWindowLong")]
    private static extern IntPtr GetWindowLongPtr32(IntPtr hWnd, int nIndex);
    
    [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
    private static extern IntPtr GetWindowLongPtr64(IntPtr hWnd, int nIndex);
    
    public static IntPtr GetWindowLongPtr(IntPtr hWnd, int nIndex)
    {
       if (IntPtr.Size == 8)
            return GetWindowLongPtr64(hWnd, nIndex);
       else
            return GetWindowLongPtr32(hWnd, nIndex);
    }
    
    static int MakeWParam(int loWord, int hiWord)
    {
         return (loWord & 0xFFFF) + ((hiWord & 0xFFFF) << 16);
    }
    
    public const int CB_SETCURSEL = 0x014E;
    public const int CBN_SELCHANGE = 0x0001;
    
    public enum GWL
    {
                GWL_WNDPROC = (-4),
                GWL_HINSTANCE = (-6),
                GWL_HWNDPARENT = (-8),
                GWL_STYLE = (-16),
                GWL_EXSTYLE = (-20),
                GWL_USERDATA = (-21),
                GWL_ID = (-12)
    }
    
    public static IntPtr Hwnd_select_control_parent = IntPtr.Zero;
    public static IntPtr Hwnd_select_control = IntPtr.Zero;
    
    static void changeit()
    
    {
    
    // Google WinSpy for tips on how to figure out how to get window handles from known ctrl_id
    
       Hwnd_select_control = 14298; // or whatever the handle of the combo box is
    
    // Get the parent of the selectbox control
    
       Hwnd_select_control_parent = GetWindowLongPtr(service_window_control, (int)GWL.GWL_HWNDPARENT);
    
    // Get the control id of the selectbox if you don't already have it
    
       IntPtr nID = GetWindowLongPtr(Hwnd_select_control, (int)GWL.GWL_ID);
       int ctrl_id = nID.ToInt32();
    
    // Change the combo box to the value "My Value"
    
       SendMessage(Hwnd_select_control, CB_SETCURSEL, "My Value", null);
    
    // low ID is the ctrl_id of the combo box, high id is CBN_SELCHANGE
    
       int send_cbn_selchange = MakeWParam(ctrl_id, CBN_SELCHANGE); 
    
    // Send the WM_COMMAND to the parent, not the control itself
    
       SendMessage(Hwnd_serviceselect_control_parent, 0x111 /* WM_COMMAND */, send_cbn_selchange, Hwnd_serviceselect_control.ToInt32()); 
    
    
    }
    
    0 讨论(0)
  • 2021-01-20 10:28

    I just discovered calling these SendMessages to the Combobox twice works... I know it's not perfect but it worked for me. (Written in VB6)

        For looper = 1 To 2
    
            bVal = SendMessage(inHandle, COMBO.CB_SHOWDROPDOWN, True, 0)
            count = SendMessage(inHandle, COMBO.CB_SETCURSEL, 1, 0)
            count = SendMessage(inHandle, WIND.WM_LBUTTONDOWN, 0, -1)
    
        Next
    
    0 讨论(0)
  • 2021-01-20 10:29

    You're not supposed to use CBN_SELCHANGE unless the change in selection was made by the user.

    You don't indicate what language you're using; it would make it easier to provide you with a workaround if you did so.

    In Delphi, where an OnChange() would be associated with the combobox, you just call the event method directly:

    // Send the CB_SETCURSEL message to the combobox
    PostMessage(ComboBox1.Handle, CB_SETCURSEL, Whatever, WhateverElse);
    
    // Directly call the OnChange() handler, which is the equivalent to CBN_SELCHANGE
    ComboBox1Change(nil);
    
    0 讨论(0)
提交回复
热议问题