﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-pengkuny-随笔分类-Virual/MFC</title><link>http://www.cppblog.com/pengkuny/category/2923.html</link><description>&lt;P&gt;&lt;FONT style="FONT-SIZE: 10pt; FILTER: glow(color=black); WIDTH: 100%; COLOR: #e4dc9b; LINE-HEIGHT: 150%; FONT-FAMILY: 楷体_GB2312"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;我爱常安!我喜欢梦之旅. 常安,拥有傲人的嗓音,声线成熟动人,她的声音高入云端而又翩跹再三,可以穿透您的心灵而回味无穷,让您的耳畔回旋着那种高亢空灵的感觉,她的音质干静、技巧纯熟,擅长诠释抒情歌曲,亦能将怀旧民歌表现的淋漓尽致.&lt;/FONT&gt;&lt;/P&gt;
</description><language>zh-cn</language><lastBuildDate>Mon, 19 May 2008 15:38:00 GMT</lastBuildDate><pubDate>Mon, 19 May 2008 15:38:00 GMT</pubDate><ttl>60</ttl><item><title>MSVCR80D.dll not found</title><link>http://www.cppblog.com/pengkuny/archive/2007/03/21/20332.html</link><dc:creator>pengkuny</dc:creator><author>pengkuny</author><pubDate>Wed, 21 Mar 2007 15:23:00 GMT</pubDate><guid>http://www.cppblog.com/pengkuny/archive/2007/03/21/20332.html</guid><wfw:comment>http://www.cppblog.com/pengkuny/comments/20332.html</wfw:comment><comments>http://www.cppblog.com/pengkuny/archive/2007/03/21/20332.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/pengkuny/comments/commentRss/20332.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pengkuny/services/trackbacks/20332.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在VS 2005中建立的Win32工程总出现这样的运行错误:"MSVCR80D.dll not found"<br>好几次了,总结各种解决方法如下&nbsp;&nbsp;<a href='http://www.cppblog.com/pengkuny/archive/2007/03/21/20332.html'>阅读全文</a><img src ="http://www.cppblog.com/pengkuny/aggbug/20332.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pengkuny/" target="_blank">pengkuny</a> 2007-03-21 23:23 <a href="http://www.cppblog.com/pengkuny/archive/2007/03/21/20332.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>编译错误:constructors not allowed a return type</title><link>http://www.cppblog.com/pengkuny/archive/2007/01/09/17474.html</link><dc:creator>pengkuny</dc:creator><author>pengkuny</author><pubDate>Tue, 09 Jan 2007 15:21:00 GMT</pubDate><guid>http://www.cppblog.com/pengkuny/archive/2007/01/09/17474.html</guid><wfw:comment>http://www.cppblog.com/pengkuny/comments/17474.html</wfw:comment><comments>http://www.cppblog.com/pengkuny/archive/2007/01/09/17474.html#Feedback</comments><slash:comments>9</slash:comments><wfw:commentRss>http://www.cppblog.com/pengkuny/comments/commentRss/17474.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pengkuny/services/trackbacks/17474.html</trackback:ping><description><![CDATA[
		<p>今天用VC6编程时,出现错误:<br />error C2533: 'WumpusWorld::WumpusWorld' : constructors not allowed a return type<br />程序并没有返回值,构造函数嘛,<br />上网一查,方有一位仁兄和我同样境遇,原来是<br />头文件中类声明的时候,没有在类结尾加上";"<br /><br />这个错误提示定位也太风马牛不相及了.</p>
<img src ="http://www.cppblog.com/pengkuny/aggbug/17474.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pengkuny/" target="_blank">pengkuny</a> 2007-01-09 23:21 <a href="http://www.cppblog.com/pengkuny/archive/2007/01/09/17474.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>我的MFC学习笔记(Cont)</title><link>http://www.cppblog.com/pengkuny/archive/2006/11/15/15177.html</link><dc:creator>pengkuny</dc:creator><author>pengkuny</author><pubDate>Wed, 15 Nov 2006 05:56:00 GMT</pubDate><guid>http://www.cppblog.com/pengkuny/archive/2006/11/15/15177.html</guid><wfw:comment>http://www.cppblog.com/pengkuny/comments/15177.html</wfw:comment><comments>http://www.cppblog.com/pengkuny/archive/2006/11/15/15177.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/pengkuny/comments/commentRss/15177.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pengkuny/services/trackbacks/15177.html</trackback:ping><description><![CDATA[
		<p>
				<font face="Tahoma" size="4">作者:<a class="" title="pengkuny" href="/pengkuny" target=""><font color="#355ea0">pengkuny</font></a><br /><strong>下决心把MFC学好,<br />从暑假到现在,<br />连皮毛都没学到一点,<br />真他*丢脸.<br /><br />发现写日记的方法效果不错,<br />该记住的终于记住了<br /><br />看了仍然不懂的,用"@#$%"符号表示.<br /></strong></font>
				<br />
				<font size="4">
						<strong>错误理解必然一大堆,只能期望日后补救拉,只是希望不要错得太离谱.</strong>
				</font>
				<br />
				<br />
				<font size="5">2006.11.10</font>
				<br />
				<br />一.消息响应事件的模式,那么消息怎么起作用的?<br />   消息以调用一个窗口的窗口过程的形式来表明自己的存在.伴随4个参数:<br />消息所指窗口句柄(包含很多窗口的信息),<br />消息ID(整型值,消息类型,以WM_开头),<br />两个名为wParam和lParam的32位参数.</p>
		<p>二<a href="mailto:.@#$%">.@#$%</a><br />API函数RegisterClass注册的类为WNDCLASS<br />而"窗口类"指从MFC的CWnd派生的C++类</p>
		<p>三.匈牙利命名法:<br />b,c/ch,By,clr,(x,y),(cx,cy),w,dw,n,I,l,s,sz/str,p,fn,h,wnd,MSG,WM_,g,AFXAPI,WINAPI,SW_,WS_,MM_<br />函数名不使用下划线<br />所有的类型和常量都是大写字母，但名字中可以允许有下划线<br />所有C++的类必须以大写C为前缀，类名字的每一个子名的第一个字母都必须大写</p>
		<p>四.熟悉一些常用的AFX函数</p>
		<p>五.接触到的一些类:<br />CCmdTarget--CWinTread--CWinApp<br />Cwnd--CFrameWnd,凡是以Wnd结尾的类都是Cwnd类,框架窗口类</p>
		<p>
				<br />六.protected:对外相当于pravite,对内相当于public</p>
		<p>七.头文件AfxWin.h,里面包含所有类的声明,可以仔细看一看</p>
		<p>八.查看CWinApp的类定义<br />待查:分析CWinApp类;<br />     DECLARE_DYNAMIC;</p>
		<p> </p>
		<p>
				<font size="5">2006.11.11</font>
				<br />
				<br />一.应用程序窗口必须由InitInstance创建,故即使最小的MFC程序都必须覆盖这个虚函数.<br />   同理,CMainWnd继承自CFrameWnd,它必须有自己的构造函数,调用Create创建一个窗口.<br />   CWinApp的一个非常重要的成员函数CWnd* m_pMainWnd;它是public的,指向CWnd类</p>
		<p>二@#$%<br />protected:friend class CWinApp;WinApp是CFrameWnd的友元</p>
		<p>三.ShowWindow(m_nCmdShow);UpdateWindow();<br />   m_nCmdWindow表示窗口CWnd的显示状态,CWinApp的public成员函数,其值以SW_前缀,默认为SW_SHOWNORMAL</p>
		<p>四.从Winmain.cpp中可以看到:<br />   AfxWinMain在幕后操纵这一切的运行</p>
		<p>五.现在可以把框架窗口看作顶层窗口看待,它是应用程序与外部世界的主要接口.</p>
		<p>六.消息映射:将消息和成员函数相互关联的表.<br />BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)<br />    ON_WM_PAINT ()<br />END_MESSAGE_MAP ()</p>
		<p>CMainWindow为消息所属的类; CFrameWnd为消息所属的类的基类,因为消息可以继承.<br />使用ON_MESSAGE(WM_SETTEXT,OnSetText);创建自己的消息映射.</p>
		<p> </p>
		<p>
				<font size="5">
						<strong>2006.11.13</strong>
						<br />
				</font>
				<br />主题:在窗口中绘图</p>
		<p>一.GDI(Graphics Device Interface)图形设备接口负责图形输出.<br />   具体由设备描述表(DC)来做.</p>
		<p>二.4类设备描述表类:<br />CPaintDC<br />CClientDC<br />CWindowDC<br />CMetaFileDC</p>
		<p>二.创建一个设备描述表后,如CPaintDC dc(this);<br />就可以调用各种画图函数了,dc.Fun();<br />   6个GDI对象:跟设备描述表dc是什么关系?<br />基类:CGDIObject类<br />画笔Pen<br />画刷Brush<br />字体Font<br />位图Bitmap<br />调色板Palette<br />区域Region<br />   <br />  它们实际上刻画了设备描述表dc的属性,并不是dc的函数,<br />通过dc.SelectObject(GDI对象指针)选入设备描述表.</p>
		<p>三.回忆WM_PAINT消息是怎么产生的:<br />移动了窗口<br />原来遮掩的部分显示出来<br />窗口大小改变<br /> <br />CPaintDC类只能干这个事,只能局限于响应WM_PAINT消息,所以要选用CClientDC类</p>
		<p>四.取得全屏访问权,入屏幕截取程序,很少见<br />传递NULL指针<br />CClientDC dc(NULL);</p>
		<p>一般情况下,取this指针给构造函数即可:<br />CPaintDC dc(this);<br />CPaintDC *pDC = new CPaintDC(this);<br />this指向调用对象本身,不可改变.<br /> </p>
		<p>五.掌握设备描述表属性Attribute的常见术语<br />文本颜色 CDC::SetTextColor<br />背景颜色 CDC::SetBKColor<br />背景模式 CDC::SetBKMode<br />映射模式 CDC::SetMapMode<br />绘图模式 CDC::SetROP2<br />分别由相关函数调用,非常方便.<br />既然有Set函数,毫无疑问,就有Get函数</p>
		<p>六.比如OnPaint函数,每次调用完以后,函数内定义的设备描述表自然被销毁<br />想要保存它的状态,请使用<br />CDC::SaveDC,对应就有:<br />CDC::RestoreDC来恢复</p>
		<p>七.映射模式:<br />一个逻辑单位对应的距离,画图的时候只要告诉GDI多少单位即可,<br />实际上这些模式都扩大了本来的表示范围,使得大尺寸的东东都可以压缩比例显示<br />8种映射模式,非常简单:<br />(1)默认MM_TEXT<br />(2)公制模式:y轴反转,完全符合数学坐标,所以y值一定要用负的.<br />(3)可编程模式:不反转,但允许反转<br />   MM_ISOTROPIC  :x,y同等缩放<br />   MM_ANISOTROPIC:x,y独立缩放</p>
		<p>八.可编程模式<br />SetViewportExt<br />SetWindowExt</p>
		<p>
				<br />九.补充:堆和栈的区别<br />首先必须弄懂C/C++中内存区的分配:</p>
		<p>堆：顺序随意 </p>
		<p>栈：先进后出 </p>
		<p>一个由c/C++编译的程序占用的内存分为以下几个部分 </p>
		<p>1、栈区（stack）— 编译期间就分配好的内存空间，存放函数的参数值，局部变量的值等。其操作方式类似于数据结构中的栈。 一切管理由系统负责.</p>
		<p>2、堆区（heap） — 程序运行期间动态分配的内存空间，你可以根据程序的运行情况确定要分配的堆内存的大小.由alloca,new申请,并由free/delete释放.注意它与数据结构中的堆是两回事。 </p>
		<p>3、全局区（静态区）（static）—，全局变量和静态变量的存储是放在一块的，初始化的全局变量和静态变量在一块区域， 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 <br />static指函数调用后仍然不消失的局部变量.</p>
		<p>4、文字常量区 —常量字符串就是放在这里的。 程序结束后由系统释放 </p>
		<p>5、程序代码区—存放函数体的二进制代码。 </p>
		<p>栈：在Windows下,栈是由高地址向低地址扩展的数据结构，是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的，在 WINDOWS下，栈的大小是2M，如果申请的空间超过栈的剩余空间时，将提示overflow。<br />速度快.<br />堆：堆是由底向高地址扩展的数据结构，是不连续的内存区域。<br />容易产生碎片.</p>
		<p>
				<br />举例:<br /> CPoint ptX; 和 CPoint ptX = new CPoint();两者的区别是什么？<br />前者栈分配,后者堆分配,用完后delete.</p>
		<p>与C++不同，Java自动管理栈和堆，程序员不能直接地设置栈或堆。</p>
		<p>
				<br />十.终于他妈的明白GetClientRect的作用了:<br />CRect rect;<br />GetClientRect(&amp;rect);<br />将当前窗口的尺寸(比如非最大非最小的状态)来初始化这个矩形,<br />而不是用矩形来初始化窗口大小(难怪rect没初始化)                                                                                                            </p>
		<p>十一.<br />CRect rect;<br />GetClientRect(&amp;rect);<br />dc.SetMapMode(MM_ANISOTROPIC);                    //可编程模式<br />dc.SetWindowExt(500,600);                         //逻辑尺寸就是500*600单位<br />dc.SetViewportExt(rect.Width(),rect.Height());    //设备单位/像素:rect.Width(),rect.Height()<br />水平方向--每单位多少像素:rect.Width()/500<br />垂直方向--每单位多少像素:rect.Height()/600                                                          缩放比例就这么来.</p>
		<p>SetWindowExt(x1, y1);                      <br />SetViewportExt(x2, y2); <br />与<br />SetWindowExt(100*x1, 100*y1);                       <br />SetViewportExt(596*x2, 596*y2); <br />效果完全一样,无非是一个比例而已.</p>
		<p>在同比例缩放模式MM_ISOTROPIC下,<br />缩放比例取min{x2/x1, y2/y1}!</p>
		<p>两个范围设置函数仅仅干了一件事,设置比例,其后画图使用逻辑单位,跟它们就没有直接关系了.                                                                                                                                                                                                                                                                         <br /><br /><strong><font size="5">2006.11.15</font></strong></p>
		<p>一.这句话不明白:<br />"使用SetWindowExt和SetViewportExt时要注意：在MM_ISOTROPIC映射模式下，<br />应该首先调用SetWindowExt.否则，部分客户区可能会因落在窗口的逻辑范围之外而不能使用。<br />而在MM_ANISOTROPIC映射模式下，窗口范围和视口范围中先设置哪一个都无关紧要。"</p>
		<p>实际上,我实验发现:只要掌握放大因子k=min{x2/x1, y2/y1},和窗口真实逻辑大小(X,Y),那么画出来的图形(x,y)<br />大小就是(kx,ky),只要kx&lt;=X, ky&lt;=Y,那么就不会有客户区落在窗口的逻辑范围之外的事情发生.</p>
		<p>二.坐标转换<br />CDC::LPtoDP<br />CDC::DPtoLP</p>
		<p>三.移动原点,终于搞懂了<br />SetViewportOrg(x,y)将视口原点移至(x,y)等价于通知Windows把逻辑点(0,0)映射成设备点(x,y),<br />什么意思?就是把逻辑原点移到设备点(x,y)的位置,在这个新位置安家作为新的逻辑原点,<br />对设备坐标没有丝毫改变,所谓映射,只不过是一种简单的移动关系,并不改变设备坐标<br />同理,SetWindowOrg(x, y)将逻辑原点(x,y)移到原设备原点(0, 0)的位置</p>
		<p>述说的时候,(x, y)和(0, 0);逻辑点和设备点<br />两个"反义词"不要同时反说,否则等于没说.<br />统一说:把逻辑点(*,*)移到设备点(*,*)的位置</p>
		<p>四.两个设备坐标值:<br />用户坐标值<br />屏幕坐标值<br />互相转化;<br />CWnd::ClientToScreen<br />CWnd::ScreenToClient</p>
		<p>四.获取设备信息:<br />CDC::GetDeviceCaps</p>
		<p>五.GDI画笔CPen<br />样式PS_<br />宽度<br />颜色<br />Windows自动选用当前画笔给图形加边框,若选用PS_NULL"NULL笔",边框就没有了.</p>
		<p>扩展笔:@#$%</p>
		<p>六.GDI画刷CBrush<br />画刷用来干什么?作为dc的属性,它一旦选入,就自动填充一切画出的封闭图形<br />类型:<br />单色<br />带阴影线:6种,默认白色背景<br />带图案:填充指定的位图</p>
		<p>@#$%:<br />移动画刷原点:选入设备之前<br />brush.UnrealizeObject();<br />dc.SetBrushOrg(x0, y0);//注意,画刷原点以设备坐标值给出<br />dc.SelectObject(&amp;brush);</p>
		<p>
				<br />七.CDC文本函数:<br />@#$%<br />DrawText<br />TextOut等</p>
		<p>八.GDI字体CFont<br />一个很好用的API函数::ZeroMemory(指针,内存大小)将一块内存清零.<br />LOGFONT为字体结构,如:<br />LOGFONT lf;<br />::ZeroMemory(&amp;lf, sizeof(lf));<br />初始化lf;<br />lf.lfEscapement和lf.Orientation指定文本旋转角度的10倍值</p>
		<p>
				<br />CRect::OffsetRect(x,y)设置一个矩形坐标偏移量.</p>
		<p>光栅字体:位图保存,不适合缩放,MS Sans Serif<br />TrueType字体:任意缩放<br />Times New Roman<br />Arial<br />Courier<br />Symbol</p>
		<p>八.备用对象:一种非常好的GDI对象,系统预定义,无须显式创建,也无须删除,非常安全.<br />CDC::SelectStockObject选入DC<br />CDC::CreateStockObject赋给已有对象</p>
		<p>九.怎么删除GDI对象?<br />堆上创建的/new,需要CGDIObject::DeleteObject显式删除</p>
		<p>十.怎么取消GDI对象?<br />变相的方法:通过选入另外一个GDI对象将当前GDI对象从设备描述表中"提取"出来.<br />先保存调用SelectObject时返回的指针,<br />然后将这个指针重选默认对象,或者选入备用对象<br />来取代当前对象.</p>
		<p>实际上,@#$%</p>
		<p>十一.CString::Format:<br />与C语言的printf功能一样,支持printf所有的格式,<br />如string.(_T("d%"), i/100);<br />然后dc.TextOut即可.</p>
		<p>十二.滚动条:窗口样式参数,将来学到更高级的滚动条控件,就应该可以抛弃这种低级的方式<br />滚动条向它所属的窗口发送消息,一切响应有窗口来做,滚动条很少自己响应消息.</p>
		<p>Create的第三个参数<br />WS_VSCROLL , WS_</p>
		<p>设置:范围,位置,页面大小<br />方法一:<br />CWnd::SetScrollRange和CWnd::SetScrollPos</p>
		<p>参数TRUE意味着重不重画,小技巧</p>
		<p>方法二:CWnd::SetScrollInfo,很好用,如:<br />    SCROLLINFO si;<br />    si.fMask = SIF_PAGE | SIF_RANGE | SIF_POS;<br />    si.nMin = 0;<br />    si.nMax = nHScrollMax;<br />    si.nPos = m_nHScrollPos;<br />    si.nPage = m_nHPageSize;</p>
		<p>    SetScrollInfo (SB_HORZ, &amp;si, TRUE);</p>
		<p>
				<br />十三.滚动条滑块大小与窗口尺寸同步变化:<br />WM_SIZE消息:<br />窗口建立的时候,就有WM_SIZE的消息传来,以后只要窗口尺寸改变,就有WM_SIZE消息传来<br />用OnSize处理.<br />afx_msg void Onsize(UINT nType, int cx, int cy);轻松解决//类型+新宽度+新高度</p>
		<p>
				<br />十四.滚动条消息类型自动传递给nCode参数,位置信息pos都是自动传递给消息处理函数,不用担心<br />WM_HSCROLL,WM_VSCROLL不是具体的消息类型,SB_才是,<br />OnHScroll,OnVScroll.</p>
		<p>但是在任何事件中,更新滚动条的位置都是程序员的事情,滚动条自己不会干.</p>
		<p>小技巧:比如有时忽略"拖动滚动条"消息SB_THUMBTRACK,<br />       而只管"释放滚动条"SB_THUMBPOSITION</p>
		<p>
				<br />十五.ScrollWindow(x,y)://向右滚动x个像素,向下滚动y个像素<br />数据快速拷贝滚动滚动,空出来的地方激活OnPaint去重画<br /><br /><br /><br />待续……</p>
