combobox下拉宽度建议

我有一个具有combobox控件的表单。 我已经选择了下拉样式属性到DropDown。 我还将DropDown Width设置为250.我已将自动完成模式设置为建议,并将自动完成源设置为listitems。 当我点击下拉菜单时它完全正常。 但是当我输入某些东西时,自动完成模式会激活一个宽度较小的下拉菜单。

任何帮助欣赏。 我想知道如何通过代码增加自动完成下拉的宽度,以便正确查看列表项。 我正在使用C#。

几个月前我曾问过这个,但没有得到正确答案。 现在顾客想要它坏:( ??

using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; ///  /// Represents an ComboBox with additional properties for setting the /// size of the AutoComplete Drop-Down window. ///  public class ComboBoxEx : ComboBox { private int acDropDownHeight = 106; private int acDropDownWidth = 170; // /// Provides an encapsulation of an Auto complete drop down window /// handle and window proc. ///  private class ACWindow : NativeWindow { private static readonly Dictionary ACWindows; #region "Win API Declarations" private const UInt32 WM_WINDOWPOSCHANGED = 0x47; private const UInt32 WM_NCDESTROY = 0x82; private const UInt32 SWP_NOSIZE = 0x1; private const UInt32 SWP_NOMOVE = 0x2; private const UInt32 SWP_NOZORDER = 0x4; private const UInt32 SWP_NOREDRAW = 0x8; private const UInt32 SWP_NOACTIVATE = 0x10; private const UInt32 GA_ROOT = 2; private static readonly List owners; [DllImport("user32.dll")] private static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam); [DllImport("user32.dll")] private static extern IntPtr GetAncestor(IntPtr hWnd, UInt32 gaFlags); [DllImport("kernel32.dll")] private static extern int GetCurrentThreadId(); [DllImport("user32.dll")] private static extern void GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll")] private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); [DllImport("user32.dll")] private static extern bool GetWindowRect(IntPtr hWnd, ref RECT lpRect); #region Nested type: EnumThreadDelegate private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam); #endregion #region Nested type: RECT [StructLayout(LayoutKind.Sequential)] private struct RECT { public readonly int Left; public readonly int Top; public readonly int Right; public readonly int Bottom; public Point Location { get { return new Point(Left, Top); } } } #endregion #endregion private ComboBoxEx owner; static ACWindow() { ACWindows = new Dictionary(); owners = new List(); } ///  /// Creates a new ACWindow instance from a specific window handle. ///  private ACWindow(IntPtr handle) { AssignHandle(handle); } ///  /// Registers a ComboBoxEx for adjusting the Complete Dropdown window size. ///  public static void RegisterOwner(ComboBoxEx owner) { if ((owners.Contains(owner))) { return; } owners.Add(owner); EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowCallback, IntPtr.Zero); } ///  /// This callback will receive the handle for each window that is /// associated with the current thread. Here we match the drop down window name /// to the drop down window name and assign the top window to the collection /// of auto complete windows. ///  private static bool EnumThreadWindowCallback(IntPtr hWnd, IntPtr lParam) { if ((GetClassName(hWnd) == "Auto-Suggest Dropdown")) { IntPtr handle = GetAncestor(hWnd, GA_ROOT); if ((!ACWindows.ContainsKey(handle))) { ACWindows.Add(handle, new ACWindow(handle)); } } return true; } ///  /// Gets the class name for a specific window handle. ///  private static string GetClassName(IntPtr hRef) { var lpClassName = new StringBuilder(256); GetClassName(hRef, lpClassName, 256); return lpClassName.ToString(); } ///  /// Overrides the NativeWindow's WndProc to handle when the window /// attributes changes. ///  protected override void WndProc(ref Message m) { if ((m.Msg == WM_WINDOWPOSCHANGED)) { // If the owner has not been set we need to find the ComboBoxEx that // is associated with this dropdown window. We do it by checking if // the upper-left location of the drop-down window is within the // ComboxEx client rectangle. if ((owner == null)) { Rectangle ownerRect = default(Rectangle); var acRect = new RECT(); foreach (ComboBoxEx cbo in owners) { GetWindowRect(Handle, ref acRect); ownerRect = cbo.RectangleToScreen(cbo.ClientRectangle); if ((ownerRect.Contains(acRect.Location))) { owner = cbo; break; // TODO: might not be correct. Was : Exit For } } owners.Remove(owner); } if (((owner != null))) { SetWindowPos(Handle, IntPtr.Zero, -5, 0, owner.AutoCompleteDropDownWidth, owner.AutoCompleteDropDownHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); } } if ((m.Msg == WM_NCDESTROY)) { ACWindows.Remove(Handle); } base.WndProc(ref m); } } #endregion } 

这就是我所做的,它确实很有效。 很高兴找到答案atlast 🙂

这个答案是雷吉答案的补充。

如果您希望用户能够调整自动完成下拉列表的大小,请在WndProc方法中添加以下代码:

  private const int WM_SIZING = 0x214; if (m.Msg == WM_SIZING) { if (owner != null) { RECT rr = (RECT) Marshal.PtrToStructure(m.LParam, typeof(RECT)); owner.acDropDownWidth = (rr.Right - rr.Left); owner.acDropDownHeight = (rr.Bottom - rr.Top); } } 

这样做是一种糟糕的设计决定。 为什么不将它设置为静态大尺寸? 您始终可以使用其中一个事件来获取文本宽度,然后使用它来设置combobox宽度。 可能是onPaint? 更简单的方法可能是创建自己的comboboxinheritance自combobox,然后重写方法来自己完成。