WinForm使用原生gdi+绘制自定义曲线图、折线图

折线图我们可以用chart控件,但是有时候需要一些自定义元素,比如曲线图放大、曲线图缩小、曲线图拖放等,因此自定义更加灵活

但是自定义有自己的缺点,就是功能有限。

1.原理

winform的自定义控件,在onpaint事件里,通过Graphics对象,将x轴、y轴,曲线绘制出来。

为了每次能够拖拽放大缩小,在每次拖放过程中,加入计算,即计算范围和刻度线位置。

2.计算

比如x的范围是  222到999,为了使轴线的刻度为整数,我们将范围扩大到200到1000。为了取得正确的范围,我们需要进行以下计算。

  • 当222的时候,对222取对数,log10(222)=2.34。
  • 2.34取整数部分2,再用10求指数,得10^2=100。
  • 2.34取小于它的最大整数,Math.Floor(2.34)=2。
  • 2乘以100=200。

同理999也一样,只不过Math.Floor改成Math.Ceiling,取大于它的最小整数

代码片段如下

  /// <summary>
        /// 获取比value大的或者小的整数值
        /// </summary>
        /// <param name="value">要处理的值</param>
        /// <param name="isBiggerThanValue">是否比value大</param>
        /// <returns></returns>
        private decimal GetProperValue(decimal value, bool isBiggerThanValue)
        {
            var positive = value > 0 ? 1 : -1;
            //负值转换为正,正值为本身
            value = value * positive;

            var temp = value;
            int tenPowPart = 0;
            if (temp > 1)
            {
                while (temp >= 10)
                {
                    tenPowPart++;
                    temp = value * (decimal)Math.Pow(0.1, tenPowPart);
                }

                if (isBiggerThanValue)
                {
                    temp = positive == 1 ? Math.Ceiling(temp) : Math.Floor(temp);
                }
                else
                {
                    temp = positive == 1 ? Math.Floor(temp) : Math.Ceiling(temp);
                }

                var proper = positive * temp * (decimal)Math.Pow(10, tenPowPart);

                return proper;
            }
            else
            {
                while (temp < 1m && temp > 0)
                {
                    tenPowPart++;
                    temp = value * (decimal)Math.Pow(10, tenPowPart);

                }

                if (isBiggerThanValue)
                {
                    temp = positive == 1 ? Math.Ceiling(temp) : Math.Floor(temp);
                }
                else
                {
                    temp = positive == 1 ? Math.Floor(temp) : Math.Ceiling(temp);
                }
                var proper = positive * temp * (decimal)Math.Pow(0.1, tenPowPart);
                return proper;
            }
        }

 

其他计算类似

3.效果图源码

 

 

 

源码:

https://files.cnblogs.com/files/lizhijian/20201127Winform%E7%BB%98%E5%88%B6%E6%9B%B2%E7%BA%BF%E5%9B%BE.zip

修改版:

https://files.cnblogs.com/files/congqiandehoulai/20201127Winform%E7%BB%98%E5%88%B6%E6%9B%B2%E7%BA%BF%E5%9B%BE.rar

 

posted @ 2020-11-27 14:24  灰主流  阅读(1513)  评论(0编辑  收藏  举报