VFP调用Windows API函数
正式开始:
我想你可能经常看过如下这种语句,我不得不在这里重复地说一遍
DECLARE INTEGER SetWindowText IN user32;
INTEGER hWnd,;
STRING lpString
Hwnd=thisform.hwnd
customtext=space(250)
lnlen=len(customtext)
SetWindowText(Hwnd,customtext, lnlen)
第一个语句就是一般的api定义,意思就是注册一个user32.dll动态库中的函数SetWindowText ,接受参
数integer类型hwnd, string 类型h的sWindowText 参数,,返回值为intger ,这是参数按值传递的一部分,第三个语句就是调用注册的api函数了,看起来和我们用普通的foxpro函数并无区别,只是多了一步注册的步骤.
我们再看看另一种定义,按引用传递的的方式,看到什么不同了吗?
第一个语句就是一般的api定义,意思就是注册一个user32.dll动态库中的函数SetWindowText ,接受的参数是integer类型hwnd, string 类型h的sWindowText , INTEGER 类型的cch,返回值为intger类型
DECLARE INTEGER GetWindowText IN user32;
INTEGER hwnd,;
STRING @lpString,;
INTEGER cch
Hwnd=thisform.hwnd
Hwnd=thisform.hwnd
Stext =space(250)
lnlen=250
SetWindowText(Hwnd,@customtext, lnlen)
没错,多了一个伊妹儿的符号:@,注意调用的时候也得加入该符号,此符号的意思是说参数sWidowText是按引用传递的,为什么要这么用呢,原因是我们要用函数GetwindowText 的得到一个窗体(Form)标
题.GetwindowText 的职责就是将我们要的值填入sWidowText中,如果调用成功你就会看到sWidowText的值已经改变.此处你要明白所谓的按引用传递有如C中的指针,我们只是该内容的地址为参数传给GetwindowText,它直接在地址指向的内存单元上修改数据.所以我们才可能看到sWidowText值在调用GetwindowText()函数就发生了改变。
以上两种就是最基本的windows api定义了.对于简单的函数一般都可以这样解决.
也许此时你有疑问,你是在哪里知道这些函数的详细信息的?很好很好,有问题是好的.那么请你打开msdn,什么?你不知道MSDN,我倒..^_^简单而说msdn是涵盖了大量内容的帮助文档,大部分的api在其中都有讲述,有些还有小实例.在这里并不要求你要记住所有windows的api函数,这不可行也不可
能,只要知道有它的存在,大概的功能,用时查msdn就可以,更重要的是知道怎么去把它纠出来,然后理解它. 如果你现在没有安装MSDN,我强烈建议你马上下载一个msdn2005.该帮助文档大部分都是E文,你得有点心理准备.
键入SetWindowText查询,你就会看到所有相关的函数原型,参数及返回值的解释.此时查询后你看到一些莫名其妙的返回值类型和参数类型.如:
DWORD,LPTSTR
为什么不是integer,string呢?
请听我说,由于window api 是基于c的,而C中有一种叫宏定义的东西,而DWORD,LPTSTR就是一种宏罢了,宏定义时一般以大写出现,只不过是类型的另一种叫法而已
再查询DWORD,LPTSTR你就可以看到它们的真面目,
DWORD<=>无符号的32位的整型,
LPTSTR<=>字符串指针
注:<=>符号在此代表等价的意思
原来DWORD与integer指的同一种数据类型.这就好比有一天在大街上你可能看到一个漂亮的女孩,很是心动,你可能称她为美女或者天使,但最终美女或天使指向的都是这个女孩,不过就是这个女孩的代名词而已.
下面我以C为例说明以不同类型来读取相同内存区域后会得到怎么样的内容,我希望你以内存的角度来看。这些原理是相通的,和语言无关,只是C来讲比较方便罢了,所以我选择它来让问题简单化.此步将有助于你理解怎么在foxpro处理含有结构参数的一些复杂 API 函数,虽然这一部分比较枯燥,但我还是希望你努力看下去.如果这道坎过了,下来也就容易许多
先来看看简单的变量声明:
假设你的系统上 int类型占4个字节,
int icount=0x11ff; //
那么该语句将为你开辟一个四字节的内存空间,假设0x11ff存入内存单元:0x000420000之处,那么内存中是这样的
内存地址内存单元的内容
0x00420000:0xff
0x00420001:0x11
0x00420002:0
0x00420003:0
如果我们现在定义一个字符串指针指向该区域,会是怎么样的呢?
char * cValue= (char *)0x00420000;
C中的字符串是以chr(0)结尾的,所以当你用* cValue取值的时候,得到的将是这样一个字符串
chr(0xff)+chr(0x11)+chr(0)
现在你应该明白,以整数存放后的内存,后以字符串读出会是什么样的.下面再讲以字符串存入后再以32
位的整数读取的情况
char * sHello="hello world";
连chr(0)在内12个字符长,一字节一个字符,也就是12个字节了.在内存里面它到底是怎么样呢?
这十二个字符将依次放到内存区域当中,不过他不是放的"H" "E" "L" ....chr(0),而是将每个字符转为ascii码后放入
假设以上"hello world"存在内存单元:0x00420000之处,那么hello world在内存中将如下所示:
内存地址内存单元的内容
0x00420000:"h"的ascii
0x00420001:"e"的ascii
0x00420002:"l"的ascii
0x00420003:"l"的ascii
0x00420004:"o"的ascii
0x00420005:" "的ascii
0x00420006:"w"的ascii
0x00420007:"o"的ascii
0x00420008:"r"的ascii
0x00420009:"l"的ascii
0x00420010:"d"的ascii
0x00420011:NULL值的ascii,即foxpro中的chr(0)
我们现在声明一个int 指针指向0x00420007之处,
int * theValue=(int *)0x00420007;
而此时0x000420007到0x000420010是"orld",四个内存单元存的分别是
0x00420007:"o"的ascii
0x00420008:"r"的ascii
0x00420009:"l"的ascii
0x00420010:"d"的ascii
那么我们用*theValue得到的值将是:
"d"的ascii向左位移24位+"l"的ascii向左位移16位+"r"的ascii向左位移8位+"o"的ascii所构成的32位整数的值
再说一个结构:
Struct
{
int ndvalue;
int nJvalue;
} testStruct;
//size 8 byte
testStruct testResult;
testResult.ndvalue=0x11
text函数什么意思testResult.ndvalue=0x22
同样假设testResult结构从内存0x00420000开始,下面就是它在内存存储的样子:
内存地址内存单元的内容
0x00420000:0x11
0x00420001:0
0x00420002:0
0x00420003:0
0x00420004:0x22
0x00420005:0
0x00420006:0
0x00420007:0
0x00420008:0
我们同样也可以用字符串,或32位整数,还有其它类型都可以,来访问该段内存,得到你想要的数据,方法和上面的一样,这里我就不再重述了.
我举这些例子,是要你明白所谓的整型数据,字符串,结构,只是不同的数据表示方法罢了,在内存中已经存在的数据要以什么表示方式来读取完全取决于你的所需.即便你是以字符串存入的,你也可以将它视为数值读出来,反之亦然.
很多api 函数并不是像上面说的函数那么简单,它可能由一些结构组成,抓取一个最简单的示例来说:
windows定义了一个名为POINT结构来存放一个座标的信息由有两个分别是32位整型成员组成,如下:
Struct
{
int x;
int y;
}Point;
//size= 8 byte
而api 函数GetCursorPos()恰好就是接收POINT这种结构.它的功能是为你填取其中传递过去地址所指向的结构,让你知道当前鼠标的座标.由于我们要得到参数在调用后的结果,我们得用引用的方式传递参数,这个到现在你要知道.可在foxpro里面没结构类型,你是不是有点抱怨了为什么不提供结构.不过没关系,我们还有办法,主要的就是用字符串来开辟内存,然后将该内存区域当作结构来使用,基本就是如此理解,不过中间得进行一些转换,转换的原理就是上面所讲的以不同类型读取相同内存的内容。下面我再说明
首先知道Point结构占八个字节长,由两个四字节的成员组成.
那么定义一个长度八个字节的字符串区域,将该区域的地址告诉GetCursorPos, 而GetCursorPos就会对该内存操作,为你老老实实填好它,我们的工作嘛就是将取出来的字符串的值还原成我们想要的成员x和y 的整数值.
lcPosition = repl(chr(0),8)
lnXCoord = 0
lnYCoord = 0
GetCursorPos(@lcPosition )
LEFT(lcPosition,4) &&就是X的值
right(lcPosition,4) &&就是Y的值
把原来内存中的内容读成我们想要的32位的整数.请不要说用str()不就可以了.NO,你会这么说,证明你还没看懂我上面说的用不同类型读取相同内存区域的部分,请折回看了再继续.
只要将这些字符取ascii,移位后组成一个32位的数值就达到目的.希望到此你已经明白为什么要如此转.虽然FOXpro8以上都提供了ctobin的函数可以达到相同的功能,但这里我们还是自己来写一段函数来实现4字节字符串到到32位整型的转换
FUNCTION API_STRTOINT(tcSrcString )
RETURN Asc(SUBSTR(tcSrcString, 1,1)) + ;
BitLShift(Asc(SUBSTR(tcSrcString, 2,1)), 8) +;
BitLShift(Asc(SUBSTR(tcSrcString, 3,1)), 16) +;
BitLShift(Asc(SUBSTR(tcSrcString, 4,1)), 24)
ENDFUNCTION
好了,完整的实现就是如下这样了,理论的东西比较多,先有了基础才能高楼筑起
lcPosition = repl(chr(0),8)
lnXCoord = 0
lnYCoord = 0
GetCursorPos(@lcPosition )
API_STRTOINT(LEFT(lcPosition,4))
API_STRTOINT(right(lcPosition,4))
在这里我小结一下:
从结构中获取内容的步骤,先用字符串分配相应的内存区域,让API函数填取其它内容,根据我们得到的字符串及成员的类型进行相应转换
此处写个32位整数到四字节字符串的函数,就是一个逆转的过程.下面我们要用到
FUNCTION api_inttostr (tnValue)
#DEFINE mbase 2^8 -1
ch0=BITAND(mbase, tnValue)
ch1=BITAND(bitrshift(tnValue,8),mbase)
ch1=BITAND(bitrshift(tnValue,16)mbase) FDAFDAF
ch1=BITAND(bitrshift(tnValue,24mbase)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论