?? 孫鑫vc++講座筆記-(4)mfc消息映射機(jī)制的剖析_亮亮的空間.htm
字號:
</STYLE>
<DIV id=usrbar><NOBR>
<SCRIPT> var myref = encodeURI("http://hi.baidu.com/hl66/blog/item/9aa6f103daebff88d53f7c6d%2Ehtml");</SCRIPT>
<A href="http://www.baidu.com/" target=_blank>百度首頁</A> | <A
href="http://hi.baidu.com/" target=_blank>百度空間</A>
<SCRIPT language=JavaScript>
document.write(" | <a href='http://passport.baidu.com/?login&tpl=sp&tpl_reg=sp&u="+myref+"'>登錄</a>");
document.write(" | <a href='http://passport.baidu.com/?reg&tpl=sp&return_method=get&skip_ok=1&u=http://hi.baidu.com/sys/reg/' target='_blank'>注冊</a>");
</SCRIPT>
</NOBR></DIV>
<DIV id=main align=left><!--[if IE]>
<SCRIPT>
var objmain = document.getElementById("main");
function updatesize(){ var bodyw = window.document.body.offsetWidth; if(bodyw <= 790) objmain.style.width="772px"; else if(bodyw >= 1016) objmain.style.width="996px"; else objmain.style.width="100%"; }
updatesize(); window.onresize = updatesize;
</SCRIPT>
<![endif]-->
<DIV id=header>
<DIV class=lc>
<DIV class=rc></DIV></DIV>
<DIV class=tit><A class=titlink title="huliang66的空間 http://hi.baidu.com/hl66"
href="http://hi.baidu.com/hl66">亮亮的空間</A></DIV>
<DIV class=desc></DIV>
<DIV id=tabline></DIV>
<DIV id=tab><A href="http://hi.baidu.com/hl66">主頁</A><A class=on
href="http://hi.baidu.com/hl66/blog">博客</A><A
href="http://hi.baidu.com/hl66/album">相冊</A><SPAN>|</SPAN><A
href="http://hi.baidu.com/hl66/profile">個人檔案</A> </DIV></DIV>
<DIV class=stage>
<DIV class=stagepad>
<DIV style="WIDTH: 100%">
<TABLE class=modth cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=modtl width=7> </TD>
<TD class=modtc noWrap>
<DIV class=modhead><SPAN class=modtit>查看文章</SPAN></DIV></TD>
<TD class=modtc noWrap align=right></TD>
<TD class=modtr width=7> </TD></TR></TBODY></TABLE>
<DIV class=modbox id=m_blog>
<DIV class=tit>孫鑫VC++講座筆記-(4)MFC消息映射機(jī)制的剖析</DIV>
<DIV class=date>2006-09-25 11:38</DIV>
<TABLE style="TABLE-LAYOUT: fixed">
<TBODY>
<TR>
<TD>
<DIV class=cnt>
<DIV class=postTitle align=center><STRONG><FONT
size=3>孫鑫VC++講座筆記-(4)MFC消息映射機(jī)制的剖析 </FONT></STRONG><STRONG><FONT
size=3><IMG style="WIDTH: 35px; HEIGHT: 30px" height=13
src="孫鑫VC++講座筆記-(4)MFC消息映射機(jī)制的剖析_亮亮的空間.files/zhuan.gif" width=15
border=0></FONT></STRONG></DIV>
<P class=postText>一,消息映射機(jī)制</P>
<P class=postText> <STRONG><FONT
color=#0000ff>MFC消息映射機(jī)制的具體實(shí)現(xiàn)方法是</FONT></STRONG>:在每個能接受和處理消息的類中,定義一個消息和消息函數(shù)靜態(tài)對照表,既消息映射表。在消息映射表中,消息與對應(yīng)的消息處理函數(shù)指針是成對出現(xiàn)的。某個類能處理的所有消息及其對應(yīng)的消息處理函數(shù)的地址都列在這個類所對應(yīng)的靜態(tài)表中。當(dāng)有消息需要處理時,程序只要搜索該消息靜態(tài)表,查看表中是否含有該消息,就可以知道該類能否處理此消息。如果能處理該消息,則同樣依照靜態(tài)表能很容易找到并調(diào)用對應(yīng)的消息處理函數(shù)。</P>
<P
class=postText>1,消息響應(yīng)函數(shù):(例:在CDrawView類響應(yīng)鼠標(biāo)左鍵按下消息)<BR> 1)在頭文件(DrawView.h)中聲明消息響應(yīng)函數(shù)原型。<BR>//{{AFX_MSG(CDrawView)
//注釋宏<BR>afx_msg void OnLButtonDown(UINT nFlags, CPoint
point);<BR>//}}AFX_MSG
//注釋宏<BR>說明:<BR>在注釋宏之間的聲明在VC中灰色顯示。afx_msg宏表示聲明的是一個消息響應(yīng)函數(shù)。<BR> 2)在源文件(DrawView.cpp)中進(jìn)行消息映射。<BR>BEGIN_MESSAGE_MAP(CDrawView,
CView)<BR> //{{AFX_MSG_MAP(CDrawView)<BR> ON_WM_LBUTTONDOWN()<BR> //}}AFX_MSG_MAP<BR> //
Standard printing commands<BR> ON_COMMAND(ID_FILE_PRINT,
CView::OnFilePrint)<BR> ON_COMMAND(ID_FILE_PRINT_DIRECT,
CView::OnFilePrint)<BR> ON_COMMAND(ID_FILE_PRINT_PREVIEW,
CView::OnFilePrintPreview)<BR>END_MESSAGE_MAP()<BR>說明:<BR>在宏BEGIN_MESSAGE_MAP()與END_MESSAGE_MAP()之間進(jìn)行消息映射。<BR>宏ON_WM_LBUTTONDOWN()把消息WM_LBUTTONDOWN與它的響應(yīng)函數(shù)OnLButtonDown()相關(guān)聯(lián)。這樣一旦有消息的產(chǎn)生,就會自動調(diào)用相關(guān)聯(lián)的消息響應(yīng)函數(shù)去處理。<BR>宏ON_WM_LBUTTONDOWN()定義如下:<BR>#define
ON_WM_LBUTTONDOWN() \<BR> { WM_LBUTTONDOWN, 0, 0, 0, AfxSig_vwp,
\<BR> (AFX_PMSG)(AFX_PMSGW)(void (AFX_MSG_CALL CWnd::*)(UINT,
CPoint))&OnLButtonDown
},<BR> 3)源文件中進(jìn)行消息響應(yīng)函數(shù)處理。(DrawView.cpp中自動生成OnLButtonDown函數(shù)輪廓,如下)<BR>void
CDrawView::OnLButtonDown(UINT nFlags, CPoint point) <BR>{<BR> //
TODO: Add your message handler code here and/or call
default<BR> CView::OnLButtonDown(nFlags,
point);<BR>}<BR>說明:<BR>可見當(dāng)增加一個消息響應(yīng)處理,在以上三處進(jìn)行了修改。可在消息響應(yīng)函數(shù)里添加消息處理代碼完成對消息的響應(yīng)、處理。</P>
<P
class=postText>2,消息響應(yīng)的方式:<BR>1)在基類中針對每種消息做一個虛函數(shù),當(dāng)子類對消息響應(yīng)時候,只要在子類中重寫這個虛函數(shù)即可。缺點(diǎn):MFC類派生層次很多,如果在基類對每個消息進(jìn)行虛函數(shù)處理,那么從基類派生的每個子類都將背負(fù)一個龐大的虛表,這樣浪費(fèi)內(nèi)存,故MFC沒有采取這中方式而采取消息映射方式。<BR>2)消息映射方式:MFC在后臺維護(hù)了一個句柄和C++對象指針對照表,當(dāng)收到一個消息后,通過消息結(jié)構(gòu)里資源句柄(查對照表)就可找到與它對應(yīng)的一個C++對象指針,然后把這個指針傳給基類,基類利用這個指針調(diào)用WindowProc()函數(shù)對消息進(jìn)行處理,WindowProc()函數(shù)中調(diào)用OnWndMsg()函數(shù),真正的消息路由及處理是由OnWndMsg()函數(shù)完成的。由于WindowProc()和OnWndMsg()都是虛函數(shù),而且是用派生類對象指針調(diào)用的,由多態(tài)性知最總終調(diào)用子類的。在OnWndMsg()函數(shù)處理的時候,根據(jù)消息種類去查找消息映射,判斷所發(fā)的消息有沒有響應(yīng)函數(shù),具體方式是到相關(guān)的頭文件和源文件中尋找消息響應(yīng)函數(shù)聲明(從注釋宏//{{AFX_MSG(CDrawView)...//}}AFX_MSG之間尋找),消息映射(從宏BEGIN_MESSAGE_MAP(...)....END_MESSAGE_MAP()之間尋找),最終找到對應(yīng)的消息處理函數(shù)。當(dāng)然,如果子類中沒有對消息進(jìn)行處理,則消息交由基類處理。<BR>說明:<BR>virtual
LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);<BR>virtual
BOOL OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT*
pResult);</P>
<P class=postText> </P>
<P class=postText>二,有關(guān)繪圖</P>
<P class=postText>1,使用SDK獲取DC句柄:<BR>HDC
hdc;<BR>hdc=::GetDc(m_hWnd);//獲取DC句柄<BR>MoveToEx(hdc,m_ptOrigin.x,m_ptOrigin.y,NULL);<BR>LineTo(hdc,point.x,point.y);<BR>::ReleaseDC(m_hWnd,hdc);//釋放DC</P>
<P class=postText>2,利用CDC類指針和CWin類成員函數(shù)獲取DC。<BR>CDC
*pDC=GetDC();<BR>pDC->MoveTo(m_ptOrigin);<BR>pDC->LineTo(point);<BR>ReleaseDC(pDC);</P>
<P class=postText>3,利用CClientDC對象。(CClientDC類從CDC類派生來的)<BR>CClientDC
dc(this);<BR>dc.MoveTo(m_ptOrigin);<BR>dc.LineTo(point);<BR>說明:<BR>The
CClientDC class is derived from CDC and takes care of calling the Windows
functions GetDC at construction time and ReleaseDC at destruction time.
This means that the device context associated with a CClientDC object is
the client area of a window.</P>
<P class=postText>4,利用CWindowDC對象。(CWindowDC類從CDC類派生來的)<BR>CWindowDC
dc(this);//<BR>dc.MoveTo(m_ptOrigin);<BR>dc.LineTo(point);<BR>說明:<BR>The
CWindowDC class is derived from CDC. It calls the Windows
functionsGetWindowDC at construction time andReleaseDC at destruction
time. This means that a CWindowDC object accesses the entire screen area
of a CWnd (both client and nonclient areas).</P>
<P class=postText>5,GetParent()得到父窗口指針;GetDesktopWindow()得到屏幕窗口指針。</P>
<P class=postText>6,利用畫筆改變線條顏色和類型:<BR>CPen
pen(PS_DOT,1,RGB(0,255,0));//構(gòu)造畫筆對象<BR>CClientDC dc(this);CPen
*pOldPen=dc.SelectObject(&pen);//將畫筆選入DC<BR>dc.MoveTo(m_ptOrigin);<BR>dc.LineTo(point);<BR>dc.SelectObject(pOldPen);//恢復(fù)先前的畫筆</P>
<P class=postText>7,使用畫刷(通常利用畫刷去填充矩形區(qū)域):<BR>使用單色畫刷<BR>CBrush
brush(RGB(255,0,0));//構(gòu)造畫刷對象<BR>CClientDC
dc(this);<BR>dc.FillRect(CRect(m_ptOrigin,point),&brush);//用指定的畫刷去填充矩形區(qū)域</P>
<P class=postText>使用位圖畫刷<BR>CBitmap
bitmap;//構(gòu)造位圖對象(使用前需要初試化)<BR>bitmap.LoadBitmap(IDB_BITMAP1);//初試化位圖對象<BR>CBrush
brush(&bitmap);//構(gòu)造位圖畫刷<BR>CClientDC
dc(this);<BR>dc.FillRect(CRect(m_ptOrigin,point),&brush);//用指定的位圖畫刷去填充矩形區(qū)域</P>
<P class=postText>使用透明畫刷<BR>CBrush
*pBrush=CBrush::FromHandle((HBRUSH)GetStockObject(NULL_BRUSH));//獲取透明畫刷對象指針<BR>CClientDC
dc(this);<BR>CBrush
*pOldBrush=dc.SelectObject(pBrush);//將透明畫刷選入DC<BR>dc.Rectangle(CRect(m_ptOrigin,point));<BR>dc.SelectObject(pOldBrush);//釋放透明畫刷<BR>說明:<BR>The
GetStockObject function retrieves a handle to one of the predefined stock
pens, brushes, fonts, or palettes. <BR>HGDIOBJ GetStockObject(<BR>
int fnObject // type of stock object<BR>);</P>
<P class=postText>Returns a pointer to a CBrush object when given a handle
to a Windows HBRUSH object. <BR>static CBrush* PASCAL FromHandle( HBRUSH
hBrush
);//FromHandle是一個靜態(tài)方法,故可用CBrush::FromHandle()形式調(diào)用。<BR>注意點(diǎn):<BR>1)靜態(tài)方法不屬于某一個具體對象,而屬于類本身,在類加載的時候就已經(jīng)為類靜態(tài)方法分配了代碼去,故可用CBrush::FromHandle()形式調(diào)用。<BR>2)靜態(tài)方法中,不能引用非靜態(tài)的數(shù)據(jù)成員和方法。<BR>3)靜態(tài)數(shù)據(jù)成員需要在類外單獨(dú)做初始化,形式如:
變量類型 類名::變量名=初始值;</P>
<P class=postText>8,CDC::SetROP2方法:<BR>int SetROP2( int nDrawMode
);<BR>Sets the current drawing mode. </P></DIV></TD></TR></TBODY></TABLE><BR>
<DIV class=opt><A title=查看該分類中所有文章
href="http://hi.baidu.com/hl66/blog/category/Ñ§Ï°Çø(×ªÔØ)">類別:學(xué)習(xí)區(qū)(轉(zhuǎn)載)</A> |
瀏覽(<SPAN id=result></SPAN>) </DIV>
<DIV class=line></DIV>
<SCRIPT language=JavaScript>
allkey=allkey+"629c923da187dc00baa167d2_9aa6f103daebff88d53f7c6d_";
</SCRIPT>
<DIV id=in_comment><A name=comment></A>
<DIV class=tit>網(wǎng)友評論:</DIV>
<SCRIPT>
function writecmt(type,id,cmtname,cmturl,cmttime){
var html1="";
if(type==1){
if(cmturl==""){
html1="<a name='"+id+"'>"+cmtname+"</a> - <span class='date'>"+cmttime+"</span> ";
}else{
html1="<a name='"+id+"' href='"+cmturl+"' target='_blank' title='"+cmturl+"'>"+cmtname+"</a> - <span class='date'>"+cmttime+"</span> ";
}
}else{
if(cmtname=="匿名網(wǎng)友"){
if(cmturl==""){
html1="<a name='"+id+"'>"+cmtname+"</a> - <span class='date'>"+cmttime+"</span> ";
}else{
html1="<a name='"+id+"' href='"+cmturl+"' target='_blank' title='"+cmturl+"'>"+cmtname+"</a> - <span class='date'>"+cmttime+"</span>";
}
}else{
if(cmturl==""){
html1="<div class='f14' style='display:inline'>網(wǎng)友:<a name='"+id+"'>"+cmtname+"</a> - <span class=\"date\">"+cmttime+"</span></div>";
}else{
html1="<div class='f14' style='display:inline'>網(wǎng)友:<a name='"+id+"' href='"+cmturl+"' target='_blank' title='"+cmturl+"'>"+cmtname+"</a> - <span class=\"date\">"+cmttime+"</span></div>";
}
}
}
document.write(html1);
}
</SCRIPT>
<DIV id=page></DIV></DIV>
<DIV id=in_send>
<FORM name=form1 onsubmit="return checkcmtform()" action=/hl66/commit
method=post><INPUT type=hidden value=8 name=ct> <INPUT type=hidden value=1
name=cm> <INPUT type=hidden value=9aa6f103daebff88d53f7c6d name=spBlogID>
<SCRIPT language=JavaScript>
document.write("<input type='hidden' name='spRefURL' value='"+window.location.href+"'>");
</SCRIPT>
<DIV class=tit>發(fā)表評論:</DIV>
<TABLE cellSpacing=5 cellPadding=0 width=620 border=0>
<TBODY>
<TR>
<TD class=f14>姓 名:</TD>
<TD><INPUT id=spBlogCmtor style="WIDTH: 220px" maxLength=49
onchange="checkname('spBlogCmtor')" name=spBlogCmtor>
<DIV id=nmerror style="DISPLAY: none">*姓名最長為50字節(jié)</DIV></TD></TR>
<TR>
<TD class=f14>網(wǎng)址或郵箱:</TD>
<TD><INPUT id=spBlogCmtURL style="WIDTH: 360px" maxLength=128
onchange="checkeandu('spBlogCmtURL')" name=spBlogCmtURL> (選填)</TD></TR>
<TR>
<TD class=f14 vAlign=top>內(nèi) 容:</TD>
<TD><TEXTAREA id=spBlogCmtText style="WIDTH: 520px; HEIGHT: 155px" onfocus=showverkey() name=spBlogCmtText></TEXTAREA></TD></TR>
<TR id=vercode>
<TD class=f14 vAlign=top>驗(yàn)證碼:</TD>
<TD vAlign=top><INPUT type=hidden
value=9999F7FA207AA80DCFF22D46F4C057F67E288B9C5A3E495F0B86C68AA95604FDCFC2E33CCD0950F901E0812C1FA079DB697ED7EC6C683C5EB8D50F859A45E1E5
name=spVcode> <INPUT maxLength=4 size=6 name=spVerifyKey
autocomplete="off">請輸入下圖中的四位驗(yàn)證碼,字母不區(qū)分大小寫。<BR>
<SCRIPT language=JavaScript>
var imgsrc="http://post.baidu.com/cgi-bin/genimg?9999F7FA207AA80DCFF22D46F4C057F67E288B9C5A3E495F0B86C68AA95604FDCFC2E33CCD0950F901E0812C1FA079DB697ED7EC6C683C5EB8D50F859A45E1E5";
document.write("<img id='verifypic' src='"+imgsrc+"' width='120' height='40'>");
function newverifypic(){
document.getElementById("verifypic").src = imgsrc +"&t="+ Math.random();
}
</SCRIPT>
<A title=看不清左邊的字符 href="javascript:newverifypic();">看不清?</A> </TD></TR>
<TR>
<TD class=f14 vAlign=top> </TD>
<TD class=f14
vAlign=top><INPUT type=submit value=發(fā)表評論 name=btn_ok></TD></TR></TBODY></TABLE></FORM></DIV><BR></DIV>
<TABLE height=8 cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=modbl width=7> </TD>
<TD class=modbc> </TD>
<TD class=modbr width=7> </TD></TR></TBODY></TABLE></DIV></DIV></DIV></DIV>
<SCRIPT language=javascript>
<!--
var hstr="/hl66/brwstat?key1=1";
document.write("<script src='"+hstr+"&key2="+allkey+"'><\/script>");
//-->
</SCRIPT>
<BR>
<CENTER>
<DIV id=ft>©2007 Baidu</DIV></CENTER>
<SCRIPT>
if(document.getElementById("m_blog"))
{
var imgarray = document.getElementById("m_blog").getElementsByTagName('img');
var imgw = document.getElementById("m_blog").offsetWidth;
imgw =imgw-40;
for(var i=0; i<imgarray.length; i++){
if(imgarray[i].className=="blogimg" && imgarray[i].width>=imgw) imgarray[i].width=imgw;
}
}
</SCRIPT>
</CENTER><IMG style="DISPLAY: none" src=""> </BODY></HTML>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -