Lesson4 MFC消息映射机制和CDC类的使用
state:finished
1.在文档-视图结构中,View类总是覆盖在CMainFrm框架窗口之上的.所以框架窗口无法对
WM_LBUTTONDOWN消息做出响应.
2.在添加WM_LBUTONDOWN后,查看我们的工程的源程序变化
<1>查看 DrawView.h
-----------------------------------------------------------------------------------
protected:
//{{AFX_MSG(CDrawView) //注释宏
afx_msg void OnLButtonDown(UINT nFlags, CPoint point); //消息响应函数原型的声明.
//}}AFX_MSG
-----------------------------------------------------------------------------------
afx_msg 也是一个宏,指明后面的函数是消息响应函数
<2>查看 DrawView.cpp
-----------------------------------------------------------------------------------
BEGIN_MESSAGE_MAP(CDrawView, CView)
//{{AFX_MSG_MAP(CDrawView)
ON_WM_LBUTTONDOWN() //通过这个宏,把消息和我们的消息响应函数
//CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
//关联起来
//}}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()
-----------------------------------------------------------------------------------
3.MFC的消息映射机制
查看MFC的源代码:WINCORE.CPP
---------------------------------------------------------------------------------
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// OnWndMsg does most of the work, except for DefWindowProc call
LRESULT lResult = 0;
if (!OnWndMsg(message, wParam, lParam, &lResult))//真正的消息处理都是由OnWndMsg
//函数进行处理的
lResult = DefWindowProc(message, wParam, lParam);
return lResult;
}
---------------------------------------------------------------------------------
查看AFX_WIN.h
---------------------------------------------------------------------------------
virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
--------------------------------------------------------------------------------
//WindowProc(UINT message, WPARAM wParam, LPARAM lParam);是一个虚函数
/*在MFC中维护了一张消息到窗口的对应表,当接收到一个消息后,通过消息的句柄,找到与其相
关 联的窗口对象的指针,然后传给CWnd::WindowProc函数,CWnd::WindowProc函数函数交由
CWnd::OnWndMsg函数进行处理,判断子类是否有这个消息的响应函数,通过查看这个类的头文件
看有没有消息响应函数原型的声明,查看源文件,看有没有消息响应函数的定义.如果子类有,那
么交由子类处理消息,如果子类没有,消息交由父类进行处理.*/
4.实现我们的画线函数
---------------------------------------------------------------------------------
void CDrawView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//MessageBox("View Clicled!");
m_ptOrigin=point;
CView::OnLButtonDown(nFlags, point);
}
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
HDC hdc;
hdc=::GetDC(m_hWnd); //每个从CWnd类派生出来的类都有一个内部的数据成员m_hWnd
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc);
CView::OnLButtonUp(nFlags, point);
}
---------------------------------------------------------------------------------
MSDN
----------------------------------------------------------------------------------
BOOL MoveToEx(
HDC hdc, // handle to device context
int X, // x-coordinate of new current position
int Y, // y-coordinate of new current position
LPPOINT lpPoint // old current position
);
BOOL LineTo(
HDC hdc, // device context handle
int nXEnd, // x-coordinate of ending point
int nYEnd // y-coordinate of ending point
);
----------------------------------------------------------------------------------
5.CDC类
MFC把所有和窗口相关的操作都封装在CWnd类中.同样,MFC把所有和绘图相关的操作也封装在
CDC类中.
class CDC :public CObject
{
.........................
};
使用CDC类完成画线的功能.
MSDN
----------------------------------------------------------------------------------
CWnd::GetDC
Retrieves a pointer to a common, class, or private device context for the client
area depending on the class style specified for the CWnd.
CDC* GetDC();
----------------------------------------------------------------------------------
DrawView.CPP
---------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CDC *pDC=GetDC();
pDC->MoveTo(m_ptOrigin);
pDC->LineTo(point);
ReleaseDC(pDC);
CView::OnLButtonUp(nFlags, point);
}
---------------------------------------------------------------------------------
6.使用CClientDC
CClientDC派生自CDC
构造CClientDC对象的时候自动调用GetDC,而在析构的时候自动调用ReleaseDC.从而我们不需要
显示的去调用这两个函数.只需要仅仅构造一个CClientDC对象.
MSDN
-----------------------------------------------------------------------------------
CClientDC::CClientDCSee Also
Constructs a CClientDC object that accesses the client area of the CWnd pointed
to by pWnd.
explicit CClientDC(
CWnd* pWnd
);
-----------------------------------------------------------------------------------
构造的时候需要一个CWnd*
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//CClientDC dc(this);
CClientDC dc(GetParent());//获得父窗口(框架窗口的句柄)
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
}
7.CWindowDC
class CWindowDC : public CDC
构造CWindowDC对象时,自动调用GetWindowDC,析构时自动调用ReleaseDC.
有了CWindowDC对象我们可以访问整个屏幕区域,包括客户区域和非客户区域.
MSDN
----------------------------------------------------------------------------------
CWindowDC::CWindowDC
Constructs a CWindowDC object that accesses the entire screen area
(both client and nonclient) of the CWnd object pointed to by pWnd.
explicit CWindowDC(
CWnd* pWnd
);
-----------------------------------------------------------------------------------
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//CWindowDC dc(this);
CWindowDC dc(GetParent());//获得父窗口(框架窗口的句柄)
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
}
-----------------------------------------------------------------------------------
8.CWnd::GetDesktopWindow 函数
MSDN
-------------------------------------------------------------------------------------
CWnd::GetDesktopWindow
Returns the Windows desktop window.
static CWnd* PASCAL GetDesktopWindow( );
-------------------------------------------------------------------------------------
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
//CWindowDC dc(this);
CWindowDC dc(GetDesktopWindow());//获得桌面窗口句柄
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
}
-----------------------------------------------------------------------------------
9.画出其他颜色的线条
CPen类
封装了和画笔相关的操作.
CPen的构造函数
MSDN
-----------------------------------------------------------------------------------
Constructs a CPen object.
CPen( );
CPen(
int nPenStyle, //笔的风格 PS_SOLID Creates a solid pen.
//PS_DASH Creates a dashed pen. Valid only when the
//pen width is 1 or less, in device units.
//PS_DOT Creates a dotted pen.........
int nWidth, //线条的宽度
COLORREF crColor //笔的颜色
);
CPen(
int nPenStyle,
int nWidth,
const LOGBRUSH* pLogBrush,
int nStyleCount = 0,
const DWORD* lpStyle = NULL
);
-----------------------------------------------------------------------------------
RGB宏
MSDN
-----------------------------------------------------------------------------------
COLORREF RGB(
BYTE byRed, // red component of color
BYTE byGreen, // green component of color
BYTE byBlue // blue component of color
); //RGB(0,0,0)Black,RGB(255,255,255)White
-----------------------------------------------------------------------------------
CDC::SelectObject
MSDN
-------------------------------------------------------------------------------------
CDC::SelectObject
Selects an object into the device context.
CPen* SelectObject(
CPen* pPen
);
CBrush* SelectObject(
CBrush* pBrush
);
virtual CFont* SelectObject(
CFont* pFont
);
CBitmap* SelectObject(
CBitmap* pBitmap
);
int SelectObject(
CRgn* pRgn
);
CGdiObject* SelectObject(
CGdiObject* pObject
);
------------------------------------------------------------------------------------
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CPen pen(PS_SOLID,1,RGB(255,0,0)); //创建画笔
CClientDC dc(this);
CPen *pOldPen=dc.SelectObject(&pen);//把创建的画笔选进设备描述表
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldPen); //还原设备描述表
CView::OnLButtonUp(nFlags, point);
}
-----------------------------------------------------------------------------------
10.创建画刷
CBrush类
MSDN
---------------------------------------------------------------------------------
CBrush::CBrush
Constructs a CBrush object.
CBrush( );
CBrush(
COLORREF crColor
);
CBrush(
int nIndex,
COLORREF crColor
);
explicit CBrush(
CBitmap* pBitmap
);
---------------------------------------------------------------------------------
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBrush brush(RGB(255,0,0)); //创建画刷
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);//用制定的画刷,填充矩形区域
CView::OnLButtonUp(nFlags, point);
}
-----------------------------------------------------------------------------------
创建位图的画刷:
CBitmap类
MSDN
-----------------------------------------------------------------------------------
CBitmap::CBitmap
Constructs a CBitmap object.
CBitmap( ); // 需要使用函数对其进行初始化
Remarks
The resulting object must be initialized with one of the initialization member
functions.
-------------------------------------------------------------------------------------
LoadBitmap函数,加载位图
MSDN
-------------------------------------------------------------------------------------
CBitmap::LoadBitmap
Loads the bitmap resource named by lpszResourceName or identified by the ID number
in nIDResource from the application's executable file.
BOOL LoadBitmap(
LPCTSTR lpszResourceName
);
BOOL LoadBitmap(
UINT nIDResource
);
-------------------------------------------------------------------------------------
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBitmap bitmap;
bitmap.LoadBitmap(IDB_BITMAP1); //加载位图
CBrush brush(&bitmap);
CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush);//用制定的画刷,填充矩形区域
CView::OnLButtonUp(nFlags, point);
}
-----------------------------------------------------------------------------------
透明画刷的创建
CBrush::FromHandle
MSDN
-------------------------------------------------------------------------------------
CBrush::FromHandle
Returns a pointer to a CBrush object when given a handle to a Windows HBRUSH object.
static CBrush* PASCAL FromHandle(
HBRUSH hBrush //这是CBrush类的静态方法
//在静态的成员函数中,是不能引用非静态的数据成员
//因为非静态的数据成员,是在类实例化一个对象时才分配内存空间的.
//静态的数据成员使用之前必须初始化
);
-------------------------------------------------------------------------------------
由CBrush::FromHandle可以从一个画刷的句柄,得到指向这个画刷对象的指针.
DrawView.CPP
-----------------------------------------------------------------------------------
void CDrawView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
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);
CView::OnLButtonUp(nFlags, point);
}
-----------------------------------------------------------------------------------
11.设置绘图模式(CDC::SetROP2)
CDC::SetROP2函数
MSDN
------------------------------------------------------------------------------------
CDC::SetROP2
Sets the current drawing mode.
int SetROP2(
int nDrawMode
);
Parameters
nDrawMode
Specifies the new drawing mode. It can be any of the following values:
R2_BLACK Pixel is always black.
R2_WHITE Pixel is always white.
R2_NOP Pixel remains unchanged.
R2_NOT Pixel is the inverse of the screen color.
R2_COPYPEN Pixel is the pen color.
R2_NOTCOPYPEN Pixel is the inverse of the pen color.