如何在 WinForms 的 ComboBox 中居中对齐所选项目?

     2023-03-05     224

关键词:

【中文标题】如何在 WinForms 的 ComboBox 中居中对齐所选项目?【英文标题】:How to center-align a selected Item in a ComboBox in WinForms? 【发布时间】:2020-03-13 08:21:00 【问题描述】:

我有一个带有 ComboBox 的表单。我找到了帖子:http://blog.michaelgillson.org/2010/05/18/left-right-center-where-do-you-align/,它帮助我将下拉列表中的所有项目居中对齐。问题是所选项目(comboBox.Text 属性中显示的项目)保持左对齐。

如何将所选项目也居中对齐? 代码是:

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.
            
        
    


【问题讨论】:

您还需要覆盖 Paint 事件来执行此操作。我建议您从ComboBox 控件创建一个新的派生类,并同时覆盖OnPaintOnDrawItem Center the text of a combobox 也应该有帮助。 【参考方案1】:

要使文本水平居中,你需要做两件事:

    要使下拉菜单项居中对齐,请让 ComboBox 所有者绘制并自己绘制项目,居中对齐。 要使控件的文本区域居中对齐,请找到ComboBoxEdit 控件并为其设置ES_CENTER 样式以使其也居中对齐。

您可能也对此帖子感兴趣:ComboBox Text Align Vertically Center。

示例

要使下拉文本居中对齐,您需要自己处理项目的绘制。为此,请将ComboBoxDrawMode 属性设置为OwnerDrawFixed。然后您可以处理DrawItem 事件或覆盖OnDrawItem

要设置文本区域居中对齐,您需要找到ComboBox 拥有的Edit 控件。为此,您可以使用返回COMBOBOXINFOGetComboBoxInfo 方法。下一步是调用GetWindowLong方法获取编辑控件的样式,然后添加ES_CENTER,然后调用SetWindowLong设置新的样式。

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);
    

注意:我将整个逻辑放在一个名为 MyComboBox 的派生控件中,以使其更易于重用且更易于应用,但是,显然您可以在没有继承的情况下执行此操作,只需依赖现有 ComboBox 的事件即可控制。您还可以通过添加允许设置文本对齐的TextAlignment 属性来稍微增强代码。

【讨论】:

我将整个逻辑放在一个名为 MyComboBox 的派生控件中,以使其更可重用且更易于应用,但是,显然您可以在没有继承的情况下仅依靠现有事件的事件来执行此操作ComboBox 控制。 支持/兼容的函数应该是GetWindowLongPtrSetWindowLongPtr(我也忘记提了,刚想起来)。我发现这个声明在我测试过的所有情况下都有效:[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] internal static extern IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);GetWindowLongPtr 也一样(当然,IntPtr dwNewLong 除外)。在 32 位应用程序中,这些功能会自动回退到以前的版本。

C# - Winforms - Combobox - 避免选择更新数据源的第一项

】C#-Winforms-Combobox-避免选择更新数据源的第一项【英文标题】:C#-Winforms-Combobox-Avoidselectingthefirstitemupdatingthedatasource【发布时间】:2022-01-0815:59:27【问题描述】:我的应用程序中有一个组合框,根据您可以在文本字段中输入的搜... 查看详情

检测何时在 Winforms 上单击 ComboBox

】检测何时在Winforms上单击ComboBox【英文标题】:DetectwhenComboBoxisclickedonWinforms【发布时间】:2021-07-0102:56:03【问题描述】:当我的combobox被点击(未更改索引)时,我正在尝试执行一项操作。基本上,每次用户单击组合框时,我... 查看详情

覆盖 Winforms ComboBox 自动完成建议规则

】覆盖WinformsComboBox自动完成建议规则【英文标题】:OverrideWinformsComboBoxAutocompleteSuggestRule【发布时间】:2011-01-1613:47:30【问题描述】:我正在尝试修改Windows.FormsComboBox的行为,以便自动完成下拉菜单根据我指定的规则显示项目。... 查看详情

有没有一种简单的方法可以在 WinForms 中实现 Checked Combobox [重复]

】有没有一种简单的方法可以在WinForms中实现CheckedCombobox[重复]【英文标题】:IsthereasimplewaytoimplementaCheckedComboboxinWinForms[duplicate]【发布时间】:2012-02-0800:14:26【问题描述】:有谁知道WinForms中选中的组合框的简单实现?谷歌搜索... 查看详情

在 C# .net winforms 中将字典绑定到 ComboBox

】在C#.netwinforms中将字典绑定到ComboBox【英文标题】:BindingDictionarytoComboBoxinC#.netwinforms【发布时间】:2021-10-0312:43:47【问题描述】:这应该是一个重复的问题,但我发布它是因为任何地方的答案都不起作用。我有一本类型的字典... 查看详情

C# Combobox (Dropdownstyle = Simple) -- 如何在键入时选择项目

