1. 在單文檔中,MFC視類窗口是覆蓋在框架窗口上的。
此時如果編寫針對MainFrame的mouseClick事件,將不會有反應,框架窗口不能感應到鼠標消息.
2. MFC的消息映射機制
(1)在每個能接收和處理消息的類中,定義一個消息和消息函數對照表,即消息映射表.
(2)在消息映射表中,消息與對應的消息處理函數指針成對出現.某個類能處理的所有消息及其對應的消息處理函數的
地址都列在這個類所對應的靜態表中.當有消息需要處理時,程序只要搜索該消息靜態表,查看錶中是否含有該消息,
就可知道該類能否處理此消息.如果能處理該消息,則同樣依照靜態表很容易找到並調用對應的消息處理函數.
(3)MFC消息映射機制是針對能接受消息和處理消息的類來定義對應的消息映射表,而不是由父類來定義所有消息對應
的虛函數,由子類來覆蓋其函數實現,因爲這樣做會使程序揹着一個很大的虛擬函數表的包袱運行,對內存是一種浪費.
MFC工程中一個消息映射在三處添加代碼:
(1) CDrawView.h
//{{AFX_MSG(CDrawView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
兩個AFX_MSG註釋宏(因爲加了註釋符)之間,afx_msg是限定符(也是宏),表明函數是一個消息響應函數的聲明,如果是用戶自定義的消息函數響應聲明則在註釋宏下, DECLARE_MESSAGE_MAP之上加寫代碼
(2) CDrawView.cpp
BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之間,定義了CDrawView類的消息映射表,其中ON_WM_LBUTTONDOWN映射宏就是將鼠標左鍵按下消息(WM_LBUTTONDOWN)與一個消息響應函數(OnLButtonDown)關聯.
BEGIN_MESSAGE_MAP(CDrawView, CView)
//{{AFX_MSG_MAP(CDrawView)
ON_WM_LBUTTONDOWN()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()
如果添加自定義的消息映射,使用ON_MESSAGE(用戶定義消息,消息響應函數名)無”;”結尾
(3) CDrawView.cpp函數實現
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TOD Add your message handler code here and/or call default
m_ptOrigin=m_ptOld=point;
m_bDraw=TRUE;
CView::OnLButtonDown(nFlags, point);
}
3. 以下繪圖程序,參考代碼的註釋可解決部分繪圖問題
void CLesson3View::OnLButtonUp(UINT nFlags, CPoint point)
{
//調用SDK函數獲取設備上下文句柄
HDC hdc;
hdc = ::GetDC(m_hWnd);//這個m_hWnd是CWnd類中的保護成員, 保存窗口句柄,而CLesson3View類是從CWnd類繼承來的
MoveToEx(hdc, m_ptnOrigin.x, m_ptnOrigin.y, NULL);
LineTo(hdc, point.x, point.y);
::ReleaseDC(m_hWnd, hdc); // 在使用完設備上下文句柄後一定注意釋放*/
/*使用CDC(MFC)關於作圖對HDC一個封裝*/
// CDC *pDc;
// pDc = GetDC();
// pDc->MoveTo(m_ptnOrigin);
// pDc->LineTo(point);
// ReleaseDC(pDc);
/*使用客戶區繪圖類,這個是比較常用的*/
//CClientDC dc(this);//CClientDC的構造函數,使用當前窗口句柄值做爲參數
//CClientDC dc(GetParent());//得到關於父類窗口一個設備上下文
// dc.MoveTo(m_ptnOrigin);
// dc.LineTo(point);
// CClientDC類在構造時調用GetDC,然後在釋放時又調用ReleaseDC所以不用手動釋放
//利用MFC的CWindowDC繪圖
//好處是可以訪問整個窗口區域,包括框架窗口客戶區和非客戶區,桌面等,
// CWindowDC dc(this);
// CWindowDC dc(GetParent());
// dc.MoveTo(m_ptnOrigin);
// dc.LineTo(point);
// CWindowDC dc(GetDesktopWindow());//這個可以畫到桌面上其它地方
// dc.MoveTo(m_ptnOrigin);
// dc.LineTo(point);
//以上所畫的線條顏色都是黑色的,因爲在設備描述表中使用默認的畫筆(黑色),
//要改變線條顏色則需要自己生成一個新的畫筆對象,
//將它選到設備描述表中,再畫就使用新畫筆來繪圖
// CPen m_pen(PS_DASH, 2, RGB(255, 0, 0));//生成新的畫筆
// CClientDC dc(this);
// CPen *pOldPen = dc.SelectObject(&m_pen);//選擇進設備描述表中
// dc.MoveTo(m_ptnOrigin);
// dc.LineTo(point);
// dc.SelectObject(pOldPen);//在使用完新的畫筆後,要將原來的畫筆重新選擇時設備描述表
//使用畫刷來填充矩形
// CBrush m_brush(RGB(120, 0, 23));
// CClientDC dc(this);
// dc.FillRect(CRect(m_ptnOrigin, point), &m_brush);
//使用位圖畫刷來填充矩形
//創建一個位圖對象
// CBitmap m_bitmap;
// m_bitmap.LoadBitmap(IDB_MyBitmap);
// CBrush m_Brush(&m_bitmap);
// CClientDC dc(this);
// dc.FillRect(CRect(m_ptnOrigin, point), &m_Brush);
//透明畫刷
//首先使用Win32的API函數GetStockObject來獲取一個NULL_BRUSH畫刷
CClientDC dc(this);
CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
//是靜態成員函數,從句柄獲取對象的指針
CBrush *pOldBrush = dc.SelectObject(pBrush);
dc.Rectangle(CRect(m_ptnOrigin, point));
dc.SelectObject(pOldBrush);
bIsMouseDown = FALSE;
CView::OnLButtonUp(nFlags, point);
}