26

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

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

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

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

ilk пишет:

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

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

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

так вот я так и делал, но на форуме квиковцев почему то сказали это не верно, надо переводить в пиксели, см и т.д

27 (2015-03-19 14:30:06 отредактировано swerg)

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

Ну вы же в силах нарисовать картинку и понять что вам на самом деле надо.
Кстати, при изменении горизонтального масштаба - угол наклона касательной будет изменяться.
Вопрос: а как вы с этим предполагаете жить? какой масштаб (а значит и угол) истинный, когда проводить измерения?

28

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

swerg пишет:

Ну вы же в силах нарисовать картинку и понять что вам на самом деле надо.
Кстати, при изменении горизонтального масштаба - угол наклона касательной будет изменяться.
Вопрос: а как вы с этим предполагаете жить? какой масштаб (а значит и угол) истинный, когда проводить измерения?

Вот, вот. На таймфрейме 5 минут есть угол, а на таймфрейме недельном горизонтально! :-)
Все равно спасибо, за разъяснения!

29 (2016-09-29 11:30:35 отредактировано sam063rus)

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

-

30

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

sam063rus пишет:

так вот я так и делал, но на форуме квиковцев почему то сказали это не верно, надо переводить в пиксели, см и т.д

если можно - то, приведите ссылку про этот разговор. заинтересовало...)))

да это было очень давно, до эпохи Клуа.
[url]http://forum-archive.quik.ru/forum/qpile/85391/[/url]

31

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

Помогите пожалуйста нажать одну из этих кнопок

http://i.imgur.com/TgXbgal.png

if w32.FindWindow("", "QUIK: окно сообщений") then
   w32.SetFocus(???);
   w32.PostMessage(???, w32.BM_CLICK, 0, 0);
 end

32

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

hMsgWnd = w32.FindWindow("", "QUIK: окно сообщений")
w32.PostMessage(hMsgWnd, 16, 0, 0)

16 - это WM_CLOSE
Значение hMsgWnd можно и не проверять, если даже окна такого нет - ничего не случится.

Надо будет функцию CloseWindow добавить в библиотеку.

33

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

Подскажите, как узнать размер экрана, на разных мониторах приходится ручками забивать.

34 (2015-06-25 22:18:43 отредактировано sam063rus)

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

_

35

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

sam063rus пишет:
hMsgWnd = w32.FindWindow("", "QUIK: окно сообщений")

боюсь, что такой номер прокатит лишь с окнами верхнего уровня.

Такой метод не подходит, не люблю огороды с детства. Можно конечно сориентироваться по координатам окна авторизации квик (оно точно центровано на любом мониторе) и от них раскидать на Qtable или MyForm. Но что-то мне такой подход не очень нравится, да и функционал масштабирования по заполнению таблиц уже сделал. Сто пудов натыкался сегодня на функции С, но как их прикрутить...

36 (2016-09-29 11:46:28 отредактировано sam063rus)

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

-

37

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

[url]http://www.pisoft.ru/verstak/desktopsize.htm[/url]

38 (2015-06-20 01:06:14 отредактировано kalikazandr)

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

спасибо, GREEN_X5, то что нужно. GetSystemMetrics - не нашел нужного индекса в описании.

39

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

Пытаюсь запустить примеры из этой ветки.
Выдаёт такую вещь:C:\Program Files\QUIK-Junior\luacom.lua:2: attempt to call global 'loadlib' (a nil value)

40

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

AlexZZZ пишет:

Пытаюсь запустить примеры из этой ветки.
Выдаёт такую вещь:C:\Program Files\QUIK-Junior\luacom.lua:2: attempt to call global 'loadlib' (a nil value)

Какой именно пример, код приведите.

41 (2016-02-08 01:00:58 отредактировано CyberTrader)

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

1. Подскажите, можно ли найти окно по фрагменту его заголовка?

2. Если запущено несколько терминалов QUIK, то код

hWnd = w32.FindWindow("InfoClass", "")

может вернуть дескриптор другого окна. Как указать, чтоб скрипт искал дескриптор только родительского процесса?

42 (2016-08-03 00:45:54 отредактировано kalikazandr)

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

