三. 简单绘图--Windows编程课程学习笔记

原文地址: https://blog.csdn.net/ling_xiao007/article/details/51720890

3.1 MFC消息映射机制

首先新建一个单文档类型的MFC APPWizard(exe)工程,取名MyMFCApp。试完成左键消息的捕捉。在

3.1.1 ClassWizard(类向导)

项目->类向导。


1.png

有命令、消息、虚函数、成员变量、方法五个选项卡,此外,还可以添加类。

3.1.2 消息映射机制

用ClassWizard添加一个LButtonDown的响应函数,在源文件会增加以下代码。

1) 消息响应函数原型

在MyMFCAppView.h中

// 生成的消息映射函数
protected:
    DECLARE_MESSAGE_MAP()
public:
    afx_msg voidOnLButtonDown(UINT nFlags, CPoint point);

2) ON_WM_LBUTTONDOWN消息映射宏

在MyMFCAppView.cpp中

BEGIN_MESSAGE_MAP(CMyMFCAppView, CView)
    // 标准打印命令
    ON_COMMAND(ID_FILE_PRINT,&CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
    ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

在BEGAIN_MESSAGE_MAP到END_MESSAGE_MAP()两个宏之间定义了CMyMFCApp类的消息映射表。作用是把WM_LBUTTONDOWN与OnLButtonDown关联。

3) 消息响应函数的定义

void CMyMFCAppView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    MessageBox("Left button down!");
    CView::OnLButtonDown(nFlags, point);
}

在windows应用程序中,消息被放到消息队列,应用程序GetMessage取消息,DispatchMessage交给操作系统,后者调用应用程序的窗口过程函数,WndProc进行处理。该函数用switch-case进行判别并分类处理。

而MFC程序中,只要定义了与消息有关的三处信息,就可以实现消息的响应。

当收到一个消息,消息的第一个参数指明了与哪个窗口句柄相关,通过对照表,可以找到与之相关的C++对象指针。把这个指针传递给应用程序框架类的基类,后者调用一个名为WindowProc的函数。该函数在WinCore.cpp中。该函数是一个虚函数。调用了OnWndMsg函数。

LRESULTCWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    //OnWndMsg does most of the work, except for DefWindowProc call
    LRESULT lResult = 0;
    if (!OnWndMsg(message, wParam, lParam, &lResult))
        lResult = DefWindowProc(message, wParam,lParam);
    return lResult;
}

OnWndMsg函数的处理过程:(1)首先判断消息是否有消息响应函数。判断方法是在相应窗口类中查找所需的消息响应函数。因为传递给WindowProc函数的事窗口子类指针,所以,OnWndMsg函数回到相应的子类头文件中查找,看看DECLARE_MESSAGE_MAP()宏上是否有消息响应函数的声明;再到子类源文件看看是否有相应的消息映射宏;(2)有消息响应函数则响应,没有则交给基类处理。

3.2 绘制线条

在CMyMFCAppView类添加一个类型为CPoint的m_ptOrigin私有成员。

在CMyMFCAppView.cpp初始化为0。

 m_ptOrigin = 0;

在OnLButtonDown函数中保存鼠标按下点的信息。

m_ptOrigin = point;

WM_LBUTTONUP消息添加响应函数。

(1)利用Platform SKD函数

HDChdc;
hdc = ::GetDC(m_hWnd);
::MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y, NULL);
::LineTo(hdc, point.x, point.y);
::ReleaseDC(m_hWnd, hdc);

(2)利用MFC CDC类

CDC*pDC = GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);

(3)利用CClientDC类

CClientDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);

(4)利用CWindowDC类

CWindowDC dc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);

(5)在桌面窗口划线

CWindowDCdc(GetDesktopWindow());
ClientToScreen(&m_ptOrigin);
dc.MoveTo(m_ptOrigin);
ClientToScreen(&point);
dc.LineTo(point);

因为客户区与桌面坐标转换问题的存在,需调用ClientToScreen函数。

(6)绘彩色线条

CPenpen(PS_SOLID, 5, RGB(255, 0, 0));
CClientDC dc(this);
CPen*pOldPen = dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen);

当构造一个GDI对象后,该对象并不会立即生效,必须通过SelectObject函数选入设备描述表,它才会在以后的绘制操作中生效。在完成绘图操作之后,都要利用SelectObject把先前的GDI对象选入设备描述表,以便使其恢复到先前的状态。

3.3使用画刷画图

(1)绘制矩形填充块

    CBrush brush(RGB(255, 0, 0));
    CClientDC dc(this);
    dc.FillRect(CRect(m_ptOrigin,point), &brush);

(2)绘制位图填充块

    CBitmap bmp;
    bmp.LoadBitmap(IDB_BITMAP1);
    CBrush brush(&bmp);
    CClientDC dc(this);
    dc.FillRect(CRect(m_ptOrigin,point), &brush);

(3)透明画刷

    CPen pen(PS_SOLID, 5, RGB(255, 0, 0));
    CClientDC dc(this);
    //CBrush*pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
    //CBrush*pOldBrush = (CBrush*)dc.SelectObject(pBrush);
    CBrush* pOldBrush =(CBrush*)dc.SelectStockObject(HOLLOW_BRUSH);
    CPen* pOldPen = dc.SelectObject(&pen);
    dc.Rectangle(CRect(m_ptOrigin, point));
    dc.SelectObject(pOldPen);

3.4 连续线条等

(1)连续线条

添加WM_MOUSEMOVE响应函数到View类中。补充函数。

    CClientDC dc(this);
    if (nFlags == MK_LBUTTON)
    {
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(point);
        m_ptOrigin = point;
    }

也可以添加私有成员BOOL m_bDraw到View类,View构造时赋值为FALSE,WM_LBUTTONDOWN为TRUE,

    CClientDC dc(this);
    if (m_bDraw == TRUE)
    {
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(point);
        m_bDraw = FALSE;
        m_ptOrigin = point;
    }

(2)扇形效果线条
添加私有成员CPoint m_btEnd到View类,OnLButtonDown赋值point。

    if (nFlags == MK_LBUTTON)
    {
        dc.MoveTo(m_ptOrigin);
        /* 3.4.1 连续线条
        //dc.LineTo(point);
        //m_ptOrigin = point;
        */
 
        // 3.4.2扇形
        dc.LineTo(m_ptEnd);
        m_ptEnd = point;
       
    }

(3)橡皮筋技术

      //通过取反异或的模式擦除旧线条
        dc.SetROP2(R2_NOTXORPEN);
        dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd);
        //绘制新线条
        m_ptEnd = point;
        dc.MoveTo(m_ptOrigin);dc.LineTo(m_ptEnd);

你可能感兴趣的:(三. 简单绘图--Windows编程课程学习笔记)