ceoguang 发表于 2009-2-26 04:22:17

程序间的参数传递及通讯

本帖最后由 ceoguang 于 2011-4-1 00:00 编辑

http://www.autoitx.com/attachment.php?aid=MTM5NzV8NjUzMGM1Yzh8MTMwMTU4NjU4NHw5Mzk5RFVOU1QvMjRUMlNYR3dSdDVCbVNrV2NpZERtaDd6eFMrSkVHbkR3K1paRQ%3D%3D&noupdate=yes

#NoTrayIcon

Opt("GUIOnEventMode", 1)
Opt("GUIResizeMode", 1)

Global Const $WM_COPYDATA = 0x004A
Global Const $WM_NULL = 0x0000
Global Const $WM_GETTEXTLENGTH = 0x000E
Global Const $EM_REPLACESEL = 0xC2
Global Const $EM_SETSEL = 0xB1

Global Const $tagCOPYDATASTRUCT = "dword dwData;dword cbData;ptr lpData;"

;http://msdn.microsoft.com/en-us/library/ms649010
#cs
      typedef struct tagCOPYDATASTRUCT {
      ULONG_PTR dwData;
      DWORD   cbData;
      PVOID   lpData;
      } COPYDATASTRUCT, *PCOPYDATASTRUCT;
#ce

Global $Mark = Random(1024, 65535, 1) ;广播的标识

$Form1 = GUICreate("进程通讯示例", 484, 351, -1, -1, -2133917696);$GUI_SS_DEFAULT_GUI, $WS_MAXIMIZEBOX, $WS_SIZEBOX
GUISetOnEvent(-3, "_GuiEvent")
$Edit1 = GUICtrlCreateEdit("", 8, 8, 465, 209)
GUICtrlSetLimit(-1, 1e8)
GUICtrlSetResizing(-1, 102)
$Edit2 = GUICtrlCreateEdit("", 8, 225, 465, 81)
GUICtrlSetResizing(-1, 582)
GUICtrlSetLimit(-1, 1e8)
$Button1 = GUICtrlCreateButton("发送", 200, 318, 75, 25)
GUICtrlSetOnEvent(-1, "_GuiEvent")
GUICtrlSetResizing(-1, 840)
GUISetState()
GUIRegisterMsg($WM_COPYDATA, "WM_COPYDATA")
GUIRegisterMsg($WM_NULL, "WM_NULL")
#EndRegion ### END Koda GUI section ###
Global $Target
Local $Count = 0
Broadcast_Msg()
While 1
      Sleep(100)
      $Count += 1
      If $Count = 100 Then ;10秒钟.
                $Count = 0
                If Not IsWindow($Target) Then Broadcast_Msg() ;向系统广播
      EndIf
WEnd

Func _GuiEvent()
      Switch @GUI_CtrlId
                Case -3
                        Exit
                Case $Button1
                        If GUICtrlRead($Edit2) <> "" Then
                              If IsWindow($Target) Then
                                        _SendProcessMsg($Target, GUICtrlRead($Edit2))
                                        If @extended Then
                                                $iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH) ;发送消息获取$Edit1的字节
                                                _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength) ;将焦点定位到最后
                                                _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, "<<发送到进程: (" & WinGetProcess($Target) & ") 的消息 " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF & GUICtrlRead($Edit2) & @CRLF & @CRLF, 0, "wparam", "wstr") ;向$Edit1焦点处写入收到的消息
                                                GUICtrlSetData($Edit2, "")
                                        Else
                                                MsgBox(48, "", "消息发送失败", -1, $Form1)
                                        EndIf

                              Else
                                        MsgBox(48, "", "找不到接收进程!", -1, $Form1)
                              EndIf
                        Else
                              MsgBox(48, "", "请输入要发送的内容!", -1, $Form1)
                        EndIf
      EndSwitch
EndFunc   ;==>_GuiEvent

Func WM_COPYDATA($hWnd, $iMsg, $iwParam, $ilParam)
      Local $iBuffer = DllStructCreate($tagCOPYDATASTRUCT, $ilParam)
      Local $tBuffer, $iLength, $RecMsg
      If DllStructGetData($iBuffer, "dwData") = 0x01234567 Then
                $tBuffer = DllStructCreate("char[" & DllStructGetData($iBuffer, 'cbData') & "]", DllStructGetData($iBuffer, 'lpData')) ;cbData保存着数据的大小,lpData接收到的数据,其值可以为空
                $RecMsg = BinaryToString(DllStructGetData($tBuffer, 1))
                $Target = $iwParam ;保存当前对话者的句柄
                $iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH) ;发送消息获取$Edit1的字节
                _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength) ;将焦点定位到最后
                _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, ">>收到消息类型 (" & $iMsg & ") 来自进程: (" & WinGetProcess($Target) & ") " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF & $RecMsg & @CRLF & @CRLF, 0, "wparam", "wstr") ;向$Edit1焦点处写入收到的消息
      EndIf
      Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_COPYDATA

Func WM_NULL($hWnd, $iMsg, $iwParam, $ilParam)
      Local $iLength
      If $ilParam <> $Mark Then
                MsgBox(64, "收到消息", "目标句柄: " & $iwParam, -1, $Form1);挂起线程,终止消息传递
                _SendProcessMsg($iwParam, "欢迎")
                $iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH)
                _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength)
                _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, ">>HWND (" & $iwParam & ") Process: (" & WinGetProcess($iwParam) & ") Msg: (" & $iMsg & ") " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF, 0, "wparam", "wstr")
      EndIf
      Return "GUI_RUNDEFMSG"
