#AutoIt3Wrapper_AU3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
#include-once
#include <WinApi.au3>
#region #HEAD#
; #INDEX# =======================================================================================================================
; Title .........: Communication
; AutoIt Version : 3.3.8.1
; Language ......: No
; Description ...: Общение между приложениями с одинаковыми идентификаторами. Например, своими копиями.
; Author(s) .....: inververs
; Requirements...: WinApi.au3
; Version........: 1.0
; ===============================================================================================================================

; #CURRENT# ===================================================================
;_Communication_Init
;_Communication_Send
; ==============================================================================

; #INTERNAL_USE_ONLY# ==========================================================
;__Communication_RMSG
;__Communication_Caller
;__Communication_Exit
; ==============================================================================

; #VARIABLES# ==================================================================
Global $__Communication_aInternalData[8]
OnAutoItExitRegister('__Communication_Exit')
; ==============================================================================
#endregion #HEAD#


; #FUNCTION# ====================================================================================================================
; Name...........: _Communication_Init
; Description ...: Подключает коммуникацию для вашего приложения.
; Syntax.........: _Communication_Init($hWnd, $sFunc = '', $vUniq = '')
; Parameters ....: $hWnd   		- HWND окна вашего приложения
; Parameters ....: $sFunc   	- функция для callback, которая будет вызываться при приеме сообщений.
;								  функция должна иметь 2 параметра:
;									1) HWND окна от которого пришло сообщение.
;									2) Само сообщение
; Parameters ....: $vUniq		- Уникальная строчка для вашего приложения.
; Return values .: Нет
; Author ........: inververs
; Modified.......: Нет
; Remarks .......: Ваше приложение должно иметь хотя бы одно окно. Запускайте эту функцию только 1 раз и коммуникация будет подключена.
;					Для отсылки сообщений используйте _Communication_Send
; Example .......: Да
; ===============================================================================================================================
Func _Communication_Init($hWnd, $sFunc = '', $vUniq = '')
	If $sFunc = Default Then $sFunc = ''
	If $vUniq = Default Then $vUniq = ''

	$__Communication_aInternalData[0] = ObjCreate('Scripting.Dictionary')
	$__Communication_aInternalData[1] = _WinAPI_RegisterWindowMessage('new_brcomm' & $vUniq)
	$__Communication_aInternalData[2] = _WinAPI_RegisterWindowMessage('bye_brcomm' & $vUniq)
	$__Communication_aInternalData[3] = _WinAPI_RegisterWindowMessage('say_brcomm' & $vUniq)
	$__Communication_aInternalData[4] = $sFunc
	$__Communication_aInternalData[5] = $hWnd

	GUIRegisterMsg($__Communication_aInternalData[1], "__Communication_RMSG")
	GUIRegisterMsg($__Communication_aInternalData[2], "__Communication_RMSG")
	GUIRegisterMsg($__Communication_aInternalData[3], "__Communication_RMSG")

	Local $aList = WinList('[CLASS:AutoIt v3 GUI]')
	For $iList = 1 To UBound($aList) - 1
		If $aList[$iList][1] = $hWnd Then ContinueLoop
		_WinAPI_PostMessage($aList[$iList][1], $__Communication_aInternalData[1], 0, $hWnd)
	Next
EndFunc   ;==>_Communication_Init

; #FUNCTION# ====================================================================================================================
; Name...........: _Communication_Send
; Description ...: Отсылает сообщение.
; Syntax.........: _Communication_Send($vMsg)
; Parameters ....: $vMsg - Данные. Данные должны быть типа PTR.
; Return values .: Нет
; Author ........: inververs
; Modified.......: Нет
; Remarks .......: Т.к данные имеют тип PTR, то это означает что нельзя отсылать строки, текст, массивы итп. Но вы можете отсылать номера сообщений,
;					которые будут понятны вашему приложению. Или можно отсылать HWND контрола вашего приложения в котором будет нужный текст.
; Link ..........: Нет
; Example .......: Нет
; ===============================================================================================================================
Func _Communication_Send($vMsg)
	__Communication_RMSG($__Communication_aInternalData[5], $__Communication_aInternalData[3], $vMsg)
EndFunc   ;==>_Communication_Send


