1 (2020-12-16 19:46:02 отредактировано swerg)

Тема: w32 - Вызов WinAPI функций из Lua

Если из скрипта робота понадобилось вызвать какие-либо функции WinAPI - проще всего взять готовую библиотеку-обертку.
Например, библиотеку w32 для Lua.

Библиотека есть в пакете LuaForWindows, но вариант на этом сайте содержит больше функций, кроме того содержит варианты для для QUIK 6-7 (Win32), QUIK 8 (Win64), QUIK 8.5 (Win64, Lua5.3), QUIK 8.11 (Win64, Lua5.4).

Загрузка (ссылки):

  • [url=https://quik2dde.ru/static-img/78/w32.dll.zip]архив с готовой библиотекой w32.dll[/url]

  • [url=https://github.com/swerg/qlua-w32]Исходники на GitHub[/url]

  • Для справки: [url=https://github.com/luaforge/w32wrappers]сайт проекта w32[/url]; на основании этих исходников была сделана библиотека, представленная на этом сайте

Установка:
Скачать архив с библиотекой по ссылке выше.
Скопировать файл w32.dll в каталог с QUIK (т.е. там, где info.exe).
В зависимости от используемой версии QUIK файл w32.dll взять из соответствующей папки архива:

  • \x32 - для QUIK версий 6.x и 7.x

  • \x64-Lua51 - для QUIK версий 8.0..8.4

  • \x64-Lua53 - для QUIK версий 8.5 и более новых

  • \x64-Lua54 - для QUIK версий 8.11 и более новых

Важно:
Для сборок Lua53 и Lua54 добавлена проверка версии Lua, указанной для запуска скрипта. Т.е. если вы взяли сборку библиотеки для Lua5.3, а запустили скрипт на Lua5.4, то увидите ошибку:
"multiple Lua VMs detected. Expected 5.3 instead of 5.4"
И наоборот, если взяли сборку библиотеки для Lua5.4, а запустили скрипт на Lua5.43, то увидите ошибку:
"multiple Lua VMs detected. Expected 5.4 instead of 5.3"

Как одновременно держать готовыми библиотеки и для Lua5.3 и для Lua5.4 - это надо придумывать. Можно разложить их в разные каталоги и настраивать в скрипте нужные пути поиска в зависимости о версии Lua, которую можно определить в скрипте из глобальной переменной _VERSION.

Использование:
В начало скрипта вставляем

w32 = require("w32")

По поводу сборки библиотеки на этом сайте.
Сначала изменения были минимальны: в исходном коде я ничего не менял, лишь указал на использование qlua.dll вместо lua5.1.dll, так удобнее в использовании. Также пересобрал библиотеку так, чтобы никакие доп. библиотеки не требовались для работы.
Позже библиотека была перекомпилирована для x64 платформы, т.к. QUIK с версии 8.х стал 64-битным.
С выходом QUIK 8.5 (где встроена Lua5.3) библиотеку модифицировал так, чтобы можно было собирать как вариант для Lua5.1, так и для Lua5.3.

Со временем в библиотеку были добавлены дополнительные функции, отсутствующие в ней изначально, которые оказались необходимы для задач автоматизации QUIK.

Справка (документация):
Порядок, типы и количество аргументов функций, включенных в эту библиотеку, совпадают с соответствующими оригинальными функциями WinAPI. Поэтому подробная справка здесь для большинства функций не приводится. Справку по аргументам функций можно получить в документации от Microsoft.

Список поддерживаемых функций:
Важно: если вы хотите использовать функции, отмеченные здесь как "добавлена" - то необходимо скачать сборку именно с этого сайта, т.к. такие функции есть только в сборке с этого сайта!

  • ShellOpen

  • FindWindow

  • FindWindowEx (добавлена)

  • SetFocus (добавлена)

  • GetWindowText (добавлена)

  • SetWindowText (добавлена)

  • GetWindowPos (добавлена)

  • RegisterHotKey

  • SetForegroundWindow

  • PostMessage

  • SendMessage (добавлена)

  • PostThreadMessage

  • GetMessage

  • PeekMessage

  • ReplyMessage

  • DispatchMessage

  • SetTopmost

  • GetLastError

  • CloseHandle

  • CreateEvent

  • OpenEvent

  • PulseEvent

  • ResetEvent

  • SetEvent

  • CreateMutex

  • OpenMutex

  • ReleaseMutex

  • CreateSemaphore

  • OpenSemaphore

  • ReleaseSemaphore

  • CreateProcess

  • GetTempFileName

  • GetTempPath

  • CreateFile

  • ReadFile

  • WriteFile

  • TerminateProcess

  • GetExitCodeProcess

  • WaitForSingleObject

  • WaitForMultipleObjects

  • GetCurrentThreadId

  • RegisterWindowMessage

  • RegQueryValueEx

  • RegSetValueEx

  • RegDeleteKey

  • RegDeleteValue

  • RegEnumKeyEx

  • RegEnumValue

  • SetCurrentDirectory

  • SHDeleteKey

  • Sleep

  • GetVersion

  • FindFirstFile

  • FindNextFile

  • FindClose

  • SHGetSpecialFolderLocation

  • GetFullPathName

  • IsUserAdmin

  • OpenProcess

  • IsRunning

  • GetWindowThreadProcessId

    • threadId, processId = w32.GetWindowThreadProcessId(handleWindow)

  • OpenSCManager

  • OpenService

  • CloseServiceHandle

  • QueryServiceStatus

  • QueryServiceConfig

  • ControlService

  • DeleteService

  • StartService

  • mciSendString (добавлена)

  • Beep (добавлена)

  • MessageBeep (добавлена)

  • CoInitialize (добавлена)

  • CoUninitialize (добавлена)

  • GetUserName (добавлена)

  • GetCurrentProcessId (добавлена)

  • CloseWindow (добавлена)

  • IsWindowVisible (добавлена)

  • TabCtrl_GetItemCount (добавлена)

  • TabCtrl_SetCurFocus (добавлена)

  • TabCtrl_SetCurSel (добавлена)

  • TabCtrl_GetItemText (добавлена)

    • text = w32.TabCtrl_GetItemText(TabCtrlHwnd {, idx})

    • Если idx не задан - возвращается текст для текущей активной вкладки.

    • При ошибке возвращает nil

  • TabCtrl_GetItemIndexByText (добавлена)

    • idx = w32.TabCtrl_GetItemIndexByText(text)

    • Возвращает индекс вкладки по названию.

    • Если вкладка с таким названием не найдена - возвращает -1.

  • TabCtrl_GetCurSel (добавлена)

  • TabCtrl_GetCurFocus (добавлена)

2 (2020-11-18 08:03:02 отредактировано swerg)

Re: w32 - Вызов WinAPI функций из Lua

Примеры использования библиотеки w32 в QUIK

1. Поиск окон, автозаполнение полей, клик на кнопках
Скрипт автологина можно рассматривать как пример поиска окон и ввода текста в поля диалога.
[url=https://quik2dde.ru/viewtopic.php?id=80]Скрипт автологина QUIK[/url]

2. Поиск окон, автозаполнение полей, клик на кнопках
Сейчас в QUIK нет средств для создания пользовательских таблиц на определённых вкладках. Пример ниже показывает как такую задачу можно решить.
[url=https://quik2dde.ru/viewtopic.php?id=329]Создание пользовательских таблиц из QLua-скрипта на определённых вкладках[/url]

3 (2021-01-24 21:27:09 отредактировано swerg)

Re: w32 - Вызов WinAPI функций из Lua

Проигрывание звуковых файлов из Lua

Для проигрывания звуковых файлов - "по совету друзей" (Siluyano, спасибо!) - добавил в библиотеку функцию mciSendString(). В данной реализации она принимает лишь 1 строковый параметр, все равно остальные параметры из Lua задействовать не просто, да и ни к чему они для наших задач.

По поводу использования самой функции mciSendString() есть [url=http://free-basic.ru/mcisendstring.html]отличная страничка с примерами[/url] (там не Lua, но это не важно, т.к. интересен формат текстовых строк с командами).

В отдельной теме [url=https://quik2dde.ru/viewtopic.php?id=79]приведен пример готовой функции PaySoundFile()[/url] для проигрывания звуковых файлов mp3, wav, midi из скриптов роботов на Lua. Важно отметить, что в приведенном там варианте робот не будет задерживаться на время проигрывания файла.

Стандартные звуки, настроенные в Windows

Можно скрипт робота заставить проиграть один из стандартных звуков, настроенных в Windows. Для этого отлично подойдет функция MessageBeep(). Ниже пример использования. Возможные варианты параметров см. в MSDN.

w32=require("w32")
w32.MessageBeep(w32.MB_OK)
"Аларм" встроенным динамиком

Еще есть вариант издавать звуки определенной частоты и длительности встроенным динамиком компьютера, для этого есть функция Beep(). Удобно для "резких" сигналов (громкость не регулируется), привлекающих внимание. (Встроенный динамик в этом способе используется только до WinXP, в следующих версиях Windows звук воспроизводится уже через звуковую карту, но работает всё точно также.)
Важно: на время проигрывания звука данным способом работа Lua-скрипта  приостанавливается!

Пример восходящего и нисходящего арпеджио:

w32=require("w32")

poluton = 2 ^ (1/12)

-- определим константами частоты гармонического звукоряда
A1 = 440
B1 = A1 * (poluton ^ 2)
C1 = A1 * (poluton ^ 3)
D1 = A1 * (poluton ^ 5)
E1 = A1 * (poluton ^ 7)
F1 = A1 * (poluton ^ 8)
G1 = A1 * (poluton ^ 10)
A2 = A1 * (poluton ^ 12)
B2 = A1 * (poluton ^ 14)
C2 = A1 * (poluton ^ 15)

-- играем звуки вверх
music1 = {C1, E1, G1, C2}
for i, tone in ipairs(music1) do
  w32.Beep(tone, 100)
end

sleep(300)

-- играем звуки вниз
music2 = {C2, G1, E1, C1}
for i, tone in ipairs(music2) do
  w32.Beep(tone, 100)
end

4

Re: w32 - Вызов WinAPI функций из Lua

< reserved >

5

Re: w32 - Вызов WinAPI функций из Lua

Буду благодарен за примеры использования вообще и полезного в частности данной библиотеки для решения различных задач автоматизации QUIK

6

Re: w32 - Вызов WinAPI функций из Lua

Ёшкин кот!! Вотэто тема! Уже скачал, буду запускать quik и начинать копаться.
swerg, сообщения из семейства WM_ было бы неплохо заиметь в этой библиотеке.
В списке функций присутствует RegisterHotKey, но отсутствует не только UnregisterHotKey, но и функции для работы с атомами (GlobalAddAtom и GlobalDeleteAtom).
Ещё ребята пропустили FindWindowEx, это всё равно что, если бы они добавили только FindFirstFile, а FindNextFile и FindClose не стали добавлять.

7

Re: w32 - Вызов WinAPI функций из Lua

Пример поиска окна QUIK.
------
stopped = false

w32=nil
w32 = require ("w32")

hWnd = 0

function main(  )
hWnd = w32.FindWindow("InfoClass", "")
message("hWnd= "..tostring(hWnd),1)
while not stopped do
  sleep(100)
end
end

8

Re: w32 - Вызов WinAPI функций из Lua

swerg, возможно неплохая идея возможность проигрывать звуковые файлы - mciSendString.
И на случай если звук нужен, но нет колонок Beep (ByVal dwFreq As Long, ByVal dwDuration As Long). Робот, допустим, когда хочет вривлечь внимание инвестора к терминалу.

9 (2013-11-02 20:22:37 отредактировано swerg)

Re: w32 - Вызов WinAPI функций из Lua

Про FindWindowEx вы правы, сам удивился. Ну видно, что у автора какие-то свои задачи стояли: сервисы, реестр, самостоятельная полная GUI прога с созданием окон и обработкокой сообщений. Сужу по набору функций.
А про звук - отличная идея!

Про поиск окна - вы верно подметили, что надо вместо NULL пустую строку передавать, хотя константа NULL как раз определена.

PS
Добавил несколько функций:

  • FindWindowEx

  • SetFocus

  • GetWindowText - возвращает строку или nil при ошибке

  • SetWindowText

  • GetWindowPos - возвращает координаты окна left, top, right, bottom или nil при ошибке

  • mciSendString - принимает только 1 параметр, описание есть в теме выше

  • Beep

  • MessageBeep

  • CoInitialize

  • CoUninitialize

Про сообщения пока думаю: какие добавить, все как-то не хочется...

10

Re: w32 - Вызов WinAPI функций из Lua

Упростил вызов мьюзик до одной команды, всё работает
С++

static int Play(lua_State *L) {
    const char *cmd = luaL_checkstring( L, 1);
    char s1[90]="play ";
    char s2[90]="";
    strcat(s2,cmd);
    strcat(s1,s2);
    mciSendString(s1, NULL, 0, NULL);
    return 0;
}

Вызов

w32.Play(getScriptPath().."\\sound.wav")

Исследования:
mciSendString и MessageBeep действительно не останавливают qlua скрипт на время проигрывания файла. Факт. время обработки:
mciSendString примерно 140 msec для wav файлов и 200 msec для mp3 файлов не зависимо от размера файлов
MessageBeep <1 msec
Для скоростных скриптов выбор очевиден - MessageBeep.
Вариантов для W7 нашел пока три:
С++

static struct {
        char    *name;
        DWORD   value;
    } consts[] = {
        //WOW
        {"MB_ICONWARNING", MB_ICONWARNING},
        {"MB_ICONEXCLAMATION", MB_ICONEXCLAMATION},
        //PLIM
        {"MB_ICONINFORMATION", MB_ICONINFORMATION},
        {"MB_ICONASTERISK", MB_ICONASTERISK},
        //BEMM
        {"MB_ICONSTOP", MB_ICONSTOP},
        {"MB_ICONERROR", MB_ICONERROR},
        {"MB_ICONHAND", MB_ICONHAND},

        {NULL,0}
};

11 (2014-12-24 17:38:29 отредактировано AgentSmit)

Re: w32 - Вызов WinAPI функций из Lua

Нажатие на кнопках "Установить связь с..." и "Разорвать связь с..."

    -- константа из windows.h
    local WM_COMMAND = 0x0111
    -- поиск главного окна
    hWnd = w32.FindWindow("InfoClass","")
    -- нажимаем кнопку
    w32.PostMessage(hWnd,WM_COMMAND,100,0)

w32.PostMessage(hWnd,WM_COMMAND,100,0) -- нажать на кнопку "Установить связь с..."
w32.PostMessage(hWnd,WM_COMMAND,101,0) -- нажать на кнопку "Разорвать связь с..."

12

Re: w32 - Вызов WinAPI функций из Lua

может кто подскажет, нужна функция типа x,y=GetMousePos()
почти все библиотеки обшарил в луа не нашел sad

13

Re: w32 - Вызов WinAPI функций из Lua

Можно использовать функцию GetCursorPos() из [url=https://quik2dde.ru/viewtopic.php?id=111]vclua библиотеки[/url].

Этот скрипт будет раз в пол-секунды выводить абсолютные координаты курсора мыши:

VCL = require "qvcl"

is_run = true    
function main()
  while is_run do
    local x,y = VCL.GetCursorPos()
    message('x='..tostring(x)..' y='..tostring(y))
    sleep(500)
  end
end
function OnStop()
 is_run = false
end

В примере идет обращение к vcl из main().
Здесь это безопасно, т.к. данная функция обращается только в read-only режиме к внутренним объектам библиотеки vcl, в общем же случае не надо забывать, что обращение к визуальным элементам, созданным через vcl из main() недопустимо.

14 (2015-03-19 08:07:23 отредактировано ilk)

Re: w32 - Вызов WinAPI функций из Lua

swerg пишет:

Можно использовать функцию GetCursorPos() из [url=https://quik2dde.ru/viewtopic.php?id=111]vclua библиотеки[/url].

Этот скрипт будет раз в пол-секунды выводить абсолютные координаты курсора мыши:

VCL = require "qvcl"

is_run = true    
function main()
  while is_run do
    local x,y = VCL.GetCursorPos()
    message('x='..tostring(x)..' y='..tostring(y))
    sleep(500)
  end
end
function OnStop()
 is_run = false
end

В примере идет обращение к vcl из main().
Здесь это безопасно, т.к. данная функция обращается только в read-only режиме к внутренним объектам библиотеки vcl, в общем же случае не надо забывать, что обращение к визуальным элементам, созданным через vcl из main() недопустимо.

Спасибо!
Дописал на cpp в dll в указаном примере luacdll
может кому нужно..

static int forLua_GetCursorPos(lua_State *L) {
    POINT Mouse;
    bool rc=GetCursorPos(&Mouse);
    if (!rc) {
        lua_pushnil( L);
        return( 1);
    }
    else {
        lua_pushinteger( L, Mouse.x);
        lua_pushinteger( L, Mouse.y);
        return( 2);
    }
}

работает в квике :-)

lua скрипт

require("luacdll")
function main(  )
x,y = luacdll.GetCursorPos()
message("now:\nx = "..x.."\ny = "..y,1)
end


чем больше изучаю, тем больше нравится Lua :-)

15

Re: w32 - Вызов WinAPI функций из Lua

А можете рассказать с какой целью такая функция сама по себе могла понадобиться?

16

Re: w32 - Вызов WinAPI функций из Lua

swerg пишет:

А можете рассказать с какой целью такая функция сама по себе могла понадобиться?

вот возникла мысль, а сколько пикселей в 5 минутах на 5минутном интервале и других интервалах, квиковцы ничего не говорят по этому поводу, опять же возникают вопросы различные автомасштабирование и т.д, они же не от балды рисуют графики (Price интервал и т.д) какие то зависимости есть по отношению к истинным значениям экрана, да и изучаю lua...

17

Re: w32 - Вызов WinAPI функций из Lua

ilk пишет:
swerg пишет:

А можете рассказать с какой целью такая функция сама по себе могла понадобиться?

вот возникла мысль, а сколько пикселей в 5 минутах на 5минутном интервале и других интервалах, квиковцы ничего не говорят по этому поводу, опять же возникают вопросы различные автомасштабирование и т.д, они же не от балды рисуют графики (Price интервал и т.д) какие то зависимости есть по отношению к истинным значениям экрана, да и изучаю lua...

Вам поэтому и задали вопрос - зачем вам эта функция. Она в ваших целях практически бесполезна, потому что Квик рисует свои графики не "от балды", а на своём "полигоне", наведя на него мышь, вы снимите только координату на мониторе, ни цены, ни чего либо другого так стабильно получать не получится.
Изначально вы не обозначили итоговую задачу. Как можно догадаться, вы возможно хотите ткнуть мышкой на какой то уровень на свечке и получить в скрипт цену. И возможно - время свечи. Как вариант реализации - через qvcl рисуете (воспроизводите) на окне-форме последнюю свечу (или несколько, если нужно), и тыкая или наводя мышь уже туда - получаете цену и время начала свечи. Вариантов рисования "копии свечи" множество, например закрашивание ячеек Grid с бесцветными границами ячеек, или два прямоугольника (один узкий для H и L, второй пошире, для O и С).

18

Re: w32 - Вызов WinAPI функций из Lua

GREEN_X5 пишет:

Квик рисует свои графики не "от балды", а на своём "полигоне", наведя на него мышь, вы снимите только координату на мониторе, ни цены, ни чего либо другого так стабильно получать не получится.

Вот про этот "полигон" ничего не известно..., даже элементарное, угол наклона кривой (допустим MA) нельзя практически вычислить в квике, хотя в МТ4 это делают спокойно.

19 (2015-03-19 12:59:05 отредактировано swerg)

Re: w32 - Вызов WinAPI функций из Lua

Угол наклона кривой?! это как?
По известным координатам (а координаты МА нам известны по определению) легко вычислить угол на основании школьных знаний 6-го класса (ну или 7-го) по геометрии.

И вы так и не написали какую задачу вообще-то пытаетесь решить.

ilk пишет:

вот возникла мысль, а сколько пикселей в 5 минутах на 5минутном интервале и других интервалах, квиковцы ничего не говорят по этому поводу,

От одного пикселя до тысячи в зависимости от установленного вами масштаба.
Даже интересно какого ответа вы предполагаете ожидать от квиковцев.

20

Re: w32 - Вызов WinAPI функций из Lua

ilk пишет:
GREEN_X5 пишет:

Квик рисует свои графики не "от балды", а на своём "полигоне", наведя на него мышь, вы снимите только координату на мониторе, ни цены, ни чего либо другого так стабильно получать не получится.

Вот про этот "полигон" ничего не известно..., даже элементарное, угол наклона кривой (допустим MA) нельзя практически вычислить в квике, хотя в МТ4 это делают спокойно.

Ну так смиритесь с этим как с данностью, КВИК самодостаточен как терминал, да ещё и с LUA, творите дальше всё что хотите, инструменты есть, путь я подсказал.

21 (2015-03-19 13:17:06 отредактировано ilk)

Re: w32 - Вызов WinAPI функций из Lua

swerg пишет:

Угол наклона кривой?! это как?
По известным координатам (а координаты МА нам известны по определению) легко вычислить угол на основании школьных знаний 6-го класса (ну или 7-го) по геометрии.

И вы так и не написали какую задачу вообще-то пытаетесь решить.

ilk пишет:

вот возникла мысль, а сколько пикселей в 5 минутах на 5минутном интервале и других интервалах, квиковцы ничего не говорят по этому поводу,

От одного пикселя до тысячи в зависимости от установленного вами масштаба.
Даже интересно какого ответа вы предполагаете ожидать от квиковцев.

Конечно элементарно,  m=(у2-y1)/(x2-x1)=tag angle или angle=arctang (m).
Так вот имеем координаты по У = Price координаты по x= время  .
Задача определить угол машки по отношению к окну где рисуется график .  :-)

22

Re: w32 - Вызов WinAPI функций из Lua

ilk пишет:

Конечно элементарно,  m=(у2-y1)/(x2-x1)=tag angle или angle=arctang (m).

Верно.
При этом вычислить у2, y1, x2 и x1 для МА - столь же элементарная формула, на основании данных свечек, которе нам в Lua-скрипте уже доступны.
Взять данные свечей, вычислить по ним МА (что очень просто), вычислить угол - и вуа-ля! Задача решена.
Это ведь то, что нужно?

PS
И всё же, МА-шка - это кривая.
Вы можете пояснть что такое "угол наклона кривой"?

23

Re: w32 - Вызов WinAPI функций из Lua

swerg пишет:
ilk пишет:

Конечно элементарно,  m=(у2-y1)/(x2-x1)=tag angle или angle=arctang (m).

Верно.
При этом вычислить у2, y1, x2 и x1 для МА - столь же элементарная формула, на основании данных свечек, которе нам в Lua-скрипте уже доступны.
Взять данные свечей, вычислить по ним МА (что очень просто), вычислить угол - и вуа-ля! Задача решена.
Это ведь то, что нужно?

т.е размеры окна в писелях,см,дюйм а Y=Price, X=время,  вычитаем Price2-Price1 и делим на разность Time2-Time2, берем арктангенс и получаем угол? :-)

24 (2015-03-19 14:15:54 отредактировано ilk)

Re: w32 - Вызов WinAPI функций из Lua

swerg пишет:
ilk пишет:

Конечно элементарно,  m=(у2-y1)/(x2-x1)=tag angle или angle=arctang (m).

Верно.
При этом вычислить у2, y1, x2 и x1 для МА - столь же элементарная формула, на основании данных свечек, которе нам в Lua-скрипте уже доступны.
Взять данные свечей, вычислить по ним МА (что очень просто), вычислить угол - и вуа-ля! Задача решена.
Это ведь то, что нужно?

PS
И всё же, МА-шка - это кривая.
Вы можете пояснть что такое "угол наклона кривой"?

касательная в точке кривой = угол наклона
каждую кривую можно построить прямыми отрезками.

тут вы правы, опечатка.

25

Re: w32 - Вызов WinAPI функций из Lua

ilk пишет:

касательная в точке кривой = угол наклона

Т.е. речь таки про угол наклона касательной.
Ну ok, тогда понятно. А то я волновался.

ilk пишет:

т.е размеры окна в писелях,см,дюйм а Y=Price, X=время,  вычитаем Price2-Price1 и делим на разность Time2-Time2, берем арктангенс и получаем угол? :-)

Вы меня не поняли.
Я предлагаю уйти от визуального отображения МА вообще, зачем оно вам?
В Lua-скрипте получаете параметры свечей, вычисляете значение МА (в рублях), время свечей известно (причем ось времени - это точно горизонталь, совпадающая с "окном графика").

Вы зачем-то привязываетесь к визуальному отображению графика, к пикселям... Но это ведь не нужно.