Что нового

AkelPad: WM_COPYDATA с CD_PARSECMDLINEW

Skif_off

Знающий
Сообщения
173
Репутация
12
С помощью CD_PARSECMDLINEW можно вызвать плагин AkelPad и его функцию с параметрами,

Код:
 COPYDATASTRUCT cds;
 PARSECMDLINEPOSTW *pclp;
 wchar_t *wpCmdLine=L"/Call(\"Scripts::Main\", 1, \"scriptname.js\") "

 if (pclp=(PARSECMDLINEPOSTW *)GlobalAlloc(GMEM_FIXED, sizeof(PARSECMDLINEPOSTW)))
 {
   pclp->bPostMessage=TRUE;
   pclp->nCmdLineLen=lstrcpynW(pclp->szCmdLine, wpCmdLine, COMMANDLINE_SIZE);
   pclp->nWorkDirLen=GetCurrentDirectoryWide(MAX_PATH, pclp->szWorkDir);

   cds.dwData=CD_PARSECMDLINEW;
   cds.cbData=sizeof(PARSECMDLINEPOSTW);
   cds.lpData=(PVOID)pclp;
   SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&cds);
   GlobalFree((HGLOBAL)pclp);
 }

Попробовал так

Код:
Global Const $WM_COPYDATA = 0x004A
$hAkelPad = WinGetHandle("[CLASS:AkelPad4]")
$hGUI = __HGetScriptProcHandle()

WinActivate("[CLASS:AkelPad4]")

$prmCommand = '/Call("Scripts::Main", 1, "transparency.js", "127") '

$dwData = 'CD_PARSECMDLINEW'
$lpDataLen = StringLen($prmCommand)
$lpData = DllStructCreate("char[" & $lpDataLen & "]")
DllStructSetData($lpData, 1, $prmCommand)
$lpDataPtr = DllStructGetPtr($lpData)
$structCOPYDATA = DllStructCreate("ulong_ptr;dword;ptr")
DllStructSetData($structCOPYDATA, 1, $dwData)
DllStructSetData($structCOPYDATA, 2, $lpDataLen)
DllStructSetData($structCOPYDATA, 3, $lpDataPtr)
$ptrCOPYDATA = DllStructGetPtr($structCOPYDATA)
DllCall("user32.dll", "int", "SendMessageW", "hwnd", $hAkelPad, "uint", $WM_COPYDATA, "wparam", $hGUI, "lparam", $ptrCOPYDATA)

Func __HGetScriptProcHandle()
    $sTitle = "ScriptWinRandomTitle"
    For $o = 1 To 7
        $sTitle &= Chr(Random(0x41, 0x5A))
    Next
    AutoItWinSetTitle($sTitle)
    Return WinGetHandle($sTitle)
EndFunc


- не работает. Пробовал wchar - тоже не сработало. Что сделал неправильно?
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Одной из причиной может быть то, что вы в ulong_ptr записываете "CD_PARSECMDLINEW". Вот здесь: DllStructSetData($structCOPYDATA, 1, $dwData)
ULONG_PTR - это unsigned integer а вы туда пишите строку. Может быть CD_PARSECMDLINEW это все таки число, какая нибудь константа?



Добавлено:
Сообщение автоматически объединено:

Вот вам все константы для wm_copydata
Код:
//// AkelPad WM_COPYDATA messages
#define CD_OPENDOCUMENT 1
#define CD_OPENDOCUMENTA 2
#define CD_OPENDOCUMENTW 3
#define CD_PARSECMDLINEW 9
https://github.com/Fr0sT-Brutal/AkelPad_AkelDefs/blob/master/AkelDLL.h
 
Автор
S

Skif_off

Знающий
Сообщения
173
Репутация
12
inververs [?]
Может быть CD_PARSECMDLINEW это все таки число, какая нибудь константа?
По сути DllStructCreate() почти целиком взята из другой функции, выполняющей подобное действие. И точно, в $dwData там получается число :smile:
Добавил
Код:
Global Const $CD_PARSECMDLINEW = 9
;...
$dwData = $CD_PARSECMDLINEW

не работает.

Пробовал разобрать пример на Си, так и не понял, что значит wchar_t *wpCmdLine=L, может быть, сама структура неправильная?

