<?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>IT博客网-weitom1982-随笔分类-程序语言</title><link>http://www.cnitblog.com/weitom1982/category/2169.html</link><description>向各位技术前辈学习,学习再学习.</description><language>zh-cn</language><lastBuildDate>Fri, 06 Jul 2007 03:41:11 GMT</lastBuildDate><pubDate>Fri, 06 Jul 2007 03:41:11 GMT</pubDate><ttl>60</ttl><item><title>应用MFC开发高级应用程序</title><link>http://www.cnitblog.com/weitom1982/archive/2007/07/05/29520.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Thu, 05 Jul 2007 08:54:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/07/05/29520.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/29520.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/07/05/29520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/29520.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/29520.html</trackback:ping><description><![CDATA[<table cellSpacing=1 cellPadding=1 width=550 border=0>
    <tbody>
        <tr>
            <td width="100%" height=27>
            <h1 align=center>应用MFC开发高级应用程序</h1>
            <p align=center>苟建兵 清华大学热能系(北京，100084)</p>
            </td>
        </tr>
        <tr>
            <td width=543 height=33>
            <p align=center><img height=3 src="http://www.gjwtech.com/picindex/headline1.gif" width=480 border=0></p>
            </td>
        </tr>
        <tr>
            <td width="100%" height=42>
            <p align=left><br></p>
            <font color=#000000>目次：<a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#一、使用C/C++">一、使用C/C++及VC与VB之比较</a>&nbsp;&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#二、MFC编程综述">二、MFC编程综述</a>&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#三、使用单文档-多视结构">三、使用单文档-多视结构</a> </font>
            <p><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#四、使用DDE服务">四、使用DDE服务</a>&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#五、使用3D控制">五、使用3D控制</a>&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#六、使用自定义消息">六、使用自定义消息</a>&nbsp;&nbsp;</font></p>
            <p><font color=#000000>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#七、使用不带文挡-视结构的MFC应用">七、使用不带文挡-视结构的MFC应用</a>&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#八、MFC应用的人工优化">八、MFC应用的人工优化</a></font></p>
            <p align=left><font color=#000000><br>[摘要]：目前在Windows下开发应用程序的工具虽然很多，但是C/C++作为一种非常成<br>熟和高效的开发语言在大型复杂项目的开发中仍然得到了广泛应用。为了减轻程序<br>开发负担，提高开发效率，各种流行的C++都提供了类库，本文就是针对如何在<br>Visual C++环境中使用MFC类库来开发高级程序所需要解决的一些问题进行了的探<br>讨，重点讨论了利用MFC开发单文档多视应用程序和DDE应用程序的方法。</font> </p>
            <p align=left><font color=#000000><br><a name=一、使用C/C++><strong>一、使用C/C++</strong></a><br>随着Windows系列操作系统的日益普遍，传统的基于DOS编程逐渐转向Windows下编程<br>已经成为必然趋势。目前在Windows下开发应用程序的工具很多，典型的如Borland<br>C++、Visual C++、Visual Baisic以及Delphi等等。每种开发工具都各有其特点，<br>一般来讲用户可以根据自己的使用习惯和开发项目的性质来选择具体的开发语言。<br><br>Visual Basic是一个被软件界称之为划时代的革新产品，该软件改变了人们开发<br>Windows程序的方式，它采用交互式的可视化操作，使得人们开发Windows程序的每<br>一过程都有直观形象的反馈，从而加速整个开发进程。Visual Basic使得Windows程<br>序设计人员不再只依赖于复杂的SDK编程，使得开发Windows程序非常容易，可以<br>说，用户学习并使用VB来开发Windows应用的时间是最短的。Visual Basic版本几经<br>演变，目前已经发展到5.0。在4.0版本中，由于完全使用了面向对象的编程概念，<br>同时具有Windows 3.1和Windows 95下的版本，因而使得其开发复杂程序的功能逐渐<br>增强。VB5.0则抛弃了Windows 3.x的用户，只能在32位Windows中使用，据悉，该版<br>本吸收了Delphi的成功策略，引入了本地代码(Native Code)编译器，从而使得程序<br>执行速度大大加快，克服了以往版本由于执行文件采用P-Code代码而导致运行速度<br>慢的特点，根据微软的声明，该版本的采用本地代码编译后得到的应用程序在某些<br>情况下执行速度较以往提高了10~20倍，执行速度可以直逼与采用Visual C++编写的<br>应用，而应用开发速度则是VB的强项，因此Visual Basic 5.0非常具有竞争性。目<br>前Visual Basic非常广泛地用于开发各种Windows程序，如数据库前端应用程序和多<br>媒体应用等。但是，在作者看来，采用VB也有一定的缺点，原因有以下几点：<br>1. Visual Basic来源于Basic语言，虽然经过微软的不断增强，但是仍然缺乏非常<br>灵活的数据类型和编程策略，因而在开发一些项目必须的复杂数据结构遇到麻烦，<br>如链表、图和二叉树等等。由于在中大型项目开发后期，开发工作不再以界面为<br>主，而是在算法设计和底层软硬件工作，这就使VB开发项目的后期工作量大幅度增<br>加，为了达到项目要求，经常需要再转向C/C++开发一些专用的动态连接库来解决问<br>题。<br>2. Visual Basic运行速度慢，前文讲过，采用P-Code代码虽然执行文件很小，但是<br>在运行时需要解释执行，并且，它的运行必须有对应的VBRUN.DLL和所使用的VBX或<br>者OCX支持。对于浮点操作密集或者循环嵌套很多的应用来说，VB没有采取特别的优<br>化，因而执行速度远不如用C/C++和Fortran开发的应用速度快。VB 5.0虽然通过引<br>入本地代码编译器大大弥补了这个缺陷，但是由于其只能运行于32位Windows环境因<br>而在16位Windows上速度问题仍然得不到解决。虽然目前转向32位Windows的趋势非<br>常强劲，但是不容忽视由于硬件的限制或者使用习惯等诸多原因，还有许多用户仍<br>然在16位Windows上工作。在计算机十分普及的美国，96年使用16位Windows的用户<br>仍然超过了使用32位Windows的用户，任何进行系统软件设计的人员都应该照顾到这<br>些仍然使用16位Windows的用户。<br>3. VB不能灵活地使用系统资源。熟悉Windows编程的人都知道，如果要直接访问硬<br>件或者要编写对系统进行有效访问的应用程序，没有Windows API函数的帮助则非常<br>困难，但是令VB程序员失望的是，API函数是用C语言和汇编语言实现的，是为C编程<br>准备的，如果要在VB里面使用这些上千个API函数则比较麻烦，特别是，如果设计人<br>员不懂C语言则尤其困难。由于API函数的复杂性，而其本身不是为了方便VB编程而<br>提供的，因此在VB里面调用API函数需要一定的技巧，这些技巧足够用一本很厚的书<br>来表述。VB程序员可以从书店里找到好多本类似的书籍。可以说，任何一个VB程序<br>员发展到一定阶段都需要与众多的API函数打交道。另外，由于VB不支持端口操作，<br>因此，如果要编写类似数据采集等需要与硬件交互的程序则需要求救于C/C++语言。<br><br>4. Visual Basic项目分发和管理困难，其原因同上讲的，VB应用的运行不能脱离VB<br>的运行库和所使用的控件，因此，如果开发人员要将VB应用分发给用户那么一定要<br>带上VB的运行库和所使用的控件，并且要保证正确安装，这就导致即使一个非常简<br>单的应用也需要附带大量其它相关支撑库程序，对于VB 4.0及更高版本，由于大量<br>的使用了OLE控件（在VB中称为OCX），其安装更为复杂。<br>Delphi软件是国际宝兰公司(Borland)的得意之作，也是备受软件界推崇，与VB一<br>样，它完全是一个交互式的可视化开发平台，支持Client/Server应用程序的开发，<br>其最新版本2.0可以开发Windows 3.x、Windows 95和Windows NT的应用程<br>序。Delphi开发速度也非常快，与VB相比，由于具有本地代码编译器因此它产生的<br>可执行文件执行速度大大加快。Delphi软件是一个非常有竞争力的软件，采用的是<br>面向对象的Object pascal语言，支持硬件操作和API调用。但是由于采用的编程语<br>言为Pascal，这种语言并不非常流行，许多程序设计人员完全不熟悉这种语言，因<br>此极大地限制了该软件的使用，如果宝兰公司能够将Delphi软件提供的RAD开发机制<br>引入到其Borland C++中，则可能会形成一个非常成功的产品（目前该版本已经推<br>出，即C++ Builder，笔者注）。<br>VB和Delphi引入的可视化开发方法还有一个共同的缺点就是各个版本之间的兼容问<br>题。一般来讲，采用这些可视化开发工具开发的应用程序在移植到高版本时不会遇<br>到太大困难，但是一旦往相反方向移植则困难重重，有时甚至不可能。C/C++语言则<br>不具有这种局限性，各个版本之间的相互移植并不困难，高版本往低版本移植一般<br>只需重建工程文件即可大功告成。<br>综上所述，根据作者的观点，如果要开发一个大型复杂的应用程序首选的还是<br>C/C++，特别是在16位Windows下。虽然这会使前期工作增加，但是在项目的中后期<br>将逐渐会领略到其优越性和开发效率，其灵活高效的执行代码适合于对速度和应用<br>程序之间的协同性要求很高的场合。纯粹基于Windows SDK来开发Windows程序是一<br>项艰巨的工程，值得庆幸的是目前各种流行的C/C++开发工具都提供了类库开发框架<br>来简化整个开发过程而又不失其固有的灵活高效性，不同的开发语言所提供的类库<br>开发框架不同，如Borland C++提供的OWL(Object Windows Library)和 Visual C++<br>提供的MFC(Microsoft Fundmental Class)，这两种类库都封装了大量的Windows<br>API和Windows的开发元素而使得开发任务简化，两种类库各有其优点，据作者掌握<br>的资料，采用MFC编写的应用程序执行代码更小，执行速度也更快，这大概是因为该<br>软件的开发者是开发Windows操作系统的Microsoft公司的缘故吧，现在MFC正逐渐成<br>为Windows下的类库开发标准，正被越来越多的其它C/C++编译工具所支持，如<br>Watcom C++。使用MC类库同时配合Visual C++提供的AppWizard、ClassWizard和<br>AppStudio可以大幅度提高开发效率。笔者在工作中积累了一些MFC的使用经验现在<br>提出来供大家参考，希望对广大同行有所帮助，尤其是那些仍然致力于16位Windows<br>编程的程序员。本文使用的Visual C++ 1.51编译器，但是其方法同样适用于其它<br>VC++版本，包括Visual C++ 4.x。<br><a name=二、MFC编程综述>二、MFC编程综述</a><br>采用MFC开发Windows程序之所以能够大幅度提高开发速度和效率主要是因为MFC在类<br>层次封装了大量Windows SDK函数和典型Windows应用的缺省处理，这样，用户只需<br>要较少的编程就可以实现自己的开发任务。如果在MFC基础上再配合Visual C++提供<br>的AppWizard、ClassWizard和AppStudio工具那么更可以大幅度加快开发进程。MFC<br>提供大量的基类供程序员使用，常见的如CWinApp类、CFrameWnd类、CMDIFrameWnd<br>类、CMDIChildWnd类、CView类、CDC类和CDocument类等等。通过从这些基类中派生<br>出用户自己的类，然后重载特殊的几个函数就可以生成一个独立的应用程序。可以<br>说，采用MFC编写Windows应用程序是非常方便的，虽然其学习过程并不简单，但是<br>其提供的灵活高效性足以使任何Windows程序开发人员为之付出努力。如果用户不曾<br>使用过MFC，那么用户可以通过附录中所列的参考书去学习MFC的强大功能。<br>采用MFC应用框架产生的应用程序使用了标准化的结构，因而使得采用MFC编写的程<br>序的在不同平台上的移植变得非常容易，事实上，MFC的16位和32位版本之间差别很<br>小。MFC提供的标准化结构是经过众多专家分析调研后总结编写出来的，一般情况下<br>可以满足绝大多数用户的要求，但有时用户也可以通过重载一些函数来修改其缺省<br>的风格从而实现自己特有的风格，如自定义应用图表和灰色背景等。在MFC提供的文<br>档视结构中，文档、视和资源之间的联系是通过定义文档模板来实现的，如：<br>m_pSimuTemplate = new CMultiDocTemplate(<br>IDR_SIMUTYPE,<br>RUNTIME_CLASS(CSimuDoc),<br>RUNTIME_CLASS(CMyChild), // Derived MDI child frame<br>RUNTIME_CLASS(CSimuView));<br>上中第一项IDR_SIMUTYPE就包括了视口的菜单，加速键和图表等资源，如果用户使<br>用AppWizard来产生的应用基本框架，那么其也同时产生了缺省的图标，如果用户不<br>满意缺省图标（实际上用户很少满足于缺省图标），只需要将缺省图标删除，然后<br>编辑或者直接引入一个新的图标，在存储这一图标时只需要使用与被删除图标同样<br>的ID即可实现替代。<br>熟悉Windows程序开发的人都知道，在Windows上通过使用灰色背景可以增强应用程<br>序的视觉效果，曾有人戏称，灰色是图形界面永恒的颜色。使用MFC产生的应用程序<br>的背景缺省为白色，如果用户希望改变成灰色或者其它颜色，那就需要使用单独处<br>理，解决的办法很多，如在每次视口的OnPaint()事件中采用灰色刷子人为填充背<br>景，但是这不是最好的办法。笔者发现最好的办法就是采用AfxRegisterWndClass()<br>函数注册一个使用灰色背景刷的新的窗口类，这需要重载PreCreateWindow()函数来<br>实现这一点，如下程序代码片段所示：<br>BOOL CSimuView::PreCreateWindow(CREATESTRUCT&amp; cs)<br>{<br>HBRUSH hbkbrush=CreateSolidBrush(RGB(192,192,192));//创建灰色背景刷<br>LPCSTR lpMyOwnClass=AfxRegisterWndClass(CS_HREDRAW<br>|CS_VREDRAW|CS_OWNDC,0,hbkbrush);//注册新类<br>cs.lpszClass=lpMyOwnClass;//修改缺省的类风格<br>return TRUE;<br>}<br>采用这种方法速度最快，也最省力。同时，还可以在PreCreateWindow()函数定义所<br>希望的任何窗口风格，如窗口大小，光标式样等。<br><strong><a name=三、使用单文档-多视结构>三、使用单文档-多视结构</a></strong><br>如果用户使用过MFC进行编程，那么就会发现借助于AppWizard基于MFC无论编写SDI<br>(单文档界面)还是编写MDI(多文档界面)都是十分方便的。MDI应用程序目前使用越<br>来越普遍，人们熟悉的Microsoft公司的Office系列产品以及Visual系列产品都是典<br>型的多文档应用程序。这种多文档界面具有多窗口的特点，因而人们可以在一个程<br>序中使用多个子窗口来实现不同数据的浏览查看。如果用户要实现在MDI各个窗口之<br>间针对同一数据进行不同的可视化就是一件比较麻烦的事情。值得庆幸的是，MFC提<br>供的文档-视结构大大简化了这一工作。文档-视结构通过将数据从用户对数据的观<br>察中分离出来，从而方便实现多视，亦即多个视口针对同一数据，如果一个视口中<br>数据发生改变，那么其它相关视口中的内容也会随之发生改变以反映数据的变化。<br>SDI和MDI这两种Windows标准应用程序框架并不是总能满足用户的需要，就作者的工<br>作而言，就特别需要一种被称为单文档多视的应用程序，英文可以缩写为SDMV。通<br>过SDMV应用我们可以利用文档类来统一管理应用程序的所有数据，同时需要采用多<br>窗口以多种方式来可视化这些的数据，如棒图，趋势图和参数列表，从而方便用户<br>从不同角度来观察数据。MDI虽然具有多窗口的特点，但是其为多文档，即通常情况<br>下，一个视口对应一个文档，视口+文档便构成一个子窗口。在各个子窗口之间数据<br>相互独立，如果要保持数据同步更新就需要采用特殊的技术了，采用这种方式既费<br>时又费力。通过笔者的实践发现，利用MFC本身提供的多视概念通过适当改造MDI窗<br>口应用程序就可以实现上述SDMV结构。<br>所谓SDMV应用程序本质上仍然是一个MDI应用程序，只是在程序中我们人为控制使其<br>只能生成一个文档类，这个文档在第一个视口创建时创建，注意，这里并不需要限<br>制各个视口的创建先后顺序。此后与MDI窗口固有特性不同的是，所有新创建的子窗<br>口都不再创建独立文档，而是把该新视口直接连接到已有的文档对象上，这样就使<br>其成为单文档多视的结构，所有相关数据都存储在文档对象中，一旦文挡中数据发<br>生改变，通过UpdateAllViews()函数通知所有相关视口，各个视口就可以在<br>OnUpdate()中相应数据的变化。这种响应机制如下图所示:<br><br>图 1 文档-视结构数据更新机制<br>由于MDI本质上并不是为这种单文档多视机制服务的，因而在实际应用时需要解决一<br>些问题。<br>1、窗口标题问题<br>窗口标题本来不应该成为问题，缺省情况下MDI窗口通过在文档模板中提供的资源ID<br>所提供的对应字符串来确定窗口标题。但是对于SDMV应用，由于各个视口实质上是<br>对应于同一个文挡，因此每个视口都具有相同标题，只不过增加了一个数据用于指<br>示这是第几个视口。如果在各个视口中指明具体的窗口名字，那么由不同的视口启<br>动创建文档产生的窗口标题就不同，这个名字会影响到后继视口。为了作到不同类<br>型的视口如棒图视口和曲线视口具有不同的标题，这就需要一定的技术处理。根据<br>笔者的摸索发现可以采用如下步骤实现：<br>首先在从标准的MDI子窗口基类CMDIChildWnd派生一个自己的子窗口类，姑且命名为<br>CMyChild，然后在其成员变量中增加一个CString型变量用以存储当前窗口标题：<br>CString winTitle;<br>然后在不同的视口创建过程中通过获取父窗口指针按自己的意愿对上述变量进行赋<br>值，程序片段如下：<br>pChild=(CMyChild*)GetParent();<br>pChild-&gt;winTitle="棒图显示窗口";<br>最后在CMyChild派生类中重载CMDIChildWnd基类中的OnUpdateFrameTitle()函数来<br>强制实现窗口标题的个性化，这一函数在各种类库手册上和联机帮助中都没有，但<br>的确有这样一个具有保护属性的函数用来实现窗口标题的更新操作，这可以从MFC类<br>库的源代码中找到该函数的实现。重载后的源代码如下：<br>void CMyChild::OnUpdateFrameTitle(BOOL bAddToTitle)<br>{<br>// update our parent window first<br>GetMDIFrame()-&gt;OnUpdateFrameTitle(bAddToTitle);<br><br>if ((GetStyle() &amp; FWS_ADDTOTITLE) == 0)<br>return; // leave child window alone!<br><br>CDocument* pDocument = GetActiveDocument();<br>if (bAddToTitle &amp;&amp; pDocument != NULL)<br>{<br>char szOld[256];<br>GetWindowText(szOld, sizeof(szOld));<br>char szText[256];<br><br>lstrcpy(szText,winTitle); //Modified by author!<br>if (m_nWindow &gt; 0)<br>wsprintf(szText + lstrlen(szText), ":%d", m_nWindow);<br><br>// set title if changed, but don't remove completely<br>if (lstrcmp(szText, szOld) != 0)<br>SetWindowText(szText);<br>}<br>}<br>2、如何创建SDMV应用<br>如何创建SDMV应用比较麻烦，下面通过举例来具体说明。该例子假设用户需要建棒<br>图类型和曲线形式的两种视口，假设用户已经利用CView基类派生并且实现了这两个<br>类，分别对应于CMyChart和CMyTraceView两个类。<br>1) 在应用类（从CWinApp派生出来的类）的头文件中加入下列变量和函数原型说<br>明：<br>CMultiDocTemplate* m_pMyTraceTemplate;<br>CMultiDocTemplate* m_pMyChartTemplate;<br>int ExitInstance();<br>2) 在应用类的InitInstance成员函数中删除对AddDocTemplate函数的调用和<br>OpenFileNew()语句，并且加入如下代码：<br>m_pMyTraceTemplate = new CMultiDocTemplate(<br>IDR_MYTRACEVIEW,<br>RUNTIME_CLASS(CSimuDoc),<br>RUNTIME_CLASS(CMyChild), // Derived MDI child frame<br>RUNTIME_CLASS(CMyTraceView));<br><br>m_pMyChartTemplate = new CMultiDocTemplate(<br>IDR_MYCHART,<br>RUNTIME_CLASS(CSimuDoc),<br>RUNTIME_CLASS(CMyChild), // Derived MDI child frame<br>RUNTIME_CLASS(CMyChart));<br>3) 实现ExitInstance()函数，在其中删除所用的两个辅助模板：<br>int CTestApp::ExitInstance()<br>{<br>if(m_pMyChartTemplate) delete m_pMyChartTemplate;<br>if(m_pMyTraceTemplate) delete m_pMyTraceTemplate;<br>return TRUE;<br>}<br>4) 在菜单资源中去掉File菜单中的New和Open项，加入New Chart View和New<br>Trace View两项，在对应的菜单命令中实现如下：<br>void CMainFrame::OnNewMychart()<br>{<br>// TODO: Add your command handler code here<br>OnNewView(((CSimuApp*)AfxGetApp())-&gt;m_pMyChartTemplate);<br>}<br>void CMainFrame::OnNewMyTrace()<br>{<br>// TODO: Add your command handler code here<br>OnNewView(((CSimuApp*)AfxGetApp())-&gt;m_pMyTraceTemplate);<br>}<br>上中OnNewView的实现如下：<br>BOOL CMainFrame::OnNewView(CMultiDocTemplate* pDocTemplate)<br>{<br>CMDIChildWnd* pActiveChild = MDIGetActive();<br>CDocument* pDocument;<br>if (pActiveChild == NULL ||<br>(pDocument = pActiveChild-&gt;GetActiveDocument()) == NULL)<br>{<br>TRACE0("Now New the specify view\n");<br>ASSERT(pDocTemplate != NULL);<br>ASSERT(pDocTemplate-&gt;IsKindOf(RUNTIME_CLASS(CDocTemplate)));<br>pDocTemplate-&gt;OpenDocumentFile(NULL);<br>return TRUE;<br>}<br><br>// otherwise we have a new frame to the same document!<br>CMultiDocTemplate* pTemplate = pDocTemplate;<br>ASSERT_VALID(pTemplate);<br>CFrameWnd* pFrame = pTemplate-&gt;CreateNewFrame(pDocument, pActiveChild);<br>if (pFrame == NULL)<br>{<br>TRACE0("Warning: failed to create new frame\n");<br>return FALSE; // command failed<br>}<br>pTemplate-&gt;InitialUpdateFrame(pFrame, pDocument);<br>return TRUE;<br>}<br>OnNewView是整个SDMV应用的核心组成，它的任务是创建一个新的指定类型的视口，<br>它首先判断是否有活动视口存在，文档是否已经创建，正常情况下活动视口存在则<br>表明文档存在，如果不存在则利用所指定的文档模板创建一个新的活动视口，否则<br>则只创建视口，同时将其连接到已存在的文档对象上。<br>通过以上步骤就可以实现SDMV应用，在其后的具体应用中利用文档对象的<br>UpdateAllViews()函数和视口的OnUpdate()函数就可以很好的工作了。<br><a name=四、使用DDE服务><strong>四、使用DDE服务</strong></a><br>Windows 3.x是一个分时多任务操作环境，在此环境下，多个应用程序可以并发地执<br>行。为了在并发执行的多个任务之间共享数据和资源，Windows 提供了几种机制，<br>主要是通过剪贴板(Clipboard)和动态数据交换(Dynamic Data Exchange)。前者对<br>于用户需要直接参与的数据交换来说，是一个非常方便的工具，但是如果希望数据<br>交换自动进行时就必须依靠DDE技术了。编写DDE应用的技术也发展了好几代，从最<br>初的基于消息的DDE到基于DDEML(动态数据交换管理库)，再到现在流行的OLE技<br>术。DDE技术的发展使得程序开发人员编写DDE应用更为简洁。从发展趋势来看，基<br>于OLE的数据交换是最好的，它特别符合当今软件领域的客户-服务器机制<br>(Client-Server)。为适应多平台和Internet的需要，在OLE基础上微软又开发了<br>ActiveX技术。但是不容忽视的是，基于传统的DDE数据交换也自有它的应用空间，<br>使用仍然广泛。目前在Windows 3.x下，基于OLE的远程数据交换还很不成熟，但是<br>在WFW(Windows for Workgroup)下基于网络动态数据交换的技术却很成熟，目前也<br>应用非常普遍。关于DDE应用的开发和NetDDE的应用可以参看附录7。<br>1、回调函数的处理<br>由于DDEML机制需要使用回调函数，因此使用DDEML的关键是解决在MFC编程体系中回<br>调函数的使用。回调函数(Callback function)大量用于Windows的系统服务，通过<br>它，程序员可以安装设备驱动程序和消息过滤系统，以控制Windows的有效使用。<br>许多程序员都发现，利用MFC或者其它的C++应用编写回调函数是非常麻烦的，其根<br>本原因是回调函数是基于C编程的Windows SDK的技术，不是针对C++的，程序员可以<br>将一个C函数直接作为回调函数，但是如果试图直接使用C++的成员函数作为回调函<br>数将发生错误，甚至编译就不能通过。通过查询资料发现，其错误是普通的C++成员<br>函数都隐含了一个传递函数作为参数，亦即&#8220;this&#8221;指针，C++通过传递一个指向自<br>身的指针给其成员函数从而实现程序函数可以访问C++的数据成员。这也可以理解为<br>什么C++类的多个实例可以共享成员函数但是确有不同的数据成员。由于this指针的<br>作用，使得将一个CALLBACK型的成员函数作为回调函数安装时就会因为隐含的this<br>指针使得函数参数个数不匹配，从而导致回调函数安装失败。要解决这一问题的关<br>键就是不让this指针起作用，通过采用以下两种典型技术可以解决在C++中使用回调<br>函数所遇到的问题。这种方法具有通用性，适合于任何C++。<br>1. 不使用成员函数，直接使用普通C函数，为了实现在C函数中可以访问类的成员变<br>量，可以使用友元操作符(friend)，在C++中将该C函数说明为类的友元即可。这种<br>处理机制与普通的C编程中使用回调函数一样。<br>2. 使用静态成员函数，静态成员函数不使用this指针作为隐含参数，这样就可以作<br>为回调函数了。静态成员函数具有两大特点：其一，可以在没有类实例的情况下使<br>用；其二，只能访问静态成员变量和静态成员函数，不能访问非静态成员变量和非<br>静态成员函数。由于在C++中使用类成员函数作为回调函数的目的就是为了访问所有<br>的成员变量和成员函数，如果作不到这一点将不具有实际意义。解决的办法也很简<br>单，就是使用一个静态类指针作为类成员，通过在类创建时初始化该静态指针，如<br>pThis=this，然后在回调函数中通过该静态指针就可以访问所有成员变量和成员函<br>数了。这种处理办法适用于只有一个类实例的情况，因为多个类实例将共享静态类<br>成员和静态成员函数，这就导致静态指针指向最后创建的类实例。为了避免这种情<br>况，可以使用回调函数的一个参数来传递this指针，从而实现数据成员共享。这种<br>方法稍稍麻烦，这里就不再赘述。<br>2、在MFC中使用DDEML<br>对于典型的MFC应用程序，主框架窗口类(CMainFrame)只有一个实例，因此可以使用<br>静态成员函数作为回调函数，从而实现DDE机制。具体的代码片段如下：<br>(1) 在CMainFrame类中声明如下静态成员：<br>static CMainFrame* pThis;<br>static DWORD idInst;<br>static HDDEDATA CALLBACK EXPORT DdeCallback(UINT,UINT,HCONV,HSZ,HSZ, HDDEDATA,DWORD,DWORD);<br>(2) 在类的创建代码(OnCreate())中作如下说明：<br>pThis=this;<br>lpDdeCallback=MakeProcInstance((FARPROC)DdeCallback,hInstance);<br>if(DdeInitialize(&amp;idInst,(PFNCALLBACK)lpDdeCallback,CBF_FAIL_EXECUTES<br>|CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS,0L))<br>{<br>AfxMessageBox("不能初始化DDE服务","错误");<br>DestroyWindow();<br>}<br>(3) 回调函数实现如下：<br>HDDEDATA FAR PASCAL _export CMainFrame::DdeCallback(UINT iType,UINT iFmt, HCONV hConv,HSZ hsz1,HSZ hsz2,HDDEDATA hData,DWORD dwData1,DWORD dwData2)<br>{<br>char szBuffer[16];<br>int i;<br><br>switch(iType)<br>{<br>case XTYP_CONNECT: //hsz1=topiv, hsz2=service<br>return (HDDEDATA)TRUE;//TRUE;<br>case XTYP_ADVSTART: //hsz1=topic, hsz2=item<br>case XTYP_REQUEST:<br>case XTYP_ADVREQ:<br>case XTYP_POKE: //hsz1=Topic, hsz2=item, hData=data<br>case XTYP_ADVSTOP:<br>return NULL;<br>}<br>}<br>3、避免变量类型冲突<br>如果在MFC应用直接使用DDEML服务，那么该MFC应用在编译时将会遇到变量类型HSZ<br>重复定义错误。经过追踪发现，错误在于在DDEML.H对HSZ作了如下定义：<br>DECLARE_HANDLE32(HSZ);<br>而在AFXEXT.H(通过stdafx.h引入)中对HSZ又作了如下说明：<br>typedef BPSTR FAR* HSZ; // Long handle to a string<br>两个定义一个为32位整数，一个为BASIC字符串指针，当然会发生编译器不能作变量<br>类型转换的错误。实际上，将HSZ声明为BASIC字符串指针主要用于在MFC应用中使用<br>VBX控制。要改正这一错误，就必须保证不要在同一个代码模块中使用DDEML和VBX支<br>持，通过将使用DDEML和VBX的代码分开，并在使用DDEML代码的模块中最开头定义如<br>下编译器宏就可以解决上述问题：<br>#define NO_VBX_SUPPORT<br><a name=五、使用3D控制><strong>五、使用3D控制</strong></a><br>毫无疑问，3D控制的使用可以显著提高Windows应用程序的界面友好性，目前，许多<br>流行的Windows应用程序都使用了3D控制，典型的如Microsoft公司的Office系列软<br>件，而且，在Windows 95和Windows NT 4.0中，3D控制更是作为操作系统的一部分<br>直接提供，这意味着在其上运行的软件不需要作任何特殊处理，就具有3D界面效<br>果，但是，很遗憾的是，在Windows 3.x中，除了命令按钮控制使用3D控制以外，其<br>余所有的控制，如编辑框，列表框，检查框等都只使用2D控制，要想使用3D控制，<br>程序设计人员就必须在自己的程序中作一定的修改，考虑到目前3D效果的流行，这<br>点努力是值得的。<br>为了支持3D效果，Microsoft公司提供了一个专门用于3D控制的动态连接库，即<br>CTL3D.DLL，但是在其Visual C++中却没有如何使用3D控制的讨论，并且，Visual<br>C++也不直接支持3D编码，因为它不包括使用3D控制所必须的头文件。但是，这并不<br>意味着在Visual C++中不能使用3D控制，只不过用户需要从其它地方获取技术支持<br>罢了。由于使用的是动态连接库机制，因此，任何其它语言提供的3D头文件和<br>CTL3D.DLL的输入库都是可用的。作者使用的就是Borland公司的Borland C++中提供<br>的CTL3D.H和CTL3D.LIB。在C/C++中使用3D控制的方法也有很多种，在这里，为节约<br>篇幅，只讨论与本文相关的主题，即使用MFC编程时如何使用3D控制。<br>在MFC的所有对话框中使用3D控制可以遵循如下步骤：<br>1. 在CWinApp::InitInstance函数中调用Ctl3dRegister和Ctl3dAutosubclass函<br>数：<br>Ctl3dRegister(AfxGetInstanceHandle());<br>Ctl3dAutoSubclass(AfxGetInstanceHandle());<br>值得一提的是，在AppWizard产生的应用框架的CWinApp::InitInstance中有一个函<br>数调用为SetDialogBkColor，此函数的作用是将所有对话框的背景颜色设置为灰<br>色，这个功能与3D界面实现相同的功能，可以移去此语句。<br>由于CTL3D在初始化时读入所有的系统颜色并自己维持，为了使应用程序能够正确反<br>映系统颜色的变化，MFC应用程序可以在WM_SYSCOLORCHANGE消息中调用<br>Ctl3dColorChange函数。<br>2. 在MFC应用程序的CWinApp类中的ExitInstance函数中调用Ctl3dUnregister函<br>数，以方便Windows对CTL3D库的正确管理。<br>3. 在MFC应用程序的项目文件中加入CTL3D.LIB（可以用IMPORT.EXE产生）。<br>使用上述CTL3D的自动子类化的机制可以大大简化使用3D控制，如果这不满足你的要<br>求，那么你就必须单独在需要使用3D控制的对话框的OnInitDialog()中自行子类化<br>相关的控制类了，典型的如下代码片断所示：<br>BOOL CMyDialog::OnInitDialog()<br>{<br>Ctl3dSubclassDlgEx(m_hWnd,CTL3D_ALL);<br>return TRUE;<br>}<br>上面讲了在对话框中使用3D效果的办法，如果用户想在非对话框中使用3D控制，典<br>型的在FormView导出类中使用，可以在导出类的OnInitialUpdate函数中进行适当修<br>改，修改的大小取决于你是否使用了3D控制的自动子类化机制。如果使用前面提到<br>的自动子类化方法，那么仅需要在相应的OnInitialUpdate函数中调用<br>Ctl3dSubclassDlg函数了，如下代码片断所示：<br>void CMyView::OnInitialUpdate()<br>{<br>Ctl3dSubclassDlg(m_hWnd,CTL3D_ALL);<br>}<br>否则，则需要修改如下：<br>void CMyView::OnInitialUpdate()<br>{<br>Ctl3dSubclassDlgEx(m_hWnd,CTL3D_ALL);<br>}<br><a name=六、使用自定义消息><strong>六、使用自定义消息</strong></a><br>1、MFC的消息映射机制<br>Windows是一个典型的消息驱动的操作系统，程序的运行是靠对各种消息的响应来实<br>现的，这些消息的来源非常广泛，既包括Windows系统本身，如WM_CLOSE、<br>WM_PAINT、WM_CREATE和WM_TIMER等常用消息，又包括用户菜单选择、键盘加速<br>键以及工具条和对话框按钮等等，如果应用程序要与其它程序协同工作，那么消息的来<br>源还包括其它应用程序发送的消息，串行口和并行口等硬件发送的消息等等。总<br>之，Windows程序的开发是围绕着对众多消息的合理响应和实现来实现程序的各种功<br>能的。使用过C语言来开发Windows程序的人都知道，在Windows程序的窗口回调函数<br>中需要安排Switch语句来响应大量的消息，同时由于消息的间断性使得不同的消息<br>响应之间信息的传递是通过大量的全局变量或者静态数据来实现的。<br>人们常用的两种类库OWL和MFC都提供了消息映射机制用以加速开发速度，使用者只<br>需要按规定定义好对应消息的处理函数自身即可，至于实际调用由类库本身所提供<br>的机制进行，或采用虚函数，或采用消息映射宏。为了有效节约内存，MFC并不大量<br>采用虚函数机制，而是采用宏来将特定的消息映射到派生类中的响应成员函数。这<br>种机制不但适用于Windows自身的140条消息，而且适用于菜单命令消息和按钮控制<br>消息。MFC提供的消息映浠剖欠浅Ｇ看蟮模市碓诶嗟母鞲霾愦紊隙韵⒔?br&gt; 控制，而不简单的局限于消息产生者本身。在应用程序接收到窗口命令时，MFC将按<br>如下次序寻找相应的消息控制函数：<br>SDI应用<br>MDI应用<br>视口<br>视口<br>文档<br>文档<br>SDI主框架<br>MDI子框架<br>应用<br>MDI主框架<br><br>应用<br>大多数应用对每一个命令通常都只有一个特定的命令控制函数，而这个命令控制函<br>数也只属于某一特定的类，但是如果在应用中对同一消息有多个命令控制函数，那<br>么只有优先级较高的命令控制函数才会被调用。为了简化对常用命令的处理，MFC在<br>基类中提供并实现了许多消息映射的入口，如打印命令，打印预览命令，退出命令<br>以及联机帮助命令等，这样在派生类中就继承了所有的基类中的消息映射函数，从<br>而可以大大简化编程。如果我们要在自己派生类中实现对消息的控制，那么必须在<br>派生类中加上相应的控制函数和映射入口。<br>2、使用自己的消息<br>在程序设计的更深层次，人们常常会发现只依赖于菜单和命令按钮产生的消息是不<br>够的，常常因为程序运行的逻辑结构和不同视口之间数据的同步而需要使用一些自<br>定义的消息，这样通过在相应层次上安排消息响应函数就可以实现自己的特殊需<br>要。比如如果我们要在特定的时间间隔内通知所有数据输出视口重新取得新数据，<br>要依靠菜单命令和按钮命令实现不够理想，比较理想的解决办法是采用定时器事件<br>进行特定的计算操作，操作完成后再采用SendMessage发送自己的特定消息，只有当<br>这一消息得到处理后才会返回主控程序进行下一时间计算。通过在文档层次上安排<br>对消息的响应取得最新计算数据，而后通过UpdateAllViews()成员函数来通知所有<br>相关视口更新数据的显示。视口通过重载OnUpdate()成员函数就可以实现特定数据<br>的更新显示。<br>如果用户能够熟练使用SendMessage()函数和PostMessage()函数，那么要发送自定<br>义消息并不难，通常有两种选择，其一是发送WM_COMMAND消息，通过消息的WORD<br>wParam参数传递用户的命令ID，举例如下：<br>SendMessage(WM_COMMAND,IDC_GETDATA,0); //MFC主框架发送<br>然后在文档层次上安排消息映射入口：<br>ON_COMMAND(IDC_GETDATA, OnGetData)<br>同时在文档类中实现OnGetData()函数：<br>void CSimuDoc::OnGetData()<br>{<br>TRACE("Now in SimuDoc,From OnGetData\n");<br>UpdateAllViews(NULL);<br>}<br>注意在上中的消息映射入口需要用户手工加入，Visual C++提供的ClassWizard并不<br>能替用户完成这一工作。上中例子没有使用PostMessage函数而使用SendMessage函<br>数的原因是利用了SendMessage函数的特点，即它只有发送消息得到适当处理后方才<br>返回，这样有助于程序控制。<br>另一种发送自定义消息的办法是直接发送命令ID，在控制层次上采用ON_MESSAGE来<br>实现消息映射入口，注意这时的命令控制函数的原型根据Windows本身消息处理的规<br>定必须如下：<br>afx_msg LONG OnCaculationOnce(WPARAM wParam,LPARAM lParam);<br>相对来讲，这种机制不如上述机制简单，也就不再赘述。<br><a name=七、使用不带文挡-视结构的MFC应用><strong>七、使用不带文挡-视结构的MFC应用<br></strong></a>文档-视结构的功能是非常强大的，可以适合于大多数应用程序，但是有时我们只需<br>要非常简单的程序，为了减少最终可执行文件尺寸和提高运行速度，我们没有必要<br>使用文挡-视结构，典型的有简单SDI应用和基于对话框的应用。<br>1、简单SDI应用<br>此时只需要使用CWinApp和CFrameWnd两个类就完全可以了。由于CWinApp类封装了<br>WinMain函数和消息处理循环，因此任何使用MFC进行编程的程序都不能脱离开该<br>类。实际上使用CWinApp类非常简单，主要是派生一个用户自己的应用类，如<br>CMyApp，然后只需重载CWinApp类的InitInstance()函数：<br><br>BOOL CMyApp::InitInstance()<br>{<br>m_pMainWnd=new CMainFrame();<br>ASSERT(m_pMainWnd!=NULL); //error checking only<br>m_pMainWnd-&gt;ShowWindow(m_nCmdShow);<br>m_pMainWnd-&gt;UpdateWindow();<br>return TRUE;<br>}<br>至于所需要的主框架类，则可以直接使用ClassWizard实用程序生成，该类的头文件<br>与实现代码可以与CMyApp类的头文件和实现代码放在一起。注意，这里由一个技<br>巧，由于ClassWizard的使用需要有相应的CLW文件存在，而收工建代码时没有对应<br>的CLW文件，因此不能直接使用，解决办法是进入App Studio实用工具后使用<br>ClassWizard，此时系统会发觉不存在相应的CLW文件，系统将提示你重建CLW文件并<br>弹出相应对话框，这时候你不需要选择任何文件就直接选择OK按钮，这样系统将为<br>你产生一个空的CLW文件，这样就可以使用ClassWizard实用工具了。为了将CWinApp<br>和CFrameWnd的派生类有机地结合在一起，只需在CFrameWnd派生类的构造函数中进<br>行窗口创建即可。典型代码如下：<br>CMainFrame::CMainFrame()<br>{<br>Create(NULL,"DDE Client Application",WS_OVERLAPPEDWINDOW,rectDefault,<br>NULL,MAKEINTRESOURCE(IDR_MAINFRAME));<br>}<br>采用ClassWizard实用程序生成相关类代码后，所有的类的其它实现和维护就同普通<br>由AppWizard实用程序产生的代码一样了。<br>2、基于对话框的程序<br>有些主要用于数据的输入和输出等的应用在使用时没有必要改变窗口大小，典型的<br>如各种联机注册程序，这些使用对话框作为应用的主界面就足够了，而且开发此类<br>应用具有方便快捷的特点，代码也比较短小，如果直接采用各种控制类生成所需要<br>的控制就特别麻烦。在Visual C++ 4.x版本中使用AppWizard就可以直接生成基于对<br>话框的应用。在Visual 1.x中没有此功能，因此这类应用需要程序员自己实现。<br>实际上使用MFC实现基于对话框的应用非常简单，同样只使用两个MFC类作为基类，<br>这两个类为CWinApp类和CDialog类。所使用的对话框主界面同样可以先用App<br>Studio编辑对话框界面，再使用ClassWizard产生相应代码框架，然后修改CMyApp类<br>的声明，增加一个该对话框类的成员变量m_Mydlg，最后修改CMyApp类的<br>InitInstance()函数如下：<br>BOOL CMyApp::InitInstance()<br>{<br>m_Mydlg.DoModal();<br>return TRUE;<br>}<br><a name=八、MFC应用的人工优化><strong>八、MFC应用的人工优化</strong></a><br>使用C/C++编写Windows程序的优点就是灵活高效，运行速度快，Visual C++编译器<br>本身的优化工作相当出色，但这并不等于不需要进行适当的人工优化，为了提高程<br>序的运行速度，程序员可以从以下几方面努力：<br>1) 减少不必要的重复显示<br>相对来讲，Windows的GDI操作是比较慢的，因此在程序中我们应该尽可能地控制整<br>个视口的显示和更新，如果前后两此数据不发生变化，那么就不要重新进行视口的<br>GDI图形操作，尤其对于背景图显示时非万不得已时不要重绘，同时不要经常五必要<br>的刷新整个窗口。<br>2) 在视口极小化时不要进行更新屏幕操作<br>在窗口处于极小化时没有必要继续进行视口更新工作，这样可以显著提高速度。为<br>此需要在子窗口一级捕获上述信息（视口不能捕获该类信息），再在视口中进行相<br>应操作。如下代码片段所示：<br>首先在子窗口类中添加如下程序段：<br>void CMyChild::OnSysCommand(UINT nID,LPARAM lparam)<br>{<br>CMDIChildWnd::OnSysCommand(nID,lparam);<br>if(nID==SC_MINIMIZE){<br>RedrawFlag=0;<br>}<br>else<br>RedrawFlag=1;<br>}<br>再在视口更新时中修改如下：<br>void CMyChart::OnUpdate( CView* pSender, LPARAM lHint, CObject* pHint )<br>{<br>if(pChild-&gt;RedrawFlag)<br>{<br>InvalidateRect(&amp;r,FALSE);<br>TRACE("Now In CMyChart::OnUpdate\n");<br>}<br>}<br>至于上中pChild指针可以在视口创建的例程中获取：<br>pChild=(CMyChild*)GetParent();<br>3) 使用永久性的资源<br>在频繁进行GDI输出的视口中，如在监控软件中常常使用的趋势图显示和棒图显示等<br>等，应该考虑在类层次上建立频繁使用的每种画笔和刷子，这可以避免频繁的在堆<br>中创建和删除GDI对象，从而提高速度。<br>4) 使用自有设备描述句柄<br>亦即在创建视口时通过指定WM_OWNDC风格来拥有自己的显示设备句柄，这虽然会多<br>消耗一些内存，一个DC大约占800字节的内存，但是这避免了每次进行GDI操作前创<br>建并合理初始化显示设备句柄这些重复操作。特别是要自定义坐标系统和使用特殊<br>字体的视口这一点尤其重要。在16M机器日益普遍的今天为了节约一点点内存而降低<br>速度的做法并不可取。<br>5) 优化编译时指定/G3选项和/FPix87选项<br>/G3选项将强迫编译器使用386处理器的处理代码，使用嵌入式协处理器指令对那些<br>频繁进行浮点运算的程序很有帮助。采用这两种编译开关虽然提高了对用户机型的<br>要求，但在386逐渐被淘汰，486市场大幅度萎缩，586市场日益普及的今天上述问题<br>已经不再成为问题了。<br>九、结束语<br>总体上讲，使用Visual C++和MFC类库进行Windows编程是非常方便的，本文中所提<br>到的一些看法只代表本人的观点，经验也只是笔者根据近年使用MFC进行Windows编<br>程的总结，在此写出来是希望对那些使用VC和MFC进行Windows编程的同行有所帮<br>助，如有不同看法欢迎与笔者联系讨论。<br>十、参考文献：<br>[1]. David J.Kruglinski ，Visual C++技术内幕，清华大学出版社，1995<br>[2]. 郑雪明，Visual C++基础类库参考大全，学苑出版社，1994<br>[3]. B.R. Overland，Visual C++程序设计精髓，科学出版社，1995<br>[4]. Mike Klein，Windows程序员使用指南--DLL和内存管理，清华大学出版社，<br>1995<br>[5]. Richard Wilton，Microsoft Windows软件开发环境与技术， 清华大学出版<br>社，1993<br>[6]. 芶建兵，倪维斗，Windows下网络DDE的使用，电子与电脑，1997.2<br></font></p>
            <p>　</p>
            </td>
        </tr>
    </tbody>
