程序vb教程

vb教程  时间:2021-04-04  阅读:()

妓欢汲即魏牡肺文档下载免费文档下载http://www.
1mpi.
com/本文档下载自文档下载网,内容可能不完整,您可以点击以下网址继续阅读或下载:http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468计算机二级vb常见错误和难点分析这款资料,通过对计算机二级VB常见错误和难点的讲解,可以帮助你轻松通过二级考试,我的计算机二级考试靠的就是它,希望大家能认真学习哈嘻嘻……全国计算机二级考试VB常见错误和难点分析.
标点符号错误在VB中只允许使用西文标点,任何中文标点符号在程序编译时产生"无效字符"错误,并在该行以红色字显示.
用户在进入VB后不要使用中文标点符号.
中、西文状态下标点号对照见下表所示.

[此处图片未下载成功]2.
字母和数字形状相似的小写字母"l"和数字"1"形式几乎相同、O的小写字母"o"与数字"0"也难以区,这在输入代码时要十分注意,避免单独作为变量名使用.

.
对象名称(Name)属性写错在窗体上创建的每个控件都有默认的名称,用于在程序中唯一地标识该控件对象.
系统为每个创建的对象提供了默认的对象名,例如,Text1、Text2、Command1、Label1等.
用户可以将属性窗口的(名称)属性改为自己所指定的可读性好的名称,如txtInput、txtOutput、cmdOk等.
对初学者,由于程序较简单、控件对象使用较少,还是用默认的控件名较方便.
当程序中的对象名写错时,系统显示"要求对象"的信息,并对出错的语句以黄色背景.
用户可以在代码窗口的"对象列表"框检查该窗体所使用的对象.
.
Name属性和Caption属性混淆属性的值用于在程序中唯一地标识该控件对象,在窗体上不可见;而Caption属性的值是在窗体上显示的内容.
.
对象的属性名、方法名写错当程序中对象的属性名、方法名写错时,VB系统会显示"方法或数据成员未找到"的信息.
在编写程序代码时,尽量使用自动列出成员功能,即当用户在输入控件对象名和句点后,系统自动列出该控件对象在运行模式下可用的属性和方法,用户按空格键或双击鼠标即可,这样既可减少输入也可防止此类错误出现.

://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468par.
变量名写错用Dim声明的变量名,在后面的使用中表示同一变量而写错了变量名,VB编译时就认为是两个不同的变量.
例如,下面程序段求1~100的和,结果放在Sum变量中:DimsumAsInteger,iAsIntegerSum=0i=1to100Sum=SuniiPrintSum显示的结果为100.
原因是累加和表达式Sum=Suni中的右边的变量名Sum写成Sun.
VB对变量声明有两种方式,可以用变量声明语句显式声明,也可以用隐式声明,即不声明直接使用.
上述变量名的写错,系统为两个不同的变量各自分配内存单元,造成计算结果不正确.
因此,为防止此类错误产生,必须对变量声明采用限制其为显式声明方式,也就是在通用声明段加OptionExplicit语句.
.
语句书写位置错在VB中,除了在"通用声明"段利用Dim等对变量声明语句外,其他任何语句都应在事件过程中,否则运行时会显示"无效外部过程"的信息.
若要对模块级变量进行初始化工作,则一般放在FormLoad()事件过程中.
.
无意形成控件数组若要在窗体上创建多个命令按钮,有些读者会先创建一个命令按钮控件,然后利用对该控件进行复制、粘贴,这时系统显示:已经有一个控件为"Command1".
创建一个控件数组吗的信息,若单击"是"按钮,则系统创建了名称为Command1的控件数组.
若要对该控件的Click事件过程编程,系统显示的框架是:SubCommand1_Click(IndexAsInteger)EndSub表示控件数组的下标.
若非控件数组,Click事件过程的框架是:PrivateSubCommand1_Click()EndSub请注意直到学习实验数组前,一律不http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468使用控件数组.
.
Print方法中定位问题定位通过Tab、Spc函数和最后的逗号、分号和无符号来控制.
VB中通过Print方法中各参数的综合使用达到所需的结果,但初学者往往难以掌握.
(1)Tab(n)与Spc(n)的区别(n)从最左第1列开始算起定位于第n列,若当前打印位置已超过n列,则定位于下一行的第n列,这是常常定位不好出现的问题.
在格式定位中,Tab用得最多.
Spc(n)从前一打印位置起空n个空格.
例如,下面程序段显示了Tab与Spc的区别,效果如图所示.
SubCommandl_Click()Print"1234567890",Tab(1);"**"';Tab(2);"%%%";spc(2);"$$$$"EndSub[此处图片未下载成功](2)紧凑格式";"分号的使用紧凑格式";",即输出项之间无间隔.
但对于数值型,输出项之间系统自动空一列,而由于数值系统自动加符号位,因此,大于零的数值,实际空两列.
对于字符型之间无空格.
例如,下面程序段,效果如图所示.
[此处图片未下载成功]SubCommand1_Click()Print1;-2;3Print"1234";"5678""A";"B";"C";"D","E","F"EndSub从该例应区分数值和字符在紧凑格式输出的差异.
.
打开工程时找不到对应的文件一般,一个再简单的应用程序也应由一个工程.
vbp文件和一个窗体.
fhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468rm文件组成.
工程文件记录该工程内的所有文件(窗体.
frm文件、标准模块.
bas文件、类模块.
cls文件等)的名称和所存放在磁盘上的路径.
若在上机结束后,把文件复制到U盘上保存,但又少复制了某个文件,下次打开工程时就会显示"文件未找到".
也有在VB环境外,利用Windows资源管理器或DOS命令将窗体文件等改名,而工程文件内记录的还是原来的文件名,这样也会造成打开工程时显示"文件未找到".

解决此问题的方法:一是修改.
vbp工程文件中的有关文件名;二是通过"工程"菜单的"添加窗体"中的"现存"选项,将改名后的窗体加入工程.

编程8个优良习惯良好的程序设计风格是反映一个人的程序设计水平的问题,对一个程序来说,仅仅当提供正确的输入时才能产生正确的输出是不够的.
一个设计得好的程序必须能在任何条件下,即在它运行过程中可能遇到的各种情况下都能正确地操作.
应当把计算机程序设计得能够重复运行或连续运行;它必须很"耐用",能够经得起偶然的或故意的错误使用.
、"&"替换""在很多人的编程语言中,用""来连接字符串,这样容易导致歧义.
良好的习惯是用"&"来连接字符串.
不正确:sMessageAsStringsMessage="1""2"正确:sMessageAsStringsMessage="1"&"2"注意:"&"的后面有个空格、变量命名大小写,语句错落有秩,源代码维护方面下面大家比较一下以下两段代码:读懂难度很大的代码:DimSNAMEAsStringDimNTURNAsIntegerIfNTURN=0Thehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468nIfSNAME="vbeden"ThenDoWhileNTURN<4NTURN=NTURN1LoopEndIfEndIf容易读懂的代码:DimsNameAsStringDimnTurnAsIntegerIfnTurn=0ThenIfsName="vbeden"ThenDoWhilenTurn<4nTurn=nTurn1LoopEndIfEndIf、请养成以下的"对象命名约定"良好习惯推荐使用的控件前缀控件类型前缀例子复选框CheckboxchkchkReadOnly组合框ComboboxcbocboEnglish命令按钮CommandbuttoncmdcmdExit通用对话框CommondialogdlgdlgFileOpen目录列表框DirectorylistboxdirdirSource驱动器列表框DrivelistboxdrvdrvTarget文件列表框FilelistboxfilfilSource窗体FormfrmfrmEntry图象框ImageimgimgIcon标签LabellbllblHelpMessage列表框ListboxlstlstPolicyCodes菜单MenumnumnuFileOpen单选按钮OptionbuttonoptoptGender图片框PictureboxpicpicVGA文本框TextboxtxttxtLastName时钟控件TimertmrtmrAlarm变量声明所有的变量将会节省编程时间,因为键入操作引起的错误减少了(例如,究竟是aUserNameTmp,还是sUserNameTmp,http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468还是sUserNameTemp).
在"选项"对话框的"编辑器"标签中,复选"要求变量声明"选项.
OptionExplicit语句要求在VisualBasic程序中声明所有的变量.
应该给变量加前缀来指明它们的数据类型.
而且前缀可以被扩展,用来指明变量范围,特别是对大型程序.
用下列前缀来指明一个变量的数据类型.
变量数据类型数据类型前缀例子(字符串类型)strstrFNameInteger(短整数类型)intintQuantityLong(长整数类型)lnglngDistanceSingle(单精度浮点数类型)sngsngAverageDouble(双精度浮点数类型)dbldblToleranceBoolean(布尔类型)blnblnFoundByte(字节类型)bytbytRasterDataDate(日期类型)dtedteNowCurrency(货币类型)curcurRevenueObject(对象类型)objobjCurrentVariant(变体类型)vntvntCheckSum、在简单的选择条件情况下,使用IIf()函数繁琐的代码:IfnNum=0Then="sancy"ElsesName="Xu"EndIf简单的代码:=IIf(nNum=0,"sancy","Xu")、尽量使用Debug.
Print进行调试在很多初学者的调试中,用MsgBox来跟踪变量值.
其实用Debug.
Print不仅可以达到同样的功效,而且在程序最后编译过程中,会被忽略.
而MsgBox必须手动注释或删除.
通常:MsgBoxnName应该:.
PrintnName://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468r、在重复对某一对象的属性进行修改时,尽量使用With.
.
.
.
EndWith通常:.
Height=5000Form1.
Width=6000.
Caption="ThisisMyLabel"应该:WithForm1.
Height=5000.
Width=6000.
Caption="ThisisMyLabel"EndWith这种结构程序执行效率比较高,特别在循环语句里.
、MsgBox中尽量使用消息图标,这样程序比较有规范一般来说用来提示确认或成功操作的消息vbExclamation用来提示警告的消息vbCritical用来提示危机情况的消息vbQuestion用来提示询问的消息、在可能的情况下使用枚举枚举的格式为[Public|Private]Enumnamemembername[=constantexpression]membername[=constantexpression].
.
.
.
EndEnum语句包含下面部分:部分描述可选的.
表示该Enum类型在整个工程中都是可见的.
Enum类型的缺省情况是Public.
可选的.
表示该Enum类型只在所声明的模块中是可见的.
必需的.
该Enum类型的名称.
name必须是一个合法的VisualBasic标识符,在定义该Enum类型的变量或参数时用该名称来指定类型.
必需的.
用于指定该Enum类型的组成元素名称的合法VisualBasic标识符.
可选的.
元素的值(为Longhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468类型).
可以是别的Enum类型.
如果没有指定constantexpression,则所赋给的值或者是0(如果该元素是第一个membername),或者比其直接前驱的值大1.
说明所谓枚举变量,就是指用Enum类型定义的变量.
变量和参数都可以定义为Enum类型.
Enum类型中的元素被初始化为Enum语句中指定的常数值.
所赋给的值可以包括正数和负数,且在运行时不能改变.
例如:SecurityLevelIllegalEntry=-1SecurityLevel1=0SecurityLevel2=1EndEnum语句只能在模块级别中出现.
定义Enum类型后,就可以用它来定义变量,参数或返回该类型的过程.
不能用模块名来限定Enum类型.
类模块中的PublicEnum类型并不是该类的成员;只不过它们也被写入到类型库中.
在标准模块中定义的Enum类型则不写到类型库中.
具有相同名字的PublicEnum类型不能既在标准模块中定义,又在类模块中定义,因为它们共享相同的命名空间.
若不同的类型库中有两个Enum类型的名字相同,但成员不同,则对这种类型的变量的引用,将取决于哪一个类型库具有更高的引用优先级.
不能在With块中使用Enum类型作为目标.
Enum语句示例下面的示例演示用Enum语句定义一个命名常数的集合.
在本例中是一些可以选择的颜色常数用于设计数据库的数据输入窗体.
PublicEnumInterfaceColorsicMistyRose=&HE1E4FF&icSlateGray=&H908070&icDodgerBlue=&HFF901E&icDeepSkyBlue=&HFFBF00&icSpringGreen=&H7FFF00&icForestGreen=&H228B22&icGoldenrod=&H20A5DAhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468&icFirebrick=&H2222B2&EndEnum好处是加快编程速度记录集和水晶报表在使用水晶报表时,经常会感到数据不是很好控制,最后只好使用这个终极绝招咯.
那就是使用数据定义文件(TTX),把得到的ADO记录集传送给水晶报表.
通常情况下,水晶报表是从物理的数据库上创建出来的,但是现在有了32位的ActiveDataDriver--P2smon.
dll,水晶就可以不用再事先连接到一个数据库上咯.
首先,需要创建一个TTX文件,进入数据源选择窗体后再单击了前面的""后弹出数据源窗体此时,我们使用"New"按钮创建一个新的数据定义文件(TTX),格式如下保存后,我们打开这个文本文件,就会发现TTX文件的格式,原来中间是TAB分割符来的.
接着,我们就按照水晶报表的老套路画式样,剩下的就是传递记录机集了.
下面,我们要声明好传递ADO记录集需要的Api,DeclareFunctionPEOpenEngineLib"crpe32.
dll"()AsIntegerDeclareFunctionPEGetErrorCodeLib"crpe32.
dll"(ByValprintJobAsInteger)AsIntegerDeclareFunctionPEOpenPrintJobLib"crpe32.
dll"(ByValRptNameAsString)AsIntegerDeclareFunctionPEOutputToWindowLib"crpe32.
dll"(_ByValprintJobAsInteger,_ByValTitleAsString,_ByValLeftAsLong,_ByValTohttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468pAsLong,_ByValWidthAsLong,_ByValHeightAsLong,_ByValstyleAsLong,_PWindowAsLong)AsIntegerDeclareFunctionPEOutputToPrinterLib"crpe32.
dll"(_ByValprintJobAsInteger,_nCopiesAsInteger)AsIntegerDeclareFunctionPEStartPrintJobLib"crpe32.
dll"(_ByValprintJobAsInteger,_WaitOrNotAsInteger)AsIntegerDeclareFunctionPEClosePrintJobLib"crpe32.
dll"(ByValprintJobAsInteger)AsIntegerDeclareSubPECloseEngineLib"crpe32.
dll"()DeclareFunctionCreateFieldDefFileLib"p2smon.
dll"(_lpUnkAsObject,ByVal_fileNameAsString,_bOverWriteExistingFileAsLong)AsLongDeclareFunctionvbEncodelPtrLib"p2smon.
dll"(xAsObject)AsStringPublicDeclareFunctionSetActiveDataSourceLibhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468"p2smon.
dll"(_ByValprintJobAsInteger,_ByValtableNumAsInteger,_xAsObject)AsLong最后给出的是报表的打印代码JobAsIntegerDimHandleAsInteger'打开打印引擎=PEOpenEngine'水晶的错误处理IfHandle=0Then=PEGetErrorCode(Handle)MsgBox"打印引擎出错!
""错误代号:"&ErrorNumEndIf'打开打印作业=PEOpenPrintJob(App.
Path&".
rpt")'水晶的错误处理IfJob=0Then=PEGetErrorCode(Job)MsgBox"打开作业New.
rpt失败!
"MsgBox"错误代号:"&ErrorNumEndIf'给水晶报表传送ADO记录集,AdoRecordset的生成就不再多说了Handle=SetActiveDataSource(Job,0,ADOrs)'输出到打印预览窗口=PEOutputToWindow(Job,"New.
rpt",0,0,520,520,WS_MAXIMIZE,0)'直接输出到打印机=PEOutputToPrinter(Job,1)'水晶的错误处理IfHandle<>0Then=PEStartPrintJob(Job,True)IfHandle<>0Thttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468henMsgBox"打印完毕"Else=PEGetErrorCode(Job)MsgBox"打印失败!
""错误代号:"&ErrorNumEndIfElse=PEGetErrorCode(Job)MsgBox"无法输出到窗体或打印机"MsgBox"错误代号:"&ErrorNumEndIf'关闭打印作业(Job)'关闭打印引擎PECloseEngine我使用的是VB6水晶报表8.
5,感觉这种方式比较灵活好用,同时解决了水晶报表补空行的问题.
.
0的使用说明是一个可以让用户在应用中快速方便的使用功能强大的报表系统的控件.
它有着强大的功能,方法和事件,能让用户在进行少量的工作的情况下就提供出完善的报表DBREPORT可以让用户把数据保存到ADO或者OLEDB的数据源中,也可以从数据列表中取得数据,或者以事件为基础取得数据.
用户可以很方便的存取或打印这些数据.
它的特征包括:DataAccess(数据的接口):此控件支持多种数据连接方式.
他可以直接连接到数据库并生成他自己的数据集,也可以绑定到已经存在的ADO数据集或OLEDB数据源.
也可以从数据列表或通过符合条件的事件来向控件输入数据.
Manipulation(数据的操作:)此控件可以让用户在不写入任何代码的情况下就可以对数据进行分类和控制.
你可以很容易的定义一对一或一对多的关系,定义用来限制数据的过滤条件,定义计算的列(如统计合计数的列)等.
此控件也可以支持主表与明细表的关系(通过平行的或串行的条件来分出表的子表).

DataAppearanhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ce(定制数据的外观表现形式):用户可以完全的控制数据的表现的属性,如数据的字体,颜色,页面设置,眉头和注脚等.
控件有一个内嵌的印象机制来转换代码值为字符串以实现用户的控制需求andCollections(目标和成品):此控件定义了一些基础的对象.
程序设计人员可以在运行中完全的控制这些对象:目标(如片断和细节)和对象构成报表的定义,这些都可以在设计时利用属性页来进行定义,也可以在运行中来进行定义.
许多人在设计时进行定义是因为它是交互式的可视的,而在运行时进行设计是因为可以给程序设计人员最终的控制权,允许用户以最终的输入的信息为基础来生成报表,以最大限度的靠近用户的最终的需要ofStyles(风格的层次):表现风格用来是控制报表列的可视属性的,以树状的等级来进行组织.
表现的风格可以从父亲那里继承并可以覆盖原有的属性.
这样的做法可以节约时间因为当用户需要新建一个新的风格时你可能只需要定义一小部分新的特性.
这样的做法也可以使用户做出来的报表具有统一的外观.
这可以使用户作出来的系统成为无论是在局部还是全局的修改都非常容易修改和跟踪的灵活的一套系统.