З.Ы. Пример в первом сообщении исправил (строка $lpDataLen = StringLen($prmCommand)), не то скопировал.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Код:
typedef struct {
BOOL bPostMessage; //FALSE for sending message (wait for return).
//TRUE for posting message (returns immediately).
wchar_t szCmdLine[COMMANDLINE_SIZE]; //Command line string.
int nCmdLineLen; //Command line length, not including the terminating null character.
wchar_t szWorkDir[MAX_PATH]; //Working directory string.
int nWorkDirLen; //Working directory length, not including the terminating null character.
BOOL bQuitAsEnd; //Internal variable - "/quit" stops parsing command line parameters, but not closes program.
} PARSECMDLINEPOSTW;
Попробуйте эту структуру заполнить и передать.
 
Автор
S

Skif_off

Знающий
Сообщения
173
Репутация
12
inververs
У меня сложности с DllStructCreate() :smile:
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Skif_off [?]
У меня сложности с DllStructCreate()
Ничего сложного. Вот пример.
Код:
;Командная строка
Local $szCmdLine = '/Call("Scripts::Main", 1, "transparency.js", "127")'
Local $nCmdLineLen = StringLen($szCmdLine)

;Создаем структуру
Local $tPARSECMDLINEPOSTW = DllStructCreate( _
		'BOOL bPostMessage;' & _
		'WCHAR szCmdLine[' & $nCmdLineLen + 1 & '];' & _
		'INT nCmdLineLen;' & _
		'WCHAR szWorkDir[255];' & _
		'INT nWorkDirLen;' & _
		'BOOL bQuitAsEnd')
;Заполняем стуктуру
DllStructSetData($tPARSECMDLINEPOSTW, 'bPostMessage', False)
;и так далее
 
Автор
S

Skif_off

Знающий
Сообщения
173
Репутация
12
inververs
Если правильно понял:
Код:
Global Const $WM_COPYDATA = 0x004A
Global Const $CD_PARSECMDLINEW = 9
$hAkelPad = WinGetHandle("[CLASS:AkelPad4]")
$hGUI = __HGetScriptProcHandle()

WinActivate("[CLASS:AkelPad4]")

;Командная строка
Local $szCmdLine = '/Call("Scripts::Main", 1, "transparency.js", "127")'
Local $nCmdLineLen = StringLen($szCmdLine)

;Создаем структуру
Local $tPARSECMDLINEPOSTW = DllStructCreate( _
        'BOOL bPostMessage;' & _
        'WCHAR szCmdLine[' & $nCmdLineLen + 1 & '];' & _
        'INT nCmdLineLen;' & _
        'WCHAR szWorkDir[255];' & _
        'INT nWorkDirLen;' & _
        'BOOL bQuitAsEnd')
;Заполняем стуктуру
DllStructSetData($tPARSECMDLINEPOSTW, 'bPostMessage', False)
;и так далее
$ptrCOPYDATA = DllStructGetPtr($tPARSECMDLINEPOSTW)
DllCall("user32.dll", "int", "SendMessageW", "hwnd", $hAkelPad, "uint", $WM_COPYDATA, "wparam", $hGUI, "lparam", $ptrCOPYDATA)

Func __HGetScriptProcHandle()
    $sTitle = "ScriptWinRandomTitle"
    For $o = 1 To 7
        $sTitle &= Chr(Random(0x41, 0x5A))
    Next
    AutoItWinSetTitle($sTitle)
    Return WinGetHandle($sTitle)
EndFunc

Не работает. Или $szWorkDir тоже нужно указать?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Если поискать в сети, то можно найти исходник AkelDLL.h, где есть примеры и вся информация по структурам. Исходя из этого описания, код должен выглядеть так:

Код:
Global Const $PCLE_QUIT = 0x01 ; Stop parsing command line parameters and close program.
Global Const $PCLE_END = 0x02 ; Stop parsing command line parameters.
Global Const $PCLE_ONLOAD = 0x04 ; Done parsing command line parameters on program load (used internally).

Global Const $CD_PARSECMDLINEW = 0x0009
Global Const $WM_COPYDATA = 0x004A

$hAkelPad = WinGetHandle('[CLASS:AkelPad4]')
$sCmdLine = '/Call("Scripts::Main", 1, "transparency.js", "127")'
$sWorkDir = @WorkingDir

$tPARSECMDLINEPOSTW = DllStructCreate('bool PostMessage;wchar CmdLine[32768];int CmdLineLen;wchar WorkDir[260];int WorkDirLen;bool QuitAsEnd')
DllStructSetData($tPARSECMDLINEPOSTW, 'PostMessage', 0)
DllStructSetData($tPARSECMDLINEPOSTW, 'CmdLine', 1, $sCmdLine)
DllStructSetData($tPARSECMDLINEPOSTW, 'CmdLineLen', StringLen($sCmdLine))
DllStructSetData($tPARSECMDLINEPOSTW, 'WorkDir', $sWorkDir)
DllStructSetData($tPARSECMDLINEPOSTW, 'WorkDirLen', StringLen($sWorkDir))

