republican 发表于 2010-9-18 09:17:50

[已解决]DllStructCreate "char"该如何转变为"wchar" (例子)

本帖最后由 republican 于 2010-9-18 22:33 编辑

整个例子是用WM_COPYDATA传输数据,不过只能传递char,单独修改为wchar后会有小问题。

这么做的目的是为了传递中文字符,而我对DllStruct之类的没什么研究,希望得到大家的帮忙,谢谢!


Parent.au3#include <WindowsConstants.au3>

Global $hParent, $hChild, $received

; parent gui
$hParent = GUICreate("Parent", 300, 120, 100)
$input_send = GUICtrlCreateInput("", 10, 10, 280, 20)
$btn = GUICtrlCreateButton("SEND TO CHILD", 80, 35, 140, 20, 0x0001)
GUICtrlCreateLabel("RECEIVED FROM CHILD", 10, 75, 280, 20, 0x01)
$input_received = GUICtrlCreateInput("", 10, 90, 280, 20, 0x0800)
GUISetState(@SW_SHOW)

; launch child - trade handles
GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA_ReceiveData") ; register WM_COPYDATA
ShellExecute("child.exe", $hParent) ; start child process - send parent handle
While Not $received ; wait for child process to return it's handle
    Sleep(50)
WEnd
$hChild = HWnd($received); assign child hamdle
$received = ""

; main loop
While 1
    $msg = GUIGetMsg()
    If $msg = -3 Then ExitLoop
    If $msg = $btn Then WM_COPYDATA_SendData($hChild, GUICtrlRead($input_send)) ; send to child
    If $received Then
      GUICtrlSetData($input_received, $received) ; receive form child
      $received = ""
    EndIf
WEnd
ProcessClose("child.exe")
Exit

;===================================================================================================================================
Func WM_COPYDATA_ReceiveData($hWnd, $MsgID, $wParam, $lParam) ;
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    $received = DllStructGetData($tMsg, 1)
EndFunc

Func WM_COPYDATA_SendData($hWnd, $sData)
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr")
    Local $tMsg = DllStructCreate("char[" & StringLen($sData) + 1 & "]")
    DllStructSetData($tMsg, 1, $sData)
    DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))
EndFunc
Child.au3#NoTrayIcon
#include <WindowsConstants.au3>

Global $hParent, $hChild, $received

Global $hParent = HWnd($CmdLine) ; get parent handle from commandline

; child gui
$hChild = GUICreate("Child", 300, 150, 440, Default, 0x00800000)
$input_send = GUICtrlCreateInput("", 10, 10, 280, 20)
$btn = GUICtrlCreateButton("SEND TO PARENT", 80, 35, 140, 20, 0x0001)
GUICtrlCreateLabel("RECEIVED FROM PARENT", 10, 75, 280, 20, 0x01)
$input_received = GUICtrlCreateInput("", 10, 90, 280, 20, 0x0800)
GUISetState(@SW_SHOW)

GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA_ReceiveData") ; register WM_COPYDATA
WM_COPYDATA_SendData($hParent, $hChild) ; return child handle to parent

; main loop
While 1
    $msg = GUIGetMsg()
    If $msg = $btn Then WM_COPYDATA_SendData($hParent, GUICtrlRead($input_send)) ; send to parent
    If $received Then
      GUICtrlSetData($input_received, $received) ; receive from parent
      $received = ""
    EndIf
WEnd
Exit

;===================================================================================================================================
Func WM_COPYDATA_ReceiveData($hWnd, $MsgID, $wParam, $lParam) ;
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("char[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    $received = DllStructGetData($tMsg, 1)
EndFunc

Func WM_COPYDATA_SendData($hWnd, $sData)
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr")
    Local $tMsg = DllStructCreate("char[" & StringLen($sData) + 1 & "]")
    DllStructSetData($tMsg, 1, $sData)
    DllStructSetData($tCOPYDATA, 2, StringLen($sData) + 1)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))
EndFunc代码打包:

republican 发表于 2010-9-18 13:30:39

谢谢Afan!

以上例子如果不修改成wchar的话,可以通过转换为 二进制 传递中文。不过这么做代码就啰嗦了,还有二次转换的问题, 所以希望研究过的各位仁兄提供一下修改意见,谢谢!

风行者 发表于 2010-9-18 13:32:26

发送
#include <winapi.au3>

$hwnd = WinGetHandle('Msg_Catcher')
$message = StringToBinary('大家好才是真的好')

$struct = DllStructCreate('char var1')
DllStructSetData($Struct,1,$message)
$pStruct = DllStructGetPtr($struct)

$struct2 = DllStructCreate('dword;dword;ptr')
DllStructSetData($struct2,1,0)
DllStructSetData($struct2,2,1000)
DllStructSetData($struct2,3,$pStruct)
$pStruct2 = DllStructGetPtr($struct2)

_SendMessage($hwnd, 0x4A, 0, $pStruct2)

接收

#include <winapi.au3>

GUICreate('Msg_Catcher')

GUIRegisterMsg(0x4A, '_Func')

While 1
    Sleep(1000)
WEnd

Func _Func($hWnd, $iMsg, $iwParam, $ilParam)

$a = DllStructCreate('dword var1;dword var2;ptr var3', $ilParam)
    $b = DllStructGetData($a, 3)
   
    $c = DllStructCreate('char var1',$b)
    $d = DllStructGetData($c, 1)
   
    MsgBox(0, '接收', BinaryToString($d))
