WinForm Custom(二) 滑塊控制項

来源:https://www.cnblogs.com/zhuanghamiao/archive/2022/06/13/winform-custom-slider.html
-Advertisement-
Play Games

public class ZhmSlider : Control { private Rectangle foreRect; private Rectangle backRect; private Rectangle setRect; private Color backgroundColor = ...


public class ZhmSlider : Control
    {
        private Rectangle foreRect;
        private Rectangle backRect;
        private Rectangle setRect;

        private Color backgroundColor = Color.White;
        private Color foregroundColor = Color.Gray;
        private Color setRectColor = Color.Black;//滑塊顏色
        private Color fontColor = Color.Black;
        private Color borderColor = Color.Black;

        private int maximum = 100; //進度條最大值
        private int minimum = 0;  //進度條最小值
        private double _value = 0;//進度條當前值

        private bool showPercent; //當前進度百分比
        private float fontSize = 9;// 
        private FontFamily _fontFamily = new FontFamily("Segoe UI");

        private Point originPoint;
        private Point originsetRectPoint;
        private bool setRectDown = false;

        public ZhmSlider()
        {
            // 避免重繪時視窗閃爍
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true);

            this.MouseDown += ZhmSlider_MouseDown;
            this.MouseMove += ZhmSlider_MouseMove;
            this.MouseUp += ZhmSlider_MouseUp;
        }

        private void ZhmSlider_MouseUp(object sender, MouseEventArgs e)
        {
            setRectDown = false;
        }

        private void ZhmSlider_MouseMove(object sender, MouseEventArgs e)
        {
            if (setRectDown)
            {
                int dd = e.Location.X - originPoint.X;

                double percent = (double)(originsetRectPoint.X + dd - this.backRect.X) / (this.backRect.Width - this.backRect.Height);
                if (percent < 0)
                {
                    this.Value = minimum;
                    this.foreRect.Width = 0;
                    this.setRect.X = backRect.X;
                }
                else if (percent > 1)
                {
                    this.Value = maximum;
                    this.foreRect.Width = this.backRect.Width;
                    this.setRect.X = backRect.X + backRect.Width - backRect.Height;
                }
                else
                {
                    this.Value = percent * maximum;
                    this.foreRect.Width = (int)(percent * this.backRect.Width);
                    this.setRect.X = originsetRectPoint.X + dd;
                }
                Invalidate();
            }
        }

        private void ZhmSlider_MouseDown(object sender, MouseEventArgs e)
        {
            if (setRect.Contains(e.Location))
            {
                this.originPoint = e.Location;
                originsetRectPoint = this.setRect.Location;
                this.setRectDown = true;
            }
        }

        [Category("擴展屬性"), Browsable(true)]
        public bool ShowPercentTag
        {
            get { return showPercent; }
            set
            {
                showPercent = value;
                Invalidate();
            }
        }
        [Category("擴展屬性"),  Browsable(true)]
        public int Maximum
        {
            get { return maximum; }
            set
            {
                maximum = value;
                Invalidate();
            }
        }
        [Category("擴展屬性"),  Browsable(true)]
        public int Minimum
        {
            get { return minimum; }
            set
            {
                minimum = value;
                Invalidate();
            }
        }

        [Category("擴展屬性"), Browsable(true)]
        public float FontSize
        {
            get { return fontSize; }
            set
            {
                this.fontSize = value;
                Invalidate();
            }
        }
        [Category("擴展屬性"), Browsable(true)]
        public FontFamily FontFamily
        {
            get { return _fontFamily; }
            set
            {
                this._fontFamily = value;
                Invalidate();
            }
        }

        [Category("擴展屬性"), Browsable(true)]
        public Color BackgroundColor
        {
            get { return backgroundColor; }
            set
            {
                this.backgroundColor = value;
                Invalidate();
            }
        }
        [Category("擴展屬性"), Browsable(true)]
        public Color ForegroundColor
        {
            get { return foregroundColor; }
            set
            {
                this.foregroundColor = value;
                Invalidate();
            }
        }
        [Category("擴展屬性"), Browsable(true)]
        public Color SetRectColor
        {
            get { return setRectColor; }
            set
            {
                this.setRectColor = value;
                Invalidate();
            }
        }
        [Category("擴展屬性"), Browsable(true)]
        public Color FontColor
        {
            get { return fontColor; }
            set
            {
                this.fontColor = value;
                Invalidate();
            }
        }

        [Category("擴展屬性"), Browsable(true)]
        public Color BorderColor
        {
            get { return borderColor; }
            set
            {
                this.borderColor = value;
                Invalidate();
            }
        }


