Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center-align a selected Item in a ComboBox in WinForms?

I have a form with a ComboBox. I found the post: http://blog.michaelgillson.org/2010/05/18/left-right-center-where-do-you-align/ that helped me to centre-align all the items in the DropDown list. The problem is that the selected item (the item shown in the comboBox.Text property) remains left aligned.

How can I centre-align also the selected Item?
The code is:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ComboBoxTextProperty
{
    public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();

            List<string> source = new List<string>() { "15", "63", "238", "1284", "13561" };
            comboBox1.DataSource = source;
            comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
            comboBox1.DropDownStyle = ComboBoxStyle.DropDown;
            comboBox1.SelectedIndex = 0;
            comboBox1.DrawItem += new DrawItemEventHandler(ComboBox_DrawItem);
    }

    /// <summary>
    /// Allow the text in the ComboBox to be center aligned.
    /// Change the DrawMode Property from Normal to either OwnerDrawFixed or OwnerDrawVariable.
    /// If DrawMode is not changed, the DrawItem event will NOT fire and the DrawItem event handler will not execute.
    /// For a DropDownStyle of DropDown, the selected item remains left aligned but the expanded dropped down list is centered.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ComboBox_DrawItem(object sender, DrawItemEventArgs e)
    {
        ComboBox comboBox1 = sender as ComboBox; // By using sender, one method could handle multiple ComboBoxes.
        if (comboBox1 != null)
        {
            e.DrawBackground(); // Always draw the background.               
            if (e.Index >= 0) // If there are items to be drawn.
            {
                StringFormat format = new StringFormat(); // Set the string alignment.  Choices are Center, Near and Far.
                format.LineAlignment = StringAlignment.Center;
                format.Alignment = StringAlignment.Center;

                // Set the Brush to ComboBox ForeColor to maintain any ComboBox color settings.
                // Assumes Brush is solid.
                Brush brush = new SolidBrush(comboBox1.ForeColor);
                if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) // If drawing highlighted selection, change brush.
                {
                    brush = SystemBrushes.HighlightText;
                }
                e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), comboBox1.Font, brush, e.Bounds, format); // Draw the string.
            }
        }
    }
}
}
like image 630
user2102327 Avatar asked Nov 18 '19 00:11

user2102327


People also ask

How do I center control in Winforms?

You can put the control you want to center inside a Panel and set the left and right padding values to something larger than the default. As long as they are equal and your control is anchored to the sides of the Panel, then it will appear centered in that Panel.

Is used to set the selected item in a ComboBox?

When you set the SelectedItem property to an object, the ComboBox attempts to make that object the currently selected one in the list. If the object is found in the list, it is displayed in the edit portion of the ComboBox and the SelectedIndex property is set to the corresponding index.

What is the correct way to add new item to ComboBox?

To add items to a ComboBox, select the ComboBox control and go to the properties window for the properties of this control. Click the ellipses (...) button next to the Items property. This opens the String Collection Editor dialog box, where you can enter the values one at a line.


1 Answers

To make the text horizontally centered, you need to do two things:

  1. To center-align dropdown menu items, make the ComboBox owner-draw and draw the items yourself, center-aligned.
  2. To center-align the text area of the control, find the Edit control of the ComboBox and set ES_CENTER style for it to make it center-aligned as well.

enter image description here

You may also be interested to this post: ComboBox Text Align Vertically Center.

Example

To make the dropdown text align at center, you need to handle drawing of items yourself. To do so, set DrawMode property of ComboBox to OwnerDrawFixed. Then you can handle DrawItem event or override OnDrawItem.

To set the alignment of text area to center, you need to find the Edit control owned by ComboBox. To do so, you can use GetComboBoxInfo method which returns a COMBOBOXINFO. The next step is calling GetWindowLong method to get styles of the edit control and then add ES_CENTER and then call SetWindowLong to set the new style.

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyComboBox : ComboBox
{
    public MyComboBox()
    {
        DrawMode = DrawMode.OwnerDrawFixed;
    }

    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
    const int GWL_STYLE = -16;
    const int ES_LEFT = 0x0000;
    const int ES_CENTER = 0x0001;
    const int ES_RIGHT = 0x0002;
    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
        public int Width { get { return Right - Left; } }
        public int Height { get { return Bottom - Top; } }
    }
    [DllImport("user32.dll")]
    public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);

    [StructLayout(LayoutKind.Sequential)]
    public struct COMBOBOXINFO
    {
        public int cbSize;
        public RECT rcItem;
        public RECT rcButton;
        public int stateButton;
        public IntPtr hwndCombo;
        public IntPtr hwndEdit;
        public IntPtr hwndList;
    }
    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        SetupEdit();
    }
    private int buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
    private void SetupEdit()
    {
        var info = new COMBOBOXINFO();
        info.cbSize = Marshal.SizeOf(info);
        GetComboBoxInfo(this.Handle, ref info);
        var style = GetWindowLong(info.hwndEdit, GWL_STYLE);
        style |= 1;
        SetWindowLong(info.hwndEdit, GWL_STYLE, style);
    }
    protected override void OnDrawItem(DrawItemEventArgs e)
    {
        base.OnDrawItem(e);
        e.DrawBackground();
        var txt = "";
        if (e.Index >= 0)
            txt = GetItemText(Items[e.Index]);
        TextRenderer.DrawText(e.Graphics, txt, Font, e.Bounds,
            ForeColor, TextFormatFlags.Left | TextFormatFlags.HorizontalCenter);
    }
}

Note: I put the whole logic inside a derived control called MyComboBox to make it more reusable and easier to apply, however, obviously you can do this without inheritance and just by relying on the events of an existing ComboBox control. You can also enhance the code a bit by adding a TextAlignment property which allows setting the text alignment.

like image 175
Reza Aghaei Avatar answered Sep 23 '22 04:09

Reza Aghaei