自定义组合框控件边框在鼠标悬停进出时闪烁



我正在开发一个自定义组合框控件,该控件派生自标准组合框,它将看起来是平面的,无边框的。

http://www.codeproject.com/Articles/6971/Making-Standard-ComboBox-appear-flat

根据各种来源,我将不得不覆盖windows过程来做到这一点,所以这里是我的WndProc覆盖,我已经阻止了几个消息到达控件:

protected override void WndProc(ref Message m)
{
    IntPtr hDC = IntPtr.Zero;
    Graphics gdc = null;
    switch (m.Msg)
    {
        // Block these messages
        case WM_CHANGEUISTATE:
        case WM_MOUSEACTIVATE:
        case WM_MOUSEFIRST:
        case WM_MOUSELAST:
        case WM_MOUSEHOVER:
        case WM_MOUSELEAVE:
            m.Result = (IntPtr)1;
            break;
        // Here we paint the border when non-client paint is received
        case WM_NC_PAINT:
            hDC = GetWindowDC(this.Handle);
            gdc = Graphics.FromHdc(hDC);
            SendMessage(this.Handle, WM_ERASEBKGND, hDC, 0);
            SendPrintClientMsg();   // Send to draw client area
            PaintFlatControlBorder(this, gdc);
            m.Result = (IntPtr) 1;  // Indicate message has been processed          
            ReleaseDC(m.HWnd, hDC);
            gdc.Dispose();
            break;
        case WM_PAINT:
            base.WndProc(ref m);
            // Flatten the border area again
            hDC = GetWindowDC(this.Handle);
            gdc = Graphics.FromHdc(hDC);
            Pen p = new Pen((this.Enabled? BackColor:SystemColors.Control), 2);
            gdc.DrawRectangle(p, new Rectangle(2, 2, this.Width-3, this.Height-3));
            PaintFlatDropDown(this, gdc);
            PaintFlatControlBorder(this, gdc);
            ReleaseDC(m.HWnd, hDC);
            gdc.Dispose();
            break;
            default:
                base.WndProc(ref m);
                break;
    }
}
这是我的构造函数:
public FlatComboBox() : base()
{
    this.FlatStyle = FlatStyle.Flat;
    this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true);
}

我必须阻止哪些其他windproc消息,或者有其他方法可以解决这个问题?

这里是所有windowproc消息的一个很好的参考:

https://www.autoitscript.com/autoit3/docs/appendix/WinMsgCodes.htm

我正在使用。net v4.5.

我之前用一个组合框做过这个,给它一个可自定义的平面外观,我展示了完整的代码,这样更容易理解它是如何工作的,但是它使用一个自定义的下拉菜单和菜单项来完成外观。

