MFC消息映射机制剖析文档格式.docx
- 文档编号:21707592
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:11
- 大小:24.18KB
MFC消息映射机制剖析文档格式.docx
《MFC消息映射机制剖析文档格式.docx》由会员分享,可在线阅读,更多相关《MFC消息映射机制剖析文档格式.docx(11页珍藏版)》请在冰豆网上搜索。
#defineON_WM_LBUTTONDOWN()\
{WM_LBUTTONDOWN,0,0,0,AfxSig_vwp,\
(AFX_PMSG)(AFX_PMSGW)(void(AFX_MSG_CALLCWnd:
*)(UINT,CPoint))&
OnLButtonDown},
3)源文件中进行消息响应函数处理。
(DrawView.cpp中自动生成OnLButtonDown函数轮廓,如下)
voidCDrawView:
OnLButtonDown(UINTnFlags,CPointpoint)
{
//TODO:
Addyourmessagehandlercodehereand/orcalldefault
CView:
OnLButtonDown(nFlags,point);
}
可见当增加一个消息响应处理,在以上三处进行了修改。
可在消息响应函数里添加消息处理代码完成对消息的响应、处理。
2,消息响应的方式:
1)在基类中针对每种消息做一个虚函数,当子类对消息响应时候,只要在子类中重写这个虚函数即可。
缺点:
MFC类派生层次很多,如果在基类对每个消息进行虚函数处理,那么从基类派生的每个子类都将背负一个庞大的虚表,这样浪费内存,故MFC没有采取这中方式而采取消息映射方式。
2)消息映射方式:
MFC在后台维护了一个句柄和C++对象指针对照表,当收到一个消息后,通过消息结构里资源句柄(查对照表)就可找到与它对应的一个C++对象指针,然后把这个指针传给基类,基类利用这个指针调用WindowProc()函数对消息进行处理,WindowProc()函数中调用OnWndMsg()函数,真正的消息路由及处理是由OnWndMsg()函数完成的。
由于WindowProc()和OnWndMsg()都是虚函数,而且是用派生类对象指针调用的,由多态性知最总终调用子类的。
在OnWndMsg()函数处理的时候,根据消息种类去查找消息映射,判断所发的消息有没有响应函数,具体方式是到相关的头文件和源文件中寻找消息响应函数声明(从注释宏//{{AFX_MSG(CDrawView)...//}}AFX_MSG之间寻找),消息映射(从宏BEGIN_MESSAGE_MAP(...)....END_MESSAGE_MAP()之间寻找),最终找到对应的消息处理函数。
当然,如果子类中没有对消息进行处理,则消息交由基类处理。
virtualLRESULTWindowProc(UINTmessage,WPARAMwParam,LPARAMlParam);
virtualBOOLOnWndMsg(UINTmessage,WPARAMwParam,LPARAMlParam,LRESULT*pResult);
二,有关绘图
1,使用SDK获取DC句柄:
HDChdc;
hdc=:
GetDc(m_hWnd);
//获取DC句柄
MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);
LineTo(hdc,point.x,point.y);
ReleaseDC(m_hWnd,hdc);
//释放DC
2,利用CDC类指针和CWin类成员函数获取DC。
CDC*pDC=GetDC();
pDC->
MoveTo(m_ptOrigin);
LineTo(point);
ReleaseDC(pDC);
3,利用CClientDC对象。
(CClientDC类从CDC类派生来的)
CClientDCdc(this);
dc.MoveTo(m_ptOrigin);
dc.LineTo(point);
TheCClientDCclassisderivedfromCDCandtakescareofcallingtheWindowsfunctionsGetDCatconstructiontimeandReleaseDCatdestructiontime.ThismeansthatthedevicecontextassociatedwithaCClientDCobjectistheclientareaofawindow.
4,利用CWindowDC对象。
(CWindowDC类从CDC类派生来的)
CWindowDCdc(this);
//
TheCWindowDCclassisderivedfromCDC.ItcallstheWindowsfunctionsGetWindowDCatconstructiontimeandReleaseDCatdestructiontime.ThismeansthataCWindowDCobjectaccessestheentirescreenareaofaCWnd(bothclientandnonclientareas).
5,GetParent()得到父窗口指针;
GetDesktopWindow()得到屏幕窗口指针。
6,利用画笔改变线条颜色和类型:
CPenpen(PS_DOT,1,RGB(0,255,0));
//构造画笔对象
CPen*pOldPen=dc.SelectObject(&
pen);
//将画笔选入DC
dc.SelectObject(pOldPen);
//恢复先前的画笔
7,使用画刷(通常利用画刷去填充矩形区域):
使用单色画刷
CBrushbrush(RGB(255,0,0));
//构造画刷对象
dc.FillRect(CRect(m_ptOrigin,point),&
brush);
//用指定的画刷去填充矩形区域
使用位图画刷
CBitmapbitmap;
//构造位图对象(使用前需要初试化)
bitmap.LoadBitmap(IDB_BITMAP1);
//初试化位图对象
CBrushbrush(&
bitmap);
//构造位图画刷
//用指定的位图画刷去填充矩形区域
使用透明画刷
CBrush*pBrush=CBrush:
FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));
//获取透明画刷对象指针
CBrush*pOldBrush=dc.SelectObject(pBrush);
//将透明画刷选入DC
dc.Rectangle(CRect(m_ptOrigin,point));
dc.SelectObject(pOldBrush);
//释放透明画刷
TheGetStockObjectfunctionretrievesahandletooneofthepredefinedstockpens,brushes,fonts,orpalettes.
HGDIOBJGetStockObject(
intfnObject
//typeofstockobject
);
ReturnsapointertoaCBrushobjectwhengivenahandletoaWindowsHBRUSHobject.
staticCBrush*PASCALFromHandle(HBRUSHhBrush);
//FromHandle是一个静态方法,故可用CBrush:
FromHandle()形式调用。
注意点:
1)静态方法不属于某一个具体对象,而属于类本身,在类加载的时候就已经为类静态方法分配了代码去,故可用CBrush:
2)静态方法中,不能引用非静态的数据成员和方法。
3)静态数据成员需要在类外单独做初始化,形式如:
变量类型类名:
变量名=初始值;
8,CDC:
SetROP2方法:
intSetROP2(intnDrawMode);
Setsthecurrentdrawingmode.
(5)文本编程
1,创建插入符:
voidCreateSolidCaret(intnWidth,intnHeight);
//创建插入符
voidCreateCaret(CBitmap*pBitmap);
//创建位图插入符
voidShowCaret();
//显示插入符
voidHideCaret();
//隐藏插入符
staticvoidPASCALSetCaretPos(POINTpoint);
//移动插入符号
1)创建插入符要在窗口创建完成之后,CreateSolidCaret函数创建的插入符被初始化为隐藏,所以需要调用ShowCaret()将其显示。
2)使用CreateCaret函数创建位图插入符的时候,不能使用局部的位图对象关联位图资源。
(与资源相关联的C++对象,当它析构的时候会同时把与它相关联的资源销毁。
)
2,获取当前字体信息的度量:
CDC:
GetTextMetrics
BOOLGetTextMetrics(LPTEXTMETRIClpMetrics)const;
typedefstructtagTEXTMETRIC{
/*tm*/
int
tmHeight;
//字体高度。
Specifiestheheight(ascent+descent)ofcharacters.
tmAscent;
//基线以上的字体高度
tmDescent;
//基线以下的字体高度
tmInternalLeading;
tmExternalLeading;
tmAveCharWidth;
//字符平均宽度
tmMaxCharWidth;
tmWeight;
BYTEtmItalic;
BYTEtmUnderlined;
BYTEtmStruckOut;
BYTEtmFirstChar;
BYTEtmLastChar;
BYTEtmDefaultChar;
BYTEtmBreakChar;
BYTEtmPitchAndFamily;
BYTEtmCharSet;
tmOverhang;
tmDigitizedAspectX;
tmDigitizedAspectY;
}TEXTMETRIC;
3,OnDraw函数:
virtualvoidOnDraw(CDC*pDC)
当窗口(从无到有或尺寸大小改变等)要求重绘的时候,会发送WM_PAIN消息,调用OnDraw函数进行重绘。
4,获取字符串的高度和宽度(区别字符串的长度):
GetTextExtent
CSizeGetTextExtent(LPCTSTRlpszString,intnCount)const;
CSizeGetTextExtent(constCString&
str)const;
TheCSizeclassissimilartotheWindowsSIZEstructure。
typedefstructtagSIZE{
intcx;
//thex-extent
intcy;
//they-extent
}SIZE;
5,路径层:
BOOLBeginPath();
//在这作图定义路径层剪切区域
BOOLEndPath();
BOOLSelectClipPath(intnMode);
//调用这个函数来使当前路径层剪切区域与新剪切区域进行互操作。
//在这覆盖作图(包含前定义的路径层区域)定义新的剪切区域
1)SelectClipPathSelectsthecurrentpathasaclippingregionforthedevicecontext,combiningthenewregionwithanyexistingclippingregionbyusingthespecifiedmode.Thedevicecontextidentifiedmustcontainaclosedpath.
////
nMode:
RGN_AND,RGN_COPY,RGN_DIFF,RGN_OR,RGN_XOR
RGN_AND
Thenewclippingregionincludestheintersection(overlappingareas)ofthecurrentclippingregionandthecurrentpath.
RGN_COPY
Thenewclippingregionisthecurrentpath.
RGN_DIFF
Thenewclippingregionincludestheareasofthecurrentclippingregion,andthoseofthecurrentpathareexcluded.
RGN_OR
Thenewclippingregionincludestheunion(combinedareas)ofthecurrentclippingregionandthecurrentpath.
RGN_XOR
Thenewclippingregionincludestheunionofthecurrentclippingregionandthecurrentpath,butwithouttheoverlappingareas.
2)应用:
当作图的时候,如果想要在整幅图形其中的某个部分和其它部分有所区别,我们可以把这部分图形放到路径层当中,然后指定调用指定互操作模式调用SelectClipPath(intnMode)函数来使路径层和覆盖在其上新绘图剪切区域进行互操作,达到特殊效果。
6,关于文本字符串一些函数:
COLORREFGetBkColor()const;
//得到背景颜色
virtualCOLORREFSetBkColor(COLORREFcrColor);
//设置背景颜色
BOOLSetTextBkColor(COLORREFcr);
//设置文本背景颜色
virtualCOLORREFSetTextColor(COLORREFcrColor);
//设置文本颜色
virtualBOOLTextOut(intx,inty,LPCTSTRlpszString,intnCount);
//输出文本
BOOLTextOut(intx,inty,constCString&
str);
CStringLeft(intnCount)const;
//得到字符串左边nCount个字符
intGetLength()const;
//得到字符串长度
7,字体CFont:
CFont
CFont();
//构造函数
//ConstructsaCFontobject.TheresultingobjectmustbeinitializedwithCreateFont,CreateFontIndirect,CreatePointFont,orCreatePointFontIndirectbeforeitcanbeused.
选用字体事例代码组:
CFontfont;
//构造字体对象
font.CreatePointFont(300,"
华文行楷"
NULL);
//初始化字体对象,与字体资源相关联
CFont*pOldFont=dc.SelectObject(&
font);
//将新字体选入DC
...
dc.SelectObject(pOldFont);
//恢复原字体
1)构造字体对象时候,必须初始化。
(初始化是将字体对象与字体资源相关联)。
2)初始化对象时候,选用的字体也可以是系统字体,但不一定都有效,据测试选用。
8,在MFC中CEditView和cRichEditView类已经完成了初步的文字处理。
可以让应用程序的View类以CEditView和cRichEditView类为基类。
9,平滑变色
TextOut()是一个字母一个字母的输出,达不到平滑效果。
DrawText():
将文字的输出局限于一个矩形区域,超出矩形区域的文字都被截断。
利用这一特点,可每隔些时间增加矩形大小,从而可实现人眼中的平滑效果。
CWnd:
SetTimer():
设置定时器。
按设定的时间定时发送WM_TIMER消息。
UINTSetTimer(UINTnIDEvent,UINTnElapse,void(CALLBACKEXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD));
//nIDEvent定时器标示,nElapse消息发送间隔时间,void(CALLBACKEXPORT*lpfnTimer)(HWND,UINT,UINT,DWORD)设置回调函数,如果设置则由设置的回调函数处理WM_TIMER消息,如果没有设置回调函数设为NULL,这发送的WM_TIMER消息压入消息队列,交由相关联的窗口处理(添加WM_TIMER消息处理函数OnTimer())。
afx_msgvoidOnTimer(UINTnIDEvent);
//响应WM_TIMER消息,nIDEvent为消息对应定时器标示(可以设置不同的定时器发送WM_TIMER消息)
问题:
1,在CCareView类中添加WM_CREATE消息响应函数OnCreate(),WM_CREATE消息是在什么时候被检查到而被响应的呢?
(猜测:
添加WM_CREATE消息后,消息被压入消息队列,然后经过消息循环进行分发到具体窗口,从而进行响应)
2,现有一文本文件内容已经读入串STR中,要求在视图客户区按原先文本文件中的格式输出。
问题是,利用CDC的TextOut()来在CView类派生类窗口中输出串时,忽略了串中的TAB、回车换行等格式,无论串有多长均在一行上输出。
这其中是CDC类成员函数TextOut()忽略串中格式的,还是CView类派生类窗口设置从中做怪呢?
怎么解决?
(6)菜单编程
1,弹出菜单(Pop-up)是不能用来作命令响应的。
2,MFC中菜单项消息如果利用ClassWizard来对菜单项消息分别在上述四个类中进行响应,则菜单消息传递顺序:
View类--Doc类--CMainFrame类--App类。
菜单消息一旦在其中一个类中响应则不再在其它类中查找响应函数。
具体:
当点击一个菜单项的时候,最先接受到菜单项消息的是CMainFrame框架类,CMainFrame框架类将会把菜单项消息交给它的子窗口View类,由View类首先进行恚蝗绻鸙iew类检测到没对该菜单项消息做响应,则View类把菜单项消息交由文档类Doc类进行处理;
如果Doc类检测到Doc类中也没对该菜单项消息做响应,则Doc类又把该菜单项消息交还给View类,由View类再交还给CMainFrame类处理。
如果CMainFrame类查看到CMainFrame类中也没对该消息做响应,则最终交给App类进行处理。
3,消息的分类:
标准消息,命令消息,通告消息。
[标准消息]:
除WM_COMMAND之外,所有以WM_开头的消息。
[命令消息]:
来自菜单、加速键或工具栏按钮的消息。
这类消息都以WM_COMMAND呈现。
在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;
在SDK中,通过消息的wParam参数识别。
[通告消息]:
由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。
这类消息也是以WM_COMMAND形式呈现。
1)从CWnd派生的类,都可以接收到[标准消息]。
2)从CCmdTarget派生的类,都可以接收到[命令消息]和[通告消息]。
4,一个菜单拦可以有若干个子菜单,一个子菜单又可以有若干个菜单项等。
对菜单栏的子菜单由左至右建立从0开始的索引。
对特定子菜单的菜单项由上至下建立了从0开始的索引。
访问子菜单和菜单项均可以通过其索引或标识(如果有标识的话)进行。
相关重要函数:
CMenu*GetMenu();
//CWnd:
GetMenu
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MFC 消息 映射 机制 剖析