zoukankan      html  css  js  c++  java
  • 实例详解:MFC坐标轴实现

    需求:MFC坐标轴实现-----最好有步骤啊,刚刚才接触C++和MFC啊。MFC怎样在特定区域建立坐标轴,x轴自适应,y轴有固定范围,最好有网格。

    解决思路:VC 内存绘图,不闪屏,具体代码如下:

    // 先上传代码,在.h 文件中:

    #pragma once  
      
    #include <afxtempl.h>  
      
    #define TEXT_AREA_WIDTH     (60)            ///< 文字区宽度,单位 像素  
    #define X_AXIS_GRAD         (600)           ///< X 轴刻度值  
    #define Y_AXIS_GRAD         (50)            ///< X 轴刻度值  
      
      
    class My_Draw  : public CStatic  
    {  
        // 构造/析构 函数  
    public:  
            My_Draw();  
            virtual ~My_Draw();  
    public:  
        struct  
        {  
            unsigned char Show_Max_Grid                 :1;         // 是否显示大网格  
            unsigned char Show_Min_Grid                 :1;         // 是否显示小网格  
            unsigned char Draw_Enable                   :1;         // 放大/缩小使能位  
            unsigned char Draw_Line_Choice              :1;         // 线被选择  
            unsigned char LButton_Down_Flag             :1;         // 鼠标左键按下标志  
            unsigned char LButton_Up_Flag               :1;         // 鼠标左键弹起标志  
            unsigned char LButton_Double_Down_Flag      :1;         // 鼠标左键双击按下标志  
        }Bool_Flag;  
      
        unsigned int TextAreaWidth;  
        int xAxisGrad,yAxisGrad;  
        unsigned short xMaxGrad,xMinGrad;  
        unsigned short yMaxGrad,yMinGrad;  
      
        int Limit_Min,Limit_Max;  
      
        POINT Mouse_Current_Point;                      // 鼠标当前坐标  
        POINT Button_Down_Point;                        // 记录鼠标左键按下时的坐标  
        POINT LButton_Double_Down_Point;                // 记录鼠标左键双击按下的坐标  
        POINT Old_LButton_Double_Down_Point;  
      
        // 画笔列表  
        CPen* pBrack;       // 黑色画笔  
        CPen* pBlue;        // 蓝色画笔  
        CPen* pYellow;      // 黄色画笔  
        CPen* pGren;        // 绿色画笔  
        CPen* pPink;        // 紫色画笔  
        CPen* pRed;         // 红色画笔  
        CPen* pGray;        // 灰色画笔  
      
        CRect Draw_Size;  
        CDC memDC;  
        CBitmap memBitmap;        
        CBitmap* pOldBmp;  
      
        unsigned short SheetMaxH;  
      
        CWnd *pWnd;  
      
        void Draw();  
        void Drawing(CDC *pDC);       // 绘制图表  
        void Draw_xAxis(CDC *pDC);  
        void Draw_yAxis(CDC *pDC);  
        void Draw_Cross_Cursor(CDC *pDC);  
      
        void My_Draw::SaveBmpToFile();  
    protected:  
          
        afx_msg void OnLButtonDown(UINT nFlags, CPoint point);  
        afx_msg void OnMouseMove(UINT nFlags, CPoint point);  
        afx_msg void OnLButtonUp(UINT nFlags, CPoint point);  
        afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);  
        DECLARE_MESSAGE_MAP()  
    }; 

    // .CPP 文件中:

    #include "stdafx.h"  
    #include "Draw_Static_Text.h"  
    #include "conio.h"  
    #include "direct.h"  
      
    #ifdef _DEBUG  
    #define new DEBUG_NEW  
    #endif  
      
    // 构造函数  
    My_Draw::My_Draw()  
    {  
        Bool_Flag.Show_Max_Grid = false;  
        Bool_Flag.Show_Min_Grid = false;  
        Bool_Flag.Draw_Enable = false;  
        Bool_Flag.Draw_Line_Choice = false;  
        Bool_Flag.LButton_Down_Flag = false;  
        Bool_Flag.LButton_Up_Flag = false;  
        Bool_Flag.LButton_Double_Down_Flag = false;  
      
        TextAreaWidth = TEXT_AREA_WIDTH;  
        xAxisGrad = X_AXIS_GRAD;  
        yAxisGrad = Y_AXIS_GRAD;  
      
        pBrack = new CPen();        // 黑色画笔  
        pBlue = new CPen();         // 蓝色画笔  
        pYellow = new CPen();       // 黄色画笔  
        pGren = new CPen();         // 绿色画笔  
        pRed = new CPen();          // 红色画笔  
        pPink = new CPen();         // 紫色画笔  
        pGray = new CPen();         // 灰色画笔  
      
        pBrack->CreatePen(PS_SOLID,1,RGB(0,0,0));  
        pBlue->CreatePen(PS_SOLID,1,RGB(0,0,255));  
        pYellow->CreatePen(PS_SOLID,1,RGB(155,125,0));  
        pGren->CreatePen(PS_SOLID,1,RGB(0,255,0));  
        pRed->CreatePen(PS_SOLID,1,RGB(255,0,0));  
        pPink->CreatePen(PS_SOLID,1,RGB(255,0,255));  
        pGray->CreatePen(PS_DOT,1,RGB(145,105,105));  
      
      
    #ifdef _DEBUG  
        AllocConsole();  
        _cprintf("Debuging....
    ");  
    #endif  
    }  
      
      
    // 析构函数  
    My_Draw::~My_Draw()  
    {  
        delete pBrack;        // 黑色画笔  
        delete pBlue;         // 蓝色画笔  
        delete pYellow;       // 黄色画笔  
        delete pGren;         // 绿色画笔  
        delete pRed;          // 红色画笔  
        delete pPink;         // 紫色画笔  
        delete pGray;         // 灰色画笔  
    }  
      
    BEGIN_MESSAGE_MAP(My_Draw, CStatic)  
        ON_WM_LBUTTONDOWN()  
        ON_WM_MOUSEMOVE()  
        ON_WM_LBUTTONUP()  
        ON_WM_LBUTTONDBLCLK()  
    END_MESSAGE_MAP()  
      
      
    void My_Draw::SaveBmpToFile()       // 保存图表为 Bmp 图片  
    {  
        CFileDialog dlg(false,NULL,NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,  
            "位图文件(*.bmp)|*.bmp|",NULL);  
      
        if (dlg.DoModal()!= IDOK) return;  
        CString filename = dlg.GetFileName() + ".bmp";  
      
        // 获取绘制坐标的文本框  
        this->GetClientRect(&Draw_Size);    // 获取窗口大小  
        CDC *pDC = this->GetDC();     // 获取 dc  
        this->Invalidate();  
     this->UpdateWindow();  
      
        //内存绘图  
        memDC.CreateCompatibleDC(pDC);  
        memBitmap.CreateCompatibleBitmap(pDC,Draw_Size.right,Draw_Size.bottom);  
        pOldBmp = memDC.SelectObject(&memBitmap);  
        memDC.BitBlt(Draw_Size.left,Draw_Size.top,Draw_Size.right,Draw_Size.bottom,pDC,0,0,SRCCOPY);  
        Drawing(&memDC);       // 绘制坐标  
      
        BITMAP bmp;  
        memBitmap.GetBitmap(&bmp);                                               // 获得位图信息  
        FILE *fp;  
        fopen_s(&fp,filename, "w+b");  
        BITMAPINFOHEADER bih = {0};                                              // 位图信息头  
        bih.biBitCount = bmp.bmBitsPixel;                                        // 每个像素字节大小  
        bih.biCompression = BI_RGB;  
        bih.biHeight = bmp.bmHeight;                                             // 高度  
        bih.biPlanes = 1;  
        bih.biSize = sizeof(BITMAPINFOHEADER);  
        bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;                       // 图像数据大小  
        bih.biWidth = bmp.bmWidth;                                               // 宽度  
        BITMAPFILEHEADER bfh = {0};                                              // 位图文件头  
        bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);     // 到位图数据的偏移量  
        bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight;            // 文件总的大小  
        bfh.bfType = (WORD)0x4d42;  
        fwrite(&bfh, 1, sizeof(BITMAPFILEHEADER), fp);                           // 写入位图文件头  
        fwrite(&bih, 1, sizeof(BITMAPINFOHEADER), fp);                           // 写入位图信息头  
        byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight];                    // 申请内存保存位图数据  
        GetDIBits(memDC.m_hDC, (HBITMAP) memBitmap.m_hObject, 0, Draw_Size.Height(), p,  (LPBITMAPINFO) &bih, DIB_RGB_COLORS);                                    //获取位图数据  
        fwrite(p, 1, bmp.bmWidthBytes * bmp.bmHeight, fp);                       // 写入位图数据  
        delete [] p;  
        fclose(fp);  
      
        memDC.SelectObject(pOldBmp);  
        memDC.DeleteDC();                                                       // 释放 Dc  
        memBitmap.DeleteObject();  
    }  
      
      
    void My_Draw::Draw()  
    {  
        this->Invalidate();  
     this->UpdateWindow();  
        this->GetClientRect(&Draw_Size);    // 获取窗口大小  
        CDC *pDC = this->GetDC();     // 获取 dc  
        //内存绘图  
        memDC.CreateCompatibleDC(pDC);  
        memBitmap.CreateCompatibleBitmap(pDC,Draw_Size.right,Draw_Size.bottom);  
        pOldBmp = memDC.SelectObject(&memBitmap);  
        memDC.BitBlt(Draw_Size.left,Draw_Size.top,Draw_Size.right,Draw_Size.bottom,pDC,0,0,SRCCOPY);  
        Drawing(&memDC);       // 绘制坐标  
        pDC->BitBlt(Draw_Size.left,Draw_Size.top,Draw_Size.right,Draw_Size.bottom,&memDC,0,0,SRCCOPY);  
      
        memDC.SelectObject(pOldBmp);  
        memDC.DeleteDC();  
        memBitmap.DeleteObject();  
      
        ReleaseDC(pDC);  
    }  
      
      
    void My_Draw::Drawing(CDC *pDC)  
    {  
        pDC->SelectObject(pBrack);                         // 选择当前画笔颜色  
        pDC->Rectangle(0,0,Draw_Size.Width(),Draw_Size.Height());       // 设定绘制范围  
      
        //绘出文字  
          
     pDC->SetTextColor(RGB(0,25,255));  
     pDC->SetBkMode(TRANSPARENT);  
     pDC->TextOutA(5,180,"");  
     pDC->TextOutA(5,200,"");  
     pDC->TextOutA(5,220,"");  
     pDC->TextOutA(5,240,"");  
     pDC->TextOutA(11,260,"|");  
     pDC->TextOutA(5,280,"");  
     pDC->TextOutA(5,300,"");  
     pDC->TextOutA(3,320,"(V)");  
          
     pDC->TextOutA(Draw_Size.Width()/2-40,Draw_Size.Height()-20,"行    程--单位 (%)");  
      
        SheetMaxH = Draw_Size.Height()-TextAreaWidth;  
      
        Draw_xAxis(pDC);  
        Draw_yAxis(pDC);  
        Draw_Cross_Cursor(pDC);  
      
        ReleaseDC(pDC);  
    }  
      
      
    void My_Draw::Draw_xAxis(CDC *pDC)  
    {  
        CString StrScale;           // 转换刻度字符串存放点  
        unsigned short drawCount;   // 画王格计数  
        unsigned short temp;  
        unsigned int girdSize;  
          
        //绘制x轴坐标  
     pDC->MoveTo(TextAreaWidth,SheetMaxH);  
     pDC->LineTo(Draw_Size.Width(),SheetMaxH);  
     //绘制箭头  
     pDC->LineTo(Draw_Size.Width()-10,SheetMaxH-5);  
     pDC->MoveTo(Draw_Size.Width(),SheetMaxH);  
     pDC->LineTo(Draw_Size.Width()-10,SheetMaxH+5);  
      
        //绘制x轴刻度  
     drawCount = 0;  
     if(xAxisGrad > Draw_Size.Width())  
     {  
      xAxisGrad/=10;  
      girdSize = 10;  
     }  
     else  
      girdSize = 1;  
      
     xMaxGrad = int((Draw_Size.Width() - TextAreaWidth) / xAxisGrad);  
     for(int i=TextAreaWidth; i<=Draw_Size.Width(); i+=xMaxGrad)  
     {  
      pDC->SelectObject(pBrack);  
      pDC->MoveTo(i,SheetMaxH);  
      if(xMaxGrad<2)  
       temp = xMaxGrad*100;  
      else  
       temp = xMaxGrad*10;  
      if((i-TextAreaWidth)%temp==0)  
      {  
       pDC->LineTo(i,SheetMaxH+10);                            // 整数刻度,绘制长刻度  
      
       //输出对应的文本  
       if(drawCount < 100)  
       {  
        //pDC->SelectObject(font1);                         //选择当前字体  
        StrScale.Format(" %d", drawCount*girdSize);  
        pDC->SetTextColor(RGB(25, 155, 12));  
        pDC->TextOutA(i-10, SheetMaxH+10, StrScale);          //修正文本显示坐标  3位数内,显示方式  
      
                    if(Bool_Flag.Show_Max_Grid)  
                    {  
                        pDC->SelectObject(pGray);                       //使用虚线灰色画笔  
                        pDC->MoveTo(i,SheetMaxH);  
                        pDC->LineTo(i,20);  
                    }  
       }  
       else  
       {  
        StrScale.Format(" %d", drawCount*girdSize);  
        pDC->TextOutA(i-12, SheetMaxH+10, StrScale);          //修正文本显示坐标  4位数内,显示方式  
      
                    if(Bool_Flag.Show_Max_Grid)  
                    {  
                        pDC->SelectObject(pGray);                       //使用虚线灰色画笔  
                        pDC->MoveTo(i, SheetMaxH);  
                        pDC->LineTo(i, 20);  
                    }  
       }  
      }  
      else  
      {  
       pDC->LineTo(i,SheetMaxH+5);                             //小数刻度,绘制短刻度  
      }  
      drawCount++;  
     }  
      
        ReleaseDC(pDC);  
    }  
      
      
    void My_Draw::Draw_yAxis(CDC *pDC)  
    {  
        unsigned int drawCount;  
     CString StrScale;     //转换刻度字符串存放点  
          
        drawCount = 0;  
        //绘制y轴坐标  
     pDC->MoveTo(TextAreaWidth, SheetMaxH);  
     pDC->LineTo(TextAreaWidth, 10);  
     //绘制箭头  
     pDC->LineTo(TextAreaWidth-5, 20);  
     pDC->MoveTo(TextAreaWidth, 10);  
     pDC->LineTo(TextAreaWidth+5, 20);  
      
     yMaxGrad = int(SheetMaxH / yAxisGrad);  
     for(int i=SheetMaxH; i>=20; i-=yMaxGrad)  
     {  
            pDC->SelectObject(pBrack);  
      StrScale.Format("%d", drawCount / 10);  
      pDC->MoveTo(TextAreaWidth, i);  
      
      if(drawCount % 10==0)  
      {  
       pDC->LineTo(TextAreaWidth-10, i);                        //整数刻度,绘制长刻度  
                  
                if(Bool_Flag.Show_Max_Grid)  
                {  
                    pDC->SelectObject(pGray);                           //使用实线灰色画笔  
                    pDC->MoveTo(TextAreaWidth, i);  
                    pDC->LineTo(Draw_Size.Width()-10, i);  
                }  
      
       pDC->SetTextColor(RGB(255, 0, 0));  
       pDC->TextOutA(TextAreaWidth-25, i-6, StrScale+"V");       //输出对应的文本  
      }  
      else  
      {  
       pDC->LineTo(TextAreaWidth-5, i);                         //小数刻度,绘制短刻度  
      }  
      drawCount++;  
     }  
          
        ReleaseDC(pDC);  
    }  
      
      
    void My_Draw::Draw_Cross_Cursor(CDC *pDC)  
    {  
        int m_intVoltage;  
        int m_intAngle;  
          
        // 十字光标和显示坐标信息  
        if(Bool_Flag.LButton_Double_Down_Flag)  
        {  
            if((LButton_Double_Down_Point.x > TextAreaWidth)  
                &&(LButton_Double_Down_Point.x < Draw_Size.Width())  
                &&(LButton_Double_Down_Point.y > 20)  
                &&(LButton_Double_Down_Point.y < SheetMaxH))  
            {  
                if(Bool_Flag.Draw_Line_Choice)  
                    pDC->SelectObject(pGren);  
                else  
                    pDC->SelectObject(pRed);  
      
                pDC->MoveTo(LButton_Double_Down_Point.x, 1);  
                pDC->LineTo(LButton_Double_Down_Point.x, SheetMaxH-1);  
      
                pDC->MoveTo(TextAreaWidth+1, LButton_Double_Down_Point.y);  
                pDC->LineTo(Draw_Size.Width()-1,LButton_Double_Down_Point.y);  
      
                Old_LButton_Double_Down_Point = LButton_Double_Down_Point;  
      
                m_intVoltage = yAxisGrad;  
                m_intVoltage = (SheetMaxH - LButton_Double_Down_Point.y)/m_intVoltage;  
                m_intVoltage /= 10;  
                m_intAngle = xAxisGrad;  
                m_intAngle = (LButton_Double_Down_Point.x - TextAreaWidth)/m_intAngle;  
    #ifdef _DEBUG  
                _cprintf("Voltage = %0.2f,Angle = %0.2f
    ",xAxisGrad,m_intAngle);  
    #endif  
                UpdateData(FALSE);  
            }  
        }  
      
        if(Bool_Flag.LButton_Down_Flag)  
        {  
            pDC->SelectObject(pBrack);  
            pDC->MoveTo(Button_Down_Point);  
            pDC->LineTo(Mouse_Current_Point.x,Button_Down_Point.y);  
      
            pDC->MoveTo(Mouse_Current_Point.x,Button_Down_Point.y);  
            pDC->LineTo(Mouse_Current_Point);  
      
            pDC->MoveTo(Mouse_Current_Point);  
            pDC->LineTo(Button_Down_Point.x,Mouse_Current_Point.y);  
      
            pDC->MoveTo(Button_Down_Point.x,Mouse_Current_Point.y);  
            pDC->LineTo(Button_Down_Point);  
      
        }  
        ReleaseDC(pDC);  
    }  
      
      
    void My_Draw::OnMouseMove(UINT nFlags, CPoint point)  
    {  
        // TODO: 在此添加消息处理程序代码和/或调用默认值  
        Mouse_Current_Point = point;  
      
        if(Bool_Flag.Draw_Line_Choice)  
        {  
            Limit_Min = point.x - 5;  
            Limit_Max = point.x + 5;  
            LButton_Double_Down_Point = point;  
        }  
      
      
        if((Bool_Flag.LButton_Down_Flag)  
        ||(Bool_Flag.LButton_Up_Flag))  
            Draw();  
          
        CStatic::OnMouseMove(nFlags, point);  
    }  
      
      
    void My_Draw::OnLButtonDown(UINT nFlags, CPoint point)  
    {  
        // TODO: 在此添加消息处理程序代码和/或调用默认值  
        if((Bool_Flag.LButton_Double_Down_Flag)  
            &&(point.x >= Limit_Min)  
            &&(point.x <= Limit_Max))  
        {  
            if(Bool_Flag.Draw_Line_Choice)  
                Bool_Flag.Draw_Line_Choice = FALSE;  
            else  
                Bool_Flag.Draw_Line_Choice = TRUE;  
          
            LButton_Double_Down_Point = point;  
        }  
        else  
        {  
            if((Bool_Flag.LButton_Down_Flag == FALSE)  
                &&(Bool_Flag.Draw_Line_Choice == FALSE))  
            {  
                Bool_Flag.LButton_Down_Flag = true;  
                Button_Down_Point = point;  
            }  
        }  
        Draw();  
      
        CStatic::OnLButtonDown(nFlags, point);  
    }  
      
       
      
       
      
    void My_Draw::OnLButtonUp(UINT nFlags, CPoint point)  
    {  
        // TODO: 在此添加消息处理程序代码和/或调用默认值  
        if(Bool_Flag.LButton_Down_Flag)  
        {  
            Bool_Flag.LButton_Up_Flag = true;  
            Bool_Flag.LButton_Down_Flag = FALSE;  
            Draw();  
        }  
      
        CStatic::OnLButtonUp(nFlags, point);  
    }  
      
      
    void My_Draw::OnLButtonDblClk(UINT nFlags, CPoint point)  
    {  
        // TODO: 在此添加消息处理程序代码和/或调用默认值  
      
        LButton_Double_Down_Point = point;  
      
        Limit_Min = LButton_Double_Down_Point.x - 5;  
        Limit_Max = LButton_Double_Down_Point.x + 5;  
      
        Bool_Flag.LButton_Double_Down_Flag = TRUE;  
        Draw();  
      
        CStatic::OnLButtonDblClk(nFlags, point);  
    }  

    程序运行效果图

    现在说明一下

    1.  新建一个 MFC 应用程序

    2. 选择“基于对话框”

    3. 添加一个 “Picture 控件”

    4. 为控件添加一个变量 my_Graw

    5. 将源文件包含进来,并在 My_ClassDlg.h 中包含 #include "My Draw.h"

    6. 在 My_ClassDlg.h 头文件中将刚才声明的 Picture  控件变量 CStatic my_Graw ; 改成  My_Draw my_Graw;

    7. 在 My_ClassDlg.cpp 文件 void CMy_ClassDlg::OnPaint() 尾部添加 my_Graw.Draw();

    8. 编译运行

    读者可根据自己的需要在响应的地方改下就好了。
    示例下载 http://download.csdn.net/detail/longzhishen/7227255

  • 相关阅读:
    Bootstrap 网页1
    Bootstrap 网页实例
    Bootstrap 警告框
    Bootstrap 表格
    Bootstrap 小功能
    【BZOJ1706】[usaco2007 Nov]relays 奶牛接力跑 矩阵乘法
    【BZOJ3669】[Noi2014]魔法森林 LCT
    【BZOJ2049,2631,3282,1180】LCT模板四连A
    【BZOJ4071】[Apio2015]巴邻旁之桥 Treap
    【BZOJ1009】[HNOI2008]GT考试 next数组+矩阵乘法
  • 原文地址:https://www.cnblogs.com/rainbow70626/p/8969748.html
Copyright © 2011-2022 走看看