dim bytSend(2) as byte
bytSend(0) = &H35
bytSend(1) = &H30
bytSend(2) = &H30
SendMessage htxt, WM_SETTEXT, 0, bytSend(0)dim strSend as string 
strsend="500"
SendMessage htxt, WM_SETTEXT, 0, byval strsend以上这两段代码执行的效果是一样的,不是很理解,谁能帮我解释一下?一般byval是用在形参前,这里用在实参前,有什么特殊意义吗?LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)这是SendMessage的原型
Declare Function SendMessage& Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any)这是VB中的声明这里调用的含义,当是定义的字符数组时,按地址传递,第一个元素传递过去是首地址,类似指针的运行;当是字符串传递,必须按值传递,传递过去还是分成了字符数组进行处理,就像c语言中字符串与字符数组的关系……不知道这样理解对不对以前我很多地方用到过第一种方式,不知道是不是都可以换成第二种方式,如果不行,是为什么?

解决方案 »

  1.   

    byval string 传的是字符串首字节地址
    字符串传值传址情况比较特殊
      

  2.   

    这与API的声明有关.在最后一个参数为lParam As Any的情况下分析:第一种情况,等于是byref lparam as byte,因此直接传入了一个字节数组的第一个元素进去,而byref表明了传递进来的是个指针:bytSend(0)的地址---->API第二种情况,是将字符串的值转化为integer类型后,再将这个临时的integer变量的地址传到API.byval strsend(将字符串自动隐式转换为integer,因为内容为数值)---->临时的integer变量的地址---->API两种方式,在最终到达API时,都是某个变量的地址.
      

  3.   

    老马,第一个我明白了,谢谢第二个你的意思是说byval是用来隐式转换的?但是我内容改为“abc”传递过去也是正确的啊~ 这个跟integer还有关系吗?
      

  4.   

    实参中,参数前加Byval关键字,一般用于API调用时Byref的参数,反之这不可以
    Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long注意到最后一个参数Lparm没有指明,VB默认为Byref
    SendMessage htxt, WM_SETTEXT, 0, bytSend(0)
    ’此句,按照约定,将bytSend(0)的地址传递给SendMessage dim strSend as string  
    strsend="500"
    SendMessage htxt, WM_SETTEXT, 0, byval strsend
    '如果没有Byval,则传递的是cstrsend的地址,现在使用byval,则传递的是strsend中的值
      

  5.   

    Byval传递副本,也就是在堆栈中开辟一个内存区域,把变量的值付给这个内存区域,只有函数对参数的使用不会影响原参数。
      

  6.   


    首先,那个应该叫字节数组,不是字符数组, byte 表示字节,并不是字符的意思
    你说字符数组,会让别人误会其次,N长度的字符串是不可能传过去的,传的是字符串首字节地址你说的代替的问题,分情况,象这帖子里面的例子就是可以代替的还有 byval xxx as string 为参数的api, 也可以改为传字节数组,无论怎么传,请无视数据内容和长度
    长度只能为4字节,只有4字节数据才能实现真正意义上的传值,否则全部都是传址,只是传的内容不同例如字符串:
      byval 传的是字符串首字节地址,这种情况下,被调用的函数可以修改字符串内容,但长度被固定了
            传进来的时候有多长,你修改的范围也就多大  byref 传变量地址,vb中,字符串变量是个2级地址类型的数据
            〔字符串变量1〕 的真实有效数据为 〔4字节字符串首字节地址〕
            在传址情况下,把字符串变量1的地址传过去,被调用的函数可以修改这个变量值的全部内容,
            也就不存在长度问题了,可以随便改
    说的有点繁琐,需要仔细体会一下,有什么不明白的,再说吧
      

  7.   

    明白什么了
    都胡说,遇见byval 就说是副本,复制,到底复制什么了
      

  8.   


    应该不是这样吧,VB对于字符串的传递,实际上是将源字符串的字串内容值转换为ansi编码,然后保存到一个临时变量中,再将该临时变量传递给函数
      

  9.   


    那是调用api和一些特殊的应用情况(put 文件 string等等)的时候才那样
    内部的字符串传递完全是 unicode格式的
    调用api时候是转换了,即便这种情况下也是遵循我说的那个方式,无论c++,c,或什么其他语言没有一种是把字符串直接复制到栈里面当参数的,全是字符串地址
      

  10.   

    这个...应该我想错了,我想成了API声明是byref xxx as integer的情况....重新组织一下,关于第二种的情况.先说一下VB中String变量的问题.VB中String类型的变量实际上就是COM规范中的BSTR,即前导4字节+后面实际存放字符串的缓冲区所组成.前导4字节中是后面字符串缓冲区的长度.而VB里面声明一个变量为String时,实际上这个变量是一个LONG类型变量,它里面保存的是指向BSTR字符串缓冲区的指针.因此使用VarPtr去取一个字符串变量的地址时,会取到一个指向LONG的指针(并不是指向字符串缓冲区),而这个LONG才是指向真正BSTR中缓冲区的第一字节的指针.所以我认为ByVal strsend实际是把那个一级指针的值(即指向真正缓冲区的指针)传入了....而API中是ByRef,则又将这个指针直接入栈了,所以能正确取得字符串的内容.(如果API声明是ByVal,则是取这个指针所指的位置的前4个字节入栈).上面是说"我认为",是因为我没有去跟踪API调用过程来进行验证,但我觉得这次是没错的,嘿嘿
      

  11.   

    >如果API声明是ByVal,则是取这个指针所指的位置的前4个字节入栈
    还纠结这个
    传的是字符串首字节地址,传字符串4个字节干嘛使,而且照这个想法,只能显示4个字节字符,实际上不是
      

  12.   

    这就不是跟踪的事,这其实都是基本概念
    msdn的帮助文档里面有说明