</table>
<table height=126 cellSpacing=1 cellPadding=1 width=550 border=0>
    <tbody>
        <tr>
            <td height=21></td>
        </tr>
        <tr>
            <td vAlign=top width="100%" height=78>
            <p align=center>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://www.gjwtech.com/vcandc/vc3cvbcompare.htm#Visual C++与Delphi/C++Builder之比较">回到页顶</a>&nbsp;</p>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/weitom1982/aggbug/29520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-07-05 16:54 <a href="http://www.cnitblog.com/weitom1982/archive/2007/07/05/29520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VC编程规范-程序员们都应该这样写代码(等待删除)</title><link>http://www.cnitblog.com/weitom1982/archive/2007/07/05/29519.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Thu, 05 Jul 2007 08:53:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/07/05/29519.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/29519.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/07/05/29519.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/29519.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/29519.html</trackback:ping><description><![CDATA[<p>基本要求<br><br>1.1 程序结构清析，简单易懂，单个函数的程序行数不得超过100行。<br>1.2 打算干什么，要简单，直接了当，代码精简，避免垃圾程序。<br>1.3 尽量使用标准库函数和公共函数。<br>1.4 不要随意定义全局变量，尽量使用局部变量。<br>1.5 使用括号以避免二义性。<br><br>2.可读性要求<br>2.1 可读性第一，效率第二。<br>2.2 保持注释与代码完全一致。<br>2.3 每个源程序文件，都有文件头说明，说明规格见规范。<br>2.4 每个函数，都有函数头说明，说明规格见规范。<br>2.5 主要变量（结构、联合、类或对象）定义或引用时，注释能反映其含义。<br>2.7 常量定义（DEFINE）有相应说明。<br>2.8 处理过程的每个阶段都有相关注释说明。<br>2.9 在典型算法前都有注释。<br>2.10 利用缩进来显示程序的逻辑结构，缩进量一致并以Tab键为单位，定义Tab为 6个<br>字节。<br>2.11 循环、分支层次不要超过五层。<br>2.12 注释可以与语句在同一行，也可以在上行。<br>2.13 空行和空白字符也是一种特殊注释。<br>2.14 一目了然的语句不加注释。<br>2.15 注释的作用范围可以为：定义、引用、条件分支以及一段代码。<br>2.16 注释行数（不包括程序头和函数头说明部份）应占总行数的 1/5 到 1/3 。<br><br><br>3. 结构化要求<br><br>3.1 禁止出现两条等价的支路。<br>3.2 禁止GOTO语句。<br>3.3 用 IF 语句来强调只执行两组语句中的一组。禁止 ELSE GOTO 和 ELSE RETURN。<br>3.4 用 CASE 实现多路分支。<br>3.5 避免从循环引出多个出口。<br>3.6 函数只有一个出口。<br>3.7 不使用条件赋值语句。<br>3.8 避免不必要的分支。<br>3.9 不要轻易用条件分支去替换逻辑表达式。<br><br>4. 正确性与容错性要求<br><br>4.1 程序首先是正确，其次是优美<br>4.2 无法证明你的程序没有错误，因此在编写完一段程序后，应先回头检查。<br>4.3 改一个错误时可能产生新的错误，因此在修改前首先考虑对其它程序的影响。<br>4.4 所有变量在调用前必须被初始化。<br>4.5 对所有的用户输入，必须进行合法性检查。<br>4.6 不要比较浮点数的相等，<br>如： 10.0 * 0.1 == 1.0 ， 不可靠<br>4.7 程序与环境或状态发生关系时，必须主动去处理发生的意外事件，如文件能否<br>逻辑锁定、打印机是否联机等。<br>4.8 单元测试也是编程的一部份，提交联调测试的程序必须通过单元测试。<br><br>5. 可重用性要求<br><br>5.1 重复使用的完成相对独立功能的算法或代码应抽象为公共控件或类。<br>5.2 公共控件或类应考虑OO思想，减少外界联系，考虑独立性或封装性。<br>5.3 公共控件或类应建立使用模板。<br><br>附：C＋＋ 编程规范,delphi作相应的参考<br><br><br>.1适用范围<br><br>本标准适用于利用Visul C++ ,Borland C++进行软件程序开发的人员.。<br><br><br><br>.2变量命名<br><br>命名必须具有一定的实际意义,形式为xAbcFgh,x由变量类型确定,Abc、Fgh表示连续意<br>义字符串,如果连续意义字符串仅两个,可都大写.如OK.<br><br>具体例程:<br><br>BOOL类型 bEnable;<br><br><br><br>ch * char chText<br>c * 类对象 cMain（对象实例）<br>h * Handle（句柄） hWnd<br>i * int<br>n * 无符号整型<br>p * 指针<br>sz,str * 字符串<br>w WORD<br>x,y 坐标<br><br>Char或者TCHAR类型 与Windows API有直接联系的用szAppName[10]形式否则用<br>FileName[10]形式,单个字符也可用小写字母表示;<br><br>Int类型 nCmdShow;<br><br>LONG类型 lParam;<br><br>UINT类型 uNotify;&nbsp;<br><br><br><br>DWORD类型 dwStart;<br><br>PSTR类型 pszTip;<br><br>LPSTR类型 lpCmdLine<br><br>LPTSTR类型 lpszClassName;<br><br>LPVOID类型 lpReserved<br><br>WPARAM类型 wParam,<br><br>LPARAM类型 lParam<br><br>HWND类型 hDlg;<br><br>HDC类型 hDC;<br><br>HINSTANCE类型 hInstance<br><br>HANDLE类型 hInstance,<br><br>HICON类型 hIcon;<br><br>int iTmp<br><br>float fTmp<br><br>DWORD dw*<br><br>String , AnsiString str *<br><br>m_ 类成员变量 m_nVal, m_bFlag<br>g_ 全局变量 g_nMsg, g_bFlag<br><br>局部变量中可采用如下几个通用变量：nTemp，nResult，I，J（一般用于循环变量）。<br><br>其他资源句柄同上<br><br>.3常量命名和宏定义<br><br>常量和宏定义必须具有一定的实际意义;<br><br>常量和宏定义在#include和函数定义之间;<br><br>常量和宏定义必须全部以大写字母来撰写,中间可根据意义的连续性用下划线连接,每一<br>条定义的右侧必须有一简单的注释,说明其作用;<br><br>资源名字定义格式:<br><br>菜单:IDM_XX或者CM_XX<br><br>位图:IDB_XX<br><br>对话框:IDD_XX<br><br>字符串:IDS_XX<br><br>DLGINIT:DIALOG_XX<br><br>ICON:IDR_XX<br><br>.4函数命名<br><br>函数原型说明包括引用外来函数及内部函数，外部引用必须在右侧注明函数来源： 模<br>块名及文件名, 如是内部函数，只要注释其定义文件名;<br><br>第一个字母必须使用大写字母,要求用大小写字母组合规范函数命名,必要时可用下划线<br>间隔,示例如下：<br><br>void UpdateDB_Tfgd (TRACK_NAME); //Module Name :r01/sdw.c<br><br>void PrintTrackData (TRACK_NAME); //Module Name :r04/tern.c<br><br>void ImportantPoint (void); //Module Name :r01/sdw.c<br><br>void ShowChar (int , int , chtype); //Local Module<br><br>void ScrollUp_V (int , int); //Local Module<br><br>.5结构体命名<br><br>结构体类型命名必须全部用大写字母,原则上前面以下划线开始;结构体变量命名必须用<br>大小写字母组合，第一个字母必须使用大写字母,必要时可用下划线间隔。对于私有数<br>据区，必须注明其所属的进程。全局数据定义只需注意其用途。<br><br>示例如下：<br><br>typedef struct<br><br>{<br><br>char szProductName[20];<br><br>char szAuthor[20];<br><br><br>char szReleaseDate[16];<br><br>char szVersion[10];&nbsp;<br><br><br>unsigned long MaxTables;<br><br>unsigned long UsedTables;<br><br>}DBS_DATABASE;<br><br>DBS_DATABASE GdataBase;<br><br><br><br>6 控件的命名：<br>用小写前缀表示类别<br><br>用小写前缀表示类别：<br>fm 窗口<br>cmd 按钮<br>cob combo，下拉式列表框<br>txt 文本输入框<br>lab labal，标签<br>img image，图象<br>pic picture<br>grd Grid，网格<br>scr 滚动条<br>lst 列表框<br>frm fram<br><br><br><br>7注释<br><br>原则上注释要求使用中文;<br><br>文件开始注释内容包括:公司名称、版权、作者名称、时间、模块用途、背景介绍等,复<br>杂的算法需要加上流程说明;<br><br>函数注释包括:输入、输出、函数描述、流程处理、全局变量、调用样例等,复杂的函数<br>需要加上变量用途说明;<br><br>程序中注释包括:修改时间和作者、方便理解的注释等;<br><br><br><br><br><br>引用一: 文件开头的注释模板<br><br>/******************************************************************<br><br>** 文件名:<br><br>** Copyright (c) 1998-1999 *********公司技术开发部<br><br>** 创建人:<br><br>** 日 期:<br><br>** 修改人:<br><br>** 日 期:<br><br>** 描 述:<br><br>**<br><br>** 版 本:<br><br>**--------------------------------------------------------------------------<br>---<br><br><br><br><br><br>******************************************************************/<br><br><br><br>引用二: 函数开头的注释模板<br><br>/*****************************************************************<br><br>** 函数名:<br><br>** 输 入: a,b,c<br><br>** a---<br><br>** b---<br><br>** c---<br><br>** 输 出: x---<br><br>** x 为 1, 表示...<br><br>** x 为 0, 表示...<br><br>** 功能描述:<br><br>** 全局变量:<br><br>** 调用模块:<br><br>** 作 者:<br><br>** 日 期:<br><br>** 修 改:<br><br>** 日 期:<br><br>** 版本<br><br>****************************************************************/<br><br>引用三: 程序中的注释模板<br><br>/*----------------------------------------------------------*/<br><br>/* 注释内容 */<br><br>/*----------------------------------------------------------*/<br><br>8 程序<br><br>a. 程序编码力求简洁，结构清晰，避免太多的分支结构及太过于技巧性的程序，<br>尽量不采用递归模式。<br><br>b. 编写程序时，亦必须想好测试的方法，换句话说，&#8221;单元测试&#8221; 的测试方案应<br>在程序编写时一并拟好。<br><br>c. 注释一定要与程序一致。<br><br>d. 版本封存以后的修改一定要将老语句用/* */ 封闭，不能自行删除或修改,并要<br>在文件及函数的修改记录中加以记录。<br><br>e. 程序中每个block 的开头 &#8221;{" 及 "}&#8221; 必须对齐，嵌套的block 每进一套，<br>缩进一个tab，TAB 为4个空格,block类型包括if、for、while、do等关键字引出的。<br><br>f. 对于比较大的函数，每个block 和特殊的函数调用，都必须注明其功能，举例如下<br><br>：<br><br>count.divisor = 1193280 / freq; // compute the proper count<br><br>OutByte((unsigned short)67, (unsigned char)182); // tell 8253 that a<br>count is coming<br><br>OutByte((unsigned short)66, count. c[0]); // send low-order byte<br><br>OutByte((unsigned short)66, count. c[1]); // send high-order byte<br><br><br><br>&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;&#215;<br><br>bcb，delphi中的变量命名：<br><br>遵循匈牙利命名法，命<br>名必须有意义，制定如下规定<br><br>窗体： 以大写的W开始，如About版权窗体， 命名为WAbout<br><br>文件：以大写的F开始，如About版权窗体，文件命名为FAbout.cpp<br><br>按钮(Button)：如退出按钮，命名为btnExit<br><br>&#8230;&#8230;<br><br>基类： 加base标记，如报表基类,窗体命名为：WBaseRep, 文件命名为FBaseRep.cpp&nbsp;<br></p>
