精华内容
下载资源
问答
  • 主要内容是,自定义函数过程和子过程声明与调用的语法格式、参数含义及功能特性;三种参数传递方式(值传递、地址传递、数组传递)的应用;嵌套调用和递归调用的执行流程以及递归过程的特点
  • VB6.0 使用递归过程实现阶乘运算  Function F(n As Integer) As Single  If n > 1 And n  F = n * F(n - 1)  Else  F = 1  End If  End Function  Private Sub Command1_Click()  Text2.Text = F(Val(Text...
  • VB Sub子过程调用程序设计Sub子过程调用程序设计Sub子过程调用程序设计Sub子过程调用程序设计Sub子过程调用程序设计Sub子过程调用程序设计
  • 该子过程含有数组参数,在调用子过程时,提示数组参数未定义的错误。 下面是该程序,请热心人帮忙检查检查,谢谢大家! Sub ssor(a() As Single, n As Integer, b() As Single, x() As Single, eps As Single, ...
  • VB过程求组合数.rar

    2019-07-10 11:26:47
     Call f(m, f1) '调用子过程,求m的阶乘  c = f1 '阶乘的结果存到变量c里  Call f(n, f1) '调用子过程,求n的阶乘  c = c / f1 '阶乘的结果参与运算然后再存回变量c里  Call f(m - n, f1) '调用子过程,求同m-n...
  • vb中函数的调用与参数的传递

    千次阅读 2010-12-14 20:54:00
    <br />形参如果是数组必须加小括号 如:定义过程 sub em( pay() as Single) 调用过程 em(xu()) 按值传递(ByVal):形参和实参占有不同的存储空间,调用过程改变了形参变量的值,实参的值...

    形参如果是数组必须加小括号

    如:定义过程  sub em( pay() as Single)

    调用过程    em(xu())

    按值传递(ByVal:形参和实参占有不同的存储空间,调用过程改变了形参变量的值,实参的值不会受影响。调用结束后,实参还是调用之前的值,

    Private Sub Command1_Click()

    Dim x As Integer

    x = 6

    Print "调用sub过程前x="; x

    Call test(x)

    Print "调用sub过程后x="; x

    End Sub

    Sub test(ByVal m As Integer)

    m = m + 5

    End Sub

     

     


    按地址传递(ByRef,默认的传递方式:调用过程,实参变量的地址传递给形参,使用相同的地址,因此使用相同的数据类型,只有实参是变量或数组时才能按地址传递,如果是常量,实际进行的是按值传递

    Private Sub Command1_Click()

    Dim x As Integer

    x = 6

    Print "调用sub过程前x="; x

    Call test(x)

    Print "调用sub过程后x="; x

    End Sub

    Sub test(ByRef m As Integer)

    m = m + 5

    End Sub

     

    数组做参数时是按地址传递参数的,不能使用关键字“ByVal”修饰形参

    展开全文
  • VB.NET在进程中调用主进程控件的方法当前遇到的问题:VB.NET窗体应用程序。在主进程中查询电脑网卡信息是个非常耗时的操作。实际的软件的应用中影响windows窗体的加载速度。现想达到一个要求,就是将非常耗时的...

    当前遇到的问题:VB.NET窗体应用程序。在主进程中查询电脑网卡信息是个非常耗时的操作。实际的软件的应用中影响windows窗体的加载速度。现想达到一个要求,就是将非常耗时的操作放在子进程中操作,主进程加载窗体时不受影响,等到耗时操作查询网卡信息完成,再将结果通过调用主进程中的控件显示出来。

    解决方案:使用代理机制,具体代码如下。
    1. 声明一个代理,要使用关键字 Delegate
    Public Delegate Sub MyDelegate()
    2. 主进程中起一个子进程,子进程中指定相应代理。
    Private Sub IndexForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Dim th1 = New Thread(AddressOf MyThreadProc)
            th1.Start()
    End Sub
    3. 定义子进程中代理函数,该函数使用声明好的代理来执行耗时操作。
    Public Sub MyThreadProc()
            Me.Invoke(New MyDelegate(AddressOf UpdateText))
    End Sub
    
    4. 定义代理需要使用的函数,耗时操作和主进程中的控件调用就放在该函数中。该函数作用是查询本机IP地址。
    Public Sub UpdateText()
            Dim strComputer = "."
            Dim ints() = NetworkInterface.GetAllNetworkInterfaces()
            Local_MAC.Text = ints(0).GetPhysicalAddress().ToString()
            Dim objWMI = GetObject("winmgmts://" & strComputer & "/root/cimv2")
            Dim colIP = objWMI.ExecQuery("Select * from Win32_NetworkAdapterConfiguration where IPEnabled=TRUE")
            For Each IP In colIP
                Me.Local_IP.Text = IP.IPAddress(0).ToString()
                Exit For
            Next
      End Sub
    
    展开全文
  • VB如何调用DLL

    千次阅读 2014-04-21 16:09:22
    等)调用。动态连接库包含两种函数:输出(exported)函数和内部(internal)函数。输出函数可以被其它模块调用,而内部函数则只能在动态连接库内部使用。尽管动态连接库也能输出数据,但实际上它的数据通常是只在...
    Windows动态连接库是包含数据和函数的模块,可以被其它可执行文件(
    EXEDLLOCX 等)调用。动态连接库包含两种函数:输出(
    exported)函数和内部(
    internal)函数。输出函数可以被其它模块调用,而内部函数则只能在动态连接库内部使用。尽管动态连接库也能输出数据,但实际上它的数据通常是只在内部使用的。使用动态连接库的优点是显而易见的。将应用程序的一部分功能提取出来做成动态连接库,不但减小了主应用程序的大小,提高了程序运行效率,还使它更加易于升级。多个应用程序共享一个动态连接库还能有效地节省系统资源。正因为如此,在
    Windows系统中,动态连接库得到了大量的使用。 
    

      一般来说,动态连接库都是以DLL为扩展名的文件,如Kernel32.dllcommdlg.dll等。但也有例外,如16Windows的核心部件之一GDI.exe其实也是一个动态库。编写动态连接库的工具很多,如VisualC++BorlandC++Delphi等,具体方法可以参见相关文档。下面只以Visual C++6.0为例,介绍一下开发应用于VisualBasic6.0的动态连接库时应注意的问题(本文中所有涉及C/C++语言或编译环境的地方,都以VC为例;所有涉及Visual Basic的地方都以VB 为例)。

      作为一种32Windows应用程序的开发工具,VB生成的exe文件自然也都是32位的,通常情况下也只能调用32位的动态连接库。但是,并不是所有的32位动态库都能被VB生成的exe 文件正确地识别。一般来说,自己编写用于VB应用程序调用的动态连接库时,应注意以下几个方面的

    问题:

      1、生成动态库时要使用__stdcall调用约定,而不能使用缺省的__cdecl调用约定;__stdcall 约定通常用于32API函数的调用。

      2、在VC中的定义文件(.def)中,必须列出输出函数的函数名,以强制VC系统将输出函数的装饰名(decoratedname)改成普通函数名;所谓装饰名是VC的编译器在编译过程中生成的输出函数名,它包含了用户定义的函数名、函数参数及函数所在的类等多方面的信息。由于在VC中定义文件不是必需的,因此工程不包含定义文件时VC就按自己的约定将用户定义的输出函数名修改成装饰名后放到输出函数列表中,这样的输出函数在VB生成的应用程序中是不能正确调用的(除非声明时使用Alias子句)。因此需要增加一个.def文件,其中列出用户需要的函数名,以强制VC不按装饰名进行输出。

      3VC中的编译选项"结构成员对齐方式(structure member alignment" 应设成4字节,其原因将在后文详细介绍。

      4、由于在C中整型变量是4个字节,而VB中的整型变量依然只有2个字节,因此在C中声明的整型(int)变量在VB中调用时要声明为长整型(long),而C中的短整型(short)在VB中则要声明成整型(integer);下表针对最常用的C语言数据类型列出了与之等价的Visual Basic 类型(用于32位版本的Windows)。

    C语言数据类型在VisualBasic中声明为调用时使用的表达式

       ATOM ByVal variable As Integer 结果为Integer 类型的表达式

       BOOL ByVal variable As Long 结果为 Long 类型的表达式

       BYTE ByVal variable As Byte 结果为 Byte 类型的表达式

       CHAR ByVal variable As Byte 结果为 Byte 类型的表达式

       COLORREF ByVal variable As Long 结果为 Long 类型的表达式

       DWORD ByVal variable As Long 结果为 Long 类型的表达式

       HWND, HDC, HMENU ByVal variable As Long 结果为 Long 类型的表达式等Windows 句柄

       INT, UINT ByVal variable As Long 结果为 Long 类型的表达式

       LONG ByVal variable As Long 结果为 Long 类型的表达式

       LPARAM ByVal variable As Long 结果为 Long 类型的表达式

       LPDWORD variable As Long 结果为 Long 类型的表达式

       LPINT, LPUINT variable As Long 结果为 Long 类型的表达式

       LPRECT variable As type 自定义类型的任意变量

       LPSTR, LPCSTR ByVal variable As String 结果为 String 类型的表达式

       LPVOID variable As Any 任何变量(在传递字符串的时候使用ByVal

       LPWORD variable As Integer 结果为Integer 类型的表达式

       LRESULT ByVal variable As Long 结果为 Long 类型的表达式

       NULL As Any ByVal Nothing

       ByVal variable As Long ByVal 0& VBNullString

       SHORT ByVal variable As Integer 结果为Integer 类型的表达式

       VOID Sub procedure 不可用

       WORD ByVal variable As Integer 结果为Integer 类型的表达式

       WPARAM ByVal variable As Long 结果为 Long 类型的表达式

      5VB中进行32位动态库的声明时,函数名是大小写敏感的。在获得了需要的动态连接库之后,就可以在VB中进行调用了。但是,由于VB不能验证应用程序传递到动态连接库中的参数值是否正确,因此VB程序中大量的API调用可能会降低整个应用程序的稳定性,也会增加以后维护的难度。所以,决定在VB程序中直接调用API函数时要慎重,但适当的使用API调用确实能够有效地提高VB程序的性能。这之间的平衡需要编程人员根据实际情况来掌握。下面就具体介绍一下在VB中调用API函数时需要做的工作。

      要声明一个DLL过程,首先需要在代码窗口的"通用(General"部分增加一个Declare语句。如果该过程返回一个值,应将其声明为

    Function

       Declare Function publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])] As Type 

      如果过程没有返回值,可将其声明为Sub

       Declare Sub publicname Lib "libname" [Alias "alias"] [([[ByVal] variable [As type] [,[ByVal] variable [As type]]...])] 

      缺省情况下,在标准模块中声明的DLL过程,可以在应用程序的任何地方调用它。在其它类型的模块中定义的DLL过程则是模块私有的,必须在它们前面声明Private关键字,以示区分。下面分别介绍声明语句的各个组成部分。

      ()、指定动态库:

      Declare语句中的Lib子句用来告诉Visual Basic如何找到包含过程的.dll文件。如果引用的过程属于Windows核心库(User32Kernel32GDI32),则可以不包含文件扩展名,如:

       Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount" () As Long 

      对于其它动态连接库,可以在Lib子句指定文件的路径:

       Declare Function lzCopy Lib "c:/windows/lzexpand.dll" _

       (ByVal S As Integer, ByVal D As Integer) As Long 

    如果未指定libname的路径,Visual Basic将按照下列顺序查找该文件:

      ①.exe文件所在的目录

      ②当前目录

      ③Windows系统目录

      ④Windows目录

      ⑤Path环境变量中的目录

      下表中列出了常用的操作系统环境库文件。

      动态链接库描述

      Advapi32.dll高级API服务,支持大量的API(其中包括许多安全与注册方面的调用)

      Comdlg32.dll通用对话框API

      Gdi32.dll图形设备接口API

      Kernel32.dllWindows32位核心的API支持

      Lz32.dll32位压缩例程

      Mpr.dll多接口路由器库

      Netapi32.dll32位网络API

      Shell32.dll32ShellAPI

      User32.dll用户接口例程库

      Version.dll版本库

      Winmm.dllWindows多媒体库

      Winspool.drv后台打印接口,包含后台打印API调用。

      对于Windows的系统API函数,可以利用VB提供的工具API Viewer查找某一函数及其相关数据结构和常数的声明,并复制到自己的程序中。

    ()、使用别名:

    A.函数名是标准的名称

      Declare语句中的Alias子句是一个可选的部分,用户可以通过它所标识的别名对动态库中的函数进行引用。例如,在下面的语句中,声明

    了一个在VB中名为MyFunction的函数,而它在动态库Mydll.dll中最初的名字是MyFunctionX

       Private Declare Function MyFunction Lib "Mydll.dll" _

       Alias "MyFunctionX" ( ) As Long 

      需要注意的是,Alias子句中的函数名是大小写敏感的,也就是说,必须与函数在生成时的声明(如在C源文件中的声明)一致。这是因为32位动态库与16位动态库不同,其中的函数名是区分大小写的。同样道理,如果没有使用Alias子句,那么在Function(或Sub)后的函数名也是区分大小写的。

      通常在以下几种情况时需要使用Alias子句:

    A.处理使用字符串的系统Windows API过程

      如果调用的系统Windows API过程要使用字符串,那么声明语句中必须增加一个Alias 子句,以指定正确的字符集。包含字符串的系统Windows API函数实际有两种格式:ANSIUnicode(关于ANSIUnicode两种字符集的区别将在后面详细阐述)。因此,在Windows头文件中,每个包含字符串的函数都同时有ANSI版本和Unicode版本。例如,下面是SetWindowText函数的两种C语言描述。可以看到,第一个描述将函数定义为SetWindowTextA,尾部的"A" 表明它是一个ANSI函数:

       WINUSERAPI BOOL WINAPI SetWindowTextA(HWND hWnd, LPCSTR lpString); 

      第二个描述将它定义为 SetWindowTextW,尾部的"W" 表明它是一个 Unicode 函数:

       WINUSERAPI BOOL WINAPI SetWindowTextW(HWND hWnd, LPCWSTR lpString); 

      因为两个函数实际的名称都不是"SetWindowText",要引用正确的函数就必须增加一个Alias子句:

    Private Declare Function SetWindowText Lib "user32" _

    Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal _

    lpString As String) As Long

      应当注意,对于VB中使用的系统WindowsAPI函数,应该指定函数的ANSI版本,因为只有WindowsNT才支持Unicode版本,而Windows95不支持这个版本。仅当应用程序只运行在WindowsNT平台上的时候才可以使用Unicode版本。

      B.函数名是不标准的名称

      有时,个别的DLL过程的名称不是有效的标识符。例如,它可能包含了非法的字符(如连字符),或者名称是VB的关键字(如GetObject)。在这种情况下,可以使用Alias关键字。例如,操作环境DLLs中的某些过程名以下划线开始。尽管在VB标识符中允许使用标识符,但是下划线不能作为标识符的第一个字符。为了使用这种过程,必须先声明一个名称合法的过程,然后用Alias子句引用过程的真实名称:

    Declare Function lopen Lib "kernel32" Alias "_lopen" _

    (ByVal lpPathName As String, ByVal iReadWrite _

    As Long) As Long

      在上例中,lopenVB中使用的过程名称。而_lopen则是动态连接库中可以识别的名称。

      C.使用序号标识DLL过程

      除了使用名称之外,还可以使用序号来标识DLL过程。某些动态连接库中不包含过程的名称,在声明它们包含的过程时必须使用序号。同使用名称标识的DLL过程相比,如果使用序号,在最终的应用程序中消耗的内存将比较少,而且速度会快些。但是,一个具体的API的序号在不同的操作系统中可能是不同的。例如GetWindowsDirectoryWin95下的序号为432,而在WindowsNT4.0下为338。总而言之,如果希望应用程序能够在不同的操作系统下运行,那么最好不要使用序号来标识API过程。如果过程不属于API,或者应用程序使用的范围很有限,那么使用序号还是有好处的。

      要使用序号来声明DLL过程,Alias子句中的字符串需要包含过程的序号,并在序号的前面加一个数字标记字符(#)。例如,Windowskernel中的GetWindowsDirectory函数的序号为432;可以用下面的语句来声明该DLL过程:

    Declare Function GetWindowsDirectory Lib "kernel32" _

    Alias "#432" (ByVal lpBuffer As String, _

    ByVal nSize As Long) As Long

      在这里,可以使用任意的合法名称作为过程的名称,VB将用序号在DLL中寻找过程。

      为了得到要声明的过程的序号,可以使用Dumpbin.exe等实用工具(Dumpbin.exeMicrosoft VisualC++提供的一个实用工具,它的使用说明可以参见VC的文档)。利用Dumpbin,可以提取出.dll文件中的各种信息,例如DLL中的函数列表,它们的序号以及与代码有关的其它信息。

      ()、使用值或引用传递

      在缺省的情况下,VB以引用方式传递所有参数(ByRef)。这意味着并没有传递实际的参数值,VB只传递了数据的32位地址。另外有许多DLL过程要求参数以值方式传递(ByVal)。这意味着它们需要实际的数据,而不是数据的内存地址。如果过程需要一个传值参数,而传递给它的参数是一个指针,那么由于得到了错误的数据,该过程将不能正确地工作。要使参数以使用值方式传递,在Declare语句中需要在参数声明的前面加上ByVal关键字。例如InvertRect过程要求第一个参数用传值方式传递,而第二个用引用方式传递:

    Declare Function InvertRect Lib "user32" Alias _

    "InvertRectA" (ByVal hdc As Long, lpRect As RECT) As Long

      动态连接库的参数传递是一个复杂的问题,也是VB中调用动态连接库时最容易出现错误的地方。参数类型或传递方式的声明错误都可能导致应用程序出现GPF(通用保护错误),甚至使操作系统崩溃,因此我们将在后面专门详细地讨论这个问题。

      ()、灵活的参数类型

      某些DLL过程的同一个参数能够接受多种数据类型。如果需要传递多种类型的数据,可以将参数声明为AsAny,从而取消类型限制。例如,下面的声明中的第三个参数(lpptAsAny) 既可以传递一个POINT结构的数组,也可以传递一个RECT结构:

    Declare Function MapWindowPoints Lib "user32" Alias _

    "MapWindowPoints" (ByVal hwndFrom As Long, _

    ByVal hwndTo As Long, lppt As Any, _

    ByVal cPoints As Long) As Long

      As Any子句提供了一定的灵活性,但是,由于它不进行任何的类型检查,风险也随之增加。因此在使用AsAny子句时,必须仔细检查所有参数的类型。正确的函数声明是在VB中调用动态连接库的前提,但要想在VB中用对、用好动态库中的函数,仅仅有声明还是远远不够的。前面已经说过,由于VB不能验证应用程序传递到动态连接库中的参数值是否正确,因此就要求程序员应对参数类型有非常详细的了解,否则很容易引起应用程序发生通用保护错或导致潜在的Bug,降低软件的可靠性。下面将参数类型分为简单数据类型、字符串、和用户自定义类型三种分别进行讨论。

      (1)、简单数据类型:

      简单数据类型是指Numeric数据类型(包括IntegerLongSingleDoubleCurrency类型)、Byte数据类型和Boolean数据类型。它们的共同的特点是结构简单,操作系统在处理时不必进行特殊的转换。

      简单数据类型参数的传递比较简单。我们知道,在VB中传递参数的方式有两种:传值(Byval)和传址(ByRef),缺省的方式是传址。所谓传值,就是对一个变量的具体值进行传递;而传址则是传递变量的地址。例如,在VB程序中需要将一个整型变量m=10的值传进动态库,如果用传值方式,那么传进动态库的值就是10,而在传址方式下,传入的则是变量m的地址,相当于C/C++ &m的值。需要注意的是,以传值方式传进动态连接库的变量,其值在动态库中是不能被改变的;如果需要在动态连接库中修改传入参数的值,则必须使用传址方式。一般来说,在VB 和动态连接库之间传递单个的简单数据类型,只要注意了以上几个方面就可以了。当需要将一个简单数据类型的整个数组传进动态库时,必须将相应参数声明为传址方式,然后把数组的第一个元素作为参数传入,这样在动态连接库中就得到了数组的首地址,从而可以对整个数组进行访问。例如,声明了一个名为ReadArrayDLL过程,要求传入一个整型数组aArray

    Declare Function ReadArray Lib "mydll.dll" _

    (aArray As Integer) As Integer

    在调用时可以采用如下方式:

    Dim ret,I(5) as Integer

    ret = ReadArray(I(0)) '

    将整个数组传入动态连接库

    (2)、字符串参数的传递:

      与简单数据类型相比,字符串类型(StringString*n)的参数传递要复杂得多,这主要是Windows 95 APIVB使用的字符串类型不同的缘故。VB使用被称为BSTRString数据类型,它是由自动化(以前被称为OLE Automation)定义的数据类型。一个BSTR由头部和字符串组成,头部包含了字符串的长度信息,字符串中可以包含嵌入的null值。大部分的BSTR Unicode的,即每个字符需要两个字节。BSTR通常以两字节的两个null字符结束。下图表示了一个BSTR类型的字符串。

      (前缀)aTest/0

      头部BSTR指向数据的第一个字节

      另一方面,大部分的DLL过程(包括Windows 95 API中的所有过程)使用LPSTR类型字符串,这是指向标准的以null结束的C语言字符串的指针,它也被称为ASCIIZ字符串。LPSTR 没有前缀。下图显示了一个指向ASCIIZ字符串的LPSTR

      aTest/0

      LPSTR指向一个以null结尾的字符串数据的第一个字节

      如果DLL过程需要一个LPSTR(指向以null结束的字符串的指针)作为参数,可以在VB 中将一个字符串以传值的方式传递给它。因为指向BSTR的指针实际指向以null值结束的字符串的第一个数据字节,所以对于DLL过程来说,它就是一个LPSTR。这样传入动态连接库的字符串,DLL过程也可以对它进行修改,尽管它是以传值方式传入的。只有当DLL过程需要一个指向LPSTR的指针时,才以传址的方式传入字符串,这时DLL过程得到的是一个指向字符串指针的指针(相当于C/C++中的char**),而不是通常所用的字符串的首地址(相当于C/C++中的char*)。

      当需要把一个字符串数组整个传入动态连接库时,情况就变得复杂多了,用传递简单数据类型数组的方式来传递字符串数组是行不通的。当我们以传值的方式将一个字符串数组的第一个元素传进动态连接库时,DLL过程得到的实际上是该元素压入堆栈段后的地址,而不是数据段中整个数组的首地址。也就是说,这时DLL过程只能得到数组的第一个元素,而无法访问整个数组。而以传址方式传入第一个元素时,DLL过程只能得到指向该元素在堆栈段中地址的指针,同样无法访问整个数组。这不能不说是VB的一个不足。因此,在程序设计中,如果确实需要将整个字符串数组传入动态库,就必须采取其它方法。

      我们知道,在VB中,有一种Byte数据类型。每个Byte型变量占一个字节,不含符号位,因此所能表示的范围为0255。这种数据类型是专门用于存放二进制数据的。为了将整个字符串数组传进动态库,可以用字节数组来保存字符串。由于Byte是一种简单数据类型,因此字节数组的传递是非常简单的。首先,需要把一个字符串正确地转变成一个字节数组。这要涉及一些字符集的知识。Windows 95VB使用不同的字符集,Windows 95 API使用的是ANSIDBCS 字符集,而VB使用的则是Unicode字符集。所谓ANSI字符集,是指每个字符都用一个字节表示,因此最多只能有28=256个不同的字符,这对于英语来说已经足够了,但不能完全支持其它语言。DBCS字符集支持很多不同的东亚语言,如汉语、日语和朝鲜语,它使用数字0-255表示ASCII 字符,其它大于255或小于0的数字表明该字符属于非拉丁字符集;在DBCS中,ASCII字符的长度是一个字节,而汉语、日语和其它东亚字符的长度是2个字节。而Unicode字符集则完全用两个字节表示一个字符,因此最多可以表示216=65536个不同字符。也就是说,ANSI字符集中所有的字符都只占一个字节,DBCS字符集中ASCII字符占一个字节,汉字占两个字节,Unicode 字符集中每个字符都占两个字节。由于VBWindowsAPI使用的字符集不同,因此在进行字符串到字节数组的转换时,当用Asc函数取得一个字符的字节码后,需要判断它是否是一个ASCII 字符;如果是ASCII字符,则在转换后的字节数组中就只占一个字节,否则要占两个字节。

      下面给出了转换函数:GetChar Byte得到一个字符的高字节或低字节,它的第一个参数是一个字符的ASCII码,第二个参数是标志取高字节还是低字节;StrToByteDBCSANSI格式将一个字符串转换成一个字节数组,第一个参数是待转换的字符串,第二个参数是转换后的一个定长字节数组,若该数组长度不足以存放整个字符串,则截去超长的部分;ChangeStrAryToByte 利用前两个函数将字符串数组转换成字节数组,第一个参数是定长的字符串数组,其中每个元素都是一个字符串(各个元素包含的字符数可以不同),第二个参数是一个变长的字节数组,保存转换后的结果。

      当转换完成以后,查看字节数组ResultAry,其中包含了21个元素,依次是:178226202212490178226202212505050017822620221251510。其中,[178226]""的字节码,[202112]""的字节码,495051 分别为字符123ASCII码。可见,经过转换后,字符串数组中的各个元素按顺序放在了字节数组中,相互间以终止符0分隔。

      这样,字符串数组就全部转换成了字节数组,然后只要将字节数组的第一个元素以传址的方式传入动态连接库,DLL过程就可以正确地访问数组中的所有字符串了。但是,使用这种方法,当DLL过程处理结束返回VB时,VB得到的仍然是字节数组。如果需要在VB中再次得到该字节数组表示的字符串,还要把整个字节数组重新以0为分割符分成多个子数组(每个子数组都对应原来字符串数组中的一个元素),然后使用VB函数StrConv将每个子数组转换成字符串(转换时第二个参数选vbUnicode),就可以显示或进行其它操作了。例如,其中一个子数组的名字是SubAry,则函数StrConv(SubAry,vbUnicode)就返回了它所对应的字符串。

      总之,VB应用程序和动态库间字符串参数的传递是一个比较复杂的过程,使用时要非常谨慎。同时应尽可能避免传递字符串数组类型的参数,因为这很容易引起下标越界、堆栈溢出等严重错误。

    (3)、用户自定义类型(User-defined Type)参数的传递

      用户自定义类型在VB中是一种重要的数据类型,它为编程者提供了很大的灵活性,使开发人员可以根据需要构造自己的数据结构。它相当于C/C++中的结构类型(structure)。在VB中,允许程序员以传址的方式将自定义数据类型参数传入动态库,DLL过程也可以将修改后的参数返回VB程序。但是,在VB中仍然不支持以传值的方式传递用户自定义类型参数。

      传递用户自定义类型参数时,必须确保VB中的数据类型的成员与动态库中的结构成员是一一对应的,所占空间也必须严格一致。这里所说的一一对应,不仅是指VB 中的所有结构成员在动态库的结构中都必须有对应的元素,而且它们在数据结构中定义的顺序也必须严格一致,这是VB中使用的"数据结构成员对齐方式"决定的。在VB 中,数据结构使用双字对齐方式(4-byte alignment),因此,在用户自己生成用于VB 调用的动态连接库时,也必须把编译选项"structure member alignment" 设为4字节(如前文所述)。

      所谓结构成员对齐方式是指一个数据结构内部,其成员的排列方式。譬如,在VB中,其对齐方式是4字节,这就好象在一个数据结构内部分成了很多个4字节大小的小单元,如果相邻两个或多个数据成员的大小可以放在一个单元中,那么就放在一起;否则这些小单元中可能会出现未用的空字节。我们来看下面一个数据类型:

    Type TestType

    m1 as Integer

    m2 as Byte

    m3 as Long

    End Type

      它的三个成员的大小加起来是2+1+4=7。但是,由于m1m2的字节总长度是3,小于4,它们就存放于一个单元中;但该单元剩下的一个字节不足以放下一个Long型的成员m3,于是m3 就被放在下一个单元中,它们之间就有了一个未用的空字节;因此,整个结构所占实际长度是8 字节。同理,如果将m3m2的位置交换一下,它所占的尺寸就变成了9字节。可见,成员在结构中的声明顺序也是非常重要的。

      通常,当一个用户自定义类型中不包含字符串时,向动态连接库中传递该类型的参数是没有什么问题的。如果只传递一个自定义类型变量,则既可以传递该变量名,也可以传递该变量的第一个成员,它们的效果是一样的,都是将该变量的地址传进了动态库;同样,如果要传递一个自定义类型的数组,则既可以传递该数组的第一个元素,也可以传递第一个元素的第一个成员。但是,如果用户自定义类型中包含字符串类型时,又该如何与动态连接库传递参数呢?答案是令人遗憾的:在VB中,你无法将一个包含字符串成员的用户自定义类型变量或数组安全、正确地传入动态库中。如果你这样做了,即使某次侥幸得到了正确的结果,在其背后也隐藏着许多致命的危险。因此,如果一定要在用户自定义类型中包含字符串变量,并且该类型的变量又要作为参数传入动态库时,你最好修改类型定义,把其中的字符串成员用相应的字节数组类型替换掉(转换方法可参见前文),这样就可以在VB 和动态库间传递这种类型的参数了。

      另外,在VB 中还可以把一个函数的指针传递到动态库中,方法也并不复杂。但笔者强烈建议最好不要这么做,因为这样一来VB 应用程序就几乎完全丧失了它所应有的安全性。如果确实需要传递函数指针的话,那么还是编一个C/C++ 的程序来完成这项工作吧。

    总之,在VB中调用DLL过程是一个比较复杂的问题,编程人员必须很好地把握,才能达到既提高了程序效率,开拓了程序功能,又不降低程序安全性的目的。另外需要特别指出的一点是,在本文中提到的所有动态连接库,都是指没有使用自动化(OLE Automation)技术的动态库,Windows API和大多数用户自编的动态连接库都是这种类型的。对于使用了OLE Automation技术的动态连接库,其参数传递的方式有所不同,读者可以参阅有关OLE 技术的书籍,在此不再涉及。

    展开全文
  • VB调用API函数

    万次阅读 多人点赞 2016-01-13 20:17:36
    API函数快速入门--怎样在VB中声明和使用API函数--     一、在VB中声明API函数有两种方法:如果我们只在某个窗体中使用API函数,我们可以在窗体代码的 General部分声明它:    声明的语法是:  Private ...

    API函数快速入门--怎样在VB中声明和使用API函数--  
     
      一、在VB中声明API函数有两种方法:如果我们只在某个窗体中使用API函数,我们可以在窗体代码的

    General部分声明它:

     

      声明的语法是:
      Private Declare Function ...
      Private Declare Sub.....
      这里必须采用Private声明,因为这个API函数只能被一个窗体内的程序所调用。

     

      如果我们的程序有多个窗体构成,而且我们需要在多个窗体中使用同一个API函数,就需要在模块中

    声明了。
      先添加一个模块(如图示),
      然后采用如下语法声明:
      Public Declare Function....
      Public Declare Sub....
      Public声明的含义是把API函数作为一个公共函数或过程,在一个工程中的任何位置(包括所有的窗

    体和模块)都能直接调用它。声明完毕我们就能在程序中使用此API函数了。

     

      二、可采用以下几种方式使用API函数,以SetWindowPos函数为例:
      (1)忽略函数返回值的调用:
        SetWindowPos Form1.hWnd, -2 ,0 ,0 ,0, 0, 3
      注意此时函数的参数是不加括号的。
      (2)Call方法调用:
        Call SetWindowPos(Form1.hWnd, -2, 0, 0, 0, 3)
      注意这里需要加上括号,但我们不取回函数的返回值。
      (3)取得函数返回值的调用:
        MyLng = SetWindowPos(Form1.hWnd, -2, 0, 0, 0, 3)
      此时需要加上括号,而且我们必须事先定义一个变量(变量的类型与函数返回值类型相同)来存储

    API函数的返回值。

     

      三、几个问题的说明:

     

      (1)声明中的Lib 和 Alias 是怎么回事
      一般情况下WIN32API函数总是包含在WINDOWS系统自带的或是其它公司提供的动态连接库DLL中,而

    Declare语句中的Lib关键字就用来指定DLL(动态连接库)文件的路径,这样VB才能找到这个DLL文件,然

    后才能使用其中的API函数。如果我们只是列出DLL文件名而不指出其完整的路径的话,VB会自动到.EXE文

    件所在目录、当前工作目录、WINDOWS\SYSTEM目录、WINDOWS目录下搜寻这个DLL文件。所以如果所要使用

    DLL文件不在上述几个目录下的话,我们应该指明其完整路径。
      Alias用于指定API函数的别名,如果我们调用的API函数要使用字符串(参数中包含String型)的话

    ,Alias关键字是必须的。这是因为在ANSI和Unicode字符集中同一API函数的名称可能是不一样的,为了

    保证不出现声明错误,我们使用Alias关键字指出API函数的别名,一般来说在WIN9X平台下我们把API函数

    名后加一个大写A作为别名即可。

     

      (2)常见的API参数类型的说明
      API函数的参数中最常见的是长整Long型数据类型,例如API中的句柄、一些特定的常量、函数的返回

    值都是此类型 的值;另外几种常见的参数类型有:整型Integer、Byte型、String型等。

     

      (3)声明中的ByVal是作什么用的
      这跟VB的参数传递方式有关,在默认情况下VB是通过地址传递方式传递函数的参数、而有些API函数

    要求必须采用传值方式来传递函数参数(这两种参数传递方式是不同的,前者传递的是一个指针,而后者

    要求是参数真实的值)。这样就会发生错误,解决的办法是在API函数参数声明的前面加上ByVal关键字,

    这样VB就采用传值方式传递参数了。

     

      (4)怎样得到完整的API函数声明
      VB自带了API文本查看器API TEXT VIEWER,我们可以在其中找到API函数的完整声明,然后把它粘贴

    到程序中即可。
     
    什么是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)段。

     
    数据类型与"类型安全"
     
    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常数来讲,没有什么太特别的学问。请看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,你将一无所获。由于结构名实际上就是指向这个结构的指针(这个结构的首地址),所以,你也就

    传送特定的结构名就可以了(参见小结,我用红色字体来突出了这种传递方式)。

    由于结构传送的是指针,所以函数将直接对结构进行读写操作。这种特性很适合于把函数执行的结果装载

    在结构
     
    小 结

     
    以下的程序是为了总结本课中学到的内容而给出的。启动VB,新建一个项目,添加一个命令按钮,并把下

    面的代码拷贝到代码段中,运行它。

    Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI) As Long
    Private Type POINTAPI '定义点(Point)结构
    X As Long '点在X坐标(横坐标)上的坐标值
    Y As Long '点在Y坐标(纵坐标)上的坐标值
    End Type
    Sub PrintCursorPos( )
    Dim dl AS Long
    Dim MyPoint As POINTAPI
    dl&= GetCursorPos(MyPoint) '调用函数,获取屏幕鼠标坐标

    Debug.Print "X=" & Str(MyPoint.X) & " and " & "Y=" & Str(MyPoint.Y)
    End Sub
    Private Sub Command1_Click()
    PrintCursorPos

    End Sub

    输出结果为(每次运行都可能得到不同的结果,这得由函数调用时鼠标指针在屏幕中所处的位置而决定)∶
    X= 240 and Y= 151

    程序中,GetCursorPos函数用来获取鼠标指针在屏幕上的位置。

    以上例子中,你可以发现,以参数传递的MyPpint结构的内容在函数调用后发生了实质性变化。

    一些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 用当前画笔画一条线,从当前位置连到一个指定的点


    展开全文
  • VB的Call调用

    2019-07-19 17:52:32
    Dim a As New clsASM Dim hwd As Long Dim pid As Long Dim hProcess As Long Dim address As Long ...address = GetProcAddress(GetModuleHandle("user32.dll"), "FindWindowA") ...a.Push V...
  • VB6.0过程的递归调用

    2009-06-10 07:54:57
    VB6.0过程的递归调用:在调用一个程序或函数的过程中又出现直接或间接调用程序或函数本身,称为过程的递归调用
  • MDI窗体实例,演示了如何在MDI窗体执行窗体的函数程序!
  • 消息驱动Bean必须实现两个接口MessageDrivenBean和MessageListener 在对象创建的过程中将被容器调用,onMessage函数方法接收消息参数,将其强制转型为合适的消息类型,同时打印出消息的内容。同时一个mail note将被...
  • VB调用DLL

    2015-05-13 13:59:15
    作为一种32位Windows应用程序的开发工具,VB生成的exe文件自然也都是32位的,通常情况下也只能调用32位的动态连接库。但是,并不是所有的32位动态库都能被VB生成的exe 文件正确地识别。 一般来说,自己编写用于VB...
  • VB中Sub过程与Function过程的区别

    千次阅读 2020-01-14 13:39:58
    VB的通用过程分为两种类型:Sub过程和Function过程。通用过程既可以保存在窗体模块(.Frm)中,也可以保存在标准模块(.Bas)中。通用过程与事件过程不同,它不依附...Sub过程(子过程) 语法格式: [Public|priva...
  • VB不同模块过程调用、菜单的编辑

    千次阅读 2010-12-14 20:53:00
    彼此独立 动态变量:使用Dim声明的局部变量,执行到该变量所在的过程,才分配空间 静态变量:使用Static声明的局部变量和全局变量,每次执行过程不释放空间,保持上次的值不变 调用窗体中的过程,...
  • vb.net的过程和函数

    千次阅读 2011-12-05 11:11:29
    1.vb.net的Sub过程 Sub过程是在响应事件时执行的代码块。将模块中的代码分成Sub过程后,在应用程序中查找和修改代码变得更容易了。Sub过程的语法是: {Private|Public|Friend} Sub subname([arguments list])  ...
  • VB轻松调用其他程序

    千次阅读 2012-08-09 16:39:57
    我们编写程序时,有时会遇到在一个程序中调用并控制另一个程序执行的情况,在一些编程语言中实现起来较为繁琐,但如果用VB编写时,则可轻松实现。下面我就以在程序中调用“计算器”为例,总结了以下几种方法: 一、...
  • 怎么在vb中文用标准模块的summain子过程代替界面的摆放实现初始化和调用控件?并且控件参量也要传递?怎么在sum main这个过程里实现?
  • VB2010的线程与跨线程调用控件

    千次阅读 2018-05-08 17:42:11
    1.调用系统线程库 Imports System.Threading2.Dim myThread As Thread '定义线程 Public Delegate Sub VoidDelegate() '定义委托类型3.初始化线程并运行 myThread = New Thread(AddressOf Listen) myThrea...
  • VB.net应用技巧4: 跨线程调用控件

    千次阅读 2017-02-02 14:55:14
    VB.net应用技巧3中,说明在线程中访问控件是不... 2、单独处理调用控件过程。    3、在线程中调用该函数。    通过以上方法,就可以跨线程安全访问控件了。 原创性文章,转载请注明出处 http:
  • '*过程名称:ShowForm '*参数说明:MDIChildForm ——需创建实例的窗体 '*功能说明:创建窗体实例 '************************************************** Private Sub ShowForm(ByVal MDIChildForm As Form) ...
  • VB可以用Declare声明来调用标准DLL的外部函数,但是其局限性也很明显:利用Declare我们只能载入在设计时通过Lib和Alias字句指定的函数指针!而不能在运行时指定由我们自己动态载入的函数指针),不能用Declare语句来...
  • 如何让VB调用外部的DLL

    千次阅读 2008-03-31 22:40:00
    collected by barenxWindows动态连接库是包含数据和函数的模块,可以被其它可执行文件(EXE、DLL、OCX 等)调用。动态连接库包含两种函数:输出(exported)函数和内部(internal)函数。输出函数可以被其它模块调用...
  • VB脚本:BAT脚本调用VB脚本的方法

    万次阅读 2017-06-24 13:27:57
    在数通平台软件的性能或功能稳定性测试过程中,经常需要用一台调试机(一般为操作系统为Windows的计算机),通过SecureCRT等远程登录工具,连接一台或多台路由器设备(操作系统一般为Linux、VxWorks、或类Linux,如...
  • C语言

    万次阅读 多人点赞 2019-12-18 23:01:50
    调用一个函数的过程中又出现直接或间接地调用该函数本身称为函数的递归调用 149.在一个函数内部定义的变量是内部变量,称为局部变量 150.在函数之外定义的变量称为外部变量,是全局变量 151.从变量的作用域角度来...
  • 因为主过程和子过程都是子程序下面的例子显示过程AboutUser。该过程要求用户姓和名,并且将姓和名从全名中分离出来。最后的语句显示用户的姓,随后是逗号和名。你再读下去,该过程将被分割成几个任务,以示范使用主...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 18,609
精华内容 7,443
关键字:

vb如何调用子过程