1 (2019-07-16 14:31:01 отредактировано swerg)

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

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

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

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

Установка:
Положить файл w32.dll в каталог с QUIK (т.е. там, где info.exe).

  • Для QUIK версий 6.x и 7.x берём файл из каталога x32

  • Для QUIK версий 8.x и последующих берём файл из каталога x64

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

w32 = require("w32")

Собственно при сборке в исходном коде я ничего не поменял, лишь указал на использование qlua.dll вместе lua5.1.dll, поэтому для этой сборки никакие доп. библиотеки не понадобятся.

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

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

  • ShellOpen

  • FindWindow

  • FindWindowEx (новая)

  • SetFocus (новая)

  • GetWindowText (новая)

  • SetWindowText (новая)

  • GetWindowPos (новая)

  • RegisterHotKey

  • SetForegroundWindow

  • PostMessage

  • 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

  • OpenSCManager

  • OpenService

  • CloseServiceHandle

  • QueryServiceStatus

  • QueryServiceConfig

  • ControlService

  • DeleteService

  • StartService

  • mciSendString (новая)

  • Beep (новая)

  • MessageBeep (новая)

  • CoInitialize (новая)

  • CoUninitialize (новая)

2 (2017-05-03 09:57:44 отредактировано swerg)

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

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

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

По поводу использования самой функции mciSendString() есть отличная страничка с примерами (там не Lua, но это не важно, т.к. интересен формат текстовых строк с командами).

В отдельной теме приведен пример готовой функции PaySoundFile() для проигрывания звуковых файлов mp3, wav, midi из скриптов роботов на Lua. Важно отметить, что в приведенном там варианте робот не будет задерживаться на время проигрывания файла.

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

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

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

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

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

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

3 (2013-11-02 20:20:56 отредактировано swerg)

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

Поиск окон, автозаполнение полей, клик на кнопках
Небольшой пример поиска окон и ввода текста в поля диалога.
Скрипт автологина QUIK

4

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

< reserved >

5

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

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

6

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

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

7

Re: Вызов 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: Вызов WinAPI функций в Lua

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

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

Re: Вызов 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: Вызов 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: Вызов 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: Вызов WinAPI функций в Lua

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

13

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

Можно использовать функцию GetCursorPos() из vclua библиотеки.

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

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: Вызов WinAPI функций в Lua

swerg пишет:

Можно использовать функцию GetCursorPos() из vclua библиотеки.

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

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: Вызов WinAPI функций в Lua

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

16

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

swerg пишет:

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

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

17

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

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

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

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

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

18

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

GREEN_X5 пишет:

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

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

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

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

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

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

ilk пишет:

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

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

20

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

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

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

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

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

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

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

swerg пишет:

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

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

ilk пишет:

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

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

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

22

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

ilk пишет:

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

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

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

23

Re: Вызов 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: Вызов WinAPI функций в Lua

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

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

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

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

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

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

25

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

ilk пишет:

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

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

ilk пишет:

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

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

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