EndFunc

rolaka 发表于 2010-9-18 16:04:30

是字符长度计算的问题把...unicode

5个中文可以显示4个 stringlen算法有问题估计

pusofalse 发表于 2010-9-18 17:05:48

- -|||
直接把char改成wchar不就好了吗,接收端和发送端都要修改,相应的指明缓存区长度的第2个DWORD,也应该改成wchar所占的长度。

republican 发表于 2010-9-18 21:00:01

回复 5# pusofalse

这个长度我换了许多值都没有正确结果,可以提示一下吗?

pusofalse 发表于 2010-9-18 22:15:07

回复 6# republican


    Send:
#include <winapi.au3>

$hWnd = WinGetHandle('Msg_Catcher')

$sString = "大家好才是真的好"
$iLength = StringLen($sString)

$tBuffer = DllStructCreate("dword;dword;ptr;wchar[" & $iLength + 1 & "]")
$pBuffer = DllStructGetPtr($tBuffer)

DllStructSetData($tBuffer, 2, $iLength * 2 + 2)
DllStructSetData($tBuffer, 3, $pBuffer + 12)
DllStructSetData($tBuffer, 4, $sString)

_SendMessage($hWnd, 0x4A, 0, $pBuffer)

Recv:
#include <winapi.au3>

GUICreate('Msg_Catcher')

GUIRegisterMsg(0x4A, '_Func')

While 1
    Sleep(1000)
WEnd

Func _Func($hWnd, $iMsg, $iwParam, $ilParam)
        Local $tBuffer, $pBuffer, $iLength, $tText

        $tBuffer = DllStructCreate("dword;ptr", $ilParam)
        $pBuffer = DllStructGetData($tBuffer, 2)
        $iLength = DllStructGetData($tBuffer, 1, 2) / 2

        $tText = DllStructCreate("wchar[" & $iLength & "]", $pBuffer)

        MsgBox(0, "", DllStructGetData($tText, 1))
EndFunc

rolaka 发表于 2010-9-18 22:19:02

本帖最后由 rolaka 于 2010-9-18 22:36 编辑

- -|||
直接把char改成wchar不就好了吗,接收端和发送端都要修改,相应的指明缓存区长度的第2个DWORD,也应 ...
pusofalse 发表于 2010-9-18 17:05 http://www.autoitx.com/images/common/back.gif

p版最近风格大变啊。。。

回复pusofalse

这个长度我换了许多值都没有正确结果,可以提示一下吗?
republican 发表于 2010-9-18 21:00 http://www.autoitx.com/images/common/back.gif

win7下不能测试 xpmode里成功了- -

DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tMsg));StringLen($sData) + 1)

republican 发表于 2010-9-18 22:31:42

本帖最后由 republican 于 2010-9-18 22:42 编辑

回复 7# pusofalse

谢谢,解决了!!!

Func WM_COPYDATA_ReceiveData($hWnd, $MsgID, $wParam, $lParam) ;
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("wchar[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    $received = DllStructGetData($tMsg, 1)
EndFunc

Func WM_COPYDATA_SendData($hWnd, $sData)
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr")
    Local $tMsg = DllStructCreate("wchar[" & StringLen($sData) + 1 & "]")
    DllStructSetData($tMsg, 1, $sData)
    DllStructSetData($tCOPYDATA, 2, StringLen($sData) * 2 + 2)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))
EndFunc

rolaka 发表于 2010-9-18 22:38:19

本帖最后由 rolaka 于 2010-9-18 22:41 编辑

回复pusofalse

谢谢,解决了!!!
republican 发表于 2010-9-18 22:31 http://www.autoitx.com/images/common/back.gif

我也贴下我的把...

Func WM_COPYDATA_ReceiveData($hWnd, $MsgID, $wParam, $lParam) ;
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr", $lParam)
    Local $tMsg = DllStructCreate("wchar[" & DllStructGetData($tCOPYDATA, 2) & "]", DllStructGetData($tCOPYDATA, 3))
    $received = DllStructGetData($tMsg, 1)
EndFunc

Func WM_COPYDATA_SendData($hWnd, $sData)
    Local $tCOPYDATA = DllStructCreate("dword;dword;ptr")
    Local $tMsg = DllStructCreate("wchar[" & StringLen($sData) + 1 & "]")
    DllStructSetData($tMsg, 1, $sData)
    DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tMsg));StringLen($sData) + 1)
    DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tMsg))
    $Ret = DllCall("user32.dll", "lparam", "SendMessage", "hwnd", $hWnd, "int", $WM_COPYDATA, "wparam", 0, "lparam", DllStructGetPtr($tCOPYDATA))
EndFunc


引用的原帖地址: http://www.autoitscript.com/forum/index.php?showtopic=106895&st=0&p=830524&hl=WM_COPYDATA&fromsearch=1&#entry830524

republican 发表于 2010-9-18 22:47:35

回复 10# rolaka

谢谢!!

republican 发表于 2010-12-3 07:02:45

回复 10# rolaka
昨天才发现这个现象:
在64位系统下,需要这样创建结构:

Local $tCOPYDATA = DllStructCreate("ptr;dword;ptr")
页: [1]
查看完整版本: [已解决]DllStructCreate "char"该如何转变为"wchar" (例子)