VB指针
- 格式:doc
- 大小:121.50 KB
- 文档页数:31
VB指针式时钟
1.添加圆圈:从左侧控件工具栏中选择shape控件,然后在窗体上画一个控件,修改该控
件的shape属性为circle
2.设置窗体坐标系
通常情况下窗体的左上角为坐标的0,0点,向下为y轴的正方向,但是这样会给我们带来不小的麻烦
所以可以设置ScaleLeft ScaleTop ScaleHeight scaleWidth属性重新设置窗体的坐标系,比如选中窗体后,修改窗体的这四个属性如下
那么坐标就变为
3.绘制秒针
要绘制秒针,需要先得到当前的秒数
s = Second(Now)
然后需要根据秒计算出需要绘制的秒针的坐标
由于秒针1圈是60秒,对应的是360度,所以1秒对应6度秒针边缘X坐标为:sx = Sin(6 * s * 3.1415926 / 180)
秒针边缘Y坐标为:sy = -Cos(6 * s * 3.1415926 / 180)
画出该指针Line (0, 0)-(sx, sy)
4.分针和时针请自行解决。
vb双指针问题
双指针问题总结
一、作用
通过两个指针在一个for循环下完成两个for循环的工作。
将时间复杂度由O(n2)降低到O(n1)
二、类型
1、链表
(1)反转链表
反转链表
反转链表的时候,使用双指针,只需要改变链表的next指针的指向,直接将链表反转,不用重新定义一个链表。
2、N数之和
(1)两个数之和
两个数之和
原思路是利用哈希表去代替一层for循环,快速查找指定元素的下标。
但是这个题目不能用双指针做,因为求的是下标。
排序会打乱原始下标,如果是求元素,就可以用双指针。
双指针首先会将元素进行排序,然后用一左一右两个指针,通过判断和的大小,移动指针的方向。
(2)三个数之和
利用一个遍历和一个双指针操作。
vb6中的指针位移运算——无符号长整数加减法的实现在VB6中,指针位移运算可以使用Win32 API中的函数来实现,其中包括获取指针地址、指针偏移和指针运算等操作。
无符号长整数的加减法实现需要借助指针位移运算来进行数值的操作和运算。
首先,让我们了解一下指针位移运算的概念和用途。
指针位移运算是通过改变指针的偏移量来实现指针的移动,以访问不同的内存地址。
在VB6中,我们可以使用Declare语句来引用Win32 API中的指针位移运算函数,例如GetMem1、GetMem2和GetMem4函数。
其中,GetMem1函数可以通过指针位移运算来获取指定内存地址的一个字节数据。
示例如下:```Private Declare Sub GetMem1 Lib "msvbvm60.dll" _Alias "GetMem1" (ByVal Address As Long, ByRef Value As Byte)Dim ptr As LongDim data As Byteptr = &H12345678 '内存地址GetMem1 ptr, data '获取内存地址对应的一个字节数据```GetMem2和GetMem4函数的用法类似,分别用于获取两个字节和四个字节数据。
在VB6中,无符号长整数没有内置的数据类型,因此,我们需要通过将长整数拆分为更小的数据类型来实现无符号的加减运算。
例如,我们可以将一个32位的无符号长整数拆分为4个8位的无符号整数,然后进行各个字节的加减运算,最后将结果拼接起来。
以下是无符号长整数加法的实现示例:```Function ULongAdd(Operand1 As Long, Operand2 As Long) As LongDim result As LongDim ptr1 As Long, ptr2 As Long, ptr3 As Long, ptr4 As LongDim byte1 As Byte, byte2 As Byte, byte3 As Byte, byte4 As Byteptr1 = VarPtr(byte1)ptr2 = VarPtr(byte2)ptr3 = VarPtr(byte3)ptr4 = VarPtr(byte4)'拆分Operand1和Operand2为4个字节GetMem1 ptr1, Operand1 And &HFFGetMem1 ptr2, (Operand1 And &HFF00) \ &H100GetMem1 ptr3, (Operand1 And &HFF0000) \ &H10000GetMem1 ptr4, (Operand1 And &HFF000000) \ &H1000000'各个字节相加byte1 = byte1 + (Operand2 And &HFF)byte2 = byte2 + ((Operand2 And &HFF00) \ &H100)byte3 = byte3 + ((Operand2 And &HFF0000) \ &H10000)byte4 = byte4 + ((Operand2 And &HFF000000) \ &H1000000) '拼接结果result = byte1 + (byte2 * &H100) + (byte3 * &H10000) + (byte4 * &H1000000)ULongAdd = resultEnd Function```上述示例中,我们先将两个长整数Operand1和Operand2拆分为4个字节数据,然后进行四个字节的相加,最后将结果拼接起来。
vb 函数指针VB函数指针在VB编程中,函数指针是一种非常有用的概念。
它允许我们将函数作为参数传递给其他函数,或者将函数赋值给变量。
函数指针的使用可以大大提高代码的灵活性和可重用性,使得程序更加高效和易于维护。
一、函数指针的定义与声明在VB中,函数指针是通过声明一个代表函数的委托类型来实现的。
委托是一种特殊的数据类型,它可以存储对一个或多个方法的引用。
通过委托,我们可以将函数指针作为参数传递给其他函数,或者将函数指针赋值给一个变量。
声明一个函数指针的语法如下:Public Delegate Sub MyDelegate(ByVal value As Integer)这里声明了一个名为MyDelegate的委托类型,它可以存储一个接受一个整数参数并返回空值的方法。
二、函数指针的使用1. 将函数指针作为参数传递给其他函数使用函数指针作为参数传递给其他函数,可以实现更加灵活的函数调用。
例如,我们可以定义一个函数,该函数接受一个函数指针作为参数,并在适当的时候调用该函数。
下面是一个示例代码:Public Sub ProcessData(ByVal data As Integer, ByVal callback As MyDelegate)' 处理数据Console.WriteLine("处理数据:" & data)' 调用回调函数callback(data)End SubPublic Sub PrintData(ByVal data As Integer)' 打印数据Console.WriteLine("打印数据:" & data)End SubPublic Sub Main()Dim callback As MyDelegate = AddressOf PrintDataProcessData(123, callback)End Sub在上面的代码中,我们定义了一个ProcessData函数,它接受一个整数参数和一个函数指针作为参数。
VB鼠标的API函数使用详解鼠标是计算机中常用的输入设备之一,通过鼠标用户可以进行控制、操作等操作。
在使用VB编程时,我们可以通过API函数来实现鼠标的一些特定操作,如设置鼠标的位置、隐藏或显示鼠标指针等。
下面我们就来详细介绍一下VB中鼠标的API函数使用方法。
首先,我们需要在VB的代码窗口中声明API函数,这样我们才能在程序中使用这些函数。
在VB中,我们可以使用Declare语句来声明API函数,如下所示:```Private Declare Function 函数名 Lib "dll文件名" (参数列表)As 返回值类型```其中,函数名是API函数的名称,Lib是API函数所在的dll文件名,参数列表是API函数的参数列表,返回值类型是API函数的返回值类型。
1.设置鼠标的位置鼠标的位置可以通过API函数SetCursorPos来设置,代码如下:```Private Declare Function SetCursorPos Lib "user32" (ByVal X As Long, ByVal Y As Long) As LongSub SetMousePosition(ByVal X As Long, ByVal Y As Long)SetCursorPos X, YEnd Sub```在上述代码中,我们使用Declare语句声明了SetCursorPos函数,该函数位于user32.dll文件中。
然后我们定义了一个名为SetMousePosition的子过程,通过调用SetCursorPos函数来设置鼠标的位置。
2.隐藏或显示鼠标指针我们可以使用API函数ShowCursor来隐藏或显示鼠标指针,代码如下:```Private Declare Function ShowCursor Lib "user32" (ByVal bShow As Long) As LongSub HideCursorShowCursor FalseEnd SubSub ShowCursorShowCursor TrueEnd Sub```在上述代码中,我们使用Declare语句声明了ShowCursor函数,该函数位于user32.dll文件中。
vb 结构体指针VB 结构体指针是一种用于在 VB 编程中处理数据的重要工具。
结构体指针是指向结构体变量内存地址的指针,通过它可以直接访问和操作结构体的成员。
本文将详细介绍 VB 结构体指针的概念、用法和注意事项。
一、概念及用法1.1 概念VB 结构体指针是指向结构体变量的内存地址的指针,它可以直接访问和操作结构体的成员。
结构体是一种用户自定义的数据类型,它可以包含多个不同类型的成员变量。
1.2 用法使用 VB 结构体指针可以实现以下功能:- 在函数中传递结构体指针作为参数,以便在函数内部直接修改结构体的值。
- 通过结构体指针来访问和修改结构体的成员,避免了对整个结构体进行复制操作,提高了程序的效率。
- 在动态分配内存时,可以使用结构体指针来操作和管理内存,灵活地分配和释放内存空间。
二、结构体指针的声明和初始化2.1 声明结构体指针在 VB 中声明结构体指针需要使用 Declare 语句,语法格式如下:Declare PtrSafe Sub ProcName Lib "LibName" Alias "AliasName" (ByRef structPtr As StructTypeName)2.2 初始化结构体指针初始化结构体指针可以通过以下两种方式实现:- 使用 AddressOf 运算符获取结构体变量的内存地址,然后将地址赋值给结构体指针变量。
- 使用 New 关键字创建一个结构体变量,并将结构体变量的地址赋值给结构体指针变量。
三、使用结构体指针修改结构体的值使用结构体指针可以方便地修改结构体的值,具体步骤如下:1. 声明一个结构体变量并初始化。
2. 声明一个结构体指针变量,并将结构体变量的地址赋值给结构体指针变量。
3. 通过结构体指针变量访问和修改结构体的成员。
4. 最后,释放结构体指针所指向的内存空间。
四、结构体指针的注意事项4.1 空指针检查在使用结构体指针之前,需要进行空指针检查,以避免访问空指针导致的程序崩溃或异常。
用vb实现指针时钟的制作1、自定义坐标,让坐标原点在中心位置。
2、获取系统时间,使用函数time获取当前系统时间,而时、分、秒分别用以下函数Hour(Time)Minute(Time)Second(Time)可以用h,m,s三个变量分别存储系统当前的时、分、秒3、钟面的绘制,钟面上任意一点A的坐标A点坐标如下:X=ρcos(α)Y=ρsin(α)绘制钟面上的点3、指针的另一点的的x,y坐标的计算分析:若指针在第一象限,则B点坐标如下:X=ρcos(α)Y=ρsin(α)∵α+θ=π/2∴α=π/2 -θ∴x=ρCos(α)= ρcos(π/2 -θ)y=ρsin(α) =ρsin(π/2 -θ)若指针在第四象限,则有:∵α+θ=π/2+2π∴α=π/2+2π-θ又∵设α为任意角,终边相同的角的同一三角函数的值相等:sin(2kπ+α)= sinαcos(2kπ+α)= cosα∴x=ρcos(α)= ρcos(π/2+2π-θ)= ρcos(π/2 -θ) y=ρsin(α)= ρsin(π/2+2π-θ)= ρsin(π/2 -θ)同理,可以证明指针端点的坐标在二、三象限上也存在以下的关系:x=ρcos(π/2 -θ)y=ρsin(π/2 -θ)即对于时刻的指针端点的坐标均符合以下的表达式x=ρcos(π/2 -θ)y=ρsin(π/2 -θ)又∵秒针转动的角度值:θ=π/30*s∴秒针端点的坐标为x=ρcos(π/2 -π/30*s)y=ρsin(π/2 -π/30*s)同理,分针端点的坐标为x=ρcos(π/2 -π/30*m)y=ρsin(π/2 -π/30*m)同理,时针端点的坐标为x=ρcos(π/2 -π/6*s)y=ρsin(π/2 -π/6*s)。
vba函数指针【原创实用版】目录1.VBA 函数指针的定义与作用2.VBA 函数指针的声明与使用3.VBA 函数指针的注意事项正文在 Visual Basic for Applications(VBA)编程中,函数指针是一种特殊的指针类型,可以用来调用其他函数或过程。
使用函数指针可以让代码更加简洁、灵活,提高代码的可读性和可维护性。
下面将详细介绍 VBA 函数指针的定义与作用、声明与使用以及注意事项。
一、VBA 函数指针的定义与作用函数指针是一个内存地址,它指向存储在 VBA 项目中的一个函数或过程。
通过使用函数指针,可以在代码中直接调用其他函数或过程,而无需明确指定其名称。
这使得代码更加简洁,尤其在处理大量函数和过程的情况下,可以提高代码的可读性和可维护性。
二、VBA 函数指针的声明与使用1.声明函数指针要声明一个函数指针,需要使用“Public/Private/Dim”关键字来定义一个变量,并在括号内指定函数或过程的名称。
以下是一个声明函数指针的示例:```Dim FunctionPtr As Function```2.使用函数指针声明完函数指针后,可以通过为其赋值来使用。
以下是一个使用函数指针调用函数的示例:```FunctionPtr = Function1(arg1, arg2)```其中,“Function1”是需要调用的函数名称,“arg1”和“arg2”是传递给函数的参数。
三、VBA 函数指针的注意事项1.函数指针在使用前必须初始化,即指向一个有效的函数或过程。
2.在调用函数指针时,需要确保传递的参数与被指向的函数或过程所需的参数类型和数量匹配。
3.函数指针可以随时更改其指向的函数或过程,但需要注意在更改指向后,需要重新为函数指针赋值。
综上所述,VBA 函数指针是一种非常有用的特性,可以让代码更加简洁、灵活。
一、函数指针AddressOf得到一个VB内部的函数指针,我们可以将这个函数指针传递给需要回调这个函数的API,它的作用就是让外部的程序可以调用VB内部的函数。
但是VB里函数指针的应用,远不象C里应用那么广泛,因为VB文档里仅介绍了如何将函数指针传递给API以实现回调,并没指出函数指针诸多神奇的功能,因为VB是不鼓励使用指针的,函数指针也不例外。
首先让我们对函数指针的使用方式来分个类。
1、回调。
这是最基本也是最重要的功能。
比如VB文档里介绍过的子类派生技术,它的核心就是两个API:SetWindowLong和CallWindowProc。
我们可以使SetWindowLong这个API来将原来的窗口函数指针换成自己的函数指针,并将原来的窗口函数指针保存下来。
这样窗口消息就可以发到我们自己的函数里来,并且我们随时可以用CallWindowProc来调用前面保存下来的窗口指针,以调用原来的窗口函数。
这样,我们可以在不破坏原有窗口功能的前提下处理钩入的消息。
具体的处理,我们应该很熟悉了,VB文档也讲得很清楚了。
这里需要注意的就是CallWindowProc这个API,在后面我们将看到它的妙用。
在这里我们称回调为让"外部调用内部的函数指针"。
2、程序内部使用。
比如在C里我们可以将C函数指针作为参数传递给一个需要函数指针的C函数,如后面还要讲到的C库函数qsort,它的声明如下:#define int (__cdecl *COMPARE)(const void *elem1, const void *elem2)void qsort(void *base, size_t num, size_t width,COMPARE pfnCompare);它需要一个COMPARE类型函数指针,用来比较两个变量大小的,这样排序函数可以调用这个函数指针来比较不同类型的变量,所以qsort可以对不同类型的变量数组进行排序。
VB指针教程(1,2,3)VB指针教程1'先理解下变量的地址与指向这个地址的值。
xx省xx市xx街xx号就是一个地址,'指向这个地址的值就是这个地址就有什么。
比如这个地址是张三家的地址,'张三的家有什么呢?这个有什么就是这个地址所指向的值。
'VB没用操作指针的语言特性,因此需要通过WinAPI函数来进行操作,下面我们将'演示一个非常简单的指针操作,让大家在VB使用指针有个基本的了解。
'CopyMemory函数参数'CopyMemory是WinAPI函数,为了演示我把其修改成了两个版本,'版本1:CopyMemory1'版本2:CopyMemory2'版本1Destination及Source的参数是按照引用传递的(ByRef) '版本2Destination及Source的参数是按照值传递的(ByVal)'参数说明:'Destination'要复制内存块的目的地址?'Source'要复制内存块的源地址?'Length'指定要复制内存块的大小,单位为字节'返回值'该函数为VOID型,没有返回值。
Private Declare Sub CopyMemory1 Lib"kernel32"Alias"Rtl MoveMemory" _(ByRef Destination As Any, ByRef Source As Any, ByVal Leng th As Long)Private Declare Sub CopyMemory2 Lib"kernel32"Alias"Rtl MoveMemory" _(ByVal Destination As Any, ByVal Source As Any, ByVal Lengt h As Long)'在Basic语言演变成QBasic,然后到Visual Basic之前,VarPtr 函数就已经存在了。
vb6中的指针位移运算——无符号长整数加减法的实现在VB6中,指针位移运算是一种非常重要并且常用的操作,特别是在进行无符号长整数的加减法实现时。
通过指针位移运算,我们可以实现更高效、更灵活的数值计算,从而更好地满足程序的需求。
在VB6中,指针位移运算是通过内置的函数和运算符来实现的。
通过这些函数和运算符,我们可以对无符号长整数进行位移操作,从而实现加减法和其他数值计算。
下面,我将详细介绍VB6中指针位移运算的实现方法,并结合实际示例进行详细讲解。
一、指针位移运算的基本概念1.1 什么是指针位移运算在VB6中,指针位移运算是指对无符号长整数进行位移操作的一种数值计算方法。
通过指针位移运算,我们可以实现对长整数的加减法,并且可以灵活地控制位移的距离和方向,从而满足不同的计算需求。
1.2 指针位移运算的应用场景指针位移运算广泛应用于各种数值计算和程序设计中,特别是在需要高效、灵活的无符号长整数加减法实现时。
通过指针位移运算,我们可以提高程序的性能和效率,同时实现更灵活的数值计算。
二、VB6中指针位移运算的实现方法2.1 内置函数和运算符在VB6中,我们可以使用内置的函数和运算符来实现指针位移运算。
这些函数和运算符包括:AND运算符、OR运算符、XOR运算符、NOT函数等。
通过这些函数和运算符,我们可以实现对无符号长整数的位移操作,从而实现加减法等数值计算。
2.2 实际示例下面,我将通过一个实际示例来详细介绍VB6中指针位移运算的实现方法。
假设我们需要实现一个无符号长整数的加法运算,可以按照以下步骤进行:Step 1:将两个长整数进行AND运算,得到结果的低位部分;Step 2:将两个长整数进行XOR运算,得到结果的高位部分;Step 3:将Step 2的结果左移一位,并与Step 1的结果进行OR运算,得到最终的加法结果。
通过以上实例,我们可以看到,在VB6中指针位移运算的实现不仅简洁高效,而且可以满足各种复杂的数值计算需求。
VB中数据库记录指针的概念与应用在数据库知识里,有一个很重要的概念,那就是记录指针。
对数据表的记录进行操作,通常有四种即:显示(读取)记录、更新(修改)字段、添加记录和删除记录。
在进行这些操作时,往往需要用户知道目前记录指针是指向哪一条记录,比如:对某一条特定记录进行某字段的修改等。
所以在数据库应用中,记录指针是一个重要的概念。
在数据库知识里,我们把记录指针指向的那条记录,叫当前记录。
本文以VB6环境下,以使用ADODB.Recordset对象为例,来介绍记录指针和当前记录的概念。
我们都知道,使用ADODB.Recordset对象,进行记录字段的修改,例如:Rst.Fields("姓名")="王老大"Rst.Fields("性别")="男"Rst.Fields("学号")="101"Rst.Updata这样就可以把此时记录指针指着的记录(叫做当前记录)的这三个字段,修改更新为上面新的数据了。
那么这里需要用户知道,用什么命令把记录指针移动到指向你要操作的记录上。
使用ADODB.Recordset对象移动记录指针的语句有四个。
Rst.MoveFirst ---- 记录指针移动到第1条记录Rst.MoveNext ---- 记录指针移动到下一条记录Rst.MoveLast ---- 记录指针移动到最后1条记录Rst.MovePrevious ---- 记录指针移动到上一条记录问题:数据表里的记录是有限的,如果我们不断地使用Rst.MoveFirst,那么记录指针终究会移动到数据表的底部,并且可能从底部移动到表的外面。
如果我们无意中将记录指针从底部移动到表的外面,然后执行:Rst.Fields("姓名")="王老大"Rst.Fields("性别")="男"Rst.Fields("学号")="101"Rst.Updata显然系统会提示错误信息。
vba函数指针摘要:1.VBA 函数指针简介2.VBA 函数指针的作用3.VBA 函数指针的定义与声明4.VBA 函数指针的实例5.VBA 函数指针的优缺点正文:【1.VBA 函数指针简介】VBA(Visual Basic for Applications)是一种为Microsoft Office 应用程序设计的编程语言。
在VBA 中,函数指针是一种特殊的数据类型,用于存储函数的名称和参数。
通过使用函数指针,可以实现对函数的调用和参数传递,从而简化代码结构和提高程序执行效率。
【2.VBA 函数指针的作用】VBA 函数指针主要用于以下两个方面:- 调用函数:使用函数指针可以实现对VBA 函数的调用,无需记住函数的具体名称和参数,提高了代码的可读性和可维护性。
- 传递参数:函数指针可以方便地传递参数,使得函数的调用过程更加简洁。
【3.VBA 函数指针的定义与声明】在VBA 中,函数指针的定义和声明与其他数据类型相似。
首先,需要声明一个函数指针变量,然后为其分配一个函数的名称和参数。
下面是一个示例:```vbaDim FunctionPtr As FunctionSet FunctionPtr = Function("myFunction", "arg1", "arg2")```其中,"myFunction"是函数的名称,"arg1"和"arg2"是函数的参数。
【4.VBA 函数指针的实例】下面是一个使用函数指针调用函数的实例:```vbaSub TestFunctionPtr()Dim FunctionPtr As FunctionDim result As VariantSet FunctionPtr = Function("myFunction", "arg1", "arg2")result = FunctionPtr("value1", "value2")MsgBox resultEnd SubFunction myFunction(arg1 As Variant, arg2 As Variant) As Variant myFunction = arg1 * arg2End Function```在这个实例中,我们声明了一个名为"myFunction"的函数,它接受两个参数并返回它们的乘积。
例1:以下程序我们申请几个指向不同类型的指针:’使用<StructLayout(LayoutKind.Sequential)>属性告诉net编译器:结构的元素在内存中按其出现的顺序排列<StructLayout(LayoutKind.Sequential)> _Public Structure DEFUDT_TestPublic bytb As BytePublic i32a As Int32End StructurePublic 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 ByteDim thObject2 As GCHandle = GCHandle.Alloc(tudtTest, GCHandleType.Pinned)Dim tpObject2 As IntPtr = thObject2.AddrOfPinnedObject() ’取得指向结构的指针’在这儿你可以写对指针处理的任意代码(在例2中会给予补充)……’在使用完毕后一定要释放指针指向的内存块,让垃圾回收器可对这个内存块回收处理If thObject.IsAllocated ThenthObject.Free()End IfIf thObject1.IsAllocated ThenthObject1.Free()End IfIf thObject2.IsAllocated ThenthObject2.Free()End IfEnd Function上例中指针流程处理可以归纳为:1、定义一个具有合适内存长度的引用变量(关于引用变量和值变量的差异可以参观 的书籍)2、使用GCHandle.Alloc方法将变量的内存区域固定下来。
vb 指针函数指针函数是在VB语言中常用的一种函数类型,它可以用来处理内存中的数据,并返回相应的结果。
本文将介绍指针函数的基本概念、使用方法以及注意事项。
一、什么是指针函数指针函数是一种特殊的函数,它的返回值是一个指针类型。
在VB语言中,指针函数可以通过声明返回类型为指针类型来定义。
指针函数的返回值可以是变量、数组或者结构体等。
二、指针函数的声明和定义在VB语言中,可以使用Declare语句声明指针函数的原型,然后在代码中进行定义和使用。
指针函数的声明通常包含函数名、返回类型、参数列表等信息。
例如:Declare Function MyPointerFunction Lib "mylibrary.dll" () As IntPtr在上述声明中,MyPointerFunction是指针函数的名称,Lib关键字用于指定函数所在的动态链接库名称,()表示该函数没有参数,As IntPtr表示返回类型为指针类型。
三、指针函数的使用方法指针函数的使用方法与普通函数类似,可以通过调用函数名加上参数列表来使用。
例如:Dim ptr As IntPtr = MyPointerFunction()在上述代码中,通过调用MyPointerFunction函数获取返回值,并将其赋值给ptr变量。
四、指针函数的注意事项在使用指针函数时,需要注意以下几点:1. 指针函数返回的指针必须在使用完之后进行释放,以防止内存泄漏。
可以使用Marshal类中的相应方法来释放指针所指向的内存空间。
2. 在使用指针函数返回的指针时,需要进行类型转换,以便正确地访问内存中的数据。
可以使用Marshal类中的相应方法进行类型转换。
3. 在使用指针函数时,需要确保传入正确的参数,以避免发生错误或异常。
可以通过检查参数的类型和值来确保参数的正确性。
4. 指针函数的使用应尽量避免出现空指针异常,可以通过判断指针是否为空来避免潜在的错误。
在VB6(Visual Basic 6.0)中,`SetFilePointer` 函数用于设置文件指针的位置。
文件指针是一个内部的概念,用于指示文件中的当前位置。
通过移动文件指针,可以读取或写入文件的不同部分。
`SetFilePointer` 函数的语法如下:```vbSetFilePointer(filehandle, offset, whence)```* `filehandle`:必需。
一个有效的文件句柄,表示要操作的文件。
* `offset`:必需。
一个Long 类型的偏移量,表示相对于`whence` 参数指定位置的偏移量。
* `whence`:可选。
指定偏移量的起始位置。
这是一个Long 类型的值,有以下可能的值:+ `0`:偏移量从文件的开头开始计算(默认值)。
+ `1`:偏移量从当前位置开始计算。
+ `2`:偏移量从文件的末尾开始计算。
下面是一个示例,演示了如何使用`SetFilePointer` 函数将文件指针移动到文件的开头:```vbDim filehandle As IntegerDim offset As Long' 打开文件filehandle = Open("C:\example.txt", "r")' 将文件指针移动到文件开头offset = 0SetFilePointer(filehandle, offset, 0)' 关闭文件Close filehandle```在上面的示例中,我们使用`Open` 函数打开了一个文件,并将返回的文件句柄存储在`filehandle` 变量中。
然后,我们使用`SetFilePointer` 函数将文件指针移动到文件的开头。
最后,我们使用`Close` 函数关闭了文件句柄。
VB中利用CopyMemory使用指针一、指针是什么?不需要去找什么标准的定义,它就是一个32位整数,在C语言和在VB里都可以用Long 类型来表示。
在32位Windows平台下它和普通的32位长整型数没有什么不同,只不过它的值是一个内存地址,正是因为这个整数象针一样指向一个内存地址,所以就有了指针的概念。
有统计表明,很大一部分程序缺陷和内存的错误访问有关。
正是因为指针直接和内存打交道,所以指针一直以来被看成一个危险的东西。
以至于不少语言,如著名的JAVA,都不提供对指针操作的支持,所有的内存访问方面的处理都由编译器来完成。
而象C和C++,指针的使用则是基本功,指针给了程序员极大的自由去随心所欲地处理内存访问,很多非常巧妙的东西都要依靠指针技术来完成。
关于一门高级的程序设计语言是不是应该取消指针操作,关于没有指针操作算不算一门语言的优点,我在这里不讨论,因为互联网上关于这方面的没有结果的讨论,已经造成了占用几个GB的资源。
无论最终你是不是要下定决心修习指针技术《葵花宝典》,了解这门功夫总是有益处的。
注意:在VB里,官方是不鼓励使用什么指针的,本文所讲的任何东西你都别指望取得官方的技术支持,一切都要靠我们自己的努力,一切都更刺激!让我们开始神奇的VB指针探险吧!二、来看看指针能做什么?有什么用?先来看两个程序,程序的功能都是交换两个字串:【程序一】:【程序二】:你是不是以为第一个程序要快,因为它看着简单而且不用调用API(调用API需要额外的处理,VB文档明确指出大量调用API将降低程序性能)。
但事实上,在VB集成环境中运行,程序二要比程序一快四分之一;而编译成本机代码或p-code,程序二基本上要比程序一快一倍。
下面是两个函数在编译成本机代码后,运行不同次数所花时间的比较:运行100000次,SwapStr需要170毫秒,SwapPtr需要90毫秒。
运行200000次,SwapStr需要340毫秒,SwapPtr需要170毫秒。
[VB]VB中的指针,VB也可以使用指针!一、指针是什么?不需要去找什么标准的定义,它就是一个32位整数,在C语言和在VB里都可以用Long类型来表示。
在32位Windows平台下它和普通的32位长整型数没有什么不同,只不过它的值是一个内存地址,正是因为这个整数象针一样指向一个内存地址,所以就有了指针的概念。
有统计表明,很大一部分程序缺陷和内存的错误访问有关。
正是因为指针直接和内存打交道,所以指针一直以来被看成一个危险的东西。
以至于不少语言,如著名的JA V A,都不提供对指针操作的支持,所有的内存访问方面的处理都由编译器来完成。
而象C和C++,指针的使用则是基本功,指针给了程序员极大的自由去随心所欲地处理内存访问,很多非常巧妙的东西都要依靠指针技术来完成。
关于一门高级的程序设计语言是不是应该取消指针操作,关于没有指针操作算不算一门语言的优点,我在这里不讨论,因为互联网上关于这方面的没有结果的讨论,已经造成了占用几个GB的资源。
无论最终你是不是要下定决心修习指针技术《葵花宝典》,了解这门功夫总是有益处的。
注意:在VB里,官方是不鼓励使用什么指针的,本文所讲的任何东西你都别指望取得官方的技术支持,一切都要靠我们自己的努力,一切都更刺激!让我们开始神奇的VB指针探险吧!二、来看看指针能做什么?有什么用?先来看两个程序,程序的功能都是交换两个字串:【程序一】:’’标准的做法SwapStrSub SwapStr(sA As String, sB As String)Dim sTmp As StringsTmp = sA: sA = sB: sB = sTmpEnd Sub【程序二】:’’用指针的做法SwapPtrPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long)Sub SwapPtr(sA As String, sB As String)Dim lTmp As LongCopyMemory lTmp, ByVal VarPtr(sA), 4CopyMemory ByVal VarPtr(sA), ByVal VarPtr(sB), 4CopyMemory ByVal VarPtr(sB), lTmp, 4End Sub你是不是以为第一个程序要快,因为它看着简单而且不用调用API(调用API需要额外的处理,VB文档明确指出大量调用API将降低程序性能)。
闲着么事使用VS2010VB制作了一个小时钟,功能是指针型的,在正常情况下时钟窗体是隐藏的,只有再点击鼠标展开时窗体才会出现并点击移动。
下面是效果图以下是实现代码,只要建立一个VS2010VB窗体工程添加相关控件即可以实现。
欢迎指正也为初学者一个参考,并希望能够带来帮助。
——青檐铃风Public Class Form1'Private Declare Function CreateEllipticRgn Lib"gdi32"(ByRef X1As Long,_'ByRef Y1As Long,ByRef X2As Long,ByRef Y2As Long)As Long'Private Declare Function SetWindowRgn Lib"user32"(ByRef hWnd As Long,_'ByRef hRgn As Long,ByRef bRedraw As Long)As Long'Dim a,b As Long'Dim w,h As LongDim sdeg,srad,Mdeg,mrad,hdeg,hradDim xx1%,yy1%'宣告变量xx1,yy1为整型(给圆心用的)Dim FormVieFlag As Integer=0Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load'w=Me.Width'h=Me.Height'a=CreateEllipticRgn(0,0,w,h)'b=SetWindowRgn(Me.hWnd,a,True)'设置椭圆形窗体'Me.Move(Screen.Width-Me.Width)\2,(Screen.Height-Me.Height)\2'PictureBox1.Image.Save("c:\桌面")'Me.FormBorderStyle=Windows.Forms.FormBorderStyle.NoneLabel1.Visible=False'Label2.Visible=FalseButton2.Visible=FalseButton1.Visible=False'计算圆心的x轴xx1xx1=142'Me.Width\2'计算圆心的y轴yy1yy1=142'(Me.Height-15)\2'将下面3根针的起点x1,y1全定位在圆心上Line1.X1=xx1:Line1.Y1=yy1Line2.X1=xx1:Line2.Y1=yy1Line3.X1=xx1:Line3.Y1=yy1'画钟的外匡让线条粗一点'Cicle1.BorderWidth=5'Cicle1.FillColor=Color.Red'画一个圆'Cicle1.Move(-Me.Width)\2,(-Me.Height)\2Line2.BorderWidth=1'秒针的粗度'Line2.BorderColor=Color.Blue'秒针的颜色Line1.BorderWidth=2'分针的粗度'Line1.BorderColor=Color.Black'分针的颜色Line3.BorderWidth=3'时针的粗度'Line3.BorderColor=Color.YellowGreen'时针的颜色Timer1.Interval=500Call ShowTime()End SubPrivate Sub Timer1_Tick1(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles Timer1.TickCall ShowTime()Label1.Text=TimeOfDayDim P2As Point=MousePositionIf P2.X>Me.Location.X And P2.X<Me.Location.X+Me.Width And P2.Y< Me.Location.Y+Me.Height And P2.Y>Me.Location.Y ThenIf Me.FormBorderStyle<>Windows.Forms.FormBorderStyle.Sizable And FormVieFlag=1ThenMe.Location=New Point(Me.Location.X,Me.Location.Y-30)Me.FormBorderStyle=Windows.Forms.FormBorderStyle.SizableElseIf Me.FormBorderStyle<>Windows.Forms.FormBorderStyle.None And FormVieFlag=0ThenMe.Location=New Point(Me.Location.X,Me.Location.Y+30)Me.FormBorderStyle=Windows.Forms.FormBorderStyle.NoneEnd IfLabel1.Visible=True'Label2.Visible=TrueButton2.Visible=TrueButton1.Visible=TrueElseIf Me.FormBorderStyle<>Windows.Forms.FormBorderStyle.None ThenMe.Location=New Point(Me.Location.X,Me.Location.Y+30)Me.FormBorderStyle=Windows.Forms.FormBorderStyle.NoneEnd IfLabel1.Visible=False'Label2.Visible=FalseButton2.Visible=FalseButton1.Visible=FalseFormVieFlag=0End IfEnd SubPrivate Sub ShowTime()Me.Text=TimeOfDay'标题栏显示现在时间'Second Hand'画秒针'计算秒针的角度,每一秒是360度除以60秒=6度,所以要乘上6sdeg=Second(TimeOfDay)*6'vb是以弧度为单位来计算,所以角度换算弧度是3.14/180,秒针跑了N度就乘上Nsrad=(3.14/180)*sdeg'900是秒针的长度,以圆心(line2的x1,y1)为准,计算出在这个弧度时line2.x2在什么位置Line2.X2=Line2.X1+(95*Math.Sin(srad))'900是秒针的长度,以圆心(line2的x1,y1)为准,计算出在这个弧度时line2.y2在什么位置Line2.Y2=Line2.Y1-(95*Math.Cos(srad))'Minute Hand'画分针'计算分针的角度,每一分是360度除以60分=6度,所以要乘上6,秒针动分针也会动,'所以还要加上秒针移动所产生的分针移动.'秒针转了1圈360度,分针才会前进1分钟=6度,所以比例是6/360等于1/60Mdeg=Minute(TimeOfDay)*6+(sdeg*1/60)'vb是以弧度为单位来计算,所以角度换算弧度是3.14/180,分针跑了N度就乘上Nmrad=(3.14/180)*Mdeg'vb是以弧度为单位来计算,所以角度换算弧度是3.14/180,分针跑了N度就乘上N'750是分针的长度,以圆心(line1的x1,y1)为准,计算出在这个弧度时line1.x2在什么位置Line1.X2=(80*Math.Sin(mrad))+Line1.X1'750是分针的长度,以圆心(line1的x1,y1)为准,计算出在这个弧度时line1.y2在什么位置Line1.Y2=Line1.Y1-(80*Math.Cos(mrad))'Hour Hand'画时针'计算时针的角度,每一小时时针跑30度,分针动时针也会动,所以还要加上分针移动所产生的时针移动.'分针转了1圈360度,时针才会前进1刻划=30度,所以比例是30/360等于1/12hdeg=Hour(TimeOfDay)*30+(Mdeg/12)'vb是以弧度为单位来计算,所以角度换算弧度是3.14/180,时针跑了N度就乘上Nhrad=(3.14/180)*hdeg'500是时针的长度,以圆心(line3的x1,y1)为准,计算出在这个弧度时line3.x2在什么位置Line3.X2=(60*Math.Sin(hrad))+Line3.X1'500是时针的长度,以圆心(line3的x1,y1)为准,计算出在这个弧度时line3.y2在什么位置Line3.Y2=Line3.Y1-(60*Math.Cos(hrad))End SubPrivate Sub Button1_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles Button1.ClickMe.Close()'卸载本窗口end subEnd SubPrivate Sub Button2_Click(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles Button2.ClickIf FormVieFlag=0ThenFormVieFlag=1ElseFormVieFlag=0End IfEnd SubEnd Class。
《VB真是想不到系列》每次看大师的东西到了精彩之处,我就会拍案叫绝:"哇噻,真是想不到!"。
在经过很多次这种感慨之后,我发现只要我们动了脑筋,我们自己也能有让别人想不到的东西。
于是想到要把这些想不到的东拿出来和大家一起分享,希望抛砖引玉,能引出更多让人想不到的东西。
VB真是想不到系列之二:VB《葵花宝典》--指针技术关键字:VB、指针、动态内存分配、效率、安全难度:中级至高级要求:熟悉VB,掌握基本的C,了解汇编,了解内存分配原理。
想当年东方不败,黑木崖密室一战,仅凭一根绣花针独战四大高手,神出鬼没,堪称天下武林第一高手。
若想成为VB里的东方不败,熟习VB《葵花宝典》,掌握VB指针技术,乃是不二的法门。
欲练神功,引刀……,其实掌握VB指针技术,并不需要那么痛苦。
因为说穿了,也就那么几招,再勤加练习,终可至神出鬼没之境。
废话少说,让我们先从指针的定义说起。
一、指针是什么?不需要去找什么标准的定义,它就是一个32位整数,在C语言和在VB里都可以用Long 类型来表示。
在32位Windows平台下它和普通的32位长整型数没有什么不同,只不过它的值是一个内存地址,正是因为这个整数象针一样指向一个内存地址,所以就有了指针的概念。
有统计表明,很大一部分程序缺陷和内存的错误访问有关。
正是因为指针直接和内存打交道,所以指针一直以来被看成一个危险的东西。
以至于不少语言,如著名的JA V A,都不提供对指针操作的支持,所有的内存访问方面的处理都由编译器来完成。
而象C和C++,指针的使用则是基本功,指针给了程序员极大的自由去随心所欲地处理内存访问,很多非常巧妙的东西都要依靠指针技术来完成。
关于一门高级的程序设计语言是不是应该取消指针操作,关于没有指针操作算不算一门语言的优点,我在这里不讨论,因为互联网上关于这方面的没有结果的讨论,已经造成了占用几个GB的资源。
无论最终你是不是要下定决心修习指针技术《葵花宝典》,了解这门功夫总是有益处的。
注意:在VB里,官方是不鼓励使用什么指针的,本文所讲的任何东西你都别指望取得官方的技术支持,一切都要靠我们自己的努力,一切都更刺激!让我们开始神奇的VB指针探险吧!二、来看看指针能做什么?有什么用?先来看两个程序,程序的功能都是交换两个字串:【程序一】:注释:标准的做法SwapStrSub SwapStr(sA As String, sB As String)Dim sTmp As StringsTmp = sA: sA = sB: sB = sTmpEnd Sub【程序二】:注释:用指针的做法SwapPtrPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"_ (Destination As Any, Source As Any, ByVal Length As Long)Sub SwapPtr(sA As String, sB As String)Dim lTmp As LongCopyMemory lTmp, ByVal VarPtr(sA), 4CopyMemory ByVal VarPtr(sA), ByVal VarPtr(sB), 4CopyMemory ByVal VarPtr(sB), lTmp, 4End Sub你是不是以为第一个程序要快,因为它看着简单而且不用调用API(调用API需要额外的处理,VB文档明确指出大量调用API将降低程序性能)。
但事实上,在VB集成环境中运行,程序二要比程序一快四分之一;而编译成本机代码或p-code,程序二基本上要比程序一快一倍。
下面是两个函数在编译成本机代码后,运行不同次数所花时间的比较:运行100000次,SwapStr需要170毫秒,SwapPtr需要90毫秒。
运行200000次,SwapStr需要340毫秒,SwapPtr需要170毫秒。
运行2000000次,SwapStr需要3300毫秒,SwapPtr需要1500毫秒。
的确,调用API是需要额外指令来处理,但是由于使用了指针技术,它没有进行临时字串的分配和拷贝,因此速度提高了不少。
怎么样,想不到吧!C/C++程序员那么依赖指针,无非也是因为使用指针往往能更直接的去处理问题的根源,更有驾驭一切的快感。
他们不是不知道使用指针的危险,他们不是不愿意开卫星定位无级变速的汽车,只是骑摩托更有快感,而有些地方只有摩托才走得过去。
和在C里类似,在VB里我们使用指针也不过三个理由:一是效率,这是一种态度一种追求,在VB里也一样;二是不能不用,因为操作系统是C写的,它时刻都在提醒我们它需要指针;三是突破限制,VB想照料我们的一切,VB给了我们很强的类型检查,VB象我们老妈一样,对我们关心到有时我们会受不了,想偶尔不听妈妈的话吗?你需要指针!但由于缺少官方的技术支持,在VB里,指针变得很神秘。
因此在C里一些基本的技术,在VB里就变得比较困难。
本文的目的就是要提供给大家一种简单的方法,来将C处理指针的技术拿到VB里来,并告诉你什么是可行的,什么可行但必须要小心的,什么是可能但不可行的,什么是根本就不可能的。
三、程咬金的三板斧是的,程序二基本上就已经让我们看到VB指针技术的模样了。
总结一下,在VB里用指针技术我们需要掌握三样东西:CopyMemory,VarPtr/StrPtr/ObjPtr, AdressOf. 三把斧头,程咬金的三板斧,在VB里Hack的工具。
1、CopyMemory关于CopyMemory和Bruce McKinney大师的传奇,MSDN的Knowledge Base中就有文章介绍,你可以搜索"ID: Q129947"的文章。
正是这位大师给32位的VB带来了这个可以移动内存的API,也正是有了这个API,我们才能利用指针完成我们原来想都不敢想的一些工作,感谢Bruce McKinney为我们带来了VB的指针革命。
如CopyMemory的声明,它是定义在Kernel32.dll中的RtlMoveMemory这个API,32位C 函数库中的memcpy就是这个API的包装,如MSDN文档中所言,它的功能是将从Source 指针所指处开始的长度为Length的内存拷贝到Destination所指的内存处。
它不会管我们的程序有没有读写该内存所应有的权限,一但它想读写被系统所保护的内存时,我们就会得到著名的Access Violation Fault(内存越权访问错误),甚至会引起更著名的general protection (GP) fault(通用保护错误)。
所以,在进行本系列文章里的实验时,请注意随时保存你的程序文件,在VB集成环境中将"工具"->"选项"中的"环境"选项卡里的"启动程序时"设为"保存改变",并记住在"立即"窗口中执行危险代码之前一定要保存我们的工作成果。
2、VatPtr/StrPtr/ObjPtr它们是VB提供给我们的好宝贝,它们是VBA函数库中的隐藏函数。
为什么要隐藏?因为VB开发小组,不鼓励我们用指针嘛。
实际上这三个函数在VB运行时库MSVBVM60.DLL(或MSVBVM50.DLL)中是同一个函数VarPtr(可参见我在本系列第一篇文章里介绍的方法)。
其库型库定义如下:[entry("VarPtr"), hidden]long _stdcall VarPtr([in] void* Ptr);[entry("VarPtr"), hidden]long _stdcall StrPtr([in] BSTR Ptr);[entry("VarPtr"), hidden]long _stdcall ObjPtr([in] IUnknown* Ptr);即然它们是VB运行时库中的同一个函数,我们也可以在VB里用API方式重新声明这几个函数,如下:Private Declare Function ObjPtr Lib "MSVBVM60" Alias "VarPtr" _(var As Object) As LongPrivate Declare Function VarPtr Lib "MSVBVM60" _(var As Any) As Long(没有StrPtr,是因为VB对字符串处理方式有点不同,这方面的问题太多,在本系列中另用一篇《VB字符串全攻略》来详谈。
顺便提一下,听说里没有这几个函数,但只要还能调用API,我们就可以试试上面的几个声明,这样在里我们一样可以进行指针操作。
但是请注意,如果通过API调用来使用VarPtr,整个程序二SwapPtr将比原来使用内置VarPtr函数时慢6倍。
)如果你喜欢刨根问底,那么下面就是VarPtr函数在C和汇编语言里的样子:在C里样子是这样的:long VarPtr(void* pv){return (long)pv;}所对就的汇编代码就两行:mov eax,dword ptr [esp+4]ret 4 注释:弹出栈里参数的值并返回。
之所以让大家了解VarPtr的具体实现,是想告诉大家它的开销并不大,因为它们不过两条指令,即使加上参数赋值、压栈和调用指令,整个获取指针的过程也就六条指令。
当然,同样的功能在C语言里,由于语言的直接支持,仅需要一条指令即可。
但在VB里,它已经算是最快的函数了,所以我们完全不用担心使用VarPtr会让我们失去效率!速度是使用指针技术的根本要求。
一句话,VarPtr返回的是变量所在处的内存地址,也可以说返回了指向变量内存位置的指针,它是我们在VB里处理指针最重要的武器之一。
3、ByVal和ByRefByVal传递的参数值,而ByRef传递的参数的地址。
在这里,我们不用去区别传指针/传地址/传引用的不同,在VB里,它们根本就是一个东西的三种不同说法,即使VB的文档里也有地方在混用这些术语(但在C++里的确要区分指针和引用)初次接触上面的程序二SwapPtr的朋友,一定要搞清在里面的CopyMemory调用中,在什么地方要加ByVal,什么地方不加(不加ByVal就是使用VB缺省的ByRef)准确的理解传值和传地址(指针)的区别,是在VB里正确使用指针的基础。
现在一个最简单的实验来看这个问题,如下面的程序三:【程序三】:注释:体会ByVal和ByRefSub TestCopyMemory()Dim k As Longk = 5Note: CopyMemory ByVal VarPtr(k), 40000, 4Debug.Print kEnd Sub上面标号Note处的语句的目的,是将k赋值为40000,等同于语句k=40000,你可以在"立即"窗口试验一下,会发现k的值的确成了40000。