4

我有一个 Windows 窗体自定义组合框,我在 dataGridView 中托管。我不知道如何在用户选择项目时保持下拉列表打开。没有关闭事件可以挂断。有谁知道这是如何实现的?我会很感激任何建议。

提前致谢,-DA

4

2 回答 2

3

您可以使用GetComboBoxInfo获取HandleDropDownList使用 customNativeWindow挂钩到 的消息循环DropDownList以捕获一些相关消息并实现您想要的。这是 custom 的完整代码,它具有默认值为ComboBox的属性,默认情况下它就像标准一样,要使其按您的意愿工作,只需设置:HideDropDownAfterSelecttrueComboBoxHideDropDownAfterSelect = false

//Must add using System.Runtime.InteropServices;
public static class Win32 {
   [DllImport("user32")]
   public static extern bool GetComboBoxInfo(IntPtr hwnd, 
                                             out Win32.COMBOBOXINFO info);
   public struct RECT {
            public int left, top, right, bottom;
   }
   public struct COMBOBOXINFO {
            public int size;
            public RECT item;
            public RECT button;
            public int state;
            public IntPtr comboHwnd;
            public IntPtr itemHwnd;
            public IntPtr listHwnd;
   }
}
public class CustomComboBox : ComboBox {
   NativeDropDownList dropDown = new NativeDropDownList();
   IntPtr dropDownHandle;
   bool hideDropDownAfterSelect = true;
   public CustomComboBox() {
      dropDown.ParentControl = this;
      HandleCreated += (s, e) => {
         Win32.COMBOBOXINFO info = new Win32.COMBOBOXINFO();
         info.size = Marshal.SizeOf(info);                   
         Win32.GetComboBoxInfo(Handle, out info);
         dropDownHandle = info.listHwnd;                    
      };
   }
   public bool HideDropDownAfterSelect {
      get {
         return hideDropDownAfterSelect;
      }
      set {
         if (hideDropDownAfterSelect != value) {
           hideDropDownAfterSelect = value;
           if (!value) dropDown.AssignHandle(dropDownHandle);
           else dropDown.ReleaseHandle();
         }
      }
   }
   private class NativeDropDownList : NativeWindow {
      public ComboBox ParentControl;
      protected override void WndProc(ref Message m) {
         if (m.Msg == 0x202) { //WM_LBUTTONUP                                    
            AcceptSelection(false);
            return;
         }
         //WM_LBUTTONDBLCLK
         if (m.Msg == 0x203) AcceptSelection(true);
         base.WndProc(ref m);
      }
      private void AcceptSelection(bool hideDropDown) {
         //LB_GETCURSEL = 0x188
         Message m = Message.Create(Handle, 0x188, IntPtr.Zero, IntPtr.Zero);
         WndProc(ref m);
         int i = m.Result.ToInt32();
         typeof(ComboBox).GetMethod("OnSelectedIndexChanged", 
                                   System.Reflection.BindingFlags.NonPublic | 
                                   System.Reflection.BindingFlags.Instance)
                         .Invoke(ParentControl, new object[] { EventArgs.Empty });
         if (i == -1) return;
         ParentControl.Text = ParentControl.Items[i].ToString();
         ParentControl.SelectAll();
         ParentControl.Invalidate();
         if (hideDropDown) {
            ParentControl.DroppedDown = false;
         }
      }
   }
} 
//Usage
customComboBox1.HideDropDownAfterSelect = false;
//You can select the item and hide the drop down by double-clicking left mouse
//It works that way because of the code above at WM_LBUTTONDBLCLK
于 2013-10-30T19:29:43.483 回答
0

使用 aListBox而不是 a ComboBox。即使在用户选择了一个选项之后,您想要保持 ComboBox 打开的操作将是不寻常和意外的行为。

于 2013-10-30T05:04:39.457 回答