VB.NET自定义ComboBox设为DropdownStyle=Dropdown时显示黑色的非WndProc解决方法
VB.NET自定义ComboBox Dropdown样式显示黑色的解决方法(不使用WndProc)
问题描述
开发自定义ComboBox组件时,将DropdownStyle设置为Dropdown时组件显示黑色,设置为DropDownList时显示正常,需在不使用WndProc的前提下解决该问题。
提供的自定义ComboBox代码
Imports System.ComponentModel Imports System.Drawing.Drawing2D Public Class FLATCOMBOBOX Inherits ComboBox ' Fields Private _disabledIndicatorColor As Color = Color.DarkGray Private _disabledColor As Color = Color.FromArgb(240, 240, 240) Private _disabledForeColor As Color = Color.FromArgb(&H6D, &H6D, &H6D) Private _disabledBorderColor As Color = Color.FromArgb(&HCC, &HCC, &HCC) Private _itemTopMargin As Integer = 1 Private _textLeftMargin As Integer = 5 Private _borderColor As Color = Color.Red Private _backColor As Color = Color.White Private _radius As Integer = 1 Private _borderthickness As BorderThickness Private _indicatorColor As Color = Color.Red ' Methods Public Sub New() Me.InitializeComponent() MyBase.SetStyle(ControlStyles.AllPaintingInWmPaint, True) MyBase.SetStyle(ControlStyles.ContainerControl, True) MyBase.SetStyle(ControlStyles.OptimizedDoubleBuffer, True) MyBase.SetStyle(ControlStyles.ResizeRedraw, True) MyBase.SetStyle(ControlStyles.Selectable, True) MyBase.SetStyle(ControlStyles.UserPaint, True) MyBase.SetStyle(ControlStyles.Selectable, True) MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True) Me.FlatStyle = FlatStyle.Flat Me.DrawMode = DrawMode.Normal Me.DropDownStyle = ComboBoxStyle.DropDown Me.Width = 260 Me.Height = &H20 Me.ItemHeight = &H1A Me.DrawMode = DrawMode.OwnerDrawFixed Me.IndicatorColor = Color.Red Me.DropdownBorderThickness = BorderThickness.Thin End Sub Private Sub DrawIndicator(ByVal graphics As Graphics, ByVal lineColor As Color, ByVal indicatorColor As Color, ByVal foreColor As Color) Dim num As Integer Dim pen As Pen graphics.SmoothingMode = SmoothingMode.AntiAlias graphics.SmoothingMode = SmoothingMode.HighQuality graphics.InterpolationMode = InterpolationMode.High Dim brush As New SolidBrush(Me._borderColor) Dim brush2 As New SolidBrush(Me._backColor) If Not Me.Enabled Then indicatorColor = Me._disabledIndicatorColor brush.Color = Me._disabledBorderColor brush2.Color = Me._disabledColor End If If Me.DropdownBorderThickness = BorderThickness.Thick Then pen = New Pen(brush, 2.0F) num = 1 Else pen = New Pen(brush, 1.0F) num = 0 End If Using p = New Pen(Me.BorderColor, 2) graphics.DrawRectangle(p, MyBase.ClientRectangle.X, MyBase.ClientRectangle.Y, MyBase.ClientRectangle.Width - 1, MyBase.ClientRectangle.Height - 1) End Using brush.Dispose() brush2.Dispose() pen.Dispose() End Sub <Category("Tools"), Description("Sets dropdown's border color.")> Public Overridable Property BorderColor As Color Get Return Me._borderColor End Get Set(ByVal value As Color) Me._borderColor = value Me.Refresh() End Set End Property <DisplayName("BackColor"), Category("Tools"), Description("Sets the dropdown's background color.")> Public Overridable Property BackgroundColor As Color Get Return Me._backColor End Get Set(ByVal value As Color) Me._backColor = value Me.Refresh() End Set End Property <Category("Tools"), Description("Sets the dropdown's border thickness.")> Public Overridable Property DropdownBorderThickness As BorderThickness Get Return Me._borderthickness End Get Set(ByVal value As Color) Me._borderthickness = value Me.Refresh() End Set End Property <Category("Tools"), Description("Sets the indicator color.")> Public Overridable Property IndicatorColor As Color Get Return Me._indicatorColor End Get Set(ByVal value As Color) Me._indicatorColor = value Me.Refresh() End Set End Property <Browsable(False)> Public Overridable Property Color As Color Get Return Me._borderColor End Get Set(ByVal value As Color) Me._borderColor = value Me.Refresh() End Set End Property Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs) If Me.Enabled Then Me.DrawIndicator(pe.Graphics, Me.Color, Me.IndicatorColor, Me.ForeColor) Else Me.DrawIndicator(pe.Graphics, Me._disabledBorderColor, Me._disabledBorderColor, Me._disabledForeColor) End If MyBase.OnPaint(pe) End Sub Public Enum BorderThickness Thick Thin End Enum End Class
解决方案
问题核心:当DropdownStyle为Dropdown时,ComboBox内部包含可编辑TextBox,开启UserPaint后未主动绘制控件背景,且原生BackColor未与自定义背景同步,导致未绘制区域显示GDI+默认黑色。
修复步骤
在OnPaint中提前填充控件背景
修改OnPaint方法,先填充整个客户端区域背景色,覆盖默认黑色:Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs) ' 先填充背景色,避免黑色区域透出 Using bgBrush As New SolidBrush(If(Me.Enabled, Me._backColor, Me._disabledColor)) pe.Graphics.FillRectangle(bgBrush, MyBase.ClientRectangle) End Using If Me.Enabled Then Me.DrawIndicator(pe.Graphics, Me.Color, Me.IndicatorColor, Me.ForeColor) Else Me.DrawIndicator(pe.Graphics, Me._disabledBorderColor, Me._disabledBorderColor, Me._disabledForeColor) End If MyBase.OnPaint(pe) End Sub同步原生BackColor与自定义BackgroundColor
在BackgroundColor属性的Set方法中同步原生BackColor,确保内部TextBox背景与控件一致:<DisplayName("BackColor"), Category("Tools"), Description("Sets the dropdown's background color.")> Public Overridable Property BackgroundColor As Color Get Return Me._backColor End Get Set(ByVal value As Color) Me._backColor = value MyBase.BackColor = value ' 同步原生BackColor Me.Refresh() End Set End Property同时在构造函数中初始化时添加同步:
Public Sub New() ' ...原有代码 Me._backColor = Color.White MyBase.BackColor = Me._backColor ' 初始化时同步 ' ...原有代码 End Sub清理DrawIndicator中的冗余代码
移除未使用的对象,优化边框绘制逻辑:Private Sub DrawIndicator(ByVal graphics As Graphics, ByVal lineColor As Color, ByVal indicatorColor As Color, ByVal foreColor As Color) graphics.SmoothingMode = SmoothingMode.HighQuality graphics.InterpolationMode = InterpolationMode.HighQualityBicubic Dim borderColor As Color = If(Me.Enabled, Me._borderColor, Me._disabledBorderColor) Dim borderWidth As Single = If(Me.DropdownBorderThickness = BorderThickness.Thick, 2.0F, 1.0F) ' 调整矩形避免边框被裁剪 Dim rect As New Rectangle( MyBase.ClientRectangle.X + CInt(borderWidth / 2), MyBase.ClientRectangle.Y + CInt(borderWidth / 2), MyBase.ClientRectangle.Width - borderWidth, MyBase.ClientRectangle.Height - borderWidth ) Using borderPen As New Pen(borderColor, borderWidth) graphics.DrawRectangle(borderPen, rect) End Using End Sub
内容的提问来源于stack exchange,提问作者dlaksmi
相关产品推荐
相关产品推荐