TableUsage(最大化窗口的使用):此控件给窗口提供了广泛的支持,包括定义窗口的眉头和注脚,列与列之间的宽度,自动的对齐列等等.
OverReportGeneration(报表生成的控制):用户可以仅通过很少的几行代码就可以实现报表的生成或打印或者打印的预览.
或者用户可以通过定义此控件的属性来控制整个报表的产生和其表现.
BuildingWizard(报表生成向导):此控件有一个内嵌的报表生成的向导,用户可以通过此向导很方便的来定义所要生成报表,通过选择已有的基础的表现风格,定义报表所包括的列,定义报表的组合方式等来生成.
报表生成向导对开发者而言是个很方便的工具,但是此向导只能被最终的用户来直接进行使用,只允许最终用户来定制他们所需要的报表的使用表现方式.
://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468parFeatures(其它的特征):此控件也包括可视的编辑器;用于表达的标准的静态的函数;高级的易于操作的页面控制器;易于定制和支持不同的配置等等属性及其使用:(右键单击该控件,选择properties)属性页包括:(数据源):在DataMode(数据连接方式)的下拉列表中可以选择:tdbmodedatasource(以数据库为数据源),tdbmodememoryarray(以数据存储列为数据源)tdbmodeuserevent(以用户自定义事件为数据源)在sourceofconnection(数据连接源目标)中可以选择:datalinkfile(使用链接文件),用browse键即可选择所需要的链接文件odbcdatasourcename(使用odbc数据源),在下拉列表中列出了已有的odbc数据源,用NEW键即可建立新的数据源connectionstring(使用语句进行连接),用BULID键可以选择所要连接的数据源,在弹出的数据链接属性框中'提供者'页是用来让用户选择下午连接的数据方式的,'连接'页是让用户选择所要使用的数据库的名称并输入登录数据库时的用户名及密码的,'高级'页中是用来设置网络的,在'所有'页中列出了进行的所有的设置attributes(其它属性的设置)(鉴定),通过设置用户名和密码来进行用户的鉴定(记录源),在commandtext中可以输入相应的SQL语句来选择表和字段及设定排序方式,过滤条件等:(主要属性)是对整个属性的一个概括,也对报表的编辑界面有个概述,如是否显示网格,网格的大小的定制等parameter:(参数),可以对报表的参数进行设置和修改删除:(报表列)对在DATASOURCE中定义的表http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468中的列进行设置,也可增加和修改列,定义计算列,如:要增加一个计算列,则在左边的空格中点击右键,在弹出的菜单中选择NEW,在右边则会出现这个新的列的属性,在NAME中输入名称,在displayname中输入报表中显示的名称,在type中定义新增的列的类型,在maxlength中定义最大长度,在calculateexpression中定义计算列的计算方法(点开.
.
.
号,弹出一编辑器,在expression中可写入计算的方法):(过滤条件)可以增加删除修改过滤条件,如:增加一过滤条件,在左空白处点击右键,在弹出菜单中选择NEW,并在右边的filterexpression(过滤条件表达示),conditionexpression(条件表达示)中定义相应的各项条件:(片断)可以定义报表的格式和表现的方法,但在作此定义之前,必须先进行另一项定义:右键单击需定义的dbreports控件,在弹出的菜单中选择reportwizard,出现一reportwizard的窗口,第一页为:style(风格),可以在左边的列表中选择所需的报表的表现风格,当鼠标点击到某一风格时,中间的框中将出现所选此风格的简单说明,且右边的框中将出现相应的范例,在选中了风格后,点击next进而第二页:fields(报表列),在左边的框中列出的是此控件所选择的列,右边是报表列的表现方式,用鼠标选择右框中的列,可以进行删除,点击左边框中的某一列,点击insertgroup则会在所选的列的地方加入group,点击addtogroup则将此列增加到组中,在确认了列的格式之后点击next进而第三页:generaloption(主页面的设置),在reportheader中输入表头的文字.
可以选择keepdetailtogther(选择保存明细说明),numbergroupheaders(在表头中显示组的数据列),numberdetailsections(显示片断的数据值)再点击finish键即可完成.
回到属性框的sections页,在左边的框中列出了在reportwinzard中定义的片断,可http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468以在此页面中增加和修改片断和片断中的元素.
如要修改片断:用鼠标选择需修改的片断,在右边的框中会出现相应的属性,属性分为general页和plus页,general页主要功能为定义该片断的主要的属性的设置:name中定义片断的名称,comment中可作相应的说明,type中可选择片断的类型,condition中定义此片断的表达式,style中定义片断的风格;plus页中,keepwithprev(保持预览)和(保持与下一片断的关系)下拉列表中可以让操作者选择:0.
donotcare(不关注),1.
ifpossible(如果可能的请客下进行保持)2.
atallcosts(在任何情况下)3.
expression(根据表达示来进行判断);plus属性页主要是用来设置一些附加的属性的:hight设置片断的高度,spacingfore(设置前置的空间),spacingafter(设置后置的空间),选择为新的页,使用条件,在打印前进行调用,在keepwithprevexp和keepwithnextexp中输入条件(仅当在general页中的keepwithprev,keepwithnext选择的属性为3.
expression时才可进行).

如要增加片断,则在左边的框中在相应的位置点击右键,在弹出的菜单中选择newsections,则会生成一新的片断,并在右边的框中出现该新的片断的属性,用户可以对此片断的属性进行个性化的设置,如修改片断所示.
如要修改片断中的元素:点击左边框的需修改的片断下的元素,右边框中将出现该元素的属性分为general页,plus页,style页,graphics页,borders页.
General页定义了该元素的主要的属性:name中输入表示的名称,comment中写入相应的说明,exp中定义该元素的表达示,style中定义表现风格(点.
.
.
可以弹出expressioneditor编辑器,可以直接进行定义),在width中定义宽度,在height中定义高度,在merge中定义混合的方式(方式可在下拉列表中进行选择);plus页定义该属性的具体表现:placement中定http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468义布局类型(0.
tileleft标题在左边,1.
centerhorizontally水平的在中央,2.
tileright标题在右边3.
free自由定义),在cellspan中定义元素间的距离,在mapping中定义应象的方式,callexperssion(使用表达示),callbeforeprint(在打印前调用);style页主要用来定义该元素中的字体大小颜色等相关属性的;graphics页主要是用来定义该元素中的图像的属性的;borders页是主要用来定义该元素的边界的方式的属性的.

如要增加元素,则在左边的框中在相应的片断位置上点击右键,在弹出的菜单中选择newcell,则会生成一新的片断的元素,并在右边的框中出现该新的元素的属性,用户可以对此元素的属性进行个性化的设置,如修改元素所示.
styles(表现风格):每一个片断的元素都可以拥有自己的表现风格,而这些表现风格则可以在此页面中进行定义增加和修改如要修改风格,则用鼠标选择在左框中的需修改的风格的名称,则右边将出现此风格的属性,可分别对general页,graphics页,borders页中的相应的属性进行修改,在修改了这些属性后,在sections中定义的相关的该表现风格的元素的风格也会发生相应的变化要增加表现风格则在左框中的空白位置点击右键,在弹出菜单中选择new,则出现新的表现风格,并在右边出现该新的风格的属性,在对general页,graphics页,borders页的属性进行了个性化的定义后,新的表现风格就出现了.
这时可以回到sections页中对需进行定义的元素联系到该新的表现风格上来:在sections页中选定某片断或元素点击右键,选择弹出菜单的recreatepresent,再在拉伸出来的菜单中选择styles,这时可以看到所有已经存在的表现风格,选择用户需要使用的表现风格单击即可.
Mappings(映像):可以增加删除修改该该报表的映像文件.
如要增加映像文件:在左边框中点击右键,在弹出的菜单中选择newmaping则将出现新的映像文件,并可在右边出现的属性框中定义该新映像文件的名称://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468如要修改映像文件的名称,则用鼠标在左框中点击到需修改的映像文件上,并在右边出现的属性框的name字段中进行修改如要修改某映像文件下的列值的属性,则用鼠标点击到该列值,并在右边的属性框中进行修改属性:在key中定义该列值的名称;在string中输入该列值的字符串,在picture中定义该列值的图形;在picfile中指定图形文件;在linkedkey中定义链接的列值名称.
(其中如定义为图形的列值则不可以再有链接文件).
在修改了这些属性后,在sections中定义的相关的该映像文件的元素的属性也会发生相应的变化如要增加列值,则用鼠标点击到需增加列值的映像文件,单击右键,在弹出的菜单中选择newvaluesitem,并在右边的属性框中进行属性的个性化的设置,如修改列值所示.
这时可以回到sections页中对需进行定义的元素联系到该新映像文件上来:在sections页中选定某片断或元素点击右键,选择弹出菜单的recreatepresent,再在拉伸出来的菜单中选择mapping,这时可以看到所有已经存在的映像文件,选择用户需要使用的映像文件单击即可.
(线条):对表格中的线条的属性进行定义和修改如要修改线条的属性则在左边框中用鼠标选择需修改的线条的名称,在右边框中的属性中进行相应的修改,在name中定义名称,在thickness中定义该线条的重度,在color中定义该线条的颜色(点击color框,将弹出一颜色框,用户可以在此选择所需要的颜色,也可自定义颜色),在右边的中部的框中将出现该线条的预览图.
在修改了这些线条的属性后,在sections页中定义的与相关的该线条的元素中的线条的表现属性也会发生相应的变化.

如要增加线条,则在左边框中的空白位置单击右键,在弹出的菜单中选择new,则会出现一新的线条的记录,并在右边框中出现相应的属性,如修改线条所示.
这时可以回到sections页中对需进行定义的元素联系到该新的线条风格上来:在sections页中选定某片断或元素点击右键,选择弹出菜单的recreatepresent,再在拉伸出来的菜单中选择lines,这时可以看到所有的已经存在的线条记录,选中用户所http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468需要使用的线条记录单击即可.

(报表的轮廓):可以对该报表的轮廓进行定义.
报表编辑器editor(右键单击该控件,选择edit)出现该报表的编辑器,用户可以直接对报表的表现形式进行定义.
用鼠标选择需拖动的片断,按住鼠标左键进行移动,则会发生相应的改变,在编辑器的顶部有一排菜单按钮,根据这些按钮可以直接对报表进行个性化定义:.
showitemproperties:显示当前片断的属性2.
showitemstyle:显示当前片断的表现风格.
attachcurrentitem'sstyletootheritems:将当前片断的风格复制到另一列上面去.
insertapicture(acellwithaprivatestyle):选择当前片断的图片5.
insertnewseciont:在当前位置插入一新的片断6.
insertnewcell:在当前位置插入一新的元素7.
deleteselecteditem(s):删除所选的片断或元素8.
undo:撤销上一步的操作9.
redo:恢复上一步的操作.
togglethealignmentgrid:显示网格.
togglesnaptogridonmove/resize:在移动和改变大小时对齐到网格12.
toggledisplayofcellexpression/cellnames:显示元素的表达示和名称13.
alignleft:将所选的对象左对齐14.
aligntop:将所选的对象顶部对齐15.
alignright:将所选的对象右对齐16.
alignbottom:将所选的对象底部对齐17.
makesamewidth:将所选的对象保持同宽18.
makesamehight:将所选的对象保持同高19.
makesamesize:将所选的对象保持同大小检查语法错误(右键单击该控http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468件,选择check)该功能用于检查用户所定义的报表的属性中是否有语法错误,如没有错误,则提示:noerrorshavebeenfound.
如有错误发现,则将弹出一张errors的表框,在表框中列举了错误的出处预览功能(右键单击该控件,选择preview)该功能用于预览用户定义的报表的模型,可参对预览的模型进行适当的修改,使报表真正符合用户的期望恢复列值(右键单击该控件,选择retrievefields)该功能用于删除所有已定义的列的属性等,并从数据源中进行恢复从xml文件中导入(右键单击该控件,选择loadfromxml)该功能用于选择xml文件导入来定义该报表控件,选择后,将弹出一打开的表框,让用户选择需使用的xml文件将控件保存为xml文件(右键单击该控件,选择saveasxml该功能用于将报表控件的定义保存为xml文件,选择和,将弹出一保存的表框,让用户选择需保存的xml文件的位置和名称的后期绑定和前期绑定.
什么是后期绑定和前期绑定后期绑定MSDN6的定义如下:后期绑定:若将一个变量声明为AsObject或AsVariant(包括AsForm或AsControl的变量),VisualBasic在编译时就无法确定该变量将引用哪种类型的对象.
因此,VisualBasic必须使用后期绑定,在运行时确定对象的属性和方法能否使用该变量.
若使用后期绑定,则每次调用属性或方法时,VisualBasic都要将成员名传给该对象IDispatch接口的GetIDsOfNames方法.
GetIDsOfNames返回该成员的派遣ID,或DispID.
VisualBasic再将该DispID传给IDispatch接口的Invoke方法来调用该成员.
对进程外部件而言,这意味着一次额外的跨进程方法调用,结果是调用开销翻番.
前期绑定:如果在编译时VisualBasic能够知道属性或方http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468法所属的对象,就可以预先查找该成员在类型库中的DispID或vtable地址.
这样就无须在运行时调用GetIDsOfNames.
当显式声明了变量的类时,例如AsWidget,该变量就只能存放该类的对象的引用.
VisualBasic就可以为该变量调用的所有属性和方法使用前期绑定.
建议在VisualBasic和应用程序中使用这种方法来声明对象变量.
使用前期绑定还是后期绑定完全取决于声明变量的方式.
对象的创建方式对此没有任何影响.
.
后期绑定的几个优势和好处第一,个人认为,由于VB6不支持实现继承,对于某些设计,可以使用将对象定义为Variant变量,而获取某些设计和编码上的便利,而得到接口或抽象类的好处.
例如:如定义2个类:Class1:OptionExplicit2PublicSubUpdate()MsgBox"Class1Updated"5EndSubClass2:OptionExplicit2PublicSubUpdate()MsgBox"Class2Updated"5EndSub在使用的时候,可以使用以下方法,而实现一些设计模式:1DimobjTestAsVariant2DimobjC1AsNewClass14SetobjTest=objC15objTest.
Update6DimobjC2AsNewClass28SetobjTest=objC29objC2.
Test10这样,无须继承机制,也可以得到抽象接口的优势,而使接口、实现分离.
第二,在调用外部的COM自动化组件时,如Office,如果通过这种方式调用,对于不同版本的Office,如果你调用的方法、属性都是存在的,那么可以适应不同版本的Officehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468,但如果通过前期绑定,在项目引用中确定对象类型,是有版本兼容问题的.

.
效率和劣势其实最主要的劣势是效率问题,《AdvancedVisualBasic6》一书说,使用Variant变量和Long变量进行循环,效率差别是1.
5倍,而没有别人认为的那么大,而且对于大对象,差别也不是很大.
对于本文前边的例子,如果创建的是进程内对象,前期绑定和后期绑定调用效率差别大概2:3左右,也就是说也是1.
5倍.
对于调用Office这样的外部COM自动化对象,也许差别大一些,没有专门测试,不过对于Office自动化,速度主要是决定于Office本身的启动、初始化.

另外一个劣势是没有了IDE下的属性、方法成员自动列出.
所以,个人认为,在使用VB6的时候,为了得到好的设计,有时不妨使用一些VB6的后期绑定的特性,来提高设计质量.
调用API制作渐变的窗口背景色导读:在许多Windows软件的安装程序中,时常可以看到以某种颜色由浅至深的渐变为背景的窗口.
使用VB制作这类窗口的方法有不少,而通过调用API函数绘制渐变的窗口背景色,似乎是一种既简单又节省资源的方法.

首先,在module文件中加入下列声明语句:FunctionCreateSolidBrushLib"GDI"(ByVal_crColorAsLong)AsIntegerFunctionFillRectLib"USER"(ByValhDCAs_,lpRectAsRECT,ByValhBrushAsInteger)AsIntegerDeclareFunctionDeleteObjectLib"GDI"(ByValhObject_AsInteger)AsIntegerTypeRECTleftAsIntegertopAsIntegerrightAsIntegerbothttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468tomAsIntegerEndType然后,在窗口的Paint事件中加入下列代码:PrivateSubForm_Paint()DimColorAsIntegerDimhBrushAsIntegerDimOldModeAsIntegerDimRetValAsIntegerDimStepSizeAsIntegerDimXAsIntegerDimFillAreaAsRECTOldMode%=Me.
ScaleModeMe.
ScaleMode=3%=1Me.
ScaleHeight/80Color%=255FillArea.
left=0.
right=Me.
ScaleWidthFillArea.
top=0.
bottom=StepSize%ForX%=1To80%=CreateSolidBrush(RGB(0,0,Color%))RetVal%=FillRect(Me.
hDC,FillArea,hBrush%)RetVal%=DeleteObject(hBrush%)Color%=Color%-4Color%$#@60;0ThenColor%=0FillArea.
top=FillArea.
bottom.
bottom=FillArea.
bottomStepSize%Next.
ScaleMode=OldMode%EndSub按F5运行,就会出现一个以从上至下、由浅至深的渐变蓝色为背景的窗口.
对上述代码稍加改动,便可制作出各种颜色和水平方向的渐变背景.
动态调用外部函数的方法导读:VB可以用Declare声明来调用标准DLL的外部函数,但是其局限性也很明显:利用Declare我们只能载入在设计时通过Lib和Alias字句指定的函http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468数指针!
而不能在运行时指定由我们自己动态载入的函数指针),不能用Declare语句来调用任意的函数指针.
当我们想动态调用外部函数的时候,就必须考虑采用其他的辅助方法,来完成这个任务了.

在文章《VB真是想不到系列之三:VB指针葵花宝典之函数指针》、《MatthewCurland的VB函数指针调用》、《利用动态创建自动化接口实现VB的函数指针调用》等文献中对此问题都进行了一定程度上的讨论,但是头绪都很繁琐,对我这样的菜鸟还有点深奥,在资料搜索过程中,找到通过在VB中调入汇编程序,比较简便的实现了这个功能,下面就是实现原理:)使用LoadLibrary加载DLL;2)GetProcAddress获得函数指针;以上两步得到了预加载函数的指针,但是VB中没有提供使用这个指针的方法.
我们可以通过一段汇编语言,来完成函数指针的调用!
)通过汇编语言,把函数的所有参数压入堆栈,然后用Call待用函数指针就可以了.
实现以上功能的主要程序:′加载Dll=LoadLibrary(ByVal"user32")′获得函数指针=GetProcAddress(LibAddr,ByVal"MessageBoxA")′原型为MessageBox(hWnd,lpText,lpCaption,uType)′---以下为Assembly部分---pushuTypepushlpCaptionpushlpTextpushhWndcallProcAddrLibAddr′释放空间嘿,够简单吧!
下面是动态调用MessageBoxA的源代码,上面的步骤被封装到RunDll32函数中,可放到模块(CallAPIbyName.
bas)中:Dims1()AsByte,s2()AsByteDimretAsLonghttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468=StrConv("Hello~World",vbFromUnicode)s2=StrConv("VBNote",vbFromUnicode)ret=RunDll32("user32","MessageBoxA",hwnd,VarPtr(s1(0)),VarPtr(s2(0)),0&)CallAPIbyName.
bas中的源代码:OptionExplicitPrivateDeclareFunctionLoadLibraryLib"kernel32"Alias"LoadLibraryA"(ByVallpLibFileNameAsString)AsLongDeclareFunctionGetProcAddressLib"kernel32"(ByValhModuleAsLong,ByVallpProcNameAsString)AsLongDeclareFunctionCallWindowProcLib"User32"Alias"CallWindowProcA"(ByVallpPrevWndFuncAsLong,ByValhWndAsLong,ByValMsgAsLong,ByValwParamAsLong,ByVallParamAsLong)AsLongDeclareFunctionFreeLibraryLib"kernel32"(ByValhLibModuleAsLong)AsLongDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(lpDestAshttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468Any,lpSourceAsAny,ByValcBytesAsLong)Publicm_opIndexAsLong′写入位置m_OpCode()AsByte′Assembly的OPCODEFunctionRunDll32(LibFileNameAsString,ProcNameAsString,ParamArrayParams())AsLongDimhProcAsLongDimhModuleAsLongm_OpCode(4006*UBound(Params))′保留用来写m_OpCode′读取API库=LoadLibrary(ByValLibFileName)IfhModule=0Then"Library读取失败!
"ExitFunctionEndIf′取得函数地址=GetProcAddress(hModule,ByValProcName)IfhProc=0Then"函数读取失败!
",vbCriticalFreeLibraryhModuleExitFunctionEndIf′执行AssemblyCode部分=CallWindowProc(GetCodeStart(hProc,Params),0,1,2,3)FreeLibraryhModule′释放空间EndFunctionPrivateFunctionGetCodeStart(ByVallngProcAsLong,ByValarrParamsAsVariant)AsLong′---以下为Assembly部分--′作用:将函数的参数压入堆栈://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468arlngIndexAsLong,lngCodeStartAsLong′程序起始位址必须是16的倍数′VarPtr函数是用来取得变量的地址=(VarPtr(m_OpCode(0))Or&HF)1_opIndex=lngCodeStart-VarPtr(m_OpCode(0))′程序开始的元素的位置′前面部分以中断点添满lngIndex=0Tom_opIndex-1m_OpCode(lngIndex)=&HCC′int3NextlngIndex以下开始放入所需的程序-将参数push到堆栈′由于是STDCallCALL参数由最后一个开始放到堆栈ForlngIndex=UBound(arrParams)To0Step-1AddByteToCode&H68′push的机器码为H68CLng(arrParams(lngIndex))′参数地址NextlngIndex′callhProc&HE8′call的机器码为HE8lngProc-VarPtr(m_OpCode(m_opIndex))-4′函数地址用call的定址结束所需的程序-返回呼叫函數&HC2′ret10hAddByteToCode&H10AddByteToCode&H0=lngCodeStartEndFunctionSubAddLongToCode(lDataAsLong)′将Long类http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468型的参数写到m_OpCode中m_OpCode(m_opIndex),lData,4m_opIndex=m_opIndex4EndSubSubAddIntToCode(iDataAsByte)′将Integer类型的参数写道m_OpCode中CopyMemorym_OpCode(m_opIndex),iData,2m_opIndex=m_opIndex2EndSubSubAddByteToCode(bDataAsByte)′将Byte类型的参数写道m_OpCode中m_OpCode(m_opIndex)=bDatam_opIndex=m_opIndex1EndSub千里行-操作Word与Excel本文将告诉你如何使用VB代码连接Office应用程序,并简要接触一下在文件中输入数据的方法.
实际上,在VB中用代码与Word和Excel进行会话并控制它们,是可行的.
但是请注意,首先需要在机器上安装office应用程序,才能在VB代码中存取它们的对象.

