Тема: AHK: GUI HTML интерфейс (шаблон для любого проекта)
Умолчу о неоспоримых и многочисленных достоинствах веб-интерфейса (ну и о некоторых его недостатках - тоже). Полагаю, что тот, кому знаком html и javascript и кого связывают возможности контролов AHK Gui свой выбор уже сделал.
Скрипт, предлагаемый вашему вниманию, является учебным. Сочиняя его, учился сам. Из нескольких возможных вариантов процедур выбирал наиболее простой и надежный. Надеюсь, пригодится как шаблон для ваших разработок.
; Для для включения html в exe-шник можно использовать модифицированный Ahk2Exe
; https://autohotkey.com/boards/viewtopic.php?f=24&t=521
; http://fincs.ahk4.net/files/NewAhk2Exe-preview2a.zip
;@Ahk2Exe-AddResource interface.html
#Warn
#NoEnv
#SingleInstance Force
SetBatchLines -1
; Gui, -DPIScale - не использовать! (Будут проблемы с масштабированием html содержимого)
Gui, Add, GroupBox, w476 h90 , % "AHK Application"
Gui, Add, Button, xp14 yp+20 w90 gGetFromIE , % "Get from IE"
Gui, Add, Edit, x+14 yp w240 vAHKEditBox , % "test AHK string"
Gui, Add, Button, x+14 yp w90 gSendToIE , % "Send to IE"
Gui, Add, Button, xs+14 y+8 w160 gCallJavaScript , % "Call JavaScript Function"
Gui, Add, ActiveX, x0 y+32 w500 h84 hwndIEhwnd vIE , Shell.Explorer
htmlfile := A_IsCompiled ? "res://" A_ScriptFullPath "/interface.html" : A_ScriptDir "\interface.html"
IE.Navigate(htmlfile)
; loop { ; Ожидание загрузки html - (приводится во всех примерах, но нам для локальной страницы абсолютно ничего не дает)
; If !IE.busy
; break
; }
Gui, Color, cC0C0C0
; Gui, Show, w500 h188, % "ActiveX Shell.Explorer"
Gui, Show, w500 h190, % "ActiveX Shell.Explorer"
loop { ; Ожидание инициализации подключений (вот эта задержка - обязательна!)
Try {
IE.document.All.IEInputBox
break
}
}
; Подключение к html элементу IEInputBox
IEInpBox := IE.document.GetElementById["IEInputBox"]
; IEInpBox := IE.document.All.IEInputBox ; альтернативный способ
Events := [] ; Подключение к событиям html элементов INPUT (для всех элементов используйте "*")
Inputs := IE.document.GetElementsByTagName["input"]
Loop % Inputs.length {
Events[A_Index] := Inputs[A_Index-1]
ComObjConnect(Events[A_Index], Inputs[A_Index-1].id "_")
}
return
; Нажатие на кнопку "Get from IE"
GetFromIE:
x := IEInpBox.value
GuiControl,, AHKEditBox, % x
return
; Нажатие на кнопку "Send to IE"
SendToIE:
GuiControlGet, y,, AHKEditBox
IEInpBox.value := y
return
; Нажатие на кнопку "Call JavaScript Function"
CallJavaScript:
GuiControlGet, param,, AHKEditBox
IE.document.parentWindow.execScript("tempJsVar=funcTest('" param "')")
ret := IE.document.Script.tempJsVar
GuiControl,, AHKEditBox, % ret
return
; Нажатие на кнопку "Get from AHK"
IEButtonGet_OnClick(this) {
GuiControlGet, v,, AHKEditBox
this.document.GetElementById["IEInputBox"].value := v
}
; Нажатие на кнопку "Send to AHK"
IEButtonSend_OnClick(this) {
v := this.document.GetElementById["IEInputBox"].value
GuiControl,, AHKEditBox, % v
}
GuiEscape:
GuiClose:
Gui, Destroy
ExitApp
interface.html
<html>
<head>
<meta http-equiv="content-type" content="text-html; charset=utf-8">
<meta http-equiv="MSThemeCompatible" content="yes">
<style type="text/css">
/* Задание общих стилей оформления элементов. Все размеры задавать только в pt! (Иначе будут проблемы с нестандартным DPI) */
* {font:8pt MS Shell Dlg;}
td {white-space:nowrap; padding-left:8pt;}
.test {color:red; background-color:yellow;}
</style>
<script type="text/javascript">
// Выбор элемента, показ всех его свойств, возврат его идентификатора
function funcTest(i){
var elements = document.getElementsByTagName('*');
var i = Math.abs(Number(i)||0); if (i >= elements.length) i = 0;
var elem = elements[i];
// Подсвечиваем элемент и показываем все его свойства
elem.className = 'test';
ShowElementProps(elem);
elem.className = '';
i++;
return Math.floor(i);
}
// Показ всех свойств заданного элемента
function ShowElementProps(obj) {
var all_props = [];
for (var prop in obj){
try {
var p = obj[prop];
if (p) all_props.push(prop + ' = ' + String(p).substr(0,25));
} catch (e) {}
}
alert(obj.tagName + '\n---------------\n' + all_props.sort().join('\n'));
}
</script>
</head>
<body style="margin:10pt; overflow:hidden; background-color:#629DAC;">
<fieldset><legend>Internet Explorer</legend>
<table style="border-width:0; border-collapse:collapse; width:100%; height:28pt;">
<tr>
<td>
<input id="IEButtonGet" type="button" value="Get from AHK">
</td>
<td>
<input id="IEInputBox" style="width:160pt;" value="test HTML string">
</td>
<td>
<input id="IEButtonSend" type="button" value="Send to AHK">
</td>
</tr>
</table>
</fieldset>
</body>
</html>
Сразу отвечу на вопрос: Почему html не вставлен в ahk скрипт, а находится в отдельном файле?
Если в html всего пара или тройка элементов, то вставка кода в ahk скрипт вполне оправдана. Когда речь идет о более-менее серьезном проекте, то такая интеграция превращается в огромную проблему. Тут и неудобство редактирования инородного кода, и необходимость его преобразования, и отсутствие возможности тестирования,... (список можно продолжить). Это - проблемы, с которыми еще можно кое как справиться, но есть и неразрешимые. Я, например, динамически впихнул и js-скрипты и таблицу стилей и все сработало, но никакого результата от добавления httpEquiv=MSThemeCompatible я так и не увидел. А html без поддержки стилей просто убог (особенно - контролы).
При компиляции html можно оставить в отдельном файле (FileInstall), а можно добавить в ресурсы получившегося exe-файла (вручную, либо с помощью нового Ahk2Exe). В общем, надеюсь, доказал. Внешний html - без вариантов. Кстати, если речь идёт о публикации, то его разработку лучше бы доверить сведущему товарищу, нежели надеяться на то, что великие познания в ahk помогут вам самостоятельно создать приличный html интерфейс.
Жду замечаний от AHK-профессионалов. Вдруг какую то процедуру можно сделать еще проще/надежнее? Может еще чего часто-используемого добавить в данный шаблон?
P.S. Просто убивают некоторые ahk скрипты, авторы которых пытаются управлять элементами html интерфейса с помощью функций AHK и WinAPI вызовов. Ребята, если связались с html, учите js, css! C их помощью все это делается на раз-два.