<img src ="http://www.cnitblog.com/weitom1982/aggbug/29519.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-07-05 16:53 <a href="http://www.cnitblog.com/weitom1982/archive/2007/07/05/29519.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于注册mscomm程序的编写(zt) 自己写了一点 </title><link>http://www.cnitblog.com/weitom1982/archive/2007/06/14/28452.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Thu, 14 Jun 2007 08:55:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/06/14/28452.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/28452.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/06/14/28452.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/28452.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/28452.html</trackback:ping><description><![CDATA[<div class=postText>
<p><font size=2>前一段用了mscomm控件编写程序，但是部署到新的设备上时需要手工注册控件，很是麻烦，能不能编写一个Winapi的程序自动注册呢？所以就自己写了一个程序。</font></p>
<p><font size=2>原理：如何手工来注册安装MSComm控件。 </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　 </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　　第一步：将Mscomm.srg, Mscomm32.ocx,Mscomm32.dep三个文件复制到系统文件夹中。要注意的是，MSComm控件是要授权的，所以必须将其使用&#8220;执照&#8221;Licence 在注册表中登记注册，下一步就是注册方法。至于为什么要这样做，可以看看下面的网页：</font><a href="http://support.microsoft.com/support/kb/articles/q151/7/71.asp"><font color=#000000 size=2>http://support.microsoft.com/support/kb/articles/q151/7/71.asp</font></a><font size=2> </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　　 </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　　第二步：用Windows下的注册工具regsvr32注册该OCX控件，点击&#8220;开始&#8221;-&gt;"运行"，再在中填入（假设操作安装在C盘，WIN2000）： </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Regsvr32&nbsp; </font><a href="file:///C:/winnt/system32/Mscomm32.ocx"><font color=#000000 size=2>C:\winnt\system32\Mscomm32.ocx</font></a><font size=2> </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　 </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>&nbsp;&nbsp; 　第三步：在注册表中手工新建一个主键项：先在点击&#8220;开始&#8221;-&gt;"运行"，再在中填入regedit命令打开注册表，找到HKEY_CLASSES_ROOT\Licenses，在其中添加主键<br>4250E830-6AC2-11cf-8ADB-00AA00C00905　并将内容设置为： </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　　　　　　　kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun </font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>　　　（注：这项内容也可以用记事本程序打开Mscomm.srg文件看到）</font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2></font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>这是手工注册的过程，非常繁琐。我得程序也是按照这个顺序执行的。</font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><font size=2>源代码：</font></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>// <br>#include &lt;windows.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;string.h&gt;</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>void CPFile(char file);<br>void regsted();<br>void regOCX();</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>void CPFile(char file[],char tarpath[])&nbsp;//将三个文件拷贝到系统目录<br>{<br>&nbsp;char tempsys[100];<br>&nbsp;&nbsp;&nbsp; char *r;<br>&nbsp;char *t;</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;r=tarpath;<br>&nbsp;t=tempsys;<br>&nbsp;strcpy(t,r);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;char path[256];<br>&nbsp;char *p;<br>&nbsp;char *q;<br>&nbsp;&nbsp;&nbsp; GetModuleFileName(GetModuleHandle(NULL),path,sizeof(path));<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; p = path;<br>&nbsp;while(strchr(p,'\\')) <br>&nbsp;{<br>&nbsp;&nbsp;p = strchr(p,'\\');&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p++;&nbsp; <br>&nbsp;}<br>&nbsp;&nbsp;&nbsp; *p = '\0';</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><br>&nbsp;p=strchr(path,'\0');<br>&nbsp;&nbsp;&nbsp; q=file;<br>&nbsp;strcpy(p,q);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; p=strchr(tempsys,'\0');<br>&nbsp;*p = '\\';<br>&nbsp;&nbsp;p++;</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><br>&nbsp;&nbsp;&nbsp; q=file;<br>&nbsp;strcpy(p,q);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;CopyFile(path,tempsys,FALSE);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>}</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>void regsted()&nbsp;&nbsp; //将相关信息写入注册表<br>{<br>&nbsp;HKEY hKey;<br>&nbsp;&nbsp;&nbsp; DWORD dwDip;<br>&nbsp;LPBYTE owner_Get=new BYTE[80]; <br>&nbsp;DWORD type_1=REG_SZ;<br>&nbsp;DWORD cbData_1=80; <br>&nbsp;long exist=RegQueryValueEx(HKEY_CLASSES_ROOT, "Licenses\\4250E830-6AC2-11cf-8ADB-00AA00C00905", NULL, &amp;type_1, owner_Get, &amp;cbData_1); </p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; if(exist!=ERROR_SUCCESS)<br>&nbsp;{<br>&nbsp;&nbsp; long ret =&nbsp; RegCreateKeyEx(HKEY_CLASSES_ROOT,"Licenses\\4250E830-6AC2-11cf-8ADB-00AA00C00905",0l,NULL,REG_OPTION_VOLATILE,KEY_ALL_ACCESS,NULL,&amp;hKey,&amp;dwDip);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DWORD leng=37;</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp; char key[37]="kjljvjjjoquqmjjjvpqqkqmqykypoqjquoun";<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPBYTE lpb=new BYTE(37);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;37;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lpb[i]=key[i];<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long ret2 = RegSetValueEx(hKey,NULL,NULL,REG_SZ,lpb,leng);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;}<br>}</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><br>void regOCX()//调用新进程注册组件<br>{</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; char commandline[256];<br>&nbsp;char windowsdir[256];<br>&nbsp;&nbsp;&nbsp; char lastcommandline[257];</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; PROCESS_INFORMATION pi;<br>&nbsp;&nbsp;&nbsp; STARTUPINFO si = {sizeof(si)};<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;char OCXfile[50]="<a href="file://MSCOMM32.OCX/">\\MSCOMM32.OCX</a>";<br>&nbsp;char REGfile[50]="<a href="file://regsvr32.exe/">\\regsvr32.exe</a>";<br>&nbsp;&nbsp;&nbsp; char *p,*q;<br>&nbsp;&nbsp;&nbsp; GetSystemDirectory(windowsdir, 256);<br>&nbsp;p=commandline;<br>&nbsp;q=windowsdir;<br>&nbsp;strcpy(p,q);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><br>&nbsp;p=strchr(commandline,'\0');<br>&nbsp;&nbsp;&nbsp; q=OCXfile;<br>&nbsp;strcpy(p,q);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;p=strchr(windowsdir,'\0');<br>&nbsp;&nbsp;&nbsp; q=REGfile;<br>&nbsp;strcpy(p,q);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left><br>&nbsp;p=commandline;<br>&nbsp;q=&amp;lastcommandline[1];<br>&nbsp;&nbsp;&nbsp; strcpy(q,p);<br>&nbsp;&nbsp;&nbsp; lastcommandline[0]=' ';<br>&nbsp;</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; </p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; // 启动regsvr32.exe作为子进程<br>&nbsp;&nbsp;&nbsp; BOOL ret = CreateProcess(windowsdir, lastcommandline, NULL, NULL, FALSE, 0, NULL, NULL, &amp;si, &amp;pi);<br>&nbsp;&nbsp;&nbsp; if(ret) <br>&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(pi.hThread);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; CloseHandle(pi.hProcess);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;}</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>}</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>int APIENTRY WinMain(HINSTANCE hInstance,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HINSTANCE hPrevInstance,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LPSTR&nbsp;&nbsp;&nbsp;&nbsp; lpCmdLine,<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nCmdShow )<br>{</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; char sys[100];</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; char file1[20]="Mscomm32.ocx";<br>&nbsp;char file2[20]="Mscomm32.dep";<br>&nbsp;char file3[20]="Mscomm.srg";</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;GetSystemDirectory(sys,100);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; CPFile(file1,sys);<br>&nbsp;CPFile(file2,sys);<br>&nbsp;CPFile(file3,sys);</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;&nbsp;&nbsp; regOCX();<br>&nbsp;<br>&nbsp;regsted();</p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left></p>
<p style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 3px" align=left>&nbsp;return 0;<br>}</p>
》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》<br>后记：<br><br>代码加入： include &#8220;stdafx.h&#8221;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 作者没有加入可能因为变成环境的问题。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mscomm的文件一共有4个，注册使用的应该只有ocx这一个，但为什么都要copy出来不太明白。另一个问题是active控件的源文件和使用上不太了解。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ms的文章没有时间读，我的理解可能.red文件是用来对照注册表的。<br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当使用IS等安装程序时，可以实现对控件的自动注册，并对注册表进行操作，所以这种解决方法也没有必要了。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这种方法的主要问题仍然是在注册上，导致了程序无法实现绿色安装。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;注册程序写入到主程序时需要每次做一个注册与否的判断，分开的话在操作上会给用户造成麻烦。<br><br>判断软件注册的方法一个是对照注册表。另一个是做一个global的标志来帮助判断（别的有待学习：P）前者更合理，但有点麻烦：（<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这段程序实现了对操作系统工具的直接调用，以及对系统文件的操作。&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结合操作系统，网络的知识编写出具备全面而有效功能的软件。<br></div>
<img src ="http://www.cnitblog.com/weitom1982/aggbug/28452.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-06-14 16:55 <a href="http://www.cnitblog.com/weitom1982/archive/2007/06/14/28452.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件开发设计中的容错考虑(别人写的)</title><link>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24783.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Tue, 27 Mar 2007 11:51:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24783.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/24783.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24783.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/24783.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/24783.html</trackback:ping><description><![CDATA[
		<u>
				<font color="#800080">与软件质量——与缺陷共舞</font>
		</u>
		<div class="postText">
				<div style="TEXT-ALIGN: center">
						<font size="5">
								<span style="FONT-WEIGHT: bold">浅谈人与软件质量——与缺陷共舞</span>
						</font>
						<br />
				</div>
				<br />
				<div style="TEXT-ALIGN: center">
						<font size="3">
								<span style="FONT-STYLE: italic">文/尹立群<br /><br /></span>
						</font>
				</div>
				<font size="3">长期以来，软件质量一直是一个广泛又热门的话题。这可能与软件的现状有关：不论如何努力，稍具规模的软件产品总是不能完全做到没有问题，同时各行各业都越来越离不开软件的使用。软件产生问题的原因很多，本文只从人的认知和行为特点出发，企图揭示和解释其与软件问题之间的关系，提倡在软件生产和使用中的“容错”概念，并概括地提出一些对应措施，以期对于改进软件质量和软件生产的总体优化有所裨益。<br /><br /><span style="FONT-WEIGHT: bold">软件质量的现状</span><br />为了了解软件质量的现状，从1994年开始，一个名叫 Standish Group 的智囊团用了十年的时间研究了多达三万五千个开发项目，用了多种方法对这些项目进行了评估，其对于项目成功的定义如下：<br />软件开发按时完成。<br />预算未超出。<br />软件功能涵盖了预定的要求。<br />软件没有被缺陷致残。<br />软件已被使用，而且产生了积极的效果。<br />最初的结果显示符合上述定义的成功软件项目只有16%。Standish 每年都会更新这一数字。之后的结果显示，该比例没有太大的改变。<br />多年来，软件业界采用了多种方法企图改善软件质量的现状。虽然 Standish Group 的研究指出成功软件的比例变化不大，却并不代表软件业界的努力没有成果。因为用户对于软件的要求越来越高，导致软件越来越来复杂，失败的概率也相应地越来越大。虽然一些有识之士例如 Ben Chelf 认识到人的因素对于软件产生缺陷至关重要，但是面对这一现实，多数还是朝着使人减少犯错误机会的方向去改进。这无疑是必要的。但是在短期不能奏效的局面下，在软件生产和使用中“容忍”缺陷是软件业得以生存和发展的关键一环，通俗地说，要与缺陷共舞。<br /><br /><span style="FONT-WEIGHT: bold">人的认知和行为特点与软件质量的关系</span><br />俗话说，人无完人。通过犯错误认识世界是人的认知方法之一。试探法是方法论领域中重要的一支。我大学的高等数学老师当年曾经讲过前一年的一道研究生入学数学试题，是求解微分方程。绝大多数考生都是沿着传统的思路求解，等到把一套常用的方法试过一遍以后，10分钟已经过去，还是没有解出来，不得不放弃。这一道题唯一的解法是试探法。事实上该题的形式非常简单，是以自然对数为底的方程，只要想到用试探法，一分钟之内连答案都写好了。日常生活中的例子更是比比皆是。从蹒跚学步到牙牙学语，甚至到成年人伸手取物都是通过不断犯错误、修正错误来达到想要的结果。蒙上眼睛伸手取物常常失败，原因是伸手出去的过程中犯的错误没有通过视觉来动态修正。有了人不能不犯错误的共识以后，就不难理解为什么软件不可能没有缺陷。因为作为软件生产的主体的人，其认知与行为特点必然直接影响到软件本身。<br />软件工程与其它工程领域不同的是，软件的产生过程直到现在也还是手工业工作方式或者说是手工艺品的生产方式，还远远没有实现软件工程这一学科当初想要到达的软件生产工程化、规范化、可复制化或代码重用等理想目标。当设计完成以后，程序员根据设计以及该程序员选择的编码方式实现设计。由于受到时间和人力成本的限制，程序员通常不可能穷尽所有的方法来择优。因此不同的程序员从同一个设计出发，往往是通过不同的方法实现设计的。即使是在设计这一层面，虽然会有更多的机会讨论不同的设计方案，还是不容易做很多不同的设计去比较优劣。这种局面导致完成后的软件总是会有不尽人意的地方。<br />如果再考虑到人的群体行为，问题的复杂程度就增加了很多。比如，业务过程的描述往往很难对应到技术层面。人与人沟通中的误解错位是软件产品出现问题的重要原因之一。<br />面对这一现实，软件生产人员和用户的最佳选择是承认软件不可能没有缺陷的现实，在生产和使用中都引入软件“容错”的理念和机制，并把有限的时间和精力放在“关键”部位上，而不是一味追求最少的缺陷和不分重点地使用软件开发力量，这样才能达到总体最优的结果。从九十年代开始发展起来的软件容错技术，正是对于没有无缺陷软件事实的认同。</font>
		</div>
