odklizec Posted November 1, 2007 Share Posted November 1, 2007 Hi guys, I need to convert relative simple C SendMesage code to AutoIt. But from some strange reasons, I cannot make it to work Maybe I don't see something obvious or it's just that I'm not very experienced with C to AutoIt conversion So can someone experienced please look at this? I want this convert to AutoIt: SendMessage(hWnd, WM_RUNSCRIPTCODE, RUNSCRIPTCODE_LOUD, LPARAM(LPCTSTR(str))); I tried the below autoit translation, which I believe should be OK. It creates the structure, gets the structure pointer, but unfortunately, it does not pass the correct result to the last SendMessage parameter. And I know the target application is OK. If the "SendMessage" is done from C code, it works OK. Global Const $WM_RUNSCRIPTCODE = 0x08C7 $hwnd = WinGetHandle("Welcome!") $stringToSend="test$='OK'" $slen = stringlen($stringToSend) + 1 MsgBox(0,"string len",$slen) $str = "char[" & $slen & "]" $struct= DllStructCreate($str); make a structure if @error Then MsgBox(0,"","Error in DllStructCreate " & @error); exit endif DllStructSetData($struct,1,$stringToSend) $pointer = DllStructGetPtr($struct,1); get the pointer to the string if @error Then MsgBox(0,"","Error in DllStructGetPtr " & @error); exit endif MsgBox(0,"DllStruct","Struct Size: " & DllStructGetSize($struct) & @CRLF & _ "Struct pointer: " & DllStructGetPtr($struct) & @CRLF & _ "Data: " & DllStructGetData($struct,1) & @CRLF) $result = DllCall("user32.dll","int","SendMessage","hWnd",$hwnd ,"int",$WM_RUNSCRIPTCODE,"int","1","ptr",$pointer) Does anyone have any idea what's wrong here? Thank you in advance! Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted November 1, 2007 Moderators Share Posted November 1, 2007 (edited) Well the obvious question... What is WM_RUNSCRIPTCODE? (That and where's the C source of this function) (You also know there's a _SendMessage() function in AutoIt right? (Same API call... but just thought I'd tell you)) Edited November 1, 2007 by SmOke_N Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
odklizec Posted November 1, 2007 Author Share Posted November 1, 2007 (edited) Thanks for reply and suggestion regarding the _SendMessage() Yes, I already tried also this UDF function, unfortunately, with the same result. I'm almost sure that the problem is in the last "pointer" part. I just don't know what's wrong here? The WM_RUNSCRIPTCODE is just a message expected in the target application. Basically, it should allow to run the applications' own script from 3rd party apps. The last parameter should be the pointer to a string of the script's source code.Here is the full description from SDK:A C++ example might be (using values from the MMBPlugInSDK.h header file): ::SendMessage(hWnd, WM_RUNSCRIPTCODE, RUNSCRIPTCODE_LOUD, LPARAM(LPCTSTR(str)));Where:- hWnd is a handle to the application's window obtained via the SetParentWindow callback of the plugin (check the plugin overviews published in this folder, too)- WM_RUNSCRIPTCODE is a symbolic constant, a number of the passed message- RUNSCRIPTCODE_LOUD (also RUNSCRIPTCODE_QUIET) are symbolic constants for showing (not showing) error messages during processing the script code, if there are any- str is a pointer to a string of the script's source codeThe values of those symbolic constants are:- WM_RUNSCRIPTCODE stands for 08C7 hexadecimally- RUNSCRIPTCODE_QUIET stands for 0- RUNSCRIPTCODE_LOUD stands for 1 Edited November 1, 2007 by odklizec Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted November 1, 2007 Moderators Share Posted November 1, 2007 Thanks for reply and suggestion regarding the _SendMessage() Yes, I already tried also this UDF function, unfortunately, with the same result. I'm almost sure that the problem is in the last "pointer" part. I just don't know what's wrong here? The WM_RUNSCRIPTCODE is just a message expected in the target application. Basically, it should allow to run the applications' own script from 3rd party apps. The last parameter should be the pointer to a string of the script's source code.Here is the full description from SDK:What happens when you send it as bytes rather than char? Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
odklizec Posted November 1, 2007 Author Share Posted November 1, 2007 What happens when you send it as bytes rather than char? Unfortunately, still the same. DllStructGetData returns the value from structure in bytes but the host application seems not getting it. Here is my actual code: #include <Misc.au3> Global Const $WM_RUNSCRIPTCODE = 0x08C7 Global Const $RUNSCRIPTCODE_LOUD = 1 Global Const $RUNSCRIPTCODE_QUIET = 0 $hwnd = WinGetHandle("Welcome!") $stringToSend="test$='OK'" $slen = stringlen($stringToSend) + 1 ;MsgBox(0,"string len",$slen) $str = "char[" & $slen & "]" $struct= DllStructCreate($str);make a struct for the string so we can get a pointer to it if @error Then MsgBox(0,"","Error in DllStructCreate " & @error); exit endif DllStructSetData($struct,1,$stringToSend) $pointer = DllStructGetPtr($struct,1);the pointer to the string if @error Then MsgBox(0,"","Error in DllStructGetPtr " & @error); exit endif MsgBox(0,"DllStruct","Struct Size: " & DllStructGetSize($struct) & @CRLF & _ "Struct pointer: " & DllStructGetPtr($struct,1) & @CRLF & _ "Data: " & DllStructGetData($struct,1) & @CRLF) $result = DllCall("user32.dll","int","SendMessage","hWnd",$hwnd ,"int",$WM_RUNSCRIPTCODE,"int",$RUNSCRIPTCODE_LOUD,"ptr",$pointer) ;$result = _SendMessage($hwnd, $WM_RUNSCRIPTCODE, $RUNSCRIPTCODE_LOUD, $pointer) If @error Then MsgBox(0,"_ToggleMonitor", "_SendMessage Error: " & @error) Exit EndIf Thanks for help! Link to comment Share on other sites More sharing options...
Zedna Posted November 1, 2007 Share Posted November 1, 2007 Instead of $pointer = DllStructGetPtr($struct,1); get the pointer to the string try $pointer = DllStructGetPtr($struct); get the pointer to the string Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
odklizec Posted November 1, 2007 Author Share Posted November 1, 2007 (edited) Thanks for tip Zedna! I forgot to mention that I already tried both ways. Still the same. If I wouldn't know for sure that this mechanism works fine from C++ code, I would say there is something wrong in the host application. But it works in C++ based apps? Here is a part of code, which I know work OK... case WM_RUNSCRIPTCODE: if(m_Process && !m_Ignore) { HWND hWnd = theApp.GetPlayerHWnd(); if(hWnd) { CString str; GetWindowText(str); ::SendMessage(hWnd, WM_RUNSCRIPTCODE, RUNSCRIPTCODE_LOUD, LPARAM(LPCTSTR(str))); theApp.StoreCommand(str); SetCurSel(-1); } } Instead of $pointer = DllStructGetPtr($struct,1); get the pointer to the string try $pointer = DllStructGetPtr($struct); get the pointer to the string Edited November 1, 2007 by odklizec Link to comment Share on other sites More sharing options...
Zedna Posted November 1, 2007 Share Posted November 1, 2007 Try this DllCall("user32.dll","int","SendMessage","hWnd",$hwnd ,"int",$WM_RUNSCRIPTCODE,"int","1","str",$stringToSend) Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
odklizec Posted November 1, 2007 Author Share Posted November 1, 2007 Try this DllCall("user32.dll","int","SendMessage","hWnd",$hwnd ,"int",$WM_RUNSCRIPTCODE,"int","1","str",$stringToSend)Yes, this was my initial code, before I realized there must be a pointer to string in last parameter. However, I made a small progress but it's very odd If I use this code in AutoIt 3.2.0.0 it definitely sends something to the target application... $result = DllCall("user32.dll","int","SendMessage","hWnd",$hwnd ,"int",$WM_RUNSCRIPTCODE,"int","1","str",$pointer) It's wrong code because of str instead of ptr, but it sends something to the target application, which immeditaly invoke the "Unknown Function" error message. It means that the application receives the string from AutoIt. But when the target application trying to run the received string (via RUNSCRIPTCODE), it fails (from obvious reason). Of course, I also tried to replace the $pointer with $stringToSend, but it does not pass the string to application. And replacing str with ptr and leaving the $pointer where it is now does not help either. Now the strange part is, that the same (Unknown Function error) does not happen if the above "wrong" script is compiled with actual 3.2.8.1 or 3.2.9.4 beta! Any idea why is it like that? Why the wrong code partially works with 3.2.0.0 and does not help with the latest versions? Link to comment Share on other sites More sharing options...
Zedna Posted November 1, 2007 Share Posted November 1, 2007 (edited) Look at Auto3Library's TreeView_GetText() There must be used alocating memory for string buffer in target application's memory area. Maybe you must do your call this way too. Func _TreeView_GetText($hWnd, $hNode) Local $iItem, $tItem, $pItem, $pBuffer, $tBuffer, $pMemory, $tMemMap, $pText $tBuffer = DllStructCreate("char Text[4096]") $pBuffer = DllStructGetPtr($tBuffer) $tItem = DllStructCreate($tagTVITEMEX) $pItem = DllStructGetPtr($tItem) DllStructSetData($tItem, "Mask", $TVIF_TEXT) DllStructSetData($tItem, "hItem", $hNode) DllStructSetData($tItem, "TextMax", 4096) if _Lib_InProcess($hWnd, $ghTVLastWnd) then DllStructSetData($tItem, "Text", $pBuffer) _API_SendMessage($hWnd, $TVM_GETITEM, 0, $pItem) else $iItem = DllStructGetSize($tItem) $pMemory = _Mem_CtrlInit($hWnd, $iItem + 4096, $tMemMap) $pText = $pMemory + $iItem DllStructSetData($tItem, "Text", $pText) _Mem_CtrlWrite($tMemMap, $pItem, $pMemory, $iItem) _API_SendMessage($hWnd, $TVM_GETITEM, 0, $pMemory) _Mem_CtrlRead($tMemMap, $pText, $pBuffer, 4096) _Mem_CtrlFree($tMemMap) endif Return DllStructGetData($tBuffer, "Text") EndFunc Edited November 1, 2007 by Zedna Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
odklizec Posted November 1, 2007 Author Share Posted November 1, 2007 Thanks Zedna. That sound reasonable. I will try that, although I don't know anything about allocating memory in target application. But yesterday I knew nothing about structures. New day..new challenge If I understand the TreeView_GetText() code right, all I need is to use/change this code to write in target application memory? $iItem = DllStructGetSize($tItem) $pMemory = _Mem_CtrlInit($hWnd, $iItem + 4096, $tMemMap) $pText = $pMemory + $iItem DllStructSetData($tItem, "Text", $pText) _Mem_CtrlWrite($tMemMap, $pItem, $pMemory, $iItem) _API_SendMessage($hWnd, $TVM_GETITEM, 0, $pMemory) _Mem_CtrlRead($tMemMap, $pText, $pBuffer, 4096) _Mem_CtrlFree($tMemMap) Link to comment Share on other sites More sharing options...
odklizec Posted November 2, 2007 Author Share Posted November 2, 2007 I'm happy to report that I got it working!!! Big thanks Zedna for your suggestions! The last one helped a lot and it now works as expected! Once again thank you and SmOke_N for your tips! Link to comment Share on other sites More sharing options...
Zedna Posted November 2, 2007 Share Posted November 2, 2007 I'm happy to report that I got it working!!! Big thanks Zedna for your suggestions! The last one helped a lot and it now works as expected! Once again thank you and SmOke_N for your tips!OK.So post your working code (or code snipet) so other AutoIters can learn something.BTW: Your nick name sounds like Czech. Are you from Czech? I am. Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
odklizec Posted November 2, 2007 Author Share Posted November 2, 2007 Oh, yes here is the code, which sends the string from AutoIt to target app.. #include <A3LMemory.au3> Global Const $WM_RUNSCRIPTCODE = 0x08C7 Global Const $RUNSCRIPTCODE_LOUD = 1 Global Const $RUNSCRIPTCODE_QUIET = 0 Local $iItem, $pMemory, $tMemMap, $pText $hwnd = WinGetHandle("Welcome!") $stringToSend='Message("","OK")' $slen = stringlen($stringToSend) +1 $str = "char[" & $slen & "]" $struct= DllStructCreate($str); make a struct for the string so we can get a pointer to it if @error Then MsgBox(0,"","Error in DllStructCreate " & @error) exit endif ; this is the critical part responsible for writing the internal pointer of string in structure to target application memory $iItem = DllStructGetSize($struct); get structure size $pMemory = _Mem_CtrlInit($hwnd, $iItem, $tMemMap); init memory and return pointer to initialized memory in target app DllStructSetData($struct, 1, $stringToSend); set string to structure $pointer = DllStructGetPtr($struct,1); pointer to string in structure _Mem_CtrlWrite($tMemMap, $pointer, $pMemory, $iItem); write string pointer to application memory ; SendMesage to target application (pointer in target application memory) $result = DllCall("user32.dll","int","SendMessage","hWnd",$hwnd ,"int",$WM_RUNSCRIPTCODE,"int",$RUNSCRIPTCODE_LOUD,"ptr",$pMemory) If @error Then MsgBox(0,"_ToggleMonitor", "_SendMessage Error: " & @error) Exit EndIf _Mem_CtrlFree($tMemMap);release the memory In the end, it was easier than I thought. But after reading your last comment I was about giving it up Yes, I'm Czech too, but currently living in Slovakia. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now