Как я могу использовать метод ControlPaint.DrawBorder для изменения цвета границы ComboBox? - PullRequest
0 голосов
/ 09 января 2019

У меня есть требование установить цвет границы элемента управления Combobox.
Я искал в Google пример кода, который реализовывал ControlPaint.Drawborder.
То, что я нашел, не идеально. Цвет рамки не изменяется.
В приведенном ниже коде вы увидите две ключевые функции WndProc и PaintControlBorder(), которые используются для получения основных событий окон и их обработки.
Последний используется для рисования границы элемента управления. После отладки в Visual Studio я обнаружил, что код в функции PaintControlBorder() был выполнен.

Почему цвет границы не меняется?

[ToolboxItem(true)]
public class ModifiedComboBox : ComboBox
{
    new public System.Windows.Forms.DrawMode DrawMode { get; set; }
    public Color HighlightColor { get; set; } //set select item highlight color 
    private IntPtr hDC;
    private Graphics gdc;
    private const int WM_ERASEBKGND = 0x14; // some windows message id 
    private const int WM_PAINT = 0xF;
    private const int WM_NC_PAINT = 0x85;
    private const int WM_PRINTCLIENT = 0x318;
    private const int WM_MOUSEHOVER = 0x2A1;
    private const int WM_MOUSELEAVE = 0x2A3;

    [DllImport("user32")]
    private static extern IntPtr GetDC(IntPtr hWnd);
    private Rectangle rectale;

    public ModifiedComboBox()
    {
        hDC = GetDC(Handle);
        gdc = Graphics.FromHdc(hDC);
        SetStyle(ControlStyles.Selectable, false);
        base.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
        this.HighlightColor = Color.Gray;
        this.DrawItem += new DrawItemEventHandler(AdvancedComboBox_DrawItem); //t bind draw item handler

        rectale = new Rectangle(0, 0, Width, Height);
    }

    public void AdvancedComboBox_DrawItem(object sender, DrawItemEventArgs e)
    {
        if (e.Index < 0)
            return;

        ComboBox combo = sender as ComboBox;
        if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
        {
            e.Graphics.FillRectangle(new SolidBrush(HighlightColor), e.Bounds);
            //e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font, new SolidBrush(combo.BackColor), new Point(e.Bounds.X, e.Bounds.Y));

            e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font, new SolidBrush(combo.ForeColor), new Point(e.Bounds.X, e.Bounds.Y));
        }
        else
        {
            e.Graphics.FillRectangle(new SolidBrush(combo.BackColor), e.Bounds);
            e.Graphics.DrawString(combo.Items[e.Index].ToString(), e.Font, new SolidBrush(combo.ForeColor), new Point(e.Bounds.X, e.Bounds.Y));
        }
        e.DrawFocusRectangle();
    }

    protected override void WndProc(ref Message m)// windows message handler
    {
        if (this.DropDownStyle == ComboBoxStyle.Simple)
        {
            base.WndProc(ref m);
            return;
        }

        switch (m.Msg)
        {
            case WM_NC_PAINT:
                break;
            case WM_PAINT:
                base.WndProc(ref m);

                PaintControlBorder();
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }
    private void PaintControlBorder()
    {
            ControlPaint.DrawBorder(gdc, this.ClientRectangle, Color.Orange, ButtonBorderStyle.Solid);
    }
}

1 Ответ

0 голосов
/ 09 января 2019

В Windows Forms вы никогда не сохраняете графический объект элемента управления.
Вы можете использовать один из методов Graphics (Paint, DrawItem и т. Д.) Или, как и в этом случае, создать новый при необходимости и сразу же утилизировать его.
В этом примере неявно заключено создание объекта Graphics в блок using.

Это простой пример, использующий ControlPaint.DrawBorder , который показывает, как нарисовать границу вокруг элемента управления ComboBox, используя объект Graphics, полученный из дескриптора элемента управления (Graphics.FromHwnd(this.Handle) ) на WM_PAINT полученном сообщении, перекрывающем WndProc элемента управления.

Пример пользовательского элемента управления предоставляет открытое свойство BorderColor, которое позволяет изменить цвет границы.

using System.ComponentModel;
using System.Drawing;
using System.Security.Permissions;
using System.Windows.Forms;

[DesignerCategory("Code")]
class ComboSimpleBorder : ComboBox
{
    private const int WM_PAINT = 0xF;
    private Color m_BorderColor = Color.Red;

    public ComboSimpleBorder() { }

    [Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
    [EditorBrowsable(EditorBrowsableState.Always), Category("Appearance")]
    [Description("Get or Set the Color of the Control's border")]
    public Color BorderColor 
    {
        get => this.m_BorderColor;
        set { this.m_BorderColor = value; this.Invalidate(); }
    }

    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
    protected override void WndProc(ref Message m) {
        base.WndProc(ref m);
        if (m.Msg == WM_PAINT) {
            using (Graphics g = Graphics.FromHwnd(this.Handle)) {
                ControlPaint.DrawBorder(g, this.ClientRectangle, this.m_BorderColor, ButtonBorderStyle.Solid);
            }
            m.Result = IntPtr.Zero;
        }
    }
}
...