需求: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. 安装mysql出现no compatible servers were found

    一.问题描述 今天在安装数据库的过程中,遇到错误提示: No compatible servers were found,You'll need to cancel this wizard and i ...

  2. mysql常用语句练习-基于ecshop2.7.3数据库(1)

    SELECT * FROM ecs_goods WHERE goods_id = 1;SELECT goods_id, goods_name FROM ecs_goods WHERE goods_id ...

  3. HDU2819(KB10-E 二分图最大匹配)

    Swap Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  4. 编写hadoop程序,并打包jar到hadoop集群运行

    windows环境下编写hadoop程序 新建:File->new->Project->Maven->next GroupId 和ArtifactId 随便写(还是建议规范点) ...

  5. Apache 、SUN、ORACLE

    Apache: 全称:Apache Software Foundation 解释:apache 软件基金会.是专门为支持开源软件项目而办的一个非盈利性组织.在它所支持的Apache项目与子项目中,所发 ...

  6. BZOJ5289: [Hnoi2018]排列

    传送门 第一步转化,令 \(q[p[i]]=i\),那么题目变成: 有一些 \(q[a[i]]<q[i]\) 的限制,\(q\) 必须为排列,求 \(max(\sum_{i=1}^{n}w[i] ...

  7. js将对象数组按照自定义规则排序

    javascript对一个对象数组进行自定义规则排序,对象中有两个字段. 按照对象中一个字段a的值从小到大规则排序, 效果如下: 排序前: [0]:a=9,b=3 [1]:a=33,b=7 [2]:a ...

  8. soapUI 再谈SoapUI接口测试--文件组织与接口“布局”管理

    再谈SoapUI接口测试--文件组织与接口“布局”管理 by:授客 QQ:1033553122 SoapUI-Pro-x64-5.1.2_576025(含破解文件),软件下载地址: http://pa ...

  9. MySQL主从复制——主库已有数据的解决方案

    在上篇文章中我们介绍了基于Docker的Mysql主从搭建,一主多从的搭建过程就是重复了一主一从的从库配置过程,需要注意的是,要保证主从库my.cnf中server-id的唯一性.搭建完成后,可以在主 ...

  10. 韩顺平php从入门到精通

    37 整型细节说明 $a; echo $a; var_dump($a) //NULL 一个数总是要占用内存空间(字节),在php中一个整数一般占用四个字节(与平台相关),一个字节占用8bit php的 ...