Windows 更改组合框中嵌入式编辑控件的背景色

Windows 更改组合框中嵌入式编辑控件的背景色,windows,vb.net,winforms,combobox,gdi,Windows,Vb.net,Winforms,Combobox,Gdi,我正在尝试创建一个带有圆角的自定义组合框,在这里我仍然能够通过用户输入编辑文本。到目前为止,我的解决方案允许我有一个像样的组合框,但只有在DropDownList样式下,我想多做一点,尝试绘制当组合框设置为DropDown时出现的嵌入式EditControl。到目前为止,我的解决方案是 Public Sub New() ' Esta llamada es exigida por el diseñador. InitializeComponent()

我正在尝试创建一个带有圆角的自定义组合框,在这里我仍然能够通过用户输入编辑文本。到目前为止,我的解决方案允许我有一个像样的组合框,但只有在DropDownList样式下,我想多做一点,尝试绘制当组合框设置为DropDown时出现的嵌入式EditControl。到目前为止,我的解决方案是

Public Sub New()

        ' Esta llamada es exigida por el diseñador.
        InitializeComponent()

        ' Agregue cualquier inicialización después de la llamada a InitializeComponent().
        Me.SetStyle(ControlStyles.UserPaint _
                    Or ControlStyles.AllPaintingInWmPaint _
                    Or ControlStyles.Opaque _
                    Or ControlStyles.ResizeRedraw, True)
        Me.m_ControlBuffer = New Bitmap(Me.Width, Me.Height)
        Me.m_ControlGraphics = Graphics.FromImage(m_ControlBuffer)
        Me.m_BackBuffer = New Bitmap(Me.Width, Me.Height)
        Me.m_BackGraphics = Graphics.FromImage(m_BackBuffer)

        Dim backcolor As Color = If(Enabled, m_UITheme.TextBoxColor, Color.White)
        BackgroundBrush = New SolidBrush(backcolor)
        Me.BackColor = backcolor
    End Sub
油漆的方法是

Public Sub CustomPaint(screenGraphics As Graphics)
        ' If there is body to be drawn.
        If Me.Width > 0 AndAlso Me.Height > 0 Then
            ' Clear the background image graphics 
            If Me.m_backImage Is Nothing Then
                '   Cached Background Image
                Me.m_backImage = New Bitmap(Me.Width, Me.Height)
                Dim backGraphics As Graphics = Graphics.FromImage(Me.m_backImage)
                backGraphics.Clear(Color.Transparent)
                Me.PaintTransparentBackground(backGraphics, Me.ClientRectangle)
            End If

            m_BackGraphics.Clear(Color.Transparent)
            m_BackGraphics.DrawImageUnscaled(Me.m_backImage, 0, 0)

            m_ControlGraphics.Clear(Color.Transparent)
            m_ControlGraphics.SmoothingMode = SmoothingMode.HighQuality

            ' Begin drawing
            Dim path As GraphicsPath = GetBoxBorder()
            m_ControlGraphics.FillPath(BackgroundBrush, path)

            PaintArrowAndLine(m_ControlGraphics)

            ' Draw text
            DrawText(m_ControlGraphics)

            m_ControlGraphics.Flush()

            m_BackGraphics.DrawImage(m_ControlBuffer,
                                         New Rectangle(0, 0,
                                                       m_ControlBuffer.Width,
                                                       m_ControlBuffer.Height),
                                         0, 0,
                                         m_ControlBuffer.Width,
                                         m_ControlBuffer.Height,
                                         GraphicsUnit.Pixel)
            m_BackGraphics.Flush()

            '   Now paint this to the screen
            screenGraphics.DrawImageUnscaled(m_BackBuffer, 0, 0)
        End If
    End Sub
问题是,对于下拉样式,白色EditControl显示在我的图形顶部。在其他论坛上搜索时,我得到了一个控制手柄的想法,也许我可以改变颜色。 然后我找到了我认为可以帮助我做的事情的方法。上面说,

如果应用程序处理此消息,它必须返回画笔的句柄。系统使用笔刷绘制编辑控件的背景

因此,我试图在组合框的WndProc上捕获该消息,并将该消息的结果(据我所知,它是WM_CTLCOLOREDIT的返回值)更改为指向我正在创建的笔刷的指针

<DllImport("gdi32.dll")>
Public Shared Function CreateSolidBrush(ByVal color As Integer) As IntPtr
End Function
Protected Overrides Sub WndProc(ByRef m As Message)
    If (m.Msg = &H133) Then
        Dim brush As IntPtr = CreateSolidBrush(RGB(255, 0, 0))
        m.Result = brush
    End If
    MyBase.WndProc(m)

End Sub
它确实会绘制红色矩形,但当我将焦点放在控件上时除外。见下图,


同时,我觉得自己离解决方案非常近。

如果想获得编辑控件的句柄,请使用GetComboBoxInfo,例如,如图所示。另外,请参见此处的注释和一些注释:您可能会发现您使用的.Net Framework版本会有所不同。处理
CB_GETCURSEL
消息的方式只是其中一个可能的区别。要设计具有平滑圆角区域的用户控件/自定义控件,请参见此处:,这可能会有所帮助。此选项以不同的方式生成圆形边界(不是区域):
Private hBrush As IntPtr = CreateSolidBrush(RGB(255, 0, 0))
    Protected Overrides Sub WndProc(ByRef m As Message)

        If (m.Msg = &H133) Then
            m.Result = hBrush
        Else
            MyBase.WndProc(m)
        End If

    End Sub