I am trying send WM_COPYDATA to Totoal Commander (TC) using VBA.
Here is what I've done so far.
And there is no error message.
What I've checked
- The setting in
TCis correct because I can call TC's internal commands usingsendmessagein Autohotkey. - For
result = SendMessage(hwndTC, 1075, 4001, 0) 'FocusLeft, it works.
That means thehwndof Total commander has been correctly got And the message has been correctly sent. - The not workable part is the
Sub TC_SetPath(hwndTarget, UserCMD As String). I've checked some other code and tried to make following change
cds.cbData = Len(UserCMD) + 1 ' not work
cds.cbData = Len(UserCMD) + 2 ' not work
cds.cbData = (Len(UserCMD) + 1)*2 ' not work
- I've also tried the code here 1. That is to covert the string input to Byte. Still doesn't work and no error message.
Sub TC_SetPath(hwndTarget, UserCMD As String)
Dim cds As CopyDataStruct, result As LongPtr
Dim MsgBytes() As Byte
MsgBytes = StrConv(UserCMD, vbUnicode)
cds.dwData = Asc("E") + 256 * Asc("M") 'OK
cds.cbData = UBound(MsgBytes)
cds.lpData = VarPtr(MsgBytes(1)) 'OK
' Send the WM_COPYDATA message
result = SendMessage(hwndTarget, WM_COPYDATA, 0, VarPtr(cds))
If result = 0 Then
Debug.Print "3"
Debug.Print GetLastErrorStr(Err.LastDllError) 'The operation completed successfully.
End If
End Sub
Any help would be appreciated. Thanks.
2nd version of VBA code based on the suggetions so far
Option Explicit
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As LongPtr, lParam As Any) As LongPtr
Public Type CopyDataStruct
dwData As LongPtr
cbData As Long
lpData As LongPtr
End Type
Private Const WM_COPYDATA = &H4A
Sub test()
Call TC_SendUserCMD("em_focusfile")
End Sub
Sub TC_SendUserCMD(UserCMD As String)
Dim cds As CopyDataStruct, result As LongPtr
Dim hwndTC As LongPtr
Dim wParam As LongPtr
wParam = 0
hwndTC = FindWindow("TTOTAL_CMD", vbNullString)
cds.dwData = Asc("E") + 256 * Asc("M")
cds.cbData = Len(UserCMD) * 2 + 2
cds.lpData = StrPtr(UserCMD)
result = SendMessage(hwndTC, WM_COPYDATA, wParam, cds)
End Sub
This is the 1st version of VBA code.
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As LongPtr, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As LongPtr
Public Type CopyDataStruct
dwData As LongPtr
cbData As LongPtr
lpData As LongPtr
End Type
Private Const WM_COPYDATA = &H4A
Sub test()
Dim newPath As String
ThisFile = "D:\xxx\xxx\.mhtml"
newPath = ThisFile & "\:\n" & "\0"
hwndTC = FindWindow("TTOTAL_CMD", vbNullString)
result = SendMessage(hwndTC, 1075, 4001, 0) 'FocusLeft OK
result = SendMessage(hwndTC, 1075, 3001, 0) 'NewTab OK
Call TC_SetPath(hwndTC, newPath)
End Sub
Sub TC_SetPath(hwndTarget, UserCMD As String)
Dim cds As CopyDataStruct
cds.dwData = Asc("C") + 256 * Asc("D") 'OK
' cds.cbData = (Len(UserCMD) + 1)*2 'also tried, not work, https://stackoverflow.com/questions/35950108/send-variable-in-lparam-in-vba-for-excel
cds.cbData = Len(UserCMD) + 1
cds.lpData = StrPtr(UserCMD) 'OK
' Send the WM_COPYDATA message
result = SendMessage(hwndTarget, WM_COPYDATA, 0, cds)
End Sub
Workable Autohotkey Script
And below is the workable Autohotkey script with the same function.
F1::
{
ThisFile:="D:\xxx\xxx.mhtml"
newPath:=ThisFile . "\:`r" . "\0"
SendMessage(0x433,4001,0,,"ahk_class TTOTAL_CMD") ; FocusLeft
SendMessage(0x433,3001,0,,"ahk_class TTOTAL_CMD") ; NewTab
TC_SetPath(newPath) ; CD to DirPath
}
TC_SetPath(userCommand)
{
; https://www.autohotkey.com/boards/viewtopic.php?p=538463&sid=4471e03917209854441ac07ebdc70901#p538463
static dwData := 17475 ;Ord("C") +256*Ord("D")
static WM_COPYDATA := 0x4A
cbData := Buffer(StrPut(userCommand, 'CP0'))
StrPut(userCommand, cbData, 'CP0')
COPYDATASTRUCT := Buffer(A_PtrSize * 3)
NumPut('Ptr', dwData, 'Ptr', cbData.size, 'Ptr', cbData.ptr, COPYDATASTRUCT)
MsgResult:=SendMessage( WM_COPYDATA,, COPYDATASTRUCT,, 'ahk_class TTOTAL_CMD')
return MsgResult
}
Please, try the next adapted code:
Now, you can have a confirmation if the API calls work correctly...