New WM_COPYData Examples

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: white, Hacker, petermad, Stefan2

hi5
Power Member
Power Member
Posts: 550
Joined: 2012-11-03, 11:35 UTC
Contact:

Post by *hi5 »

Does this still work with TC8.5? When I use it to change directory it goes to the parent directory on the directory itself - say I want to go to "c:\totalcmd\plugins\wlx\" I end up in "c:\totalcmd\plugins\" - happens on both 32 & 64 bit systems/versions of TC. AHK 1.1.15.00 (unicode)

edit:
it seems to be in this line? In the code in the 1st post there is a space before the `r in " `r" - removing it seems to do the trick:

Code: Select all

TC_SendWMCopyData( "CD", cmd:=(src "`r"), params, wID )
User avatar
Balderstrom
Power Member
Power Member
Posts: 2148
Joined: 2005-10-11, 10:10 UTC

Post by *Balderstrom »

The code in the first post isn't correct, it's noted later in the thread, that it requires other functions, and shouldn't have "A" as the default for 'window ID' (wID).
Please see the link in the first post, also please note this post which clarifies that you need an ID, and how you might do so.
dragonetti
Junior Member
Junior Member
Posts: 33
Joined: 2007-07-09, 21:03 UTC

Post by *dragonetti »

A while ago I asked in a seperate topic how to use WM_COPYDATA.
I am working in an scripting environment in which the scripting language has some parallels with .vb script , c++, ... the environment is called quickmacros.
I am telling this because I have no real experience in C++.

Still I hope I might get some clues on how to modify the below code so that I might:
- open tabs
- use internal commands like: cm_FocusLeft

The code I currently have, which works for navigating the left and right panel:

Code: Select all

str data="c:\test\test.txt[13]C:\Windows" 
COPYDATASTRUCT cds;
cds.dwData='D'<<8|'C';
cds.lpData=data;
cds.cbData=data.len+2;
SendMessage(w WM_COPYDATA 0 &cds)

With syntax highlighting

Image: http://dl.dropbox.com/u/85973479/totalcmd_forum/0308.png

I have a 'usercmd.ini' with the following content:

Code: Select all

[em_test]
cmd=OPENTABS f:\PortableApps\totalcmd\_TABS\test.tab
I hope someone can provide some hints on how to modify my code to: Open a certain tab (tabset) and how to use internal comands like: 'cm_FocusLeft'.
I know it's a lot to ask and I do not expect a solution but maybe a nudge in the right direction can mean a lot!
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

Thank you for very useful script. Work great.
But I can't understand - how to put Send_WM_COPYDATA result to variable and use it without Persistent and OnMessage?
Something like
MyVariable := Send_WM_COPYDATA(cmd:="SP")
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
User avatar
nsp
Power Member
Power Member
Posts: 1802
Joined: 2005-12-04, 08:39 UTC
Location: Lyon (FRANCE)
Contact:

Post by *nsp »

LonerD wrote:Thank you for very useful script. Work great.
But I can't understand - how to put Send_WM_COPYDATA result to variable and use it without Persistent and OnMessage?
Something like
MyVariable := Send_WM_COPYDATA(cmd:="SP")
When you send data to TC you only receive errorlevel !
If you want to have a client/server communication with TC, must have a wait loop arround onMessage in order to receive data from TC !
This is the meaning of frank AHK script and others...
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

2nsp
Can you help with simple example?
We run script. Script automatically detect what panel is active - Send_WM_COPYDATA(cmd:="A"). If active left panel - switch to right (command 4002 cm_FocusRight ). If active right panel - switch to right (command 4001 cm_FocusLeft). Then script close itself (ExitApp).
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
User avatar
nsp
Power Member
Power Member
Posts: 1802
Joined: 2005-12-04, 08:39 UTC
Location: Lyon (FRANCE)
Contact:

Post by *nsp »

LonerD wrote:2nsp
Can you help with simple example?
We run script. Script automatically detect what panel is active - Send_WM_COPYDATA(cmd:="A"). If active left panel - switch to right (command 4002 cm_FocusRight ). If active right panel - switch to right (command 4001 cm_FocusLeft). Then script close itself (ExitApp).
You should take frank GUI sample and adapt the script to first send a "A" command and then on the receive_data send another command to switch to other side and then exit the application !

You must have a window handle as TC will send back to you a message to your window the onMessage loop will "intercept" it.