        //確定控制項的位置。 我們根據寬度和高度屬性確定矩形的位置。 因為Control類也有這兩個屬性,所以我們在前面添加new來覆蓋原來的屬性 
        [Category("擴展屬性"), Browsable(true)]
        public new int Width
        {
            get { return base.Width; }
            set
            {
                base.Width = value;
                foreRect.X = backRect.X = base.Width / 20;
                backRect.Width = base.Width * 9 / 10;
                foreRect.Width = (int)(_value / maximum * backRect.Width);
                setRect.X = (int)(_value / maximum * (backRect.Width - backRect.Height) + foreRect.X);

                Invalidate();
            }
        }
        [Category("擴展屬性"), Browsable(true)]
        public new int Height
        {
            get { return base.Height; }
            set
            {
                base.Height = value;
                foreRect.Height = backRect.Height = setRect.Height = setRect.Width = base.Height / 3;
                foreRect.Y = backRect.Y = setRect.Y = base.Height / 3;
                Invalidate();
            }
        }

        //值發生變化的屬性。 當向事件添加外部響應函數時,事件將生效,否則OnValueChanged方法的值為空 
        protected EventHandler OnValueChanged;
        public event EventHandler ValueChanged
        {
            add
            {
                if (OnValueChanged != null)
                    foreach (Delegate d in OnValueChanged.GetInvocationList())
                        if (object.ReferenceEquals(d, value)) return;
                OnValueChanged = (EventHandler)Delegate.Combine(OnValueChanged, value);
            }
            remove
            {
                OnValueChanged = (EventHandler)Delegate.Remove(OnValueChanged, value);
            }
        }

        //定義value的值。 當Value值發生變化時,重置矩形的進度,控制塊的位置,並重新繪製控制項(如果在value屬性中修改進度條的值,請使用_value變數,在其他地方,請使Value屬性 )
        [Category("擴展屬性"), Browsable(true)]
        public double Value
        {
            get { return _value; }
            set
            {
                if (_value < Minimum)
                    throw new ArgumentException("Less than minimum");
                if (_value > Maximum)
                    throw new ArgumentException("Exceeds the maximum");

                _value = value;
                foreRect.Width = (int)(_value / maximum * backRect.Width);
                setRect.X = (int)(_value / maximum * (backRect.Width - backRect.Height) + backRect.X);

                if ((_value - maximum) > 0)
                {
                    foreRect.Width = backRect.Width;
                    setRect.X = backRect.Width - backRect.Height + backRect.X;
                }

                if (OnValueChanged != null)
                    OnValueChanged(this, EventArgs.Empty);

                Invalidate();
            }
        }
        //繪製控制項,重載OnPaint方法來繪製控制項 
        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);

            DrawRect(pe.Graphics);
            DrawText(pe.Graphics);
        }

        //滑塊區域
        private void DrawRect(Graphics e)
        {
            Pen pen = new Pen(this.foregroundColor);

            e.FillRectangle(new SolidBrush(this.backgroundColor), backRect);
            e.DrawRectangle(new Pen(this.borderColor), backRect);

            e.FillRectangle(new SolidBrush(this.foregroundColor), foreRect);
            e.DrawRectangle(new Pen(this.borderColor), foreRect);

            e.FillRectangle(new SolidBrush(this.setRectColor), setRect);
            e.DrawRectangle(new Pen(this.borderColor), setRect);
        }

         // 繪製文本
        private void DrawText(Graphics e)
        {
            Point point = new Point();
            point.X = this.backRect.X + this.backRect.Width * 3 / 7;
            point.Y = this.backRect.Y + this.backRect.Height / 3;

            SolidBrush brush = new SolidBrush(fontColor);
            Font font = new Font(_fontFamily, this.fontSize);
            string percent = ((int)this._value).ToString() + "%";

            //設置文本居中
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            e.DrawString(percent, font, brush, backRect, format);
        }

        //在設計期間更改控制項的大小時調用OnResize方法。 當您拖動邊緣上的箭頭來更改控制項的大小時,當需要對控制項進行相應更改時,可以重寫此方法。如果沒有重新載入,則只有在修改完成後才會更新控制項。
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            this.Width = Width;
            this.Height = Height;
            Invalidate();
        }
    }

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 周末到了,不想給大家太多的壓力,今天就給大家分享一個比較簡單的彈球小游戲吧。這無聊的周末又有事可以做了,nice… 先看一下我們的最終效果圖 我們分9步來講解如何寫這個小游戲 1.創建游戲的主界面 我們用Python的內置模塊Tkinter來完成了,它是Python的標準GUI工具包,可以非常 ...
  • 前面我們剖析了Redisson的源碼,主要分析了Redisson實現Redis分散式鎖的15問,理清了Redisson是如何實現的分散式鎖和一些其它的特性。這篇文章就來接著剖析Zookeeper分散式鎖的實現框架Curator的源碼,看看Curator是如何實現Zookeeper分散式鎖的,以及它提 ...
  • 認識JavaWeb,衛星定位:zhanjiquan666,衛星定位:zhanjiquan666 ...
  • 一、說明 Fate 是一個工業級聯邦學習框架,所謂聯邦學習指的就是可以聯合多方的數據,共同構建一個模型; 與傳統數據使用方式相比,它不需要聚合各方數據搭建 數據倉庫,聯邦學習在聯合計算建模的過程中,多方機構之間的數據是不會進行共用的,實現數據的 可用不可見;本文主要分享隱私計算平臺 Fate 的相關 ...
  • 文章首發在公眾號(龍台的技術筆記),之後同步到個人網站:xiaomage.info Hippo-4J 距離上一個版本 1.2.1 已經過去一個月的時間。在此期間,由 8 位貢獻者 提交了 170+ commits,正式發佈 1.3.0 版本。 註:這是一個 相容歷史版本 的重大升級。 Github: ...
  • Blazor WebAssembly是什麼 首先來說說WebAssembly是什麼,WebAssembly是一個可以使C#,Java,Golang等靜態強類型編程語言,運行在瀏覽器中的標準,瀏覽器廠商基於此標準實現執行引擎。 在實現了WebAssembly標準引擎之後,瀏覽器中可以執行由其他語言編譯 ...
  • Openxml的顏色變化屬性 目前Openxml存在顏色變化屬性如下: 參數 說明 Hue 色調(色相) HueModulate 色調調製,百分比 HueOffset 色調偏移量,角度值 Saturation 飽和度 SaturationModulation 飽和度調製,百分比 Saturation ...
  • 在基於SqlSugar的開發框架的服務層中處理文件上傳的時候,我們一般有兩種處理方式,一種是常規的把文件存儲在本地文件系統中,一種是通過FTP方式存儲到指定的FTP伺服器上。這種處理應該由程式進行配置,決定使用那種方式,那麼這裡面我們為了彈性化處理, 在文件上傳模塊中採用選項模式【Options】處... ...