<img src ="http://www.cnitblog.com/weitom1982/aggbug/24783.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-03-27 19:51 <a href="http://www.cnitblog.com/weitom1982/archive/2007/03/27/24783.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>原始模型模式(随便看看就好,别人写的)</title><link>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24782.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Tue, 27 Mar 2007 11:45:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24782.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/24782.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24782.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/24782.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/24782.html</trackback:ping><description><![CDATA[
		<p>
				<font size="3">        原始模型模式，我认为也可以称为克隆模式，就是由一个完整的产品对象复制出另一个对象的模式。它也是对象的创建模式，但是只与原始对象有关，不需要工厂类。</font>
		</p>
		<div>
				<font size="3">        原始模型模式最成功的应用之一就是Object类的clone方法，可能由于这种方法的存在，很多人没有意识到原始模型模式是一种特定的创建模式。但是，它的确是一种产生对象的模式，而且clone方法所实现的只是原始模型模式的一种情况。</font>
		</div>
		<div>
				<font size="3">        原始模型模式的对象创建方式有两种，可以分别称为浅复制和深复制：浅复制就是从原对象复制出新的对象时，并不复制它的成员对象，即它的成员对象句柄所指向的还是原对象中的成员对象；深复制就是在新对象中，成员对象也是新的。</font>
				<div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
						<div>
								<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
								<span style="COLOR: #0000ff">package</span>
								<span style="COLOR: #000000"> prototype;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br /><img id="_47_141_Open_Image" onclick="this.style.display='none'; document.getElementById('_47_141_Open_Text').style.display='none'; document.getElementById('_47_141_Closed_Image').style.display='inline'; document.getElementById('_47_141_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_47_141_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_47_141_Closed_Text').style.display='none'; document.getElementById('_47_141_Open_Image').style.display='inline'; document.getElementById('_47_141_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
								<span style="COLOR: #0000ff">public</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">interface</span>
								<span style="COLOR: #000000"> Prototype </span>
								<span id="_47_141_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
								<span id="_47_141_Open_Text">
										<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">void</span>
										<span style="COLOR: #000000"> printPart();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    Object flatClone();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    Object deepClone() </span>
										<span style="COLOR: #0000ff">throws</span>
										<span style="COLOR: #000000"> Exception;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
								</span>
								<span style="COLOR: #0000ff">package</span>
								<span style="COLOR: #000000"> prototype;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span>
								<span style="COLOR: #0000ff">import</span>
								<span style="COLOR: #000000"> java.io.</span>
								<span style="COLOR: #000000">*</span>
								<span style="COLOR: #000000">;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br /><img id="_250_897_Open_Image" onclick="this.style.display='none'; document.getElementById('_250_897_Open_Text').style.display='none'; document.getElementById('_250_897_Closed_Image').style.display='inline'; document.getElementById('_250_897_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_250_897_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_250_897_Closed_Text').style.display='none'; document.getElementById('_250_897_Open_Image').style.display='inline'; document.getElementById('_250_897_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
								<span style="COLOR: #0000ff">public</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">class</span>
								<span style="COLOR: #000000"> ConcretePrototype </span>
								<span style="COLOR: #0000ff">implements</span>
								<span style="COLOR: #000000"> Prototype , Serializable</span>
								<span id="_250_897_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
								<span id="_250_897_Open_Text">
										<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">private</span>
										<span style="COLOR: #000000"> Part part;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img id="_303_327_Open_Image" onclick="this.style.display='none'; document.getElementById('_303_327_Open_Text').style.display='none'; document.getElementById('_303_327_Closed_Image').style.display='inline'; document.getElementById('_303_327_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_303_327_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_303_327_Closed_Text').style.display='none'; document.getElementById('_303_327_Open_Image').style.display='inline'; document.getElementById('_303_327_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> ConcretePrototype() </span>
										<span id="_303_327_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
										<span id="_303_327_Open_Text">
												<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        part </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> Part();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img id="_356_387_Open_Image" onclick="this.style.display='none'; document.getElementById('_356_387_Open_Text').style.display='none'; document.getElementById('_356_387_Closed_Image').style.display='inline'; document.getElementById('_356_387_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_356_387_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_356_387_Closed_Text').style.display='none'; document.getElementById('_356_387_Open_Image').style.display='inline'; document.getElementById('_356_387_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">void</span>
										<span style="COLOR: #000000"> printPart() </span>
										<span id="_356_387_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
										<span id="_356_387_Open_Text">
												<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(part);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br /><img id="_419_508_Open_Image" onclick="this.style.display='none'; document.getElementById('_419_508_Open_Text').style.display='none'; document.getElementById('_419_508_Closed_Image').style.display='inline'; document.getElementById('_419_508_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_419_508_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_419_508_Closed_Text').style.display='none'; document.getElementById('_419_508_Open_Image').style.display='inline'; document.getElementById('_419_508_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> Object flatClone() </span>
										<span id="_419_508_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
										<span id="_419_508_Open_Text">
												<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        ConcretePrototype cp </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> ConcretePrototype();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        cp.part </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">this</span>
												<span style="COLOR: #000000">.part;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        </span>
												<span style="COLOR: #0000ff">return</span>
												<span style="COLOR: #000000"> cp;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img id="_557_848_Open_Image" onclick="this.style.display='none'; document.getElementById('_557_848_Open_Text').style.display='none'; document.getElementById('_557_848_Closed_Image').style.display='inline'; document.getElementById('_557_848_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_557_848_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_557_848_Closed_Text').style.display='none'; document.getElementById('_557_848_Open_Image').style.display='inline'; document.getElementById('_557_848_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> Object deepClone() </span>
										<span style="COLOR: #0000ff">throws</span>
										<span style="COLOR: #000000"> Exception </span>
										<span id="_557_848_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
										<span id="_557_848_Open_Text">
												<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        ByteArrayOutputStream bo </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> ByteArrayOutputStream();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        ObjectOutputStream oo </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> ObjectOutputStream(bo);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        oo.writeObject(</span>
												<span style="COLOR: #0000ff">this</span>
												<span style="COLOR: #000000">);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        ByteArrayInputStream bi </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> ByteArrayInputStream(bo.toByteArray());<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        ObjectInputStream oi </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> ObjectInputStream(bi);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        </span>
												<span style="COLOR: #0000ff">return</span>
												<span style="COLOR: #000000"> (oi.readObject());<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />
												<br />
												<img id="_887_893_Open_Image" onclick="this.style.display='none'; document.getElementById('_887_893_Open_Text').style.display='none'; document.getElementById('_887_893_Closed_Image').style.display='inline'; document.getElementById('_887_893_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" />
												<img id="_887_893_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_887_893_Closed_Text').style.display='none'; document.getElementById('_887_893_Open_Image').style.display='inline'; document.getElementById('_887_893_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">class</span>
										<span style="COLOR: #000000"> Part </span>
										<span style="COLOR: #0000ff">implements</span>
										<span style="COLOR: #000000"> Serializable </span>
										<span id="_887_893_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
										<span id="_887_893_Open_Text">
												<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
								</span>
								<span style="COLOR: #0000ff">package</span>
								<span style="COLOR: #000000"> prototype;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br /><img id="_941_1402_Open_Image" onclick="this.style.display='none'; document.getElementById('_941_1402_Open_Text').style.display='none'; document.getElementById('_941_1402_Closed_Image').style.display='inline'; document.getElementById('_941_1402_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_941_1402_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_941_1402_Closed_Text').style.display='none'; document.getElementById('_941_1402_Open_Image').style.display='inline'; document.getElementById('_941_1402_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span>
								<span style="COLOR: #0000ff">public</span>
								<span style="COLOR: #000000"> </span>
								<span style="COLOR: #0000ff">class</span>
								<span style="COLOR: #000000"> Client </span>
								<span id="_941_1402_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
								<span id="_941_1402_Open_Text">
										<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />    <br /><img id="_1002_1399_Open_Image" onclick="this.style.display='none'; document.getElementById('_1002_1399_Open_Text').style.display='none'; document.getElementById('_1002_1399_Closed_Image').style.display='inline'; document.getElementById('_1002_1399_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_1002_1399_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; document.getElementById('_1002_1399_Closed_Text').style.display='none'; document.getElementById('_1002_1399_Open_Image').style.display='inline'; document.getElementById('_1002_1399_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />    </span>
										<span style="COLOR: #0000ff">public</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">static</span>
										<span style="COLOR: #000000"> </span>
										<span style="COLOR: #0000ff">void</span>
										<span style="COLOR: #000000"> main(String[] args) </span>
										<span style="COLOR: #0000ff">throws</span>
										<span style="COLOR: #000000"> Exception </span>
										<span id="_1002_1399_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff">...</span>
										<span id="_1002_1399_Open_Text">
												<span style="COLOR: #000000">{<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        ConcretePrototype originate, cloned, deepCloned;<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        originate </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> </span>
												<span style="COLOR: #0000ff">new</span>
												<span style="COLOR: #000000"> ConcretePrototype();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        Thread.sleep(</span>
												<span style="COLOR: #000000">2000</span>
												<span style="COLOR: #000000">);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        cloned </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> (ConcretePrototype)originate.flatClone();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        deepCloned </span>
												<span style="COLOR: #000000">=</span>
												<span style="COLOR: #000000"> (ConcretePrototype)originate.deepClone();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(originate);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(cloned);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        System.out.println(deepCloned);<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        originate.printPart();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        cloned.printPart();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />        deepCloned.printPart();<br /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />    }</span>
										</span>
										<span style="COLOR: #000000">
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />
												<br />
												<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span>
								</span>
								<span style="COLOR: #000000">
										<br />
										<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />
								</span>
						</div>
				</div>
		</div>  
