1

Тема: AHK: GUI HTML интерфейс (шаблон для Вашего проекта)

Скрипт является примером использования HTML для построения GUI интерфейса.
Приведены примеры организации типового взаимодействия между AHK и DOM структурой HTML документа.
Надеюсь, пригодится как шаблон для ваших разработок.


; Для для включения 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 props = [];
		for (var p in obj){
			try {
				var v = obj[p];
				if (v) props.push(p + ' = ' + String(v).substr(0,25));
			} catch (e) {}
		}
		alert(obj.tagName + '\n---------------\n' + 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 скрипт вполне оправдана. Когда речь идет о более-менее серьезном проекте, то такая интеграция превращается в огромную проблему. Тут и неудобство редактирования инородного кода, и необходимость его преобразования, и отсутствие возможности тестирования,... (список можно продолжить). Это - проблемы, с которыми еще можно кое как справиться, но есть и неразрешимые.
При компиляции HTML можно оставить в отдельном файле (FileInstall), а можно добавить в ресурсы получившегося exe-файла (вручную, либо с помощью нового Ahk2Exe). В общем, надеюсь, доказал. Внешний HTML - без вариантов.

Обсуждение данного шаблона ведётся в этой теме.