vb.netapi指针 vb指令

VB.NET的API调用现在我用我所知道的为楼主介绍VB.NET的API调用,请楼主浏览一下 , 看看行不行 。
Windows API就是Windows系统的API函数简称(Application Program Interface,即:应用程序接口函数),它是Windows操作系统提供给各种开发基于Windows平台应用软件的开发语言的一些公用的函数,这些函数一般都比较底层,所以当各种开发语言使用自带的函数或类库已无法解决问题时,调用Windows API函数往往是一种非常直接、有效的解决方法 。但由于在程序中调用Windows API函数一般都很复杂,所以对于程序员来说,是否能够灵活的使用Windows API函数,往往也是其水平高低的一个重要标志 。但自从微软推出.Net框架以后 , 各种开发基于.Net平台下的程序语言,如Visual Basic .Net、Visual C#等却很少使用Windows API函数,并且微软公司也不像以前那样,提倡在这些.Net开发语言中使用Windows API函数,其主要的原因如下:
1. .Net框架所附带的类库.Net FrameWork SDK是一个内容丰富、功能强大的软件开发包,各种Windows API函数所实现的各种功能几乎都可以在这个软件开发包中找到与之对应的部分 。
2. 微软Visual Basic .Net、Visual C#等目的是编写跨平台的应用程序,如果在Visual Basic .Net、Visual C#等中使用Windows API函数,这也就注定了编写出的程序只能运行于Windows平台之下,而弱化了.NET的跨平台能力 。这也就是为什么微软不提倡在.Net平台调用Windows API函数的原因 。
虽然微软并不提倡在Visual Basic .Net、Visual C#中调用Windows API函数,但由于目前.Net 框架推出时间较短,.Net FrameWork SDK中提供的类库还并不足以完全替换Windows API函数的所有功能,所以在某些时候,.Net开发语言还是必须要调用Windows API函数 。
一.平台调用、托管DLL、非托管DLL简介:
托管DLL就是能够在公共语言运行库(Common Language Runtime,简称CLR)中能够直接引用的,并且扩展名为“DLL”的文件 。具体所指就是封装各种命名空间所在的DLL文件,如System.dll等 。非托管DLL就是平常所的动态链接库等,其中就包括了封装所有Windows API函数的DLL文件 。各种非托管DLL中的函数在公共语言运行库中不能直接被调用,而需要经过.Net框架提供的“平台调用”服务后才可以 。
“平台调用”是.Net框架为Visual Basic .Net、Visual C#等.Net开发语言提供的一种服务,用以在托管代码中引入各种非托管DLL中封装的函数(其中包括Windows API函数) 。“平台调用”依赖于元数据在运行时查找导出函数并封装其参数 。图01公共语言运行库利用“平台服务”调用非托管DLL中的函数的流程图:
图01:“平台服务”的调用非托管函数的流程图
在托管代码中使用“平台调用”服务调用非托管DLL中封装的函数时,“平台服务”将依次执行以下操作:
1. 查找包含该函数所在的DLL文件 。
2. 如果找到,则将该DLL文件 加载到内存中 。
3. 查找函数在内存中的地址并将其参数推到堆栈上,并封送所需的数据 。
4. 将控制权转移给非托管函数 。这样整个函数调用完成 。
在Visual Basic .Net中使用“平台调用”服务,申明Windows API函数主要有二种具体的实现方法:
1. 使用DllImport特征类来申明Windows API函数 。
2. 使用“Declare”语句来申明Windows API函数 。
这二种方法虽有异曲同工之效,但在繁简上却有很大差异,第一种方法申明过程比较复杂,很容易在申明Windows API函数时出错,所以并不提倡 。而第二种方法相对简单,并且又保存了以前Visual Basic中的很多语法,所以在平常时大都使用这种方法来申明Windows API函数 。
二.VB.Net查看文件中图标的函数及申明Windows API的方法:
Visual Basic .Net要实现查看文件中的图标,目前只使用.Net FrameWork SDK是无法实现这种功能的,正如前面所说 , 主要是由于.Net FrameWork SDK推出的时间较短 , 其功能还不可能面面俱到 。解决问题的关键是正确使用Windows API函数,其中所涉及到的Windows API函数主要有二个:其一是获得指定文件中的图标数目;其二是从指定文件的指定位置导出图标的Windows句柄 。这二个函数都位于“Shell32.dll”文件中 , 并且函数的入口点都为“ExtractIcon” 。下面是在Visual Basic .Net中分别使用DllImport特征类和“Declare”语句申明这二个Windows API函数的具体方法 。
(1).使用DllImport特征类来申明Windows API函数:
下面是在Visual Basic .Net中使用DllImport特征类申明二个Windows API函数的具体示例:
'函数ExtractIcon,其功能是是从指定文件的指定位置导出图标的Windows句柄 。
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'函数Icon_Num , 其功能是获得指定文件中的图标数目
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" , EntryPoint := "ExtractIcon" ) > _
Public Function _
Icon_Num ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
End Function
在使用DllImport特征类申明Windows API函数时,如果申明的函数名称和函数的入口点相同,则可以在申明Windows API函数时,省略定义函数入口点对应的代码,即EntryPoint对象字段对应的代码,这样声明ExtractIcon函数的代码也可以简化为如下所示:
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
(2).使用“Declare”语句来申明Windows API函数:
使用“Declare”语句的确比使用DllImport特征类要简单了许多,下面是在Visual Basic .Net中使用“Declare”语句来声明上述二个Windows API函数的具体方法:
Declare Auto Function ExtractIcon Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
'声明ExtractIcon函数
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As Integer ) As Integer
'声明Icon_Num函数
在Visual Basic .Net中声明Windows API函数时,“Declare”语句中Alias关键字的作用相当于使用DllImport特征类中的EntryPoint对象字段 。同样在使用“Declare”语句声明Windows API函数时 , 如果声明的函数和函数的入口点相同,也可以省略Alias关键字对应的代码,所以ExtractIcon函数也可以简化为如下:
Declare Auto Function ExtractIcon Lib "Shell32.dll" ( ByVal src As System.IntPtr , ByVal strFileName As string , ByVal uiIconIndex As UInt32 ) As System.IntPtr
下面就结合一个示例的编写过程来掌握的这二个Windows API函数的具体使用方法 , 这个示例的作用就是读取指定文件中的图标数目,并显示文件中的图标 。
三.本文中程序的编写、调试和运行环境:
(1).视窗2000高级服务器版 。
(2).Visual Studio .Net 2003企业结构设计版 , .Net FrameWork SDK版本号4322 。
四.Visual Basic .Net读取文件中的图标的实现步骤:
下面介绍的示例,其功能读取指定文件中包含的图标数目,并把这些图标全部显示出来 。下面是这个示例的实现步骤:
1. 启动Visual Studio .Net 。
2. 选择菜单【文件】|【新建】|【项目】后,弹出【新建项目】对话框 。
3. 将【项目类型】设置为【Visual Basic项目】 。
4. 将【模板】设置为【Windows应用程序】 。
5. 在【名称】文本框中输入【Visual Basic .Net查看文件中的图标】 。
6. 在【位置】的文本框中输入【E:\VS.NET项目】,然后单击【确定】按钮,这样在【E:\VS.NET项目】目录中就产生了名称为【Visual Basic .Net查看文件中的图标】文件夹,里面存放着【Visual Basic .Net查看文件中的图标】项目的所有文件 。具体如图02所示:
图02:【Visual Basic .Net查看文件中的图标】项目的【新建项目】对话框
7. 选择菜单【项目】|【添加新项】 , 在弹出的对话框中的【模板】设置为【模块】 , 【名称】文本框设置为【Module1.vb】后 。单击【打开】按钮,则在项目中增加了一个模板文件 , 名称为【Module1.vb】 。
8. 把Visual Stuido .Net的当前窗口切换到Module1.vb的代码编辑窗口,并在其Module1的代码区中添加下列代码,下列代码是用二种方式声明二个Windows API函数:
< System.Runtime.InteropServices.DllImport ( "Shell32.dll" ) > _
Public Function _
ExtractIcon ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As UInt32 ) As System.IntPtr
End Function
'声明ExtractIcon函数
Declare Auto Function Icon_Num Lib "Shell32.dll" Alias "ExtractIcon" ( ByVal src As System.IntPtr , ByVal strFileName As String , ByVal uiIconIndex As Integer ) As Integer
9. 把Visual Studio .Net的当前窗口切换到Form1窗体的设计查看,并从【工具箱】中的【Windows窗体】选项卡中拖入下列组件到Form1窗体:
四个Label组件 , 其中二个用以显示提示信息,另外二个分别用以显示选择的文件名称和这个文件中包含的图标数目 。
一个ListView组件,利用其显示大图标的属性用以显示选定文件中的图标 。
一个OpenFileDialog组件,用以选择要查看图标的文件名称 。
一个ImageList组件,它起的是桥梁的作用 , 首先把从文件中导出的图标存放到这里,然后再提供ListView组件显示出来 。
一个Button组件 。
10. 按照表01中数值来设定设定组件的主要属性:
组件类型组件名称属性设置结果
FormForm1TextVB.NET查看文件中的图标
Form1MaximizeBoxFalse
Form1MinimizeBoxFalse
Form1FormBorderStyleFixedSingle
ListViewListView1ImageList1LargeImageList
ListView1MultiSelectFalse
ListView1SizeSize ( 380 , 208 )
ButtonButton1Text选择文件
Button1FlatStyleFlat
ImageListImageList1SizeSize ( 32 , 32 )
ImageList1TransparentColorColor.Transparent
LabelLabel1Text文件名称:
Label2Text图标数目:
Label3Text""
Label4 Text"0"
表01:【Visual Basic .Net查看文件中的图标】项目窗体中各组件的主要属性设定数值表
并按照图02中各组件的位置、大小和排列方式来调整窗体中各个组件:
图02:【Visual Basic .Net查看文件中的图标】项目的设计界面
11. 把Visual Studio .Net当前窗口切换到Form.vb的代码编辑窗口,并用下列代码替换Form1.vb中的Button1组件的Click事件的处理代码,下列代码是在Button1组件的Click事件中处理查看文件中图标的功能,具体如下:
Private Sub Button1_Click ( ByVal sender As System.Object , ByVal e As System.EventArgs ) Handles Button1.Click
If OpenFileDialog1.ShowDialog ( ) = DialogResult.OK Then
'清除组件中的所有项目
ListView1.Items.Clear ( )
ImageList1.Images.Clear ( )
Dim sfName As String = OpenFileDialog1.FileName
Label3.Text = sfName
Dim iIcon_Num As Integer = Icon_Num ( IntPtr.Zero , sfName , -1 )
'显示文件中的图标数目
Label4.Text = iIcon_Num.ToString ( )
Dim i As Integer
For i = 0 To iIcon_Num - 1 Step 1
'强制实现int到uint类型转换
Dim j As UInt32
j = System.Convert.ToUInt32 ( i )
Dim hIcon As System.IntPtr = ExtractIcon ( IntPtr.Zero , sfName , j )
'在imageList1组件中加入当然提取的图标
ImageList1.Images.Add ( Icon.FromHandle ( hIcon ).ToBitmap ( ) )
'在ListView组件中加入一个项目
ListView1.Items.Add ( "第"( i1 ).ToString ( )"个图标" )
'把加入项目的图象索引指向刚才加入图标在imagList1组件中的索引 , 从而显示图标
ListView1.Items ( i ).ImageIndex = i
Next i
End If
End Sub
12. 至此,在上述步骤都正确执行后 , 【Visual Basic .Net查看文件中的图标】项目的全部工作就完成了 。单击快捷键F5就可以运行程序 , 此时单击【选择文件】按钮选择文件后,程序就能够读取这个文件中的图标及其数目,并显示出来了 。具体如图03所示:
图03:【Visual Basic .Net查看文件中的图标】项目的运行界面
五.总结:
解决Visual Basic .Net查看文件中的图标的关键并非是使用.Net框架中提供的类库 , 而是使用Windows的API函数 。虽然这与利用Visual Basic .Net开发跨平台程序的初衷相违背,但的确不失为一种解决问题的方法 。有些时候通过Windows API函数能够快捷、方便的解决实际问题,而这往往是只使用.Net FrameWork SDK所望尘莫及的,但随着.Net FrameWork SDK内容的不断丰富,各种新的组成部分和新的功能不断加入,可以预见的是,在未来的.Net FrameWork SDK中必将拥有可以替换本文中介绍的二个Windows API函数的组成部分 。
VB2010 API函数具体用法一、在VB中声明API函数有两种方法vb.netapi指针:如果vb.netapi指针我们只在某个窗体中使用API函数vb.netapi指针,我们可以在窗体代码vb.netapi指针的General部分声明它:
声明的语法是:
Private Declare Function ...
Private Declare Sub.....
这里必须采用Private声明,因为这个API函数只能被一个窗体内的程序所调用 。
如果我们的程序有多个窗体构成,而且我们需要在多个窗体中使用同一个API函数 , 就需要在模块中声明vb.netapi指针了 。
先添加一个模块 ,
然后采用如下语法声明:
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就采用传值方式传递参数了 。
用最简单的代码介绍一下指针在VB.net里面的用法?例1:以下程序我们申请几个指向不同类型的指针:
’使用StructLayout(LayoutKind.Sequential)属性告诉net编译器:结构的元素在内存中按其出现的顺序排列
StructLayout(LayoutKind.Sequential) _
Public Structure DEFUDT_Test
Public bytb As Byte
Public i32a As Int32
End Structure
Public Function fnGetIntptr1() As IntPtr
’取得一个4字节数组指针
Dim tabytTest(3) As Byte
’以下语句告诉net垃圾回收进程不对tabytTest进行处理 , 也就是说tabytTest占用的内存区域固定不变 。
Dim thObject As GCHandle = GCHandle.Alloc(tabytTest, GCHandleType.Pinned)
Dim tpObject As IntPtr = thObject.AddrOfPinnedObject() ’取得指向字节数组的指针
’取得一个指向32位内存数据的指针,
’由于使用gchandle取指针的方法只能对引用的对象有效,
’所以对如int32等值类型必须使用将其封装成为一个对象的方法以变为引用类型
Dim ti32Test As Object = Convert.ToInt32(0)
’以下语句告诉net垃圾回收进程不对ti32test进行处理,也就是说ti32Test的内存位置固定不变 。
Dim thObject1 As GCHandle = GCHandle.Alloc(ti32Test, GCHandleType.Pinned)
Dim tpObject1 As IntPtr = thObject1.AddrOfPinnedObject() ’取得ti32Test的首地址
Dim tudtTest1 As DEFUDT_Test
’由于结构是一种值类型变量,为保证指针申请方便 , 我们申请
’取得一个和结构tudtTest1大小一致的字节数组指针,只要空间占用长度和结构一样就可以了
’由于net在结构封装中会插入额外的数据位 , 所以一定要用sizeof方法得到结构在非托管使用时的实际大小
Dim tudtTest(Marshal.SizeOf(tudtTest1)) As Byte
Dim thObject2 As GCHandle = GCHandle.Alloc(tudtTest, GCHandleType.Pinned)
Dim tpObject2 As IntPtr = thObject2.AddrOfPinnedObject() ’取得指向结构的指针
’在这儿你可以写对指针处理的任意代码(在例2中会给予补充)……
’在使用完毕后一定要释放指针指向的内存块 , 让垃圾回收器可对这个内存块回收处理
If thObject.IsAllocated Then
thObject.Free()
End If
If thObject1.IsAllocated Then
thObject1.Free()
End If
If thObject2.IsAllocated Then
thObject2.Free()
End If
End Function
上例中指针流程处理可以归纳为:
1、 定义一个具有合适内存长度的引用变量(关于引用变量和值变量的差异可以参观VB.NET的书籍)
2、使用GCHandle.Alloc方法将变量的内存区域固定下来 。
3、使用GCHandle对象的AddrOfPinnedObject取得该内存区域的首地址并赋值给指针变量.
4、对指针进行操作
5、使用GCHandle对象的free方法释放指针指向的内存区域以便net垃圾回收器可以回收这个内存空间
2、指针所指向数据的存取
在.net中,对指针指向数据的存储函数都封装在marshal类中 , 主要的函数包括:Copy、PtrToStringUni 、PtrToStructure 、OffsetOf、WriteXXX,RreadXXX等,其中WriteXXX的表示向指针所表示的地址中写入XXX类型的数据,而ReadXXX中作用就是将指针所在地址的数据以XXX类型方式读出 。看例程2 , 我们使用这些方法演示对例1那几个指向不同类型数据的指针作数据存/取操作 。
例2:演示向例1申请得到的几个指针执行写入及读取数据的操作.
Marshal.WriteInt32(tpObject1, 0, Convert.ToInt32(77)) ’向ti32Test变量指向的地址写入32位整数77
MsgBox("现在ti32Test的值为:"ti32Test) ’因为变量存储地址的数据已改为77,所以显示为77
’以下这句之所以可行 , 因为ti32Test是32位整数,而tpObject指向的tabytTest数组刚好有4个元素
’而每一个byte元素都占用8位,合起来就是32位,和ti32Test占用的空间一样 。这就印证了前面提’
’到的net中指针没有指向类型的说明 。
Marshal.WriteInt32(tpObject, 0, ti32Test)
’以下代码再将tabytTest字节数组的内容理解为一个int32整数,
’并将值赋值给tudtTest结构中的int32元素
’我们使用Marshal.OffsetOf(GetType(DEFUDT_Test), "i32a").ToInt32以取得i32a元素在结构中的内存偏移位置
’所以New IntPtr(tpObject2.ToInt32Marshal.OffsetOf(GetType(DEFUDT_Test), "i32a").ToInt32)就临时产生了
’一个指针并指向i32a所在的内存地址(, 这个方法也说明了指针可以以字节为单位进行加减计算以指向合适的变量 。
【vb.netapi指针 vb指令】’Marshal.ReadInt32的作用是从指针中读取一个32整数 。
Marshal.WriteInt32(New IntPtr(tpObject2.ToInt32Marshal.OffsetOf(GetType(DEFUDT_Test), "i32a").ToInt32), _
0, Marshal.ReadInt32(tpObject))
’这儿可以将字节数组的内容复制到真正的结构中
MsgBox(Marshal.OffsetOf(tudtTest1.GetType, "i32a").ToInt32)
tudtTest1 = CType(Marshal.PtrToStructure(tpObject2, GetType(DEFUDT_Test)), DEFUDT_Test)
MsgBox("结构tidtTest1中i32a元素的值为:"tudtTest1.i32a) ’此处将显示刚赋的值77
如何在VB.net中用程序控制鼠标移动和点击调用api
在Visual Baisc.net中的声明:
Declare Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Public Const MOUSEEVENTF_LEFTDOWN = H2 '模拟鼠标左键按下
Public Const MOUSEEVENTF_LEFTUP = H4 ’模拟鼠标左键释放
Public Const MOUSEEVENTF_MIDDLEDOWN = H20 '模拟鼠标中间键按下
Public Const MOUSEEVENTF_MIDDLEUP = H40 '模拟鼠标中间键释放
Public Const MOUSEEVENTF_RIGHTDOWN = H8 '模拟鼠标右键按下
Public Const MOUSEEVENTF_RIGHTUP = H10 '模拟鼠标右键释放
Public Const MOUSEEVENTF_MOVE = H1 '模拟鼠标指针移动
例:
mouse_event MOUSEEVENTF_LEFTDOWN,10,10,0,0
'在(10 , 10)模拟鼠标左键按下
指针在VB中如何用法?。?有什么好处,有例子吗,调用函数指针 , 在Delphi , VC及汇编中,是非常简单的事情,所以,如果你不是VB程序员,请不要浪费你的时间,不要再看这篇文章了 。。
在VB中就不能直接调用了,VB唯一与之有点关系的就是AddressOf 操作符,所有VB程序都知道,它能取得模块内的函数地址,看到这里,相信很多VB程序员马上就说,调用函数指针,用 CallWindowProc 不就可以啦,还有什么可以讲的,呵呵,不错 , 你掌握了这个技巧!是的,这确实是利用这个API可以调用函数指针 , 不过呢 , 它只支持4个参数 , 给你的应用带来很多不便 。又有程序员要讲了,四个参数我可以扩展到任意功能呀,比如将其中一个参数传入的是一个结构块的指针,在结构中我可以随意的定义数据呀 。鼓掌!鼓掌!鼓掌!很不错!是的,你完全可以这样做 。不过呢 , 如果有一个函数不是你写的呢,你了解这个函数的所有参数及意义,也得到了它的指针,你怎么调用呀?惨了!呵呵 。不过不被困难吓倒的你可能又说,呵呵,有了,在《高级VB编程》这本被称为VB程序员的圣经的书中有解决方案 。鼓掌!鼓掌!鼓掌!不过,太累了!太累了,我对这本书的评价就是,它确实是一本高深 , 很值得读的书 。不过,毕竟作者的宗旨是基于COM为出发点,再来解决问题的 。所以难免很多事情复杂化了,(题外话,很多朋友同我讲,说这本书很难看懂,呵呵,如果你研究一下COM,你就很容易读懂这本书了?。?
下面,我所提供的方法就是 , 利用嵌入一段汇编代码,借助 CallWindowProc 函数实现调用任意个数的参数(当然参数类型也任意啦)的函数指针的能力 。
有关CallWindowProc 调用函数指针,在这我就不重复介绍了 , 毕竟掌握的人很多,网上资料也一大把的 。我就省了它吧
Private Declare Function CallAsmCode Lib "user32" Alias "CallWindowProcA" (lpPrevWndFunc As Long, _ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, lParam As Long) As Long
'------------------------------------------------------
' 功能:借用API调用任意个数参数的函数的纯VB实现版.
' 此函数内部自带SEH错误处理机制,但并不保证任意
' 错误调用均不会让您的VB崩溃(比如破坏栈平衡后返回)
' 作者:阿国哥 hackor@yeah.net
'------------------------------------------------------
Private Function CallAnyFunc(ByVal pFn As Long, ByVal pParam As Long, ByVal Count As Long) As Long
Dim CallAnyFuncCode(34) As Long, lRet As Long
CallAnyFuncCode(0) = H53EC8B55
CallAnyFuncCode(1) = HE8
CallAnyFuncCode(2) = HEB815B00
CallAnyFuncCode(3) = H1000112C
CallAnyFuncCode(4) = H114A938D
CallAnyFuncCode(5) = H64521000
CallAnyFuncCode(6) = H35FF
CallAnyFuncCode(7) = H89640000
CallAnyFuncCode(8) = H25
CallAnyFuncCode(9) = H8B1FEB00
CallAnyFuncCode(10) = HE80C2444
CallAnyFuncCode(11) = H0
CallAnyFuncCode(12) = H53E98159
CallAnyFuncCode(13) = H8D100011
CallAnyFuncCode(14) = H119791
CallAnyFuncCode(15) = HB8908910
CallAnyFuncCode(16) = H33000000
CallAnyFuncCode(17) = H558BC3C0
CallAnyFuncCode(18) = H104D8B0C
CallAnyFuncCode(19) = HEB8A148D
CallAnyFuncCode(20) = HFC528D06 CallAnyFuncCode(21) = HB4932FF
CallAnyFuncCode(22) = H8BF675C9
CallAnyFuncCode(23) = HD0FF0845
CallAnyFuncCode(24) = H58F64
CallAnyFuncCode(25) = H83000000
CallAnyFuncCode(26) = H4D8B04C4
CallAnyFuncCode(27) = H5B018914
CallAnyFuncCode(28) = H10C2C9
CallAnyFuncCode(29) = H58F64
CallAnyFuncCode(30) = H83000000
CallAnyFuncCode(31) = HC03304C4
CallAnyFuncCode(32) = H89144D8B
CallAnyFuncCode(33) = HC2C95B21
CallAnyFuncCode(34) = H90900010
CallAnyFunc = CallAsmCode(CallAnyFuncCode(0), pFn, pParam, Count, lRet)
If CallAnyFunclRet Then
CallAnyFunc = 0 '这里表示出现严重错误,你应当再了解目的函数的使用方法
Debug.Assert False '因为你的参数传递问题,导致程序已出现了非法操作 。
End If
End Function
下面介绍一下如何使用这个函数
参数一(pFn ):函数指针
参数二(pParam ):参数指针,指向一个连续的内存块,比如目的函数有三个参数,分别为A,B,C 。你可以定义一个结构,结构体为A , B,C(每个参数均为4字节长),然后传这个结构的地址 。
参数三(Count ):参数个数 。
返回:目的函数的返回值 。(你可以修改成其它类型的返回值)
vb.net用指针或变量调用函数指针是c语言的概念,VB、VB.NET没有指针,除了指针以外也很少有人能玩到你的编程深度,关键看不懂呢 。
???就是子程序的名称 , 比如每次点击c后就自动调动相对应的子程序,如子程序是
Private Sub my_do ()
........
End Sub
相应的AddHandler c.Click, AddressOf my_do
实际上是个委托
vb.netapi指针的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于vb指令、vb.netapi指针的信息别忘了在本站进行查找喔 。

    推荐阅读