Thank you for explanation.
Still wait.FIXED... it will not wait for 5 seconds for the empty value
And you lost CD-Command section in script comment ))
Moderators: Hacker, petermad, Stefan2, white
Still wait.FIXED... it will not wait for 5 seconds for the empty value
Code: Select all
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")
Code: Select all
IF ((msg=0x4A) AND (hwnd=A_ScriptHwnd)) ; EnSure is trigered by this Script.
{
TC_ReceiveDataValue:=StrGet(NumGet(CmdType + A_PtrSize * 2))
TC_DataReceived:="1"
MsgBox,4096,Those Data Received by TC:,[%TC_ReceiveDataValue%]
EXIT
}
Code: Select all
Imports System.Runtime.InteropServices
Imports System.Windows.Interop
Class MainWindow
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInteger, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
Private Const TCMD_MSG = 1075 ' WM_USER + 51
Private Function GetProcess() As Process
Return Process.GetProcessesByName("TOTALCMD64").First()
End Function
Private Sub btnCmCommand_Click(sender As Object, e As RoutedEventArgs) Handles btnCmCommand.Click
Using p = GetProcess()
' Example: 2027 = cm_PrintDir - print current directory (with preview)
SendMessage(p.MainWindowHandle, TCMD_MSG, New IntPtr(2027), IntPtr.Zero)
End Using
End Sub
Private Const WM_COPYDATA = &H4A
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInteger, wParam As IntPtr, ByRef lParam As COPYDATASTRUCT) As Boolean
End Function
<StructLayout(LayoutKind.Sequential)>
Structure COPYDATASTRUCT
Dim dwData As IntPtr
Dim cbData As Int32
Dim lpData As IntPtr
End Structure
Private Function IntPtrAlloc(Of T)(param As T) As IntPtr
Dim ptr As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(param))
Marshal.StructureToPtr(param, ptr, False)
Return ptr
End Function
Private Sub IntPtrFree(preAllocated As IntPtr)
If IntPtr.Zero = preAllocated Then Throw New Exception()
Marshal.FreeHGlobal(preAllocated)
preAllocated = IntPtr.Zero
End Sub
Private Sub SendCommand(commandType As String, command As String)
SendCommand(commandType, command, IntPtr.Zero)
End Sub
Private Sub SendCommand(commandType As String, command As String, hWnd As IntPtr)
Using p = GetProcess()
Dim dataStruct = New COPYDATASTRUCT
dataStruct.dwData = New IntPtr(Convert.ToInt32(commandType(0)) + 256 * Convert.ToInt32(commandType(1)))
dataStruct.cbData = command.Length + 1
dataStruct.lpData = Marshal.StringToHGlobalAnsi(command)
Dim dataStructPointer = IntPtrAlloc(dataStruct)
SendMessage(p.MainWindowHandle, WM_COPYDATA, hWnd, dataStructPointer)
IntPtrFree(dataStruct.lpData)
IntPtrFree(dataStructPointer)
End Using
End Sub
Private Sub btnEmCommand_Click(sender As Object, e As RoutedEventArgs) Handles btnEmCommand.Click
Dim commandType = "EM"
Dim command = "em_PutCommandNameHere"
SendCommand(commandType, command)
End Sub
Private Sub btnChangeDir_Click(sender As Object, e As RoutedEventArgs) Handles btnChangeDir.Click
Dim commandType = "CD"
Dim left = "c:\!Temp\"
Dim right = "d:\!Temp\"
' S - use source/target instead of left/right (optional)
' T - open in new tab (optional)
Dim command = left & Convert.ToChar(13) & right & Convert.ToChar(0) & "ST"
SendCommand(commandType, command)
End Sub
Private Sub btnGetInfo_Click(sender As Object, e As RoutedEventArgs) Handles btnGetInfo.Click
' W returns data in UTF16 (or use A instead)
Dim commandType = "GW"
' 1 byte: A: Active side (returns L or R)
' or
' 2 bytes:
' first byte: L=left, R=right, S=source, T=target
' second byte: P=current path, C=list count, I=caret index, N=name of file under caret
Dim command = "SN"
Dim hWnd = DirectCast(PresentationSource.FromVisual(Me), HwndSource).Handle ' because of WPF
SendCommand(commandType, command, hWnd)
End Sub
Private Function WndProc(hWnd As IntPtr, msg As Integer, wParam As IntPtr, lParam As IntPtr, ByRef handled As Boolean) As IntPtr
If msg = WM_COPYDATA Then
' W returns data in UTF16 (or use A instead)
Dim expected = "RW"
Dim dataStruct = DirectCast(Marshal.PtrToStructure(lParam, GetType(COPYDATASTRUCT)), COPYDATASTRUCT)
If dataStruct.dwData.ToInt32() = Convert.ToInt32(expected(0)) + 256 * Convert.ToInt32(expected(1)) Then
Dim data = New Byte(dataStruct.cbData) {}
Marshal.Copy(dataStruct.lpData, data, 0, dataStruct.cbData)
Dim text = System.Text.Encoding.Unicode.GetString(data)
MessageBox.Show(text)
handled = True
End If
End If
Return IntPtr.Zero
End Function
' used because there is no WndProc to override in WPF
Private Sub MainWindow_SourceInitialized(sender As Object, e As EventArgs) Handles Me.SourceInitialized
DirectCast(PresentationSource.FromVisual(Me), HwndSource).AddHook(New HwndSourceHook(AddressOf WndProc))
End Sub
Private Sub MainWindow_Closing(sender As Object, e As ComponentModel.CancelEventArgs) Handles Me.Closing
DirectCast(PresentationSource.FromVisual(Me), HwndSource).RemoveHook(New HwndSourceHook(AddressOf WndProc))
End Sub
End Class
Code: Select all
function _TotalCmdChangeDir(const TC: THandle; const ADir: string = '';
const ADir2: string = ''; const AFlags: string = '';
const ASender: THandle = 0): Boolean;
var
Ls: string;
Lcds: TCopyDataStruct;
begin
Result:= False;
if (ADir = '') AND (ADir2 = '') then Exit;
if (ADir <> '') then
Ls:= ADir;
Ls:= Ls + #13;
if (ADir2 <> '') then
Ls:= Ls + ADir2;
if AFlags <> '' then
Ls:= Ls + #0 + AFlags;
ZeroMemory(@Lcds, SizeOf(Lcds));
Lcds.dwData := Ord('C') + 256 * Ord('D');
Lcds.cbData := (Length(Ls) + 1);
Lcds.lpData := PChar(Ls);
SendMessage(TC, WM_COPYDATA, ASender, LPARAM(@Lcds));
Result:= True;
end;
//------------------------------------------------------------------------------
{$IFDEF UNICODE}
function _TotalCmdChangeDirW(const TC: THandle; const ADir: string = '';
const ADir2: string = ''; const AFlags: string = '';
const ASender: THandle = 0): Boolean;
const UTF8BOM : RawByteString = #$EF + #$BB + #$BF;
var Ls: RawByteString;
Lcds: TCopyDataStruct;
begin
Result:= False;
if (ADir = '') AND (ADir2 = '') then Exit;
if (ADir <> '') then
Ls:= UTF8BOM + UTF8Encode(ADir);
Ls:= Ls + #13;
if (ADir2 <> '') then
Ls:= Ls + UTF8BOM + UTF8Encode(ADir2);
if AFlags <> '' then
Ls:= Ls + #0 + RawByteString(AFlags);
ZeroMemory(@Lcds, SizeOf(Lcds));
Lcds.dwData := Ord('C') + 256 * Ord('D');
Lcds.cbData := (Length(Ls) + 1);
Lcds.lpData := Pointer(Ls);
SendMessage(TC, WM_COPYDATA, ASender, LPARAM(@Lcds));
Result:= True;
end;
{$ENDIF}
//------------------------------------------------------------------------------
function TotalCmdChangeDir(const TCHandle: THandle; const ADir: string; ANewTab: Boolean = True): Boolean;
var Lflags: string;
begin
Lflags:= 'S';
if ANewTab then
Lflags:= Lflags + 'T';
{$IFDEF UNICODE}
Result:= _TotalCmdChangeDirW(TCHandle, ADir, '', Lflags);
{$ELSE}
Result:= _TotalCmdChangeDir(TCHandle, ADir, '', Lflags);
{$ENDIF}
end;
Code: Select all
TC_SendData("D:\日本" "`r", "ST")
I took this script and edit it a bit based on the result of the other postartt wrote: 2015-04-23, 06:05 UTC 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
; F1 for input cm_ & em_ command test
; F2 for asking TC some simple panel status
; F12 for a batch test, but you will need to set up some user command and Dirs first.
EM = em_foo|em_cd *.ini *.exe|em_命令 *.*|em_APPENDTABS D:\TC\Tab\标签.tab ;
CM = cm_select 5|cm_wait 2000|cm_about
ASK = A|LP|LC|LI|LN|RP|RC|RI|RN|SP|SC|SI|SN|TP|TC|TI|TN
bom :=( A_IsUnicode )?Chr(0xFEFF):""
Dir1 := "e:\测试\ビデオゲームミュージック"
Dir2 := "%windir%"
Dir3 := "E:\测试\totalcmd950b6x64.cab" ; it is an arhive for testing "A" parameters
Dir4 := "d:\tc"
return
F1::
InputBox, StringToSend, Send command via WM_COPYDATA,interanl command cm_select 5 `nuser command em_foo (you need to define it first):
TC_SendData(bom StringToSend, "EM")
return
F2::
InputBox, StringToSend, Send command via WM_COPYDATA,A|LP|LC|LI|LN|RP|RC|RI|RN|SP|SC|SI|SN|TP|TC|TI|TN `n for example ask for A for Active panel:
answer:=TC_SendData(StringToSend)
MsgBox, %answer%
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, CM, | ; internal command, but call as em_cmd
{
MsgBox,4096, internal command, %A_LoopField%
TC_SendData(bom A_LoopField,"EM")
}
LOOP, PARSE, EM, | ; User Command
{
MsgBox,4096, User Command, %A_LoopField%
TC_SendData(bom A_LoopField,"EM")
}
MsgBox,4096, CD Command, LeftDir=%Dir1% - RightDir=%Dir2% `n Active->Right
TC_SendData(bom Dir1 "`r" bom Dir2, "R")
MsgBox,4096, CD Command, SourceDir=%Dir3% `n open in NEW tab `n if path is an archive, do not open but select it `n Active->Left
TC_SendData(bom Dir3 "`r" bom "c:" , "ASTL")
MsgBox,4096, CD Command, TargetDir=%Dir4% `n open in NEW tab
TC_SendData( "`r" bom Dir4, "ST")
MsgBox,4096, CD Command, SourceDir=%Dir2% `n open in NEW tab `n Active->Right
TC_SendData(bom Dir2 "`r", "SRT")
MsgBox,4096, CD Command, RightDir=%Dir3% `n when you have no CD param "STLRA" just leave "CD" for distinguishing from "ASK"
TC_SendData( "`r" bom Dir3, "CD") ;
MsgBox,4096, CD Command, SourceDir=%Dir3% TargetDir=%Dir4% `n open in NEW Background tab `n Active->Left
TC_SendData(bom Dir3 "`r" bom Dir4, "STBL")
Return
/*
TESTED AND WORKING ON: AHK_L v 1.1.31.01 unicode & ansi version, Win 10 64bit and TC9.22
modified by dindog
-------------------------------------------------------------------------
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("em_CD C:", "EM") ; User Command with parameters (usercmd.ini as following)
; [em_cd]
; cmd=cd
; param=%A
TC_SendData("em_命令 *.exe", "EM") ; User Command with parameters (usercmd.ini as following) test for command name non-ASCII
; [em_命令]
; cmd=cd
; 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", "CD") ; CD Command: (LeftDir - RightDir)
TC_SendData("C:\tc" "`r" , "R") ; CD Command: (LeftDir) and activate Right panel
TC_SendData( "`r" "D:\data", "LT") ; CD Command: ( RightDir) in new tab and activate left panel
TC_SendData("C:\tc" "`r" "D:\data", "S") ; CD Command: (SourceDir - TargetDir)
TC_SendData("C:\tc" "`r" , "SBT") ; CD Command: (SourceDir) in new background tab
TC_SendData( "`r" "D:\data", "ST") ; CD Command: ( TargetDir) in new background tab
S: Interpret the paths as source/target instead of left/right
T: Open path(s) in new tabs
B: Open tabs in background (do not activate them)
L: Activate the left panel
R: Activate the right panel
A: Do not open archives as directories. Instead, open parent directory and place cursor on it.
TC accepts more then 2 parameters here, so sending e.g. STBL is legitimate.
*/
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="") ; Ask TC
CmdType:=(A_IsUnicode ? "GW" : "GA"), TC_ReceiveDataValue:=""
else if (CmdType="EM") or (CmdType="em") ; em command
CmdType:="EM"
else ; CD command STBALR
DirType:=(CmdType="CD")?"":CmdType, CmdType:="CD"
;;;;;;VarSetCapacity need to request at least 5 more byte to allow 4 CD params
VarSetCapacity(cmdA, StrPut(cmd, (A_IsUnicode ?"UTF-8":"CP0")) + (CmdType="CD" ? 5 : 0) * (A_IsUnicode ? 2 : 1), 0) , Len:=StrPut(cmd, &cmdA, (A_IsUnicode ?"UTF-8":"CP0"))
NumPut( Asc(SubStr(CmdType,1,1)) + 256 * Asc(SubStr(CmdType,2,1)), CopyDataStruct,0 )
NumPut( Len + (CmdType="CD" ? 5 : 0) * (A_IsUnicode ? 2 : 1) , CopyDataStruct, A_PtrSize )
NumPut( &cmdA , CopyDataStruct, A_PtrSize * 2)
Loop, % strlen(DirType) ;(CmdType=="CD" ? 2 : 0)
{
NumPut(Asc(SubStr(DirType,A_Index,1)), cmdA ,Len+A_Index-1, "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
}