<img src ="http://www.cppblog.com/pengkuny/aggbug/15177.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pengkuny/" target="_blank">pengkuny</a> 2006-11-15 13:56 <a href="http://www.cppblog.com/pengkuny/archive/2006/11/15/15177.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>匈牙利命名法及其质疑</title><link>http://www.cppblog.com/pengkuny/archive/2006/11/07/14814.html</link><dc:creator>pengkuny</dc:creator><author>pengkuny</author><pubDate>Tue, 07 Nov 2006 13:32:00 GMT</pubDate><guid>http://www.cppblog.com/pengkuny/archive/2006/11/07/14814.html</guid><wfw:comment>http://www.cppblog.com/pengkuny/comments/14814.html</wfw:comment><comments>http://www.cppblog.com/pengkuny/archive/2006/11/07/14814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/pengkuny/comments/commentRss/14814.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pengkuny/services/trackbacks/14814.html</trackback:ping><description><![CDATA[
		<p>匈牙利命名法       <br /><font color="#0000ff">本人觉得匈牙利命名法确实是一件规范编程的好东东，可是苦于部分名字难记，见了好几遍也不见得认识，难道一定要全盘按照匈牙利法来命名吗？恐怕不见得。<br />文后有某君却也走了极端，全盘否定匈牙利命名法，贴出来以供参考，探讨。</font>                                    </p>
		<p>按照MS方式编程：匈牙利符号表示法  <br />匈牙利符号表示法包括许多与下列命名有关的约定：  <br />（1）变量  <br />（2）函数  <br />（3）类型和常量  <br />（4）类  <br />（5）参数  <br />匈牙利符号表示法的前缀代码指导说明书：  <br />**************************************************************************  <br />前缀                          数据类型（基本类型）  <br />C                             字符  <br />BY                            字节  <br />N                             短整数和整数（表示一个数）  <br />I                             整数  <br />X，Y                          短整数（通常用于X坐标和Y坐标）  <br />CX，CY                        短整数（通常用于表示X和Y的长度，C表示计数）  <br />B                             布尔型  <br />W                             UINT（无符号数）和WORD（无符号字）  <br />L                             LONG（长整数）  <br />DW                            DWORD（无符号长整数）  <br />FN                            函数指针  <br />S                             串  <br />SZ，STR                       以0字节终止的字符串  <br />LP                            32位长整数指针  <br />H                             编号（常用于表示Windows对象）  <br />MSG                           消息  <br />**************************************************************************  <br />变量的命名：  <br />应用匈牙利表示法，变量可用上表中的前缀代码来表示。另外，当一个变量是由一个或几个子名构成时 </p>
		<p>，每一个子名都要以大写字母开头。下  </p>
		<p>面是几个例子：  <br />char *szfileName;          // a nulla terminated string:以0终止的字符串  <br />int *lpidate;               // a 32-bit pointer to an int:指向一个整型变量的32位的长指针  <br />Bool,bSemaphore;              //a boolean value  <br />WORD dwMaxCount             // a 32-bit unsigned WORD  <br />尽管我们了解一个函数的局部变量没有说明，但是也有个别表示全局变量必须要以 g_ 开头：  <br />int g_iXPos;               // a global x-position  <br />int g_iTimer;              // a global y-position  <br />char *g_szString           //a global NULL terminated string  <br />函数的命名：  <br />函数和变量的命名方式相同，但是没有前缀，换句话说，子名的第一个字母要大写。下面是几个例子： </p>
		<p>
				<br />int PlotPixel(int ix,int iy,int ic);  <br />void *MemScan(char *szString);  <br />而且，下划线是非法的。例如，下面的函数名表示是无效的匈牙利表示法：  <br />int Get_Pixel(int ix,int iy);  <br />类型和常量的命名：  <br />所有的类型和常量都是大写字母，但名字中可以允许有下划线。如：  <br />const LONG NUM_SECTORS=100;          // a C++ style constant  <br />#define MAX_CELLS 64;                // a C style constant  <br />#define POWERUNIT 100;               // a C style constant  <br />typedef unsigned char UCHAR;         // a user defined type  <br />类的命名  <br />类命名的约定可能要麻烦一点。但我也看到有很多人在使用这个约定，并独立地进行补充。不管怎么说 </p>
		<p>，所有C++的类必须以大写C为前缀，类  </p>
		<p>名字的每一个子名的第一个字母都必须大写：  <br />class CVector         // the chinese mean of vector is 矢量  <br />{  <br />public  <br />CVector();  <br />{ix=iy=iz=imagnitude=0;}    //the chinese mean of magnitude is 大小  <br />CVector(int x, int y, int z)   <br />{ix=x;iy=y;iz=z;}  <br />......  <br />private:  <br />int ix,iy,iz;//the position of the vector  <br />int imagnitude; //the magnitude of the vector  <br />......  <br />}  <br />参数的命名  <br />函数的参数命名和标准变量命名的约定相同。但也不总是如此。如：  <br />UCHAR GetPixel(int x,int y);  <br />这种情况下，更准确的匈牙利的函数原型是：  <br />UCHAR GetPixel(int ix,int iy); </p>
		<p>
				<br />MFC、句柄、控件及结构的命名规范Windows类型 样本变量 MFC类 样本变量 <br />HWND hWnd； CWnd* pWnd； <br />HDLG hDlg； CDialog* pDlg； <br />HDC hDC； CDC* pDC； <br />HGDIOBJ hGdiObj； CGdiObject* pGdiObj； <br />HPEN hPen； CPen* pPen； <br />HBRUSH hBrush； CBrush* pBrush； <br />HFONT  hFont；  CFont* pFont； <br />HBITMAP  hBitmap； CBitmap* pBitmap； <br />HPALETTE  hPaltte； CPalette* pPalette； <br />HRGN  hRgn； CRgn* pRgn； <br />HMENU  hMenu； CMenu* pMenu； <br />HWND  hCtl； CState*  pState； <br />HWND  hCtl； CButton* pButton； <br />HWND  hCtl； CEdit* pEdit； <br />HWND  hCtl； CListBox* pListBox； <br />HWND  hCtl； CComboBox* pComboBox； <br />HWND  hCtl； CScrollBar* pScrollBar； <br />HSZ  hszStr； CString  pStr； <br />POINT  pt； CPoint  pt； <br />SIZE  size； CSize  size； <br />RECT  rect； CRect  rect； </p>
		<p>
				<br />一般前缀命名规范前缀 类型 实例 <br />C 类或结构 CDocument，CPrintInfo <br />m_ 成员变量 m_pDoc，m_nCustomers </p>
		<p> </p>
		<p>-------------------------------------------------------------------------------- </p>
		<p>变量命名规范 前缀 类型 描述 实例 <br />ch char 8位字符 chGrade <br />ch  TCHAR 如果_UNICODE定义，则为16位字符 chName <br />b BOOL 布尔值 bEnable <br />n  int 整型（其大小依赖于操作系统） nLength <br />n  UINT  无符号值（其大小依赖于操作系统） nHeight <br />w  WORD  16位无符号值 wPos <br />l  LONG  32位有符号整型 lOffset <br />dw  DWORD  32位无符号整型  dwRange <br />p  *  指针 pDoc <br />lp  FAR*  远指针  lpszName <br />lpsz  LPSTR  32位字符串指针 lpszName <br />lpsz  LPCSTR  32位常量字符串指针 lpszName <br />lpsz  LPCTSTR  如果_UNICODE定义，则为32位常量字符串指针 lpszName <br />h  handle  Windows对象句柄 hWnd <br />lpfn  callback 指向CALLBACK函数的远指针   </p>
		<p>
				<br />应用程序符号命名规范 前缀 符号类型 实例 范围 <br />IDR_  不同类型的多个资源共享标识 IDR_MAIINFRAME 1～0x6FFF <br />IDD_ 对话框资源 IDD_SPELL_CHECK  1～0x6FFF <br />HIDD_ 对话框资源的Help上下文 HIDD_SPELL_CHECK  0x20001～0x26FF <br />IDB_  位图资源 IDB_COMPANY_LOGO  1～0x6FFF <br />IDC_ 光标资源 IDC_PENCIL  1～0x6FFF <br />IDI_ 图标资源 IDI_NOTEPAD  1～0x6FFF <br />ID_ 来自菜单项或工具栏的命令 ID_TOOLS_SPELLING  0x8000～0xDFFF <br />HID_ 命令Help上下文 HID_TOOLS_SPELLING  0x18000～0x1DFFF <br />IDP_ 消息框提示 IDP_INVALID_PARTNO  8～0xDEEF <br />HIDP_ 消息框Help上下文 HIDP_INVALID_PARTNO  0x30008～0x3DEFF <br />IDS_ 串资源 IDS_COPYRIGHT  1～0x7EEF <br />IDC_ 对话框内的控件 IDC_RECALC  8～0xDEEF </p>
		<p>
				<br />Microsoft MFC宏命名规范 名称 类型 <br />_AFXDLL 唯一的动态连接库（Dynamic Link Library，DLL）版本 <br />_ALPHA 仅编译DEC Alpha处理器 <br />_DEBUG 包括诊断的调试版本 <br />_MBCS 编译多字节字符集 <br />_UNICODE 在一个应用程序中打开Unicode <br />AFXAPI  MFC提供的函数 <br />CALLBACK 通过指针回调的函数  </p>
		<p>
				<br />库标识符命名法 标识符 值和含义 <br />u  ANSI（N）或Unicode（U） <br />d  调试或发行：D = 调试；忽略标识符为发行。 </p>
		<p>
				<br />静态库版本命名规范 库 描述 <br />NAFXCWD.LIB 调试版本：MFC静态连接库 <br />NAFXCW.LIB 发行版本：MFC静态连接库 <br />UAFXCWD.LIB 调试版本：具有Unicode支持的MFC静态连接库<br /> <br />UAFXCW.LIB 发行版本：具有Unicode支持的MFC静态连接库 </p>
		<p>
				<br />动态连接库命名规范 名称 类型 <br />_AFXDLL 唯一的动态连接库（DLL）版本<br /> <br />WINAPI  Windows所提供的函数 </p>
		<p>
				<br />Windows.h中新的命名规范 类型 定义描述 <br />WINAPI 使用在API声明中的FAR PASCAL位置，如果正在编写一个具有导出API人口点的DLL<br />，则可以在自己的API中使用该类型 <br />CALLBACK 使用在应用程序回叫例程，如窗口和对话框过程中的FAR PASCAL的位置 <br />LPCSTR 与LPSTR相同，只是LPCSTR用于只读串指针，其定义类似（const char FAR*） </p>
		<p>UINT 可移植的无符号整型类型，其大小由主机环境决定（对于Windows NT和Windows 9x为<br />32位）；它是unsigned int的同义词 <br />LRESULT 窗口程序返回值的类型 <br />LPARAM 声明lParam所使用的类型，lParam是窗口程序的第四个参数 <br />WPARAM 声明wParam所使用的类型，wParam是窗口程序的第三个参数 <br />LPVOID 一般指针类型，与（void *）相同，可以用来代替LPSTR<br /> <br /></p>
		<div id="title" twffan="done">
				<h1>
						<font size="3">
								<strong>抨击匈牙利命名法</strong>
						</font>
				</h1>作者:bbao </div>
		<div id="google_ad" twffan="done">
				<script type="text/javascript">
						<!--