下面就是一些例子,告诉你如何与这些程序会话,并控制它们.
OptionExplicitxlsAppAsExcel.
ApplicationDimwrdAppAsWord.
Application只要相关的对象库已经被选择,在应用程序中进行对象变量的赋值是可能的.
MicrosoftExcel8.
0对象库是相对于Excel的,而MicrosoftWord8.
0对象库是为Word服务的.
在VB的IDE环境中,从"工程"菜单中选择"引用",可以看到系统可用的所有库列表.
PrivateSubCommand1_Click()SetxlsApp=Excel.
ApplicationWithxlsApp'ShowExcel.
Visible=True'Createanewwohttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468rkbook.
Workbooks.
Add'Puttextintothecellthatisselected.
ActiveCell.
Value="Hi"'PuttextintoA3regardlessoftheselectedcell.
Range("A3").
Value="ThisisanexampleofconnectingtoExcel"EndWithEndSub在上面的程序段中,我们在变量xlsApp中建立了一个对象,这样Excel就对用户可见了.
当Excel象这样启动后,并不包含一个工作簿,所以必须创建或者执行打开操作.
这里,我们建立了一个新的工作簿,然后,就可以操作其中的信息,或者打印,或者保存,或者你任意想做的事情.

SubCommand2_Click()'closetheworkbookxlsApp.
Workbooks.
Close'CloseExcelxlsApp.
QuitEndSub上面这段代码执行关闭程序的功能.
首先,关闭工作簿,这将出现一个提示对话框,询问用户是否想保存修改;然后,退出应用程序.
PrivateSubCommand3_Click()wrdApp=NewWord.
ApplicationWithwrdApp'ShowWord.
Visible=True'CreateNewDocument.
Documents.
Add'Addtexttothedocument.
ActiveDocument.
Content.
Text="Hi".
ActiveDocument.
Content.
Text="Thisisatestexample"EndWithhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468EndSub上面这段代码中,在变量wrdApp中设置引用Word程序的对象.
同样,当Word按照这种方式启动后,不会包含一个文档,所以,必须执行建立或者打开操作.
这里是建立了一个新文档,然后可以操作其中的信息了,打印、保存、发送邮件,等等.
.
.

但是,在Word文档中放置文本并非容易!
特别是与Excel一起工作时.
为了简单地在特定的地方放置文本,需要有一个bookmark标记.
这意味着,需要事先建立一个模板.
PrivateSubCommand4_Click()'ClosethecurrentdocumentwrdApp.
ActiveDocument.
Close'CloseWordwrdApp.
QuitEndSub上面这段代码的功能是关闭应用程序.
首先,关闭当前文档,这时可能需要用户保存修改.
然后,退出程序.
SubForm_Unload(CancelAsInteger)'ClearthememorySetxlsApp=NothingSetwrdApp=NothingEndSub最后一段代码就是关闭VB应用程序.
这是优秀程序员编程的好习惯.
Ihopethisbrieftutorialishelpful.
Itdoesnottouchonmuchofwhatyoucandototheofficeapplicationsoncethey'reopen,butshouldgiveyouanideaofhowtogetstarted.
实现窗口的弹出式菜单导读:在Windows95、Windows98或NT的风格中,有按动鼠标器右键弹出下拉菜单的操作,在VB执行环境下,有一些控件本身具有弹下拉菜单的功能,如TexTbox控件等,但大多数编辑类控件以及窗体本身却没有此功能,要在窗口中任意位置实现PopUpMenu(弹出式菜单),可借助VB的菜单工http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468具来实现.

首先,打开VB的"工具"菜单条,利用"菜单编辑器"为窗体生成一个菜单:标题(Caption)菜单条名(Name)编辑menuEdit复制mnuCopy剪切munCut其次,将生成的menuEdit菜单设置为不可视.
PrivateSubForm_Load()Me.
menuEdit.
Visibe=False′menuEdit菜单设置为不可视EndSub然后,利用MouseDown事件实现任意位置弹出PopUpMenu,如下例:本例中以RichTexBox控件为例,在其上面实现复制、剪切功能.
.
复制功能的实现.
PrivateSubMnuCopy_Click()Clipboar.
Clear′将剪贴板清空′将RichTexBox控件上选择上的内容复制到剪贴板Clipboard.
SetTextRichTexBox1.
SelTextEndSub.
剪切功能的实现.
PrivateSubMnuCut_Click()Clipboard.
Clear′将剪贴板清空′将RichTextBox控件上选择了的内容复制到剪贴板Clipboard.
SetTextRichBox1.
SelText′将RichTexBox控件上选择了的内容删除SendKeys″DELETE″,TrueEndSub.
在RichTexBox控件的MouseDown事件中实现任意位置弹出PopUPMenu.
SubRichTexBox1_MouseDown(ButtonAsInteger,ShiftAsInteger,xAsSingle,YAsSingle)MnuFileASMenu′声明一个菜单类型的变量SetmunFile=Me.
MenuEdit′将MenuEdit赋给菜单变量http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ifButton=2Then′判断是否按动鼠标器右键′判断RichTexBox控件上选择了的内容是否存在,决定复制、剪切菜单条是否可操作.
IfLen(RichTexBox.
Text)=0OrLen(RichTexBox.
SelText)=0ThenmnuCopy.
Enabled=Flase′复制菜单条不可操作.
nmuCut.
Enabled=False′剪切菜单条不可操作.
nmuCopy.
Enabled=True′复制菜单条可操作.
nmuCut.
Enabled=True′剪切菜单条可操作.
EndmnuFile′弹出PopUpMenu.
EndIfEndSub这样,在VB执行环境中,操作窗体上的RichTexBox控件,按动鼠标器右键就可弹出下拉菜单,实现复制、剪切功能.
数据库编程的几点心得一、ADODB.
Connection的连接字符串(ConnectionString)的生成之道是当前访问数据库的主流,但其ConnectionString往往有一大串,并且在访问不同的数据库(如Access和SQLServer),或访问方式(通过ODBC和OLEDB)不一样时,其具体参数的设置差异很大,这给连接字符串的编写增加了一定的难度.
这里给大家介绍两种生成ConnectionString的方法,以便在没有现成的资料可供参考时,写出需要的连接字符串.

方法一,使用ADODC控件的连接字符串向导生成连接字符串.
用VB新建一标准EXE工程,先引用ADODC部件(选菜单[工程][部件.
.
.
],在弹出的部件窗口中选MicrosoftADODataControl),再将其加到Form1上,默认名为Adodc1;选中Adodc1,在其上单击右键,单击"ADODC属性",选"使用连接字符串",单击"生成"按钮,接下来根据该向导一步一步输入各相关的连接信息,"确定"后,在"使用连接字符串"下面的文本框中就是我们需要的内容.

方法二,http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468调用Ado连接窗口,获得连接字符串.
用VB新建一标准EXE工程,引用MicrosoftOLEDBServiceComponent1.
0TypeLibary和MicrosoftActiveXDataObjects2.
xLibrary(具体操作与ADODC的引用类似,只是通过菜单[工程][引用.
.
.
]选),加一个TextBox到Form1,双击Form1,进入Code编辑区,清除VB自动生成的所有代码,再输入下述代码:OptionExplicitSubForm_Load()dlTempAsMSDASC.
DataLinksDimcnTempAsADODB.
connectionSetdlTemp=NewMSDASC.
DataLinksSetcnTemp=NewADODB.
connectiondlTemp.
PromptEditcnTempText1.
Text=cnTemp.
ConnectionStringSetdlTemp=NothingSetcnTemp=NothingEndSub运行时会弹出一个与ADODC相似的生成连接字符串的向导,输入各相关数据,"确定"后在Form1的Text1中就得到我们需要的连接字符串.
二、汉字乱码问题笔者曾经在使用ADO向SQLServer6.
5中追加或修改数据后,发现查询出来的汉字都是乱码,最初以为是客户端的环境有问题,后来打开服务器端的数据库,发现其中的汉字也都是乱码,费了九牛二虎之力才找到原因:在追加和修改的过程中,ADO将字符进行了自动翻译(AutoTranslate),翻译后就成了乱码(Microsoft给我们开了一个"小小"的玩笑),解决的办法就是不让它乱翻译,具体操作如下:如果ADO通过OLEDB直接连接到数据库,则在Connection的ConnectionString中加入字符串:AutoTranslate=False;如果ADO通过ODBC连接到数据库,http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468则在配置ODBC时,将"执行字符数据转换"一项的勾去掉.

三、在SQL中处理含单引号的字符串在写SQL时,对字符串数据都用单引号引起来,如:Select*fromMyTableWhereID='FirstID'若其中的FirstID为First'ID,即中间多出一个单引号,则上述写法将导致错误,解决的办法是将字符串中的每一个单引号用两双引号替换,下面的函数StrToSQL完成该功能,并用单引号将处理后的字符串引起来:FunctionStrToSQL(ByValstrValueAsString)AsStringStrToSQL="'"Replace(strValue,"'","'")"'"EndFunction在写SQL时如有字符串数据,不管其中有没有单引号,都可以这样使用:strValue="First'Id"="Select*fromMyTableWhereID="StrToSQL(strValue)四、只返回查询结果的前N个记录这是个老生常谈的问题,稍有这方面经验的人都会想到在SQL中用"SelectTop"语句来完成此功能,如访问Access数据库时为:Selecttop50*FromMyTableServer7.
0和SQLServer2000中都可以这样,但在SQLServer6.
5中不行,它不支持"SelectTop",笔者采用了一个折衷的办法,使用SQLServer6.
5的"SetRowcount"来限制记录数,例如:.
Execute"SetRowcount50"执行查询.
Exhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ecute"Setrowcount0"最后一行表示取消记录数据限制,这句千万不能少,因为记录数的限制在MyConnection的生存期都有效,所以其它的查询也会受此限制,最多只返回50条记录,笔者曾深受其害.
本文中涉及的内容的测试平台为VisualBaisc6.
0EnterpriseServicePack4.
中实现菜单分割导读:当一个菜单下子菜单项较多时,一打开菜单就出现了长长的菜单项,如果其他的菜单项下子菜单较少,就显得很不协调.
现在的一些软件还允许用户在已有的菜单中添加菜单项,这都会造成子菜单项过多的情况,如果能像某些软件那样将较多的子菜单项分成两列显示就显得美观多了.

在VB中要实现这一功能还是比较方便的,下面举例说明.
实现菜单分割这一功能需要使用API函数,思路是:首先获得菜单句柄,从而可得到其子菜单项数,然后将子菜单项数除以2,若子菜单项数为奇数,则将多余的一项划到第一部分,然后利用API函数SetMenuItemInfo重新设定菜单显示形式即可.

下面是一个例子.
首先用菜单生成器制做一个包括9个子菜单项的菜单,然后,在总体声明部分声明用到的API函数和常数,这些可以从API说明文件中复制.
OptionExplicit′菜单信息结构说明PrivateTypeMENUITEMINFOcbSizeAsLongfMaskAsLongfTypeAsLongfStateAsLongwIDAsLonghSubMenuAsLonghbmpCheckedAsLonghbmpUncheckedAsLongdwItemDataAsLongdwTypeDataAsStringcchAsLongEndType'所需的API函数和常数DeclareFunctionGetMenuLib"user32"(Bhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468yValhwndAsLong)AsLongPrivateDeclareFunctionGetMenuItemCountLib"user32"(ByValhMenuAsLong)_LongDeclareFunctionGetSubMenuLib"user32"(ByValhMenuAsLong,_ByValnPosAsLong)AsLongDeclareFunctionGetMenuItemInfoLib"user32"Alias_"GetMenuItemInfoA"(ByValhMenuAsLong,ByValunAsLong,_ByValbAsBoolean,lpmiiAsMENUITEMINFO)AsLongDeclareFunctionSetMenuItemInfoLib"user32"Alias_"SetMenuItemInfoA"(ByValhMenuAsLong,ByValuItemAsLong,_ByValfByPositionAsLong,lpmiiAsMENUITEMINFO)AsLongConstMIIM_TYPE=&H10RGB_STARTNEWCOLUMNWITHVERTBAR=&H20&ConstMFT_STRING=&H0&在窗体中添加一个命令按钮,Caption="分割菜单",双击写如下代码:PrivateSubCommand1_Click()DimrvAsLongDimhSubMenuAsLongDimmnuItemCountAsLongDimmIhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468nfoAsMENUITEMINFODimpadAsLong'获取菜单项句柄和子菜单项数=GetSubMenu(GetMenu(Me.
hwnd),0)mnuItemCount=GetMenuItemCount(hSubMenu)'将子菜单项分成两部分mnuItemCountMod2<>0Thenpad=1'取得当前菜单信息mInfo.
cbSize=Len(mInfo)mInfo.
fMask=MIIM_TYPEmInfo.
fType=MFT_STRINGmInfo.
dwTypeData=Space$(256)http://www.
1mpi.
comh=Len(mInfo.
dwTypeData)=GetMenuItemInfo(hSubMenu,(mnuItemCount2)+pad,True,mInfo)'按新格式显示菜单.
fType=RGB_STARTNEWCOLUMNWITHVERTBARmInfo.
fMask=MIIM_TYPE=SetMenuItemInfo(hSubMenu,(mnuItemCount2)+pad,True,mInfo)IfrvThenMsgBox"分割完毕"EndSub运行后按命令按钮,将发现子菜单项分成了两部分,左边五项,右边四项.
程序运行环境:中文WIN95,VB5.
0.
查询及删除重复记录的方法(一)、查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断select*frompeoplepeopleIdin(selectpeopleIdfrompeoplegroupbypeopleIdhavingcount(peopleId)>1)、删除表中多余的重复记录,重复记录是根据单个字段(http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468peopleId)来判断,只留有rowid最小的记录frompeoplewherepeopleIdin(selectpeopleIdfrompeoplegroupbypeopleIdhavingcount(peopleId)>1)rowidnotin(selectmin(rowid)frompeoplegroupbypeopleIdhavingcount(peopleId)>1)、查找表中多余的重复记录(多个字段)select*fromvitaea(a.
peopleId,a.
seq)in(selectpeopleId,seqfromvitaegroupbypeopleId,seqhavingcount(*)>1)、删除表中多余的重复记录(多个字段),只留有rowid最小的记录deletefromvitaea(a.
peopleId,a.
seq)in(selectpeopleId,seqfromvitaegroupbypeopleId,seqhavingcount(*)>1)rowidnotin(selectmin(rowid)fromvitaegroupbypeopleId,seqhavingcount(*)>1)、查找表中多余的重复记录(多个字段),不包含rowid最小的记录select*fromvitaea(a.
peopleId,a.
seq)in(selectpeopleId,seqfromvitaegroupbypeopleId,seqhavingcount(*)>1)rowidnotin(selectmin(rowid)fromvitaegroupbypeopleId,seqhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468havingcount(*)>1)(二)比方说在A表中存在一个字段"name",而且不同记录之间的"name"值有可能会相同,现在就是需要查询出在该表中的各记录之间,"name"值存在重复的项;SelectName,Count(*)FromAGroupByNameHavingCount(*)>1如果还查性别也相同大则如下:Name,sex,Count(*)FromAGroupByName,sexHavingCount(*)>1(三)方法一@maxinteger,@idintegerdeclarecur_rowscursorlocalforselect主字段,count(*)from表名groupby主字段havingcount(*)>;1opencur_rowscur_rowsinto@id,@maxwhile@@fetch_status=0begin@max=@max-1setrowcount@maxfrom表名where主字段=@idfetchcur_rowsinto@id,@maxendclosecur_rowssetrowcount0方法二有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略.
1、对于第一种重复,比较容易解决,使用selectdistinct*fromtableName就可以得到无重复记录的结果集.
如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除selectdistinct*into#Tmpfrohttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468mtableNamedroptabletableName*intotableNamefrom#Tmpdroptable#Tmp发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决.
、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集selectidentity(int,1,1)asautoID,*into#TmpfromtableNamemin(autoID)asautoIDinto#Tmp2from#TmpgroupbyName,autoIDselect*from#TmpwhereautoIDin(selectautoIDfrom#tmp2)最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)(四)查询重复*fromtablenamewhereidin(selectidfromtablenamegroupbyidcount(id)>1)、查找表中多余的重复记录(多个字段)select*fromvitaea(a.
peopleId,a.
seq)in(selectpeopleId,seqfromvitaegroupbypeopleId,seqhavingcount(*)>1)运行会产生问题,where(a.
peopleId,a.
seq)这样的写发是通不过的!
处理字符串中的字符导读:当要处理字符串中的每一个字符时,可以将字符串赋值到一个byte数组中进行操作.
要记住:每一个Unicode字符对应双字节.
这种方法通常要快许多,因为节http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468省了大量的Mid$函数操作以及大量的临时字符串空间.
下面的代码是统计字符串中空格数目的最快方法Dimb()asByte,countAsIntegerb()=source$i=0toUBound(b)StepLenB("A")Ifb(i)=32Thencount=count1Next请注意上面代码中LenB()函数的特殊用法:在VB4(32位)、VB5和VB6中它返回数值2,在VB4(16位)中返回数值1.
因此,我们就可以使用同一代码段,而无需#If编译指令.
创建位图菜单在通常的程序中菜单总是以文本的方式存在,有时候显得非常单调乏味.
如果能够在菜单中加入位图图形,将会极大地增加用户的使用兴趣.
本文介绍了如何使用位图制作菜单选项.
创建位图菜单创建位图菜单其实非常简单,它需要用到Windows应用程序编程接口(API)的一些菜单函数和位图函数,你需要将这些函数的声明包含在你的应用程序的标准模块中,具体的内容请参见样例程序.
步骤如下:使用函数GetSubMenu来提取子菜单项的句柄,并通过使用函数CreateCompatibleDC来创建一个兼容的设备环境描述表;在一个循环过程中通过使用CreateCompatibleBitmap函数,SelectObject函数以及BitBlt函数来分别将针对各个菜单项所载入的位图选入到兼容设备环境中;通过ModifyMenu函数绘制真正的位图菜单选项;使用DeleteDC函数来释放设备环境,以便其他的程序可以使用它们.
提取位图可以有多种方法,在本样例程序中在窗体上设置了四个图形框控件,使用它们载入4个预设的图标来作为菜单选项位图的源文件,当然你也可以使用其他的方法,例如使用LoadPicture函数来从磁盘装载位图.

样例程序在VisualBasic中开始一个新的工程,采用缺http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468省的方法建立Form1.
创建一个新的模块,采用缺省的方法建立Module1.
Bas.
将如下的声明语句和常量添加到Module1.
Bas模块中:OptionExplicitFunctionGetMenuLib"user32"(ByValhwndAsLong)AsLongDeclareFunctionGetSubMenuLib"user32"(ByValhMenuAsLong,ByValnPosAsLong)AsLongFunctionGetMenuItemIDLib"user32"(ByValhMenuAsLong,ByValnPosAsLong)AsLongFunctionModifyMenuLib"user32"Alias"ModifyMenuA"(ByValhMenuAsLong,ByValnPositionAsLong,ByValwFlagsAsLong,ByValwIDNewItemAsLong,ByVallpStringAsAny)AsLongFunctionCreateCompatibleDCLib"gdi32"(ByValhdcAsLong)AsLongDeclareFunctionDeleteDCLib"gdi32"(ByValhdcAsLong)AsLongDeclareFunctionCreateCompatibleBitmapLib"gdi32"(ByValhdcAsLong,ByValnWidthAsLong,ByValnHeightAsLong)AsLhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ongDeclareFunctionSelectObjectLib"gdi32"(ByValhdcAsLong,ByValhObjectAsLong)AsLongFunctionBitBltLib"gdi32"(ByValhDestDCAsLong,ByValxAsLong,ByValyAsLong,ByValnWidthAsLong,ByValnHeightAsLong,ByValhSrcDCAsLong,ByValxSrcAsLong,ByValySrcAsLong,ByValdwRopAsLong)AsLongPublicConstSRCCOPY=&HCC0020PublicConstMF_BYPOSITION=&H400&PublicConstMF_BITMAP=&H4&注意上面的声明语句需要书写在一行内.
在Form1上添加4个图形框控件,将它们的Name属性设置为Picture1,将它们的Index属性依次设置为0,1,2,3,将它们的AutoRedrew属性设置为True,将它们的AutoResize属性设置为Ture,以及将它们的Visable属性设置为False.

