Возможно ли посылать полноценные команды AkelPad из другого приложения? Забирать текст как скрипты, а не передавая путь файла внешней утилите (предварительно сохранив этот самый файл (только так работает, например, Tidy AutoIt: вероятно, утилита крайне заточена под SciTE)) и делать с ним что угодно? Или хотя бы то, что можно записать как строку меню или кнопку тулбара. И если да, то как?
Научился скриптом AutoIt посылать внутренние команды (4101-5001, без опциональных параметров):
Не знаю, что правильнее - класс окна AkelPad или окна редактирования - AkelPad4 или AkelEditW? Вероятно, зависит от целей?
$WM_COMMAND = 0x0111 - непонятно, это действительно константа или нужно менять? Для одной из команд ТС мне подсказали с оговоркой "в данном случае равно %число%", значит надо где-то посмотреть? Вероятно, грозит вдумчивое чтение AkelEdit.c?
Или только через COM-объекты и мне, как дилетанту, нечего соваться?
И если возможно, пару-тройку примеров: вызов плагина, скрипта с хотя бы одним параметром и что-нибудь из методов из Script-Rus.txt.
Posted: Wed Jul 23, 2014 12:31 pm
by Instructor
Skif_off
Из другого приложения в одностороннем порядке можно посылать командую строку на обработку AkelPad'у с помощью WM_COPYDATA с CD_PARSECMDLINEW (см. AkelDLL.h).
Для целей двухстороннего диалога можно использовать Scripts плагин. Недавно была тема в англоязычной ветке.
Skif_off wrote:$WM_COMMAND = 0x0111 - непонятно, это действительно константа или нужно менять?
И если возможно, пару-тройку примеров: вызов плагина, скрипта с хотя бы одним параметром и что-нибудь из методов из Script-Rus.txt.
Это лучше спросить у пользователей AutoIt как послать WM_COPYDATA.
Posted: Wed Jul 23, 2014 3:40 pm
by Skif_off
Instructor
Кажется, не по Сеньке, так сказать, шапка Но энтузиазм (самонадеянность?) пока не угас: перегнал все Defines из AkelDLL.h в Global Const, нашел образец, но DllStructCreate пока за гранью понимания.
Вы можете привести пример кода на С/С++ для отправки AkelPad, например
#NoTrayIcon
#Include <GUIConstantsEx.au3>
#Include <GUIListBox.au3>
#Include <WinAPI.au3>
#Include <WindowsConstants.au3>
#include <Array.au3>
#include <GuiTab.au3>
#include <ListBoxConstants.au3>
;Смотрите справку AutoItSetOption()
Opt('MustDeclareVars', 1)
Opt('GUIDataSeparatorChar','|')
Global $hForm, $Msg, $Dummy, $List, $hList, $hWin, $hTab, $iCount, $aTabs, $F, $index
;Получаем дескриптор окна AkelPad
$hWin = WinGetHandle('[Class:AkelPad4]')
If Not $hWin Then Exit 1
;Получаем указатель для элемента SysTabControl32 (вкладки AkelPad)
$hTab = ControlGetHandle($hWin, '', '[CLASS:SysTabControl32; INSTANCE:1]')
If Not $hTab Then Exit 2
;Получаем количество вкладок
$iCount = _GUICtrlTab_GetItemCount($hTab)
;Создаем массив с названиями вкладок
Local $aTabs[1]
$aTabs[0] = $iCount
For $i = 0 To $iCount - 1
_ArrayAdd($aTabs, _GUICtrlTab_GetItemText($hTab, $i))
Next
;Рисуем GUI
$hForm = GUiCreate('Выбор вкладки AkelPad', 280, 380)
$List = GUICtrlCreateList('', 5, 5, 270, 370, $GUI_SS_DEFAULT_LIST + BitNOT($LBS_SORT))
$hList = GUICtrlGetHandle(-1)
;и набиваем List списком вкладок
$F = ''
For $i = 1 To $iCount
$F &= $aTabs[$i]
$F &= '|'
Next
GUICtrlSetData(-1, $F, $aTabs[1])
;Создаем элемент Dummy
$Dummy = GUICtrlCreateDummy()
;Регистрация пользовательской функции и горячей клавиши
GUIRegisterMsg($WM_COMMAND, 'WM_COMMAND')
HotKeySet('{ENTER}', 'HKEnter')
GUISetState()
While 1
$Msg = GUIGetMsg()
Switch $Msg
Case $GUI_EVENT_CLOSE
ExitLoop
Case $Dummy
$index = _GUICtrlListBox_GetCurSel($hList)
WinActivate($hWin)
_GUICtrlTab_SetCurFocus($hTab, $index)
EndSwitch
WEnd
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
Local $Index
Switch $lParam
Case $hList
Switch _WinAPI_HiWord($wParam)
Case $LBN_DBLCLK
$Index = _GUICtrlListBox_GetCurSel($hList)
If ($Index > -1) And (_GUICtrlListBox_GetCaretIndex($hList) = $Index) Then
GUICtrlSendToDummy($Dummy, $Index)
EndIf
EndSwitch
EndSwitch
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_COMMAND
Func HKEnter()
Local $Index
If _WinAPI_GetFocus() = $hList Then
$Index = _GUICtrlListBox_GetCurSel($hList)
If $Index > -1 Then
GUICtrlSendToDummy($Dummy, $Index)
Return
EndIf
EndIf
HotKeySet('{ENTER}')
Send('{ENTER}')
HotKeySet('{ENTER}', 'HKEnter')
EndFunc ;==>HKEdit
По сути - функциональный набросок: список создаётся один раз при запуске, не запоминает положение, жёстко задан размер окна (добавить изменение размера и положение окна сравнительно легко, можно даже попробовать рассчитывать свободное место и открывать окно вне области, занятой окном AkelPad).
Нюансы: скомпилированный скрипт или интерпретатор должны быть той же разрядности, что и AkelPad; антивирусник/проактивка могут сделать стойку на строку
внутри _GUICtrlTab_GetItemText() (это не считая 2-3 вендоров на вирустотал, традиционно гавкающих на скомпилированные скрипты и/или UPX)
З.Ы. Это не WSH и плагин Scripts, не представляю, как получить полное имя файла, по сути: список создаётся для благообразного вида, фактически происходит оперирование индексами (номер вкладки от 0 до N и индекс в списке от 0 до N).
Posted: Tue Nov 04, 2014 3:53 am
by Skif_off
Instructor
А как должна выглядеть строка запуска скрипта с WM_COPYDATA?
Или вообще /Exec? Нужна ли точка с запятой в конце? AkelPad.ScriptNoMutex()?
Наверное, AkelPad.xxx не то, раз методы плагина?
Posted: Tue Nov 04, 2014 8:38 am
by Instructor
Skif_off
Instructor wrote:Из другого приложения в одностороннем порядке можно посылать командую строку на обработку AkelPad'у с помощью WM_COPYDATA с CD_PARSECMDLINEW (см. AkelDLL.h).
вставит текст в позицию курсора или заменив выделение. Для замены всего текста есть ControlSetText(), но с неприятностью: документ не изменит статус на "изменен" (запрос сохранения не вылезет при закрытии AkelPad). _GUICtrlEdit_SetText() и _GUICtrlEdit_InsertText() сработают аналогично? До их проверки не дошёл
Это если по взрослому, не задействуя буфер обмена.
Ну и добавлю, если кому-то понадобиться автоматизировать обработку: WM_COPYDATA с CD_PARSECMDLINEW позволят если не всё, что угодно, то очень многое (см. параметры командной строки, включая методы, конечно).
Но есть нюанс: антивирусник может гавкнуть на попытку послать оконное сообщение.
Насчёт актуальности: сейчас, наверное, для информации Практически всё так или иначе решается плагинами и скриптами WSH. Ну, для декодирования Quoted-Printable скрипт всё-таки перепишу, наверное.
Posted: Sat Dec 06, 2014 12:03 pm
by Andrey_A_A
но с неприятностью: документ не изменит статус на "изменен"
В Autoit часто приходится считать разные выражения с участием функций к примеру
$hAkelPad = WinGetHandle('[Class:AkelPad4]')
If Not $hAkelPad Then Exit
$Text = ControlGetText($hAkelPad, '', 'AkelEditW1')
$Text = StringRegExpReplace($Text, '(\r\n|\r|\n){2,}', ' ')
ControlSetText($hAkelPad, '', 'AkelEditW1', $Text)
; Закрываем вкладку
_SendMessage($hAkelPad, $WM_COMMAND, 4318, 0)
; или закрываем AkelPad
_SendMessage($hAkelPad, $WM_COMMAND, 4109, 0)
не изменит файл и AkelPad не выдаст запрос на сохранение изменений. Нужно дополнительно послать команду сохранения изменений (4105) и только потом закрывать.
Надо ещё проверить _GUICtrlEdit_SetText() и _GUICtrlEdit_InsertText() (только я не понял - они для собственных окон или любых?), но этот нюанс определённо нужно иметь в виду.