Тема: Визуальный интерфейс VCLua в QUIK
Для создания интерфейса с пользователем в программах на Lua среди других разработана библиотека VCLua.
С точки зрения внутреннего устройства определенная "изюминка" ее состоит в том, что написана она на языке Pacscal, в то время как подавляющее большинство других библиотек написаны на C/C++. Само по себе это довольно здорово, т.к. для компиляции ее можно использовать Delphi или Lazarus, для которых них создано просто огромное количество визуальных компонент, реализующих различные элементы экранного интерфейса, что при определенном навыке позволяет легко расширять эту библиотеку, добавляя в нее новые необходимые элементы. Впрочем, при использовании этой библиотеки из Lua уже и так доступно весьма большое количество элементов визуального интерфейса (полный перечень их можно найти в файле controls.txt в дистрибутиве).
Домашняя страничка проекта [url]http://vclua.99k.org/[/url]
Последняя выложенная версия значится VCLua v0.3.5.
Стоит отметить довольно бедную справку по данной библиотеке и крайне малое количество примеров.
Установка
Вариант 1. Официальная сборка:
Для установки идем вот по этой ссылке [url]http://files.luaforge.net/releases/vclua/vclua/VCLua-0.3.5[/url] и скачиваем файл со скомпилированной (готовой к использованию) библиотекой и, желательно, файл с документацией (уж какая есть):
vclua-0.3.5-win32.zip
vclua-0.3.3-doc.zip
Вариант 2. Исправленная сборка с этого сайта:
Я буду постепенно исправлять и немного дополнять эту библиотеку.
Ссылка для скачивания и история изменений есть в [url=https://quik2dde.ru/viewtopic.php?pid=59#p59]следующем сообщении этой темы[/url]; в виде одного [url=https://quik2dde.ru/static-img/26/vcl.zip]архива vcl.zip[/url].
Далее все общее для любого варианта.
Из папки, куда распаковался архив vclua-0.3.5-win32.zip или vcl.zip, копируем в каталог с терминалом QUIK единственный файл:
vcl.dll (из папки bin для варианта 1)
Если вы до этого не ставили никакие другие дополнительные Lua-библиотеки, то вам еще необходимо скопировать файл lua5.1.dll из дистрибутива Lua с сайта lua.org, копируем тоже в каталог с QUIK. Подробнее где что брать см. отдельную тему рядом на этом форуме.
В варианте 2 файл lua5.1.dll добавлен в скачиваемый архив.
Вот и все. На этом установка закончена, можно использовать VCLua.
Использование
Создадим файл vcl-test-01.lua в текстовом редакторе и скопируем в него такой текст:
-- НЕ ИСПОЛЬЗУЙТЕ КОД ЭТОГО ПРИМЕРА В QUIK! Он приведен лишь как пример этапов изучения VCLua!
-- Читайте сообщение дальше, дальше есть правильный код
require "vcl"
mainForm = VCL.Form("mainForm")
mainForm.Caption = "My first VCLua application"
mainForm._= { position="podesktopcenter", height=400, width=600 }
mainForm.onclosequery = "onCloseQueryEventHandler"
function onCloseQueryEventHandler(Sender)
return true -- the form can be closed
end
mainMenu = VCL.MainMenu(mainForm,"mainMenu")
mainMenu:LoadFromTable({
{name="mmfile", caption="&File",
submenu={
{caption="Exit", onclick="onMenuExitClick", shortcut="Ctrl+F4"},
}
}
})
function onMenuExitClick()
mainForm:Close()
end
mainForm:ShowModal()
function main()
message("main started", 1)
end
Скрипт этот сделан на основе самого простого примера из поставки VCLua и даже еще несколько упрощен. Добавим файл vcl-test-01.lua в QUIK (Таблицы -> Lua -> Доступные скрипты) и запустим на выполнение. Появляется простейшее окно в меню, при этом как и с другими фреймворками визуализации для Lua в QUIK видим типичные проблемы: форма конечно создана и присутствует на экране, но скрипт отображается в состоянии "не запущен", да и сообщение "main started" не отображается, что означает, что поток с main() не запущен, т.е. скрипт еще даже не прошел инициализацию. Никакие обработчики событий тоже не работают.
Оно и понятно, ведь мы, как обычно, стоим в строке модального отображения главной формы:
mainForm:ShowModal()
И только когда мы форму закрываем - появляется сообщение "main started"!
Как делать правильно
Самой приятной особенностью библиотеки VCLua оказалось то, что она абсолютно отлично поддерживает немодальное отображение форм, в том числе и главной формы! Собственно в этом смысле понятие "главной формы" сразу исчезает, т.к. любые формы (т.е. окна интерфейса) можно отображать в любое время, VCLua от наличия или отсутствия форм работать не перестает! Давайте немного изменим предыдущий пример; основное, что будет изменено – будет вызываться метод Show вместо метода ShowModal. Это позволит нам не останавливаться на инициализации скрипта, а выполнять обычную нормальную работу QLua дальше. Сохраним текст в файле vcl-test-02.lua ([url=https://quik2dde.ru/static-img/26/vcl-test-02.lua]скачать[/url]).
require "vcl"
mainForm = VCL.Form("mainForm")
mainForm.Caption = "VCLua in QUIK"
mainForm._= { position="podesktopcenter", height=150, width=300}
mainMenu = VCL.MainMenu(mainForm,"mainMenu")
mainMenu:LoadFromTable({
{name="mmfile", caption="&File",
submenu={
{caption="Exit", onclick="onMenuExitClick", shortcut="Ctrl+F4"},
}
}
})
label = VCL.Label(mainForm,"Label")
label.Top = 30
label.Left = 50
label.Caption = "VCLua in QUIK"
label.Font.Size = 20
function onMenuExitClick()
OnStop()
end
mainForm:Show()
is_run = true
function main()
while is_run do
sleep(50)
end
end
function OnStop()
is_run = false
mainForm:Free()
end
Запустив скрипт, увидим такую картинку:
Обратите внимание:
скрипт корректно находится в состоянии "запущен"
при нажатии на "Остановить" скрипт завершается и окно закрывается
при выборе из меню на окне пункта File -> Exit окно закрывается и скрипт переходит в состояние "остановлен"
Остановка скрипта "по требованию" осуществляется здесь:
function OnStop()
is_run = false
mainForm:Free()
end
Т.е. в обработчике OnStop завершается цикл в main, для чего присваивается false переменной is_run, и уничтожается форма путем вызова метода Free().
Чтобы закрыть форму через ее меню - просто вызываем OnStop из обработчика пункта меню:
function onMenuExitClick()
OnStop()
end
Это же то, что и хотелось! Скрипт вполне корректно уживается внутри QUIK, реагируя на события, завершаясь по требованию и т.д.
Чуть сложнее пример
Попробуем добавить обработчик события и отображение информации из этого обработчика.
Например, в событии OnAllTrade будем суммировать объем всех сделок по двум инструментам: LKOH и SBER. Файл будет называться vcl-test-03.lua ([url=https://quik2dde.ru/static-img/26/vcl-test-03.lua]скачать[/url]).
require "vcl"
mainForm = VCL.Form("mainForm")
mainForm.Caption = "VCLua in QUIK"
mainForm._= { position="podesktopcenter", height=150, width=300}
mainMenu = VCL.MainMenu(mainForm,"mainMenu")
mainMenu:LoadFromTable({
{name="mmfile", caption="&File",
submenu={
{caption="Exit", onclick="onMenuExitClick", shortcut="Ctrl+F4"},
}
}
})
label = {}
label["SBER"] = VCL.Label(mainForm,"Label1")
label["LKOH"] = VCL.Label(mainForm,"Label2")
label["SBER"].Top = 10
label["SBER"].Left = 10
label["LKOH"].Top = 30
label["LKOH"].Left = 10
cnt = {}
cnt["LKOH"] = 0
cnt["SBER"] = 0
qty = {}
qty["LKOH"] = 0
qty["SBER"] = 0
val = {}
val["LKOH"] = 0
val["SBER"] = 0
function onMenuExitClick()
OnStop()
end
mainForm:Show()
is_run = true
function main()
while is_run do
sleep(50)
end
end
function OnStop()
is_run = false
mainForm:Free()
end
function OnAllTrade(trade)
if is_run == false then
return
end
if (trade.seccode == "LKOH") or (trade.seccode == "SBER") then
cnt[trade.seccode] = cnt[trade.seccode] + 1
qty[trade.seccode] = qty[trade.seccode] + trade.qty
val[trade.seccode] = val[trade.seccode] + trade.value
label[trade.seccode].Caption = trade.seccode .. " (" .. cnt[trade.seccode] .. ") " .. qty[trade.seccode] .. " = " .. val[trade.seccode]
end
end
Да оно отлично работает! В нашем окне выводится количество сделок (в скобках), суммарное количество лотов в сделках и суммарный объем сделок. Разумеется, все это подсчитывается только с начала работы скрипта.
Небольшие пояснения по коду. Первые три строчки в OnAllTrade нужны для того, чтобы предотвратить падения терминала после остановки скрипта (как известно, в версии 6.4 есть ошибка: обработчики вызываются и после завершения скрипта, приводя к падению терминала)
function OnAllTrade(trade)
if is_run == false then
return
end