swerg пишет:

Поиск окон, автозаполнение полей, клик на кнопках

http://s018.radikal.ru/i502/1608/99/13ba69e70e57.png

Как получить доступ к тексту сообщения? Спасибо.
Вот тут подсказали [url]http://quikluacsharp.ru/[/url]:

function FindOrderText()
  hWnd = w32.FindWindow("", "Замена заявки")
  local h = w32.FindWindowEx(hWnd, 0, "", "")
  local hw = w32.FindWindowEx(hWnd, h, "", "")
  return w32.GetWindowText(hw)
end

43 (2017-08-20 21:22:24 отредактировано DanP)

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

swerg большое Вам спасибо за работу!

Жаль что приходится реанимировать старую тему, но считаю, что полезнее будет написать здесь, чем создавать новую.

по аналогии со скриптом автологина, хочу сделать скрипт, который будет пере/запускать основной рабочий скрипт в случае его остановки, например из-за ошибки.

предполагаемая схема действия следующая:
1) основной рабочий скрипт при запуске пишет в файл переключатель время старта и статус "ON" + каждую минуту пишет вспомогательный лог-статус, который перестает обновляться при остановке скрипта.
2) вспомогательный скрипт 1 следит за изменением лог-статуса и при отсутствии изменений в нем в рабочее время рынка пишет в файл переключатель время остановки основного скрипта и статус "OFF"
3) вспомогательный скрипт 2 (автозапуск) читает файл-переключатель и при получении в последней строке состояния значения "OFF" пере/запускает основной скрипт.

основной скрипт работает на больших ТФ, поэтому отслеживание статусов раз в 1-2 минуты не критично.

в примере скрипта для автологина позиционирование на окне авторизации использует поиск родительского окна FindWindow, окно "Доступные скрипты" в терминале quik является дочерним, и с помощью FindWindowEx найти его получилось только после нескольких итераций вложенных циклов.

к сожалению не могу разобраться как выбрать/активировать один конкретный скрипт из списка загруженных, поэтому пока перезапускаются все скрипты с помощью кнопок "Выбрать все" и "Запустить", что не очень удобно.

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

Заранее большое спасибо за помощь!

полный текст скрипта:

[+]Spoiler


-- перезапуск скрипта в терминале QUIK
-- Версия: 1.0

R_NAME = "MAIN_SCRIPT_NAME"; -- скрипт работу, которого отслеживает данный вспомогательный робот
local w32 = require("w32");
--local WM_COMMAND = 0x0111 -- константа из windows.h

timeout = 10000;  -- таймаут между проходами основного цикла
is_run = true;

function OnInit()
    LOG_DATE = DateConvertion(); --getInfoParam("TRADEDATE")
    SWCH_FILE= "\\"..R_NAME.."_"..LOG_DATE.."_swch.txt"; -- файл переключатель
    LOG_FILE = "\\"..R_NAME.."_"..LOG_DATE.."_swch_log.txt"; -- файл для записи лога событий

-- подготовка тестового лог файла для записи событий удалить после отладки
    log = io.open(getScriptPath()..LOG_FILE,"r+");-- Пытается открыть файл в режиме "чтения/записи"
    if log == nil then -- Если файл не существует
        log = io.open(getScriptPath()..LOG_FILE,"w"); -- Создает файл в режиме "записи"
        log:close(); -- Закрывает файл
        log = io.open(getScriptPath()..LOG_FILE,"r+");-- Открывает уже существующий файл в режиме "чтения/записи"
    end;
    log:seek("end",0);
    log:write("log file opened "..os.date("%X").."\n"); -- "\n" признак конца строки
--********************** конец подготовки лог файла удалить после отладки
    -- подготовка файла переключателя
    SWCH_log = io.open(getScriptPath()..SWCH_FILE,"r+");
    if SWCH_log == nil then -- Если файл не существует
        SWCH_log = io.open(getScriptPath()..SWCH_FILE,"w"); -- Создает файл в режиме "записи"
        SWCH_log:close();-- Закрывает файл
        SWCH_log = io.open(getScriptPath()..SWCH_FILE,"r+");-- Открывает уже существующий файл в режиме "чтения/записи"
        SWCH_log:seek("end",0); --позиционирует курсор на конец файла
        SWCH_log:write(os.date("%X")..";OFF".."\n"); -- дописывает состояние по умолчанию
    end;
    SWCH_log:flush();
    SWCH_log:close();
