locked
Redimensionner la largeur d'un autocompletion dropdownlist RRS feed

  • Question

  • J'ai un combobox avec la propriété autocompletion a on. Mais le problème c'est que la dropdownlist qu'il affiche dans ce mode doit avoir 150 pixel de large et je dois lui donner environ 350 pour qu'elle soi utilisable.

    Quelqu'un à la solution à ce petit problème.

    Merci
    Steve
    mercredi 24 février 2010 17:32

Réponses

  • Bonjour,

    J'ai cherché et j'ai trouvé un post qui parle de ça ici :
    http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/5d0e19bb-d5a2-444e-bda8-6774e9889963

    En espérant que cela t'aide,

    Cordialement,

    Thomas
    Thomas Aimonetti - C# - Sharplog Engineering - http://www.sharplog.fr
    mercredi 24 février 2010 18:04
  • C'est très bon voici la version c# avec l'autre parti de code qui permet de calculer automatiquement la largeur du dropdown par rapport aux valeurs que la liste contient

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    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 acDropDownWidth = 170;
        private int acDropDownHeight = 106;
    
        //<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);
        }
    
    
        /// <summary> 
        /// Provides an encapsulation of an Auto complete drop down window 
        /// handle and window proc. 
        /// </summary> 
        private class ACWindow : NativeWindow
        {
    
            private ComboBoxEx owner;
            private static readonly Dictionary<IntPtr, ACWindow> ACWindows;
            private static readonly List<ComboBoxEx> owners;
            
            #region "Win API Declarations"
            private const UInt32 WM_WINDOWPOSCHANGED = 0x47;
            private const UInt32 WM_NCDESTROY = 0x82;
    
            private const UInt32 SWP_NOMOVE = 0x2;
            private const UInt32 SWP_NOZORDER = 0x4;
            private const UInt32 SWP_NOACTIVATE = 0x10;
    
            private const UInt32 GA_ROOT = 2;
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
    
                public Point Location
                {
                    get { return new Point(Left, Top); }
                }
            }
    
            private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
            
            [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, System.Text.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);
            
            #endregion
            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)
            {
                System.Text.StringBuilder lpClassName = new System.Text.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;
                        RECT 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;
                            }
                        }
                        owners.Remove(owner);
                    }
                    if (((owner != null)))
                    {
                        SetWindowPos(Handle, IntPtr.Zero, 0, 0, owner.AutoCompleteDropDownWidth, owner.AutoCompleteDropDownHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
                    }
                }
                if ((m.Msg == WM_NCDESTROY))
                {
                    ACWindows.Remove(Handle);
                }
                base.WndProc(ref m);
            }
        }
    }
    
    
    et voici la méthode pour auto width
    
            private void AdjustWidthComboBox_DropDown(object sender, EventArgs e)
            {
                //Méthode qui permet d'ajuster la taille d'un dropdownlist d'un combobox 
                //à la largeur de son item le plus grand.
    
                var senderComboBox = (ComboBoxEx) sender;
                int width = senderComboBox.DropDownWidth;
                Graphics g = senderComboBox.CreateGraphics();
                Font font = senderComboBox.Font;
                //Calcul la largeur du bouton scrollbar s'il y en a un.
                int vertScrollBarWidth =
                    (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems)
                        ? SystemInformation.VerticalScrollBarWidth
                        : 0;
    
                //Boucle à travers tous les items de la liste.
                for (int i = 0; i < senderComboBox.Items.Count; i++)
                {
                    //Calcul la largeur qu'une chaine de caratère occupe d'après sa police + la largeur du bouton scrollbar
                    int newWidth = (int) g.MeasureString(senderComboBox.GetItemText(senderComboBox.Items[i]), font).Width
                                   + vertScrollBarWidth;
                    if (width < newWidth)
                    {
                        width = newWidth;
                    }
                }
                senderComboBox.DropDownWidth = width;
                senderComboBox.AutoCompleteDropDownWidth = width;
            }
    
    
    Steve
    • Marqué comme réponse stefor jeudi 4 mars 2010 14:45
    jeudi 4 mars 2010 14:44

