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