---------------------------------------

     T_DP = { -- waiting periods table start-stop
        ["00:00:01"]="09:55:10", --
        ["13:59:55"]="14:01:00", -- morning clearing time - с лагом
        ["18:49:59"]="19:01:00", -- evening clearing time  - с лагом
        ["20:38:00"]="23:59:59", --
    };
   
    ServDate=getInfoParam("TRADEDATE"); -- получаем дату сервера в формате дд/мм/гггг
end;

function main()
    while is_run do
        ServTimeSec = os.time(os.date("*t")); -- конвертируем текущее время сервера из таблицы в секунды
        local waiting = false;
        for k,v in pairs(T_DP) do -- выключаем работу в период клиринга и периоды вне рабочего времени
            if k~=nil then
                StartSec = os.time(TimeConvertion(ServDate,tostring(k))); -- конвертируем время начала паузы в секунды
                StopSec = os.time(TimeConvertion(ServDate,tostring(v))); -- конвертируем время конца паузы в секунды
                if StopSec>ServTimeSec and  ServTimeSec> StartSec  then
                    waiting = true;
                end;
            end;
        end;   
        if not waiting then
            local MainScriptOff=false;
            -- открывает файл переключатель для чтения
            local TP = io.open(getScriptPath()..SWCH_FILE,"r");
            local k=0;
            for LINE in TP:lines() do
                k=k+1; -- счетчик строк
            end;
            TP:close(); -- Закрывает файл переключатель
            local TP = io.open(getScriptPath()..SWCH_FILE,"r");
            local i=0;
            for LINE in TP:lines() do
                i=i+1; -- счетчик строк
                local a=0;
                if k>1 then
                    a = k-1;
                else
                    a=k;
                end;
                if i==a then
                -- в последней строке файла переключателя по разделителю определяем наличие данных
                    local POS = string.find(LINE,";");
                    if POS ~= nil then
                        local j = LINE:len();
                        local i = POS;
                        local STATE = LINE:sub(i+1,j);
                        --log:write(STATE.."\n");
                        if STATE=="OFF" then
                            MainScriptOff=true;
                        end;
                    end;
                end;
            end;
            TP:close(); -- Закрывает файл переключатель

       
            if MainScriptOff then
                local hScriptWnd = FindScriptWindow();
                local nBtnSlctAll=0;
                local nBtnRun=0;
                local nBtnStop=0;
                local nBtnDel=0;
                local hLdScr=0;
                if hScriptWnd ~= 0 then
                    local hChldWnd=0;
                    for     k=0,1 do
                        hChldWnd = w32.FindWindowEx(hScriptWnd, hChldWnd, "", "");
                        if hChldWnd~=0 then
                            local wndt = w32.GetWindowText(hChldWnd,wndt,256);
                            --log:write(" hChldWnd "..hChldWnd.." hChldWnd text "..tostring(wndt).."\n");
                            local hSChldWnd=0;
                            for     i=0,1 do
                                hSChldWnd = w32.FindWindowEx(hChldWnd, hSChldWnd, "", "");
                                if hSChldWnd~=0 then
                                    local wndt = w32.GetWindowText(hSChldWnd,wndt,256);
                                    --log:write("i"..i.." hSChldWnd "..hSChldWnd.." hSChldWnd text "..tostring(wndt).."\n");
                                    local hS2ChldWnd=0;
                                    for     j=0,10 do
                                        hS2ChldWnd = w32.FindWindowEx(hSChldWnd, hS2ChldWnd, "", "");
                                        if hS2ChldWnd~=0 then
                                            local wndt = w32.GetWindowText(hS2ChldWnd,wndt,256);
                                            --log:write("j"..j.." hS2ChldWnd "..hS2ChldWnd.." hS2ChldWnd text "..tostring(wndt).."\n");
                                            if wndt=="Run" or  wndt=="Запустить" then
                                                nBtnRun=hS2ChldWnd;
                                                log:write("nBtnRun "..nBtnRun.." nBtnRun text "..tostring(wndt).."\n");
                                            elseif wndt=="Stop" or  wndt=="Остановить" then
                                                nBtnStop=hS2ChldWnd;
                                                log:write("nBtnStop "..nBtnStop.." nBtnStop text "..tostring(wndt).."\n");
                                            elseif wndt=="Select all" or  wndt=="Выделить все" then
                                                nBtnSlctAll=hS2ChldWnd;
                                                log:write("nBtnSlctAll "..nBtnSlctAll.." nBtnSlctAll text "..tostring(wndt).."\n");
                                            elseif wndt=="Loaded scripts" or  wndt=="Загруженные скрипты" then
                                                hLdScr=hS2ChldWnd;
                                                log:write("hLdScr "..hLdScr.." hLdScr text "..tostring(wndt).."\n");
                                            elseif wndt=="Delete" or  wndt=="Удалить" then
                                                nBtnDel=hS2ChldWnd;
                                                log:write("nBtnDel "..nBtnDel.." nBtnDel text "..tostring(wndt).."\n");
                                            end;

                                        end;
                                    end;
                                end;
                            end;
                        end;
                    end;

                    w32.SetFocus(nBtnSlctAll); -- кнопка выбрать все
                    w32.PostMessage(nBtnSlctAll, w32.BM_CLICK, 0, 0);
                    w32.SetFocus(nBtnRun); --кнопка запустить
                    w32.PostMessage(nBtnRun, w32.BM_CLICK, 0, 0);
                   

