需求: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 :; // 是否显示大网格
unsigned char Show_Min_Grid :; // 是否显示小网格
unsigned char Draw_Enable :; // 放大/缩小使能位
unsigned char Draw_Line_Choice :; // 线被选择
unsigned char LButton_Down_Flag :; // 鼠标左键按下标志
unsigned char LButton_Up_Flag :; // 鼠标左键弹起标志
unsigned char LButton_Double_Down_Flag :; // 鼠标左键双击按下标志
}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,,RGB(,,));
pBlue->CreatePen(PS_SOLID,,RGB(,,));
pYellow->CreatePen(PS_SOLID,,RGB(,,));
pGren->CreatePen(PS_SOLID,,RGB(,,));
pRed->CreatePen(PS_SOLID,,RGB(,,));
pPink->CreatePen(PS_SOLID,,RGB(,,));
pGray->CreatePen(PS_DOT,,RGB(,,)); #ifdef _DEBUG
AllocConsole();
_cprintf("Debuging....\r\n");
#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,,,SRCCOPY);
Drawing(&memDC); // 绘制坐标 BITMAP bmp;
memBitmap.GetBitmap(&bmp); // 获得位图信息
FILE *fp;
fopen_s(&fp,filename, "w+b");
BITMAPINFOHEADER bih = {}; // 位图信息头
bih.biBitCount = bmp.bmBitsPixel; // 每个像素字节大小
bih.biCompression = BI_RGB;
bih.biHeight = bmp.bmHeight; // 高度
bih.biPlanes = ;
bih.biSize = sizeof(BITMAPINFOHEADER);
bih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight; // 图像数据大小
bih.biWidth = bmp.bmWidth; // 宽度
BITMAPFILEHEADER bfh = {}; // 位图文件头
bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // 到位图数据的偏移量
bfh.bfSize = bfh.bfOffBits + bmp.bmWidthBytes * bmp.bmHeight; // 文件总的大小
bfh.bfType = (WORD)0x4d42;
fwrite(&bfh, , sizeof(BITMAPFILEHEADER), fp); // 写入位图文件头
fwrite(&bih, , sizeof(BITMAPINFOHEADER), fp); // 写入位图信息头
byte * p = new byte[bmp.bmWidthBytes * bmp.bmHeight]; // 申请内存保存位图数据
GetDIBits(memDC.m_hDC, (HBITMAP) memBitmap.m_hObject, , Draw_Size.Height(), p, (LPBITMAPINFO) &bih, DIB_RGB_COLORS); //获取位图数据
fwrite(p, , 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,,,SRCCOPY);
Drawing(&memDC); // 绘制坐标
pDC->BitBlt(Draw_Size.left,Draw_Size.top,Draw_Size.right,Draw_Size.bottom,&memDC,,,SRCCOPY); memDC.SelectObject(pOldBmp);
memDC.DeleteDC();
memBitmap.DeleteObject(); ReleaseDC(pDC);
} void My_Draw::Drawing(CDC *pDC)
{
pDC->SelectObject(pBrack); // 选择当前画笔颜色
pDC->Rectangle(,,Draw_Size.Width(),Draw_Size.Height()); // 设定绘制范围 //绘出文字 pDC->SetTextColor(RGB(,,));
pDC->SetBkMode(TRANSPARENT);
pDC->TextOutA(,,"输");
pDC->TextOutA(,,"出");
pDC->TextOutA(,,"电");
pDC->TextOutA(,,"压");
pDC->TextOutA(,,"|");
pDC->TextOutA(,,"单");
pDC->TextOutA(,,"位");
pDC->TextOutA(,,"(V)"); pDC->TextOutA(Draw_Size.Width()/-,Draw_Size.Height()-,"行 程--单位 (%)"); 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()-,SheetMaxH-);
pDC->MoveTo(Draw_Size.Width(),SheetMaxH);
pDC->LineTo(Draw_Size.Width()-,SheetMaxH+); //绘制x轴刻度
drawCount = ;
if(xAxisGrad > Draw_Size.Width())
{
xAxisGrad/=;
girdSize = ;
}
else
girdSize = ; 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<)
temp = xMaxGrad*;
else
temp = xMaxGrad*;
if((i-TextAreaWidth)%temp==)
{
pDC->LineTo(i,SheetMaxH+); // 整数刻度,绘制长刻度 //输出对应的文本
if(drawCount < )
{
//pDC->SelectObject(font1); //选择当前字体
StrScale.Format(" %d", drawCount*girdSize);
pDC->SetTextColor(RGB(, , ));
pDC->TextOutA(i-, SheetMaxH+, StrScale); //修正文本显示坐标 3位数内,显示方式 if(Bool_Flag.Show_Max_Grid)
{
pDC->SelectObject(pGray); //使用虚线灰色画笔
pDC->MoveTo(i,SheetMaxH);
pDC->LineTo(i,);
}
}
else
{
StrScale.Format(" %d", drawCount*girdSize);
pDC->TextOutA(i-, SheetMaxH+, StrScale); //修正文本显示坐标 4位数内,显示方式 if(Bool_Flag.Show_Max_Grid)
{
pDC->SelectObject(pGray); //使用虚线灰色画笔
pDC->MoveTo(i, SheetMaxH);
pDC->LineTo(i, );
}
}
}
else
{
pDC->LineTo(i,SheetMaxH+); //小数刻度,绘制短刻度
}
drawCount++;
} ReleaseDC(pDC);
} void My_Draw::Draw_yAxis(CDC *pDC)
{
unsigned int drawCount;
CString StrScale; //转换刻度字符串存放点 drawCount = ;
//绘制y轴坐标
pDC->MoveTo(TextAreaWidth, SheetMaxH);
pDC->LineTo(TextAreaWidth, );
//绘制箭头
pDC->LineTo(TextAreaWidth-, );
pDC->MoveTo(TextAreaWidth, );
pDC->LineTo(TextAreaWidth+, ); yMaxGrad = int(SheetMaxH / yAxisGrad);
for(int i=SheetMaxH; i>=; i-=yMaxGrad)
{
pDC->SelectObject(pBrack);
StrScale.Format("%d", drawCount / );
pDC->MoveTo(TextAreaWidth, i); if(drawCount % ==)
{
pDC->LineTo(TextAreaWidth-, i); //整数刻度,绘制长刻度 if(Bool_Flag.Show_Max_Grid)
{
pDC->SelectObject(pGray); //使用实线灰色画笔
pDC->MoveTo(TextAreaWidth, i);
pDC->LineTo(Draw_Size.Width()-, i);
} pDC->SetTextColor(RGB(, , ));
pDC->TextOutA(TextAreaWidth-, i-, StrScale+"V"); //输出对应的文本
}
else
{
pDC->LineTo(TextAreaWidth-, 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 > )
&&(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, );
pDC->LineTo(LButton_Double_Down_Point.x, SheetMaxH-); pDC->MoveTo(TextAreaWidth+, LButton_Double_Down_Point.y);
pDC->LineTo(Draw_Size.Width()-,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 /= ;
m_intAngle = xAxisGrad;
m_intAngle = (LButton_Double_Down_Point.x - TextAreaWidth)/m_intAngle;
#ifdef _DEBUG
_cprintf("Voltage = %0.2f,Angle = %0.2f\r\n",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 - ;
Limit_Max = point.x + ;
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 - ;
Limit_Max = LButton_Double_Down_Point.x + ; 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

实例详解:MFC坐标轴实现的更多相关文章

  1. linux基础-磁盘阵列(RAID)实例详解

    磁盘阵列(RAID)实例详解 raid技术分类 软raid技术 硬raid技术 Raid和lvm的区别 为什么选择用raid RAID详解 RAID-0 RAID-1 RAID-5 Raid-10 R ...

  2. Cocos2d-x 3.X手游开发实例详解

    Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...

  3. JavaScript学习笔记-实例详解-类(二)

    实例详解-类(二)   //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...

  4. JavaScript学习笔记-实例详解-类(一)

    实例详解-类(一): //每个javascript函数(除了bind())都自动拥有一个prototype对象// 在未添加属性或重写prototype对象之前,它只包含唯一一个不可枚举属性const ...

  5. Entity Framework实例详解

    Entity Framework Code First的默认行为是使用一系列约定将POCO类映射到表.然而,有时候,不能也不想遵循这些约定,那就需要重写它们.重写默认约定有两种方式:Data Anno ...

  6. 免费的HTML5连载来了《HTML5网页开发实例详解》连载(二)

    最近新浪.百度.腾讯.京东.大众点评.淘宝等流行的网站都加大了招聘HTML5的力度,HTML5开发人员成了抢手货,本次连载的是由大众点评前端工程师和一淘网前端工程师基情奉献的<HTML5网页开发 ...

  7. Linux下rz命令使用的实例详解

    Linux中rz命令和sz命令都可用于文件传输,而rz命令主要用于文件的上传,下面将通过几个实例来给大家详细介绍下Linux下rz命令的用法,一起来学习下吧. rz命令可以批量上传文件,当然也可上传单 ...

  8. 实例详解 DB2 排序监控和调优

    实例详解 DB2 排序监控和调优http://automationqa.com/forum.php?mod=viewthread&tid=2882&fromuid=2

  9. 转:【工欲善其事必先利其器】—Entity Framework实例详解

    开始本篇文章之前,先说一下Entity Framework 6 Alpha1在NuGet中已可用,原文链接http://blogs.msdn.com/b/adonet/archive/2012/10/ ...

  10. Linux计划任务Crontab实例详解教程

    说明:Crontab是Linux系统中在固定时间执行某一个程序的工具,类似于Windows系统中的任务计划程序 下面通过详细实例来说明在Linux系统中如何使用Crontab 操作系统:CentOS ...

随机推荐

  1. while和if的区别

    while用于循环语句,而if用于判断和分支语句.由于你并没有指明是什么程序,只能泛泛而谈了.if 语句中,常用格式为:if(判断条件){执行语句}上面的结构,只是进行一次判断.if与else结合,就 ...

  2. 2.Observer Pattern(观察者模式)

    Observer Pattern(观察者模式)定义: 在对象之间定义一对多的依赖,这样一来,当一个对象改变状态,依赖它的对象都会收到通知,并自动更新. 干说定义肯定没有举例理解的透彻.想到Observ ...

  3. js-ES6学习笔记-Iterator

    1.遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员). 2.Iterator ...

  4. CentOS7安装maven3.6.1

    1.下载maven的tar.gz安装包 2.移到centos7中并解压 tar -xzvf maven.tar.gz 3.开始配置maven环境变量,通过命令 vim /etc/profile 4.配 ...

  5. (二)收集的MongoDB命令集合

    一:针对整个数据库的 1."show dbs" 命令可以显示所有数据的列表. 2. "db" 命令可以显示当前数据库对象或集合. 3."use&quo ...

  6. 【代码笔记】iOS-自定义alertView

    一,效果图. 二,代码. ViewController.h #import <UIKit/UIKit.h> @interface ViewController : UIViewContro ...

  7. ActiveReports 报表控件V12新特性 -- 新增JSON和CSV导出

    ActiveReports是一款专注于 .NET 平台的报表控件,全面满足 HTML5 / WinForms / ASP.NET / ASP.NET MVC / WPF 等平台下报表设计和开发工作需求 ...

  8. sql语句查找某一列的值得最大值。

    记录一下:sql语句查找某一列的值得最大值. 1.例如我要查找 表A中a列的最大值: 查找语句可以这么写: "select Max(a) a from A" 2.查找表A中a列中包 ...

  9. Expo大作战(二十)--expo中的Release channels(不重要*)

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  10. 从零自学Java-4.使用字符串来交流

    1.使用字符串来存储文本: 2.在程序中显示字符串: 3.在字符串中包含特殊的字符: 4.拼接字符串: 5.在字符串中包含变量: 6.比较字符串: 7.判断字符串的长度: 程序Credits:显示一部 ...