In your case it is easier to send a TAB key !
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

2nsp
In your case it is easier to send a TAB key !
I know. But in my case it only the simpliest example for understanding work of Send_WM_COPYDATA function.
first send a "A" command and then on the receive_data send another command to switch to other side and then exit the application !
You must have a window handle as TC will send back to you a message to your window the onMessage loop will "intercept" it.
My script. Are any ideas how to simplify it?

Code: Select all

; #Warn
#NoEnv
#NoTrayIcon
#SingleInstance, Force
;SetBatchLInes, -1
;SendMode, Input

If WinExist("ahk_class TTOTAL_CMD") && WinActive("ahk_class TTOTAL_CMD")
{
  WinGet, TCHWND, ID, A

  OnMessage(0x4a, "Receive_WM_COPYDATA")
  Send_WM_COPYDATA(cmd:="A")

  if ( retVal = "R" )
    SendMessage, 1075, 4001,,, % "ahk_id " TCHWND
    else
      SendMessage, 1075, 4002,,, % "ahk_id " TCHWND
}
ExitApp

Send_WM_COPYDATA(ByRef cmd, aWinID=0x0)
{
  global TCHWND
  Critical
  if(!RegExMatch(cmd, "^(A|[LRST][PCIN]?)$"))
    return
  DetectHiddenWindows, On

  len:=StrLen(cmd) + 1
  if( A_IsUnicode )   ; This needs to be done, as TC is expecting
  {      ; "chars" for the cmd string.
     cmdStr:=cmd
     VarSetCapacity(cmd, StrPut(cmd, "cp0"))
     Loop, % len
        NumPut( Asc(SubStr(cmdStr, A_Index, 1)), cmd, A_Index - 1, "Char")
  }
  VarSetCapacity(CopyDataStruct, A_PtrSize * 3)
  NumPut(Asc("G") + 256 * Asc(A_IsUnicode ? "W" : "A"), CopyDataStruct)
  NumPut(len , CopyDataStruct, A_PtrSize)
  NumPut(&cmd, CopyDataStruct, A_PtrSize * 2)

  scriptID := WinExist(A_ScriptFullPath " ahk_class AutoHotkey")
  SendMessage, 0x4A, scriptID, &CopyDataStruct, , % "ahk_id " TCHWND
  return ErrorLevel
}