EndFunc   ;==>WM_NULL

Func Broadcast_Msg()
      _SendMessageTimeout(0xFFFF, $WM_NULL, $Form1, $Mark)
      $iLength = _SendMessageTimeout(GUICtrlGetHandle($Edit1), $WM_GETTEXTLENGTH)
      _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_SETSEL, $iLength, $iLength)
      _SendMessageTimeout(GUICtrlGetHandle($Edit1), $EM_REPLACESEL, True, "<<广播WM_NULL信息 " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & @CRLF, 0, "wparam", "wstr")
EndFunc   ;==>Broadcast_Msg

Func _SendProcessMsg($hWnd, $sMsg)
      ;$hWnd: 目标进程的主窗口句柄
      ;$sMsg: 要发送的消息内容
      Local $sBuffer = DllStructCreate("char[" & StringLen(StringToBinary($sMsg)) + 1 & "]")
      Local $tBuffer = DllStructCreate($tagCOPYDATASTRUCT)
      Local $pBuffer = DllStructGetPtr($tBuffer)
      Local $StrLen
      DllStructSetData($sBuffer, 1, StringToBinary($sMsg))
      DllStructSetData($tBuffer, "dwData", 0x01234567) ;标识。这个数值可以随意定。
      $StrLen = DllStructGetSize($sBuffer)
      If $StrLen > 2 ^ 32 - 1 Then
                MsgBox(16, "", "消息内容超出lParam限制", -1, $hWnd)
                Return SetError(1, 0)
      EndIf
      DllStructSetData($tBuffer, "cbData", $StrLen) ;数据大小
      DllStructSetData($tBuffer, "lpData", DllStructGetPtr($sBuffer)) ;发送的数据
      _SendMessageTimeout($hWnd, $WM_COPYDATA, $Form1, $pBuffer)
      ;对应消息函数的($hWnd, $iMsg, $iwParam, $ilParam)
      ;这里使用SendMessageTimeout是为了防止因目标线程繁忙或挂起导致返回时间过长(或无返回)从而导致当前调用的线程挂起(不再向下执行),当然你可以使用PostMessage,但PostMessage是没有结果返回的.
      Return SetExtended(@extended)
EndFunc   ;==>_SendProcessMsg

Func _SendMessageTimeout($hWnd, $iMsg, $wparam = 0, $lparam = 0, $iReturn = 0, $wParamType = "wparam", $lParamType = "lparam", $sReturnType = "lresult", $iTimeout = 1000, $iFlags = 3)
      ;这个参数结构是根据封装好的_SendMessage修改而来.可以完全替换_SendMessage.默认超时设置$iTimeout = 1000(单位毫秒),$iFlags是(SMTO_BLOCK , SMTO_ABORTIFHUNG)的组合
      ;http://msdn.microsoft.com/en-us/library/ms644952(VS.85).aspx
      Local $Ret = DllCall("user32.dll", $sReturnType, "SendMessageTimeoutW", "hwnd", $hWnd, "uint", $iMsg, $wParamType, $wparam, $lParamType, $lparam, "uint", $iFlags, "uint", $iTimeout, "dword_ptr*", $iReturn)
      If (@error) Or (Not $Ret) Then
                Return SetError(1, 0, "")
      EndIf
      Return SetError(0, 1, $Ret)
EndFunc   ;==>_SendMessageTimeout

Func IsWindow($hWnd)
      Local $aResult = DllCall("user32.dll", "bool", "IsWindow", "hwnd", $hWnd)
      If @error Then Return SetError(@error, @extended, 0)
      Return $aResult
EndFunc   ;==>IsWindow

出自http://www.autoitx.com/forum.php?mod=redirect&goto=findpost&ptid=21636&pid=263933&fromuid=1009
由于下载人数过多及原内容过旧,特更新一下.
使用这种方式传送的数据可以多达2^31-1字节.

破帽遮颜 发表于 2009-2-26 04:28:40

:face (37): :face (37): :face (37):

xrbenbeba 发表于 2009-2-26 10:13:33

:face (29):

jinghai 发表于 2009-2-26 10:41:30

很好,测试了一下

298311657 发表于 2009-3-10 19:40:14

实在是太好了~不用再使用TCP来传递信息了:face (36):

itljl 发表于 2009-3-11 17:55:04

主要应用在什么方面?

jycel 发表于 2009-3-13 16:22:18

看不懂?能讲解下么?

xulinghai 发表于 2009-3-13 18:50:58

不如直接贴出来看方便些。

UID 发表于 2009-3-13 20:43:32

收下了:face (31):

文白 发表于 2009-3-19 08:10:06

顶了
再说
终于找到你了

ddx13 发表于 2009-3-28 23:09:34

可以考虑用这个写什么东东玩了。

bachelor66 发表于 2009-5-27 15:15:45

留记号,需要时再来

yjcblue 发表于 2009-5-31 10:56:30

赚钱了 再来~~~

卫和谐 发表于 2009-5-31 17:45:25

看看这个是做什么用的?

guoliyan1 发表于 2009-6-1 09:54:56

收下以后研究。。
:face (29):
页: [1] 2 3 4 5 6 7 8 9 10
查看完整版本: 程序间的参数传递及通讯