|
|
用户名:Birdy 笔名:Steel.Yin 地区: 上海 行业:其他 |
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
每一天我的周围都在发生一些事情,新知心情,个种滋味尽在心头,为了不让这些生活的点滴随时间流逝而淡忘,愿能通过键盘记录我的生活、我的成长
如何利用门户网页提高访问量
网页编辑中双引号的输出
今天想输出双引号,搜了搜发现有几种方法:
对于JavaScript可以使用转义字符'\',如 \" 即可
对于VBScript使用连续两个双引号,如 ""
妹子的blog
今天在妹子的blog上看了她的丽江之行,看她玩的好开心,让我这个喜欢旅游的人又蠢蠢欲动了:)骑马被她说成骑驴看着我都笑晕了,给个链接 http://yvonne-deng.spaces.msn.com
显示器分辨率变而层位置不变
ASP操作Excel技术总结
http://www.blueidea.com/tech/program/2006/3547.asp
一、环境配置
二、ASP对Excel的基本操作
三、ASP操作Excel生成数据表
四、ASP操作Excel生成Chart图
五、服务器端Excel文件浏览、下载、删除方案
六、附录正文
一、环境配置
服务器端的环境配置从参考资料上看,微软系列的配置应该都行,即:
1.Win9x+PWS+Office
2.Win2000Professional+PWS+Office
3.Win2000Server+IIS+Office
目前笔者测试成功的环境是后二者。Office的版本没有特殊要求,考虑到客户机配置的不确定性和下兼容特性,建议服务器端Office版本不要太高,以防止客户机下载后无法正确显示。
服务器端环境配置还有两个偶然的发现是:
1.笔者开发机器上原来装有金山的WPS2002,结果Excel对象创建始终出现问题,卸载WPS2002后,错误消失。
2.笔者开发ASP代码喜欢用FrontPage,结果发现如果FrontPage打开(服务器端),对象创建出现不稳定现象,时而成功时而不成功。扩展考察后发现,Office系列的软件如果在服务器端运行,则Excel对象的创建很难成功。
服务器端还必须要设置的一点是COM组件的操作权限。在命令行键入“DCOMCNFG”,则进入COM组件配置界面,选择MicrosoftExcel后点击属性按钮,将三个单选项一律选择自定义,编辑中将Everyone加入所有权限。保存完毕后重新启动服务器。
客户端的环境配置没发现什么特别讲究的地方,只要装有Office和IE即可,版本通用的好象都可以。
二、ASP对Excel的基本操作
1、建立Excel对象
setobjExcelApp=CreateObject("Excel.Application")
objExcelApp.DisplayAlerts=false不显示警告
objExcelApp.Application.Visible=false不显示界面
2、新建Excel文件
objExcelApp.WorkBooks.add
setobjExcelBook=objExcelApp.ActiveWorkBook
setobjExcelSheets=objExcelBook.Worksheets
setobjExcelSheet=objExcelBook.Sheets(1)
3、读取已有Excel文件
strAddr=Server.MapPath(".")
objExcelApp.WorkBooks.Open(strAddr&"\Templet\Table.xls")
setobjExcelBook=objExcelApp.ActiveWorkBook
setobjExcelSheets=objExcelBook.Worksheets
setobjExcelSheet=objExcelBook.Sheets(1)
4、另存Excel文件
objExcelBook.SaveAsstrAddr&"\Temp\Table.xls"
5、保存Excel文件
objExcelBook.Save(笔者测试时保存成功,页面报错。)
6、退出Excel操作
objExcelApp.Quit一定要退出
setobjExcelApp=Nothing
三、ASP操作Excel生成数据表
1、在一个范围内插入数据
objExcelSheet.Range("B3:k3").Value=Array("67","87","5","9","7","45","45","54","54","10")
2、在一个单元格内插入数据
objExcelSheet.Cells(3,1).Value="InternetExplorer"
3、选中一个范围
4、单元格左边画粗线条
5、单元格右边画粗线条
6、单元格上边画粗线条
7、单元格下边画粗线条
8、单元格设定背景色
9、合并单元格
10、插入行
11、插入列
四、ASP操作Excel生成Chart图
1、创建Chart图
objExcelApp.Charts.Add
2、设定Chart图种类
objExcelApp.ActiveChart.ChartType=97
注:二维折线图,4;二维饼图,5;二维柱形图,51
3、设定Chart图标题
objExcelApp.ActiveChart.HasTitle=True
objExcelApp.ActiveChart.ChartTitle.Text="AtestChart"
4、通过表格数据设定图形
objExcelApp.ActiveChart.SetSourceDataobjExcelSheet.Range("A1:k5"),1
5、直接设定图形数据(推荐)
objExcelApp.ActiveChart.SeriesCollection.NewSeries
objExcelApp.ActiveChart.SeriesCollection(1).Name="=""333"""
objExcelApp.ActiveChart.SeriesCollection(1).Values="={1,4,5,6,2}"
6、绑定Chart图
objExcelApp.ActiveChart.Location1
7、显示数据表
objExcelApp.ActiveChart.HasDataTable=True
8、显示图例
objExcelApp.ActiveChart.DataTable.ShowLegendKey=True
五、服务器端Excel文件浏览、下载、删除方案
浏览的解决方法很多,“Location.href=”,“Navigate”,“Response.Redirect”都可以实现,建议用客户端的方法,原因是给服务器更多的时间生成Excel文件。
下载的实现要麻烦一些。用网上现成的服务器端下载组件或自己定制开发一个组件是比较好的方案。另外一种方法是在客户端操作Excel组件,由客户端操作服务器端Excel文件另存至客户端。这种方法要求客户端开放不安全ActiveX控件的操作权限,考虑到通知每个客户将服务器设置为可信站点的麻烦程度建议还是用第一个方法比较省事。
删除方案由三部分组成:
A:同一用户生成的Excel文件用同一个文件名,文件名可用用户ID号或SessionID号等可确信不重复字符串组成。这样新文件生成时自动覆盖上一文件。
B:在Global.asa文件中设置Session_onEnd事件激发时,删除这个用户的Excel暂存文件。
C:在Global.asa文件中设置Application_onStart事件激发时,删除暂存目录下的所有文件。
注:建议目录结构\Src代码目录\Templet模板目录\Temp暂存目录
六、附录
出错时Excel出现的死进程出现是一件很头疼的事情。在每个文件前加上“OnErrorResumeNext”将有助于改善这种情况,因为它会不管文件是否产生错误都坚持执行到“Application.Quit”,保证每次程序执行完不留下死进程。
补充两点:
1、其他Excel具体操作可以通过录制宏来解决。
2、服务器端打开SQL企业管理器也会产生问题。
<%
OnErrorResumeNextstrAddr=Server.MapPath(".")setobjExcelApp=CreateObject("Excel.Application")
objExcelApp.DisplayAlerts=false
objExcelApp.Application.Visible=false
objExcelApp.WorkBooks.Open(strAddr&"\Templet\Null.xls")
setobjExcelBook=objExcelApp.ActiveWorkBook
setobjExcelSheets=objExcelBook.Worksheets
setobjExcelSheet=objExcelBook.Sheets(1)objExcelSheet.Range("B2:k2").Value=Array("Week1","Week2","Week3","Week4","Week5","Week6","Week7",
"Week8","Week9","Week10")
objExcelSheet.Range("B3:k3").Value=Array("67","87","5","9","7","45","45","54","54","10")
objExcelSheet.Range("B4:k4").Value=Array("10","10","8","27","33","37","50","54","10","10")
objExcelSheet.Range("B5:k5").Value=Array("23","3","86","64","60","18","5","1","36","80")
objExcelSheet.Cells(3,1).Value="InternetExplorer"
objExcelSheet.Cells(4,1).Value="Netscape"
objExcelSheet.Cells(5,1).Value="Other"objExcelSheet.Range("b2:k5").Select
objExcelApp.Charts.Add
objExcelApp.ActiveChart.ChartType=97
objExcelApp.ActiveChart.BarShape=3
objExcelApp.ActiveChart.HasTitle=True
objExcelApp.ActiveChart.ChartTitle.Text=
"Visitorslogforeachweekshowninbrowserspercentage"
objExcelApp.ActiveChart.SetSourceDataobjExcelSheet.Range("A1:k5"),1
objExcelApp.ActiveChart.Location1
'objExcelApp.ActiveChart.HasDataTable=True
'objExcelApp.ActiveChart.DataTable.ShowLegendKey=TrueobjExcelBook.
SaveAsstrAddr&"\Temp\Excel.xls"objExcelApp.Quit
setobjExcelApp=Nothing
%>
<!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.0Transitional//EN">
<HTML>
<HEAD>
<TITLE>NewDocument</TITLE>
<METANAME="Generator"CONTENT="MicrosoftFrontPage5.0">
<METANAME="Author"CONTENT="">
<METANAME="Keywords"CONTENT="">
<METANAME="Description"CONTENT="">
</HEAD>
<BODY>
</BODY>
</HTML>
.NET架构的核心开发技术
新型的开发模式正逐渐被推广,将分发软件演变成一种服务还有待于所有开发人员的共同努力,而互联网却将彻底改变应用程序的开发模式和配置方式。
传统上,软件开发人员通过集成本地系统服务的方式开发应用程序。这种模型使开发人员有权使用一整套丰富的开发资源,精确控制应用程序的性能。
如今,开发人员在很大程度上已挣脱了这种模式的束缚,致力于构建具有复杂结构的n层系统,这种系统能将网络中各处的众多的应用程序进行集成,并大大提升 应用程序的价值。这样,开发人员便可集中精力挖掘软件独特的商业价值,而不必日夜为如何构建基本结构伤脑筋了。令人欣喜的局面将应运而生:软件投放市场的 时间大大缩短、开发人员的编程效率明显提高,最为根本的是开发出质量上乘的软件。
我们正在进入计算机发展的下一个阶段——基于 Internet的阶段,特别是基于Internet核心技术——XML扩充标记语言。尽管多层应用程序开发将焦点集中在建造大型企业级应用程序上,但现 在XML使得能够创建可用于任何人、任何场所的大型应用程序。它扩大了应用程序的使用范围。这样,软件就不是只能从CD上安装的某种东西,而是一种服务 ——就像呼叫服务或者计费电视一样,可以通过通信媒体来预订。
这一切,是通过将紧密联接的、高效的n层计算技术与面向消息的、松散 联接的Web概念相结合来实现的。我们将这种计算风格称为Web Service(Web服务),它的出现标志着人类已经迈入应用程序开发技术的新纪元。Web服务是一种应用程序,它可以使用标准的互联网协议,像超文本 传输协议(HTTP)和XML,将功能纲领性地体现在互联网和企业内部网上。
我们也可将Web服务视作Web上的组件编程。
从理论上讲,开发人员通过调用Web应用编程接口(API),将Web服务集成进他们的应用程序,就像调用本地服务一样。两者区别在于前者能够通过 Internet发送到某个远程系统的服务上。例如,像微软护照(Microsoft Passport)这样的服务,可以给开发人员提供应用程序身份确认的功能。通过对护照服务编程,开发人员就可以利用护照服务的基础体系,实现维护用户数 据库,确信服务开启和运行以及正确地备份等等功能。
■松散联接
跨越网络的分布应用程序逻辑的概念并不是一个新名词,但跨越Web的分布和集成应用程序逻辑的概念却是。
此前,像微软的DCOM (Distributed Component Object Model )、Object Management Group公司的CORBA (Common Object Request Broker Architecture )以及Sun公司的RMI(Remote Method Invocation )这些分布式对象模型被称为分布应用程序逻辑。运用这些系统结构,虽然服务放在远程系统上,开发人员仍然可以像原来本机编程那样维护和丰富应用程序的功 能。
但这种系统的问题是不能扩展到Internet。因为该体系的基础是服务器上的客户端和服务器的紧密联结。这意味着两者必须是 同质的基础体系,但也就常常意味着这种系统是非常脆弱的,如果有任何一端接口发生变化,另一端程序必然就会被中断。举个例子,如果服务器应用程序的接口改 变了,那么客户端也将会失效。
开发中要求有一个紧密联接的系统这本身没有错,而且许多应用程序也一直就是建立在这些系统上的。但最 终,随着时间的流逝,这种模型是不会扩展的。因为众多公司企业要求相互沟通,这很难保证会有一个统一的系统,同样也很难保证,你的客户的服务器会有你所需 要的完全一致的系统,你甚至都不可能猜想到它所用的是什么操作系统、什么对象模型和什么编程语言。
相反,Web服务的联接非常松 散。这就意味者你可以在联接的任何一端任意改变接口,而应用程序可以不受影响地照常工作。从技术上说,这主要是由于使用了拥有稳固性能的基于消息的异步技 术,如像HTTP、SMTP等Web标准协议。而且最重要的是,XML可以帮助实现其通用性。
作为一个宏伟的计划,.NET的路还很长。今后的发展无论是崎岖坎坷还是一片光明,在对新技术和IT产业的推动上,微软都是功不可没的。
消息系统将通信的基本单元打包进自描述的、运用于网络通信层的包(被称做消息)。消息系统和分布式对象系统的关键区别在于,发送者需要对接收者的系统了 解多少。使用分布式的对象系统,发送者需要帮助接收者考虑许多问题,比如应用程序将如何激活和卸载、调用的是什么接口等等。
另一方面,消息系统在通讯层上达成协议。发送者只需考虑的是接收者能够知道信息正被发送。发送方不需要了解一旦消息被收到后将会如何处理,也不需要对发送方和接收方之间作任何考虑。
在通讯层上达成协议的优势是显而易见的。例如,协议能够使接收方随时作修改而无须中断发送方,只要该协议始终明白是同一条消息。接收方不用中断任何当前 应用程序,可以自由升级和改进。更进一步说,就是发送方不用要求任何特殊的软件就可以和接收方交谈,只要他发送的是符合格式的信息,接收方就可以作出应 答。
■XML的通讯基础:SOAP
建造跨越Web的 Web服务的工作和异步系统的关键是使用统一的数据说明格式,这就是XML。特别说明的是,Web服务器在三方面需要XML来实现:基础语言、服务说明以及服务发现。
● SOAP:系统在底层需要有统一语言,特别地,应用程序相互通讯需要建立一套规则来说明如何表示不同数据类型(如整数和数组),如何表示命令(如进行数据 处理)。同时,应用程序在需要时还可以扩充这种语言。简单对象存取协议SOAP(Simple Object Access Protocol),这是XML的一种实现,代表了一组如何表示和扩充数据和命令的规则集。
● WDSL(Web Services描述语言) :一旦应用程序有了如何表述数据和命令的基本规则,他们就需要如何描述可以接收的特定数据和命令。应用程序只是声明如何接收整数是不够的,他们必须用明确 的方法声明。如给你两个整数,把它们相乘。WDSL是一种XML语法,开发人员和开发工具可以用它来表示Web服务的功能。
● SOAP Discovery:最后需要一组规则来定位服务的描述——对于开发者和开发工具在什么地方可以发现一个Web服务。SOAP Discovery规范提供了一组规则让开发者和开发工具可以自动发现Web服务的描述。
一旦这些准备好了,开发者可以方便地发现Web 服务,把它作为一个对象集成进他们的应用程序,并使应用程序和Web服务相互通讯。
■.NET框架:Web服务引擎
很显然,许多基本结构都需实现上述进程对开发人员和用户的透明化。.NET框架(.NET Framework)提供此基本结构。从.NET框架角度看,所有组件都可以是Web服务,而Web服务也仅是一种组件。实际上,.NET框架提取出微软 组件对象模型(COM)的精华,将它们与松散联接计算的精华有机地结合在一起,生成了强大、高效的Web组件系统:简化程序员的“管道”操作,深入地集成 了安全性,引进了基于互联网的操作系统,极大地改善应用程序的可靠性和可扩展性。
.NET框架由三个主要部分组成:通用语言运行库、一套层次结构的统一类库和一个被称为ASP+的高级ASP版本。
有关.NET的许多东西让人印象深刻,尤其是微软充分传达出的对互联网作为未来主要技术平台的首肯,和在某些方面对公开的标准的欢迎。
.NET的确牵动着每个人的猜测……
1.通用语言运行库
除了通用语言运行库的字面含义外,在开发阶段和运行过程中它还扮演着另一个角色。在组件运行时,运行库负责管理内存分配、启动和中止线程和进程、强化安 全系数,同时还调整任何该组件涉及到的其他组件的附件配置。在开发阶段,运行库的角色稍微有点变化:因为很多方面可以自动实现(例如内存管理等)。运行库 可以使开发过程变得非常简单,特别是同今天的COM编程相比更是如此。特别典型的是,像Reflection这样的特性可以极大地缩小开发人员将商业逻辑 转化成一个可重复使用的组件而不得不编写的代码数量。
运行库对于编程语言来说并不是新鲜的东西。实际上每一种编程语言都已包含一个 运行库。Visual Basic开发系统有最明显的运行库(正规名字为VBRUN),Visual C++也有一个MSVCRT,此外,像Visual FoxPro、Jscript、SmallTalk、Perl、Python和Java等等都如此。.NET框架的关键角色就是它提供了一个跨所有编程语 言的统一环境。
2.统一编程类
.NET框架类为开发人员提供了一套可以使用的统一的面向对象、异步、层次结构 的可扩展类库。现在,C++的使用者使用Microsoft Foundation Classes,Java程序员使用Windows Foundation Classes,Visual Basic的用户使用Visual Basic APIs。微软用.NET框架统一了这些不同的框架。结果是,开发人员不用非去学多个框架来完成自己的工作。而且,通过创建一套跨编程语言的通用 API,.NET框架可以实现跨语言继承、纠错处理以及程序调试。实际上,从JScript 到C++的所有编程语言,对于.Net框架都是相互等同的,开发人员可以自由地选择他们想使用的任何语言。
.NET是一种全新的平台,它将对现有的所有代码产生影响。盖茨说:“微软所有的产品都会被涉及。我们的整个战略是围绕这个平台展开的。”
3.ASP+
ASP+是使用 .NET框架提供的类库构建而成的,它提供了一个Web应用程序模型,该模型由一组控件和一个基本结构组成。有了它,Web应用程序的构建变得非常容易。 开发人员可以直接使用ASP+控件集,该控件集封装了公共的、用于超文本标识语言(HTML)用户界面的各种小组件(诸如文本框、下拉选单等等)。实际 上,这些控件运行在Web服务器上,它们将用户界面转换成HTML格式后再发送给浏览器。在服务器上,控件负责将面向对象的编程模型呈现给Web开发人 员,这种编程模型能提供面向对象的编程技术拥有的丰富功能。ASP+还提供一些基本结构服务(诸如会话状态管理和进程循环),这些服务进一步减少了开发人 员要编写的代码量,并使应用程序的可靠性得到了大幅度提高。ASP+还允许开发人员将软件作为一项服务进行传送。通过使用ASP+ Web服务功能,ASP+开发人员只需进行简单的业务逻辑编程,而由ASP+基本结构负责通过SOAP传送服务。
尽管ASP+还未正式发行,但它已在改进应用程序功能方面创造出了令人难以置信的奇迹:在现有基于ASP的应用程序性能基础上,性能优化了三倍之多,更为激动人心的是生产效率再度攀升。
■.NET框架的核心部分
.NET框架有几个要素值得一提。首先是它的安全系统和配置系统。这两个系统协同工作,有力地遏止了运行不安全代码的可能性,并大幅度减少了号称“DLL Hell”的对应用程序进行配置时所面临的挑战。
安全系统是一个高度细化、基于事实的系统,它赋予开发人员和管理员多种代码处理权限(而不仅仅是“on”或“off”)。将来,还会根据代码本身的核心要素来决定如何实施上述权限。
例如,当.NET框架应用程序被下载到某一系统中时,它会申请一组权限(诸如对临时目录的写入权限)。运行时将收集有关应用程序的事实信息(诸如:它是 从何处下载的、是否用了有效签名、甚至它访问系统的准确程度),并按管理策略决定是否允许应用程序运行。运行时甚至还可告之应用程序它无法授权申请的所有 权限,并允许应用程序自行决定是否继续运行。
有这种安全系统作保障,许多应用程序配置问题便会迎刃而解。开发人员和管理员(最终是 用户)所面临的最大挑战之一是版本的管理问题。如果在您新装了某个应用程序之后,一切都陷于瘫痪状态,而在这之前系统一直运行得非常良好,那么最大的可能 是新安装的应用程序重写了一些共享库,并极有可能修正了现有应用程序正使用的程序错误。这种情况出现的频率很高,以致人们将它称为:“DLL Hell”。
.NET框架拥有的几项高级功能可以彻底消除“DLL Hell”现象。首先,它有一个非常强大的内部命名系统,能够有效地防止两个库因互相重名而被错当为对方的情况发生。除此之外,它还提供一项被称作 “side by side”配置的新功能。如果前例中新安装的应用程序确实重写了共享库,现有应用程序可对该库进行修复。等现有应用程序再次启动时,它会检查所有的共享文 件。如果发现文件被更改,同时这些更改又是不兼容的,则它可以请求运行时提取一个它可以使用的版本。得益于强大的安全系统,运行时可以安全地执行该操作, 这样应用程序就完成了本身的修复工作。
■后记
人们总是喜欢不厌其烦地发表诸如“互联网改变了一切”的陈词。同 样地,在谈论互联网给人类带来的影响时,总是情不自禁地使用广告式的夸张语,以表达对互联网的推崇。不过,互联网的确彻底改变了应用程序的开发模式和配置 方式。将分发软件演变成一种服务还有待人们的共同努力,XML是实现这个梦想的重要手段。.NET框架是微软开发人员战略的核心内容,它旨在帮助开发人员 轻松地构建、配置和运行Web服务。
总之,.NET的最先受益者,将是我们的开发人员。.NET的路还很长,今后的发展无论是崎岖坎坷还是一片光明,在对新技术和IT产业的推动上,微软都是功不可没的
VC++.NET开发环境整合技巧
运行机制及MFC类结构
本讲先来通过一个简单的MFC应用程序来介绍"类"的有关概念,然后分析其运行机制以及基本MFC类层次结构,最后使用项目模板所提供的MFC应用程序向导来创建一个单文档程序TextViewer。
一个简单的MFC应用程序
在现在的"面向对象"程序设
计中,我们经常会听说过"类"和"对象"的概念。那么什么是"类"呢?"类"的实质上是一种新的复杂数据类型。说它"新",是因为它不同于C语言中的
char、int、float等基本数据类型,说它"复杂",是因为它不仅可以包含各种基本类型的数据,而且还可以包含处理这些数据的函数。
MFC使用"类"来编写Windows应用程序,例如下面的过程:
(1) 单击"开始"页面中的"新建项目",或者打开"文件"菜单中的"新建",选择"项目"命令,都将弹出"新建项目"对话框。
(2) 在左侧的"项目类型"窗格中,选中"Visual C++项目"。在右侧的"模板"窗格中,拖动窗格右侧的滚动条显示其他模板,然后选中"Win32 项目"。
(3) 在"名称"文本框中,输入项目名称"Ex_1_SimpMFC",单击"确定"按钮,弹出"Win32 应用程序向导"对话框。
(4) 单击左侧的"应用程序设置"。选中"应用程序类型"中的"Windows 应用程序",在"附加选项"中选中"空项目",结果如图1所示,单击"完成"按钮。

