标签:poi his creates new command unless 计算 客户 when
上一节中鸡啄米讲了CDC类及其屏幕绘图函数,本节的主要内容是GDI对象之画笔CPen。
GDI对象
在MFC中,CGdiObject类是GDI对象的基类,通过查阅MSDN我们可以看到,CGdiObject类有六个直接的派生类,GDI对象主要也是这六个,分别是:CBitmap、CBrush、CFont、CPalette、CPen和CRgn。
在这六个GDI对象中,最常用的莫过于画笔和画刷了,即CPen类和CBrush类。本文就主要讲解画笔的使用。
画笔的应用实例
鸡啄米在这里直接通过一个波形图的实例,来详细讲解画笔的使用方法。
首先介绍此实例要实现的功能:在对话框上有一个Picture控件,将此控件的背景填充为黑色;启动一个定时器,每次定时器到时,所有波形数据都前移一个单位,并获取一个80以内的随机数作为波形的最后一个数据,然后以绿色画笔在绘图控件上绘制波形。这样就实现了波形的绘制及动态变化。
下面是具体实施步骤:
1、创建一个基于对话框的MFC工程,名字设为“Example50”。
2、在自动生成的对话框模板IDD_EXAMPLE50_DIALOG中,删除“TODO: Place dialog controls here.”静态文本框,添加一个Picture控件,ID设为IDC_WAVE_DRAW。
3、为Picture控件IDC_WAVE_DRAW添加CStatic变量,名称设为m_picDraw。
4、在文件Example50Dlg.h文件中CExample50Dlg类声明的上面添加宏定义:
C++代码
- #define POINT_COUNT 100
此符号常量的意义是波形的点数,这里用define将其定义为符号常量是为了方便以后可能的修改,假如我们以后想将点数改为200,则只改此宏定义就可以了:#define POINT_COUNT 200,而如果没有使用符号常量,在程序中直接使用了100,那么就需要将所有使用100的位置找出来,并替换为200,这样不仅麻烦也很容易出错,所以最好是将其定义为符号常量。
5、在CExample50Dlg.h文件中为CExample50Dlg类添加成员数组:
C++代码
- int m_nzValues[POINT_COUNT];
此数组用于存放波形数据。
6、在CExample50Dlg类的构造函数中为数组m_nzValues的元素赋初值:
C++代码
- CExample50Dlg::CExample50Dlg(CWnd* pParent
- : CDialogEx(CExample50Dlg::IDD, pParent)
- {
- m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
-
-
- memset(m_nzValues, 0, sizeof(int) * POINT_COUNT);
- }
7、在CExample50Dlg对话框的初始化成员函数CExample50Dlg::OnInitDialog()中,构造随机数生成器,并启动定时器。CExample50Dlg::OnInitDialog()修改如下:
C++代码
- BOOL CExample50Dlg::OnInitDialog()
- {
- CDialogEx::OnInitDialog();
-
-
-
-
- ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
- ASSERT(IDM_ABOUTBOX < 0xF000);
-
- CMenu* pSysMenu = GetSystemMenu(FALSE);
- if (pSysMenu != NULL)
- {
- BOOL bNameValid;
- CString strAboutMenu;
- bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
- ASSERT(bNameValid);
- if (!strAboutMenu.IsEmpty())
- {
- pSysMenu->AppendMenu(MF_SEPARATOR);
- pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
- }
- }
-
-
-
- SetIcon(m_hIcon, TRUE);
- SetIcon(m_hIcon, FALSE);
-
-
-
-
- srand((unsigned)time(NULL));
-
-
- SetTimer(1, 200, NULL);
-
- return TRUE;
- }
8、为CExample50Dlg类添加波形绘制的成员函数CExample50Dlg::DrawWave(CDC *pDC, CRect &rectPicture),参数分别为设备上下文指针和绘图的矩形区域。
C++代码
- void CExample50Dlg::DrawWave(CDC *pDC, CRect &rectPicture)
- {
- float fDeltaX;
- float fDeltaY;
- int nX;
- int nY;
- CPen newPen;
- CPen *pOldPen;
- CBrush newBrush;
- CBrush *pOldBrush;
-
-
- fDeltaX = (float)rectPicture.Width() / (POINT_COUNT - 1);
- fDeltaY = (float)rectPicture.Height() / 80;
-
-
- newBrush.CreateSolidBrush(RGB(0,0,0));
-
- pOldBrush = pDC->SelectObject(&newBrush);
-
- pDC->Rectangle(rectPicture);
-
- pDC->SelectObject(pOldBrush);
-
- newBrush.DeleteObject();
-
-
- newPen.CreatePen(PS_SOLID, 1, RGB(0,255,0));
-
- pOldPen = pDC->SelectObject(&newPen);
-
-
- pDC->MoveTo(rectPicture.left, rectPicture.bottom);
-
- for (int i=0; i<POINT_COUNT; i++)
- {
- nX = rectPicture.left + (int)(i * fDeltaX);
- nY = rectPicture.bottom - (int)(m_nzValues[i] * fDeltaY);
- pDC->LineTo(nX, nY);
- }
-
-
- pDC->SelectObject(pOldPen);
-
- newPen.DeleteObject();
- }
9、有了定时器和绘图成员函数,我们就可以在WM_TIMER消息的响应函数中添加对波形数据的定时处理和对波形的定时绘制了。定时器及WM_TIMER消息处理函数的添加方法如果忘记了,可以再到VS2010/MFC编程入门之四十四(MFC常用类:定时器Timer)温习下。
WM_TIMER消息的处理函数修改如下:
C++代码
- void CExample50Dlg::OnTimer(UINT_PTR nIDEvent)
- {
-
- CRect rectPicture;
-
-
- for (int i=0; i<POINT_COUNT-1; i++)
- {
- m_nzValues[i] = m_nzValues[i+1];
- }
-
- m_nzValues[POINT_COUNT-1] = rand() % 80;
-
-
-
- m_picDraw.GetClientRect(&rectPicture);
-
-
- DrawWave(m_picDraw.GetDC(), rectPicture);
-
- CDialogEx::OnTimer(nIDEvent);
- }
10、在对话框销毁时,定时器应关闭。所以为CExample50Dlg类添加WM_DESTROY消息的处理函数,并修改如下:
C++代码
- void CExample50Dlg::OnDestroy()
- {
- CDialogEx::OnDestroy();
-
-
-
-
- KillTimer(1);
- }
11、一切准备就绪,编译运行。最终的效果如下图:
关于画笔,鸡啄米就讲到这里了,下一节将为大家简单讲讲画刷的使用。谢谢大家的关注!
原文地址:http://www.jizhuomi.com/software/246.html
(转载)VS2010/MFC编程入门之五十(图形图像:GDI对象之画笔CPen)
标签:poi his creates new command unless 计算 客户 when
原文地址:http://www.cnblogs.com/wodehao0808/p/6758693.html