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()中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM