返回列表 发帖

【技术】VB新手学习系列教程之基础篇

第一讲    什么是API








首先,有必要向大家讲一讲,什么是API。所谓API本来是为C和C++程序员写的。API说来说去,就是一种函数,他们包含在一个附加名为DLL的动态连接库文件中。用标准的定义来讲,API就是Windows的32位应用程序编程接口,是一系列很复杂的函数,消息和结构,它使编程人员可以用不同类型的编程语言编制出的运行在Windows95和Windows NT操作系统上的应用程序。可以说,如果你曾经学过VC,那么API对你来说不是什么问题。但是如果你没有学过VC,或者你对Windows95的结构体系不熟悉,那么可以说,学习API将是一件很辛苦的事情。
如果你打开WINDOWS的SYSTEM文件夹,你可以发现其中有很多附加名为DLL的文件。一个DLL中包含的API函数并不只是一个,数十个,甚至是数百个。我们能都掌握它嘛?回答是否定的∶不可能掌握。但实际上,我们真的没必要都掌握,只要重点掌握Windos系统本身自带的API函数就可以了。但,在其中还应当抛开掉同VB本身自有的函数重复的函数。如,VB
的etAttr命令可以获得文件属性,SetAttr可以设置文件属性。对API来讲也有对应的函数
GetFileAttributes和SetFileAttributes,性能都差不多。如此地一算,剩下来的也就5、600个。是的,也不少。但,我可以敢跟你说,只要你熟悉地掌握100个,那么你的编程水平比现在高出至少要两倍。尽管人们说VB和WINDOWS具有密切的关系,但我认为,API更接近
WINDOWS。如果你学会了API,首要的收获便是对WINDOWS体系结构的认识。这个收获是来自不易的。
如果你不依靠API会怎么样?我可以跟你说,绝大多是高级编程书本(当然这不是书的名程叫高级而高级的,而是在一开始的《本书内容》中指明《本书的阅读对象是具有一定VB基础的读者》的那些书),首先提的问题一般大都是从API开始。因此可以说,你不学API,你大概将停留在初级水平,无法往上攀登。唯一的途径也许就是向别人求救∶我快死了,快来救救我呀,这个怎么办,那个怎么办?烦不烦呢?当然,现在网上好人太多(包括我在内,嘻嘻),但,你应当明白,通过此途径,你的手中出不了好的作品。这是因为缺乏这些知识你的脑子里根本行不成一种总体的设计构思。











API文本游览器








很多API函数都是很长很长的。想看什么样子吗?如下就是作为例子的API DdeClientTransaction函数∶
Declare Function DdeClientTransaction Lib "user32" (pData As Byte, ByVal cbData As Long, ByVal hConv As Long, ByVal hszItem As Long, ByVal wFmt As Long, ByVal wType As Long, ByVal dwTimeout As Long, pdwResult As Long) As Long
哇!这么长?如果你从来没有接触过API,我想你肯定被吓住了。你也许考虑,该不该继续学下去。不过不要担心,幸运的是Microsoft的设计家们为我们提供了有用的工具,这便是API
文本查看器。
通过API文本查看器,我们可以方便地查找程序所需要的函数声明、结构类型和常数,然后将它复制到剪贴板,最后再粘贴到VB程序的代码段中。在大多数情况下,只要我们确定了程序所需要的函数、结构和常数这三个方面后,就可以通过对API文本游览器的以上操作将他们加入到程序段中,从而程序中可以使用这些函数了。这些是学习API最基本的常识问题,它远远占不到API的庞大的体系内容。今后我们把精力浪费(这绝不是浪费)在哪里呢?那就是∶
什么时候使用什么函数,什么时候使用什么结构类型,什么时候使用什么常数。












API函数声明









让我们回想一下。在VB中,如何声明函数呢?我想,如果你正在看此文,那么你绝对能够回答得出这个问题。以下便是你应该很熟悉的函数声明∶
Function SetFocus (ByVal hwnd As Long) As Long
即,这行代码定义了名为SetFocus的函数,此函数具有一个Long型数据类型的参数,并按值传递(ByVal),函数执行后将返回一个Long型数据。
API函数的声明也很类似,如,API中的SetFocus 函数是这样写的∶
Declare Function SetFocus Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long
有点复杂了一些。是的,是复杂了点。但我可以告诉你,除了这些多出来的部分,其他部分还是和你以前学到的东西是一样的。函数在程序中的调用也是一样。如:
Dim dl As Long
dl&=SetFoucs(Form1.Hwnd)
但,一点是清楚的。它不象你自己写的程序那样能够看到里面的运行机理,也不像VB
自带的函数那样,能够从VB的联机帮助中查到其用法。唯一的方法就是去学、查VB以外的资料。
Declare 语句用于在模块级别中声明对动态链接库 (DLL) 中外部过程的引用。对此,你只要记住任何API函数声明都必须写这个语句就可以了。
Iib 指明包含所声明过程或函数的动态链接库或代码资源。也就是说,它说明的是,函数或过程从何而来的问题。
如在上例中,SetFocus Lib "user32"说明 函数 SetFocus 来自 user32.dll文件。主要的dll动态连接库文件有∶
user32.dll Windows管理。生成和管理应用程序的用户接口。
GDI32.dll 图形设备接口。产生Windows设备的图形输出
Kernel32.dll 系统服务。访问操作系统的计算机资源。
注意,当DLL文件不在Windows或System文件夹中的时候,必须在函数中说明其出处(
路径)。如,SetFocus Lib "c:\Mydll\user32"
函数声明中的Alias 是可选的。表示将被调用的过程在动态链接库 (DLL) 中还有另外的名称(别名)。如,Alias "SetFocus" ,说明SetFocus函数在User32.dll中的另外一个名称是,
SetFocus。怎么两个名都一样呢?当然,也可以是不同的。在很多情况下,Alias说明的函数名,即别名最后一个字符经常是字符A,如SetWindowsText函数的另一个名称是
SetWindowsTextA,表示为Alias "SetWindowsTextA"。这个A只不过是设计家们的习惯的命名约定,表示函数属于ANSI版本。
那么,别名究竟有什么用途呢?从理论上讲,别名提供了用另一个名子调用API的函数方法。如果你指明了别名,那么 尽管我们按Declare语句后面的函数来调用该函数,但在函数的实际调用上是以别名作为首要选择的。如,以下两个函数(Function,ABCD)声明都是有效的,他们调用的是同一个 SetFocus函数∶
Declare Function SetFocus Lib "user32" "SetFocus" (ByVal hwnd As Long) As Long
Declare ABCD SetFocus Lib "user32" Alias "SetFocus" (ByVal hwnd As Long) As Long
需要注意的是,选用Alias的时候,应注意别名的大小写;如果不选用Alias 时的时候,函数名必须注意大小写,而且不能改动。当然,在很多情况下,由于函数声明是直接从API
文本游览器中拷贝过来的,所以这种错误的发生机会是很少的,但您有必要知道这一点。
最后提醒你一句,API声明(包括结构、常数)必须放在窗体或模块的"通用(General Declarations)段。