#region #INTERNAL_USE_ONLY#
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __Communication_RMSG
; Description ...: Регистрирует сообщения
; Syntax.........: __Communication_RMSG($hWnd, $msgID, $wParam = 0, $lParam = 0)
; Parameters ....: $hWnd - HWND своего окна
;                  $msgID - номер сообщения
;                  $wParam - тело сообщения
;                  $lParam - HWND окна отправителя
; Return values .: Нет
; Author ........: inververs
; Remarks .......: Нет
; Example .......: Нет
; ===============================================================================================================================
Func __Communication_RMSG($hWnd, $msgID, $wParam = 0, $lParam = 0)
	Switch $msgID
		Case $__Communication_aInternalData[1]
			If Not $__Communication_aInternalData[0] .exists(String($lParam)) Then ;New window
				$__Communication_aInternalData[0] .add(String($lParam), 1)
				_WinAPI_PostMessage($lParam, $__Communication_aInternalData[1], 0, $hWnd)
			EndIf
		Case $__Communication_aInternalData[2], $__Communication_aInternalData[3]
			If Not $lParam Then
				For $v In $__Communication_aInternalData[0]
					_WinAPI_PostMessage(HWnd($v), $msgID, $wParam, $hWnd)
				Next
			ElseIf $msgID = $__Communication_aInternalData[2] And $__Communication_aInternalData[0] .exists(String($lParam)) Then ;Window closed
				$__Communication_aInternalData[0] .remove(String($lParam))
			Else ;New msg
				$__Communication_aInternalData[6] = $lParam
				$__Communication_aInternalData[7] = $wParam
				AdlibRegister('__Communication_Caller', 5)
			EndIf
	EndSwitch
EndFunc   ;==>__Communication_RMSG

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __Communication_Caller
; Description ...: Вызывает пользовательскую функцию
; Syntax.........: __Communication_Caller()
; Parameters ....: Нет
; Return values .: Нет
; Author ........: inververs
; Modified.......: Нет
; Remarks .......: Организует правильный Callback
; Related .......: Нет
; Link ..........: http://autoit-script.ru/index.php/topic,14718.0.html
; Example .......: Нет
; ===============================================================================================================================
Func __Communication_Caller()
	AdlibUnRegister('__Communication_Caller')
	Call($__Communication_aInternalData[4], $__Communication_aInternalData[6], $__Communication_aInternalData[7])
EndFunc   ;==>__Communication_Caller

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __Communication_Exit
; Description ...: Отсылает сообщения о выходе
; Syntax.........: __Communication_Exit
; Parameters ....: Нет
; Return values .: Нет
; Author ........: inververs
; Modified.......: Нет
; Remarks .......: Вызывается автоматически при выходе.
; Related .......: Нет
; Link ..........: Нет
; Example .......: Нет
; ===============================================================================================================================
Func __Communication_Exit()
	If $__Communication_aInternalData[5] Then __Communication_RMSG($__Communication_aInternalData[5], $__Communication_aInternalData[2])
EndFunc   ;==>__Communication_Exit
#endregion #INTERNAL_USE_ONLY#

#region #EXAMPLE#
; #EXAMPLE# =====================================================================================================================
; Запустить много раз
;~ #include <ButtonConstants.au3>
;~ #include <EditConstants.au3>
;~ #include <GUIConstantsEx.au3>
;~ #include <WindowsConstants.au3>
;~ $Form1 = GUICreate("Form1", 513, 407, 283, 265)
;~ $Edit1 = GUICtrlCreateEdit("", 8, 8, 497, 361)
;~ $Input1 = GUICtrlCreateInput("", 8, 376, 400, 21)
;~ $Button1 = GUICtrlCreateButton("Send", 424, 376, 75, 25, $BS_DEFPUSHBUTTON)
;~ GUISetState(@SW_SHOW)
;~ WinSetTitle($Form1,'',$Form1)
;~ _Communication_Init($Form1,'__DataRes')
;~ $hCtrl = GUICtrlGetHandle($Input1)
;~ While 1
;~ 	$nMsg = GUIGetMsg()
;~ 	Switch $nMsg
;~ 		Case $GUI_EVENT_CLOSE
;~ 			Exit
;~ 		Case $Button1
;~ 			_Communication_Send($hCtrl)
;~ 	EndSwitch
;~ WEnd
;~ Func __DataRes($hWndFrom = 0, $sMsg = 0)
;~ 	$sText = ControlGetText($hWndFrom,'',$sMsg)
;~ 	GUICtrlSetData($Edit1,'Msg from ' &$hWndFrom & ': ' & $sText & @CRLF,1)
;~ EndFunc
; ===============================================================================================================================
#endregion #EXAMPLE#