将上面的4个图形框控件的Picture属性依次设置为Face1.
ico,Face2.
ico,Face3.
ico,Face4.
ico.
在Form1上添加第一个菜单项,将它的标题设置为"[&F]文件",名称设置为mnuFile.
在其下添加一个子菜单项,将它的标题设置为"[&E]退出",名称设置为mnuExit.

在Form1上添加第二个菜单项,将它的标题设置为"[&A]脸谱",名称设置为mnuFace.
在其下添加4个子菜单项,分别将改4个子菜单项的名称设置为"[N]正常","[&S]微笑","[&L]大笑",以http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468及"[&O]悲伤".
将它们的名称设置为"mnuFaceSel",并相应将这4个子菜单项的索引设置为0,1,2,3.

将如下的代码添加到Form1的Form_Load事件中:PrivateSubForm_Load()DimnLoopCtrAsIntegerDimlResultAsLongDimhTempDCAsLongDimnWidthAsIntegerDimnHeightAsIntegerDimlTempIDAsLongDimhMenuIDAsLongDimlItemCountAsLongDimhBitmapAsLong=Picture1(nLoopCtr).
WidthScreen.
TwipsPerPixelXnHeight=Picture1(nLoopCtr).
HeightScreen.
TwipsPerPixelYhMenuID=GetSubMenu(GetMenu((Me.
hwnd)),1)=CreateCompatibleDC(Picture1(nLoopCtr).
hdc)FornLoopCtr=0To3=CreateCompatibleBitmap(Picture1(nLoopCtr).
hdc,nWidth,nHeight)=SelectObject(hTempDC,hBitmap)=BitBlt(hTempDC,0,0,nWidth,nHeight,(Picture1(nLoopCtr).
hdc),0,0,SRCCOPY)=SelectObject(hTempDC,lTempID)mnuFaceSel(nLoopCtr).
Caption=""=ModifyMenu(hhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468MenuID,nLoopCtr,MF_BYPOSITIONOrMF_BITMAP,GetMenuItemID(hMenuID,nLoopCtr),hBitmap)NextnLoopCtr=DeleteDC(hTempDC)EndSub将如下的代码添加到"退出"子菜单的单击事件中:PrivateSubmnuExit_Click(IndexAsInteger)SelectCaseIndexCase0UnloadMeEndSelectEndSub运行该样例程序,单击"脸谱"菜单,则会看到由4个脸谱图标所形成的位图子菜单项,如图1所示.
单击"文件""退出"菜单可退出应用程序.
关闭vb6.
0时弹出内存冲突错误解决办法前几天重装了系统,vb6.
0自然也重新安装了,可是居然发现了问题,每次关闭VB时都弹出错误提示,提示"0x0043f08f"指令引用的"0x608af85c"内存.
该内存不能为"read":这个问题在以前默认安装vb6.
0从来没有出现过,问题遗留了好几天都没解决的了,包括删除VB6再重装.
后来无意中发现VB6.
0默认加载了SourceCodeControl,它是SourceSafe的控制插件,会在保存完窗体和项目后询问是否将工程加入到SourceSafe(AddthisprojecttoSourceSafe),而我这次安装vb6.
0的时候并没有安装SourceSafe,估计问题出现在这里了.
那么就先取消它的加载试试,依次单击菜单栏上的"外接程序"--"外接程序管理器",打开外接程序管理器选中SourceCodeControl项,然后在下面的"加载行为"的多选去掉"在启动加载"和"加载/卸载"的勾勾.
关闭VB6.
0,此时程序已经加载到内存中了,所以还会提示引http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468用内存错误,忽略它.
再次运行vb6.
0,现在关闭它,不提示内存错误了吧.

我们已经了解了引起故障的原因,由此我们可以知道还有一个解决办法,就是用vb6.
0的安装文件重新安装SourceSafe.
谢谢你关注巧巧读书网编程频道.
汉化ActiveReports2.
0界面用法很简单:在要显示ActiveReports窗体前,加入:CreportActiveReport1'ActiveReport1是AR的窗体.
PublicSubCreport(AReportAsActiveReport)'汉化ActiveReport'以下适用2.
0WithAReport.
ToolBar.
Tools.
Item(0).
Tooltip="各页目录".
ToolBar.
Tools.
Item(2).
Caption="打印.
.
.
".
ToolBar.
Tools.
Item(2).
Tooltip="打印报表".
ToolBar.
Tools.
Item(4).
Tooltip="拷贝".
ToolBar.
Tools.
Item(6).
Tooltip="查找".
ToolBar.
Tools.
Item(8).
Tooltip="单页显示".
ToolBar.
Tools.
Item(9).
Tooltip="多页显示".
ToolBar.
Tools.
Item(11).
Tooltip="缩小".
ToolBar.
Tools.
Item(12).
Tooltip="放大".
ToolBar.
Tools.
Item(15).
Tooltip="上一页".
ToolBar.
Tools.
Item(16).
Tooltip="下一页".
ToolBar.
Tools.
Item(19).
Tooltip="后退".
ToolBar.
Tools.
Item(19).
http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468Caption="后退".
ToolBar.
Tools.
Item(20).
Tooltip="前进".
ToolBar.
Tools.
Item(20).
Caption="前进"EndWithEndSub获得某一台网络打印机有几份等待打印的报表当我们要打印报表时,如果打印机是本机的打印机的话,当然马上就会将报表打印出来,反正打印机就只有您一个人在使用而已!
但是如果是在一个人数很多的公司或企业时,往往就必须很多人来分享某一部打印机了,而且打印机也不一定就放在举目可及之处!

当您将报表丢到网络打印机之后,由于不一定看得到打印机,您必须特别到摆放打印机的地方去拿报表,这时候您最关心的,就是报表印了没有,如果还没有的话,那还有几份还没打印的报表排在您的报表之前呢下面这一段程序,可以让您知道某一台网络打印机尚有几份等待打印的报表在您的程序丢出报表的同时,您可以告诉您的User,他的报表排在第几份!
′在.
bas文件中加入以下声明及模组:′ConstantsDefinitionConstCCHDEVICENAME=32PublicConstCCHFORMNAME=32ConstPRINTER_ACCESS_ADMINISTER=&H4PublicConstPRINTER_ACCESS_USE=&H8′TypesDefinitionPublicTypeDEVMODEAsString*CCHDEVICENAMEdmSpecVersionAsIntegerdmDriverVersionAsIntegerdmSizeAsIntegerdmDriverExtraAsIntegerdmFieldsAsLongAsInteghttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468erdmPaperSizeAsIntegerdmPaperLengthAsIntegerdmPaperWidthAsIntegerdmScaleAsIntegerdmCopiesAsIntegerAsIntegerdmPrintQualityAsIntegerdmColorAsIntegerdmDuplexAsIntegerAsIntegerdmTTOptionAsIntegerdmCollateAsIntegerAsString*CCHFORMNAMEdmUnusedPaddingAsIntegerdmBitsPerPelAsLongdmPelsWidthAsLongdmPelsHeightAsLongdmDisplayFlagsAsLongdmDisplayFrequencyAsLongEndTypeTypePRINTER_DEFAULTSpDatatypeAsStringpDevModeAsDEVMODEDesiredAccessAsLongEndType基于VBA组卷中自动排版的实现导读:建立完善的题库是课程建设的一项重要工作,当数据库的形式进行题库管理,通过编写抽题程序,在分类明确、题量丰富的题库支持下,实现自动组卷并非难事.
试卷一般都采用Word文档,若采用VBA编程,要用程序将试题写入到Word文档,可以通过引用MicrosoftWord9.
0ObjectLibrary中的相关对象来实现:图片、图形、文本框及艺术字等可利用Shapes集合对象的相应方法加入到文档中!
一、引言建立完善的题库是课程建设的一项重要工作,当数据库的形式进行题库管理,通过编写抽题程序,在分类明确、题量丰富的题库支持下,实现自动组卷并非难事.
试卷一般都采用Word文档,若采用VBA编程,要用程序将试题写入到Whttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ord文档,可以通过引用MicrosoftWord9.
0ObjectLibrary中的相关对象来实现:图片、图形、文本框及艺术字等可利用Shapes集合对象的相应方法加入到文档中;表格也可以通过Tables集合对象的Add方法加入,其大小、位置等排版信息都可以以参数的形式传入;而文字部分的内容也能以字符串的形式通过调用Content对象的InsertAfter方法插入,排版时对其字型、字体、字号及段落格式则可以利用Font对象及Paragraph对象的属性或方式进行设置.
选择题是各类试卷中经常出现的题型,而它的排版有其特殊性,因为选择题的四个选项根据其长度有可能排成四段(行),也可能排成两行,每行两个选项,且它对段落缩进及上、下行中选项的对齐等都有一定的要求.

这里要解决的几个问题是:.
题干部分的题号对齐,尤其是一位数题号与两位数题号(如第9题与第10题);前、后题题干内容的第一个字符对齐;题干部分作为段落要采用悬挂缩进、且缩进量应合适.
2.
若选项由四段(行)构成,则每段应有左缩进、缩进量与题干部分的悬挂缩进量相同,同时,选项内容的长度也有可以超过一行(如第10题中的选项C),所以对选项也要设置悬挂缩进、且缩进量应合适.

.
若选项由两行构成(如第11题中的四个选项),则上一行的选项C与下一行的选项D应对齐.
二、定义选择题的数据结构程序设计中为了便于将选择题作为函数的参数传递,应定义选择题的数据类型的结构,选择题的结构通常由题干及四个选项构成,具体定义如下:PublicTypeChoiceAsString'题干内容,不包括题号ChoiceAAsString'选项A的内容ChoiceBAsString'选项B的内容ChoiceCAsString'选项C的内容ChoiceDAsString'选项D的内容EndType三、页面设置与段落格式首先进http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468行页面设置,页面上边距、下边距、左边距、右边距分别设为1英寸、1英寸、1.
25英寸、1.
25英寸,默认制表位长度为0.
33英寸.
WithActiveDocument.
PageSetup.
TopMargin=InchesToPoints(1).
BottomMargin=InchesToPoints(1).
LeftMargin=InchesToPoints(1.
25).
RightMargin=InchesToPoints(1.
25)EndWith.
DefaultTabStop=InchesToPoints(0.
33)为了对题干部分进行排版,先自定义一个过程insTabIndent,其功能是根据第一个参数str1传入的题干内容及第二个参数Num传入的本题题号,在题干内容前加上题号,若Num为0,则表示不加题号;在题号后设置一个制表位,使前、后题的题干内容的第一个字符对齐;对题干所在段落设置悬挂缩进一个制表.

SubinsTabIndent(str1AsString,NumAsInteger)DimsAsStringIfNum<10Thens=""Trim(str(Num))".
"Elses=Trim(str(Num))".
"Num=0Thens=""myRange=appObj.
ActiveDocument.
ContentmyRange.
CollapseDirection:=wdCollapseEndmyRange.
InsertAfters&vbTab&str1myRange.
InsertParagraphAfterhttp://www.
1mpi.
com="宋体"myRange.
Font.
Size=12://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468armyRange.
ParagraphFormat.
TabHangingIndent1'悬挂缩进1个制表位EndSub为了对选项进行排版,自定义一个过程insLeftAndHangingIndent,其功能是根据参数str1传入的选项内容,将其作为段落写入Word文档,设置字型、字体、字号及左缩进和悬挂缩进.

SubinsLeftAndHangingIndent(str1AsString)SetmyRange=ActiveDocument.
ContentmyRange.
CollapseDirection:=wdCollapseEndmyRange.
InsertAfterstr1myRange.
InsertParagraphAfterhttp://www.
1mpi.
com="宋体"myRange.
Font.
Size=12'小四'设置左缩进与悬挂缩进.
ParagraphFormat.
FirstLineIndent=CentimetersToPoints(-0.
64)myRange.
ParagraphFormat.
LeftIndent=CentimetersToPoints(1.
48)EndSub四、选择题的写入及排版如果四个选项按四段(行)进行排版,则只要通过调用前面所定义的两个过程就能实现,但四个选项要按两行排版则有两种方法可供选择:一是分节分栏法:将四个选项按四段写入Word文档,并将它们设置成单独的一节,再采用分成两栏的方法实现;二是直接写入排版法:在同一行的两个选项之间插入若干个制表位实现对齐,编程中将涉及写入点的定位问题.

、分节分栏法选择题写入Word文档及排版操作在自定义过程insSelect中实现,传入参数mObj内封装了一道选择题;题号通过参数n传入;参数max传入的值是选项内容字符数的临界值,即当四个选项内容中字符数最多者如果超过了max,则四个选项排版成四段(行),否则排成http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468两行.
其中用到的函数maxLen(mObj)返回值表示选择题mObj的四个选项内容中字符数的最大值.

SubinsSelect(mObjAsChoice,ByRefnAsInteger,maxAsInteger)insTabIndentmObj.
Sentence,n'写入题干内容及题号maxLen(mObj)>maxThen'按四段(行)并采用左缩进及悬挂缩进写入insLeftAndHangingIndent"A)"mObj.
ChoiceA"B)"mObj.
ChoiceBinsLeftAndHangingIndent"C)"mObj.
ChoiceCinsLeftAndHangingIndent"D)"mObj.
ChoiceDActiveDocument.
Content.
InsertParagraphAftern=n1'选项按缩进一个制表位形式写入,为后面的分节分栏做准备SettempRange=ActiveDocument.
Content.
CollapseDirection:=wdCollapseEnd.
InsertAftervbTab&"A)"&mObj.
ChoiceAtempRange.
InsertParagraphAfter.
InsertAftervbTab&"B)"&mObj.
ChoiceBtempRange.
InsertParagraphAfter.
InsertAftervbTab&"C)"&mObj.
Chohttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468iceCtempRange.
InsertParagraphAfter.
InsertAftervbTab&"D)"&mObj.
ChoiceDtempRange.
InsertParagraphAfterhttp://www.
1mpi.
com="宋体"tempRange.
Font.
Size=12'小四=n1'题号增1,为写入下一题做准备tempRange.
Select'选定四个选项所在的区域ActiveWindow.
View.
SplitSpecial<>wdPaneNoneThenActiveWindow.
Panes(2).
CloseEndIfActiveWindow.
ActivePane.
View.
Type<>wdPrintViewThenActiveWindow.
ActivePane.
View.
Type=wdPrintViewEndIf'在选定区域的起始位置和末尾位置插入分节符.
Range(Start:=Selection.
Start,End:=Selection.
Start).
_InsertBreakType:=wdSectionBreakContinuousSelection.
Start=Selection.
Start1.
Range(Start:=Selection.
End,_:=Selection.
End).
InsertBreakType:=wdSectionBreakContinuous'将选定的文本分成两栏Selection.
PageSetup.
TextColumns.
SetCountNumColumns:=2.
EvenlySpaced=True.
LineBetween=False://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ar.
Width=CentimetersToPoints(6.
95).
Spacing=CentimetersToPoints(0)EndWith.
Content.
InsertParagraphAfterEndIfEndSub2、直接插入排版法这种方法是将选项A与选项C作为同一行写入、选项B与选项D作为同一行写入,关键在于要求上一行的C选项与下一行的D选项要求对齐,定位方法是在选项A的末尾与选项C、选项B的末尾与选项D之间插入若干个制表位,模拟手工调整的方法进行对齐.
但上、下行要分别插入多少个制表位才能对齐呢这要借助于Selection对象的Information属性进行检测.
http://www.
1mpi.
comrmation(wdHorizontalPositionRelativeToPage)可以返回指定的所选内容或区域的水平位置,该位置是所选内容或区域的左边与页面的左边之间的距离,以磅为单位(72磅=1英寸).
具体方法是每插入一个制表位就将选定区域收缩为选定区域后一个字符,同时检测它距页面的左边之间的距离,直到距离达到某个设定值时就停止插入.
具体程序如下:"A)"mObj.
ChoiceA,0'写入选项Ax=appObj.
ActiveDocument.
Content.
Paragraphs.
Count–1'x记录下选项A所在的段落数'每次循环插入一个制表位,并在循环条件中进行位置检测DotempRange=.
ActiveDocument.
Range(appObj.
ActiveDocument.
Content.
Paragraphs(x).
_Range.
End-1,appObj.
ActiveDocument.
Content.
Paragraphs(x).
Range.
End)tempRange.
Select.
TypeTextvbTabhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468'在选项A的内容后插入一个制表位SettempRange=.
ActiveDocument.
Range(appObj.
ActiveDocument.
Content.
Paragraphs(x).
_Range.
End-1,appObj.
ActiveDocument.
Content.
Paragraphs(x).
Range.
End)tempRange.
Select'选定区域设为当前区域的最后位置While(http://www.
1mpi.
comrmation(wdHorizontalPositionRelativeToPage)<280)'当检测到写入点位置距与页面左边的距离超过280磅时停止插入制表位Selection.
TypeText"C)"mObj.
ChoiceC'写入选项C'以下处理下一行的选项B和选项D,方法同上"B)"mObj.
ChoiceB,0'写入选项Bx=appObj.
ActiveDocument.
Content.
Paragraphs.
Count-1DotempRange=.
ActiveDocument.
Range(appObj.
ActiveDocument.
Content.
Paragraphs(x).
_Range.
End-1,appObj.
ActiveDocument.
Content.
Paragraphs(x).
Range.
End)tempRange.
Select.
TypeTextvbTabSettempRange=.
ActiveDocument.
Range(appObj.
ActiveDocument.
Content.
Paragraphs(x).
_Range.
End-1,appObj.
ActiveDocument.
Content.
Paragraphs(http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468x).
Range.
End)tempRange.
SelectWhile(http://www.
1mpi.
comrmation(wdHorizontalPositionRelativeToPage)<280)Selection.
TypeText"D)"mObj.
ChoiceD'写入选项DappObj.
ActiveDocument.
Content.
InsertParagraphAfter五、结语前述两种选择题的排版方式均已在实际的试卷自动生成系统的排版应用中进行实测,测试表明两种方法都能得到较为规范、美观的排版效果.
分节分栏法实现思想较为简单,但由于生成的文档中有大量的分节符,如果对于生成的文档要作手工调整,可能会带来一点麻烦;直接插入排版法的好处是不分节,便于后期的手工调整,但生成文档的速度稍慢.

参考文献.
MicrosoftWord2000VisualBasic对象模型帮助系统[DK].
孟祥瑞.
VisualBasic6.
0程序设计[M].
华东理工大学出版社,2005监控网页中元素的事件对编写脚本熟悉的读者都知道页面中可以添加脚本响应元素的事件,例如超链接的OnClick事件,图片的OnMouseMove事件,我们也可以使VB程序响应这些事件.
下面是一个VB响应页面中按钮的Click事件的代码:首先建立一个新工程,在Form1中加入一个Webbrowser控件,然后在Form1中加入以下代码:ExplicitSubSome_Procedure()MsgBox"你点击了按钮.
"EndSubSubForm_Load()'下载空页面.
Navigate2"about:blank"EndSubPrivateSubWebBrowser1_Docuhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468mentComplete(ByValpDispAsObject,URLAsVariant)'建立事件响应类cfForwardAsclsForward'定义在浏览器中显示的HTML代码,其中包含一个按钮btnMyButtonDimsHTMLAsString="<P>Thisissometext.
</P>"=sHTML&"<P>Andhereisabutton.
</P>"sHTML=sHTML&"<BUTTONID=btnMyButton>"sHTML=sHTML&"Clickthisbutton.
</BUTTON>"'将HTML代码写入浏览器.
Document.
body.
innerHTML=sHTML'将事件响应类连接到页面的按钮btnMyButton上SetcfForward=NewclsForward.
Set_DestinationMe,"Some_Procedure".
Document.
All("btnMyButton").
onclick=cfForwardEndSub向工程中添加一个ClassModule,ClassModule的Name属性设定为clsForward,在clsForward中添加以下代码:OptionExplicitoObjectAsObjectDimsMethodAsStringbInstantiatedAsBooleanPrivateSubClass_Initialize()http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468bInstantiated=FalseEndSubSubSet_Destination(oInObjectAsObject,sInMethodAsString)SetoObject=oInObjectsMethod=sInMethodbInstantiated=TrueEndSubSubMy_Default_Method()IfbInstantiatedThenoObject,sMethod,VbMethodEndIfEndSub运行程序,点击Webbrowser中的"Clickthisbutton"按钮.
程序就会弹出消息框提示"你点击了按钮.
"简单讲解VisualBasic开发分布式本文向大家介绍VB开发分布式,可能好多人还不了解VB开发分布式,没有关系,看完本文你肯定有不少收获,希望本文能教会你更多东西.
微软推出的VB是一个功能强大的开发平台.
它在"代码重用性"上地加强是一个引人注目的特点.
我们可以将需要多次重复使用的功能单元开发成activex组件(activexcontrol,activexexe,activexdll),然后在新程序中象使用vb标准控件及类一样使用这些组件.
activex组件给开发网络应用带来很大方便.
我们可以将这些组件分布在网络的不同机器上,构成分布式应用,就好象所有组件都在同一台机器上一样.
很多朋友都有开发本地activex组件的经验,本文将结合实例介绍一下如何将activex组件分布在网络上构成分布式应用.

