VB的API编程精粹(二)
清醒时做事,糊涂时读书,大怒时睡觉,无聊时关注图老师为大家准备的精彩内容。下面为大家推荐VB的API编程精粹(二),无聊中的都看过来。
第一节:API基础
API说到底就是一系列的底层函数,是系统提供给用户用于进入操作系统核心,进行高级编程的途径。通过在VisualBasic应用程序中声明外部过程就能够访问WindowsAPI(以及其它的外部DLLs)。在声明了过程之后,调用它的方法与调用VisualBasic自己的过程相同。要声明一个DLL过程,需要在代码窗口的"声明"部分增加一个Declare语句,如果该过程返回一个值,应将其声明为Function。例如:
DeclareFunctionpublicnameLib"libname"[Alias"alias"][([[ByVal]variable[Astype][,[ByVal]variable[Astype]]...])]AsType
如果过程没有返回值,可将其声明为Sub。
缺省情况下,在标准模块中声明的DLL过程,可以在应用程序的任何地方调用它。在其他类型的模块中定义的DLL过程是模块私有的,必须在它们前面加上Private关键字,以示区分。特别提请注意的是,在32位的VisualBasic中过程名是区分大小写的。而在以前的16位版本中并不区分大小写,这是初学者容易出错的地方。
Declare语句中的Lib子句用来告诉VisualBasic如何找到包含该过程的dll文件。如果引用的过程属于Windows核心库(User32、Kernel32或GDI32),则可以不包含文件扩展名。例如:
DeclareFunctionGetTickCountLib"kernel32"Alias"GetTickCount"()AsLong。对于其它DLL,Lib子句须指定文件的路径及扩展名。
如果调用的WindowsAPI过程要使用字符串,那么在声明语句中必须增加一个Alias子句,以指定正确的字符集。包含字符串的WindowsAPI函数实际有两种格武ANSI格式Unicode格式。因此,在Windows头文件中,每个包含字符串的函数都同时有ANSI版本和Unicode版本。
例如,下面是SetWindowText函数的两种C语言描述。可以看到,第一个描述将函数定义为SetWindowTextA,尾部的"A"表明它是一个ANSI函数:
SetWindowTextA(HWNDhWnd,LPCSTRlpString);
第二个描述将它定义为SetWindowTextW,尾部的"w"表明它是一个Unicode函数:
SetWindowTextW(HWNDHwnd,LPCWSTRlpString);
因为两个函数实际的名称都不是"SetWindowText",要引用正确的函数就必须增加一个Alias子句:
PrivateDeclareFunctionSetwindowTextLib"user32"Alias"SetWindowTextA"(ByValhwndAsLongg,ByVallpStringAsString)AsLong
请注意,Alias子句后面的字符串必须是过程的真正名称,必须是区分大小写的。事实上,您只需要记住,只有WindowsNT才支持Unicode格式,而Windows95只支持ANSI格式就行了。至于两者的区别,作一般的应用程序开发是不需要了解的。
VB5专业版在VB目录的Winapi子目录下,用几个文件提供了关于API的信息。Win32api.txt文件中包含了32位WindowsAPI函数中用到的函数和类型的结构声明以及全局常量的值。用户可以用VB本身带的外接程序"API浏览器"来方便地使用Win32api.Txt,如下所示:
点击菜单文件项的"加载文本文件…"从VB目录下的WINAPI目录中选择"WIN32API.TXT",就可以查看WINDOWS95系统的API函数的声明、常数定义和数据类型了。例如,我们打算查看函数InverRect()的声明。首先,点击"搜索"按钮,输入字符串"InverRect"。在"可选项"栏中,兰色的亮度条将移动到"InverRect"项上。再点按"添加"按钮,在"选定项"中就出现"InverRect"在VisualBasic中的声明了。接下来自然是点按"复制"按钮,然后将窗口切换到VisualBasic开发环境中,在需要声明API函数的地方Ctrl+V(粘贴)即可。
上面所讲的声明方法虽然简单,但只有使用WINDOWS本身的API函数才能这样。对于第三方提供的动态链接库(DLL)您只有用键盘老老实实地敲了。
第二节:牛刀小试
现在读者一定很想自己亲自试一下,下面举两个实际应用的例子让大家体会一下API的妙用吧!
1.使一个窗体始终保持在屏幕的最上面
我们知道VB本身自带的函数是难以完成此功能的,我们可以通过调用Windows的API函数:SetWindowPos达到我们的要求。操作步骤如下:
(1)启动VB5建立一个新工程,在该工程中添加一个模块(Moudel),在该模块中用上述的"API例览器"添加如下的该API函数的函数声明和常量声明部分:
'API函数声明
DeclareFunctionSetWindowPosLib"user32"Alias"SetWindowPos"(ByValhwndAsLong,ByValhWndInsertAfterAsLong,ByValxAsLong,ByValyAsLong,ByValcxAsLong,ByValcyAsLong,ByValwFlagsAsLong)AsLong
'常量声明
GlobalConstSWP_HIDEWINDOW=&H80
GlobalConstSWP_NOACTIVATE=&H10
GlobalConstSWP_NOCOPYBITS=&H100
GlobalConstSWP_NOMOVE=&H2
GlobalConstSWP_NOOWNERZORDER=&H200
GlobalConstSWP_NOREDRAW=&H8
GlobalConstSWP_NOREPOSITION=SWP_NOOWNERZORDER
GlobalConstSWP_NOSIZE=&H1
GlobalConstSWP_NOZORDER=&H4
GlobalConstSWP_SHOWWINDOW=&H40
GlobalConstHWND_BOTTOM=1
GlobalConstHWND_BROADCAST=&HFFFF&
GlobalConstHWND_DESKTOP=0
GlobalConstHWND_NOTOPMOST=-2
GlobalConstHWND_TOPMOST=-1
GlobalConstHWND_TOP=0
GlobalConstFlags=SWP_NOMOVEOrSWP_NOSIZE
这里以"SWP_"开头的常量是表示窗体所具有的风格,这些常量可以通过VB中的"OR"操作符组合在一起。而以"HWND_"开头的常量表示窗体在桌面上的位置。从这些常量的英文单词的意义上读者应该很容易理解他们所具有的风格了。所以笔者就不一一去说明了。至于为什么要添加这些常量而不是别的这就要您去查看WindowsSDK关于该函数的帮助文档了。当然这对于初学者来说有一定的难度,但不要畏惧,只要您仔细看帮助就会慢慢搞懂的。因为这些API函数是为C和C++的编程人员编写的,所以如果您懂一点C 的话会很容易理解的。
(2)现在只要在您想要此功能的地方调用该函数就可以了,调用的方法如:
DimSuccessasLong
SuccesS=SetwindowPos(me.HWnd.HWND_TOPMOST,0,0,0,0,FLAGS)
若Success返回的值不等于零则表示调用成功。
比如在某个窗体的Load事件中加入上述的两行代码,就可以达到使该窗体始终位于屏幕最上面的目的。
细心的读者可能已经发现上面的例子中的模块声明中声明了好几个常量,可为什么只用到三个呢?现在您可以试着改变一下API函数"SetWindowPos"中的第二个参数或常量FLAGS中的项,看看您的窗体会出现什么样的效果?
2.VB5中如何屏蔽掉win95中的CTRL_ALT_DEL,CTRL_ESC,ALT_TAB三组热键通过调用API函数"SystemParametersInfo"来实现。
首先创建一新工程;在此工程中添加一个窗体和一个模块;在窗体上拖放两个按钮分别命名为"cmdDisable","cmdEnable";Copy如下代码入模块中:
PublicDeclareFunctionSystemParametersInfoLib"user32"Ahias"SystemParametersInfoA"(ByValuActionAsLong,ByValuParamAsLong,lpvParamAsAny,ByValfuWinIniAsLong)ASLong
PublicConstSPI_SCREENSAVERRUNNING=97
在窗体的代码编辑区Copy如下代码:
'使三组热键失效
PrivateSubcmdDisable_click()
SystemParametersInfo
SPI_SCREENSAVERRUNNING,True,byVal1&,0
EndSub
PrivateSubForm_Unload(CancelAsInteger)
'程序退出前是热键有效
CndEnable_Click
EndSub
若将此功能和屏幕保护程序结合到一起,那您的屏幕保护程序一定增色许多。
API函数的简单调用例子就是这么容易,相信现在您对API的调用已不再感到神秘了,接下来我们就看看一个比较复杂的应用。
第三节:高手进阶
上面的关于API的调用的例子只是为了带您去WindowsAPI世界中去探索一下。相信您已探索到了一点眉目并想去实现一些更"好玩"的东西了。好!下面就向您介绍一个很"好玩"同时又会使您的程序看起来更专业化的一个API调用。
相信您的机器上一定装有"金山词霸",试着启动它您发现了什么?启动画面过后它"不见了"。把鼠标移到桌面的右下角,原来它以图标的形式"藏在"Windows的托盘中。用鼠标右击它还会弹出一个菜单功能项供您选择。现在您一定想把自己的程序也放到托盘,这样您的程序多具有专业水准!
下面是此功能的实现步骤:
1.这里我们调用的API函数是:"Shell_NotifyIcon",在您的模块中添加如下的函数声明和常量声明:
'以下常量告诉系统在托盘中您的图标上发生了什么操作
'常量声明
PublicConstWM_MOUSEMOVE=&H200'在图标上移动鼠标
PublicConstWM_LBUTTONDOWN=&H201'鼠标左键按下
PublicConstWM_LBUTTONUP=&H202'鼠标左键释放
PublicConstWM_LBUTTONDBLCLK=&H203'双击鼠标左键
PublicConstWM_RBUTTONDOWN=&H204'鼠标右键按下
PublicConstWM_RBUTTONUP=&H205'鼠标右键释放
PublicConstWM_RBUTTONDBLCLK=&H206'双击鼠标右键
PublicConstWM_SETHOTKEY=&H32'响应您定义的热键
'API函数声明
PublicDeclareFunctionShell_NotifyIconLib"shell32.dll"Alias"Shell_NotifyIconA"(ByValdwMessageAsLong,lpDataAsNOTIFYICONDATA)AsLong
'自定义一个调用APIShell_NotifyIcon要用到的类型"NOTIFYICONDATA"
PublicTypeNOTIFYICONDATA
cdSizeAsLong'NOTIFYICONDATA类型的大小
hwndAsLong'你的应用程序窗体的名柄
uIdAsLong'应用程序图标资源的ID号
uFlagsAsLong'使那些参数有效它是以下枚举类型中的
'NIF_MESSAGE、NIF_ICON、NIF_TIP三组的组合
uCallbackMessageAsLong'鼠标移动时把此消息发给该图标的窗体
hIconAsLong'图标名柄
szTipAsString*64'当鼠标在图标上时显示的Tip文本
EndType
'这是一个枚举类型它告诉APIShell_NotifyIcon去做什么操作
PublicEnumenm_NIM_Shell
NIM_ADD=&H40'在“金碟”中加一图标
NIM_MODIFY=&H1'修改“金碟”中的图标
NIM_DELETE=&H2'删除“金碟”中的图标
NIF_MESSAGE=&H1'使类型"NOTIFYICONDATA"中的uCallbackMessage有效
NIF_ICON=&H2'使类型"NOTIFYICONDATA"中的hIcon有效
NIF_TIP=&H4'使类型"NOTIFYICONDATA"中的szTip有效
WM_MOUSEMOVE=&H200'使鼠标移动消息有效
EndEnum
'定义一个"NOTIFYICONDATA"类型的变量
PublicnidProgramDataAsNOTIFYICONDATA
以上是函数及常量声明和自定义的一个类型变量,下面是此API函数的调用方法:
2.在窗体上用菜单编辑一个具有如下信息的菜单项:
主菜单:无标题、名称(mainMenu)
子菜单:标题(API编程)、名称(submnul);
标题(退出)、名称(submnu2).
这里只是举个例子,具体的功能你可以根据你的具体需要来编辑此菜单项
3.在窗体的Load事件中添加如下代码:
PrivateSubForm_Load()
'隐藏窗体
WithMe
.Top=-10000
.Left=-10000
.WindowState=vbMinimized
EndWith
'设置类型NOTIFYICONDATA所具有的特征
WithnidprogramData
.cbSize=Len(nidProgramData)
.hwnd=Me.hwnd.uld=vbNull
.uFlags=NIF_ICONOrNIF_TIPOrNIF_MESSAGE
'触发鼠标移动消息
.uCallbackMessage=WM_MOUSEMOVE
.hIcon=Me.Icon'“托盘”中放入窗体图标,你可以把窗体的图标换成你所喜欢的图标
.szTip="VB的Win32API编程"&vbNullChar
EndWith
'调用该函数
Shell_NotifyIconNIM_ADD,nidprogramData
EndSub
'根据不同的鼠标消息做不同的操作
PrivateSubForm_MouseMove(ButtonAsinteger,ShiftAslnteger,xAsSingle,YAsSingle)
OnErrorGoToForm_MouseMove_err:
DimResultAsLong
DimmsgAsLong
'X的值依赖与显示模式的设置
IfMe.ScaleMode=vbpixelsThen
msg=x
Else
msg=x/Screen.TwipsPerPixe1X
EndIf
SelectCasemsg
CaseWM_LBUTTONUP
'在这里加入鼠标左键释放时你想做的操作
CaseWM_LBUTTONDBLCLK
'在这里加入双击鼠标左键时你想做的操作
CaseWM_RBUTTONUP
'通常这里弹出你的功能菜单
PopupMenumainMenu
CaseWM_MOUSEISMOVING
'在这里加入鼠标正在移动时你想做的操作
EndSelect
ExitSub
Form_MouseMove_err:
'在这里加入你的处理异常错误的代码
EndSub
4.Run你的程序,您是不是看到了象“金山词霸”一样的功能?相信你此时的感觉一定特别“爽”!
API的世界j是丰富多彩的,只要你肯细心地去探索它你一定会获得许多意想不到的好东西。所以笔者觉得定值得每一个具有“好奇”精神的人去探索它。后续的期刊笔者会向读者详细介绍一些更好更“牛”的API调用。->