1. 窗口选择:
View类和Frame类虽然都是窗口类,但是在单文档中View类是视类窗口,“挡在”Frame类框架窗口的前面。因此,如果编写针对Frame的MouseClick事件,框架窗口不能感到鼠标消息,即不会出现相应的效果。
2. MFC的消息映射机制:
在每个能接收和处理消息的类中,定义一个消息和消息函数对照表,即消息映射表。在消息映射表中,消息与对应的消息处理函数指针成对出现。某个类能处理的所有消息及其对应的消息处理函数的地址都列在这个类所对应的静态表中。当有消息需要处理时,程序只要搜索该消息静态表,查看表中是否含有该消息,就可知道该类能否处理此消息。如果能处理该消息,则同样依照静态表很容易找到并调用对应的消息处理函数。
MFC 消息映射机制是针对能接受消息和处理消息的类来定义对应的消息映射表,而不是由父类来定义所有消息对应的虚函数,由子类来覆盖其函数实现。因为这样做会使程序背着一个很大的虚拟函数表的包袱运行,对内存是一种浪费。
MFC工程中一个消息映射需要在三处添加代码:
- DoLineView.h视类头文件(vs2008)
在CDoLineView类的消息中添加ON_WM_LBUTTONDOWN函数后,DoLineView.h中自动添加响应的函数声明。
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
/*afx_msg是限定符(也是宏),表明函数是一个消息响应函数的声明*/
- DoLineView.cpp源文件的BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间,定义了CDoLineView类的消息映射表,其中ON_WM_LBUTTONDOWN映射宏就是将鼠标左键按下消息(WM_LBUTTONDOWN)与一个消息响应函数(OnLbuttonDown)关联。
BEGIN_MESSAGE_MAP(CDoLineView, CView)
// 标准打印命令
ON_COMMAND(ID_FILE_PRINT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, &CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CView::OnFilePrintPreview)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEHWHEEL()
END_MESSAGE_MAP()
自动添加自定义的消息映射,使用ON_MESSAGE(用户定义的消息,消息响应函数名)结尾无“;”号。
- DoLineView.cpp中添加函数实现。
void CDoLineView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
m_ptOrigin=m_ptOld=point;
m_bDraw=TRUE;
CView::OnLButtonDown(nFlags, point);
}
通过分析MFC消息响应函数在程序中有三处:函数原型,用来关联消息和消息响应函数的宏和函数实现。
3. 绘图程序
void CDoLineView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: 在此添加消息处理程序代码和/或调用默认值
//作图
//调用SDK函数获取设备上下文句柄
/*HDC hdc;
hdc=::GetDC(m_hWnd); //这个m_hWnd是CWnd类中的保护成员,保存窗口句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
::ReleaseDC(m_hWnd,hdc);*/ //在使用完设备上下文句柄后一定注意释放
//使用CDC关于作图对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);*/
CPen pen(PS_GEOMETRIC,10,RGB(255,255,255));//画笔类型,大小,颜色
CClientDC dc(this);
CPen *pOldpen=dc.SelectObject(&pen);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
dc.SelectObject(pOldpen);
CBrush brush(RGB(255,255,255));
/*CBitmap bitmap;
bitmap.LoadBitmap(IDC_ARROW);
CBrush brush(&bitmap);*/
/*CClientDC dc(this);
dc.FillRect(CRect(m_ptOrigin,point),&brush); //画刷
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;
CView::OnLButtonUp(nFlags, point);
}
类的静态成员函数可以由类名直接调用,也可以由对象调用。可以认为静态成员函数并不属于某个对象,它属于类本身。程序运行伊始,即使没有实例化类的对象,静态成员函数和静态成员变量已然有其内存空间。 静态成员函数不能访问非静态成员变量!静态成员变量必须在类的外部初始化。当然如果并不打算用到静态成员变量,此时你可以不初始它。