--[[                -- нерабочая часть - нужно выбрать конкретный скрипт для запуска
                    if hLdScr~=0 then
                        for     k=0,10 do
                            hChldWnd = w32.FindWindowEx(hLdScr, hChldWnd, "", "");
                            if hChldWnd~=0 then
                                local wndt = w32.GetWindowText(hChldWnd,wndt,256);
                                log:write("hLdScr hChldWnd "..hChldWnd.." hChldWnd text "..tostring(wndt).."\n");
                            end;
                        end;
                    end;
]]
--[[                -- функции из автологина
                    hWnd = w32.FindWindow("InfoClass",""); -- поиск главного окна
                    -- нажимаем кнопку
                    w32.PostMessage(hWnd,WM_COMMAND,100,0) -- нажать на кнопку "Установить связь с..."
                    -- w32.PostMessage(hWnd,WM_COMMAND,101,0) -- нажать на кнопку "Разорвать связь с..."
                    --w32.SetWindowText(hLogin, QUIK_LOGIN);
                    --w32.SetWindowText(nPassw, QUIK_PASSW);
]]   
                end;

--[[            -- для тестов ставим переключатель здесь, в рабочем режиме переключатель в ON ставит основной скрипт при запуске
                local TP = io.open(getScriptPath()..SWCH_FILE,"r+");
                TP:seek("end",0);
                TP:write(os.date("%X")..";ON".."\n");
                TP:flush();
                TP:close();
]]               
            end;
        end;
        sleep(timeout);
    end;
    log:flush();
    log:close();
end;

function OnStop()
    timeout = 1;
    is_run = false;
end;

function TimeConvertion(CDate, CTime) -- конвертирует текстовый формат даты и времени в таблицу datetime
    if CDate == nil or CDate == 0 then -- если при вызове функции дата не указана - то берем текущую
        --[[ функция os.date("%x") возвращает дату в формате мм/дд/гг, что не соотвествует
             формату getInfoParam('TRADEDATE') дд/мм/гггг, поэтому форматируем вручную
        ]]    
        CDate = getInfoParam('TRADEDATE');
        if CDate == 0 then
            local day = (os.date("%d"));
            local month = (os.date("%m"));
            local year = (os.date("%Y"));
            CDate = day.."/"..month.."/"..year;
        end;
    end;
    if CTime == nil or CTime == 0 then
        CTime = getInfoParam('SERVERTIME'); -- если при вызове функции время не указано - то берем текущее
        if CTime == 0 then
            CTime = os.date("%X");
        end;
    end;