第五讲    封面的设计










一、封面的设计是这样的,先出现一窗体,上面为你喜欢的图案。然后出现一艘从左向右行驶着的船。屏幕上方从两侧分别移动出“欢迎”两个字。具体的制作方法是:把预先选好的背景图案装入封面窗体中,窗体命名为CAI。再分别在三个图像控件(image)中装入预先制作好的位图“欢”、“迎”和船型图案。然后把三个image放置在初始位置(即图案刚在窗体出现时的位置),并把它们的可视属性都设置为“false”。程序如下:
Sub Form_load()
cai.Show ′显示封面窗体
Dim i ′定义变量
image3.visible=True ′船型图像控件出现
a1: If image3.Left < 6120 Then
′6120为船移动到屏幕右边的坐标,此值可以随需要选取
image3.Move image3.Left+50
′移动此图像控件如嫌移动慢,可改变移动值
Goto a1
End If
image1.visible=True ′“欢”字出现
a2: If image1.Left < 2120 Then
′2120为“欢”字移动到屏幕中间的位置
image1.Move image1.Left+50 ′移动此图像控件
Goto a2
End If
image2.visible=True ′“迎”字出现
a3: If image2.Left > 5420 Then
′5420为“迎”字移动到屏幕中间的位置
image2.Move image2.Left-50 ′移动此图像控件
Goto a3
End If
For i=1 To 10000
′使窗体暂停一段时间时间长短可通过改变循环次数实现
Next i
menul.Show ′显示程序主窗体
Unload cai ′卸载封面窗体
End Sub
二、简单的“动画”
点击一3D按钮后,屏幕表现光线平行进入一玻璃管,在管中有一散射中心,有的光线射到此中心后反射到管的初始端。程序如下:
Sub Command3Dl_Click()
Dim i, j, k, m, n ′定义变量
For i=2080 To 5520
′显示出三条线,直到图像中的散射中心处,颜色为黑色
Line(2080,2760)-(i,2760),RGB(0, 0, 0)
Line(2080,2860)-(i,2860),RGB(0, 0, 0)
Line(2080,2660)-(i,2660),RGB(0, 0, 0)
Next i
For j=5520 To 4800 Step-1 ′反射光线第一次射到管壁上
Line(5520,2760)-(j,2760-(5520-j)*.33333333),RGB
(255, 0, 0) ′反射光线,颜色为红色
Line(5520,2660)-(5520+(5520-j),2660),RGB(0, 0, 0)
Line(5520,2860)-(5520+(5520-j),2860),RGB(0, 0, 0)
′没有遇到散射中心的两条光线,为黑色,继续前进
Next j
For k=4800 To 3360 Step-1 ′反射光线第二次射到管壁上
Line(4800,2520)-(k,2520+(4800-k)*.33333333),
RGB(255, 0, 0) ′反射光线,颜色为红色
Line(6240,2660)-(6240+(4800-k),2660),RGB(0,0,0)
Line(6240,2860)-(6240+(4800-k),2860),RGB(0,0,0)
′没有遇到散射中心的两条光线,颜色为黑色
Next k
For m=3360 To 2080 Step-1 ′反射光线第三次射到管壁上
Line(3360,3000)-(m,3000-(3360-m)*.33333333),
RGB(255, 0, 0) ′反射光线,颜色为红色
Next m
End Sub
三、封底
封底的设计是:先出现全黑的屏幕,然后从上至下逐渐拉出白底红字的“再见”的字样。先按要求在画板中做一个BMP图,上面写着“再见”。然后在一名为BYE的窗体中加入一个全屏大的Picturel,将BMP图装入。程序如下:
Sub Form_Load()
Dim i ′定义变量
bye.Show ′封底出现
Unload menu1 ′卸载主菜单
al: If picture1.Height < 7130 Then ′7130为图的高度
picturel.Height=picture1.Height+50 ′下拉屏幕
GoTo al
End If
For i=1 To 20000 ′使窗体暂停一段时间
Next i
End ′结束所有操作
End Sub
利用Visual Basic让命令行软件全面转向Windows
众所周知,Windows以其优美的图形界面,方便快捷的操作环境,已成为当今的主流操作系统,但由于其程序编写过于复杂,有很多用户常用的工具和小程序仍然只能运行于DOS环境下,造成Windows和DOS的频繁切换、使工作缺乏连续性和效率低下。有什么方法可以解决这一问题呢?等待For Windows版本的面市,但仍会造成重复投资。据笔者观察发现,常用工具中有一部分为命令行软件,这些软件完全可以利用VB改编成For Windows版本的。首先由于VB的简单易用,使Windows的界面设计变得异常简单直观。所以可轻而易举的将命令选项、开关等转化为对应的图形界面(如复选钮等)。其次由于VB为用户提供了Shell函数,也使得命令调用非常简单。通过Shell其实你只做了个界面,核心还是DOS下的原来工具。其函数格式如下:
Shell(命令字符串<,窗口类型>)
命令字符串即具体执行的命令(如字符串“arj e a:user.arj c:\user ”)有关字符串的操作可查阅有关书籍。至于窗口型类型缺省即可。最后只须注意,在Shell执行函数之前,有必要对命令行中有可能引发错误的参数进行检测,如在执行前检查用户给的源文件是否存在等,以保证达到预期结果。笔者用VB改编的Arj for Windows版本,其结果出乎想象。希望大家能自己动手全面转向Windows。












让窗体居中









在主窗体的Form_load()中的最前面加入下列代码:
Dim X0 As long
Dim Y0 As Long
'让窗体居中
X0 = Screen.Width
Y0 = Screen.Height
X0 = (X0 - Me.Width) / 2
Y0 = (Y0 - Me.Height) / 2
Me.Move X0, Y0

TOP

第四讲   IP地址与子网掩码