Receive_WM_COPYDATA(wParam, lParam, msg, hwnd)
{
  global retVal
  retVal:=StrGet(NumGet(lParam + A_PtrSize * 2))
  return 1
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

2Balderstrom and all
What mean this code fragment?
In which situation it used?

Code: Select all

   if( A_IsUnicode )   ; This needs to be done, as TC is expecting 
    {      ; "chars" for the cmd string. 
       cmdStr:=cmd 
       VarSetCapacity(cmd, StrPut(cmd, "cp0")) 
       Loop, % len 
          NumPut( Asc(SubStr(cmdStr, A_Index, 1)), cmd, A_Index - 1, "Char") 
    }
I try to delete it, try with different AutoHotkey.exe (ANSI, Unicode) - script seems to work fine without this code.
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
User avatar
artt
Junior Member
Junior Member
Posts: 50
Joined: 2009-05-03, 07:03 UTC

Just another working AHK script

Post by *artt »

Just another working AHK script
TESTED AND WORKING ON: AHK_L v1.1.21.03 UNICODE X32 + Win7 X32 + TC 8.51a

Code: Select all

EM	  = em_foo|em_APPENDTABS C:\tc\tabs\TC Select.tab
ASK	 = A|LP|LC|LI|LN|RP|RC|RI|RN|SP|SC|SI|SN|TP|TC|TI|TN
Dir1	= C:\tc\tabs\
Dir2	= D:\data\backup\
Return

F12::
i:=""
LOOP, PARSE, ASK, |	; Ask TC
	i .= A_LoopField ":`t" TC_SendData(A_LoopField) (A_Index=1 OR A_Index=5 OR A_Index=9 OR A_Index=13 ? "`n`n" : "`n")
MsgBox,4096, Ask TC, % i

LOOP, PARSE, EM, |	; User Command
	{
	MsgBox,4096, User Command, %A_LoopField%
	TC_SendData(A_LoopField,"EM")
	}

MsgBox,4096, CD Command, LeftDir - RightDir
TC_SendData(Dir1 "`r" Dir2, "LR")
	MsgBox,4096, CD Command, SourceDir
	TC_SendData(Dir1 "`r", "ST")
	MsgBox,4096, CD Command, TargetDir
	TC_SendData("`r" Dir2, "ST")
MsgBox,4096, CD Command, LeftDir
TC_SendData(Dir1 "`r", "LR")
MsgBox,4096, CD Command, RightDir
TC_SendData("`r" Dir2, "LR")
	MsgBox,4096, CD Command, SourceDir -  TargetDir
	TC_SendData(Dir1 "`r" Dir2, "ST")
Return


/*
TESTED AND WORKING ON: AHK_L v1.1.21.03 UNICODE X32 + Win7 X32 + TC 8.51a
-------------------------------------------------------------------------
TC_SendData("em_FOO"         	     , "EM") ; User Command
TC_SendData("em_APPENDTABS C:\my.tab", "EM") ; User Command with parameters (usercmd.ini as following)
															;				[em_APPENDTABS]
															;				cmd=APPENDTABS
															;				param=%A

TC_SendData("cmd") 								  ; Ask TC :     (cmd one of the following varues:)
															; A  = Active Side
						
															; LP = Left Path            RP = Right Path
															; LC = Left List Count      RC = Right List Count
															; LI = Left Caret Index     RI = Right Caret Index
															; LN = Left Name Caret      RN = Right Name Caret

															; SP = Source Path          TP = Target Path
															; SC = Source List Count    TC = Target List Count
															; SI = Source Caret Index   TI = Target Caret Index
															; SN = Source Name Caret    TN = Target Name Caret

TC_SendData("C:\tc" "`r" "D:\data", "LR")	 ; CD   Command: (LeftDir - RightDir)
TC_SendData("C:\tc" "`r"          , "LR")	 ; CD   Command: (LeftDir)
TC_SendData(        "`r" "D:\data", "LR")	 ; CD   Command: (          RightDir)

TC_SendData("C:\tc" "`r" "D:\data", "ST")	 ; CD   Command: (SourceDir - TargetDir)
TC_SendData("C:\tc" "`r"          , "ST")	 ; CD   Command: (SourceDir)
TC_SendData(        "`r" "D:\data", "ST")	 ; CD   Command: (            TargetDir)
*/
TC_SendData(Cmd, CmdType="", msg="", hwnd="") {
   Critical   ; Define "OnMessage" as STATIC it is registered at Script startup.
   STATIC om:=OnMessage(0x4a, "TC_SendData"), TC_ReceiveDataValue:="", TC_DataReceived:=""	; 0x4a is WM_COPYDATA

   IF ((msg=0x4A) AND (hwnd=A_ScriptHwnd)) ; EnSure is trigered by this Script.
      EXIT (TC_ReceiveDataValue:=StrGet(NumGet(CmdType + A_PtrSize * 2)), TC_DataReceived:="1")

   VarSetCapacity(CopyDataStruct, A_PtrSize * 3), TC_ReceiveDataValue:=1, TC_DataReceived:=""
   IF CmdType IN LR,ST			; CD   Command
	DirType:=CmdType, CmdType:="CD"
   ELSE IF (CmdType="")			; Ask TC
	CmdType:=(A_IsUnicode ? "GW" : "GA"), TC_ReceiveDataValue:=""

   If( A_IsUnicode ) {
      VarSetCapacity( cmdA, StrPut(cmd, "cp0"),0) ; 3rd parameter "0" is necessary for CD "LeftPath only"
      Loop, % StrLen(cmd)
         NumPut( Asc(SubStr(cmd, A_Index, 1)), cmdA, A_Index - 1, "Char")
   }
   NumPut( Asc(SubStr(CmdType,1,1)) + 256 * Asc(SubStr(CmdType,2,1)), CopyDataStruct,0 )
   NumPut( StrLen(cmd) + (CmdType="CD" ? 5 : 0), CopyDataStruct, A_PtrSize )
   NumPut((A_IsUnicode ? &cmdA : &cmd), CopyDataStruct, A_PtrSize * 2)
   Loop, % (CmdType=="CD" ? 2 : 0)
      NumPut(Asc(SubStr(DirType,A_Index,1)), (A_IsUnicode ? cmdA : cmd), (StrLen(cmd)+A_Index),"Char")
   SendMessage, 0x4A,%A_ScriptHwnd%, &CopyDataStruct,, ahk_class TTOTAL_CMD
   
   While (TC_ReceiveDataValue="") {
      IfEqual, TC_DataReceived,    1, Break
      IfGreaterOrEqual, A_Index, 500, Break
      Sleep,10
   }
   Return TC_ReceiveDataValue
}

FIXED at 20150425:
When you send an "ASK TC" command and the value returned by TC is an "empty" string (as if you send "SP" and the source panel contains a search results list), it will not wait for 5 seconds for the empty value to be returned to the user. (Thanks LonerD for your report)
FIXED at 20150426:
Restored the missing comments about the syntax of CD command, that were lost during last post modification! (Thanks LonerD for your report)
Last edited by artt on 2015-04-26, 05:42 UTC, edited 3 times in total.
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

2artt
Thank you! Very useful all-in-one.
Small error in description.

Code: Select all

TC_SendData("cmd")                           ; Ask TC :     (cmd one of the following values:)
instead

Code: Select all

TC_SendData(cmd)                             ; Ask TC :     (cmd one of the following varues:)
We need to use quotes around cmd :-)
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
User avatar
artt
Junior Member
Junior Member
Posts: 50
Joined: 2009-05-03, 07:03 UTC