google_ad_client = "pub-4911831409822175";
google_alternate_color = "FFFFCC";
google_ad_width = 300;
google_ad_height = 250;
google_ad_format = "300x250_as";
google_ad_type = "text_image";
google_ad_channel ="1609457216";
google_color_border = "FFFFFF";
google_color_bg = "FFFFFF";
google_color_link = "003366";
google_color_text = "191919";
google_color_url = "333333";
//-->
				</script>
				<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
				</script>
		</div>
		<div id="Content" twffan="done">
				<p align="center">
						<strong>抨击匈牙利命名法</strong>
				</p>
				<p>匈牙利命名法是一种编程时的命名规范。命名规范是程序书写规范中最重要也是最富争议的地方，自古乃兵家必争之地。命名规范有何用？四个字：名正言顺。用二分法，命名规范分为好的命名规范和坏的命名规范，也就是说名正言顺的命名规范和名不正言不顺的命名规范。好的舞鞋是让舞者感觉不到其存在的舞鞋，坏的舞鞋是让舞者带着镣铐起舞。一个坏的命名规范具有的破坏力比一个好的命名规范具有的创造力要大得多。 </p>
				<p>本文要证明的是：匈牙利命名法是一个坏的命名规范。本文的作用范围为静态强类型编程语言。本文的分析范本为C语言和C++语言。下文中的匈法为匈牙利命名法的简称。 </p>
				<p>
						<strong>一 匈牙利命名法的成本</strong>
				</p>
				<p>匈法的表现形式为给变量名附加上类型名前缀，例如：nFoo,szFoo,pFoo,cpFoo分别表示整型变量，字符串型变量，指针型变量和常指针型变量。可以看出，匈法将变量的类型信息从单一地点（声明变量处）复制到了多个地点（使用变量处），这是冗余法。冗余法的成本之一是要维护副本的一致性。这个成本在编写和维护代码的过程中需要改变变量的类型时付出。冗余法的成本之二是占用了额外的空间。一个优秀的书写者会自觉地遵从一个法则：代码最小组织单位的长度以30个自然行以下为宜，如果超过50行就应该重新组织。一个变量的书写空间会给这一法则添加不必要的难度。 </p>
				<p>
						<strong>二 匈牙利命名法的收益</strong>
				</p>
				<p>这里要证明匈牙利命名法的收益是含糊的，无法预期的。 </p>
				<p>
						<font face="黑体">范本1：strcpy(pstrFoo,pcstrFoo2) Vs strcpy(foo,foo2)<br /></font>匈法在这里有什么收益呢？我看不到。没有一个程序员会承认自己不知道strcpy函数的参数类型吧。 </p>
				<p>
						<font face="黑体">范本2：unknown_function(nFoo) Vs unknown_function(foo)</font>
						<br />匈法在这里有什么收益呢？我看不到。对于一个不知道确定类型的函数，程序员应该去查看该函数的文档，这是一种成本。使用匈法的唯一好处是看代码的人知道这个函数要求一个整型参数，这又有什么用处呢？函数是一种接口，参数的类型仅仅是接口中的一小部分。诸如函数的功能、出口信息、线程安全性、异常安全性、参数合法性等重要信息还是必须查阅文档。 </p>
				<p>
						<font face="黑体">范本3：nFoo=nBar Vs foo=bar</font>
						<br />匈法在这里有什么收益呢？我看不到。使用匈法的唯一好处是看代码的人知道这里发生了一个整型变量的复制动作，听起来没什么问题，可以安心睡大觉了。如果他看到的是<font face="黑体">nFoo=szBar</font>，可能会从美梦中惊醒。且慢，事情真的会是这样吗？我想首先被惊醒的应该是编译器。另一方面，<font face="黑体">nFoo=nBar</font>只是在语法上合法而已，看代码的人真正关心的是语义的合法性，匈法对此毫无帮助。另一方面，一个优秀的书写者会自觉地遵从一个法则：代码最小组织单位中的临时变量以一两个为宜，如果超过三个就应该重新组织。结合前述第一个法则，可以得出这样的结论：易于理解的代码本身就应该是易于理解的，这是代码的内建高质量。好的命名规范对内建高质量的助益相当有限，而坏的命名规范对内建高质量的损害比人们想象的要大。 </p>
				<p>
						<strong>三 匈牙利命名法的实施</strong>
				</p>
				<p>这里要证明匈牙利命名法在C语言是难以实施的，在C++语言中是无法实施的。从逻辑上讲，对匈法的收益做出否定的结论以后，再来论证匈法的可行性，是画蛇添足。不过有鉴于小马哥曾让已射杀之敌死灰复燃，我还是再踏上一支脚为妙。 </p>
				<p>前面讲过，匈法是类型系统的冗余，所以实施匈法的关键是我们是否能够精确地对类型系统进行复制。这取决于类型系统的复杂性。 </p>
				<p>先来看看C语言： </p>
				<p>1.内置类型：int,char,float,double 复制为 n,ch,f,d？好像没有什么问题。不过谁来告诉我void应该怎么表示？<br />2.组合类型：array,union,enum,struct 复制为 a,u,e,s？好象比较别扭。<br />这里的难点不是为主类型取名，而是为副类型取名。an表示整型数组？sfoo,sbar表示结构foo，结构bar？ausfoo表示联合结构foo数组？累不累啊。<br />3.特殊类型：pointer。pointer在理论上应该是组合类型，但是在C语言中可以认为是内置类型，因为C语言并没有非常严格地区分不同的指针类型。下面开始表演：pausfoo表示联合结构foo数组指针？ppp表示指针的指针的指针？ </p>
				<p>噩梦还没有结束，再来看看类型系统更阿为丰富的C++语言： </p>
				<p>1.class：如果说C语言中的struct还可以用stru搪塞过去的话，不要梦想用cls来搪塞C++中的class。严格地讲，class根本就并不是一个类型，而是创造类型的工具，在C++中，语言内置类型的数量和class创造的用户自定义类型的数量相比完全可以忽略不计。stdvectorFoo表示标准库向量类型变量Foo？疯狂的念头。<br />2.命名空间：boostfilesystemiteratorFoo，表示boost空间filesystem子空间遍历目录类型变量Foo？程序员要崩溃了。<br />3.模板：你记得std::map&lt;std::string,std::string&gt;类型的确切名字吗？我是记不得了，好像超过255个字符，还是饶了我吧。<br />4.模板参数：template &lt;class T, class BinaryPredicate&gt;const T&amp; max(const T&amp; a, const T&amp; b, BinaryPredicate comp) 聪明的你，请用匈法为T命名。上帝在发笑。<br />5.类型修饰：static,extern,mutable,register,volatile,const,short,long,unsigned 噩梦加上修饰是什么？还是噩梦。 </p>
				<p>你愿意做镣铐上的舞者吗？ </p>
		</div>