-- преобразуем дату/время в таблицу вида datetime
    local dt = {};
    dt.day,dt.month,dt.year,dt.hour,dt.min,dt.sec = string.match(CDate..' '..CTime,"(%d*).(%d*).(%d*) (%d*):(%d*):(%d*)");
    for key,VALUE in pairs(dt) do dt[key] = tonumber(VALUE) end;
    return dt; -- таблица вида datetime
end;

function DateConvertion() -- форматирует дату в текстовое значение
    local day = (os.date("%d"));
    local month = (os.date("%m"));
    local year = (os.date("%Y"));
    ConvertedDate = year..month..day;
    return ConvertedDate; -- текстовый формат год-месяц-день без разделителя
end;

function FindScriptWindow()
    local hScriptWnd = 0;
    local hWnd = w32.FindWindow("InfoClass",""); -- поиск главного окна
    local hChldWnd=0
    for     i=0,100 do
        hChldWnd = w32.FindWindowEx(hWnd, hChldWnd, "", ""); -- 1й уровень дочерних окон
        local hSChldWnd=0;
        for     k=0,50 do
            hSChldWnd = w32.FindWindowEx(hChldWnd, hSChldWnd, "", ""); -- 2й уровень дочерних окон
            local wndt = w32.GetWindowText(hSChldWnd,wndt,256);
            if wndt=="Available scripts" or  wndt=="Доступные скрипты" then
                hScriptWnd=hSChldWnd;
                --log:write("hScriptWnd "..hScriptWnd.." hScriptWnd text "..tostring(wndt).."\n");
                break; -- прерываем цикл
            end;
        end;
        if hScriptWnd~=0 then break; end;
    end;
    return hScriptWnd;
end;

44

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

DanP пишет:

swerg большое Вам спасибо за работу!

И вам спасибо на добром слове.

DanP пишет:

к сожалению не могу разобраться как выбрать/активировать один конкретный скрипт из списка загруженных, поэтому пока перезапускаются все скрипты с помощью кнопок "Выбрать все" и "Запустить", что не очень удобно.

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

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

45 (2017-08-23 17:29:56 отредактировано DanP)

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

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

46

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

Нужна функция GetUserName.
Дело в том, что за компьютером может работать несколько пользователей. И, например, при автологине quik хотелось бы проверить ещё пользователя Windows.

47

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

DanP пишет:

то при переборе окон появляются идентификаторы с пустыми или nil текстами, но как их проверить не совсем понятно.

Обычно просто опираемся на тот факт, что перебираются окна всегда в определённом порядке (в порядке их создания). При этом порядок создания в одном и том же приложении - всегда един (т.к. код создания - один и тот же).

48

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

reg05 пишет:

Нужна функция GetUserName.

Здраво, надо сделать.

reg05 пишет:

Дело в том, что за компьютером может работать несколько пользователей. И, например, при автологине quik хотелось бы проверить ещё пользователя Windows.

Я бы тут лучше использовал штатные возможности Windows: для разных пользователей - разные папки подключаются в профиле.
Причем я бы прямо весь терминал QUIK положил в папки, специфичные для профиля пользователей (Рабочий стол, Мои документы, или AppData\Local и т.п.).
Это позволит:
1) экранировать пользователей друг от друга (вы же не под админом их запускаете?)
2) использовать ключи нужного пользователя волшебно, штатными средствами Windows
3) у пользователей не будут пересекаться/портиться настроенные ими конфигурации окон
Если при этом нужны общие Lua-скрипты - их положить в общую папку, постоянную для всех пользователей (C:\QLua для примера). Тогда пользователя смогут использовать общие скрипты, а всё остальное у них будет гарантированно раздельно.

49

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

Здравствуйте. С поиском окон, полей и кнопок вроде понятно. А как создать свой комбинированый список, свое поле ввода и кнопку с помощью данной библиотеки?

50

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

bitsotik,
для этого лучше использовать визуальные библиотеки. Они предназначены как раз для изготовления интерфейса.
Например, QVCLua
[url]https://quik2dde.ru/viewtopic.php?id=111[/url]
Разные примеры есть тут
[url]https://quik2dde.ru/viewtopic.php?id=73[/url]