Post by *artt »

2LonerD
Small error in description.
It is fixed Thank you!
Regards
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

2artt
SP, TP, RP, LP work long time when it opened search results in panel.
In Balderstorm script return result in moment without delay.
What reason to make 500 iterations in IfGreaterOrEqual ?
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
User avatar
artt
Junior Member
Junior Member
Posts: 50
Joined: 2009-05-03, 07:03 UTC

Post by *artt »

LonerD wrote:2artt
SP, TP, RP, LP work long time when it opened search results in panel.
In Balderstorm script return result in moment without delay.
Script sends all commands to the main window of TC "ahk_class TTOTAL_CMD" and has not been tested for secondary TC windows like 'search'.
Search window's class is "ahk_class TFindFile" so it is not receiving the messages.
LonerD wrote:2artt
What reason to make 500 iterations in IfGreaterOrEqual ?
IF you send a 'request' command to TC (all Ask TC commands: A, LP, LC, ...), script is waiting for (500 x 10 = 5000ms = 5 seconds) for TC to response/answer.
If the answer arrives before the 5 seconds, it is immediately breaking the interaction and return the answer to the user (normally their is no delay).
User avatar
LonerD
Senior Member
Senior Member
Posts: 381
Joined: 2010-06-19, 20:18 UTC
Location: Makeyevka, Russia
Contact:

Post by *LonerD »

Script sends all commands to the main window of TC "ahk_class TTOTAL_CMD" and has not been tested for secondary TC windows like 'search'.

Search window's class is "ahk_class TFindFile" so it is not receiving the messages.
Search window with class TFindFile is closed.
It's opened only one TC window with search result on one panel.
Path to search result panel is empty in TC, and you script make 5seconds delay to return this empy result
"I used to feel guilty in Cambridge that I spent all day playing games, while I was supposed to be doing mathematics. Then, when I discovered surreal numbers, I realized that playing games IS math." John Horton Conway
User avatar
artt
Junior Member
Junior Member
Posts: 50
Joined: 2009-05-03, 07:03 UTC

Post by *artt »

LonerD wrote:Search window with class TFindFile is closed.
It's opened only one TC window with search result on one panel.
OK i see what you mean and i will try to explain:
When you open the search results in main window's left or right or both panels, this panel loose/miss it's "current directory".
You can see for yourself, if option "Configuration / Options / Layout / Show current directory" is checked, an Edit control with panel's "current directory" is appearing under panel's Tabs and above the panel's list.
As you browse into directories, this Edit control is always see the "current directory", except if you "feed to listbox" the results of a search so this Edit control is made blank.
That's why some of LP, RP, SP, TP are empty depends on which panel(s) contain search results.
My script send the LP, RP, SP, TP requests and waiting for an answer. But because the answer is an empty string, it is continue waiting for 5 seconds for a value.

Thank you LonerD for your report, the delay is already fixed!
FIXED at 20150425:
When you send an "ASK TC" command and the value returned by TC is an "empty" string (as if you send "SP" and the source panel contains a search results list), it will not wait for 5 seconds for the empty value to be returned to the user. (Thanks LonerD for your report)
Best Regards
Post Reply