小弟之前做了一个小程序,用于VB6制作有输出函数的DLL文件.但自己在使用之中,发现在DLL里的函数的返回值如果是String类型,便无法返回.经人指点,使用了类似SendMessage返回的方法,就是采用事先定义一缓冲区,由函数把返回值写入缓冲区的方法来得到返回值.试了一下,返回值是到了,但是有点不对.具体情况如下:    DLL内函数:Public Function GetPwd(Hwnd As Long, BuffLong As Long, Buff As String) As LongGetPwd = SendMessage(Hwnd, WM_GETTEXT, BuffLong, Buff)End Function   程序内调用部分的代码:Dim K as string * 255
Din M as longM=GetPwd(FormHwnd,len(K),K)Text1.Text=K   如果这样调用,程序就会非法操作.而对DLL内作如下改动后,侧可以返回返回值,但是值不正常:Public Function GetPwd(Hwnd As Long, BuffLong As Long, Buff As String) As LongDim M As LongM = Len(Buff)GetPwd = SendMessage(Hwnd, WM_GETTEXT, M, Buff)End Function   设Buff的值为"D:\kkk\mydate.exe",那么在程序内得到的值就是"D",也就是说返回值始终只有第一个字符.调用方法都是一样的,这让我很不明白.于是,在DLL内又添加了一句MsgBox语句,确认了DLL内的Buff的值是正常的:Public Function GetPwd(Hwnd As Long, BuffLong As Long, Buff As String) As LongDim M As LongM = Len(Buff)GetPwd = SendMessage(Hwnd, WM_GETTEXT, M, Buff)MsgBox M & "    " & BuffEnd Function结果是,DLL内的值是非常正确,然后我又想到是不是在调用时的缓冲区出了问题,于是在程序内加入这样一句:Dim K as string * 255
Din M as longM=GetPwd(FormHwnd,len(K),K)MsgBox len(K)Text1.Text=K结果,程序内显示"255".这下,我真的晕了.最后,我把做DLL用的模块直接添加到工程里,把对自制DLL函数的声明先注释掉,然后运行程序,返回值就正常了!但是,由于不是在DLL内,无法达到我所期望的效果来.我现在真的是没有一点办法了.我想请教一下大家,这当中到底哪里出了问题呢?还烦请指点一二!

解决方案 »

  1.   

    Public Function GetPwd(Hwnd As Long, BuffLong As Long, Byval Buff As String) As Long
      

  2.   

    简单给你写了一个:
    activex dll工程:工程名pwd,只有一个class(名为test),编译为pwd.dll,类模块test代码如下:
    Option ExplicitPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal Hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
    Private Const WM_GETTEXT = &HD
    Public Function GetPwd(ByVal Hwnd As Long, ByVal BuffLong As Long, Buff As String) As Long
        If BuffLong < 1 Then
            GetPwd = 0
        End If
        Dim mbuff() As Byte
        ReDim mbuff(BuffLong - 1)
        Dim i As Long, j As Long
        i = VarPtr(mbuff(0))
        j = SendMessage(Hwnd, WM_GETTEXT, BuffLong, ByVal i&)
        If j > 0 Then
            Dim out() As Byte
            ReDim out(j - 1)
            CopyMemory out(0), mbuff(0), j
            Erase mbuff
            Buff = StrConv(out, vbUnicode)
            GetPwd = j
            Erase out
          Else
            Erase mbuff
            GetPwd = 0
            Buff = vbNullString
          End If
    End Function普通工程中,窗体上只有一个按钮
    '首先要引用pwd.dll(工程 引用 浏览 找到pwd.dll,并点击确定,当然你先用regsvr32注册也行)
    Option ExplicitPrivate Sub Command1_Click()
        Dim myGetpwd As New pwd.test
        Dim s As String
        Dim i As Long
        '不需要给字串预先分配缓冲区,直接调用即可,返回值为字串所占的字节数
        i = myGetpwd.GetPwd(Text1.Hwnd, 255, s)
        MsgBox s
        Set myGetpwd = Nothing
    End Sub
      

  3.   

    注意vb默认的是unicode,sendmessage是不是默认ansi,M = Len(Buff)至少要改成M = LenB(Buff),反正一句话,注意unicode和ansi的区别。
      

  4.   

    给你举个例子:dll中的导出函数
    Public Function AddStr(s1 As String, s2 As String) As String
        AddStr = s1 & s2
    End Function测试的声明
    Private Declare Function AddStr Lib "dll.dll" (s1 As String, s2 As String) As StringPrivate Sub Form_Load()
        MsgBox AddStr("hello ", "world!")
    End Sub
      

  5.   

    //If BuffLong < 1 Then
            GetPwd = 0
        End If修改一下:
    If BuffLong < 1 Then
            GetPwd = 0
            Buff =vbnullstring
            exit function
     End If