Toutes les réponses

  • Bonjour,

    J'ai cherché et j'ai trouvé un post qui parle de ça ici :
    http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/5d0e19bb-d5a2-444e-bda8-6774e9889963

    En espérant que cela t'aide,

    Cordialement,

    Thomas
    Thomas Aimonetti - C# - Sharplog Engineering - http://www.sharplog.fr
    mercredi 24 février 2010 18:04
  • Bonjour,

     

    Thomas, merci pour le lien.

     

    Stefor, avez-vous trouvé une solution satisfaisante la bas ?

     

    Cordialement,

    Alex


    Alex Petrescu - MSFT
    vendredi 26 février 2010 13:45
  • C'est très bon voici la version c# avec l'autre parti de code qui permet de calculer automatiquement la largeur du dropdown par rapport aux valeurs que la liste contient

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    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 acDropDownWidth = 170;
        private int acDropDownHeight = 106;
    
        //<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);
        }
    
    
        /// <summary> 
        /// Provides an encapsulation of an Auto complete drop down window 
        /// handle and window proc. 
        /// </summary> 
        private class ACWindow : NativeWindow
        {
    
            private ComboBoxEx owner;
            private static readonly Dictionary<IntPtr, ACWindow> ACWindows;
            private static readonly List<ComboBoxEx> owners;
            
            #region "Win API Declarations"
            private const UInt32 WM_WINDOWPOSCHANGED = 0x47;
            private const UInt32 WM_NCDESTROY = 0x82;
    
            private const UInt32 SWP_NOMOVE = 0x2;
            private const UInt32 SWP_NOZORDER = 0x4;
            private const UInt32 SWP_NOACTIVATE = 0x10;
    
            private const UInt32 GA_ROOT = 2;
    
            [StructLayout(LayoutKind.Sequential)]
            private struct RECT
            {
                public int Left;
                public int Top;
                public int Right;
                public int Bottom;
    
                public Point Location
                {
                    get { return new Point(Left, Top); }
                }
            }
    
            private delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
            
            [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, System.Text.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);
            
            #endregion
            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)
            {
                System.Text.StringBuilder lpClassName = new System.Text.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;
                        RECT 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;
                            }
                        }
                        owners.Remove(owner);
                    }
                    if (((owner != null)))
                    {
                        SetWindowPos(Handle, IntPtr.Zero, 0, 0, owner.AutoCompleteDropDownWidth, owner.AutoCompleteDropDownHeight, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
                    }
                }
                if ((m.Msg == WM_NCDESTROY))
                {
                    ACWindows.Remove(Handle);
                }
                base.WndProc(ref m);
            }
        }
    }
    
    
    et voici la méthode pour auto width
    
            private void AdjustWidthComboBox_DropDown(object sender, EventArgs e)
            {
                //Méthode qui permet d'ajuster la taille d'un dropdownlist d'un combobox 
                //à la largeur de son item le plus grand.
    
                var senderComboBox = (ComboBoxEx) sender;
                int width = senderComboBox.DropDownWidth;
                Graphics g = senderComboBox.CreateGraphics();
                Font font = senderComboBox.Font;
                //Calcul la largeur du bouton scrollbar s'il y en a un.
                int vertScrollBarWidth =
                    (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems)
                        ? SystemInformation.VerticalScrollBarWidth
                        : 0;
    
                //Boucle à travers tous les items de la liste.
                for (int i = 0; i < senderComboBox.Items.Count; i++)
                {
                    //Calcul la largeur qu'une chaine de caratère occupe d'après sa police + la largeur du bouton scrollbar
                    int newWidth = (int) g.MeasureString(senderComboBox.GetItemText(senderComboBox.Items[i]), font).Width
                                   + vertScrollBarWidth;
                    if (width < newWidth)
                    {
                        width = newWidth;
                    }
                }
                senderComboBox.DropDownWidth = width;
                senderComboBox.AutoCompleteDropDownWidth = width;
            }
    
    
    Steve
    • Marqué comme réponse stefor jeudi 4 mars 2010 14:45
    jeudi 4 mars 2010 14:44