using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Custom.Controls
{
    public class CustomComboBox : UserControl
    {
        private const int DEFAULT_WIDTH = 121;
        private const int DEFAULT_HEIGHT = 20;
        private CustomContextMenuStrip _popupControl;
        private CustomToolStripMenuItem _selectedItem;
        private bool _bDroppedDown;
        private Color _borderColour;
        private Color _dropDownButtonColour;
        private Color _droppedDownArrowColour;
        private Color _closedArrowColour;
        private Color _dropDownBackColour;
        private Color _dropDownForeColour;
        private Color _dropDownBorderColour;
        public Color BorderColour
        {
            get
            {
                return _borderColour;
            }
            set
            {
                _borderColour = value;
                this.Invalidate();
            }
        }
        public Color ClosedArrowColour
        {
            get
            {
                return _closedArrowColour;
            }
            set
            {
                _closedArrowColour = value;
                this.Invalidate();
            }
        }
        public Color DroppedDownArrowColour
        {
            get
            {
                return _droppedDownArrowColour;
            }
            set
            {
                _droppedDownArrowColour = value;
                this.Invalidate();
            }
        }
        public Color DropDownButtonColour
        {
            get
            {
                return _dropDownButtonColour;
            }
            set
            {
                _dropDownButtonColour = value;
                this.Invalidate();
            }
        }
        public Color DropDownBorderColour
        {
            get
            {
                return _dropDownBorderColour;
            }
            set
            {
                _dropDownBorderColour = value;
                _popupControl.BorderColour = value;
                this.Invalidate();
            }
        }
        public Color DropDownBackColour
        {
            get
            {
                return _dropDownBackColour;
            }
            set
            {
                _dropDownBackColour = value;
                _popupControl.BackColor = value;
                this.Invalidate();
            }
        }
        public Color DropDownForeColour
        {
            get
            {
                return _dropDownForeColour;
            }
            set
            {
                _dropDownForeColour = value;
                _popupControl.ForeColor = value;
                this.Invalidate();
            }
        }
        public bool DropShadowEnabled
        {
            get
            {
                return _popupControl.DropShadowEnabled;
            }
            set
            {
                _popupControl.DropShadowEnabled = value;
                this.Invalidate();
            }
        }
        public bool DroppedDown
        {
            get
            {
                return _bDroppedDown;
            }
            set
            {
                _bDroppedDown = value;
                if (value)
                {
                    _popupControl.Show(this, new Point(0, this.Height), ToolStripDropDownDirection.BelowRight);
                }
                else
                {
                    _popupControl.Hide();
                }
                this.Invalidate();
            }
        }
        public ToolStripItemCollection Items
        {
            get
            {
                return _popupControl.Items;
            }
        }
        public CustomToolStripMenuItem SelectedItem
        {
            get
            {
                return _selectedItem;
            }
        }
        public CustomComboBox()
        {
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.UserMouse, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SuspendLayout();
            this.ResumeLayout(false);
            _popupControl = new CustomContextMenuStrip();
            _popupControl.BackColor = this.BackColor;
            _popupControl.Closed += new ToolStripDropDownClosedEventHandler(PopupControl_Closed);
            _popupControl.ItemClicked += new ToolStripItemClickedEventHandler(PopupControl_ItemClicked);
            this.Width = DEFAULT_WIDTH;
            this.Height = DEFAULT_HEIGHT;
            _selectedItem = null;
            _bDroppedDown = false;
            this.BackColor = SystemColors.Control;
            this.ForeColor = SystemColors.ControlText;
            _borderColour = SystemColors.ActiveBorder;
            _dropDownButtonColour = SystemColors.ButtonFace;
            _droppedDownArrowColour = SystemColors.ControlLight;
            _closedArrowColour = SystemColors.ControlDark;
            //Set these via the properties so they take effect on _popupControl
            this.DropDownBackColour = SystemColors.Control;
            this.DropDownForeColour = SystemColors.ControlText;
            this.DropDownBorderColour = SystemColors.ActiveBorder;
        }
        protected override void OnFontChanged(EventArgs e)
        {
            _popupControl.Font = this.Font;
            base.OnFontChanged(e);
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            this.Invalidate();
            this.DroppedDown = !this.DroppedDown;
            base.OnMouseDown(e);
        }
        protected override void OnMouseWheel(MouseEventArgs e)
        {
            int nIndex = this.Items.IndexOf(_selectedItem);
            if (e.Delta < 0)
            {
                if (nIndex < (this.Items.Count - 1))
                {
                    _selectedItem = (CustomToolStripMenuItem)this.Items[nIndex + 1];
                    OnSelectedItemChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
            else if (e.Delta > 0)
            {
                if (nIndex > 0)
                {
                    _selectedItem = (CustomToolStripMenuItem)this.Items[nIndex - 1];
                    OnSelectedItemChanged(EventArgs.Empty);
                    this.Invalidate();
                }
            }
            base.OnMouseWheel(e);
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            Rectangle boundingRect = new Rectangle(0, 0, this.Width, this.Height);
            using (SolidBrush brush = new SolidBrush(this.BackColor))
            {
                e.Graphics.FillRectangle(brush, boundingRect);
            }
            ControlPaint.DrawBorder(e.Graphics, boundingRect, _borderColour, ButtonBorderStyle.Solid);
            //Draw the dropdown button background
            int nButtonWidth = SystemInformation.VerticalScrollBarWidth + SystemInformation.VerticalFocusThickness;
            Rectangle dropDownButtonRect = new Rectangle(this.Width - nButtonWidth, 0, nButtonWidth, this.Height);
            using (SolidBrush brush = new SolidBrush(_dropDownButtonColour))
            {
                e.Graphics.FillRectangle(brush, dropDownButtonRect);
            }
            //Draw the dropdown button arrow
            using (GraphicsPath path = new GraphicsPath())
            {
                Point pTopLeft = new Point()
                {
                    X = (int)Math.Round((float)dropDownButtonRect.X + ((float)dropDownButtonRect.Width * 0.30f)),
                    Y = (int)Math.Round((float)dropDownButtonRect.Y + ((float)dropDownButtonRect.Height * 0.35f))
                };
                Point pTopRight = new Point()
                {
                    X = (int)Math.Round((float)dropDownButtonRect.X + ((float)dropDownButtonRect.Width * 0.70f)),
                    Y = (int)Math.Round((float)dropDownButtonRect.Y + ((float)dropDownButtonRect.Height * 0.35f))
                };
                Point pBottom = new Point()
                {
                    X = (int)Math.Round((float)dropDownButtonRect.X + ((float)dropDownButtonRect.Width * 0.5f)),
                    Y = (int)Math.Round((float)dropDownButtonRect.Y + ((float)dropDownButtonRect.Height * 0.65f))
                };
                path.AddLine(pTopLeft, pTopRight);
                path.AddLine(pTopRight, pBottom);
                SmoothingMode previousSmoothingMode = e.Graphics.SmoothingMode;
                e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
                {
                    using (SolidBrush brush = new SolidBrush(_bDroppedDown ? _droppedDownArrowColour : _closedArrowColour))
                    {
                        e.Graphics.FillPath(brush, path);
                    }
                }
                e.Graphics.SmoothingMode = previousSmoothingMode;
            }
            if (_selectedItem != null)
            {
                using (SolidBrush brush = new SolidBrush(this.ForeColor))
                {
                    SizeF stringSize = e.Graphics.MeasureString(_selectedItem.Text, this.Font);
                    e.Graphics.DrawString(_selectedItem.Text, this.Font, brush, new Point(0, (this.Height / 2) - ((int)stringSize.Height / 2)));
                }
            }
        }
        protected override void OnSizeChanged(EventArgs e)
        {
            if (_popupControl != null)
            {
                _popupControl.MaximumItemSize = new Size(this.Width - 1, _popupControl.MaximumItemSize.Height);
                _popupControl.Width = this.Width;
            }
            base.OnSizeChanged(e);
        }
        private void OnSelectedItemChanged(EventArgs e)
        {
            if (SelectedItemChanged != null)
            {
                SelectedItemChanged(this, e);
            }
        }
        public void SelectFirstItem()
        {
            if (this.Items != null && this.Items.Count > 0)
            {
                _selectedItem = (CustomToolStripMenuItem)this.Items[0];
                OnSelectedItemChanged(EventArgs.Empty);
            }
        }
        public event EventHandler SelectedItemChanged;
        private void PopupControl_Closed(object sender, ToolStripDropDownClosedEventArgs e)
        {
            this.DroppedDown = false;
            this.Invalidate(true);
        }
        private void PopupControl_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            _selectedItem = (CustomToolStripMenuItem)e.ClickedItem;
            OnSelectedItemChanged(EventArgs.Empty);
        }
    }
}

最新更新