...02-1019:59:05【问题描述】:我的表单上有一个Combobox控件(WinForms,.NET3.5),它的DropDownStyle属性设置为Simple。假设它填充了字母表中的字母, 查看详情

当 DataSource 值更改时,WinForms ComboBox 中的项目不会更新

】当DataSource值更改时,WinFormsComboBox中的项目不会更新【英文标题】:ItemsinWinFormsComboBoxnotupdatingwhenDataSourcevalueschange【发布时间】:2015-11-1212:40:22【问题描述】:我有一个通过数据源绑定到列表的组合框。出于某种原因,当数据... 查看详情

C# WinForms ComboBox:AutoComplete 不按降序排序

】C#WinFormsComboBox:AutoComplete不按降序排序【英文标题】:C#WinFormsComboBox:AutoCompletedoesnotsortdescending【发布时间】:2021-08-1518:54:06【问题描述】:在WinForms数据查看器项目中,我制作了一个ComboBox来选择过滤器值。列表项来自数据库... 查看详情

WinForms ComboBox DropDown 和 Autocomplete 窗口都出现

】WinFormsComboBoxDropDown和Autocomplete窗口都出现【英文标题】:WinFormsComboBoxDropDownandAutocompletewindowbothappear【发布时间】:2011-03-0503:13:06【问题描述】:我在一个winforms应用程序上有一个ComboBox,代码如下:comboBox1.AutoCompleteMode=AutoComple... 查看详情

Winforms Databound Combobox 更新数据但不改变 RowState

】WinformsDataboundCombobox更新数据但不改变RowState【英文标题】:WinformsDataboundComboboxupdatesdatabutdoesnotchangeRowState【发布时间】:2021-01-2120:09:26【问题描述】:.NET4.7.2Winformsc#有一个包含一堆组合框的表单。所有人的下拉列表。组合框... 查看详情

Winforms - 如何在设计器中显示/隐藏元素?

】Winforms-如何在设计器中显示/隐藏元素?【英文标题】:Winforms-howtoshow/hideelementsindesigner?【发布时间】:2012-04-1710:13:55【问题描述】:我正在尝试使用winforms制作多页应用程序。我决定使用多个面板-每个面板代表不同的页面,... 查看详情

如何禁用 C# 组合框中元素的编辑?

...13:14:48【问题描述】:我在ComboBox中有一些元素(带有C#的WinForms)。我希望他们的内容是静态的,以便用户在运行应用程序时无法更改其中的值。我也不希望用户向ComboBox添加新值【问题讨论】:【参考方案1】:使用ComboStyle属性... 查看详情

如何在winforms中找到并关闭任何打开的OleDbConnections?

】如何在winforms中找到并关闭任何打开的OleDbConnections?【英文标题】:HowtofindandcloseanyopenOleDbConnectionsinwinforms?【发布时间】:2016-11-1616:17:08【问题描述】:首先:我看到了很多关于这个主题的堆栈讨论(以及在其他论坛上)。不... 查看详情

如何在随机生成的数字中添加逗号 C# winforms [重复]

】如何在随机生成的数字中添加逗号C#winforms[重复]【英文标题】:HowtoaddcommainrandomgeneratednumbersC#winforms[duplicate]【发布时间】:2015-11-2818:29:18【问题描述】:目前我有这个代码:privatevoidbutton1_Click(objectsender,EventArgse)label1.Text=(newRan... 查看详情

如何在 winforms 设计器中访问继承的控件

】如何在winforms设计器中访问继承的控件【英文标题】:Howtoaccessinheritedcontrolsinthewinformsdesigner【发布时间】:2010-11-0523:44:41【问题描述】:我正在制作一些控件,它们都必须具有相同的外观和一些共同的行为,尽管它们适用于不... 查看详情

如何在winforms的WebBrowser控件中调用javascript?

】如何在winforms的WebBrowser控件中调用javascript?【英文标题】:HowtocallJavaScriptinsideaWebBrowsercontrol?【发布时间】:2015-01-3021:26:33【问题描述】:我想像这样调用javascript函数“Goto”:javascript:Goto(\'DM_NEW_OBJECT.ASPX?DM_CAT_ID=2063&amp;DM_P... 查看详情

如何在 WinForms 中禁用 TreeView 的节点重命名?

】如何在WinForms中禁用TreeView的节点重命名?【英文标题】:HowcanIdisablenoderenamingfortheTreeViewinWinForms?【发布时间】:2011-06-2205:21:56【问题描述】:是否可以在单击树节点时禁用进入“重命名”模式的选项?我不想完全禁用重命名... 查看详情

如何在 WPF/Winforms/C# 中打开 FileDialog 引用?

】如何在WPF/Winforms/C#中打开FileDialog引用?【英文标题】:HowtogetopenedFileDialogreferencesinWPF/Winforms/C#?【发布时间】:2020-06-1621:07:23【问题描述】:我正在尝试构建一个将FileDialog同步到特定路径的应用程序。我自己没有打开FileDialog... 查看详情