如何更改组合框下拉按钮的颜色
Posted
技术标签:
【中文标题】如何更改组合框下拉按钮的颜色【英文标题】:How to change the ComboBox dropdown button color 【发布时间】:2021-01-31 06:05:13 【问题描述】:如何更改滑动按钮的颜色? 不是边框颜色,也不是幻灯片项目颜色。
我已经更改了幻灯片项目的颜色
有什么办法可以改变颜色吗?
【问题讨论】:
***.com/questions/6468024/… 这不是我的麻烦。我想改变▾这个按钮的背景颜色 也许在这个线程上为自定义控件添加一个标签? =) 【参考方案1】:Flat ComboBox - 更改边框颜色和下拉按钮颜色
您需要自己处理WM_PAINT
并绘制边框和下拉矩形。这就是 .Net Framework 内部 ComboBox.FlatComboAdapter
类的工作方式。
在这篇文章中,我创建了一个FlatComboBox
,它以平面样式绘制边框和下拉菜单,具有以下附加属性:
代码如下:
using System;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class FlatComboBox : ComboBox
private Color borderColor = Color.Gray;
[DefaultValue(typeof(Color), "Gray")]
public Color BorderColor
get return borderColor;
set
if (borderColor != value)
borderColor = value;
Invalidate();
private Color buttonColor = Color.LightGray;
[DefaultValue(typeof(Color), "LightGray")]
public Color ButtonColor
get return buttonColor;
set
if (buttonColor != value)
buttonColor = value;
Invalidate();
protected override void WndProc(ref Message m)
if (m.Msg == WM_PAINT && DropDownStyle != ComboBoxStyle.Simple)
var clientRect = ClientRectangle;
var dropDownButtonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
var outerBorder = new Rectangle(clientRect.Location,
new Size(clientRect.Width - 1, clientRect.Height - 1));
var innerBorder = new Rectangle(outerBorder.X + 1, outerBorder.Y + 1,
outerBorder.Width - dropDownButtonWidth - 2, outerBorder.Height - 2);
var innerInnerBorder = new Rectangle(innerBorder.X + 1, innerBorder.Y + 1,
innerBorder.Width - 2, innerBorder.Height - 2);
var dropDownRect = new Rectangle(innerBorder.Right + 1, innerBorder.Y,
dropDownButtonWidth, innerBorder.Height + 1);
if (RightToLeft == RightToLeft.Yes)
innerBorder.X = clientRect.Width - innerBorder.Right;
innerInnerBorder.X = clientRect.Width - innerInnerBorder.Right;
dropDownRect.X = clientRect.Width - dropDownRect.Right;
dropDownRect.Width += 1;
var innerBorderColor = Enabled ? BackColor : SystemColors.Control;
var outerBorderColor = Enabled ? BorderColor : SystemColors.ControlDark;
var buttonColor = Enabled ? ButtonColor : SystemColors.Control;
var middle = new Point(dropDownRect.Left + dropDownRect.Width / 2,
dropDownRect.Top + dropDownRect.Height / 2);
var arrow = new Point[]
new Point(middle.X - 3, middle.Y - 2),
new Point(middle.X + 4, middle.Y - 2),
new Point(middle.X, middle.Y + 2)
;
var ps = new PAINTSTRUCT();
bool shoulEndPaint = false;
IntPtr dc;
if (m.WParam == IntPtr.Zero)
dc = BeginPaint(Handle, ref ps);
m.WParam = dc;
shoulEndPaint = true;
else
dc = m.WParam;
var rgn = CreateRectRgn(innerInnerBorder.Left, innerInnerBorder.Top,
innerInnerBorder.Right, innerInnerBorder.Bottom);
SelectClipRgn(dc, rgn);
DefWndProc(ref m);
DeleteObject(rgn);
rgn = CreateRectRgn(clientRect.Left, clientRect.Top,
clientRect.Right, clientRect.Bottom);
SelectClipRgn(dc, rgn);
using (var g = Graphics.FromHdc(dc))
using (var b = new SolidBrush(buttonColor))
g.FillRectangle(b, dropDownRect);
using (var b = new SolidBrush(outerBorderColor))
g.FillPolygon(b, arrow);
using (var p = new Pen(innerBorderColor))
g.DrawRectangle(p, innerBorder);
g.DrawRectangle(p, innerInnerBorder);
using (var p = new Pen(outerBorderColor))
g.DrawRectangle(p, outerBorder);
if (shoulEndPaint)
EndPaint(Handle, ref ps);
DeleteObject(rgn);
else
base.WndProc(ref m);
private const int WM_PAINT = 0xF;
[StructLayout(LayoutKind.Sequential)]
public struct RECT
public int L, T, R, B;
[StructLayout(LayoutKind.Sequential)]
public struct PAINTSTRUCT
public IntPtr hdc;
public bool fErase;
public int rcPaint_left;
public int rcPaint_top;
public int rcPaint_right;
public int rcPaint_bottom;
public bool fRestore;
public bool fIncUpdate;
public int reserved1;
public int reserved2;
public int reserved3;
public int reserved4;
public int reserved5;
public int reserved6;
public int reserved7;
public int reserved8;
[DllImport("user32.dll")]
private static extern IntPtr BeginPaint(IntPtr hWnd,
[In, Out] ref PAINTSTRUCT lpPaint);
[DllImport("user32.dll")]
private static extern bool EndPaint(IntPtr hWnd, ref PAINTSTRUCT lpPaint);
[DllImport("gdi32.dll")]
public static extern int SelectClipRgn(IntPtr hDC, IntPtr hRgn);
[DllImport("user32.dll")]
public static extern int GetUpdateRgn(IntPtr hwnd, IntPtr hrgn, bool fErase);
public enum RegionFlags
ERROR = 0,
NULLREGION = 1,
SIMPLEREGION = 2,
COMPLEXREGION = 3,
[DllImport("gdi32.dll")]
internal static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
private static extern IntPtr CreateRectRgn(int x1, int y1, int x2, int y2);
【讨论】:
我建议您反转您的流量控制。无需在每条 Windows 消息(包括您不关心的消息)上运行所有这些。您可以通过执行类似if (!youCareAboutThisMessage) base.WndProc(ref m); return;
的操作来短路
@Zer0 有道理,我没有反转控制流,但我将声明移到了 if 块中。就像一个侧节点:这是一个非常快速的实现,我假设未来的读者自己关心性能。在为生产环境实施某些东西时,应该考虑很多因素。我会留给未来的读者做更多的优化/修正。
@mr.G 您可能对FlatNumericUpdown 和TextBox with BorderColor 感兴趣。
@RezaAghaei 非常感谢 :) ,但代码中存在一些问题如果我使用下拉样式 dropdownList,combobox1.text 不可见
@mr.G 我会看看并更新答案。以上是关于如何更改组合框下拉按钮的颜色的主要内容,如果未能解决你的问题,请参考以下文章