找回密码
 加入
搜索
查看: 64664|回复: 170

[原创] 程序间的参数传递及通讯

 火... [复制链接]
发表于 2009-2-26 04:22:17 | 显示全部楼层 |阅读模式
本帖最后由 ceoguang 于 2011-4-1 00:00 编辑



#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[0]) Then
                Return SetError(1, 0, "")
        EndIf
        Return SetError(0, 1, $Ret[7])
EndFunc   ;==>_SendMessageTimeout
 
Func IsWindow($hWnd)
        Local $aResult = DllCall("user32.dll", "bool", "IsWindow", "hwnd", $hWnd)
        If @error Then Return SetError(@error, @extended, 0)
        Return $aResult[0]
EndFunc   ;==>IsWindow

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

评分

参与人数 2金钱 +15 贡献 +11 收起 理由
wjc826194 + 1
破帽遮颜 + 15 + 10 精品文章

查看全部评分

发表于 2009-2-26 04:28:40 | 显示全部楼层

评分

参与人数 1金钱 -20 收起 理由
sanmoking -20 逮着你了,禁止纯表情帖,扣你分...

查看全部评分

发表于 2009-2-26 10:13:33 | 显示全部楼层
发表于 2009-2-26 10:41:30 | 显示全部楼层
很好,测试了一下
发表于 2009-3-10 19:40:14 | 显示全部楼层
实在是太好了~不用再使用TCP来传递信息了
发表于 2009-3-11 17:55:04 | 显示全部楼层
主要应用在什么方面?
发表于 2009-3-13 16:22:18 | 显示全部楼层
看不懂?能讲解下么?
发表于 2009-3-13 18:50:58 | 显示全部楼层
不如直接贴出来看方便些。
发表于 2009-3-13 20:43:32 | 显示全部楼层
收下了
发表于 2009-3-19 08:10:06 | 显示全部楼层
顶了
再说
终于找到你了
发表于 2009-3-28 23:09:34 | 显示全部楼层
可以考虑用这个写什么东东玩了。
发表于 2009-5-27 15:15:45 | 显示全部楼层
留记号,需要时再来
发表于 2009-5-31 10:56:30 | 显示全部楼层
赚钱了 再来~~~
发表于 2009-5-31 17:45:25 | 显示全部楼层
看看这个是做什么用的?
发表于 2009-6-1 09:54:56 | 显示全部楼层
收下以后研究。。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-4-20 00:33 , Processed in 0.080077 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表