【MFC笔记】GDI对象之画笔CPen画波形图

【MFC笔记】GDI对象之画笔CPen画波形图

1、创建一个基于对话框的MFC工程。

2、添加一个Picture控件,ID设为IDC_WAVE_DRAW。 

3、为Picture控件添加CStatic变量,名称设为m_picDraw。

4、在文件XXXXDlg.h文件中添加宏定义:#define POINT_COUNT 100 

此符号常量的意义是一个界面显示波形的点数,这里用define将其定义为符号常量是为了方便以后可能的修改。

5、在XXXXDlg.h文件中为XXXXDlg类添加成员数组。int   m_nzValues[POINT_COUNT];用于存储数据

【MFC笔记】GDI对象之画笔CPen画波形图

6、在XXXXDlg类的构造函数中为数组m_nzValues的元素赋初值。

【MFC笔记】GDI对象之画笔CPen画波形图

void *memset(   void *dest,   int c,   size_t count );

将dest所指向的某一块内存中的每个字节的内容全部设置为c指定的ASCII值,存储的长度为count

7、在XXXXDlg对话框的初始化成员函数XXXXDlg::OnInitDialog()中,构造随机数生成器,并启动定时器。XXXXDlg::OnInitDialog()添加如下:

srand((unsigned)time(NULL));   //以时间为种子来构造随机数生成器   

SetTimer(1, 200, NULL);   //启动定时器,ID为1,定时时间为200ms   

/*void srand(   unsigned int seed );//产生伪随机数time(NULL)获取系统时间,单位为秒*/

8、为XXXXDlg类添加波形绘制的成员函数XXXXDlg::DrawWave(CDC *pDC, CRect &rectPicture),参数分别为设备上下文指针和绘图的矩形区域。

【MFC笔记】GDI对象之画笔CPen画波形图

void XXXXDlg::DrawWave(CDC *pDC, CRect &rectPicture)
{
    float fDeltaX;     // x轴相邻两个绘图点的坐标距离   
    float fDeltaY;     // y轴每个逻辑单位对应的坐标值   
    int nX;      // 在连线时用于存储绘图点的横坐标   
    int nY;      // 在连线时用于存储绘图点的纵坐标   
    CPen newPen;       // 用于创建新画笔   
    CPen *pOldPen;     // 用于存放旧画笔   
    CBrush newBrush;   // 用于创建新画刷   
    CBrush *pOldBrush; // 用于存放旧画刷   

    // 计算fDeltaX和fDeltaY   
    fDeltaX = (float)rectPicture.Width() / (POINT_COUNT - 1);
    fDeltaY = (float)rectPicture.Height() / 80;

    newBrush.CreateSolidBrush(RGB(0, 0, 0)); // 创建黑色新画刷
    pOldBrush = pDC->SelectObject(&newBrush);// 选择新画刷,并将旧画刷的指针保存到pOldBrush   
    pDC->Rectangle(rectPicture);    // 以黑色画刷为绘图控件填充黑色,形成黑色背景   
    pDC->SelectObject(pOldBrush);    // 恢复旧画刷
    newBrush.DeleteObject();    // 删除新画刷

  
    newPen.CreatePen(PS_SOLID, 1, RGB(0, 255, 0));    // 创建实心画笔,粗度为1,颜色为绿色
    pOldPen = pDC->SelectObject(&newPen);    // 选择新画笔,并将旧画笔的指针保存到pOldPen

    pDC->MoveTo(rectPicture.left, rectPicture.bottom);    // 将当前点移动到绘图控件窗口的左下角,以此为波形的起始点   
    for (int i = 0; i < POINT_COUNT; i++)    // 计算m_nzValues数组中每个点对应的坐标位置,并依次连接,最终形成曲线   
    {
        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消息的响应函数中添加对波形数据的定时处理和对波形的定时绘制。

void CMFCApplication6Dlg::OnTimer(UINT_PTR nIDEvent)
{
       CRect rectPicture;

    // 将数组中的所有元素前移一个单位,第一个元素丢弃   
    for (int i = 0; i < POINT_COUNT - 1; i++)
    {        m_nzValues[i] = m_nzValues[i + 1];    }
    // 为最后一个元素赋一个80以内的随机数值(整型)   
    m_nzValues[POINT_COUNT - 1] = rand() % 80;

    // 获取绘图控件的客户区坐标   
    // (客户区坐标以窗口的左上角为原点,这区别于以屏幕左上角为原点的屏幕坐标)   
    m_picDraw.GetClientRect(&rectPicture);

    // 绘制波形图   
    DrawWave(m_picDraw.GetDC(), rectPicture);

    CDialogEx::OnTimer(nIDEvent);
}

10、按下取消键,销毁定时器。