一、概述"activex"是微软为分布式计算制定的一套标准,它的前身就是大家所熟知的"oleautomation".
当分布式应用通过网络通讯时,activex可以使用两种不同的机制对客户请求作出响应.
一种称为"分布组件对象模式(dcom)",只可以在windowsnt和windows95上使用;另一种是"远程自动http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468化(remoteautomation)",它可以在16位环境下构造分布式应用.
这两种分布式机制,有着极其引人的特点:与组件物理位置的无关性.
也就是说,当你构造一个activex组件时,无需知道它将分布在那一台机器上.
同样的组件,即可以将它放在本机,也可以将它分布在其它机器上而不需要从新编译.
这样,根据网络的性能和网络结构的变化,我们可以方便的调整组件的分布策略.

当然,用activex构建分布式应用的各个独立组件,还有其它优点:构造远程组件和构造本地组件的编程方法一模一样,无须特殊的工程经验.
可以用activex组件在服务器端实现复杂的商业规则.
比起用dbms(如sqlserver)来完成同样的工作,我们有更好地编程、维护、排错手段.
有大量的商业组件可以使用.
而且这样的组件会越来越多.
我们只需将特殊的商业规则开发成组件,与购买的组件配合使用.
二、开发和调试开发分布式组件和开发本地组件相同,调试也可以在本地完成,本文不在赘述.
(可以参看VB所带的例子:_cli.
vbp客户端程序;_svr.
vbp服务器程序.
)在开发分布式服务器段组件时,请注意下列问题:服务器端的project应为activexexe(进程外的activex组件).
这也很容易理解,不可能在两台机器上完成同一个进程,所以,不可能使用activexdll(进程内的组件).
在projectproperties对话框的组件栏目下,应设为remoteserverfile.
这样,在程序编译时会生成一个vbr文件,在生成安装盘时要用.
大家知道,windows程序在系统注册表中有注册,此文件与注册有关.
属性应设为mutiuse,以便多个客户应用可以使用它.
强制和防止窗口重画导读:这个例子告诉你如何强制窗口的一部分重画.
有时这是必须的,上学吧提示当你试验自己重画控件的技术,或者已经使用http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468了LockWindowUpdate这个API函数以阻止控件重画时(参见"防止一个窗口重画").

新建一个项目,添加一个module,然后粘贴下列代码:PrivateTypeRECTLeftAsLongTopAsLongRightAsLongBottomAsLongEndTypeTypePOINTAPIXAsLongYAsLongEndTypeDeclareFunctionGetWindowRectLib"user32"(ByValhWndAsLong,lpRectAsRECT)AsLongDeclareFunctionGetClientRectLib"user32"(ByValhWndAsLong,lpRectAsRECT)AsLongPrivateDeclareFunctionInvalidateRectLib"user32"(ByValhWndAsLong,lpRectAsRECT,ByValbEraseAsLong)AsLongDeclareFunctionScreenToClientLib"user32"(ByValhWndAsLong,lpPointAsPOINTAPI)AsLongSubRepaintWindow(ByRefobjThisAsObject,OptionalByValbClientAreaOnlyAsBoolean=True)DimtRAsRECTDimtPAsPOINTAPI(bClientAreaOnly)ThenobjThis.
hWnd,tRElse://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468parobjThis.
hWnd,tRtP.
X=tR.
Left:tP.
Y=tR.
TopScreenToClientobjThis.
hWnd,tPtR.
Left=tP.
X:tR.
Top=tP.
YtP.
X=tR.
Right:tP.
Y=tR.
BottomScreenToClientobjThis.
hWnd,tPtR.
Right=tP.
X:tR.
Bottom=tP.
YEndIfobjThis.
hWnd,tR,1EndSub为了试试重画,在窗体上添加一个ListBox和一个Command.
把ListBox拉得大一些,这样效果比较明显.
再加入下列代码:PrivateSubCommand1_Click()RepaintWindowList1EndSubSubForm_Load()DimiAsLongFori=1To200.
AddItem"TestItem"&iNextiEndSub当你单击Command按钮,ListBox的客户区将全部重画.
对于ListBox,这种效果并不十分明显地显示,但这段代码放在这里主要目的,是让你在遇上有东西不能恰当地重画它自己时可以有办法解决.

防止窗口重画WXJ_Lake编译这则代码演示了如何防止窗口的一部分重画.
当你要往ListBox或ListView这样的控件里添加许多项时,暂缓重画可以相当地提高处理速度.
在我的系统上,往一个ListBox中加10000项比原来提速30%.

新建一个项目,添加一个ListBox、一个Command和一个CheckBox.
把CheckBox的Caption设为"&LockUpdate",Command的Capthttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ion设为"&Load".
然后,把下列代码粘贴到窗体中:PrivateDeclareFunctionLockWindowUpdateLib"user32"(ByValhwndLockAsLong)AsLongDeclareFunctiontimeGetTimeLib"winmm.
dll"()AsLongPrivateSubCommand1_Click()DimiAsLongDimlTImeAsLonglTIme=timeGetTime()(Check1.
Value=Checked)ThenLockWindowUpdateList1.
hWndEndIf.
Cleari=1To10000.
AddItem"Test"&iNexti(Check1.
Value=Checked)ThenLockWindowUpdate0List1.
RefreshEndIf"Time:"&timeGetTime-lTImeEndSub当你单击Command按钮,代码将往ListBox中添加10000项.
如果"LockUpdate"的复选框被选中,Windows将在往ListBox中添加项时防止它的重画.
操作结束后,会弹出一个对话框报告运行时间.
使用VB截获WIN98系列下的IP数据包因广大VB爱好者开发捕获IP数据包的需要,我花了一个下午的工夫,终于把它整里出来了,由于时间关系,以下的数据分析部分写的不是很详细.
以下代码在WIN98VB6.
0上测试通过,主函数部分比较简单,1.
打开设备驱动程序,2.
绑定网卡,3.
设置捕获数据,http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a384684.
循环截获IP包.

由于在WIN98下捕获IP数据包,必须要使用VXD技术,它不像WIN2000(可以参照前二天写的,"使用VB捕获WIN2000下的IP数据包"),捕获IP数据包不需要VXD文件,单单只要使用VB就可以了.
因为编写VXD的步骤比较麻烦,在以下的源代码中,直接使用IPMAN中的VPACKET.
VXD这个驱动程序.
可以在网上比较容易得到,需要的朋友也可以跟我联系.
以下包含了截获数据包的所有源代码,只要把下面的代码放到一个模块(.
BAS)文件中就可以了,里面信息截获到以后,并没有对数据做太多的处理,所有的数据都放在OutBuff数组中,只是简单的分离出了以太网头部m_EtherPacketHead,IP包头部m_IPPacketHead,其中程序中只是简单的输出了源IP地址,目的IP地址,需要更进一不分析里面的内容,可以参照别的资料.
在这里为了程序尽量的简单,所以不过多的牵涉.
进一步分析的内容可以添加到输出内容的附近代码就可以了.

