1.在單文檔中view擋在MainFrame的前面。此時如果編寫針對MainFrame的mouseClick事件,將不會有反應。
2.訊息響應會在3處修改代碼,1處是在標頭檔中,
//{{AFX_MSG(CDrawView)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
另一處是cpp檔案的begin MessageMap和End MessageMap之間,
BEGIN_MESSAGE_MAP(CDrawView, CView)
//{{AFX_MSG_MAP(CDrawView)
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
//}}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()
最後是要有函數實現的代碼。
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.畫線:定義一個成員變數儲存mouseDown的點m_Point
1)API函數方法畫線用HDC
2)用CDC類成員函數畫線。此時別忘記ReleaseDC
3)用CClientDC
4)用CWindowDC,用它甚至可以整個螢幕地區畫線。
下面是上面4種方法的代碼
/*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);必須成對使用。*/
/*CDC *pDC=GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);必須成對使用。*/
//CClientDC dc(this);
/*CClientDC dc(GetParent());
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);此處不需要ReleaseDC,因為CClientDC會自動釋放DC*/
//CWindowDC dc(this);
//CWindowDC dc(GetParent());
/*CWindowDC dc(GetDesktopWindow());//此時可以在整個螢幕上畫線。
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);*/
/*CPen pen(PS_DOT,1,RGB(0,255,0));
CClientDC dc(this);
CPen *pOldPen=dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen);*/
5)用Bitmap填充所畫的矩形。
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1);
CBrush brush(&bitmap);
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);
//CBRUSH::FromHandle是靜態成員函數,所以可以用下面的方法調用。
CBrush *pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
CBrush *pOldBrush=dc.SelectObject(pBrush);
dc.Rectangle(CRect(m_ptOrigin,point));
dc.SelectObject(pOldBrush);
m_bDraw=FALSE;
6)用其它顏色畫線
CClientDC dc(this);
CPen pen(PS_SOLID,1,RGB(255,0,0));
CPen *pOldPen=dc.SelectObject(&pen);//選中紅色畫筆
if(m_bDraw==TRUE)
{
dc.SetROP2(R2_BLACK);//設定繪畫模式
dc.MoveTo(m_ptOrigin);
//dc.LineTo(point);
dc.LineTo(m_ptOld);
//dc.MoveTo(m_ptOrigin);
dc.MoveTo(m_ptOld);
dc.LineTo(point);
//m_ptOrigin=point;
m_ptOld=point;
}
dc.SelectObject(pOldPen);
4.MFC中隱式的包含了windows.h。為什嗎?
因為在AFXV_W32.h檔案中:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
在AFXWIN.h中
// Note: WINDOWS.H already included from AFXV_W32.H
5.如何從控制代碼獲得對象的指標?
答FromHandle
6.類的靜態成員函數可以由類名直接調用,也可以由對象調用。可以認為靜態成員函數並不屬於某個對象,它屬於類本身。程式運行伊始,即使沒有執行個體化類的對象,靜態成員函數和靜態成員變數已然有其記憶體空間。靜態成員函數不能訪問非靜態成員變數!靜態成員變數必須在類的外部初始化。當然如果並不打算用到靜態成員變數,此時你可以不初始它。
7.理解代碼區,資料區,堆,棧!
請見下面的簡介:
http://www.downcode.com/server/j_server/J_1010.Html
對於一個進程的記憶體空間而言,可以在邏輯上分成3個部份:代碼區,待用資料區和動態資料區。動態資料區一般就是“堆棧”。“棧(stack)”和“堆(heap)”是兩種不同的動態資料區,棧是一種線性結構,堆是一種鏈式結構。進程的每個線程都有私人的“棧”,所以每個線程雖然代碼一樣,但本地變數的資料都是互不干擾。一個堆棧可以通過“基地址”和“棧頂”地址來描述。全域變數和靜態變數分配在待用資料區,本地變數分配在動態資料區,即堆棧中。程式通過堆棧的基地址和位移量來訪問本地變數。