$tCOPYDATA = DllStructCreate('ulong_ptr;dword;ptr')
DllStructSetData($tCOPYDATA, 1, $CD_PARSECMDLINEW)
DllStructSetData($tCOPYDATA, 2, DllStructGetSize($tPARSECMDLINEPOSTW))
DllStructSetData($tCOPYDATA, 3, DllStructGetPtr($tPARSECMDLINEPOSTW))
$Result = DllCall('user32.dll', 'lresult', 'SendMessageW', 'hwnd', $hAkelPad, 'uint', $WM_COPYDATA, 'wparam', 0, 'ptr', DllStructGetPtr($tCOPYDATA))

; Returns 0 if "PostMessage" is TRUE or PCLE_* otherwise
ConsoleWrite('Result: ' & $Result[0] & @CR)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Yashied
Код:
DllStructSetData($tPARSECMDLINEPOSTW, 'CmdLine', $sCmdLine)



Добавлено:
Сообщение автоматически объединено:

Skif_off [?]
Если правильно понял:
Нет, под "и так далее" я имел ввиду, что вы заполняете данными всю структуру сами, по аналогии. Не было времени что бы дописать до конца. ;D
 
Автор
S

Skif_off

Знающий
Сообщения
173
Репутация
12
Yashied
Исходники на SF AkelDLL.h, на гитхабе с правками, кажется. Проблема в моих знаниях и возможностях :smile:
Пример не сработал, в выводе Result: 2. А с
Код:
DllStructSetData($tPARSECMDLINEPOSTW, 'CmdLine', $sCmdLine)

сработало, хотя тоже Result: 2.

inververs [?]
под "и так далее" я имел ввиду, что вы заполняете данными всю структуру сами, по аналогии.
А я просто обрадовался, скопировал и про DllStructSetData() даже не вспомнил :smile:)

inververs
Yashied
Спасибо, надо было сразу спросить :smile: Такой вопрос всплыл про $sWorkDir: значение не имеет значения? Или лучше выбрать каталог AkelPad.exe или файла?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Skif_off сказал(а):
Такой вопрос всплыл про $sWorkDir: значение не имеет значения? Или лучше выбрать каталог AkelPad.exe или файла?

Я не знаю, что делает этот AkelPad, но скорее всего нужно указать папку, где находится transparency.js, или вообще оставить пустым этот параметр:

Код:
DllStructSetData($tPARSECMDLINEPOSTW, 'WorkDirLen', 0)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Skif_off [?]
Или лучше выбрать каталог AkelPad.exe или файла?
Скорее всего файла.

сработало, хотя тоже Result: 2.
Значит все ок, вам вернуло
Код:
Global Const $PCLE_END = 0x02 ; Stop parsing command line parameters.

Попробуйте другую команду.
Код:
/p "C:\MyFile.txt\
, вроде как печатать файл. Только опцию вот эту выберите
DllStructSetData($tPARSECMDLINEPOSTW, 'PostMessage', 1)
 
Автор
S

Skif_off

Знающий
Сообщения
173
Репутация
12
inververs [?]
Скорее всего файла.
У AkelPad есть свои переменные:
%%f - активный файл
%%d - директория активного файла
%%a - директория AkelPad'а
Запуск будет простым :smile:

inververs сказал(а):
Skif_off [?]
Попробуйте другую команду.
Код:
/p "C:\MyFile.txt\
, вроде как печатать файл. Только опцию вот эту выберите
DllStructSetData($tPARSECMDLINEPOSTW, 'PostMessage', 1)
Почему DllStructSetData($tPARSECMDLINEPOSTW, 'PostMessage', 1)? С 0 тоже работает.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
Skif_off
Ок, пробуйте.
С 1 вроде как скрипт не будет ждать завершение и вернется в исполнение мгновенно.
 
Автор
S

Skif_off

Знающий
Сообщения
173
Репутация
12
inververs [?]
С 1 вроде как скрипт не будет ждать завершение и вернется в исполнение мгновенно.
В смысле - не будет ждать $Result? Или завершения вызванного события?


Добавлено:
Сообщение автоматически объединено:

Кажется, понял: по сути, разница, как с PostMessage (1) и SendMessage (0)?
 
Верх