源代码开始,放到.
bas中即可以测试-DeclareFunctionCloseHandleLib"kernel32"(ByValhObjectAsLong)AsLongDeclareFunctionCreateFileLib"kernel32"Alias"CreateFileA"(ByVallpFileNameAsString,ByValdwDesiredAccessAsLong,ByValdwShareModeAsLong,lpSecurityAttributesAsLong,ByValdwCreationDispositionAsLong,ByValdwFlagsAndAttributesAsLong,ByValhTemplateFileAsLong)AsLongPrivateDeclareFunctionhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468CreateEventLib"kernel32"Alias"CreateEventA"(ByVallpEventAttributesAsLong,ByValbManualResetAsLong,ByValbInitialStateAsLong,ByVallpNameAsString)AsLongPrivateDeclareFunctionWaitForMultipleObjectsExLib"kernel32"(ByValnCountAsLong,lpHandlesAsLong,ByValbWaitAllAsLong,ByValdwMillisecondsAsLong,ByValbAlertableAsLong)AsLongPrivateConstINFINITE=&HFFFFConstGENERIC_WRITE=&H40000000PrivateConstGENERIC_READ=&H80000000PrivateConstOPEN_EXISTING=3ConstFILE_ATTRIBUTE_NORMAL=&H80ConstFILE_FLAG_OVERLAPPED=&H40000000PrivateConstFILE_FLAG_DELETE_ON_CLOSE=&H4000000PrivateConstERROR_IO_INCOMPLETE=996&ConstNDIS_PACKET_TYPE_DIRECTED=&H1PrivateConstIOCTL_PROTOCOL_SET_OID=&H80000004PrivateConstIOCTL_PROTOCOL_READ=&H80http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468000010ConstOID_GEN_CURRENT_PACKET_FILTER=&H1010EPrivateConstWAIT_FAILED=-1PrivateTypeOVERLAPPEDInternalAsLongInternalHighAsLongoffsetAsLongOffsetHighAsLonghEventAsLongEndTypeEtherAddrAddrByte1AsByteAddrByte2AsByteAddrByte3AsByteAddrByte4AsByteAddrByte5AsByteAddrByte6AsByteEndTypeEtherPacketHeadDestEtherAsEtherAddrSourEtherAsEtherAddrServTypeAsIntegerEndTypeTypeIPAddr(0To3)AsByteEndTypeIPPacketHeadVerHLenAsByteType1AsByteTtlLenAsIntegerIdAsIntegerTTLAsByteProtoAsByteChkSumAsIntegerSourIPAsIPAddrDestIPAsIPAddrEndTypePACKET_OID_DATAOidAsLongLengthAsLongdataAsByteEndTypeDeclareFunctionDeviceIoControlAsStringLib"kernel32"Alias"Devicehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468IoControl"(ByValhDeviceAsLong,ByValdwIoControlCodeAsLong,ByVallpInBufferAsString,ByValnInBufferSizeAsLong,ByVallpOutBufferAsString,ByValnOutBufferSizeAsLong,lpBytesReturnedAsLong,lpOverlappedAsOVERLAPPED)AsLongDeclareFunctionDeviceIoControlLib"kernel32"(ByValhDeviceAsLong,ByValdwIoControlCodeAsLong,lpInBufferAsAny,ByValnInBufferSizeAsLong,lpOutBufferAsAny,ByValnOutBufferSizeAsLong,lpBytesReturnedAsLong,lpOverlappedAsOVERLAPPED)AsLongDeclareFunctionGetOverlappedResultLib"kernel32"(ByValhFileAsLong,lpOverlappedAsOVERLAPPED,lpNumberOfBytesTransferredAsLong,ByValbWaitAsLong)AsLongDeclareSubCopyMemoryLib"kernel32"Alias"RtlMoveMemory"(DestinationAsAny,SourceAsAny,ByValLengthAsLong)PrivateDeclareSubZeroMemoryLib"kernel32"Alias"Rthttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468lZeroMemory"(ByValdestAsLong,ByValnumbytesAsLong)DeclareFunctionGetLastErrorLib"kernel32"()AsLongConstETHER_PROTO_IP=&H8ConstIP_PROTO_TCP=&H6ConstETHER_HEAD_LEN=14ConstIP_HEAD_BYTE_LEN=20DimbFirstAsBooleanConstSYSERR=-1BUFFER_SIZE=16384ConstnREAD=1TypePacketTablehEventAsLongActiveAsBooleanOverlapAsOVERLAPPEDSizeAsLong(BUFFER_SIZE)AsByteLengthAsLongEndTypeRECV_MAX=32RecvTab(RECV_MAX)AsPacketTableDimEventTab(RECV_MAX)AsLongDimInBuff(1514)AsByteDimOutBuff(1514)AsByteBind(hVxDAsLong,inBufferAsString)AsBooleanDimhEventAsLongDimcbRetAsLongovlpAsOVERLAPPEDDimresultAsLongDimcbInAsLongcbIn=5=CreateEvent(0,1,0,vbNullString)IfhEvent=0ThenBindhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468=False"errbind"ExitFunctionEndIf.
hEvent=hEvent'((0x8000)<<16)|((0)<<14)|((7)<<2)|(0))ConstIOCTL_PROTOCOL_BIND=&H8000001Cresult=DeviceIoControlAsString(hVxD,_IOCTL_PROTOCOL_BIND,_ByValinBuffer,_cbIn,_inBuffer,_cbIn,_cbRet,_ovlp)(result=0)ThenGetOverlappedResult(hVxD,ovlp,cbRet,True)EndIfCloseHandle(hEvent)Bind=TrueEndFunctionFunctionQueryPacket(ByValhVxDAsLong,ByValioctlAsLong,ByValcbInAsLong,ByValcbOutAsLong)AsLongDimhEventAsLongDimcbRetAsLongovlpAsOVERLAPPEDDimresultAsLong=CreateEvent(0,1,0,vbNullString)IfhEvent=0ThenQueryPacket=FalseMsgBox"errbind"ExitFunctionEndIf.
Internal=0ovlp.
InternalHigh=0ovlp.
offset=0http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ovlp.
OffsetHigh=0ovlp.
hEvent=hEvent'ioc=&H80000018result=DeviceIoControl(hVxD,ioctl,InBuff(0),cbIn,InBuff(0),cbOut,cbRet,ovlp)result=0Then(GetLastError()=ERROR_IO_PENDING)ThenMsgBox"Ok0"ElseCloseHandle(hEvent)ExitFunctionEndIf(0=GetOverlappedResult(hVxD,ovlp,cbRet,0))ThenIf(GetLastError()=ERROR_IO_INCOMPLETE)ThenMsgBox"ok2"ElseCloseHandle(hEvent)ExitFunctionEndIfEndIf=GetOverlappedResult(hVxD,ovlp,cbRet,1)EndIf=cbRetEndFunctionQueryOid(hVxDAsLong,ulOidAsLong,ulLengthAsLong)AsLongDimcbInAsLongcbIn=14ulLengthDimcbRetAsLongOidDataAsPACKET_OID_DATAOidData.
Oid=ulOid.
Length=ulLengthOidData.
data=0DimioctlAsLongOID_802_3_PERMANENT_ADDhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468RESS=&H1010101ConstIOCTL_PROTOCOL_QUERY_OID=&H80000000ConstIOCTL_PROTOCOL_STATISTICS=&H80000008IfulOid>=OID_802_3_PERMANENT_ADDRESSThenioctl=IOCTL_PROTOCOL_QUERY_OIDElse=IOCTL_PROTOCOL_STATISTICSEndIfCopyMemory(InBuff(0),OidData,cbIn)cbRet=QueryPacket(hVxD,ioctl,cbIn,cbIn)QueryOid=cbRetEndFunctionGetHardEtherAddr(ByValhVxDAsLong,petheraddrAsEtherAddr)AsBooleannretAsLongOID_802_3_CURRENT_ADDRESS=&H1010102=QueryOid(hVxD,OID_802_3_CURRENT_ADDRESS,6)If(nret>0)ThenCopyMemory(petheraddr,InBuff(8),6)GetHardEtherAddr=TrueElse=FalseEndIfFunctionFunctionSetOid(ByValhVxDAsLong,ByValulOidAsLong,ByValulLengthAsLong,ByValdataAsLong)AsLongDimcbInAsLongDimcbRetAsLong://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468DimOidDataAsPACKET_OID_DATADimioctlAsLongcbIn=32If(ulOid=OID_GEN_CURRENT_PACKET_FILTER)Thenioctl=IOCTL_PROTOCOL_SET_OIDOidData.
Oid=ulOid.
Length=ulLengthOidData.
data=1InBuff(0),OidData,cbIn=QueryPacket(hVxD,ioctl,cbIn,cbIn)SetOid=0EndFunctionGetPacket(ByValhVxDAsLong,ByValioctlAsLong,ByValcbInAsLong,ByValcbOutAsLong)AsLongDimhEventAsLongDimcbRetAsLongovlpAsOVERLAPPEDDimresultAsLong=CreateEvent(0,1,0,vbNullString)IfhEvent=0ThenGetPacket=0ExitFunctionEndIf.
hEvent=hEventresult=DeviceIoControl(hVxD,ioctl,InBuff(0),cbIn,OutBuff(0),cbOut,cbRet,ovlp)(result=0)ThenCallGetOverlappedResult(hVxD,ovlp,cbRet,True)GetPacket=cbRetEndFunctionRecvPacket(ByValhVxDAsLong,ByValhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468pbufAsVariant)AsLongDimhEventAsLongIAsLong,JAsLong,KAsLongDimlen1AsLongIf(bFirst)ThenI=0ToRECV_MAX-1=CreateEvent(0,1,0,vbNullString)If(hEvent=0)ThenMsgBox"ERROR"RecvPacket=SYSERRExitFunctionEndIf(I).
hEvent=hEventRecvTab(I).
Size=BUFFER_SIZERecvTab(I).
Active=TrueRecvTab(I).
Type=nREADEventTab(I)=hEventRecvStart(hVxD,RecvTab(I))Next=FalseEndIf=WaitForMultipleObjectsEx(RECV_MAX,EventTab(0),0,INFINITE,0)If(I=WAIT_FAILED)Then"errorWaitForMultipleObjectsEx"RecvPacket=SYSERRExitFunctionEndIfJ=0ToRECV_MAX-1(EventTab(I)=RecvTab(J).
hEvent)ThenExitForNextK=J(RecvTab(K).
Type=nREADAndRecvTab(K).
Active=True)ThenGetOverlappedResult(hVxD,Rehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468cvTab(K).
Overlap,RecvTab(K).
Length,0)If(RecvTab(K).
Length>BUFFER_SIZE)ThenRecvTab(K).
Length=BUFFER_SIZECallCopyMemory(OutBuff(0),RecvTab(K).
Buffer(0),RecvTab(K).
Length)len1=RecvTab(K).
LengthCloseHandle(RecvTab(K).
hEvent)ForJ=I1ToRECV_MAX-1EventTab(I)=EventTab(J)I=I1Next=CreateEvent(0,1,0,vbNullString)If(hEvent=0)Then"ERRORCREATEEVENT"RecvPacket=SYSERRExitFunctionEndIf(K).
hEvent=hEvent'memset(RecvTab[k].
Buffer,0,BUFFER_SIZE);RecvTab(K).
Size=BUFFER_SIZERecvTab(K).
Active=TrueRecvTab(K).
Type=nREAD(RECV_MAX-1)=hEventCallRecvStart(hVxD,RecvTab(K))RecvPacket=len1ExitFunctionElse=SYSERREndIfFunctionRecvStart(ByValhVxDAsLong,packtabAsPacketTable)AsLongDimresultAsLong://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ar.
Overlap.
Internal=0packtab.
Overlap.
InternalHigh=0packtab.
Overlap.
offset=0packtab.
Overlap.
OffsetHigh=0.
Overlap.
hEvent=packtab.
hEventresult=DeviceIoControl(hVxD,_IOCTL_PROTOCOL_READ,_packtab.
Buffer(0),_packtab.
Size,_.
Buffer(0),_packtab.
Size,_packtab.
Length,_packtab.
Overlap)(result<>0)ThenRecvStart=SYSERRElse=0EndIfFunctionSubMain()bFirst=TrueDimhVxDAsLongm_EtherPacketHeadAsEtherPacketHeadDimm_IPPacketHeadAsIPPacketHeadDimm_EtherAddrAsEtherAddr=CreateFile(".
.
VXD",_GENERIC_READOrGENERIC_WRITE,_0,_0,__EXISTING,__ATTRIBUTE_NORMALOr_FILE_FLAG_OVERLAPPEDOr_FILE_FLAG_DELETE_ON_CLOSE,_0)hVxD,"0001"GetHardEtherAddr(hVxD,m_Ethehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468rAddr)hVxD,OID_GEN_CURRENT_PACKET_FILTER,4,NDIS_PACKET_TYPE_DIRECTEDDoUntilFalseDoEvents'result=GetPacket(hVxD,IOCTL_PROTOCOL_READ,1514,1514)result=RecvPacket(hVxD,OutBuff)Ifresult=0ThenExitDoIfresult<>SYSERRThenCopyMemory(m_EtherPacketHead,OutBuff(0),ETHER_HEAD_LEN)Ifm_EtherPacketHead.
ServType=ETHER_PROTO_IPThenCopyMemory(m_IPPacketHead,OutBuff(ETHER_HEAD_LEN),IP_HEAD_BYTE_LEN)Ifm_IPPacketHead.
Proto=IP_PROTO_TCPThen.
Print"SourIP:",m_IPPacketHead.
SourIP.
AddrByte(0)&".
"&_IPPacketHead.
SourIP.
AddrByte(1)&".
"&m_IPPacketHead.
SourIP.
AddrByte(2)&".
"&m_IPPacketHead.
SourIP.
AddrByte(3).
Print"DestIP:",m_IPPacketHead.
DestIP.
AddrByte(0)&".
"&_IPPacketHead.
DestIP.
AddrByte(1)&".
"http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468;&m_IPPacketHead.
DestIP.
AddrByte(2)&".
"&m_IPPacketHead.
DestIP.
AddrByte(3)EndIfEndIfEndIfLoopCloseHandle(hVxD)EndSub源代码结束-使用VB实现Excel自动获取外部数据表格生成和公式设置十分强大便利,是一个强有力的信息分析与处理工具.
VisualBasic是一套可视化、面向对象、事件驱动方式的结构化高级程序设计语言,正成为高效率的Windows应用程序开发工具.
由于微软的努力,VisualBasic应用程序版可作为一种通用宏语言被所有微软可编程应用软件共享.
面始之初带有表格处理类软件中功能最强的宏语言,通过单击"工具"菜单中的"宏",选择宏名来调用宏过程.
随后发展至VisualBasicforApplication专用版,可制作按钮、复选框、单选钮等控件,赋控件以宏名,单击控件运行宏,事件驱动方式就Click(单击)一种.
新近推出的Office97套件中的Excel97,在"工具"菜单中选择"宏"后,就会发现增加了"VisualBasic编辑器"功能.
运用这个新增功能,就完全与VisualBasic编程无异了.
在菜单栏上单击鼠标右键,选择弹出式菜单中的"控件工具箱",在"控件工具箱"工具条上,单击待添加的控件按钮,在工作表中将控件拖曳到所需位置和大小,单击鼠标右键选中"属性"设置控件属性后,双击控件就会出现VisualBasic编辑器.
选择该控件的一个事件如Click或Change,编写程序.
在工作表中操作该控件,如鼠标单击、键入字符等,则触发相应事件,执行相应程序.
笔者在Excel97平台,采用VisualBasic应用程序版开发了一套"通用报表分析系统"(界面如图1).
该系统用于拥有众多子公司http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468的母公司的每月财务报表合并汇总.
所有子公司的统计报表如资产负债表、损益表是由FoxBase编制的财务软件生成的dbf文件,取名为ATV001xx.
dbf----xx月份资产负债表,ATV002xx.
dbf----xx月份损益表等.
一个子公司的所有dbf文件放在一个单独的目录中,如C:,C:等.
母公司每月份生成的汇总报表为TTTyymm.
xls(yy----年份,mm----月份),它有"资产负债表"、"损益表"等若干工作表组成.
每张工作表是由所有子公司相应的dbf文件的相应项目的数据相加而成.
只要将dbf文件逐一转化到TTTyymm.
xls中去,很容易利用Excel的公式设置功能生成母公司的每张汇总报表.

这套系统的关键在于如何将所有dbf文件转换到同一个Excel工作簿中.
直接通过"文件"菜单中的"打开"项,选择文件类型为dBase文件(*.
dbf),可将dbf文件转换到Excel工作簿中,但这工作簿只存转换而来的一张工作表,其他表都自动关闭了.
另外,通过"工具"菜单中的"向导",选择"文件转换"后,只是将一系列dbf文件转换为一系列xls文件而已.
于是采用建立ODBC数据源获取外部数据的办法,将dbf文件逐一转换到一个Excel工作簿内,且用VisualBasicforApplication将转换过程自动化.
只要按一下图1中的"生成报表"按钮,就能完成所有dbf文件的转换,且利用Excel公式自动计算功能完成所有报表的汇总计算.
按"显示报表"按钮,选择表名,可以浏览报表数据.
具体的方法是:一、建立ODBC数据源(1)打开"数据"菜单,选择"获取外部数据",然后单击"新建查询";(2)在"选择数据源"对话框中,双击"<新数据源>";(3)出现"创建新数据源"对话框,输入数据源名称,选择驱动程序如MicrosoftdBaseDriver(*.
dbf),单击"连接";(4)在"ODBCdBase安装"对话框中,单击"使用当前工作目录"前的复选框,去掉缺http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468省(,单击"选定目录(s)",选择子公司存放dbf文件的目录如C:,连按"确定";(5)当出现MicrosoftQuary对话框时,单击"关闭",退出.
不要理会出现的警示信息,因为此时只需建立数据源,并不需要用MicrosoftQuery查询数据;(6)重复上述步骤,在(4)中改换另一家子公司的目录,就为另一家子公司建立一个数据源.
必须建立所有子公司的数据源.
二、手动获取外部数据(1)单击"数据",选取"获取外部数据",单击"新建查询";(2)出现"选取数据源"对话框,点中"使用查询向导创建/编辑查询"前的复选框,然后双击数据源名,如palm1;(3)在"查询向导——选择列"对话框中选择一个查询表名,单击>键,"查询中用到的列"框内会出现表中所有列名,单击"下一步";(4)出现"查询向导——过滤数据",单击"下一步";(5)出现"查询向导——排序顺序",单击"下一步";(6)出现"查询向导——完成",点中"将数据返回MicrosoftExcel"前的单选钮,单击"完成";(7)出现"将外部数据返回到Excel"对话框,选中"新建工作表",按"确定";(8)在建立查询的工作簿内新建工作表,并放入转换好的数据.
这样就将一个dbf文件转换好了.
(9)重复上述过程,所有子公司的dbf文件转换到同一个工作簿中.
三、使用VB实现Excel自动获取外部数据(1)进行手动获取外部数据(1)步骤前,单击"工具"菜单中的"宏",选择"录制新宏",在"宏名"的编辑框中键入宏名dbftoxls,按"确定"键;(2)完成手动获取外部数据(1)-(8)步骤;(3)单击"工具"菜单中的"宏",选择"停止录制".
这样就将获取外部数据的过程记录为宏.
(4)编辑dbftoxls宏,加以修改,使它作为VisualBasic模块表中的一个子程序,并设置调用参数.
提供的程序如下:`设置初值://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468rapppath="c:documents"Constmodulefile=apppath"module.
xls"Conststaticspre="TTT"Constdbfpre="ATV00"`调用dbftoxls的模块SubCmdgeneratetable_Click()DimstaticsfileAsStringDims1AsStringDims2AsStringDims3AsStringDimidyesAsIntegerDimdbfstringAsStringOnErrorGoToerrhandler1idyes=6=txtyear.
Texts1=Mid(s1,3,2)s2=txtmonth.
TextIfLen(s2)=1Thens2="0"s2EndIf=apppathstaticspres1s2".
xls"IfFileLen(staticsfile)>0Then=MsgBox("该年月报表已存在,是否重新生成",vbYesNovbExclamationvbDefaultButton1,"")choice=idyesThen.
OpenFileName:=staticsfileFori=0Tocompanynum-1Forj=0Totablenum-1=dbfpreTrim(Str$(j1))s2http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468=sqlstringfunc(dbfstring,fieldlist(),tablefieldnum(j))Calldbftoxls(s(i,j),sqlstring)NextjNexti.
SaveActiveWorkbook.
CloseEndIfEndIfExitSuberrhandler1:SelectCaseErrCase53.
OpenFileName:=modulefiles3=s1"年"s2"月"("资产负债表").
Range("e4").
FormulaR1C1="'"s3ActiveWorkbook.
SaveAsFileName:=staticsfile,FileFormat_:=xlNormal,Password:="",WriteResPassword:="",ReadOnlyRecommended:=_False,CreateBackup:=FalseFori=0Tocompanynum-1Forj=0Totablenum-1=dbfpreTrim(Str$(j1))s2=sqlstringfunc(dbfstring,fieldlist(),tablefieldnum(j))Calldbftoxls(s(i,j),sqlstring)NextjNexti.
SaveActiveWorkbook.
CloseEndSelectEndSub`dbftoxls子程序://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468rdbftoxls(activesheetname,sqlstring)Sheets(activesheetname).
ActivateCells.
SelectSelection.
ClearRange("a1").
SelectActiveSheet.
QueryTables.
Add(Connection:=Array(Array(_"ODBC;CollatingSequence=ASCII;DBQ=C:;DefaultDir=C:;Deleted=1;Driver=MicrosoftdBaseDriver(*.
dbf);DriverId=533;FIL"_),Array(_"=dBaseIII;ImplicitCommitSync=Yes;MaxBufferSize=512;MaxScanRows=8;PageTimeout=600;SafeTransactions=0;Statistics=0;Threads=3;Use"_),Array("rCommitSync=Yes;")),Destination:=Range("A1")).
Sql=Array(sqlstring).
FieldNames=True.
RefreshStyle=xlInsertDeleteCells.
RowNumbers=False.
FillAdjacentFormulas=False.
RefreshOnFileOpen=False.
HasAutoFormat=True.
BackgroundQuery=True.
TablesOnlyFromHTML=True.
RefreshBackgroundQuery:=False.
SavePassword=True.
SaveData=TrueEndWithEndSub谈谈VB的数据库编http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468程方式全称VisualBasic,是微软公司推出的基于Basic语言的可视化编程环境,以其简单易学功能强大而倍受广大电脑爱好者的青睐.
的数据库编程方面按其难易程度可分为三类(由易到难);使用数据库控制项和绑定控制项使用数据库对象变量进行编程直接调用ODBC2.
0API在使用VB进行数据库编程时,通常,会首先选择三种基本方法之一来进行数据库应用程序的方案设计,现在就将以上三种设计方法的适应范围及其优缺点进行一个比较.
使用数据库控制项和绑定控制项1.
1优点它是三种方法中编码量最小的不必了解CDBC2.
0API的细节允许使用标准的和第三方厂商制订的控制项简化了错误处理支持所有的动态集方法及属性1.
2缺点不能存取快照对象(snapshop)对象或表格对象(都属于记录集对象)不能存取数据库集合,比如表定义(TableDefs)字段(Fieds),索引(Indexes)及查询定义(QueryDefs)只能存取部分ODBC2.
0管理函数不能进行真正的事务处理有限的错误诊断功能1.
3应用对中小规模的数据库表(通常少于一千条记录)只进行简章的浏览操作基本SQL查询所对应的结果集长度有限(通常结果集的记录数小于一百,这些记录从一个或两个长度有限的表中检索出来)应用程序的数据输入/输出项较少(通常只涉及一个或两个长度有限的表、并且表中的字段数在10个左右且不具有关系完整性限制使用数据库对象变量进行编程2.
1优点可以在程序中存取ODBC2.
0的管理函数可以控制多种记录集类型:Dynaset、Snapshop及Table记录集合对象可以存取存储过程和查询动作可以存取数据库集合对象,例如TableDefs、Fields、Indexes及QueryDefs具有真正的事务处理能力,包括启动事务(Begintrans)http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468、提交事务(CommitTrans)及回滚事务(Rollback)2.
2缺点比使用数据控制项的方法编码量较大只能进行间接的错误处理和错误恢复对每个数据库操作没有细粒度的控制对结果集和包含结果集的内丰资源的操作受到限制同直接使用ODBC2.
0API函数的方法相比性能较低2.
3应用应用程序需要在执行期间动态地建立表、字段及索引应用程序涉及同步更新几张表(但在逻辑上保持一致性)的复杂事务应用程序使用结果集而不是Dynaset的窗体(FORMS),例如Snapshots或Tables,这里是设计要考虑的关键应用程序的表非常大,多于1000条记录应用程序具有复杂的数据输入/输出项,它涉及许多内部相关的字段并且包括数据库参照完整性或一致性规则应用程序需要执行一些额外的操作和对结果集的查询后处理,尤其是需要很高的数据格式化显示应用程序需要利用复杂的ODBC管理功能以选择、配置、校验及建立各种数据源应用程序需要在执行期间"显示"数据库的基本结构应用程序需要使用复杂的多码索引方式来检索或更新记录直接调用ODBC2.
0API3.
1优点可以直接参与结果集的开发、管理及规范化对结果集游标提供了更多的控制,并且提供了更多的游标类型和执行动作能够确定ODBC驱动程序及SQL的一致性级别可以更好地控制Windows的执行调度及资源利用其他方面同其他方法差不多,因此这种方法很可能具有最好的性能3.
2缺点较其他两种方法需要大量的代码代码复杂并且要求程序员具有编制API调用的经验在网络上VisualBasic运行期间库的错误处理缺乏安全性,因此代码运行期间出现的错误所造成的后果会非常严重3.
3应用如果系统环境为客户机/服务器模式下的大规模多用户环境,那么应用程序必须都能够准确地解决可能出现的系统错误和失败应用程序强调资源使用,这http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468里如何对内存、网络服务器资源进行直接控制是首要的考虑因素应用程序使用超大规模数据库,例如数据库表可能包含几万或几十万条记录拖动无系统标题栏的窗口导读:在VB中可以通过设置Form的属性,制作无系统标题栏的窗口.
可是,由于失去了系统标题栏,如何使用鼠标拖动窗口便成了一个棘手的问题.
其实,借助API函数ReleaseCapture和SendMessage,这个问题便可迎刃而解了.

首先,在module文件中加入下列声明语句:DeclareSubReleaseCaptureLib"User"()FunctionSendMessageLib"User"(ByValhWnd_Integer,ByValwMsgAsInteger,ByValwParamAsInteger,_lParamAsAny)AsLongConstWM_SYSCOMMAND=&H112PublicConstSC_MOVE=&HF010PublicConstHTCAPTION=2然后,在Form的MouseDown事件中加入下列代码:ReleaseCapture&=SendMessage(Me.
hWnd,WM_SYSCOMMAND,_SC_MOVEHTCAPTION,0)程序运行后,只要当光标落在Form区域时按住鼠标左键,便可以拖动窗口了.
在一些要求生动活泼的界面的程序设计中,开发者常常希望自制风格独特的标题栏,以满足整个界面的要求.
通过这个方法,就可以使自制的标题栏达到乱真的地步.
不过,用作自制标题栏的控件,必须具有MouseDown事件以摆放上述代码.

一组有用的操作Excel的函数在用VB做程序的时候,它本身的报表并不太好使用,因此应用Excel输出数据,是一个好方法,以下是一组操纵Excel的函数据,希望能帮助大家.
'Ehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468xcelVBA控制函数'WriteByWeiHua2000.
10.
12'检测文件CheckFile(ByValstrFileAsString)AsBooleanDimFileXlsAsObjectFileXls=CreateObject("Scripting.
FileSystemObject")IfIsNull(strFile)OrstrFile=""ThenCheckFile=FalseExitFunctionEndIfFileXls.
FileExists(strFile)=FalseThenCheckFile=FalseSetFileXls=NothingExitFunctionElse=TrueFileXls=NothingEndIfFunction'检测工作表CheckSheet(ByValstrSheetAsString,ByValstrWorkBookAsString,xlCheckAppAsExcel.
Application)AsBooleanDimLAsIntegerCheckWorkBookAsExcel.
WorkbookCheckFile(strWorkBook)AndstrSheet<>""AndNotIsNull(strSheet)ThenForL=1ToxlCheckApp.
Workbooks.
CountGetPath(xlCheckApp.
Workbooks(L).
Path)&xlCheckApp.
Workbooks(L).
Name=strWorkBookThen://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468parCheckWorkBook=xlCheckApp.
Workbooks(L)ExitForEndIfNextLCheckWorkBook=xlCheckApp.
Workbooks.
Open(strWorkBook)ForL=1ToCheckWorkBook.
Worksheets.
CountCheckWorkBook.
Worksheets(L).
Name=Trim(strSheet)ThenCheckSheet=TrueExitForEndIfNextLElse"工作表不存在,可能是由文件名或工作表名引起的!
"CheckSheet=FalseEndIfFunction'建立工作表'CreateMethod:1追加'CreateMethod:2覆盖FunctionCreateSheet(ByValstrSheetNameAsString,ByValstrWorkBookAsString,ByValCreateMethodAsInteger,xlCreateAppAsExcel.
Application)AsBooleanDimxlCreateSheetAsExcel.
WorksheetIfCheckFile(strWorkBook)Then.
Workbooks.
Open(strWorkBook)IfCreateMethod=1ThenCheckSheet(strSheetName,strWorkBook,xlCreateApp)=FalseThenSetxlCreateSheet=xlCreateApp.
Worksheets.
Addhttp://www.
1mpi.
com=strSheetNamexlCreateApphttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468.
ActiveWorkbook.
SaveCreateSheet=TruexlCreateSheet=NothingElse'MsgBoxstrSheetName&"工作表已存在!
"CreateSheet=FalsexlCreateSheet=NothingEndIfCreateMethod=2ThenCheckSheet(strSheetName,strWorkBook,xlCreateApp)=TrueThenSetxlCreateSheet=xlCreateApp.
Worksheets(strSheetName)xlCreateSheet.
Cells.
SelectxlCreateSheet.
Cells.
Delete.
ActiveWorkbook.
SaveCreateSheet=TruexlCreateSheet=NothingElse'MsgBoxstrSheetName&"工作表不存在!
"CreateSheet=FalsexlCreateSheet=NothingEndIfEndIfEndIfFunction'删除工作表FunctionDeleteSheet(ByValstrSheetNameAsString,ByValstrWorkBookAsString,xlDeleteAppAsExcel.
Application)AsBooleanDimiAsIntegerxlDeleteSheetAsExcel.
WorksheetIfCheckFile(strWorkBook)ThenCheckSheet(http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468strSheetName,strWorkBook,xlDeleteApp)=TrueThenxlDeleteApp.
Workbooks.
Open(strWorkBook)IfxlDeleteApp.
Worksheets.
Count=1Then"工作薄不能全部删除,"&strSheetName&"是最后一个工作表!
"DeleteSheet=FalseExitFunctionEndIf.
Worksheets(strSheetName).
DeletexlDeleteApp.
ActiveWorkbook.
SaveDeleteSheet=TrueElse=FalseEndIfEndIfFunction'复制工作表CopySheet(ByValstrSrcSheetNameAsString,ByValstrSrcWorkBookAsString,ByValstrTagSheetNameAsString,ByValstrTagWorkbookAsString,xlCopyAppAsExcel.
Application)AsBooleanDimxlSrcBookAsExcel.
WorkbookDimxlTagBookAsExcel.
WorkbookDimExcelSourceAsExcel.
WorksheetDimExcelTargetAsExcel.
WorksheetDimResultAsBooleanCheckFile(strSrcWorkBook)=FalseOrCheckFile(strTagWorkbook)=FalseThenSetExcelSource=NothingSetExcelTargethttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468=NothingSetxlSrcBook=NothingSetxlTagBook=NothingCopySheet=FalseExitFunctionElsexlSrcBook=xlCopyApp.
Workbooks.
Open(strSrcWorkBook)IfstrSrcWorkBook=strTagWorkbookThenIfstrSrcSheetName=strTagSheetNameThenSetExcelSource=NothingSetExcelTarget=NothingSetxlSrcBook=NothingSetxlTagBook=NothingCopySheet=FalseExitFunctionEndIfxlTagBook=xlSrcBookElsexlTagBook=xlCopyApp.
Workbooks.
Open(strTagWorkbook)EndIfExcelSource=xlSrcBook.
Worksheets(strSrcSheetName)SetExcelTarget=xlTagBook.
Worksheets(strTagSheetName)ExcelSource.
SelectExcelSource.
Cells.
CopyExcelTarget.
SelectExcelTarget.
Paste.
Application.
CutCopyMode=xlCopyIfstrSrcWorkBook=strTagWorkbookThenxlTagBook.
SavexlSrcBook.
SaveElse.
SaveEndIfExcelSource=NothingSetExcelTargethttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468=NothingSetxlSrcBook=NothingSetxlTagBook=NothingCopySheet=TrueEndIfFunction'复制工作表ExcelCopySheet(ByValstrSrcSheetNameAsString,ByValstrSrcWorkBookAsString,ByValstrTagSheetNameAsString,ByValstrTagWorkbookAsString,xlCopyAppAsExcel.
Application)AsBooleanDimxlSrcBookAsExcel.
WorkbookDimxlTagBookAsExcel.
WorkbookDimExcelSourceAsExcel.
WorksheetDimExcelTargetAsExcel.
WorksheetDimResultAsBooleanCheckFile(strSrcWorkBook)=FalseOrCheckFile(strTagWorkbook)=FalseThenSetExcelSource=NothingSetExcelTarget=NothingSetxlSrcBook=NothingSetxlTagBook=NothingCopySheet=FalseExitFunctionElsexlSrcBook=xlCopyApp.
Workbooks.
Open(strSrcWorkBook)IfstrSrcWorkBook=strTagWorkbookThenIfstrSrcSheetName=strTagSheetNameThenSetExcelSource=NothingSetExcelTarget=NothingSetxlSrcBook=http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468NothingSetxlTagBook=NothingCopySheet=FalseExitFunctionEndIfxlTagBook=xlSrcBookElsexlTagBook=xlCopyApp.
Workbooks.
Open(strTagWorkbook)EndIfExcelSource=xlSrcBook.
Worksheets(strSrcSheetName)SetExcelTarget=xlTagBook.
Worksheets(strTagSheetName)ExcelSource.
Select.
CopybeforeExcelTarget.
SelectExcelTarget.
Paste.
Application.
CutCopyMode=xlCopyIfstrSrcWorkBook=strTagWorkbookThenxlTagBook.
SavexlSrcBook.
SaveElse.
SaveEndIfExcelSource=NothingSetExcelTarget=NothingSetxlSrcBook=NothingSetxlTagBook=NothingCopySheet=TrueEndIfFunction'关闭Excel应用CloseExcelApp(xlAppAsObject)OnErrorResumeNextxlApp.
QuitxlApp=NothingEndFunction'建立Excel应用CreateExcelApp(QuitAppAsBoolean)AsObjectOnErrorResumeNextDimxlObjehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ctAsObjectIfCheckExcelThenSetxlObject=GetObject(,"Excel.
Application")Iferr.
Number<>0ThenSetxlObject=NothingxlObject=CreateObject("Excel.
Application")CreateExcelApp=xlObjectElseQuitAppThenxlObject.
QuitxlObject=NothingxlObject=CreateObject("Excel.
Application")EndIf=xlObjectEndIfEndIfFunction'检测EXCEL环境CheckExcel()AsBooleanDimxlCheckAppAsObjectxlCheckApp=CreateObject("Excel.
Application")IfxlCheckAppIsNothingThen"对不起,系统未检测到EXCEL安装,请重新检查EXCEL是否被正确安装!
"CheckExcel=FalsexlCheckApp.
QuitxlCheckApp=NothingExitFunctionElse.
QuitCheckExcel=TruexlCheckApp=NothingEndIfFunctionCreateWorkBook(ByValshttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468trWorkBookAsString,xlAppAsExcel.
Application)xlCreateWorkBookAsExcel.
WorkbookSetxlCreateWorkBook=xlApp.
Workbooks.
AddxlCreateWorkBook.
SaveAs(strWorkBook)EndFunctionGetPath(strPathAsString)AsString=IIf(Len(strPath)=3,strPath,strPath&"")EndFunction这上面的函数只不过是一部分,其于的因为专用目的,写不标准,以后也许会整理出来一份标准的函数库的!
用printer对象打印表格这两天我写了一个测试c异常处理机制的例子,感觉有很好的示范作用,在此贴出来,给c异常处理的初学者入门.
本文后附有c异常的知识普及,有兴趣者也可以看看.
下面的代码直接贴到你的console工程中,可以运行调试看看效果,并分析c的异常机制.
#include"stdafx.
h"#include<stdlib.
h>#include<crtdbg.
h>#include<iostream>//内存泄露检测机制#define_CRTDBG_MAP_ALLOC#ifdef_DEBUG#definenewnew(_NORMAL_BLOCK,__FILE__,__LINE__)#endif//自定义异常类classMyExcepction://构造函数,参数为错误代码MyExcepction(interrorId)//输出构造函数被调用信息:http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468:cout<<"MyExcepctioniscalled"<<std::endl;m_errorId=errorId;//拷贝构造函数(MyExcepction&myExp)//输出拷贝构造函数被调用信息::cout<<"copyconstructiscalled"<<std::endl;this->m_errorId=myExp.
m_errorId;~MyExcepction()//输出析构函数被调用信息::cout<<"~MyExcepctioniscalled"<<std::endl;//获取错误码intgetErrorId()m_errorId;://错误码m_errorId;;main(intargc,char*argv[])//内存泄露检测机制_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);//可以改变错误码,以便抛出不同的异常进行测试intthrowErrorCode=110;::cout<<"inputtestcode:"<<std::endl;std::cin>>throwErrorCode;try(throwErrorCode==110)mySthttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ru(110);//抛出对象的地址->由catch(MyExcepction*pMyExcepction)捕获//这里该对象的地址抛出给catch语句,不会调用对象的拷贝构造函数//传地址是提倡的做法,不会频繁地调用该对象的构造函数或拷贝构造函数//catch语句执行结束后,myStru会被析构掉throw&myStru;if(throwErrorCode==119)myStru(119);//抛出对象,这里会通过拷贝构造函数创建一个临时的对象传出给catch//由catch(MyExcepctionmyExcepction)捕获//在catch语句中会再次调用通过拷贝构造函数创建临时对象复制这里传过去的对象//throw结束后myStru会被析构掉throwmyStru;if(throwErrorCode==120)//不提倡这样的抛出方法//这样做的话,如果catch(MyExcepction*pMyExcepction)中不执行delete操作则会发生内存泄露//由catch(MyExcepction*pMyExcepction)捕获MyExcepction*pMyStru=newMyExcepction(120);throwpMyStru;else//直接创建新对象抛出//相当于创建了临时的对象传递给了catch语句//由catch接收时通过拷贝构造函数再次创建临时对象接收传递过去的对象//throw结束后两次创建的临时对象会被析构掉throwMyExcepction(throwErrorCode);(MyExcehttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468pction*pMyExcepction)//输出本语句被执行信息::cout<<"执行了catch(MyExcepction*pMyExcepction)"<<std::endl;//输出错误信息::cout<<"errorCode:"<<pMyExcepction->getErrorId()<<std::endl;//异常抛出的新对象并非创建在函数栈上,而是创建在专用的异常栈上,不需要进行delete//deletepMyExcepction;(MyExcepctionmyExcepction)//输出本语句被执行信息::cout<<"执行了catch(MyExcepctionmyExcepction)"<<std::endl;//输出错误信息::cout<<"errorCode:"<<myExcepction.
getErrorId()<<std::endl;(.
.
.
)//输出本语句被执行信息::cout<<"执行了catch(.
.
.
)"<<std::endl;//处理不了,重新抛出给上级throw;//暂停inttemp;::cin>>temp;return0;知识点:c异常机制一、概述自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制.
C的异常http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468情况无非两种,一种是语法错误,即程序中出现了错误的语句,函数,结构和类,致使编译程序无法进行.
另一种是运行时发生的错误,一般与算法有关.

关于语法错误,不必多说,写代码时心细一点就可以解决.
C编译器的报错机制可以让我们轻松地解决这些错误.
第二种是运行时的错误,常见的有文件打开失败、数组下标溢出、系统内存不足等等.
而一旦出现这些问题,引发算法失效、程序运行时无故停止等故障也是常有的.
这就要求我们在设计软件算法时要全面.
比如针对文件打开失败的情况,保护的方法有很多种,最简单的就是使用"return"命令,告诉上层调用者函数执行失败;另外一种处理策略就是利用c的异常机制,抛出异常.
二、c异常处理机制异常处理机制是一个用来有效地处理运行错误的非常强大且灵活的工具,它提供了更多的弹性、安全性和稳固性,克服了传统方法所带来的问题.
异常的抛出和处理主要使用了以下三个关键字:try、throw、catch.
抛出异常即检测是否产生异常,在C中,其采用throw语句来实现,如果检测到产生异常,则抛出异常.
该语句的格式为:throw表达式;如果在try语句块的程序段中(包括在其中调用的函数)发现了异常,且抛弃了该异常,则这个异常就可以被try语句块后的某个catch语句所捕获并处理,捕获和处理的条件是被抛弃的异常的类型与catch语句的异常类型相匹配.
由于C使用数据类型来区分不同的异常,因此在判断异常时,throw语句中的表达式的值就没有实际意义,而表达式的类型就特别重要.
catch语句形式如下:try包含可能抛出异常的语句;(类型名[形参名])//捕获特定类型的异常(类型名[形参名])//捕获特定类型的异常三个点则表示捕获所有类型的异常【范例1】处理除数为http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a384680的异常.
该范例将上述除数为0的异常可以用try/catch语句来捕获异常,并使用throw语句来抛出异常,从而实现异常处理,实现代码如代码清单1-1所示.

//代码清单1-1#include<iostream.
h>//包含头文件2#include<stdlib.
h>doublefuc(doublex,doubley)//定义函数4if(y==0)6throwy;//除数为0,抛出异常8returnx/y;//否则返回两个数的商10voidmain()常doubleres;try//定义异常15res=fuc(2,3);cout<<"Theresultofx/yis:"<<res<<endl;res=fuc(4,0);//出现异常,函数内部会抛出异catch(double)//捕获并处理异常21://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468arcerr<<"errorofdividingzero.
";23exit(1);//异常退出程序2425【范例2】自定义异常类型(在本文开始的代码中已经给出示范)三、异常的接口声明为了加强程序的可读性,使函数的用户能够方便地知道所使用的函数会抛出哪些异常,可以在函数的声明中列出这个函数可能抛出的所有异常类型,例如:fun()throw(A,B,C,D);这表明函数fun()可能并且只可能抛出类型(A,B,C,D)及其子类型的异常.
如果在函数的声明中没有包括异常的接口声明,则此函数可以抛出任何类型的异常,例如:voidfun();一个不会抛出任何类型异常的函数可以进行如下形式的声明:fun()thow();五、异常处理中需要注意的问题.
如果抛出的异常一直没有函数捕获(catch),则会一直上传到c运行系统那里,导致整个程序的终止.
一般在异常抛出后资源可以正常被释放,但注意如果在类的构造函数中抛出异常,系统是不会调用它的析构函数的,处理方法是:如果在构造函数中要抛出异常,则在抛出前要记得删除申请的资源.
.
异常处理仅仅通过类型而不是通过值来匹配的,所以catch块的参数可以没有参数名称,只需要参数类型.
.
函数原型中的异常说明要与实现中的异常说明一致,否则容易引起异常冲突.
5.
应该在throw语句后写上异常对象时,throw先通过Copy构造函数构造一个新对象,再把该新对象传递给catch.
那么当异常抛出后新对象如何释放异常处理机制保证:异常抛出的新对象并非创建在函数栈上,而是创建在专用的异常栈上,因此它才可以跨接多个函数而传递到上层,否则在栈清空的过程中就会被销毁.
所有从try到http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468throw语句之间构造起来的对象的析构函数将被自动调用.
但如果一直上溯到main函数后还没有找到匹配的catch块,那么系统调用terminate()终止整个程序,这种情况下不能保证所有局部对象会被正确地销毁.
6.
catch块的参数推荐采用地址传递而不是值传递,不仅可以提高效率,还可以利用对象的多态性.
另外,派生类的异常扑获要放到父类异常扑获的前面,否则,派生类的异常无法被扑获.
.
编写异常说明时,要确保派生类成员函数的异常说明和基类成员函数的异常说明一致,即派生类改写的虚函数的异常说明至少要和对应的基类虚函数的异常说明相同,甚至更加严格,更特殊.
用VB、VFP设计右键弹出式菜单导读:凡是用过WINDOWS95或WINDOWS98的用户,非常熟悉单击鼠标右键会出现一个弹出式菜单,那么如何在应用系统中也实现上述功能,增加用户界面的友善性.
笔者分别用VB和VFP实现了用鼠标右键实现弹出式菜单的效果.

用VISUALBASIC6.
0实现弹出式菜单.
建立含有如下控件的窗体:控件NAMECAPTIONINDEX弹出式菜单窗体FORMENU弹出式窗口实例1菜单项MENUS编辑子菜单项MENUS1窗口移动0子菜单项MENUS1窗口最小化1子菜单项MENUS1窗口最大化2子菜单项MENUS1-3&&分割线子菜单项MENUS1退出4(2)程序清单:DeclareFunctionSendMessageLib"user32"Alias"SendMessageA"(ByValhwndAsLong,ByValwMsgAsLong,ByValwParamAsLong,lParamAsAny)AsLongConstWM_SYSCOMMAND=&H112PrivateConstSC_MOVE=&ahttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468mp;HF010&PrivateConstSC_MINIMIZE=&HF020&PrivateConstSC_MAXIMIZE=&HF030&>SubForm_MouseDown(ButtonAsInteger,ShiftAsInteger,XAsSingle,YAsSingle)Button=2ThenMe.
PopupMenuFORMENU!
MENUSEndIfEndSubSubMENUS1_Click(IndexAsInteger)DimXAsLongSelectCaseIndexCase0=SendMessage((FORMENU.
hwnd),WM_SYSCOMMAND,SC_MOVE,0&)Case1=SendMessage((FORMENU.
hwnd),WM_SYSCOMMAND,SC_MINIMIZE,0&)Case2=SendMessage((FORMENU.
hwnd),WM_SYSCOMMAND,SC_MAXIMIZE,0&)Case3Case4UnloadFORMENUEndSelectEndSub用VISUALFOXPRO6.
0实现弹出式菜单.
建立含有如下控件的窗体POPMENU.
SPR:控件NAMECAPTION窗体FORM1弹出式菜单实例2命令按钮COMMAND1单击鼠标右键演示弹出式菜单(2)建立弹出式菜单MENUS.
MPR:菜单项窗口移动菜单项窗口最小化菜单项窗口最大化在COMMAND1控件的RIGHTCLICK事件中输入:DOMENUS.
MPR&&调用弹出式菜单运行环境:http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468WINDOWS98,VISUALBASIC6.
0、VISUALFOXPRO6.
0FORWINDOWS.
用VB编写标准CGI程序<!
--StartFragment-->虽然目前已经有很多可以取代CGI且性能较CGI要高的技术(例如ASP、ISAPI、NSAPI等),但使用它们需要用到专门的知识和工具,并且利用这些技术所编制的程序也只适用于特定的Web服务器或系统平台.
考虑到CGI程序的易用易学性、跨服务器平台特性等优点,CGI程序还将在WWW上占有一一席之地.
本文将介绍如何用VB编写标准的CGI程序,最后本文还用VB实现了一个有关主页客户留言簿的CGI程序.

利用通用网关接口(CGI),Web服务器可以执行一些外部程序,并将这些外部程序所产生的输出结果和Web服务器所管理的静态文本、图像和声音融合在一起传给相应的Web浏览器.
当客户机的浏览器向Web服务器请求一个HTML文件时,服务器在收到请求后就去寻找这个文件并将找到的文件传送给客户机.
而当客户机的请求是一个CGI程序时,Web服务器将激活客户机所请求的CGI程序并把程序的执行结果传给客户机.

标准的CGI程序是通过环境变量和标准输入输出来与Web服务器交换信息的.
任何一个被系统激活的进程都拥有标准输入和输出这两个文件句柄,CGI程序的进程也不例外.
不过,当CGI程序被Web服务器激活以后,它的标准输入STDIN被连接到Web服务器的标准输出STDOUT上,而CGI程序的标准输出STDOUT则被连到服务器的标准输入STDIN上.
因此,CGI程序从标准输入读取信息(也就是从Web服务器的标准输出读信息),而它向标准输出写信息(也就是向Web服务器的标准输入写信息).
服务器一般将客户机传送来的信息放在它的标准输出和相关环境变量中,而CGI程序则从环境变量和它的标准输入(也就是Web服务器的标准输出)获取所需的信息,程序的最终输出结果则被写向它的标准输出STDOUT(也就是Web服务器的标准输入).
Web服务器将从它的标准输入STDIN(也就是CGI程序的标准输出)获取CGI程序的输出结http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468果并将它传送给客户机.
客户机、Web服务器和CGI程序之间的信息交流.
Web服务器就像是客户机和CGI程序间的中介.

服务器、CGI程序间的这种标准框架在Unix系统下和微软Windows环境中的字符方式下可以工作得非常好,因为此时系统产生的所有进程都可以存取标准输入和标准输出.
但对于微软Windows图形方式下的程序就不行了,因为它们无法存取标准输入和标准输出.
为了解决这一问题,微软在Win32系统中创建了另一类型的标准输入和标准输出,程序可以通过调用Win32API函数来存取标准输入和标准输出,不过,这就意味着使用这类标准输入和标准输出的CGI程序都必须是32位的.
微软Windows环境下的其它一些Web服务器(例如Website)则使用另外一种特殊的技术(即利用INI文件)来实现Web服务器和CGI程序间的数据交流.
采用这种被称为"Win-CGI"规范编写的CGI程序通常只能在部分Web服务器上运行.
一般地,支持Win-CGI的Web服务器将客户端的输入以及有关的状态信息写入到一个INI文件中,而CGI程序则从该INI文件中获取相关信息,这类程序的执行效率没有标准CGI程序高.

在进行CGI编程时,只要使CGI程序从标准输入和环境变量中获取客户机提供的信息,并将要传送给客户机的输出结果写入标准输出,剩下的信息传递工作将由Web服务器自动完成.
CGI只是规定了一个标准的接口规范,只要遵守这个标准规范,程序开发人员就可以利用各种编程工具(如Perl、C、FORTRAN、VisualBasic等)进行CGI编程了.
考虑到VisualBasic的强大的数据库处理能力、客户机/服务器模式的编程能力以及字符串处理能力,所以本文主要向大家介绍如何使用VB编写标准的CGI程序.

一、输入输出的处理一个CGI程序被激活以后,它首先要做的事情就是确定系统平台、Web服务器和客户端浏览器的状态信息以及客户端用户的输入数据.
此外,它还必须能够将相关信息传送给客户端,否则它将一事无成.
这些操作都是通过存取环境变量和标准输入输出来完成的.
用VB编写的CGI程序通过调用函数Environ(来获取相关环境变量的值http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468.
存取标准输入输出就要在程序中使用Win32API函数GetStdHandle()、ReadFile()和WriteFile(),在使用这些函数时首先必须在程序中声明它们,写声明语句时可以借助于VB提供的API文本查看器.
以下的CGI程序说明了在VB-CGI程序中如何处理环境变量和标准输入输出.
该CGI程序非常简单,可将标准输入中的信息不经任何处理就返回给客户端,它可被任何表单用POST方法激活:FunctionGetStdHandleLib"kernel32"(ByValnStdHandleAsLong)AsLongDeclareFunctionReadFileLib"kernel32"(ByValhFileAsLong,lpBufferAsAny,ByValnNumberOfBytesToReadAsLong,lpNumberOfBytesReadAsLong,lpOverlappedAsAny)AsLongFunctionWriteFileLib"kernel32"(ByValhFileAsLong,ByVallpBufferAsString,ByValnNumberOfBytesToWriteAsLong,lpNumberOfBytesWrittenAsLong,lpOverlappedAsAny)AsLongConstSTD_INPUT_HANDLE=-10&PublicConstSTD_OUTPUT_HANDLE=-11&PublicConstFILE_BEGIN=0&hStdInAsLong'标准输入文件句柄PublichStdOutAsLong'标准输出文件句柄SubMain()CGI_ContentLengthAsStrhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ingDimCGI_QueryStringAsStringlContentLengthAsLong'标准输入中的字符串的长度DimsBuffAsString'用于存储标准输入中的字符串DimlBytesReadAsLong'实际读入的字符个数DimrcAsLongsFormDataAsString'调用系统函数生成标准输入输出文件句柄hStdIn=GetStdHandle(STD_INPUT_HANDLE)hStdOut=GetStdHandle(STD_OUTPUT_HANDLE)'获取环境变量CONTENT_LENGTH的值,并将它转换为整型CGI_ContentLength=Environ("CONTENT_LENGTH")lContentLength=Val(CGI_ContentLength)sBuff=String(lContentLength,Chr$(0))'从标准输入中读数据=ReadFile(hStdIn,ByValsBuff,lContentLength,lBytesRead,ByVal0&)sFormData=Left$(sBuff,lBytesRead)"Content-type:text/html"&vbCrLfOutPut"<HTML><HEAD>""<TITLE>表单传送数据的方法POST</TITLE></HEAD>"OutPut"<BODY><H3>表单传送数据的方法POST</H3>"OutPut"<P>本CGI程序使用VisualBasic编制!
"http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468;OutPut"<P>POST方法传送的数据:"OutPut"<P>"&sBuffOutPut"</BODY></HTML>"EndSubOutPut(sAsString)'定义一个向标准输出写信息的函数DimlBytesWrittenAsLongs=s&vbCrLfhStdOut,s,Len(s),lBytesWritten,ByVal0&EndSub一般地,用VB编译生成的CGI程序不能正确处理中文信息.
这主要表现在CGI程序向STDOUT输出的中文在Web页面上无法正确显示,可通过在该中文字符串后跟着输出一些空格来解决这个问题.
当使用HTML标识符<P>、</P>对Web页面进行排版时,浏览器在显示该Web页面时会吃掉多余的空格而只保留一个.
在这种情况下,这些空格对Web页面的外观基本上没有什么影响.
如果使用HTML标识符<PRE>、</PRE>对Web页面进行排版,则由于空格不能被浏览器吃掉,所以Web页面的外观将会受到较大的影响.
不过,这时可用HTML的表格<table>、<P>来代替<PRE>对Web页面进行排版.

注意:整个CGI程序的主体必须放在MAIN()函数中.
二、URL译码与解码由于Web服务器和浏览器不能正确处理一些特殊的字符,Web服务器和浏览器之间可能会因此而产生某种程度的误会,所以在数据被传送之前,浏览器都要对表单内客户输入的数据中的特殊字符进行URL译码.

例如,Web系统用"="分解表单各元素的NAME和VALUE属性,用"&"分解不同表单元素的输入数据.
如果在表单的输入数据中包含这些特殊的字符,并且表单的数据在传送给Web服务器前不作任何处理,则Web服务器将无法知道哪一个"http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468="、"&"是用户输入的,哪一个是浏览器加上的.
在由表单属性ACTION定义的URL中,也可能会出现一些特殊的字符,当在CGI程序的名称和路径信息(PathInformation)中出现"="、"&"和""时,都会影响数据的正确传送.
译码(URLEncoding)就是将Web服务器所不能正确处理的特殊字符转换成它的十六进制数的形式,比如将"%"转换成"%"、"="转换成"="等等.
这些特殊的字符通常被称作Web系统的保留字符.
在Web系统上无论是用GET方法还是用POST方法传送的数据都要进行URL译码.
CGI程序要想处理表单传送来的数据,还必须对浏览器URL译码过的数据进行解码.
因此,理解URL译码对于我们进行CGI编程是非常重要的.
URL译码一般包括以下步骤:、浏览器将所传送的数据根据表单所包含的元素分解成"NAME=VALUE"形式,NAME和VALUE分别是表单元素的属性.
其中,VALUE属性中存储客户机在表单中输入的数据:如果客户机没有输入数据,则VALUE存储的是表单定义的缺省值;如果缺省值也没有定义,则VALUE值为空.

、代表表单中各元素的各个"NAME=VALUE"对被浏览器用"&"连接起来.
3、VALUE属性中存放的数据若含有空格,则被转换成"".
、URL和输入数据中所包含的Web系统的保留字符必须被译码成其十六进制数形式.
5、被译码后的字符被表示成一个"%"和它们的十六进制数形式(即%HH).
程序从环境变量"QUERY_STRING"或标准输入中读入的数据是经过浏览器URL译码过的,故在使用这些数据以前还必须对它们进行URL解码.
解码的目的是将数据还原成客户端用户在Web页面上输入时的形式.
本文已经介绍了URL译码过程,URL解码过程与它正好相反,它一般包括以下步骤:、从浏览器用GET或POST方法所传送来的数据中找出代表各个表单元素所储存数据的"NAME=VALUE"对.
、VALUE属性中所存放的数据若含有"",则被转换成空格.
、将VALUE属性中所存放的http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468数据的十六进制数"%HH"转换成相应的字符.
系统将汉字当成特殊的字符,对它也要进行URL译码.
对于一个特殊的单字节字符(比如"/"),浏览器通常将它译码成十六进制数的形式(比如/),"%"表示它后面跟的是两位十六进制数.
当VB程序对其进行处理时调用Chr$函数就可以将其恢复为原貌.
而一个汉字则被浏览器译码成四位十六进制数(比如).
如果CGI程序还像以前那样分别调用Chr(D5)和Chr(C5),则由于D5、C5都不是正常的单字节十六进制数码,故Chr函数返回空,汉字将无法正确还原.
正确的做法应该是将有关汉字的四位十六进制数一起传给函数Chr(如Chr(D5C5)),此时汉字才能被正确还原.

因此,可以让CGI程序对四位连续的十六进制数一起进行译码,以便使汉字能够被正确还原.
但在这种情况下,当客户端用户输入了两个连续的Web系统保留字符时,CGI程序又可能把它们当成汉字来处理.
这时可以让CGI程序在需要对四位连续的十六进制数进行译码时首先检查前面两位是否为Web系统的保留字符,如果是则仍然按照单字节的字符处理.
不过如果客户端用户在表单内填写了很多汉字,则CGI程序的负担将会大大加重.
事实上,在大多数情况下,客户端用户很少会使用两个连续的Web系统的保留字符,所以可以只让CGI程序对最容易出现的情形如"://"(当客户端用户在表单中输入某一URL时会出现这种情况)进行检查,本文下节提供的函数UrlDecode()可以实现对汉字和Web系统保留字符的URL解码.
三、CGI编程实例本节将用VB编写一个处理主页客户留言簿的CGI程序.
除了要调用本文前面所介绍的Win32API函数外,程序中还调用了Win32API函数GetTempFileName()来获得一个唯一的临时文件名.
程序中的函数UrlDecode()用来对客户端的输入进行URL译码.
函数GetCgiValue()则用来分解字符串,根据表单元素的NAME属性获取其VALUE值,并调用UrlDecode()函数对其进行URL译码.

本程序要求在留言簿文件guests.
html中使用一个定位串"<!
ENDHEADhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468>",将文件的开始部分和具体的客户留言部分分开.
CGI程序将在"<!
ENDHEAD>"所在的位置插入客户新的留言.
guests.
html应具有如下所示的样式:<html><head><title>DHTMLZone</title></head><bodybgcolor="#FFFFFF"text="#00000"vlink="#990000"link="#333399"><!
ENDHEAD><!
---客户的留言部分从这开始--><P>.
<!
---客户的留言部分结束于此--></body></html>这种样式将保证最后的留言出现在留言簿的最前面.
如果要想使最后的留言出现在留言簿的最后面,则只需将留言簿文件中的定位字符串"<!
ENDHEAD>"移到留言簿文件中客户留言部分和HTML文件结尾部分之间的位置就行了.
整个程序的完整代码如下所示:'guestbook.
basDeclareFunctionGetStdHandleLib"kernel32"(ByValnStdHandleAsLong)AsLongDeclareFunctionReadFileLib"kernel32"(ByValhFileAsLong,lpBufferAsAny,ByValnNumberOfBytesToReadAsLong,lpNumberOfBytesReadAsLong,lpOverlappedAsAny)AsLongFunctionWriteFileLib"kernel32"(ByValhFileAsLong,Bhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468yVallpBufferAsString,ByValnNumberOfBytesToWriteAsLong,lpNumberOfBytesWrittenAsLong,lpOverlappedAsAny)AsLongDeclareFunctionGetTempFileNameLib"kernel32"Alias"GetTempFileNameA"(ByVallpszPathAsString,ByVallpPrefixStringAsString,ByValwUniqueAsLong,ByVallpTempFileNameAsString)AsLongConstSTD_INPUT_HANDLE=-10&PublicConstSTD_OUTPUT_HANDLE=-11&PublicConstFILE_BEGIN=0&hStdInAsLong'标准输入文件句柄PublichStdOutAsLong'标准输出文件句柄sFormDataAsString'用于存储没有经过URL译码的用户输入数据PubliclContentLengthAsLongCGI_RequestMethodAsStringSubMain()CGI_ContentLengthAsString,CGI_QueryStringAsString,sBuffAsString,chinesetailAsStringlBytesReadAsLong,rcAsLong,IAsLongsEmailAsString,sNameAsString,sURLAsString,sfromAsString,tempstringAsString://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468parsCommentAsString,tempFileNameAsString,guestbookAsString'CGI程序的初始化工作=GetStdHandle(STD_INPUT_HANDLE)hStdOut=GetStdHandle(STD_OUTPUT_HANDLE)CGI_RequestMethod=Environ("REQUEST_METHOD")CGI_QueryString=Environ("QUERY_STRING")CGI_ContentLength=Environ("CONTENT_LENGTH")lContentLength=Val(CGI_ContentLength)sBuff=String(lContentLength,Chr$(0))"Content-type:text/html"&vbCrLf'输出MIME类型OutPut"<FONTSIZE=""2"">"CGI_RequestMethod="POST"Then=String(lContentLength,Chr$(0))=ReadFile(hStdIn,ByValsBuff,lContentLength,lBytesRead,ByVal0&)sFormData=Left$(sBuff,lBytesRead)ElseIfCGI_RequestMethod="GET"ThensFormData=CGI_QueryStringElse"UnknowFormMethod!
"EndIf'为了在页http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468面上正确显示中文,生成一个空格串以获取客户端用户的输入chinesetail=String(400,"")sName=GetCgiValue("name")sEmail=GetCgiValue("email")sURL=GetCgiValue("URL")sfrom=GetCgiValue("from")=GetCgiValue("URL_Comment")'对客户端用户的输入进行检查IfLen(sName)=0Then"<P>非常抱歉!
您还没有填写姓名!
"&chinesetailExitSubEndIfLen(sComment)=0Then"<P>非常抱歉!
您还没有提出建议!
"&chinesetailExitSubEndIf'获取唯一的临时文件名和留言簿文件并打开它们=TempFile("c:","gbk")guestbook="e:.
html"OpentempFileNameForOutputAs#1OpenguestbookForInputAs#2'本循环体用于将留言簿中字符串"<!
ENDHEAD>"前面的内容写入临时文件DoInput#2,tempstringPrint#1,tempstringWhiletempstring<>"http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468<!
ENDHEAD>"AndNotEOF(2)'向临时文件中插入客户端用户的留言Print#1,"<hr>"&vbCrLfPrint#1,"<ul>"&vbCrLf#1,"<li><b>留言时间</b>:"&Date$&""&Time$&vbCrLfPrint#1,"<li><b>姓名:</b>"&sName&vbCrLfIfLen(sEmail)<>0Then#1,"<li><b>E-mail:</b><ahref=""mailto:"&sEmail&""">"&sEmail&"</a>"&vbCrLfEndIfLen(sURL)<>0Then#1,"<li><b>我的主页:</b><ahref="""&sURL&""">"&sURL&"</a>"&vbCrLfEndIfLen(sfrom)<>0Then#1,"<li><b>我来自:</b>"&sfrom&ahttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468mp;vbCrLfEndIf#1,"<li><b>我的建议:</b>"&vbCrLfPrint#1,sComment&vbCrLfPrint#1,"</ul>"&vbCrLf'本循环体用于将留言簿剩余的东西写入留言簿DoInput#2,tempstringPrint#1,tempstringLoopWhileNotEOF(2)Close#1Close#2guestbook'删除旧的留言簿tempFileNameAsguestbook'将临时文件改成新的留言簿OutPut"<P>非常感谢您的留言!
"&chinesetail"<P>欢迎您经常光顾本主页!
"&chinesetailOutPut"</FONT>"EndSubOutPut(sAsString)'本子程序用于向标准输出写信息DimlBytesWrittenAsLongs=s&vbCrLfhStdOut,s,Len(s),lBytesWritten,ByVal0&EndSub'本子程序可以获取表单上某一元素的数据FunctionGetCgiValue(cgiNameAsString)AsStringDimdelim2AsLong'positionof"="Dimdelim1AsLong'positionof"&"DimnAsInteger://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468pointer1AsLong,pointer2AsLong,lengthAsLong,length1AsLongDimtmpstring1AsString,tmpstring2AsStringpointer1=1pointer2=1=InStr(pointer2,sFormData,"=")pointer2=delim21Do=delim2-pointer1=Mid(sFormData,pointer1,length)delim1=InStr(pointer1,sFormData,"&")pointer1=delim11=delim1-pointer2delim1=0Thenlength1=lContentLength1-pointer2Iftmpstring1=cgiNameThen=Mid$(sFormData,pointer2,length1)GetCgiValue=UrlDecode(tmpstring2)ExitDoEndIfdelim1=0ThenExitDoEndIf=InStr(pointer2,sFormData,"=")pointer2=delim21LoopFunction'本函数可以对用户输入的数据进行URL解码FunctionUrlDecode(ByValsEncodedAsString)AsStringDimpointerAsLong'sEncodedpositionpointerDimposAshttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468Long'positionofInStrtargetDimtempAsStringsEncoded=""ThenExitFunctionpointer=1'本循环体用于将""转换成空格Do=InStr(pointer,sEncoded,"")Ifpos=0ThenExitDo$(sEncoded,pos,1)=""pointer=pos1Loop=1'本循环体用于将%XX转换成字符.
对于两个连续的%XX,如果第一个%XX不是某些特指的Web系统保留字符,将把它们转换成汉字Do=InStr(pointer,sEncoded,"%")Ifpos=0ThenExitDo=Chr$("&H"&(Mid$(sEncoded,pos1,2)))Mid(sEncoded,pos3,1)="%"And(temp<>":")And(temp<>"/")_And(temp<>"(")And(temp<>")")And(temp<>".
")And(temp<>",")_And(temp<>";")And(temp<>"%")Then$(sEncoded,pos,2)=Chr$("&H"http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468&(Mid$(sEncoded,pos1,2))_&(Mid$(sEncoded,pos4,2)))=Left$(sEncoded,pos)&Mid$(sEncoded,pos6)pointer=pos1Else$(sEncoded,pos,1)=temp=Left$(sEncoded,pos)&Mid$(sEncoded,pos3)pointer=pos1EndIfLoop=sEncodedExitFunctionEndFunction'本函数可以获得一个唯一的临时文件名FunctionTempFile(sPathAsString,sPrefixAsString)AsStringDimxAsLong,rcAsLong=String(127,Chr$(0))=GetTempFileName(sPath,sPrefix,ByVal0&,TempFile)x=InStr(TempFile,Chr$(0))x>0ThenTempFile=Left$(TempFile,x-1)EndFunction程序guestbook.
bas所要处理的表单如下所示:<html><head><title>贵宾留言簿</title></head><body><h3>贵宾留言簿测试</h3><formaction="/cgi-bin/guest.
exe"method="post&quhttp://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a38468ot;>您的姓名:<inputtype="text"name="name"><br>您的Email信箱:<inputtype="text"name="email"><br>您的主页的URL:<inputtype="text"name="URL"><br>您的建议:<br><textareaname="URL_Comment"rows=4cols=30></textarea><br>您来自:<inputtype="text"name="from"><br><inputtype="submit"value="留言"></form></body></html>用VB编写简单的程序来清空文档菜单文档菜单内存放的是我们最近使用的文件的快捷方式,它所对应的目录在WINDOWS95(或WINDOWS98)安装目录下的Recent目录.
当我们不在需要这些快捷方式时,我们可以清空文档菜单.
清空文档菜单的方法有两种.
方法一:选择"开始菜单→设置→任务栏和开始菜单"(或右击任务栏选择"属性"),弹出"任务栏属性",再选择"开始菜单程序→清除".
方法二:在资源管理器里选定C:目录(假设你的WINDOWS95安装在C:目录下),然后把Recent目录里的文件全部选择并删除它们.
遗憾的是这两种方法都比较麻烦,能不能有一种简便的方法,只点一下鼠标就完成清空文档菜单的办法呢按照一下的步骤试试:1.
在VisualBasic5.
0中新建一个工程.
http://www.
1mpi.
com/doc/f10ba2ff2a1611bb37a384682.
在代码窗口中键入以下代码:PrivateSubForm_Load()'如果文档菜单非空Dir("c:文档下载网是专业的免费文档搜索与下载网站,提供行业资料,考试资料,教学课件,学术论文,技术资料,研究报告,工作范文,资格考试,word文档,专业文献,应用文书,行业论文等文档搜索与文档下载,是您文档写作和查找参考资料的必备网站.

瓜云互联-美国洛杉矶高防CN2高防云服务器,新老用户均可9折促销!低至32.4元/月!

瓜云互联一直主打超高性价比的海外vps产品,主要以美国cn2、香港cn2线路为主,100M以内高宽带,非常适合个人使用、企业等等!安全防护体系 弹性灵活,能为提供简单、 高效、智能、快速、低成本的云防护,帮助个人、企业从实现网络攻击防御,同时也承诺产品24H支持退换,不喜欢可以找客服退现,诚信自由交易!官方网站:点击访问瓜云互联官网活动方案:打折优惠策略:新老用户购买服务器统统9折优惠预存返款活动...

特网云(198元/月),高质量云虚拟主机低至0.16元/天,裸金属服务器仅需10.5元/天

特网云为您提供高速、稳定、安全、弹性的云计算服务计算、存储、监控、安全,完善的云产品满足您的一切所需,深耕云计算领域10余年;我们拥有前沿的核心技术,始终致力于为政府机构、企业组织和个人开发者提供稳定、安全、可靠、高性价比的云计算产品与服务。官方网站:https://www.56dr.com/ 10年老品牌 值得信赖 有需要的请联系======================特网云推出多IP云主机...

Ftech:越南vps,2核/2G/20G SSD/1Gbps不限流量/可安装Windows系统,$12.5月

ftech怎么样?ftech是一家越南本土的主机商,成立于2011年,比较低调,国内知道的人比较少。FTECH.VN以极低的成本提供高质量服务的领先提供商之一。主营虚拟主机、VPS、独立服务器、域名等传统的IDC业务,数据中心分布在河内和胡志明市。其中,VPS提供1G的共享带宽,且不限流量,还可以安装Windows server2003/2008的系统。Ftech支持信用卡、Paypal等付款,但...

vb教程为你推荐
AsgardiaCONSTANTIA 1685(2017年)红酒多少一瓶?sonicchat深圳哪里有卖汽车模型?www.522av.com现在怎样在手机上看AVip在线查询我要用eclipse做个ip在线查询功能,用QQwry数据库,可是我不知道怎么把这个数据库放到我的程序里面去,高手帮忙指点下,小弟在这谢谢了m.kan84.net那里有免费的电影看?avtt4.comCOM1/COM3/COM4是什么意思??/杨丽晓博客杨丽晓今年高考了吗?ww.66bobo.com有的网址直接输入***.com就行了,不用WWW, 为什么?33tutu.comDnf绝望100鬼泣怎么过梦遗姐昨晚和姐姐和她朋友一起吃晚饭,我们都喝了酒,我迷糊着回到家的,早上我回想起我好像发生关系射过,会不会是我姐姐,如果是这样我怎么办
域名信息查询 域名升级访问中 北京域名空间 免费申请网页 免费ftp空间 新站长网 主机合租 镇江联通宽带 免空 空间论坛 工信部icp备案号 秒杀汇 佛山高防服务器 爱奇艺vip免费领取 搜索引擎提交入口 英雄联盟台服官网 net空间 免费蓝钻 国外网页代理 稳定空间 更多