一、 IP地址与网络分类
(1) IP地址
   我们知道,不同的物理网络技术有不同的编址方式;不同物理网络中的主机,有不同的物理网络地址。网间网技术是将不同物理网络技术统一起来的高层软件技术。网间网技术采用一种全局通用的地址格式,为全网的每一网络和每一主机都分配一个网间网地址,以此屏蔽物理网络地址的差异。
   IP协议提供一种全网间网通用的地址格式,并在统一管理下进行地址分配,保证一个地址对应一台网间网主机(包括网关),这样物理地址的差异被IP层所屏蔽。IP层所用到的地址叫做网间网地址,又叫IP地址。它由网络号和主机号两部分组成,统一网络内的所有主机使用相同的网络号,主机号是唯一的。IP地址是一个32为的二进制数,分成4个字段,每个字段8位。
(2) 三类主要的网络地址
   我们知道,从LAN到WAN,不同种类网络规模相差很大,必须区别对待。因此按网络规模大小,将网络地址分为主要的三类,如图:
A类: 0 1 2 3 8 16 24
31
0
网络号
主机号
B类:
1
0
网络号
主机号
C类:
1
1
0
网络号
主机号
   A类地址用于少量的(最多27个)主机数大于216的大型网,每个A类网络可容纳最多224台主机;B类地址用于主机数介于28~216之间数量不多不少的中型网,B类网络最多214个;C类地址用于每个网络只能容纳28台主机的大量小型网,C类网络最多221个。
   除了以上A、B、C三个主类地址外,还有另外两类地址,如图:
D类:
1
1
1
0
多目地址
E类:
1
1
1
1
0
留待后用
   其中多目地址(multicast address)是比广播地址稍弱的多点传送地址,用于支持多目传输技术。E类地址用于将来的扩展之用。
(3) TCP/IP规定
   网络地址除了一般地标识一台主机外,还有几种具有特殊意义的特殊形式。
* 广播地址
   TCP/IP规定,主机号全为“1”的网络地址用于广播之用,叫做广播地址。
   所谓广播,指同时向网上所有主机发送报文。
* 有限广播
   前面提到的广播地址包含一个有效的网络号和主机号,技术上称为直接广播(directed boradcasting)地址。在网间网上的任何一点均可向其他任何网络进行直接广播,但直接广播有一个缺点,就是要知道信宿网络的网络号。
   有时需要在本网络内部广播,但又不知道本网络网络号。TCP/IP规定,32比特全为“1”的网间网地址用于本网广播,该地址叫做有限广播地址(limited broadcast address)。
* “0”地址
   TCP/IP协议规定,各位全为“0”的网络号被解释成“本”网络。
* 回送地址
   A类网络地址127是一个保留地址,用于网络软件测试以及本地机进程间通信,叫做回送地址(loopback address)。无论什么程序,一旦使用回送地址发送数据,协议软件立即返回之,不进行任何网络传输。
   TCP/IP协议规定,一、含 网络号127的分组不能出现在任何网络上;二、主机和网关不能为该地址广播任何寻径信息。
   由以上规定可以看出,主机号全“0”全“1”的地址在TCP/IP协议中有特殊含义,不能用作一台主机的有效地址





二、 子网掩码
(1) 子网
  TCP/IP网间网技术产生于大型主流机环境中,它能发展到今天的规模是当初的设计者们始料未及的。网间网规模的迅速扩展对IP地址模式的威胁并不是它不能保证主机地址的唯一性,而是会带来两方面的负担:第一,巨大的网络地址管理开销;第二,网关寻径急剧膨胀。其中第二点尤为突出,寻径表的膨胀不仅会降低网关寻径效率(甚至可能使寻径表溢出,从而造成寻径故障),更重要的是将增加内外部路径刷新时的开销,从而加重网络负担。
  因此,迫切需要寻求新的技术,以应付网间网规模增长带来的问题。仔细分析发现,网间网规模的增长在内部主要表现为网络地址的增减,因此解决问题的思路集中在:如何减少网络地址。于是IP网络地址的多重复用技术应运而生。通过复用技术,使若干物理网络共享同一IP网络地址,无疑将减少网络地址数。
  子网编址(subnet addressing)技术,又叫子网寻径(subnet routing),英文简称subnetting,是最广泛使用的IP网络地址复用方式,目前已经标准化,并成为IP地址模式的一部分。
  一般的,32位的IP地址分为两部分,即网络号和主机号,我们分别把他们叫做IP地址的“网间网部分”和“本地部分”。子网编址技术将本地部分进一步划分为“物理网络”部分和“主机”部分,如图:
网间网部分
物理网络
主机
|←网间网部分→|←────本地部分─────→|
  其中“物理网络”用于标识同一IP网络地址下的不同物理网络,既是“子网”。
(2) 子网掩码
  IP协议标准规定:每一个使用子网的网点都选择一个32位的位模式,若位模式中的某位置1,则对应IP地址中的某位为网络地址(包括网间网部分和物理网络号)中的一位;若位模式中的某位置0,则对应IP地址中的某位为主机地址中的一位。例如位模式:11111111 11111111 11111111 00000000中,前三个字节全1,代表对应IP地址中最高的三个字节为网络地址;后一个字节全0,代表对应IP地址中最后的一个字节为主机地址。这种位模式叫做子网模(subnet mask)或“子网掩码”。
  为了使用的方便,常常使用“点分整数表示法”来表示一个IP地址和子网掩码,例如B类地址子网掩码(11111111 11111111 11111111 00000000)为:255.255.255.0
  IP协议关于子网掩码的定义提供一种有趣的灵活性,允许子网掩码中的“0”和“1”位不连续。但是,这样的子网掩码给分配主机地址和理解寻径表都带来一定困难,并且,极少的路由器支持在子网中使用低序或无序的位,因此在实际应用中通常各网点采用连续方式的子网掩码。像255.255.255.64和255.255.255.160等一类的子网掩码不推荐使用。
(3) 子网掩码与IP地址
  子网掩码与IP地址结合使用,可以区分出一个网络地址的网络号和主机号。
例如:有一个C类地址为:
192.9.200.13
其缺省的子网掩码为:
255.255.255.0
则它的网络号和主机号可按如下方法得到:
① 将IP地址192.9.200.13转换为二进制
11000000 00001001 11001000 00001101
② 将子网掩码255.255.255.0转换为二进制
11111111 11111111 11111111 00000000
③ 将两个二进制数逻辑与(AND)运算后得出的结果即为网络部分
11000000 00001001 11001000 00001101
AND
11111111 11111111 11111111 00000000
11000000 00001001 11001000 00000000
  结果为192.9.200.0,即网络号为192.9.200.0。
