带有移动百分比标签的TrackBar

时间:2017-06-22 22:14:15

标签: c# winforms custom-controls trackbar

我使用来自herehere

的答案拼凑了一个自定义TrackBar,其百分比代表当前的Slider位置

我的自定义控件如下:

using System;
using System.Drawing;
using System.Windows.Forms;
using System.ComponentModel;
using System.Runtime.InteropServices;

namespace CustomControls
{
    public partial class TrackBarPercent : TrackBar
    {
        /// <summary>
        /// Initializes a new instance of <see cref="TrackBarPercent"/>.
        /// </summary>
        public TrackBarPercent() : base()
        {
            InitializeComponent();
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
        }

        private Font _percentFont = SystemFonts.DefaultFont;
        private Color _percentColor = Color.Black;
        private SolidBrush _drawBrush = new SolidBrush(Color.Black);

        /// <summary>
        /// Gets or sets the font of the percent text.
        /// </summary>
        [Description("Gets or sets the font of the percent text.")]
        [Browsable(true)]
        public Font PercentFont
        {
            get { return _percentFont; }
            set { _percentFont = value; }
        }

        /// <summary>
        /// Gets or sets the color of the percent text.
        /// </summary>
        [Description("Gets or sets the color of the percent text.")]
        [Browsable(true)]
        public Color PercentColor
        {
            get { return _percentColor; }
            set { _percentColor = value; _drawBrush = new SolidBrush(_percentColor); }
        }

        private Rectangle Slider
        {
            get
            {
                try
                {
                    RECT rc = new RECT();
                    SendMessageRect(this.Handle, TBM_GETTHUMBRECT, IntPtr.Zero, ref rc);
                    return new Rectangle(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top);
                }
                catch
                {
                    return new Rectangle();
                }
            }
        }

        private const int TBM_GETTHUMBRECT = 0x400 + 25;
        private struct RECT { public int left, top, right, bottom; }
        [DllImport("user32.dll", EntryPoint = "SendMessageW")]
        private static extern IntPtr SendMessageRect(IntPtr hWnd, int msg, IntPtr wp, ref RECT lp);

        private int lastValue = 0;
        protected override void WndProc(ref Message m)
        {
            try
            {
                base.WndProc(ref m);

                if (m.Msg == 0x0F)
                {
                    if (this.Value != lastValue)
                    {
                        lastValue = this.Value;
                        this.Invalidate();
                    }

                    using (Graphics graphics = Graphics.FromHwnd(Handle))
                    {
                        DrawPercentText(graphics);
                    }
                }
            }
            catch { }
        }

        private void DrawPercentText(Graphics g)
        {
            try
            {
                Point pctTxtPoint;

                if (this.Orientation == System.Windows.Forms.Orientation.Horizontal)
                {
                    pctTxtPoint = new Point((Slider.Left + Slider.Right) / 2, Slider.Bottom);
                }
                else
                {
                    pctTxtPoint = new Point(Slider.Right + 5, Slider.Top - 2);
                }

                double percent = (double)this.Value * 100.0 / (double)this.Maximum;
                string pctStr = string.Format("{0:0.##}%", percent);

                g.DrawString(pctStr, _percentFont, _drawBrush, pctTxtPoint);
            }
            catch { }
        }

        [DllImport("user32.dll")]
        public extern static int SendMessage(IntPtr hWnd, uint msg, int wParam, int lParam);

        private static int MakeParam(int loWord, int hiWord)
        {
            return (hiWord << 16) | (loWord & 0xffff);
        }

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            SendMessage(this.Handle, 0x0128, MakeParam(1, 0x1), 0);
        }
    }
}

这在大多数情况下都有效,但每次将鼠标悬停在滑块上时文本都会重新绘制,导致文本看起来很粗体。当另一个控件获得焦点时,此效果消失。另外,我得到了我不理解的控件抛出的定期异常。

我会跟踪为此控件设置的最后一个值,以便在值已更改时使视图无效。我需要这个来阻止控件在前一个文本上绘制百分比文本。我不认为这种做法非常优雅,但我不确定如何做得更好。

如何修复此代码,以便文本不会变为&#34;粗体&#34;并修复我得到的例外情况?

0 个答案:

没有答案