<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><font size="3">    下面是这段代码的打印：</font></span></p><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><a href="mailto:prototype.ConcretePrototype@1034bb5">prototype.ConcretePrototype@1034bb5</a><br /><a href="mailto:prototype.ConcretePrototype@19efb05">prototype.ConcretePrototype@19efb05</a><br /><a href="mailto:prototype.ConcretePrototype@723d7c">prototype.ConcretePrototype@723d7c</a><br /><a href="mailto:prototype.ConcretePrototype$Part@b162d5">prototype.ConcretePrototype$Part@b162d5</a><br /><a href="mailto:prototype.ConcretePrototype$Part@b162d5">prototype.ConcretePrototype$Part@b162d5</a><br /><a href="mailto:prototype.ConcretePrototype$Part@22c95b">prototype.ConcretePrototype$Part@22c95b</a></span></p><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt"><span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'"><font face="Times New Roman" size="3">        可以看出，打印的前三行各不相同，这说明通过浅复制和深复制，所得到的对象都是与原对象不同的；打印的后三行中有两行相同，这说明，在浅复制时，成员对象的实体没有被复制，只是复制了其句柄，而深复制时，成员对象的实体也被复制了。</font></span></p></span><img src ="http://www.cnitblog.com/weitom1982/aggbug/24782.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-03-27 19:45 <a href="http://www.cnitblog.com/weitom1982/archive/2007/03/27/24782.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>七种武器——.NET工程师求职面试必杀技(zz)</title><link>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24780.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Tue, 27 Mar 2007 11:09:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24780.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/24780.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24780.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/24780.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/24780.html</trackback:ping><description><![CDATA[七种武器——.NET工程师求职面试必杀技 <br />一、.NET框架（七种武器之孔雀翎） <br /><br />开发人员应该熟悉.NET FrameWork体系结构和基本原理，熟悉CLR（公共语言运行时）和MSIL(中间语言)，熟悉.NET框架中的委托、线程、序列化、集合、垃圾回收机制、反射等内容。 <br /><br />（世界上绝没有一种暗器能比孔雀翎更厉害，也绝没有一种武器能比孔雀翎更美丽……孔雀翎娇小的身躯中隐藏着巨大的威力…….NET框架的博大精深，正如同孔雀翎一样美丽而深不可测。） <br /><br />二、面向对象软件开发（七种武器之霸王枪） <br /><br />开发人员应该熟悉面向对象软件开发(OOP)基本概念，熟悉面向对象软件开发中的类、继承、封装、多态等概念，具备良好的面向对象软件开发思想和设计原则。 <br /><br />（霸王，力拔山兮气盖世。枪，百兵之祖是为枪……霸王枪是世上最霸道的兵器之一……正如面向对象软件开发，它大小通吃，不论是采用何种软件开发框架，还是使用不同的开发语言，面向对象软件开发在其中畅通无阻，霸气十足。） <br /><br />三、C# (七种武器之离别钩) <br /><br />开发人员应该熟练掌握C#这门面向对象编程语言，虽然.NET框架支持多种编程语言，但C#无疑是最简洁、使用者最广泛和功能最强大的一种。 <br /><br />（离别钩是一件武器，无论钩住人的任何部位，都能造成离别……但使用它的初衷却是为了能够与所爱的人相聚……C#是一门年轻的语言，它的出现，让更多的开发者爱上了C#，脱离了VB和ASP的阵营，造成离别。） <br /><br />四、ASP.NET（七种武器之碧玉刀） <br /><br />开发人员应该理解ASP.NET的页面生命周期、熟悉配置文件的格式、熟悉ASP.NET的各种服务器控件和数据控件、了解ASP.NET中的各种对象，了解ASP.NET2.0新特性。 <br /><br />（刀是最容易上手的武器，也是使用最广泛的武器……ASP.NET技术在网站开发当中的应用，正如同刀一样地使用频繁，更何况是一把华丽的碧玉刀。碧玉刀本身也是实力的象征，就如同ASP.NET在WEB开发中的位置。） <br /><br />五、数据库(七种武器之长生剑) <br /><br />开发人员需了解各种主流数据库，熟悉数据库的规范设计、精通SQL及存储过程、触发器的编写。 <br /><br />（长生剑，世上最锋利的剑，剑气威力强大而又持续不断、绵绵不息……正如同数据库一样，吸纳吞吐，化大象于无形，强力支撑着软件系统。要想在IT界获得长生，就看你数据库的功底了。） <br /><br />六、AJAX技术(JAVASCRIPT和XML)(七种武器之多情环) <br /><br />XML和JAVASCRIPT的跨平台特性，在实际软件开发中的运用越来越广泛，由于现代软件对用户界面和WEB前端的日益重视，集JAVASCRIPT和XML技术于大成的AJAX正在流行，特别是在基于WEB2.0的网站开发中。 <br /><br />（多情环是一种奇特的武器。无论套住了什么，立刻就紧紧地缠住，绝不会再脱手，就像多情的恋人一样……JAVASCRIPT和XML技术已经出现多年，此前一直不痛不痒，但由于集JAVASCRIPT和XML于大成的AJAX技术的出现及其在互联网上的不断应用，又重新焕发出生命活力，就像多情的环一样，将众多的开发者牢牢系住，在2006年红透了整个IT界，2007年AJAX技术将继续红火。） <br /><br />七、软件体系架构(拳头) <br /><br />优秀的软件离不开优秀的软件体系架构，作为开发人员，要想在IT行业更进一步，需要具备系统的、良好的软件体系架构思维，从而从更高层次决定软件的整体系统框架。 <br /><br />（拳头也是一种武器。而且是无可替代的武器。当分散的五指握成拳头，它的力量又岂仅仅是原来的五倍……优良的软件体系架构是整个软件开发体系的核心，就如同拳头一样，它是直接而致命的。但有一点，不是每个人的拳头都可以用做武器的。） <br /><br />结束语：无论多可怕的武器，也比不上人类的信心。所以人类最厉害的武器。便是自己的信心。相信你自己，做最好的自己，你就会成功！ <br /><img src ="http://www.cnitblog.com/weitom1982/aggbug/24780.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-03-27 19:09 <a href="http://www.cnitblog.com/weitom1982/archive/2007/03/27/24780.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>软件架构师</title><link>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24774.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Tue, 27 Mar 2007 07:58:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24774.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/24774.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24774.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/24774.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/24774.html</trackback:ping><description><![CDATA[很多架构师都是从好的开发人员逐步过渡而来的，但并非每个好的开发人员都希望成为架构师，而且他们并不是都适合做架构师。无论您是打算进行职业转型的开发人员，还是寻找能承担体系结构设计责任的合适人选的经理，都务必对此转型过程有个清楚的了解。本文将讨论从实现专家到架构师的过渡过程。 
<p></p><p>　　在寻找优秀的指挥的时候，您首先要找的是一名优秀的音乐演奏家。但并非每个音乐演奏家都能成为优秀的指挥。架构师的专业发展方面也与此类似。越来越多的 IT 组织开始认识到良好软件体系结构的重要性，架构师职业正迅速发展为 IT 内一个独立的门类。由于要从相当小的候选范围内招募架构师，因此这就给管理带来了一些新挑战。即使人力资源部门找到了候选者，针对经验进行的筛选也比其他门类更为严格。跨越这些障碍的最快方式是要认识到，大部分好的架构师同时也是好的开发人员，因此寻找架构师人才时可能首先应该从普通开发人员中找起。招聘人员在对候选者(内部或外部)进行详细审查时，应该考虑这个观点。不过，对此资源进行挑选可能比较麻烦，因为只有极少的优秀开发人员具有成为架构师的特征或愿望。</p><p>　　本文列出了开发人员成为架构师要进行的工作。我将从可能考虑进行此转型的开发人员和评估进行此转型的开发人员的经理这两个方面来探讨这一问题。我还将提供一系列在做出这些决策时要考虑的因素。</p><p>　　<strong>个人特征</strong></p><p>　　软件开发团队和管理层之间的联系始终是 IT 中的一个关键所在。二者都倾向于以完全不同的方式考虑给定的问题。大部分相关技术都是讨论项目经理应如何跟踪和解释开发人员的进度和问题。但沟通不足的情况仍然非常普遍，而且这是项目失败的首要原因。好的架构师是解决这个问题的最有效办法。架构师的主要责任是提供开发人员和项目经理之间的共用沟通媒体。他们负责让业务规则及需求与工程实践及限制相适应，以确保成功。以下是成功架构师的一些主要特征。</p><p>　　<strong>愿意并有能力进行沟通：</strong>在开发人员中发现架构师的最有价值标准是有效的沟通。您需要技术娴熟、经验丰富的开发人员，这样的人员需要有就项目中的业务相关问题进行沟通的经历。架构师经常必须对理解方面的差距进行预计，然后才能有所贡献。他们必须愿意克服困难来确保技术和业务观点的融合。他们并不必对意见交换工作进行计划和协调;这仍然主要是项目经理的工作。他们的任务是确定表述系统设计时的最佳工具和构件，以促进有效的意见交换。他们必须能够判断当前方法显得不足而需要采用新方法的情况。写作技能也非常重要，还需要具有制作草图的技能或使用制图软件的能力。 </p><p>　　<strong>具有处理谈判细节方面的经验：</strong>架构师经常需要负责讨论系统开发的技术折衷方案。优先级的冲突可能会带来实践限制、风险规避或可能导致在各个不同业务组之间需求不同。优秀的架构师能够有效地评估技术可能性，并能在不损失项目的主要价值的前提下制订开发计划来处理各种利害关系和限制。这与前面讨论的沟通技能紧密相关，但同时也要体现架构师的技术能力。好的架构师候选者应该是经常帮助对有争议的讨论进行引导的人，能够使讨论得出新的想法，而不会使其在一个位置停滞不前。 </p><p>　　<strong>自觉主动;积极解决设计问题：</strong>架构师的日常工作目标经常并不明确。很多开发人员直接参考功能规范来列出任务清单。架构师通常则是向这些开发人员提供所需结构的人员，以便尽可能提高工作效率。好的候选者不仅进行沟通方面的工作，而且也会预计各种设计问题并加以解决——通常在没有任何具体指示的情况下自觉进行。无论所分配的职责如何，积极参与项目的开发人员都有机会从一起工作的人员中脱颖而出。 </p><p>　　<strong>抽象思维和分析：</strong>架构师必须能够理解表述模糊的概念并将其变成相关各方能够理解的项目构件。他们必须能够理解抽象概念，并以具体的语言对其进行沟通。开发人员中好的候选者经常要求或自己主动解释开发生命周期中容易混淆的问题。他们能迅速评估各种想法并将其纳入后续工作的操作建议中。</p><p>　　开发人员经常具有很强的数学能力，而好的架构师则倾向于表现出更强的口头表达能力。管理人员经常说开发人员具有“工程意识”，而这是一个用于评估架构师的非常有意义的方面。架构师应该具有很强的解决技术问题的能力，但还必须能够准确获知更为全面的人员如何与技术交互的信息。这要求具有某种形式的抽象思维(而不再是代码的细节)，这种思维能力可能较难形成。</p><p>　　有些人认为，某种级别的正式教育是成为优秀开发人员的必备条件之一，我并不同意这种精英论。我遇到了很多高中就辍学的优秀开发人员。不过，对于体系结构设计工作，我的个人经验以及我对所需能力的认识都让我相信，好的架构师通常至少获得了一个有挑战性的学士学位。</p><p>　　<strong>跟踪生命周期</strong></p><p>　　好的架构师通常有在具备定义良好的软件开发生命周期(Software Development Life Cycle，SDLC)的组织工作的经验。架构师必须理解在其所属专业内最重要的操作过程。这并不意味着需要有其他前提，例如，并不需要高能力成熟度模型(Capability Maturity Model，CMM)级别的工作经验。好的架构师可能来自使用 SDLC 的多个小型迭代的极限编程(Extreme Programming，XP)方法的组织。务必注意各种传统软件开发操作，如 Michael A. Jackson 的方法：Jackson 结构编程(Jackson Structured Programming，JSP)和 Jackson 系统开发(Jackson System Development，JSD)。Jackson 的研究对架构师职业发展的意义就像 Donald Knuth 的研究对程序员一样重要。架构师可以偏爱任何经典的、经过时间考验的软件系统开发方法。</p><p>　　SDLC 也可以成为评估架构师合适人选的有用机制。每个 SDLC 阶段都具有能提供相关线索的特征。SDLC 包含很多小的变体，但在此部分，我将使用几乎所有方法的公共基础部分。下面的列表详细说明了 SDLC 的各个阶段，并列出了好的架构师候选者在每个阶段表现出来的特征。</p><ul><li>　　<strong>分析：</strong>在分析期间，好的架构师会考虑非技术影响，以便了解需求和将在其中进行开发的环境。架构师可为风险评估任务带来广泛的软件经验供参考。寻找具有丰富经验的开发人员，以帮助业务部门理解技术人员正确解释需求所需的信息。寻找在开发的早期阶段能够预计可能遇到的问题的开发人员。 
</li><li>　　<strong>设计：</strong>在高级设计期间，好的架构师会收集问题空间的各个抽象元素，并就其进行沟通，以便开发团队草拟将要开发的系统的相关图表。架构师负责将需求谨慎地映射到所得到的系统体系结构的功能。在详细设计期间，他们所扮演的角色并不是核心角色，但为了根据整个系统的规则对特定模块的元素进行审查，仍然需要他们。寻找善于让团队能够预计设计决策对最终系统的影响的开发人员。寻找善于确定一些最佳构件来促进与技术和非技术受众沟通设计问题的开发人员。 
</li><li>　　<strong>实现：</strong>在实现期间，架构师对项目进行引导，以确保其符合系统体系结构。他们在一线评估技术更改请求，并确定如何对设计进行调整，以最好地处理此类请求。架构师还要密切了解开发人员的进度，特别要跟踪系统中模块间的集成点的状态。寻找经常对讨论进行引导来连接多个子系统的开发人员。寻找项目经理可以依赖其快速地进行与更改和出现的问题相关的风险评估的开发人员。 
</li><li>　　<strong>测试：</strong>架构师对系统集成和用户接受度测试进行指导，并负责评估进度的正确沟通的持续测试结果。寻找理解错误模式且善于将测试复查结果转换为行动计划的开发人员。 
</li><li>　　<strong>维护：</strong>在维护期间，架构师将发起关于系统集成的讨论。无论处理 IT 基础设施问题，还是确保部门之间的技术合作，架构师都必须完全理解应用程序，必须快速学习姊妹应用程序的体系结构，而且必须就集成点和风险进行有效沟通。寻找具有系统集成经验且表现出快速掌握全貌的能力的开发人员。系统集成是一项独特的任务。 </li></ul><p>　　<strong>架构师培养建议</strong></p><p>　　有些组织能比其他组织更有效地进行架构师培养。如果充分考虑到招聘此类新专业人才的困难，努力促成能鼓励开发人员发展为架构师的环境是非常明智的策略。但务必避免对不愿意或不适合走这条路的开发人员进行处罚。组织应该为开发人员制订多条发展路线，包括那些愿意继续担任开发人员的人。对架构师而言，资深开发人员不可或缺。他们可以实现系统中最关键的模块。通过对其他开发人员进行代码检查和测试支持，他们可帮助确保总体软件质量，而如果质量不能保证，即使最好的体系结构也毫无用处。</p><p>　　组织应制订个人评估程序，以鼓励开发人员考虑其职业目标，其中要包含体系结构设计的选项。应该鼓励经理在其下属中寻找体系结构设计人才。应该实现指导计划，让架构师与希望成为架构师的开发人员协作工作。应该鼓励开发人员通过参加各种协会、撰写文章和参加会议，从而参与到专业领域中来。通过这样参与进来，可帮助开发人员从新的角度理解系统，并帮助他们更好地就其认识进行沟通。这样还能培养可提高效率的重要创新想法。</p><p>　　<strong>结束语</strong></p><p>　　开发人员一旦迈出了通向体系结构设计专业方向的第一步，就可以利用很多资源来获得帮助，其中包括很多来自 IBM 的资源。有时候，此过程的最困难的部分就是第一步，而本文提供了一些线索和提示，经理和开发人员可以利用其来评估应该鼓励哪些人努力成为架构师。</p><img src ="http://www.cnitblog.com/weitom1982/aggbug/24774.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/weitom1982/" target="_blank">高山流水</a> 2007-03-27 15:58 <a href="http://www.cnitblog.com/weitom1982/archive/2007/03/27/24774.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java面试题(转自CSDN)</title><link>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24772.html</link><dc:creator>高山流水</dc:creator><author>高山流水</author><pubDate>Tue, 27 Mar 2007 07:34:00 GMT</pubDate><guid>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24772.html</guid><wfw:comment>http://www.cnitblog.com/weitom1982/comments/24772.html</wfw:comment><comments>http://www.cnitblog.com/weitom1982/archive/2007/03/27/24772.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/weitom1982/comments/commentRss/24772.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/weitom1982/services/trackbacks/24772.html</trackback:ping><description><![CDATA[
		<p>第一，谈谈final, finally, finalize的区别。 </p>
		<p>　　第二，Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)? </p>
		<p>　　第三，Static Nested Class 和 Inner Class的不同，说得越多越好(面试题有的很笼统)。 </p>
		<p>　　第四，&amp;和&amp;&amp;的区别。 </p>
		<p>　　第五，HashMap和Hashtable的区别。 </p>
		<p>　　第六，Collection 和 Collections的区别。 </p>
		<p>　　第七，什么时候用assert。 </p>
		<p>　　第八，GC是什么? 为什么要有GC? </p>
		<p>　　第九，String s = new String("xyz");创建了几个String Object? </p>
		<p>　　第十，Math.round(11.5)等於多少? Math.round(-11.5)等於多少? </p>
		<p>　　第十一，short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错? </p>
		<p>　　第十二，sleep() 和 wait() 有什么区别? </p>
		<p>　　第十三，Java有没有goto? </p>
		<p>　　第十四，数组有没有length()这个方法? String有没有length()这个方法? </p>
		<p>　　第十五，Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型? </p>
		<p>　　第十六，Set里的元素是不能重复的，那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别? </p>
		<p>　　第十七，给我一个你最常见到的runtime exception。 </p>
		<p>　　第十八，error和exception有什么区别? </p>
		<p>　　第十九，List, Set, Map是否继承自Collection接口? </p>
		<p>　　第二十，abstract class和interface有什么区别? </p>
		<p>　　第二十一，abstract的method是否可同时是static,是否可同时是native，是否可同时是synchronized? </p>
		<p>　　第二十二，接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)? </p>
		<p>　　第二十三，启动一个线程是用run()还是start()? </p>
		<p>　　第二十四，构造器Constructor是否可被override? </p>
		<p>　　第二十五，是否可以继承String类? </p>
		<p>　　第二十六，当一个线程进入一个对象的一个synchronized方法后，其它线程是否可进入此对象的其它方法? </p>
		<p>　　第二十七，try {}里有一个return语句，那么紧跟在这个try后的finally {}里的code会不会被执行，什么时候被执行，在return前还是后? </p>
		<p>　　第二十八，编程题: 用最有效率的方法算出2乘以8等於几? </p>
		<p>　　第二十九，两个对象值相同(x.equals(y) == true)，但却可有不同的hash code，这句话对不对? </p>
		<p>　　第三十，当一个对象被当作参数传递到一个方法后，此方法可改变这个对象的属性，并可返回变化后的结果，那么这里到底是值传递还是引用传递? </p>
		<p>　　第三十一，swtich是否能作用在byte上，是否能作用在long上，是否能作用在String上? </p>
		<p>　　第三十二，编程题: 写一个Singleton出来。</p>
		<p>　　答案请参看楼下： <br />以下是答案 </p>
		<p>　　第一，谈谈final, finally, finalize的区别。 </p>
		<p>　　final?修饰符（关键字）如果一个类被声明为final，意味着它不能再派生出新的子类，不能作为父类被继承。因此一个类不能既被声明为 abstract的，又被声明为final的。将变量或方法声明为final，可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值，而在以后的引用中只能读取，不可修改。被声明为final的方法也同样只能使用，不能重载finally?再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常，那么相匹配的 catch 子句就会执行，然后控制就会进入 finally 块（如果有的话）。 </p>
		<p>　　finalize?方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的，因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。 </p>
		<p>　　第二，Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)? </p>
		<p>　　匿名的内部类是没有名字的内部类。不能extends(继