带滑块的趋势图(slider control in chart)

      如果没记错的话,好像是第一次在用趋势图显示数据的时候,就遇到过这个问题,当时是在一个趋势图中显示一个月中每天的数据趋势变化,结果就是根本在一张图中显示不下,X轴的文字标注都重叠到一起,当时用的是PB,里面的图形显示功能非常强大,后来好像是将文字直立显示的,避免了标注的重叠。

      最近同时好像在搞趋势图,又想起这个问题,就试着在里面加个slider实现拖动以便可以显示“被多出”的部分。老规矩,先看图。

      

      嘿嘿,其实也没用到什么,纯GDI+,用到的也不外乎就是双缓存和坐标变换。主要处理的事件就是MouseDown和MouseMove,重绘Paint。在MouseDown中变化X轴的值和Value值(这里也有变换坐标),在MouseMove中变换坐标,Paint中绘制轴、趋势图、滑块。

      下面看看完整的代码:

代码
        /// <summary>
        
/// X轴和Value值重加载
        
/// </summary>
        private void lbchart_MouseDown(object sender, MouseEventArgs e)
        {
            
//是否点中滑块
            IsClick = IsClickSlider(new Point(e.X, e.Y));
            
//左键有效
            if (e.Button == MouseButtons.Left)
            {
                
double disvalue = 0//位移
                if (curPoint.X != e.X || curPoint.Y != e.Y)
                {
                    curPoint.X 
= e.X;
                    curPoint.Y 
= e.Y;
                    Capture 
= true;
                    
//是否需要移动
                    if (IsClick)
                    {
                        IsNeedMove 
= true;
                    }
                    
//位移差
                    disvalue =curPoint.X - oldPoint.X;
                }
                
else
                {
                    IsNeedMove 
= false;
                    
//位移差
                    disvalue = dx;
                }

                
//重新复制PartValue中的值
                
//****x轴移动的位移
                int xd = (int)Math.Round(disvalue / xdvalue);
                curArrPos 
= curArrPos + xd;
                
if (curArrPos < 0)
                {
                    curArrPos 
= 0;
                }
                
if (curArrPos > 6)
                {
                    curArrPos 
= 6;
                }
                
for (int i = curArrPos; i < curArrPos + 7; i++)
                {
                    xPartValue[i 
- curArrPos] = xValue[i];
                    partValue[i 
- curArrPos] = value[i];
                }
            }
            
if (e.Button == MouseButtons.Right)
            {
                Capture 
= false;
            }
            dx 
= 0;
            
this.lbchart.Invalidate();
        }


        
/// <summary>
        
/// 鼠标移动
        
/// </summary>
        private void lbchart_MouseMove(object sender, MouseEventArgs e)
        {
            Graphics g2 
= CreateGraphics();
            
if (IsNeedMove)
            {
                dx 
= dx + (e.X - oldPoint.X);
                curPoint 
= new Point(e.X, e.Y);
            }
            
this.lbchart.Invalidate();
        }

       上面是两个主要的鼠标事件,下面看看绘制代码:

代码
       #region 重绘
       
private void lbchart_Paint(object sender, PaintEventArgs e)
       {
            
//初始化值
            g0 = e.Graphics;
            bitmap 
= new Bitmap(lbchart.Width, lbchart.Height);
            g1 
= Graphics.FromImage(bitmap);
            g1.Clear(
this.lbchart.BackColor);
            g1.SmoothingMode 
= SmoothingMode.AntiAlias;

            
#region 绘制
            
//
            DrawAxes();
            
//趋势图
            DrawChart();
            
//滑块
            DrawSlider();
            
#endregion

            
//绘制到lb上
            g0.DrawImage(bitmap, 00);

        }

        
/// <summary>
        
/// 绘制轴
        
/// </summary>
        private void DrawAxes()
        {
            Brush axesbrush 
= new SolidBrush(Color.Black);
            Font axesfont 
= new Font("宋体"15, FontStyle.Bold);
            Font valuefont 
= new Font("宋体"10, FontStyle.Regular);

            
//箭头
            AdjustableArrowCap cap = new AdjustableArrowCap(33);
            cap.WidthScale 
= 3;
            cap.BaseCap 
= LineCap.Square;
            cap.Height 
= 3;
            axesPen.CustomStartCap 
= cap;

            
//****Y轴
            g1.DrawLine(axesPen, lbPosX + 10, lbPosY + 10, lbPosX + 10, lbHeight - 30);
            g1.DrawString(
"Y", axesfont, axesbrush, lbPosX + 15, lbPosY + 10);
            
//*****Y轴差值
            ydvalue = ((lbHeight - 15- (lbPosY + 10)) / (yValue.Length + 1);
            
for (int i = 0; i < yValue.Length; i++)
            {
                
float y = (float)(lbHeight - 15 - (i + 1* ydvalue);
                g1.DrawString(yValue[i].ToString(), valuefont, axesbrush, lbPosX 
+ 12, y);
                g1.DrawLine(valuePen, lbPosX 
+ 10, y, lbPosX + 15, y);
            }

            
//****X轴
            g1.DrawLine(axesPen, lbWidth - 5, lbHeight - 30, lbPosX + 10, lbHeight - 30);
            g1.DrawString(
"X", axesfont, axesbrush, lbWidth - 15, lbHeight - 55);
            
//******X轴差值
            xdvalue = (lbWidth - 5 - (lbPosX + 10)) / (partValue.Length - 1);
            
for (int i = 0; i < xPartValue.Length; i++)
            {
                
float x = (float)(lbPosX + 10 + (i) * xdvalue);
                
if (Convert.ToDouble(xPartValue[i].ToString()) >= 10)
                {
                    g1.DrawString(xPartValue[i].ToString(), valuefont, axesbrush, x 
- 12, lbHeight - 28);
                }
                
else
                {
                    g1.DrawString(xPartValue[i].ToString(), valuefont, axesbrush, x 
- 5, lbHeight - 28);
                }
                g1.DrawLine(valuePen, x, lbHeight 
- 30, x, lbHeight - 35);
            }
        }

        
/// <summary>
        
/// 绘制趋势图
        
/// </summary>
        private void DrawChart()
        {
            
//****绘制曲线图
            double dvalue = ydvalue / 5.0;
            
for (int i = 0; i < partValue.Length - 1; i++)
            {
                
double startX = lbPosX + 10 + (i) * xdvalue;
                
double endX = startX + xdvalue;
                
double startY = Convert.ToDouble(partValue[i].ToString()) * dvalue;
                
double endY = Convert.ToDouble(partValue[i + 1].ToString()) * dvalue;
                g1.DrawEllipse(
new Pen(Color.Red), (float)(startX - 3), (float)(startY - 3), 66);
                g1.DrawLine(valuePen, (
float)endX, (float)endY, (float)startX, (float)startY);
            }
        }

        
/// <summary>
        
/// 绘制滑块
        
/// </summary>
        private void DrawSlider()
        {
            
//绘制滑块
            if (curPoint.X != 0 && curPoint.Y != 0)
            {
                oldPoint 
= curPoint;
                g1.DrawLine(sliderPen, lbPosX 
+ curPoint.X, lbPosY, lbPosX + curPoint.X, lbPosY + lbHeight);
            }
            
else
            {
                g1.DrawLine(sliderPen, lbWidth 
/ 2, lbPosY, lbWidth / 2, lbPosY + lbHeight);
            }
        }

        
#endregion
原文地址:https://www.cnblogs.com/wangyong/p/1806480.html