Jump to content
Sign in to follow this  
Erik.

Send message to external program

Recommended Posts

Erik.

Hi everyone,

I already made a search in the help file but i could not realy found where i was looking for.

I am trying to make a little program to send some commands trough midi to light up some lights.

Those lights need to light up when functions or other things in an external program are running or used.

I have the possibility to send commands to the external program and receive information back.

The program is written in Delphi, there is a little example program that i have attached in this post to see what i need to send and how it's received back.

I hope some could help me sending information to the program and receive information back.

Greetings,

Erik

external infomation.zip


I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
Erik.

I managed to get a few things working.

I now can get the _R_RequestCurrentSeq, _R_RequestCurrentCue, version number, ready etc.

The only thing i now need to find, how to get _R_RequestSequenceList for example.

In the example code the are using Self.Handle in the sendmessage function.


I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
Erik.

Can someone please help me?

I think i need to work with structs.

This is what i am trying:

Global $WM_USER = 1024 
Global $_R_LJReady = $WM_USER + 1502 
Global $_R_ExternalConfiguration = $WM_USER + 1600 
Global $_LJVersionRequest = 1 
Global $_R_RequestCurrentSeq = 256 
Global $_R_RequestCurrentCue = 257 
Global $_R_RequestCurrentCuelist = 258 
Global $_R_RequestUserPath = 260 
Global $_R_FixtureSelection = 3   
$test2 = "int;int;char[30]" 

$h = DllStructCreate($test2)  
$test =  _SendMessage($hwnd,$_R_ExternalConfiguration,267, DllStructGetPtr($h))  
$Get = DllStructGetData($h, 1)  
ConsoleWrite($test &"  " & $Get & "   "& $h &"   " &@error &@CRLF)

I am not getting any information back.


I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
martin

Can someone please help me?

I think i need to work with structs.

This is what i am trying:

Global $WM_USER = 1024 
Global $_R_LJReady = $WM_USER + 1502 
Global $_R_ExternalConfiguration = $WM_USER + 1600 
Global $_LJVersionRequest = 1 
Global $_R_RequestCurrentSeq = 256 
Global $_R_RequestCurrentCue = 257 
Global $_R_RequestCurrentCuelist = 258 
Global $_R_RequestUserPath = 260 
Global $_R_FixtureSelection = 3   
$test2 = "int;int;char[30]" 

$h = DllStructCreate($test2)  
$test =  _SendMessage($hwnd,$_R_ExternalConfiguration,267, DllStructGetPtr($h))  
$Get = DllStructGetData($h, 1)  
ConsoleWrite($test &"  " & $Get & "   "& $h &"   " &@error &@CRLF)

I am not getting any information back.

I'm not sure what you want to do exactly but this is what I inderstand from the code you've shown:

You create a struct in the AutoIt script, you pass a pointer to the struct to the DElphi program and you are hoping that the Delphi program will write some data to this struct and you will be able to read it.

If I understand correctly then this could work but we would need to see the Delphi code which handles this request. The Delphi program would have to get read/write permissions for the memory space used by your script for example. It might be easier to send a message to Delphi which replies with the address of a record (=struct in C or AutoIt) and then use Memory.au3 functions, or NomadMemory.au3 functions to read that record.

Alternatively you could use WM_COPYTDATA in your Delphi program to send the data and that might be a lot easier.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Erik.

Sorry but i dont have any code that works with structs.

I have a little code that asks if the program is ready, it will return 1 of 0.

What i am now trying is to get w whole list of items.

I have posted a working delphi code to let you see how it works, problem is i can't get it working in autoit.

I didn't wrote the delphi code.

An little line of code that gets the ready status from the program:

Global $WM_USER = 1024
Global $_R_LJReady = $WM_USER + 1502
Global $_LJVersionRequest = 1
$hwnd = WinGetHandle("[CLASS:TLJMainForm]")
$LJ_version = _SendMessage($hwnd,$_R_LJReady,$_LJVersionRequest) ;Returns the LJ version

The external program is an lightjockey program, i have premission to write a program and i have got a list of functions i can send to the program.

I don't have the source code of the program, i only have a little example that shows how to send data and receive it back.

The list is in the file i have attached.

Edited by Erik.

I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
martin

Sorry but i dont have any code that works with structs.

I have a little code that asks if the program is ready, it will return 1 of 0.

What i am now trying is to get w whole list of items.

I have posted a working delphi code to let you see how it works, problem is i can't get it working in autoit.

I didn't wrote the delphi code.

An little line of code that gets the ready status from the program:

Global $WM_USER = 1024
Global $_R_LJReady = $WM_USER + 1502
Global $_LJVersionRequest = 1
$hwnd = WinGetHandle("[CLASS:TLJMainForm]")
$LJ_version = _SendMessage($hwnd,$_R_LJReady,$_LJVersionRequest) ;Returns the LJ version