一周排行
    -Advertisement-
    Play Games
  • 前言 在我們開發過程中基本上不可或缺的用到一些敏感機密數據,比如SQL伺服器的連接串或者是OAuth2的Secret等,這些敏感數據在代碼中是不太安全的,我們不應該在源代碼中存儲密碼和其他的敏感數據,一種推薦的方式是通過Asp.Net Core的機密管理器。 機密管理器 在 ASP.NET Core ...
  • 新改進提供的Taurus Rpc 功能,可以簡化微服務間的調用,同時可以不用再手動輸出模塊名稱,或調用路徑,包括負載均衡,這一切,由框架實現並提供了。新的Taurus Rpc 功能,將使得服務間的調用,更加輕鬆、簡約、高效。 ...
  • 順序棧的介面程式 目錄順序棧的介面程式頭文件創建順序棧入棧出棧利用棧將10進位轉16進位數驗證 頭文件 #include <stdio.h> #include <stdbool.h> #include <stdlib.h> 創建順序棧 // 指的是順序棧中的元素的數據類型,用戶可以根據需要進行修改 ...
  • 前言 整理這個官方翻譯的系列,原因是網上大部分的 tomcat 版本比較舊,此版本為 v11 最新的版本。 開源項目 從零手寫實現 tomcat minicat 別稱【嗅虎】心有猛虎,輕嗅薔薇。 系列文章 web server apache tomcat11-01-官方文檔入門介紹 web serv ...
  • C總結與剖析:關鍵字篇 -- <<C語言深度解剖>> 目錄C總結與剖析:關鍵字篇 -- <<C語言深度解剖>>程式的本質:二進位文件變數1.變數:記憶體上的某個位置開闢的空間2.變數的初始化3.為什麼要有變數4.局部變數與全局變數5.變數的大小由類型決定6.任何一個變數,記憶體賦值都是從低地址開始往高地 ...
  • 如果讓你來做一個有狀態流式應用的故障恢復,你會如何來做呢? 單機和多機會遇到什麼不同的問題? Flink Checkpoint 是做什麼用的?原理是什麼? ...
  • C++ 多級繼承 多級繼承是一種面向對象編程(OOP)特性,允許一個類從多個基類繼承屬性和方法。它使代碼更易於組織和維護,並促進代碼重用。 多級繼承的語法 在 C++ 中,使用 : 符號來指定繼承關係。多級繼承的語法如下: class DerivedClass : public BaseClass1 ...
  • 前言 什麼是SpringCloud? Spring Cloud 是一系列框架的有序集合,它利用 Spring Boot 的開發便利性簡化了分散式系統的開發,比如服務註冊、服務發現、網關、路由、鏈路追蹤等。Spring Cloud 並不是重覆造輪子,而是將市面上開發得比較好的模塊集成進去,進行封裝,從 ...
  • class_template 類模板和函數模板的定義和使用類似,我們已經進行了介紹。有時,有兩個或多個類,其功能是相同的,僅僅是數據類型不同。類模板用於實現類所需數據的類型參數化 template<class NameType, class AgeType> class Person { publi ...
  • 目錄system v IPC簡介共用記憶體需要用到的函數介面shmget函數--獲取對象IDshmat函數--獲得映射空間shmctl函數--釋放資源共用記憶體實現思路註意 system v IPC簡介 消息隊列、共用記憶體和信號量統稱為system v IPC(進程間通信機制),V是羅馬數字5,是UNI ...