建议上的组合框下拉宽度 [英] Combo box drop down width on suggest

查看:21
本文介绍了建议上的组合框下拉宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含组合框控件的表单.我已将下拉样式属性选择为 DropDown.我还将下拉宽度设置为 250.我将自动完成模式设置为建议,将自动完成源设置为列表项.当我点击下拉菜单时它工作得很好.但是当我输入一些东西时,自动完成模式会激活一个宽度很小的下拉菜单.

I have a form which has a Combo Box Control. I have selected the drop down style property to DropDown. I have also set the DropDown Width to 250. I have set the auto complete mode to suggest and the auto complete source to listitems. it works absolutely fine when i click on the drop down. but when i type in somethin, the auto complete mode activates a drop down which has a small width.

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

any help appreciate. i wanna know how to increase the width of the auto complete drop down via code so that the list items are viewed properly. I am using C#.

几个月前我问过这个问题,但没有得到正确的答案.现在客户想要它不好:(??

I had asked this a couple of months back but didn't get a proper answer. now the customer wants it bad :( ??

推荐答案

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

/// <summary>  
/// Represents an ComboBox with additional properties for setting the   
/// size of the AutoComplete Drop-Down window.  
/// </summary>  
public class ComboBoxEx : ComboBox
{
private int acDropDownHeight = 106;
private int acDropDownWidth = 170;


//<EditorBrowsable(EditorBrowsableState.Always), _  

[Browsable(true), Description("The width, in pixels, of the auto complete drop down box"), DefaultValue(170)]
public int AutoCompleteDropDownWidth
{
    get { return acDropDownWidth; }

    set { acDropDownWidth = value; }
}


//<EditorBrowsable(EditorBrowsableState.Always), _  

[Browsable(true), Description("The height, in pixels, of the auto complete drop down box"), DefaultValue(106)]
public int AutoCompleteDropDownHeight
{
    get { return acDropDownHeight; }

    set { acDropDownHeight = value; }
}


protected override void OnHandleCreated(EventArgs e)
{
    base.OnHandleCreated(e);

    ACWindow.RegisterOwner(this);
}

#region Nested type: ACWindow

/// <summary>  
/// Provides an encapsulation of an Auto complete drop down window   
/// handle and window proc.  
/// </summary>  
private class ACWindow : NativeWindow
{
    private static readonly Dictionary<IntPtr, ACWindow> 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<ComboBoxEx> 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<IntPtr, ACWindow>();

        owners = new List<ComboBoxEx>();
    }


    /// <summary>  
    /// Creates a new ACWindow instance from a specific window handle.  
    /// </summary>  
    private ACWindow(IntPtr handle)
    {
        AssignHandle(handle);
    }


    /// <summary>  
    /// Registers a ComboBoxEx for adjusting the Complete Dropdown window size.  
    /// </summary>  
    public static void RegisterOwner(ComboBoxEx owner)
    {
        if ((owners.Contains(owner)))
        {
            return;
        }

        owners.Add(owner);

        EnumThreadWindows(GetCurrentThreadId(), EnumThreadWindowCallback, IntPtr.Zero);
    }


    /// <summary>  
    /// 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.  
    /// </summary>  
    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;
    }


    /// <summary>  
    /// Gets the class name for a specific window handle.  
    /// </summary>  
    private static string GetClassName(IntPtr hRef)
    {
        var lpClassName = new StringBuilder(256);

        GetClassName(hRef, lpClassName, 256);

        return lpClassName.ToString();
    }


    /// <summary>  
    /// Overrides the NativeWindow's WndProc to handle when the window  
    /// attributes changes.  
    /// </summary>  
    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
}

这就是我所做的,而且效果非常好.很高兴终于找到答案:)

This is what I did and it actually works really well. Good to find an answer atlast :)

这篇关于建议上的组合框下拉宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