④ 将子网掩码取反再与IP地址逻辑与(AND)后得到的结果即为主机部分
11000000 00001001 11001000 00001101
AND
00000000 00000000 00000000 11111111
00000000 00000000 00000000 00001101
结果为0.0.0.13,即主机号为13。









三、 子网划分与实例
    根据以上分析,建议按以下步骤和实例定义子网掩码。
    1、 将要划分的子网数目转换为2的m次方。如要分8个子网,8=23。
    2、 取上述要划分子网数的2的m次方的幂。如23,即m=3。
    3、 将上一步确定的幂m按高序占用主机地址m位后转换为十进制。如m为3则是11100000,转换为十进制为224,即为最终确定的子网掩码。如果是C类网,则子网掩码为255.255.255.224;如果是B类网,则子网掩码为255.255.224.0;如果是C类网,则子网掩码为255.224.0.0。
  在这里,子网个数与占用主机地址位数有如下等式成立:2m=n。其中,m表示占用主机地址的位数;n表示划分的子网个数。
    根据这些原则,将一个C类网络分成4个子网。若我们用的网络号为192.9.200,则该C类网内的主机IP地址就是192.9.200.1~192.9.200.254(因为全“0”和全“1”的主机地址有特殊含义,不作为有效的IP地址),现将网络划分为4个部分,按照以上步骤:4=22,取22的幂,即2,则二进制为11,占用主机地址的高序位即为11000000,转换为十进制为192。这样就可确定该子网掩码为:192.9.200.192,4个子网的IP地址范围分别为:
二进制
十进制
① 11000000 00001001 11001000 00000001
~
11000000 00001001 11001000 00111110
192.9.200.1
~
192.9.200.62
② 11000000 00001001 11001000 01000001
~
11000000 00001001 11001000 01111110
192.9.200.65
~
192.9.200.126
③ 11000000 00001001 11001000 10000001
~
11000000 00001001 11001000 10111110
192.9.200.129
~
192.9.200.190
④ 11000000 00001001 11001000 11000001
~
11000000 00001001 11001000 11111110
192.9.200.193
~
192.9.200.254
在此列出A、B、C三类网络子网数目与子网掩码的转换表,以供参考。
A类:
子网数目
占用位数
子网掩码
子网中主机数
2
1
255.128.0.0
8,388,606
4
2
255.192.0.0
4,194,302
8
3
255.224.0.0
2,097,150
16
4
255.240.0.0
1,048,574
32
5
255.248.0.0
524,286
64
6
255.252.0.0
262,142
128
7
255.254.0.0
131,070
128
7
255.255.0.0
65,534
B类:
子网数目
占用位数
子网掩码
子网中主机数
2
1
255.255.128.0
32,766
4
2
255.255.192.0
16,382
8
3
255.255.224.0
8,190
16
4
255.255.240.0
4,094
32
5
255.255.248.0
2,046
64
6
255.255.252.0
1,022
128
7
255.255.254.0
510
256
8
255.255.255.0
254
C类:
子网数目
占用位数
子网掩码
子网中主机数
2
1
255.255.255.128
126
4
2
255.255.255.192
62
8
3
255.255.255.224
30
16
4
255.255.255.240
14
32
5
255.255.255.248
6
64
6
255.255.255.252
2

















HTTP协议 (学习笔记)









HTTP服务器与HTTP客户机之间的会话如下:
    1 客户机与服务器建立联系
    与服务器建立连接,就是与SOCKET建立连接,因此要指定机器名称、资源名称和断口号,可以通过URL来提供这些信息。URL的格式为:
HTTP:///[端口号]/[路径][?<查询信息>]
    资源的缺省值是INDEX或DEFAULT,断口号缺省为80.
    2 客户向服务器提出请求
    请求信息包括希望返回的文件名和客户机信息.客户机信息以请求头发送给服务器,请求头包括HTTP方法和头字段.HTTP方法常用的有GET、HEAD、POST,而PUT、DELETE、LINK、UNLINK方法许多HTTP服务器都不使用。