The external program is an lightjockey program, i have premission to write a program and i have got a list of functions i can send to the program.

I don't have the source code of the program, i only have a little example that shows how to send data and receive it back.

The list is in the file i have attached.

I had a quick look at the Delphi code which I hadn't realized was in the zip file in your first post. The way you get the data is by processing WM_COPYDATA. First you send a request for which data list you want and send the handle of the window where the message reply with the data is to be sent. Then the delphi program sends that window a WM_COPYDATA message with the list requested. You then need to transfer this data to the struct yourself.

If I am telling you what you already know then my apologies.

So the code you showed in post 3 should be more like this

; *** Start added by AutoIt3Wrapper ***
#include <WindowsConstants.au3>
#include <sendmessage.au3>
; *** End added by AutoIt3Wrapper ***
#AutoIt3Wrapper_Add_Constants=n
;Global $WM_USER = 1024

Global Const $StructDef_COPYDATA = "dword datatype;dword count;ptr pointer"
Global $_R_LJReady = $WM_USER + 1502
Global $_R_ExternalConfiguration = $WM_USER + 1600
Global $_LJVersionRequest = 1
Global $_R_RequestCurrentSeq = 256
Global $_R_RequestCurrentCue = 257
Global $_R_RequestCurrentCuelist = 258
Global $_R_RequestUserPath = 260
Const $_R_RequestStaticsList = 267;

Const $_WMCOPY_SequenceList = 259; // LJ Sequence List
Global $_R_FixtureSelection = 3

;you must have a window or you can't have a message sent to your script. (Actually there is always a hidden AutoIt window anyway.)
Global $hGui = GUICreate("ExampleA")

GUIRegisterMsg($WM_COPYDATA, "getList")

$test2 = "int;int;char[30]"
Global $h = 0; = DllStructCreate($test2)
Global $showRes = False


If Not WinExists('TLJMainForm') Then Exit;the DElphi program must be running

$hwnd = WinGetHandle('TLJMainForm')
$test = _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestStaticsList, $hGui);DllStructGetPtr($h))
While 1
    Sleep(90)
    If $showRes Then
        ConsoleWrite("struct contains" & @CRLF)
        ConsoleWrite(DllStructGetData($h, 1) & @CRLF)
        ConsoleWrite(DllStructGetData($h, 2) & @CRLF)
        ConsoleWrite(DllStructGetData($h, 3) & @CRLF)
        $showRes = False
    EndIf
WEnd



Func getlist($hw, $msg, $wParam, $LParam)
    Local $vs_cds, $ListType, $tstruct1, $tstruct2, $dataSize, $hLen

    ; $LParam = Pointer to a COPYDATA Struct
    $vs_cds = DllStructCreate($StructDef_COPYDATA, $LParam)
    $ListType = DllStructGetData($vs_cds, "datatype")

    If $ListType = $_WMCOPY_SequenceList Then
        $h = 0;destroy any previous struct

        ; Member No. 3 of COPYDATA Struct (PVOID lpData;) = Pointer to Custom Struct
        $dataSize = DllStructGetData($vs_cds, "count")


        $tstruct1 = DllStructCreate("char[" & $dataSize & "]", DllStructGetData($vs_cds, "pointer"))
        $tstruct2 = DllStructCreate("char[" & $dataSize & "]")
        DllStructSetData($tstruct2, 1, DllStructGetData($tstruct1, 1))
        $h = DllStructCreate($test2, DllStructGetPtr($tstruct2))
        $hLen = DllStructGetSize($h)
        ;if $datasize > $hLen then something wrong?
        $showRes = True
        Return True
    EndIf



EndFunc   ;==>getlist

But it is just an outline and of course it hasn't been tested.

Edited by martin

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Erik.

Sorry for the late response.

Thanks for the support!

It is exactly what i mean. You need to send an command to the program and it will send a list of information back.

Unfortunately is it not working right now.


I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
martin

Sorry for the late response.

Thanks for the support!

It is exactly what i mean. You need to send an command to the program and it will send a list of information back.

Unfortunately is it not working right now.

Of course but what have you tried?

Do you get a handle for the 'TLJMainForm' window?

Have you tried sending the _R_LJReady message and tried to get the version?

What is the return from the initial _SendMessage request for data and were you sent a WM_COPYDATA message?


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Erik.

Yes i can get information from a few things.

I can get the version, if the program is ready. The correct running seq the correct running cue.

All that information will be returned into the sendmessage var like : $info _sendmessage.....

The information i now want to have is returned into a list etc. I can not get that working.


I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
Erik.

I will post some examples that are working:

lobal $WM_USER = 1024
Global $_R_LJReady = $WM_USER + 1502
Global $_R_ExternalConfiguration = $WM_USER + 1600
Global $_LJVersionRequest = 1
Global $_R_RequestCurrentSeq = 256
Global $_R_RequestCurrentCue = 257
Global $_R_RequestCurrentCuelist = 258
Global $_R_RequestUserPath = 260
Global $_R_FixtureSelection = 3


Global $UM_STATICS = $WM_USER + 146;

Opt("WinTitleMatchMode", 4)
$hwnd = WinGetHandle("[CLASS:TLJMainForm]")
$ready = _SendMessage($hwnd,$_R_LJReady) ;Returns 1 of 0 1 is set if LJ is ready
$LJ_version = _SendMessage($hwnd,$_R_LJReady,$_LJVersionRequest) ;Returns the LJ version

$seq_running = _SendMessage($hwnd,$_R_ExternalConfiguration,$_R_RequestCurrentSeq) ;Returns the number of the current running seq
$cue_running = _SendMessage($hwnd,$_R_ExternalConfiguration,$_R_RequestCurrentCue) ;Returns the number of the current running cue

I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
martin

I will post some examples that are working:

lobal $WM_USER = 1024
Global $_R_LJReady = $WM_USER + 1502
Global $_R_ExternalConfiguration = $WM_USER + 1600
Global $_LJVersionRequest = 1
Global $_R_RequestCurrentSeq = 256
Global $_R_RequestCurrentCue = 257
Global $_R_RequestCurrentCuelist = 258
Global $_R_RequestUserPath = 260
Global $_R_FixtureSelection = 3


Global $UM_STATICS = $WM_USER + 146;

Opt("WinTitleMatchMode", 4)
$hwnd = WinGetHandle("[CLASS:TLJMainForm]")
$ready = _SendMessage($hwnd,$_R_LJReady) ;Returns 1 of 0 1 is set if LJ is ready
$LJ_version = _SendMessage($hwnd,$_R_LJReady,$_LJVersionRequest) ;Returns the LJ version

$seq_running = _SendMessage($hwnd,$_R_ExternalConfiguration,$_R_RequestCurrentSeq) ;Returns the number of the current running seq
$cue_running = _SendMessage($hwnd,$_R_ExternalConfiguration,$_R_RequestCurrentCue) ;Returns the number of the current running cue

Ok, that's good.

You have no gui in your examples which is needed so you can send the window handle to the Delphi program and then it can send a WM_COPYDATA message back. What happens if you try the example I posted? Is the WM_COPYDATA message received?


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Erik.

Okay, i will try to create a gui.

I have tried your example but it does nothing. The message has been transmitted to the program but i don't get anything back.


I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
martin

Okay, i will try to create a gui.

I have tried your example but it does nothing. The message has been transmitted to the program but i don't get anything back.

OK, I'll have a look at what I posted later. It was not written with great care so probably some simple errors.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Erik.

Is there an possibility to get more information to see where the program lies.

For example the gui handle of the eternal program so you are sure the program is trying to get contact with my program etc.

Edit:

I am trying to debug your code a little.

The function getList has not been called to run.

Edited by Erik.

I little problem, hard to find and fix

Share this post


Link to post
Share on other sites
martin

Is there an possibility to get more information to see where the program lies.

For example the gui handle of the eternal program so you are sure the program is trying to get contact with my program etc.

Edit:

I am trying to debug your code a little.

The function getList has not been called to run.

That is not good.

This is a mixture of your code and mine

#include <WindowsConstants.au3>
#include <sendmessage.au3>
$mgtest = True
;Global $WM_USER = 1024
Global $_R_LJReady = $WM_USER + 1502
Global $_R_ExternalConfiguration = $WM_USER + 1600
Global $_LJVersionRequest = 1
Global $_R_RequestCurrentSeq = 256
Global $_R_RequestCurrentCue = 257
Global $_R_RequestCurrentCuelist = 258
Global $_R_RequestUserPath = 260
Global $_R_FixtureSelection = 3
Global $_R_RequestSequenceList = 263;

Global $_R_RequestSeqInfoNotifications      = 300; // return Handle in LParam
Global $_R_RequestCueInfoNotifications      = 301; // return Handle in LParam
Global $_R_RequestCuelistInfoNotifications  = 302; // return Handle in LParam
Global $_R_RequestBGCueInfoNotifications    = 303; // return Handle in LParam
Global $_R_RequestStaticsInfoNotifications  = 304; // return Handle in LParam

Global $_R_RequestSequenceList              = 263; // Return Handle in LParam
Global $_R_RequestCuesList                  = 264; // Return Handle in LParam
Global $_R_RequestCueListsList              = 265; // Return Handle in LParam
Global $_R_RequestBGCueList                 = 266; // Return Handle in LParam
Global $_R_RequestStaticsList               = 267; // Return Handle in LParam
Global $_WMCOPY_SequenceList = 259;


