MFC笔记——VC++深入详解(第3版)孙鑫

1、Windows下的程序都是基于消息的,窗口在创建时都会产生一个WM_CREATE消息。其他类可以响应这个消息,添加WM_CREATE消息的处理函数。

类视图——某个类处鼠标右键,属性——消息(找到WM_CREATE)。或者使用“类向导”。

2、文档/视类结构,视类窗口始终覆盖在框架类窗口之上,鼠标所有操作都只能由视类窗口捕获。如,CMainFrame中鼠标单击事件无反应,而在CDrawView中就有反应。

 3、消息映射机制

消息映射表,由头文件的DECLARE_MESSAGE_MAP()、源文件的BEGIN_MESSAGE_MAP与END_MESSAGE_MAP构建而成。BEGIN_MESSAGE_MAP与END_MESSAGE_MAP之间,有消息映射宏,一旦有消息产生,程序就调用对应的消息响应函数来处理。

 消息响应函数

 4、画线,推荐方式三

    /* 方式一:SDK
    // 首先获得窗口的设备描述表
    HDC hdc;
    hdc = ::GetDC(m_hWnd); //当前窗口的设备描述表
    //移动到线条的起点
    MoveToEx(hdc, m_ptOrigin.x, m_ptOrigin.y, NULL);
    //画线
    LineTo(hdc, point.x, point.y);
    //释放设备描述表
    ::ReleaseDC(m_hWnd, hdc);
    */

    /* 方式二:MFC的CDC类,封装了所有与绘图相关的操作
    CDC* pDC = GetDC();
    pDC->MoveTo(m_ptOrigin);
    pDC->LineTo(point);
    ReleaseDC(pDC);
    */

    方式三:MFC的CClientDC类,CDC的进一步封装,省去GetDC与ReleaseDC
    CClientDC dc(this); //客户区范围
    //CClientDC dc(GetParent()); //客户区+工具栏区
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);

    /* 方式四:MFC的CWindowDC类,也是派生自CDC,可画的范围更大
    CWindowDC dc(this); //客户区范围
    //CWindowDC dc(GetParent()); //客户区+工具栏区
    //CWindowDC dc(GetDesktopWindow()); //所有窗口
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
    */

5、画笔

    CPen pen(PS_SOLID, 1, RGB(255, 0, 0)); //PS_DASH、PS_DOT宽度≤1,虚线才有效
    CClientDC dc(this);
    CPen* pOldPen = dc.SelectObject(&pen); //选择画笔
    dc.MoveTo(m_ptOrigin);
    dc.LineTo(point);
    //推荐写上以下两行,不然可能造成GDI对象的增加,程序崩溃
    dc.SelectObject(pOldPen); //重置画笔
    pen.DeleteObject(); //释放画笔

6、画刷,一般用于填充

    CBrush brush(RGB(255, 0, 0));//创建一个红色画刷
    CClientDC dc(this);    //创建并获得设备描述表
    dc.FillRect(CRect(m_ptOrigin, point), &brush);//利用红色画刷填充鼠标拖曳过程中形成的矩形区域
    brush.DeleteObject();

画刷画矩形,dc中有默认白色画刷。但是新的会覆盖旧的。透明矩形的实现。

    /* 画矩形,dc中有默认白色画刷
    CClientDC dc(this);
    dc.Rectangle(CRect(m_ptOrigin, point)); //绘制矩形,黑边白色填充
    */

    // 透明矩形,新的不遮蔽旧的
    CClientDC dc(this);//创建并获得设备描述表
    CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//创建一个空画刷
    CBrush *pOldBrush = dc.SelectObject(pBrush);//将空画刷选入设备描述表
    dc.Rectangle(CRect(m_ptOrigin, point));//绘制一个矩形
    dc.SelectObject(pOldBrush);//恢复先前的画刷
    pBrush->DeleteObject();

说明,CClientDC操作的都是对象而不是句柄。GetStockObject()获取画刷、画笔、字体的句柄。

 

将句柄转为对象,用画刷、画笔、字体类提供的FromHandle()函数。

 7、绘制连续线条

鼠标移动消息WM_MOUSEMOVE,不断更新起始点,不断在起始点与最新点之间画非常短的线段。

void CDrawView::OnMouseMove(UINT nFlags, CPoint point)
{
    CClientDC dc(this);        
    CPen pen(PS_SOLID, 1, RGB(255, 0, 0));//创建一个红色的、宽度为1的实线画笔
    CPen *pOldPen = dc.SelectObject(&pen);//把创建的画笔选入设备描述表

    if (m_bDraw == TRUE) //鼠标按下开始,抬起结束
    {
        dc.MoveTo(m_ptOrigin);
        dc.LineTo(point);        
        m_ptOrigin = point;//修改线段的起点
    }    
    dc.SelectObject(pOldPen);//恢复设备描述表
    pen.DeleteObject();

    CView::OnMouseMove(nFlags, point);
}

 8、窗口重绘

当窗口创建时、尺寸发生变化时,都会调用OnDraw()。防止文字等内容在窗口重绘时消失,可以将代码写在OnDraw()中。

原文地址:https://www.cnblogs.com/xixixing/p/14025705.html