头字段包括:
。DATE:请求发送的日期和时间
。PARGMA:用于向服务器传输与实现无关的信息。这个字段还用于告诉代理服
务器,要从实际服务器而不是从高速缓存取资源
。FORWARDED:可以用来追踪机器之间,而不是客户机和服务器的消息。这个字段
可以用来追踪在代理服务器之间的传递路由。
。MESSAGE_ID:用于唯一地标识消息
。ACCEPT: 通知服务器客户所能接受的数据类型和尺寸。(*/*表示可以接受
所有类型的数据。
。AOTHORIZATION:向服务器提供旁路安全保护和加密机制,若服务器
不需要这个字段,则不提供这个字段
。FROM:当客户应用程序希望想服务器提供有关其电子邮件地址时使用
。IF-MODEFIED-SINCE用于提供条件GET。如果所请求的文档自从所指定
的日期以来没有发生变化,则服务器应不发送该对象。如果所发送的日期格式不合
法,或晚于服务器的日期,服务器会忽略该字段
。BEFERRER:向服务器进行资源请求用到的对象
。MIME-VERTION:用于处理不同类型文件的MIME协议版本号
。USER-AGENT:有关发出请求的客户信息
3 服务器对请求作出应答
服务器收到一个请求,就会立刻解释请求中所用到的方法,并开始处理应答。
服务器的应答消息也包含头字段形式的报文信息。
。报文第一行是状态行,格式为 <状态代码><解释短语>
状态码是个三位数字码,分为四类:
。以2开头,表示请求被成功处理
。以3开头,表示请求被重定向
。以4开头,表示客户的请求有错
。以5开头,表示服务器不能满足请求
解释短语是对状态码的解释。
。报文还向客户返回几个头字段,如:
。STATUS CODE/REASON PHRASE
。DATE
。LAST-MODIFIED
。SERVER
。CONTENT _TYPE
。RETRY_AFTER:服务器太忙时返回这个字段
。WWW_AUTHENTICATE:当服务器的安全机制要求客户发送某中授权信息时使用该字段
。报文最后是实体信息,即客户请求得到的HTTP服务器上的资源内容。
4 关闭客户与服务器之间的连接

TOP

第三讲     常数









对于API常数来讲,没有什么太特别的学问。请看VB中的以下代码∶
Msg = MsgBox("您好", vbOKCancel)
我们知道, vbOKCancel这个常数的值等于1。对上面的代码我们完全可以这样写,而不会影响代码的功能∶
Msg = MsgBox("您好", 1)
但你大概不太愿意选择后一种,因为这会使得看懂代码费劲起来。这种方法也被API采取了。只是API常数必须在事情之前做好初始化声明VB本身是看不懂的。其内容仍然来自与API
文本游览器。具体形式如下等等∶
Public Const ABM_ACTIVATE = &H6
Public Const RIGHT_CTRL_PRESSED = &H4
Public Const RPC_E_SERVER_DIED = &H80010007
Private Const RPC_S_CALL_FAILED_DNE = 1727&
在常数的初始化中,有些程序使用Global,如Global Const ABM_ACTIVATE = &H6,但我认为Public完全可以代替它。过去我也用过Global,但现在不大用了。一会儿用这个,一会儿用那个,各程序之间不能保持一致性了,起码看起来别扭。












结构









结构是C和C++语言中的说法。在VB中一般称为自定义数据类型。想必很多朋友都已经认识它。在API领域里,我更喜欢把它叫做结构,因为API各种结构类型根本不是我定义(
自定义)的。
在VB中,API结构同样由TYPE.......END TYPE语句来定义。如,在API中,点(Point)结构的定义方法如下:
Public Type POINTAPI
X As Long '点在X坐标(横坐标)上的坐标值
Y As Long '点在Y坐标(纵坐标)上的坐标值
End Type
又如,API中矩形(Rect)结构的定义如下∶
Public Type RECT
Left As Long '矩形左上角的X坐标
Top As Long '矩形左上角的Y坐标
Right As Long '矩形右下角的X坐标
Bottom As Long '矩形右下角的Y坐标
End Type
这些内容同样可以从API文本游览器中拷贝过来。这些结构中的变量名可随意改动,而不会影响结构本身。也就是说,这些成员变量都是虚拟的。如,POINTAPI结构可改为如下∶
Public Type POINTAPI
MyX As Long '点在X坐标(横坐标)上的坐标值
MyY As Long '点在Y坐标(纵坐标)上的坐标值
End Type
不过,一般来讲,是没有这种必要的。结构本身是一种数据类型,因此,使用时必须声明具体变量为该结构型,才能在程序中真正使用到该结构。结构的声明方法和其他数据的声明方法一样,如,以下语句把变MyPoint声明为POINTAPI结构类型∶
MyPoint As POINTAPI
引用结构中的成员变量也十分简单,在结构名后面加上一个".",然后紧接着写要引用的成员变量即可。这很象VB中的引用一个对象的某个属性。如,假如我们把上面已经声明的MyPoint结构中的X变量的值赋给变量Temp&
则代码如下∶
Temp&=MyPoint.X
但,特别注意的是,你千万不要认为上例中的MyPoint是一个值。它不是值,而是地址(
指针)。值和地址是完全不同的概念。结构要求按引用传递给WINDOWS函数,即所有API
函数中,结构都是按ByRef传递的(在Declare语句 中ByRef是默认型)。对于结构的传递,你不要试图采用ByVal,你将一无所获。由于结构名实际上就是指向这个结构的指针(这个结构的首地址),所以,你也就传送特定的结构名就可以了(参见小结,我用红色字体来突出了这种传递方式)。
由于结构传送的是指针,所以函数将直接对结构进行读写操作。这种特性很适合于把函数执行的结果装载在结构之中。












一些API函数集










Windows API
1.控件与消息函数
AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小
AnyPopup 判断屏幕上是否存在任何弹出式窗口
ArrangeIconicWindows 排列一个父窗口的最小化子窗口
AttachThreadInput 连接线程输入函数
BeginDeferWindowPos 启动构建一系列新窗口位置的过程
BringWindowToTop 将指定的窗口带至窗口列表顶部
CascadeWindows 以层叠方式排列窗口
ChildWindowFromPoint 返回父窗口中包含了指定点的第一个子窗口的句柄
ClientToScreen 判断窗口内以客户区坐标表示的一个点的屏幕坐标
CloseWindow 最小化指定的窗口
CopyRect 矩形内容复制
DeferWindowPos 该函数为特定的窗口指定一个新窗口位置
DestroyWindow 清除指定的窗口以及它的所有子窗口
DrawAnimatedRects 描绘一系列动态矩形
EnableWindow 指定的窗口里允许或禁止所有鼠标及键盘输入
EndDeferWindowPos 同时更新DeferWindowPos调用时指定的所有窗口的位置及状态
EnumChildWindows 为指定的父窗口枚举子窗口
EnumThreadWindows 枚举与指定任务相关的窗口
EnumWindows 枚举窗口列表中的所有父窗口
EqualRect 判断两个矩形结构是否相同
FindWindow 寻找窗口列表中第一个符合指定条件的顶级窗口
FindWindowEx 在窗口列表中寻找与指定条件相符的第一个子窗口
FlashWindow 闪烁显示指定窗口
GetActiveWindow 获得活动窗口的句柄
GetCapture 获得一个窗口的句柄,这个窗口位于当前输入线程,且拥有鼠标捕获(鼠标活动由它接收)
GetClassInfo 取得WNDCLASS结构(或WNDCLASSEX结构)的一个副本,结构中包含了与指定类有关的信息
GetClassLong 取得窗口类的一个Long变量条目
GetClassName 为指定的窗口取得类名
GetClassWord 为窗口类取得一个整数变量
GetClientRect 返回指定窗口客户区矩形的大小
GetDesktopWindow 获得代表整个屏幕的一个窗口(桌面窗口)句柄
GetFocus 获得拥有输入焦点的窗口的句柄
GetForegroundWindow 获得前台窗口的句柄
GetLastActivePopup 获得在一个给定父窗口中最近激活过的弹出式窗口的句柄
GetLastError 针对之前调用的api函数,用这个函数取得扩展错误信息
GetParent 判断指定窗口的父窗口
GetTopWindow 搜索内部窗口列表,寻找隶属于指定窗口的头一个窗口的句柄
GetUpdateRect 获得一个矩形,它描叙了指定窗口中需要更新的那一部分
GetWindow 获得一个窗口的句柄,该窗口与某源窗口有特定的关系
GetWindowContextHelpId 取得与窗口关联在一起的帮助场景ID
GetWindowLong 从指定窗口的结构中取得信息
GetWindowPlacement 获得指定窗口的状态及位置信息
GetWindowRect 获得整个窗口的范围矩形,窗口的边框、标题栏、滚动条及菜单等都在这个矩形内
GetWindowText 取得一个窗体的标题(caption)文字,或者一个控件的内容
GetWindowTextLength 调查窗口标题文字或控件内容的长短
GetWindowWord 获得指定窗口结构的信息
InflateRect 增大或减小一个矩形的大小
IntersectRect 这个函数在lpDestRect里载入一个矩形,它是lpSrc1Rect与lpSrc2Rect两个矩形的交集
InvalidateRect 屏蔽一个窗口客户区的全部或部分区域
IsChild 判断一个窗口是否为另一窗口的子或隶属窗口
IsIconic 判断窗口是否已最小化
IsRectEmpty 判断一个矩形是否为空
IsWindow 判断一个窗口句柄是否有效
IsWindowEnabled 判断窗口是否处于活动状态
IsWindowUnicode 判断一个窗口是否为Unicode窗口。这意味着窗口为所有基于文本的消息都接收Unicode文字
IsWindowVisible 判断窗口是否可见
IsZoomed 判断窗口是否最大化
LockWindowUpdate 锁定指定窗口,禁止它更新
MapWindowPoints 将一个窗口客户区坐标的点转换到另一窗口的客户区坐标系统
MoveWindow 改变指定窗口的位置和大小
OffsetRect 通过应用一个指定的偏移,从而让矩形移动起来
OpenIcon 恢复一个最小化的程序,并将其激活
PtInRect 判断指定的点是否位于矩形内部
RedrawWindow 重画全部或部分窗口
ReleaseCapture 为当前的应用程序释放鼠标捕获
ScreenToClient 判断屏幕上一个指定点的客户区坐标
ScrollWindow 滚动窗口客户区的全部或一部分
ScrollWindowEx 根据附加的选项,滚动窗口客户区的全部或部分
SetActiveWindow 激活指定的窗口
SetCapture 将鼠标捕获设置到指定的窗口
SetClassLong 为窗口类设置一个Long变量条目
SetClassWord 为窗口类设置一个条目
SetFocusAPI 将输入焦点设到指定的窗口。如有必要,会激活窗口
SetForegroundWindow 将窗口设为系统的前台窗口
SetParent 指定一个窗口的新父
SetRect 设置指定矩形的内容
SetRectEmpty 将矩形设为一个空矩形
SetWindowContextHelpId 为指定的窗口设置帮助场景(上下文)ID
SetWindowLong 在窗口结构中为指定的窗口设置信息
SetWindowPlacement 设置窗口状态和位置信息
SetWindowPos 为窗口指定一个新位置和状态
SetWindowText 设置窗口的标题文字或控件的内容
SetWindowWord 在窗口结构中为指定的窗口设置信息
ShowOwnedPopups 显示或隐藏由指定窗口所有的全部弹出式窗口
ShowWindow 控制窗口的可见性
ShowWindowAsync 与ShowWindow相似
SubtractRect 装载矩形lprcDst,它是在矩形lprcSrc1中减去lprcSrc2得到的结果
TileWindows 以平铺顺序排列窗口
UnionRect 装载一个lpDestRect目标矩形,它是lpSrc1Rect和lpSrc2Rect联合起来的结果
UpdateWindow 强制立即更新窗口
ValidateRect 校验窗口的全部或部分客户区
WindowFromPoint 返回包含了指定点的窗口的句柄。忽略屏蔽、隐藏以及透明窗口
2.硬件与系统函数
ActivateKeyboardLayout 激活一个新的键盘布局。键盘布局定义了按键在一种物理性键盘上的位置与含义
Beep 用于生成简单的声音
CharToOem 将一个字串从ANSI字符集转换到OEM字符集
ClipCursor 将指针限制到指定区域
ConvertDefaultLocale 将一个特殊的地方标识符转换成真实的地方ID
CreateCaret 根据指定的信息创建一个插入符(光标),并将它选定为指定窗口的默认插入符
DestroyCaret 清除(破坏)一个插入符
EnumCalendarInfo 枚举在指定“地方”环境中可用的日历信息
EnumDateFormats 列举指定的“当地”设置中可用的长、短日期格式
EnumSystemCodePages 枚举系统中已安装或支持的代码页
EnumSystemLocales 枚举系统已经安装或提供支持的“地方”设置
EnumTimeFormats 枚举一个指定的地方适用的时间格式
ExitWindowsEx 退出windows,并用特定的选项重新启动
ExpandEnvironmentStrings 扩充环境字串
FreeEnvironmentStrings 翻译指定的环境字串块
GetACP 判断目前正在生效的ANSI代码页
GetAsyncKeyState 判断函数调用时指定虚拟键的状态
GetCaretBlinkTime 判断插入符光标的闪烁频率
GetCaretPos 判断插入符的当前位置
GetClipCursor 取得一个矩形,用于描述目前为鼠标指针规定的剪切区域
GetCommandLine 获得指向当前命令行缓冲区的一个指针
GetComputerName 取得这台计算机的名称
GetCPInfo 取得与指定代码页有关的信息
GetCurrencyFormat 针对指定的“地方”设置,根据货币格式格式化一个数字
GetCursor 获取目前选择的鼠标指针的句柄
GetCursorPos 获取鼠标指针的当前位置
GetDateFormat 针对指定的“当地”格式,对一个系统日期进行格式化
GetDoubleClickTime 判断连续两次鼠标单击之间会被处理成双击事件的间隔时间
GetEnvironmentStrings 为包含了当前环境字串设置的一个内存块分配和返回一个句柄
GetEnvironmentVariable 取得一个环境变量的值
GetInputState 判断是否存在任何待决(等待处理)的鼠标或键盘事件
GetKBCodePage 由GetOEMCP取代,两者功能完全相同
GetKeyboardLayout 取得一个句柄,描述指定应用程序的键盘布局
GetKeyboardLayoutList 获得系统适用的所有键盘布局的一个列表
GetKeyboardLayoutName 取得当前活动键盘布局的名称
GetKeyboardState 取得键盘上每个虚拟键当前的状态
GetKeyboardType 了解与正在使用的键盘有关的信息
GetKeyNameText 在给出扫描码的前提下,判断键名
GetKeyState 针对已处理过的按键,在最近一次输入信息时,判断指定虚拟键的状态
GetLastError 针对之前调用的api函数,用这个函数取得扩展错误信息
GetLocaleInfo 取得与指定“地方”有关的信息
GetLocalTime 取得本地日期和时间
GetNumberFormat 针对指定的“地方”,按特定的格式格式化一个数字
GetOEMCP 判断在OEM和ANSI字符集间转换的windows代码页
GetQueueStatus 判断应用程序消息队列中待决(等待处理)的消息类型
GetSysColor 判断指定windows显示对象的颜色
GetSystemDefaultLangID 取得系统的默认语言ID
GetSystemDefaultLCID 取得当前的默认系统“地方”
GetSystemInfo 取得与底层硬件平台有关的信息
GetSystemMetrics 返回与windows环境有关的信息
GetSystemPowerStatus 获得与当前系统电源状态有关的信息
GetSystemTime 取得当前系统时间,这个时间采用的是“协同世界时间”(即UTC,也叫做GMT)格式
GetSystemTimeAdjustment 使内部系统时钟与一个外部的时钟信号源同步
GetThreadLocale 取得当前线程的地方ID
GetTickCount 用于获取自windows启动以来经历的时间长度(毫秒)
GetTimeFormat 针对当前指定的“地方”,按特定的格式格式化一个系统时间
GetTimeZoneInformation 取得与系统时区设置有关的信息
GetUserDefaultLangID 为当前用户取得默认语言ID
GetUserDefaultLCID 取得当前用户的默认“地方”设置
GetUserName 取得当前用户的名字
GetVersion 判断当前运行的Windows和DOS版本
GetVersionEx 取得与平台和操作系统有关的版本信息
HideCaret 在指定的窗口隐藏插入符(光标)
IsValidCodePage 判断一个代码页是否有效
IsValidLocale 判断地方标识符是否有效
keybd_event 这个函数模拟了键盘行动
LoadKeyboardLayout 载入一个键盘布局
MapVirtualKey 根据指定的映射类型,执行不同的扫描码和字符转换
MapVirtualKeyEx 根据指定的映射类型,执行不同的扫描码和字符转换
MessageBeep 播放一个系统声音。系统声音的分配方案是在控制面板里决定的
mouse_event 模拟一次鼠标事件
OemKeyScan 判断OEM字符集中的一个ASCII字符的扫描码和Shift键状态
OemToChar 将OEM字符集的一个字串转换到ANSI字符集
SetCaretBlinkTime 指定插入符(光标)的闪烁频率
SetCaretPos 指定插入符的位置
SetComputerName 设置新的计算机名
SetCursor 将指定的鼠标指针设为当前指针
SetCursorPos 设置指针的位置
SetDoubleClickTime 设置连续两次鼠标单击之间能使系统认为是双击事件的间隔时间
SetEnvironmentVariable 将一个环境变量设为指定的值
SetKeyboardState 设置每个虚拟键当前在键盘上的状态
SetLocaleInfo 改变用户“地方”设置信息
SetLocalTime 设置当前地方时间
SetSysColors 设置指定窗口显示对象的颜色
SetSystemCursor 改变任何一个标准系统指针
SetSystemTime 设置当前系统时间
SetSystemTimeAdjustment 定时添加一个校准值使内部系统时钟与一个外部的时钟信号源同步
SetThreadLocale 为当前线程设置地方
SetTimeZoneInformation 设置系统时区信息
ShowCaret 在指定的窗口里显示插入符(光标)
ShowCursor 控制鼠标指针的可视性
SwapMouseButton 决定是否互换鼠标左右键的功能
SystemParametersInfo 获取和设置数量众多的windows系统参数
SystemTimeToTzSpecificLocalTime 将系统时间转换成地方时间
ToAscii 根据当前的扫描码和键盘信息,将一个虚拟键转换成ASCII字符
ToUnicode 根据当前的扫描码和键盘信息,将一个虚拟键转换成Unicode字符
UnloadKeyboardLayout 卸载指定的键盘布局
VkKeyScan 针对Windows字符集中一个ASCII字符,判断虚拟键码和Shift键的状态

3.菜单函数
AppendMenu 在指定的菜单里添加一个菜单项
CheckMenuItem 复选或撤消复选指定的菜单条目
CheckMenuRadioItem 指定一个菜单条目被复选成“单选”项目
CreateMenu 创建新菜单
CreatePopupMenu 创建一个空的弹出式菜单
DeleteMenu 删除指定的菜单条目
DestroyMenu 删除指定的菜单
DrawMenuBar 为指定的窗口重画菜单
EnableMenuItem 允许或禁止指定的菜单条目
GetMenu 取得窗口中一个菜单的句柄
GetMenuCheckMarkDimensions 返回一个菜单复选符的大小
GetMenuContextHelpId 取得一个菜单的帮助场景ID
GetMenuDefaultItem 判断菜单中的哪个条目是默认条目
GetMenuItemCount 返回菜单中条目(菜单项)的数量
GetMenuItemID 返回位于菜单中指定位置处的条目的菜单ID
GetMenuItemInfo 取得(接收)与一个菜单条目有关的特定信息
GetMenuItemRect 在一个矩形中装载指定菜单条目的屏幕坐标信息
GetMenuState 取得与指定菜单条目状态有关的信息
GetMenuString 取得指定菜单条目的字串
GetSubMenu 取得一个弹出式菜单的句柄,它位于菜单中指定的位置
GetSystemMenu 取得指定窗口的系统菜单的句柄
HiliteMenuItem 控制顶级菜单条目的加亮显示状态
InsertMenu 在菜单的指定位置处插入一个菜单条目,并根据需要将其他条目向下移动
InsertMenuItem 插入一个新菜单条目
IsMenu 判断指定的句柄是否为一个菜单的句柄
LoadMenu 从指定的模块或应用程序实例中载入一个菜单
LoadMenuIndirect 载入一个菜单
MenuItemFromPoint 判断哪个菜单条目包含了屏幕上一个指定的点
ModifyMenu 改变菜单条目
RemoveMenu 删除指定的菜单条目
SetMenu 设置窗口菜单
SetMenuContextHelpId 设置一个菜单的帮助场景ID
SetMenuDefaultItem 将一个菜单条目设为默认条目
SetMenuItemBitmaps 设置一幅特定位图,令其在指定的菜单条目中使用,代替标准的复选符号(√)
SetMenuItemInfo 为一个菜单条目设置指定的信息
TrackPopupMenu 在屏幕的任意地方显示一个弹出式菜单
TrackPopupMenuEx 与TrackPopupMenu相似,只是它提供了额外的功能

以下是几个关于菜单函数的类型定义
MENUITEMINFO 这个结构包含了菜单条目的信息
TPMPARAMS 这个结构用于TrackPopupMenuEx函数以支持额外的功能
4.绘图函数
AbortPath 抛弃选入指定设备场景中的所有路径。也取消目前正在进行的任何路径的创建工作
AngleArc 用一个连接弧画一条线
Arc 画一个圆弧
BeginPath 启动一个路径分支
CancelDC 取消另一个线程里的长时间绘图操作
Chord 画一个弦
CloseEnhMetaFile 关闭指定的增强型图元文件设备场景,并将新建的图元文件返回一个句柄
CloseFigure 描绘到一个路径时,关闭当前打开的图形
CloseMetaFile 关闭指定的图元文件设备场景,并向新建的图元文件返回一个句柄
CopyEnhMetaFile 制作指定增强型图元文件的一个副本(拷贝)
CopyMetaFile 制作指定(标准)图元文件的一个副本
CreateBrushIndirect 在一个LOGBRUSH数据结构的基础上创建一个刷子
CreateDIBPatternBrush 用一幅与设备无关的位图创建一个刷子,以便指定刷子样式(图案)
CreateEnhMetaFile 创建一个增强型的图元文件设备场景
CreateHatchBrush 创建带有阴影图案的一个刷子
CreateMetaFile 创建一个图元文件设备场景
CreatePatternBrush 用指定了刷子图案的一幅位图创建一个刷子
CreatePen 用指定的样式、宽度和颜色创建一个画笔
CreatePenIndirect 根据指定的LOGPEN结构创建一个画笔
CreateSolidBrush 用纯色创建一个刷子
DeleteEnhMetaFile 删除指定的增强型图元文件
DeleteMetaFile 删除指定的图元文件
DeleteObject 删除GDI对象,对象使用的所有系统资源都会被释放
DrawEdge 用指定的样式描绘一个矩形的边框
DrawEscape 换码(Escape)函数将数据直接发至显示设备驱动程序
DrawFocusRect 画一个焦点矩形
DrawFrameControl 描绘一个标准控件
DrawState 为一幅图象或绘图操作应用各式各样的效果
Ellipse 描绘一个椭圆,由指定的矩形围绕
EndPath 停止定义一个路径
EnumEnhMetaFile 针对一个增强型图元文件,列举其中单独的图元文件记录
EnumMetaFile 为一个标准的windows图元文件枚举单独的图元文件记录
EnumObjects 枚举可随同指定设备场景使用的画笔和刷子
ExtCreatePen 创建一个扩展画笔(装饰或几何)
ExtFloodFill 在指定的设备场景里,用当前选择的刷子填充一个区域
FillPath 关闭路径中任何打开的图形,并用当前刷子填充
FillRect 用指定的刷子填充一个矩形
FlattenPath 将一个路径中的所有曲线都转换成线段
FloodFill 用当前选定的刷子在指定的设备场景中填充一个区域
FrameRect 用指定的刷子围绕一个矩形画一个边框
GdiComment 为指定的增强型图元文件设备场景添加一条注释信息
GdiFlush 执行任何未决的绘图操作
GdiGetBatchLimit 判断有多少个GDI绘图命令位于队列中
GdiSetBatchLimit 指定有多少个GDI绘图命令能够进入队列
GetArcDirection 画圆弧的时候,判断当前采用的绘图方向
GetBkColor 取得指定设备场景当前的背景颜色
GetBkMode 针对指定的设备场景,取得当前的背景填充模式
GetBrushOrgEx 判断指定设备场景中当前选定刷子起点
GetCurrentObject 获得指定类型的当前选定对象
GetCurrentPositionEx 在指定的设备场景中取得当前的画笔位置
GetEnhMetaFile 取得磁盘文件中包含的一个增强型图元文件的图元文件句柄
GetEnhMetaFileBits 将指定的增强型图元文件复制到一个内存缓冲区里
GetEnhMetaFileDescription 返回对一个增强型图元文件的说明
GetEnhMetaFileHeader 取得增强型图元文件的图元文件头
GetEnhMetaFilePaletteEntries 取得增强型图元文件的全部或部分调色板
GetMetaFile 取得包含在一个磁盘文件中的图元文件的图元文件句柄
GetMetaFileBitsEx 将指定的图元文件复制到一个内存缓冲区
GetMiterLimit 取得设备场景的斜率限制(Miter)设置
GetNearestColor 根据设备的显示能力,取得与指定颜色最接近的一种纯色
GetObjectAPI 取得对指定对象进行说明的一个结构
GetObjectType 判断由指定句柄引用的GDI对象的类型
GetPath 取得对当前路径进行定义的一系列数据
GetPixel 在指定的设备场景中取得一个像素的RGB值
GetPolyFillMode 针对指定的设备场景,获得多边形填充模式
GetROP2 针对指定的设备场景,取得当前的绘图模式
GetStockObject 取得一个固有对象(Stock)
GetSysColorBrush 为任何一种标准系统颜色取得一个刷子
GetWinMetaFileBits 通过在一个缓冲区中填充用于标准图元文件的数据,将一个增强型图元文件转换成标准windows图元文件
InvertRect 通过反转每个像素的值,从而反转一个设备场景中指定的矩形
LineDDA 枚举指定线段中的所有点
LineTo 用当前画笔画一条线,从当前位置连到一个指定的点

TOP

第二讲    数据类型与"类型安全"








API函数中使用的数据类型基本上和VB中的一样。但作为WIN32的API函数中,不存在Integer
数据类型。另外一点是在API函数中看不到Boolean数据类型。 Variant数据类型在API函数中是以Any的形式出现,如Data As Any。尽管其含义是允许任意参数类型作为一个该API函数的参数传递,但这样做存在一定的缺点。其原因是,这将会使得对目标参数的所有类型检查都会被关闭。这自然会给各种类型的参数调用带来了产生错误的机会。
为了强制执行严格的类型检查,并避免上面提到的问题,一个办法是在函数里使用上面提到到Alias技术。如对API函数 GetDIBits 可进行另外一种声明方法。如下∶
GetDIBits函数的原型∶
Public Declare Function GetDIBits Lib "gdi32" Alias "GetDIBits" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
GetDIBits函数的改型∶
Public Declare Function GetDIBitsLong Lib "gdi32" Alias "GetDIBits" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Long, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long
通过本课程前面所学到的知识,我们已经可以得知原型 GetDIBits函数也好,改型 GetDIBitsLong函数也好,实际将调用的都是Alias所指定的 GetDIBits原函数。但你应当看到,两者的区别在于,我们在改型的函数中强制指定lpBits参数为Long形。这样就会使得函数调用中发生的错误机率减少到了最小。这种方法叫做"安全类型"声明。
API函数中经常看到的数据类型有∶Long,String,Byte,Any....(也就这些吧。)

TOP

返回列表