Global $UM_STATICS = $WM_USER + 146;

Global Const $StructDef_COPYDATA = "dword datatype;dword count;ptr pointer"

Opt("WinTitleMatchMode", 4)

Global $hGui = GUICreate("Test Messages A")
$Btn1 = GUICtrlCreateButton("get sequence list", 20, 20)
$ed = GUICtrlCreateEdit("", 10, 50, 380, 320)
GUISetState()

GUIRegisterMsg($WM_COPYDATA, "getList")

Const $test2 = "int;int;char[30]"

$hwnd = WinGetHandle("[CLASS:TLJMainForm]")
$ready = 0
$readyCount = 0
If Not $mgtest Then
    While Not $ready
        $ready = _SendMessage($hwnd, $_R_LJReady) ;Returns 1 of 0 1 is set if LJ is ready
        $readyCount += 1
        Sleep(100)
        GUICtrlSetData($ed, "TLJ is Ready" & @CRLF, 1)
        If $readyCount > 20 Then
            MsgBox(262144, "Error", "No response from TLJMainForm")
            Exit
        EndIf
    WEnd
EndIf

$LJ_version = _SendMessage($hwnd, $_R_LJReady, $_LJVersionRequest) ;Returns the LJ version
GUICtrlSetData($ed, "Version = 0x" & Hex($LJ_version) & @CRLF, 1)


$seq_running = _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestCurrentSeq) ;Returns the number of the current running seq
GUICtrlSetData($ed, "Current running sequence =" & Hex($seq_running) & @CRLF, 1)
$cue_running = _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestCurrentCue) ;Returns the number of the current running cue
GUICtrlSetData($ed, "Current running cue =" & Hex($cue_running) & @CRLF, 1)

While 1
    $ms = GUIGetMsg()
    Switch $ms
        Case -3
            Exit
        Case $Btn1
            _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestSequenceList, $hGui);     // Clear Info Request
            _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestCuesList, $hGui);     // Clear Info Request
            _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestCueListsList, $hGui); // Clear Info Request
            _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestBGCueList, $hGui);   // Clear Info Request
            _SendMessage($hwnd, $_R_ExternalConfiguration, $_R_RequestStaticsList, $hGui);  // Clear Info Request
            GUICtrlSetData($ed, "Sent request for sequence list" & @CRLF, 1)
    EndSwitch
WEnd
Exit


Func getlist($hw, $msg, $wParam, $LParam)
    Local $vs_cds, $ListType, $tstruct1, $dataSize, $hLen, $StaticListStruct

    ; $LParam = Pointer to a COPYDATA Struct
    $vs_cds = DllStructCreate($StructDef_COPYDATA, $LParam)
    $ListType = DllStructGetData($vs_cds, "datatype")
    GUICtrlSetData($ed, "Received WM_COPYDATA message" & @CRLF, 1)
    If $ListType = $_WMCOPY_SequenceList Then
        GUICtrlSetData($ed, "Receiving SequenceList" & @CRLF, 1)

        ; Member No. 3 of COPYDATA Struct (PVOID lpData;) = Pointer to Custom Struct
        $dataSize = DllStructGetData($vs_cds, "count")


        $tstruct1 = DllStructCreate("byte[" & $dataSize & "]", DllStructGetData($vs_cds, "pointer"))
        $StaticListStruct = DllStructCreate($test2, DllStructGetPtr($tstruct1))
        $hLen = DllStructGetSize($StaticListStruct)
        ;if $datasize > $hLen then something wrong?

        GUICtrlSetData($ed, "Data 1 = " & DllStructGetData($StaticListStruct, 1) & @CRLF, 1)
        GUICtrlSetData($ed, "Data 2 = " & DllStructGetData($StaticListStruct, 2) & @CRLF, 1)
        GUICtrlSetData($ed, "Data 3 = " & DllStructGetData($StaticListStruct, 3) & @CRLF, 1)
        Return True
    EndIf



EndFunc   ;==>getlist

The Delphi example sends a set of messages in a row so maybe it's necessary to do the same. Just in case the script above sends the same set of messages.


Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.

Share this post


Link to post
Share on other sites
Erik.

I am getting more information back.

There a copy of the console:

Version = 0x02640100

Current running sequence =00000000

Current running cue =00000000

Received WM_COPYDATA message

Receiving SequenceList

Data 1 = 0

Data 2 = 0

Data 3 = 0

Received WM_COPYDATA message

Received WM_COPYDATA message

Received WM_COPYDATA message

Received WM_COPYDATA message

Sent request for sequence list

I think the data is empty but we are getting some information back.

The listtype works now only the data is empty.

Datasize is 0.

Edited by Erik.

I little problem, hard to find and fix

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×