图1 Win32 应用程序设置
(5) 在"解决方案资源管理器"中,右击项目名称Ex_1_SimpMFC,从弹出的快捷菜单中选择"添加",然后选择"添加新项",弹出"添加新项"对话框。
(6) 在右侧的"模板"窗格中选中"C++文件",在"名称"文本框中输入SimpMFC,单击"打开"按钮。
(7) 键入如图2所示的代码。

(8) 在"解决方案资源管理器"标签中,右击顶层的项目名"Ex_1_SimpMFC",从弹出的快捷菜单中选择"属性"菜单项,弹出如图3所示的"Ex_1_SimpMFC 属性页"对话框。

(9) 单击"MFC的使用",然后单击右边的下拉按钮,从弹出的下拉选择列表选择"在共享DLL中使用MFC",单击"确定"按钮。
(10) 打开"调试"菜单,选择"开始执行(不调试)",或按Ctrl + F5,运行程序,结果如图4所示。

运行机制及MFC类结构
1.代码分析
在图2中,包含文件afxwin.h是使用MFC类库的头文件。class是定义类的关键字,class的后面是用户定义的类名,即CSimpApp。需要说明和是:通常用大写的C字母开始的标识符作为类名,C用来表示类(Class),以与函数及其他数据类型相区别。
类体中定义的函数或变量,都称为该类的"成员",其中变量称为"成员变量",函数称为"成员函数"。成员可被声明成public、private。对于public类成员来说,它们是公有的,能被类外面的程序访问;对于private类成员来说,它们是私有的,只能由类中的函数所使用,而不能被外面的程序所访问。
在"public:"或"private:"后面定义的所有成员都是公有或私有的,直到下一个"public:"或"private:"出现为止。若
成员前面没有类似"public:"或"private:"的声明,则所定义的成员是private(私有),这是类的默认处理。关键字public和
private可以在类中出现多次,且前后的顺序没有关系。
类名冒号后面的是用来定义类的继承,其格式如下:
class 派生类名 : 继承方式 基类名
{
派生类的成员
};
其中,被继承的类称为基类(base class),在基类上建立的新类称为派生类(derived
class)。继承方式有三种:public(公有)、private(私有)及protected(保护),若继承方式没有指定,则被指定为缺省的
public方式。继承方式决定了派生类的继承基类属性的使用权限,public继承方式能够使用基类的所有共有成员。
从代码中可以看出,类CSimpApp是从应用程序类CWinApp派生而来。而类CMainFrame是从框架窗口类CFrameWnd派生而来。
在面向对象的程序设计中,类有函数重载、运算符重载和虚函数等,这些称为类的多样性。
所谓"函数重载",是指在类中或同一个作用域中,允许有多个同名的函数存在,但同名的各个函数的形参必须有区别:形参的个数不同,或者形参的个数相同,但参数类型有所不同。
所谓"运算符重载",就是赋予已有的运算符多重含义。
所谓"虚函数",它是指在函数名前面加上virtual关键字的成员函数,如成员函数InitInstance就是被声明成了虚函数。虚函数也是能使一个函数具有多种不同的版本,只不过虚函数的不同版本是在基类和派生类中进行定义的。这样系统就会根据相应的类对象来决定调用的是派生类CSimpApp的InitInstance()函数中的代码,还是基类InitInstance()函数中的代码。
在CMainFrame类中,我们还看到了与该类名相同的成员函数CMainFrame(),这个函数称为该类的"构造函数"。每个类都有一个构造函数,如果我们没有指定,系统就会自动使用默认的构造函数。构造函数的最大特点是在对象建立时它会被自动执行,因此用于变量、对象的初始化代码一般放在构造函数中。在定义构造函数时,不能指定函数返回值的类型,也不能指定为void类型。
在CMainFrame()构造函数中的Create函数是用来创建窗口,它的参数依次用来指定类名、窗口标题、窗口样式和窗口大小。其中,预定义样
式WS_OVERLAPPEDWINDOW用来创建一个常规窗口,CRect是一个矩形的数据类,用来确定窗口的大小和位置。
与构造函数相对应的是析构函数。析构函数是另一种特殊的C++成员函数,它只是在类名称前面加上一个"~"符号。每一个类只有一个析构函数,没有任何参数,也不返回任何值。
在类定义时,成员函数既可以在类中定义,也可以在类外定义。但在类外定义时,必须用作用域运算符"::"来通知编译系统该函数所属的类。例如,InitInstance函数就是在类CSimpApp外面定义的。
代码中,m_pMainWnd是MFC中的一个全局指针变量。MessageBox()是窗口基类CWnd的一个成员函数,用来弹出一个对话框窗口,显示参数指定的短信息,这里是"你好,欢迎进入MFC世界!"。
2.运行机制
在程序中,当定义一个类对象时,它会自动调用相应的构造函数。所谓"类对象",就是用该类定义的"变量",这个"变量"又称为类的一个实例。例如,theApp就是类CSimpApp的一个对象。
MFC正是利用类的这种"自动调用相应的构造函数"特性,使得WinMain()函数的调用变成了应用程序框架内部的调用,所以我们在代码中看不到每个Windows程序所必须有的WinMain()函数。
当应用程序运行到"CSimpApp theApp;"时,系统就会先调用基类CWinApp构造函数,进行一系列的内部初始化操作,然后自动调用CSimpApp的虚函数InitInstance(),该函数会进一步调用相应的函数来完成主窗口的构造和显示工作。下面来看看上述程序中InitInstance的执行过程。
首先执行的是:
m_pMainWnd = new CMainFrame;
该语句用来创建从CFrameWnd类派生而来的用户框架窗口CMainFrame类对象,继而调用该类的构造函数,使得Create函数被调用,完成了窗口创建工作。
然后执行后面两句:
m_pMainWnd->ShowWindow(m_nCmdShow);
m_pMainWnd->UpdateWindow();
用作窗口的显示和更新。接下来调用:
m_pMainWnd->MessageBox("你好,欢迎进入MFC世界!");
最后返回TRUE,表示窗口创建成功。
由于应用程序类CWinApp是用来调用WinMain以及实例的初始化,因此每一个MFC应用程序有且只能一个这样的应用程序类,且需要一个全局的对象实例,如上述程序中的theApp,当然也可换一个对象名。
InitInstance()完成初始化工作之后,接下来就是调用基类CWinApp的成员函数Run(),执行应用程序的消息循环,即重复执行接收消息并转发消息的工作。当Run()检查到消息队列为空时,将调用基类CWinApp的成员函数OnIdle进行空闲时的后台处理工作。若消息队列为空且又没有后台工作要处理时,则应用程序一直处于等待状态,一直等到有消息为止。
当程序结束后,调用基类CWinApp的成员函数ExitInstance(),完成终止应用程序的收尾工作。这就是MFC应用程序的运行机制。
ActiveX Automation
| ' Sub Macro1() '' 宏在 02-5-1 由 LiuTao 录制 ' Documents.Open FileName:="基于Visual C.doc", ConfirmConversions:=False, _ ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:="", _ PasswordTemplate:="", Revert:=False, WritePasswordDocument:="", _ WritePasswordTemplate:="", Format:=wdOpenFormatAuto Selection.WholeStory Selection.Copy End Sub |
| if (CoInitialize(NULL)!=0) { AfxMessageBox("初始化COM支持库失败!"); exit(1); } |
| void CKkView::OnMenuAutoDisplay() { // TODO: Add your command handler code here static char BASED_CODE szFilter[]="Word Files(*doc)|*.DOC||"; CFileDialog fd(true,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,szFilter,NULL); CString strFilePath;//用来保存打开的文件名; if(fd.DoModal()==IDOK) strFilePath=fd.GetPathName();//获取要打开的Word文档的名字; _Application m_App;//定义Word提供的应用程序对象; Documents m_Docs;//定义Word提供的文档对象; Selection m_Sel;//定义Word提供的选择对象; m_Docs.ReleaseDispatch(); m_Sel.ReleaseDispatch(); m_App.m_bAutoRelease=true; if(!m_App.CreateDispatch("Word.Application")) { AfxMessageBox("创建Word2000服务失败!"); exit(1); } //下面是定义VARIANT变量; COleVariant varFilePath(strFilePath); COleVariant varstrNull(""); COleVariant varZero((short)0); COleVariant varTrue(short(1),VT_BOOL); COleVariant varFalse(short(0),VT_BOOL); m_Docs.AttachDispatch(m_App.GetDocuments());//将Documents类对象m_Docs和Idispatch接口关联起来; m_Docs.Open(varFilePath,varFalse,varFalse,varFalse, varstrNull,varstrNull,varFalse,varstrNull, varstrNull,varTrue,varTrue,varTrue); //打开Word文档; m_Sel.AttachDispatch(m_App.GetSelection());//将Selection类对象m_Sel和Idispatch接口关联起来; m_Sel.WholeStory ();//选择文档中的全部内容; m_Sel.Copy();//将数据拷贝到剪贴板 this->GetEditCtrl( ).Paste ();//将数据粘贴到程序的"视"中; m_Docs.ReleaseDispatch();//断开关联; m_Sel.ReleaseDispatch(); } |
Visual C++.NET 2003中的代码优化
| int i; … // Do something that assigns a value to i. … return i*15; |
| mov eax, DWORD PTR _i$[esp-4] imul eax, 15 |
| mov ecx, DWORD PTR _i$[esp-4] mov eax, ecx shl eax, 4 sub eax, ecx |
| int f1(int i, int j, int k) { return i + k; } int main() { int n = a+b+c+d; m = f1(3, n, 4); return 0; } |
| mov eax, 4 mov ecx, 3 call ?f1@@YAHHHH@Z mov DWORD PTR ?m@@3HA, eax |
| // File 1 extern void func (int *, int *); int g, h; int main() { int i = 0; int j = 1; g = 5; h = 6; func(&I, &j); g = g + i; h = h + i; return 0; } // File 2 extern int g; extern int h; void func(int *pi, int *pj) { *pj = g; h = *pi; } |
| sub esp, 8 lea eax, DWORD PTR _j$[esp+8] push eax lea ecx, DWORD PTR _i$[esp+12] push ecx mov DWORD PTR _i$[esp+16], 0 mov DWORD PTR _j$[esp+16], 1 mov DWORD PTR ?g@@3HA, 5 mov DWORD PTR ?h@@3HA, 6 call ?func@@YAXPAH0@Z mov eax, DWORD PTR _i$[esp+16] mov edx, DWORD PTR ?g@@3HA mov ecx, DWORD PTR ?h@@3HA add edx, eax add ecx, eax mov DWORD PTR ?g@@3HA, edx mov DWORD PTR ?h@@3HA, ecx xor eax, eax add esp, 16 ret 0 |
| sub esp, 8 lea ecx, DWORD PTR _j$[esp+8] lea edx, DWORD PTR _i$[esp+8] mov DWORD PTR _i$[esp+8], 0 mov DWORD PTR ?g@@3HA, 5 mov DWORD PTR ?h@@3HA, 6 call ?func@@YAXPAH0@Z mov DWORD PTR ?g@@3HA, 5 xor eax, eax add esp, 8 ret 0 |
| #pragma optimize("t", on) int fiddle(S *p) { …; } #pragma optimize("", on) |
| 选项 | 效果 |
| /RTC1 | 使用无优化的Debug模式,编译器插入动态检测代码以帮助你发现程序中的错误。比如你没有初始化的内存,或者你把__stdcall和__cdecl弄混了。 |
| /GS | 加入检测静态缓冲区(栈)溢出的代码,黑客就不能覆盖函数返回的地址以执行恶意代码。 注意:这不意味着你可以高枕无忧,你仍要留心编写安全的代码! |
| /Wp64 | 检测生成64位代码的问题,通过它你可以发现移植到64位环境下你的代码可能出现的问题。 |