- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
是否可以在 C# 中更改组合框下拉列表的边框颜色?
我想将白色边框更改为较暗的阴影以匹配深色方案。我搜索了 .net 文档并找到了 DropDownList.BorderStyle
属性。但是,我不确定这是否有效。我正在使用 WinForms。
这是我为组合框使用的类:
public class FlattenCombo : ComboBox
{
private Brush BorderBrush = new SolidBrush(SystemColors.WindowFrame);
private Brush ArrowBrush = new SolidBrush(SystemColors.ControlText);
private Brush DropButtonBrush = new SolidBrush(SystemColors.Control);
private Color _borderColor = Color.Black;
private ButtonBorderStyle _borderStyle = ButtonBorderStyle.Solid;
private static int WM_PAINT = 0x000F;
private Color _ButtonColor = SystemColors.Control;
public Color ButtonColor
{
get { return _ButtonColor; }
set
{
_ButtonColor = value;
DropButtonBrush = new SolidBrush(this.ButtonColor);
this.Invalidate();
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
switch (m.Msg)
{
case 0xf:
Graphics g = this.CreateGraphics();
Pen p = new Pen(Color.Black);
g.FillRectangle(BorderBrush, this.ClientRectangle);
//Draw the background of the dropdown button
Rectangle rect = new Rectangle(this.Width - 17, 0, 17, this.Height);
g.FillRectangle(DropButtonBrush, rect);
//Create the path for the arrow
System.Drawing.Drawing2D.GraphicsPath pth = new System.Drawing.Drawing2D.GraphicsPath();
PointF TopLeft = new PointF(this.Width - 13, (this.Height - 5) / 2);
PointF TopRight = new PointF(this.Width - 6, (this.Height - 5) / 2);
PointF Bottom = new PointF(this.Width - 9, (this.Height + 2) / 2);
pth.AddLine(TopLeft, TopRight);
pth.AddLine(TopRight, Bottom);
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
//Determine the arrow's color.
if (this.DroppedDown)
{
ArrowBrush = new SolidBrush(SystemColors.HighlightText);
}
else
{
ArrowBrush = new SolidBrush(SystemColors.ControlText);
}
//Draw the arrow
g.FillPath(ArrowBrush, pth);
break;
default:
break;
}
}
[Category("Appearance")]
public Color BorderColor
{
get { return _borderColor; }
set
{
_borderColor = value;
Invalidate(); // causes control to be redrawn
}
}
[Category("Appearance")]
public ButtonBorderStyle BorderStyle
{
get { return _borderStyle; }
set
{
_borderStyle = value;
Invalidate();
}
}
protected override void OnLostFocus(System.EventArgs e)
{
base.OnLostFocus(e);
this.Invalidate();
}
protected override void OnGotFocus(System.EventArgs e)
{
base.OnGotFocus(e);
this.Invalidate();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.Invalidate();
}
}
最佳答案
而FlatComboBoxAdapter确实是不可用的。仍然可以捕获 WM_CTLCOLORLISTBOX 窗口消息并将 native GDI 矩形应用于下拉边框。这是一些工作,但它完成了工作。 (如果你想跳过这个,底部有一个例子的链接)
首先,如果您不熟悉 WM_CTLCOLORLISTBOX 窗口消息,它是这样描述的:
"在系统绘制列表框之前发送给列表框的父窗口。通过响应该消息,父窗口可以使用指定的显示设备设置列表框的文本和背景颜色上下文句柄。”
消息常量定义如下:
const int WM_CTLCOLORLISTBOX = 0x0134;
定义消息常量后,在您的自定义 ComboBox 的重写 WndProc() 事件中为其设置条件:
protected override void WndProc(ref Message m)
{
// Filter window messages
switch (m.Msg)
{
// Draw a custom color border around the drop down pop-up
case WM_CTLCOLORLISTBOX:
base.WndProc(ref m);
DrawNativeBorder(m.LParam);
break;
default: base.WndProc(ref m); break;
}
}
DrawNativeBorder() 方法是我们将使用 Win API 绘制矩形的地方。它接受下拉列表的句柄作为参数。然而,在我们这样做之前,我们需要定义将要使用的 native 方法、枚举和结构:
public enum PenStyles
{
PS_SOLID = 0,
PS_DASH = 1,
PS_DOT = 2,
PS_DASHDOT = 3,
PS_DASHDOTDOT = 4
}
public enum ComboBoxButtonState
{
STATE_SYSTEM_NONE = 0,
STATE_SYSTEM_INVISIBLE = 0x00008000,
STATE_SYSTEM_PRESSED = 0x00000008
}
[StructLayout(LayoutKind.Sequential)]
public struct COMBOBOXINFO
{
public Int32 cbSize;
public RECT rcItem;
public RECT rcButton;
public ComboBoxButtonState buttonState;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[DllImport("user32.dll")]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[DllImport("user32.dll")]
public static extern IntPtr SetFocus(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
[DllImport("gdi32.dll")]
public static extern int ExcludeClipRect(IntPtr hdc, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect);
[DllImport("gdi32.dll")]
public static extern IntPtr CreatePen(PenStyles enPenStyle, int nWidth, int crColor);
[DllImport("gdi32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hObject);
[DllImport("gdi32.dll")]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport("gdi32.dll")]
public static extern void Rectangle(IntPtr hdc, int X1, int Y1, int X2, int Y2);
public static int RGB(int R, int G, int B)
{
return (R | (G << 8) | (B << 16));
}
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left_, int top_, int right_, int bottom_)
{
Left = left_;
Top = top_;
Right = right_;
Bottom = bottom_;
}
public override bool Equals(object obj)
{
if (obj == null || !(obj is RECT))
{
return false;
}
return this.Equals((RECT)obj);
}
public bool Equals(RECT value)
{
return this.Left == value.Left &&
this.Top == value.Top &&
this.Right == value.Right &&
this.Bottom == value.Bottom;
}
public int Height
{
get
{
return Bottom - Top + 1;
}
}
public int Width
{
get
{
return Right - Left + 1;
}
}
public Size Size { get { return new Size(Width, Height); } }
public Point Location { get { return new Point(Left, Top); } }
// Handy method for converting to a System.Drawing.Rectangle
public System.Drawing.Rectangle ToRectangle()
{
return System.Drawing.Rectangle.FromLTRB(Left, Top, Right, Bottom);
}
public static RECT FromRectangle(Rectangle rectangle)
{
return new RECT(rectangle.Left, rectangle.Top, rectangle.Right, rectangle.Bottom);
}
public void Inflate(int width, int height)
{
this.Left -= width;
this.Top -= height;
this.Right += width;
this.Bottom += height;
}
public override int GetHashCode()
{
return Left ^ ((Top << 13) | (Top >> 0x13))
^ ((Width << 0x1a) | (Width >> 6))
^ ((Height << 7) | (Height >> 0x19));
}
public static implicit operator Rectangle(RECT rect)
{
return System.Drawing.Rectangle.FromLTRB(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
public static implicit operator RECT(Rectangle rect)
{
return new RECT(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
}
DrawNativeBorder() 方法定义为:
/// <summary>
/// Non client area border drawing
/// </summary>
/// <param name="handle">The handle to the control</param>
public static void DrawNativeBorder(IntPtr handle)
{
// Define the windows frame rectangle of the control
RECT controlRect;
GetWindowRect(handle, out controlRect);
controlRect.Right -= controlRect.Left; controlRect.Bottom -= controlRect.Top;
controlRect.Top = controlRect.Left = 0;
// Get the device context of the control
IntPtr dc = GetWindowDC(handle);
// Define the client area inside the control rect so it won't be filled when drawing the border
RECT clientRect = controlRect;
clientRect.Left += 1;
clientRect.Top += 1;
clientRect.Right -= 1;
clientRect.Bottom -= 1;
ExcludeClipRect(dc, clientRect.Left, clientRect.Top, clientRect.Right, clientRect.Bottom);
// Create a pen and select it
Color borderColor = Color.Magenta;
IntPtr border = WinAPI.CreatePen(WinAPI.PenStyles.PS_SOLID, 1, RGB(borderColor.R,
borderColor.G, borderColor.B));
// Draw the border rectangle
IntPtr borderPen = SelectObject(dc, border);
Rectangle(dc, controlRect.Left, controlRect.Top, controlRect.Right, controlRect.Bottom);
SelectObject(dc, borderPen);
DeleteObject(border);
// Release the device context
ReleaseDC(handle, dc);
SetFocus(handle);
}
我使用洋红色来清楚地显示这幅画。这将完成边界绘画。然而,还有一个问题。当下拉菜单显示并且鼠标没有移到下拉菜单项上时,默认边框仍然显示。要处理该问题,您必须确定下拉菜单何时完全打开。然后发送一个我们自己的WM_CTLCOLORLISTBOX消息来更新边框。
我使用计时器粗略地检查下拉显示时刻。我尝试了其他各种选择,但没有成功。老实说,如果有人有更好的解决方案,那就太好了。
您需要一个计时器来检查下拉列表何时真正完全下降:
private Timer _dropDownCheck = new Timer();
计时器是您自定义组合框中的一个字段。在 InitializeComponent() 之后在您的自定义组合框构造函数中进行设置:
_dropDownCheck.Interval = 100;
_dropDownCheck.Tick += new EventHandler(dropDownCheck_Tick);
覆盖自定义组合框的 OnDropDown() 事件,并设置定时器滴答事件:
/// <summary>
/// On drop down
/// </summary>
protected override void OnDropDown(EventArgs e)
{
base.OnDropDown(e);
// Start checking for the dropdown visibility
_dropDownCheck.Start();
}
/// <summary>
/// Checks when the drop down is fully visible
/// </summary>
private void dropDownCheck_Tick(object sender, EventArgs e)
{
// If the drop down has been fully dropped
if (DroppedDown)
{
// Stop the time, send a listbox update
_dropDownCheck.Stop();
Message m = GetControlListBoxMessage(this.Handle);
WndProc(ref m);
}
}
最后,创建以下方法来获取下拉句柄并创建 WM_CTLCOLORLISTBOX 消息以发送到控件:
/// <summary>
/// Creates a default WM_CTLCOLORLISTBOX message
/// </summary>
/// <param name="handle">The drop down handle</param>
/// <returns>A WM_CTLCOLORLISTBOX message</returns>
public Message GetControlListBoxMessage(IntPtr handle)
{
// Force non-client redraw for focus border
Message m = new Message();
m.HWnd = handle;
m.LParam = GetListHandle(handle);
m.WParam = IntPtr.Zero;
m.Msg = WM_CTLCOLORLISTBOX;
m.Result = IntPtr.Zero;
return m;
}
/// <summary>
/// Gets the list control of a combo box
/// </summary>
/// <param name="handle">Handle of the combo box itself</param>
/// <returns>A handle to the list</returns>
public static IntPtr GetListHandle(IntPtr handle)
{
COMBOBOXINFO info;
info = new COMBOBOXINFO();
info.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(info);
return GetComboBoxInfo(handle, ref info) ? info.hwndList : IntPtr.Zero;
}
就是这样,如果您仍然感到困惑,那么看一下我提供的这个示例 VS 2010 自定义组合框项目中的控件可能会更容易:
http://www.pyxosoft.com/downloads/CustomComboBoxBorderColor.zip
关于c# - 在 C# 中更改组合框下拉列表边框颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20831951/
我有一个像这样的数组 var resultsArray = [ { name: "BMW", value: "BMW", text: "BMW" }, { name: "Mercedes-Benz",
我正在尝试实现发现的下拉检查列表 here在 ASP.NET ListBox 控件上。它将控件呈现为下拉列表,并应用所有 css。但是,这些选项不是预期的复选框,而是单选按钮。有谁知道为什么当我让它与
如何使用 Javascript 在下拉列表的更改事件中获取先前选择的索引。 最佳答案 不,这是不可能的,但您可以在 onchange 事件中使用一个变量来跟踪之前的选择 示例: var previou
我想使用一个名为 dropdown-check-list 的插件: http://code.google.com/p/dropdown-check-list/ 但是,它的某些功能似乎与谷歌浏览器不兼容
我正在尝试找出如何制作类似于苹果商店的过滤选项的过滤选项。我首先想到的是类似于网站的下拉列表。但xcode中的对象选项上似乎没有它。想知道我应该从哪里开始才能实现这种功能。 和这个类似 http://
我正在尝试为类别创建一个下拉列表。如果这检查没问题,那么它必须是数据库。 型号: 分类 var $hasMany = 'Product'; 产品 var $belongsTo = 'Category'
有六个问题要问用户。如果用户回答了这些问题,我正在尝试制作一个应用程序,该应用程序将确定在右侧使用哪种研究设计的结果。我正在用 python dash 做这个应用程序。我的 Python 代码如下。如
我的问题是我所问问题的延续,请参阅链接。 Load Country/State/City 我已经展开以从数据库加载我的下拉列表,我只需要一种方法在我的第一个下拉列表和第二个下拉列表中连接 onchan
我正在尝试为一家餐厅创建一个内部成本核算电子表格。我重新熟悉了如何创建下拉列表(在本例中用于选择成分)。 当有人选择例如从下拉列表中选择“胡萝卜”,我希望其他字段能够使用另一个电子表格中的成本数据自动
JavaScript/jQuery 新手。我在有序列表中显示了一些数据,如下所示 Data 0 Data 1. Da
我在其中一个主题上发现了这一点: http://jsfiddle.net/GHzfD/357/我想问一下从下拉列表中选择图像后如何提醒(路径)。 $("body select").msDropDow
我使用 JAVA Swing 创建了一个下拉列表。当我选择“跟踪 RCM 的状态:”时,我想在所选选项旁边创建另一个下拉列表。我应该使用 mouseactionlistener 代替吗?我试图完成类似
在 Symfony2 网站中,我尝试制作一个包含 2 个(或 3 个)下拉列表的表单,其依赖关系为国家 > 地区 > 城市。该城市是我正在使用表单编辑的元素的字段。这个想法是根据选择来填充列表。 我已
我正在尝试创建一个菜单来计算 的数量如果列表中的数量超过 5 个,请将其余的移动到下拉列表中。 基本上代码如下所示: Item 1 Item 2 Item 3 Item 4 I
当我点击要安装主题的部门时,当我点击主题时要安装的服务。但当我点击服务时却没有看到问题。我认为对json的描述不准确。你能帮我解决这个问题吗?谢谢。我的 Jquery 代码; /* Select';
我有一个包含两个值的下拉列表:Sponsor 和 Social_Worker。我想要做的是,当选择其中一个时,它会显示一个 div 并隐藏另一个 div,如果选择另一个则反之亦然。我设法使用按钮执行此
我正在创建 2 个下拉列表,第二个下拉列表基于对第一个下拉列表的选择。从mysql数据库中获取数据 索引.php P
我正在尝试使用 JS 创建互斥的下拉菜单。 只能从这 4 个操作系统中选择一个:image 当一个被选中时,其他的应该被禁用。 HTML 部分: Re
首先,我是 java 脚本的新手。我正在开发我的 Web 应用程序,我有一个下拉菜单,其中包含人员列表。使用它我知道如何传递一个人的选定值。但是我如何选择多个值(人名)并将该数据发送到后端实现。是否可
我正在使用 Laravel 框架,并且有两个下拉列表,它们都从数据库表中读取数据, 第一个它从表中读取所有记录并将其填充到选择列表中 这是我的代码: {{Form::select
我是一名优秀的程序员,十分优秀!