<img src ="http://www.cppblog.com/pengkuny/aggbug/14814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pengkuny/" target="_blank">pengkuny</a> 2006-11-07 21:32 <a href="http://www.cppblog.com/pengkuny/archive/2006/11/07/14814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MFC中的ClassWizard的使用</title><link>http://www.cppblog.com/pengkuny/archive/2006/11/01/14516.html</link><dc:creator>pengkuny</dc:creator><author>pengkuny</author><pubDate>Wed, 01 Nov 2006 09:17:00 GMT</pubDate><guid>http://www.cppblog.com/pengkuny/archive/2006/11/01/14516.html</guid><wfw:comment>http://www.cppblog.com/pengkuny/comments/14516.html</wfw:comment><comments>http://www.cppblog.com/pengkuny/archive/2006/11/01/14516.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/pengkuny/comments/commentRss/14516.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/pengkuny/services/trackbacks/14516.html</trackback:ping><description><![CDATA[
		<p>MFC <br /> <br />前面我们利用AppWizard创建了一个应用程序框架，它除了显示一个Windows的多文档界面以外，目前还没有任何实际的用处，我们必须为它添加实际的功能。事实上，大多数Visual C++程序员都是在这个应用程序框架的基础上从事添加各种功能模块的工作，包括设计自己的类，编写具有一定功能的成员函数。<br />Visual C++的集成开发环境向用户提供了一个功能很强的操作类的工具—ClassWizard，我们可以利用该工具非常方便地向应用程序中添加类、向类中添加消息处理函数、成员函数、以及添加成员变量等。利用ClassWizard，我们再也不用手工编写那些繁琐的代码，只需使用简单的鼠标和键盘操作就能够完成大量的工作，相当于用机器制造机器。<br />一 ClassWizard简介<br />从字面上看，Class是类的意思，而Wizard则是“智者”的意思，两者合起来，ClassWizard的意思就是智能地操作类的工具。<br />在Visual C++ 6.0的集成开发环境中，ClassWizard最能体现它的特征。与AppWizard类似，ClassWizard也能自动生成程序代码，只是两者生成的对象不同，AppWizard主要用来创建应用程序的框架，而ClassWizard则主要是在应用程序框架的基础上创建和编辑各种类。<br />ClassWizard既可以操作由AppWizard在应用程序框架中创建的类，又可以操作后来由ClassWizard自己添加的类。利用ClassWizard可以很轻松地完成一些最基本、最普通的工作，如在自己的应用程序中创建新类、映射消息为其添加消息处理函数、覆盖虚拟函数、将对话框中的控件与某个变量相关联等。<br />ClassWizard只能用于使用MFC类库的应用程序中。<br />ClassWizard可以完成的主要功能如下：<br />◆ 创建新类。这是ClassWizard最基本的用途之一。创建的新类由一些主要的基类派生而来，这些基类用于处理Windows的消息，对一般用户来说，这些基类已经足够了。<br />◆ 进行消息映射。这些消息主要和窗口、菜单、工具栏、对话框、控件以及加速键相关联。<br />◆ 添加成员变量。利用ClassWizard，可以很方便地向类中添加成员变量，并将这些成员变量与对话框或窗口中的控件关联起来，当控件的值改变时，所对应的成员变量的值也跟着发生变化。<br />◆ 覆盖虚拟函数。使用ClassWizard可以方便地覆盖基类中定义的虚拟函数。<br />二 ClassWizard操作说明<br />在刚进入Visual C++ 集成开发环境时，菜单项View|ClassWizard是灰化禁止的，只有在打开一个工作区文件后，该菜单项才能正常显示，表明该选项是可用的。<br />首先打开以前创建的多文档应用程序FirstApp，再选择菜单项View|ClassWizard，即可启动ClassWizard，进入ClassWizard环境，ClassWizard是一个对话框，其中包含五个选项卡，分别为：Message Maps、Member Variables、Automation、ActiveX Events、以及Class Info。它们针对不同的对象完成不同的任务。<br />1. Message Maps选项卡<br />它是ClassWizard对话框中最重要的选项卡，主要完成创建新类、添加、删除消息处理函数等任务。<br />该选项卡中包含了两个下拉列表框：Project下拉列表框和Class name下拉列表框；三个列表框：Object IDs列表框、Message列表框和Member functions列表框；一个文本信息框；四个工具按钮。<br />★ Project下拉列表框：该下拉列表框用于选择当前操作的项目。当当前打开的工作区中包含多个项目文件时，用户可以从这个下拉列表框中选择将要操作的项目文件。对于单项目工作区来说，其默认值就是项目文件。<br />★ Class name下拉列表框：该下拉列表框用于选择当前要操作的类。当用户在Class name下拉列表框中选中了某个类之后，Object IDs窗口中的内容将会发生相应的变化。<br />★ Object IDs列表框：该列表框用于显示当前选定类中能够产生消息的对象的ID值。这些对象包括菜单选项、工具栏按钮选项、对话框以及各种控件等。<br />通常Object IDs列表框中所包含的第一个对象就是当前类名。<br />★ Message列表框：Message列表框中列出了对应于Object IDs列表框中所选中的当前项可以处理的消息以及可被重写的MFC虚函数。当Object IDs列表框中选定当前类名时，Message列表框前部分显示的是当前类所能覆盖的虚拟函数，后部分显示的是能够处理的消息。如Object IDs列表框中选定其它对象，则Message列表框显示的就是当前项可以处理的消息。<br />★ Member functions列表框：Member functions列表框中列出了在Class name下拉列表框中所选中的当前类包含的所有成员函数。其中用字母“V”标出的是MFC虚函数，用字母“W” 标出的是Windows消息处理函数。<br />★ 文本信息框：在Project下拉列表框的下方有一个文本信息框，用于显示当前选中类的源文件，包括.h文件和.cpp文件。该文本信息框中显示的内容会随着选定类的变化而变化。<br />★ Add Class按钮：该按钮用于向当前的Project中添加一个新类，新类可以是自己创建，也可以是从已有的文件中选取。<br />★ Add Function按钮：该按钮用于向当前选定类中为当前选定的消息添加一个消息处理函数。其中类是在Class name下拉列表框中选定的类；而当前消息则是在Message列表框中选定的消息。<br />Add Function按钮平时是灰化禁止的，只有当用户在Message列表框中选中某个特定的消息之后，该按钮才能正常显示，即此时才能使用。<br />★ Delete Function按钮：该按钮用于在当前选定的类中删除已有的成员函数。Delete Function按钮平时是灰化禁止的，只有当用户在Member functions列表框中选中某个消息处理函数之后，才能选择该按钮。<br />★ Edit Code按钮：单击该按钮将打开编辑窗口，并将光标位置自动跳到当前选定的成员函数的源代码处。<br />2. Member Variables选项卡<br />该选项卡主要用于添加与对话框中的控件相关联的成员变量，以便程序能利用这些成员变量与对话框中的控件进行数据交换。该选项卡与Message Maps选项卡一样，也包含Project下拉列表框和Class name下拉列表框，分别用于选定用户操作的当前项目和当前类；Add Class按钮用于向当前项目中添加一个新类；一个文本信息框，用于显示当前选中类的源文件。<br />此外，Member Variables选项卡中还包含另一个列表框以及另外四个工具按钮。列表框中共有3列数据，分别为：<br />★ Control IDs：该项显示了当前选定类中能够映射成员变量的控件的ID值。所谓能映射成员变量的控件，就是可以使用类中的成员变量来代表某个控件，当控件发生改变时，该成员变量的值也发生相应变化。<br />★ Type：该项表示成员变量的类型。<br />★ Member：该项表示成员变量的名字。<br />注意：并不是所有的类都有这些信息，只有在选择了对话框类、有格式视图类或记录视图类时才能显示出这些信息。<br />★ Add Variable按钮：该按钮用于为当前选定的控件添加一个成员变量。<br />★ Delete Variable按钮：该按钮用于删除一个现有的成员变量。该按钮平时是灰化禁止的，只有当用户在Control IDs列表框中选中某个成员变量以后，才能选择该按钮执行删除工作。<br />★ Update Columns按钮：该按钮用于选定一个数据源，只在记录集合类中才可以使用。<br />★ Bind All按钮：只适用于记录集合类，单击此按钮将把所有未绑定的记录集里的数据成员绑定到数据源的一个表中相应的列上。在默认情况下，MFC AppWizard和ClassWizard将绑定所有的列，所以很少需要使用数据绑定。如果通过删除相关的数据成员将一些或所有列取消绑定，那么在这之后还可以重新绑定它们。<br />3. Automation选项卡<br />该选项卡允许用户加入方法或属性以增强Automation功能。<br />4. ActiveX Events选项卡<br />该选项卡允许用户加入事件以支持ActiveX控件。<br />5. Class Info选项卡<br />该选项卡用于显示和设置当前选定类中的一些重要信息。</p>
		<p>三 使用ClassWizard创建新类<br />使用ClassWizard最重要的作用就是创建新类，用户将不必手工添加创建类所需的大量代码，只需指定一些关于新类的重要信息，ClassWizard将自动为你生成这些代码。<br />下面以应用程序FirstApp为例说明创建过程。步骤如下：<br />(1) 首先打开FirstApp的项目工作区。<br />(2) 点击菜单项View|ClassWizard，进入ClassWizard对话框。<br />(3) 在Message Maps选项卡中选择功能按钮Add Class，并从其下拉选项栏中单击New选项，将会打开New Class对话框。<br />(4) 首先在Name栏中键入新类的名称，如FirstButton。此时我们将看到在下面的File name栏中显示出ClassWizard自动为新类定义的默认文件名：FirstButton.cpp。如果你不想要这个名字，也可以单击Change按钮对文件名进行修改。<br />(5) 接下来应当设定新类的基类，即该类是由什么类派生而来的。在Base class下拉列表框中选中所需的基类名，如CButton。<br />(6) 如果你创建的基类需要对话框或其它资源，则应当在Dialog ID框中选择一个资源ID值。<br />(7) Automation组框用于设置类的自动化信息，这只适用于能够自动化的类，即由CCmdTarget所派生的类，我们保持其默认选择None。<br />(8) 最后单击OK按钮结束。<br />至此我们已经成功地向项目中添加了一个新类FirstButton。<br />回到Visual C++的主窗口中，我们将发现在FirstApp的项目工作区中发生了一些变化。打开ClassView选项卡，将看到一个新类FirstButton已经被添加到该项目的类列表中了。同时在FirstView选项卡中将发现FirstApp项目中新增加了两个文件：FirstButton.h，FirstButton.cpp。</p>
		<p>四 使用ClassWizard添加消息处理函数<br />使用ClassWizard来为类添加消息处理函数，用户将不需要手工编写消息映射所需的各种消息宏，这样大大减轻了工作量。<br />本节将以FirstApp应用程序为例来添加消息处理函数，处理用户在视图中的单击鼠标操作。步骤如下：<br />(1) 首先打开FirstApp的项目工作区。<br />(2) 点击菜单项View|ClassWizard，进入ClassWizard对话框。<br />(3) 选择Message Maps选项卡，在Project下拉列表框中选择项目名FirstApp，在Class name下拉列表框中选择类名CFirstAppView。<br />(4) 在Object IDs列表框中选择对象ID为CFirstAppView。<br />(5) 在Message列表框中选择需要处理的消息为WM_LBUTTONDOWN，即按下鼠标左键消息。<br />(6) 此时会发现Add Function按钮已经可用。单击此按钮，ClassWizard将选中消息的处理函数添加到Member Functions列表框中。在本例中，对应WM_LBUTTONDOWN消息的处理函数是OnLButtonDown()。<br />(7) 最后单击OK按钮结束。<br />注意：当用户为一些标准的Windows消息添加消息处理函数时，ClassWizard一般会自动地为你创建一个默认的消息处理函数名。而当用户为非标准消息添加处理函数时，ClassWizard将弹出一个对话框，并给出一个缺省的函数名，用户可以重新命名该消息响应函数。<br />在Visual C++的主窗口中打开项目工作区的ClassView选项卡，并打开CFirstAppView类的成员列表，就会发现消息处理函数OnLButtonDown()已经被添加进去了。<br />同时，通过查看文件，将会看到在CFirstAppView类的头文件FirstAppView.h中新加了消息处理函数OnLButtonDown()的声明。<br />可以看到该函数体是空的，其中只调用了一个其父类的成员函数，并且ClassView为用户生成了一些重要的注释行，以提示用户在何处添加自己的代码。<br />五 使用ClassWizard添加成员变量<br />成员变量也是类中不可或缺的组成部分，用于保存类的信息，我们将利用ClassView来为类添加成员变量。具体步骤如下：<br />(1) 首先打开FirstApp的项目工作区。<br />(2) 点击菜单项View|ClassWizard，进入ClassWizard对话框。<br />(3) 在ClassWizard对话框中选择Member Variables选项卡，在Project下拉列表框中选择当前项目名FirstApp，在Class name下拉列表框中选择当前类名CAboutDlg。此时在Controls IDs列表框中将显示该类中包含的控件ID：“IDOK”，这个ID值对应于About对话框中的OK按钮。<br />(4) 单击Add Variables按钮，将打开Add Member Variables对话框。有3个控件用来设置新成员变量的一些重要信息。<br />◆ Member variables name文本框：该文本框用来输入新成员变量的名字，在默认情况下，ClassWizard提供“m_”这个前缀以便将这个变量确认为成员变量。<br />◆ Category下拉列表框：该下拉列表框用于指定新变量是一个“Value”类型的成员变量还是一个“Control”类型的成员变量。对于标准的Windows控件来说，选择Value可以创建一个包含由用户来输入控件文本和控件状态的成员变量。而当用户选中Control选项时，就可以创建一个“Control”类型的变量，我们可以对这个控件直接进行访问。<br />◆ Variable type下拉列表框：该下拉列表框用于选择变量的数据类型。<br />(5) 在Member variables name栏中输入变量名m_ok；在Category栏中选择该变量的类型：copntrol类型；在Variable type栏中选择该变量的数据类型CButton。<br />(6) 单击OK按钮退出，这时我们可以看到，ClassWizard对话框中发生了改变。<br />打开FirstApp程序的项目工作区，可以看到，在CAboutDlg类的数据成员中，新增加了一个成员变量：m_ok。在CAboutDlg类的成员函数DoDataExchange()中，也添加了一条语句来映射控件ID值IDOK和成员变量m_ok：<br />DDX_Control(pDX, IDOK, m_ok);<br />六 使用ClassWizard覆盖虚拟函数<br />我们还可以使用ClassWizard来覆盖基类中定义的虚拟函数，方法如下：<br />(1) 打开ClassWizard对话框的Message Maps选项卡。<br />(2) 在Class name下拉列表框中选择一个类名来作为当前类。如CFirstAppView。<br />(3) 在Object Ids列表框中再次选择该类名，如CFirstAppView。此时在Message列表框中将列出所有可以覆盖的虚拟函数名和所有可操作的Windows消息。<br />(4) 在Message列表框中选择所要覆盖的虚拟函数，如OnPaint()。<br />(5) 单击Add Function按钮覆盖基类的该虚拟函数。此时在Member functions列表框中将显示虚拟函数名OnPaint()。注意在此函数前有一个“V”字母，表示该函数是一个虚拟函数。<br />(6) 单击OK按钮结束。<br />我们在头文件FirstAppView.h中可看到该虚拟函数的定义：<br />virtual void OnPaint(CDC * pDC, CPrintInfo * pInfo);<br />同时在实现函数FirstAppView.cpp中可看到该虚拟函数的函数体：<br />void CFirstAppView::OnPaint(CDC * pDC, CPrintInfo * pInfo)<br />{<br />//在此处加上专门代码或调用基类<br />CView::OnPaint(pDC, pInfo);<br />}<br /></p>
<img src ="http://www.cppblog.com/pengkuny/aggbug/14516.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/pengkuny/" target="_blank">pengkuny</a> 2006-11-01 17:17 <a href="http://www.cppblog.com/pengkuny/archive/2006/11/01/14516.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>