1 (2019-12-11 12:03:37 отредактировано toxa)

Тема: языковые ресурсы QUIK

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

package.cpath = getScriptPath() .. "\\lua_quik_resources.dll"
qres = require "quik_resources"

function main()  
  quik_resources_lib = "lang_rus.dll"

  hQUIK = qres.get_quik_handle()
  if (hQUIK ~= 0) then
    message("QUIK main window handle: " .. tostring(hQUIK))

    conn_dlg_title = tostring(qres.get_dlg_title(10107))
    message("Connect dialog caption: " .. conn_dlg_title, 1)

    HWND_DESKTOP = 0
    WM_COMMAND = 273
    INFOMENU_CONNECT = 100
    INFOMENU_DISCONNECT = 101
    IDOK = 1
    MF_ENABLED = 0

    connect_menu_state = qres.get_menu_state(hQUIK, INFOMENU_CONNECT)
    message("Connect menu item state: " .. tostring(connect_menu_state))

    if (connect_menu_state == MF_ENABLED) then
      qres.post_message(hQUIK, WM_COMMAND, INFOMENU_CONNECT, 0)
      sleep(100)

      hConnDlg = qres.get_child_handle(HWND_DESKTOP, conn_dlg_title)
      if (hConnDlg ~= 0) then
        message("Connection dialog handle: " .. tostring(hConnDlg))

        qres.set_dlg_item_text(hConnDlg, 10101, "quik_login")
        qres.set_dlg_item_text(hConnDlg, 10102, "quik_password")
        qres.post_message(hConnDlg, WM_COMMAND, IDOK, 0)
      else
        message("Unable to get connection dialog handle", 2)
      end
    else
      message("Connect menu item is grayed or disabled", 2)
    end
  else
    message("Unable to get QUIK main window handle", 2)
  end
end

для quik 7 нужно задать quik_resources_lib = "lang_res.dll". логин и пароль нужно подставить свои.

либа тут: https://www.dropbox.com/s/ktfniynywbdvw … s.zip?dl=0
исходники тут: https://github.com/untoxa/lua_quik_resources

2

Re: языковые ресурсы QUIK

волшебные константы 10107, 10101, 10102 можно подсмотреть в любом resource editor'е, для окна "Идентификация пользователя" это выглядит вот так:

10107 DIALOGEX 40, 30, 180, 85
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Идентификация пользователя"
LANGUAGE LANG_RUSSIAN, 0x1
FONT 9, "Arial"
{
   CONTROL "", 10103, COMBOBOX, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 5, 7, 169, 98 
   CONTROL "", 10101, EDIT, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 5, 26, 169, 12 
   CONTROL "", 10102, EDIT, ES_LEFT | ES_PASSWORD | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 5, 44, 169, 12 
   CONTROL "Вход", 1, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 84, 65, 44, 15 
   CONTROL "Отмена", 2, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 131, 65, 44, 15 
   CONTROL "Запомнить имя", 10097, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 68, 67, 8 
}

3

Re: языковые ресурсы QUIK

Спасибо!

4

Re: языковые ресурсы QUIK

Потренил сегодня волшебные команды, работают, но есть нюанс один не здоровый.
Был прецедент замены кнопки "&Нет"(ID=2) на кнопку "Отмена"(ID=7), естественно, что их ID волшебным образом так же изменятся, как и названия.
Т.е. отправление команды кнопке по ее ID - это круто, убирает 4+ лишних действия с поиском по caption кнопки, но от коварных действий арки не спасает.
И так или иначе требует проверки или отправки нескольких сообщений, чтоб наверняка:
w32.PostMessage(hWnd, WM_COMMAND, 2, 0)
w32.PostMessage(hWnd, WM_COMMAND, 7, 0)

Собственно, так и сделал.
К моему удивлению - PostMessage до кнопки идет дольше, чем 1мс, т.к. через sleep(1) окно сообщения еще "висит" (глазом сообщение вообще не видно) и функции вызываются дважды, чего не замечалось при таком подходе:

local btn = w32.FindWindowEx(hWnd, 0, "", "&Нет")
if btn == 0 then
    btn = w32.FindWindowEx(hWnd, 0, "", "Отмена")
end
w32.SetFocus(btn)
w32.PostMessage(btn, w32.BM_CLICK, 0, 0)

С чем сие может быть связано?

5

Re: языковые ресурсы QUIK

А еще нюанс, "товарищи" из арки на окно сообщения "Внимание" Вы хотите снять заявку №.. повесили активную кнопку IDCLOSE=8, (ну что бы двумя кнопками можно было отменить такое не желательное действие), а на сообщение "Замена заявки" кнопка закрытия есть, но не активна.
По этому:
w32.PostMessage(hWnd, WM_COMMAND, 8, 0) тупо не подходит для всех окон этого типа.

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

6 (2019-11-13 01:00:13 отредактировано toxa)

Re: языковые ресурсы QUIK

kalikazandr пишет:

Собственно, так и сделал.

никогда не нужно так делать. нужно посылать IDOK сразу диалоговому окну. еще раз: никогда не нужно искать кнопки диалога и эмулировать их нажатие, надо слать WM_COMMAND диалогу.

7 (2019-11-13 01:08:01 отредактировано toxa)

Re: языковые ресурсы QUIK

kalikazandr пишет:

w32.PostMessage(hWnd, WM_COMMAND, 8, 0) тупо не подходит для всех окон этого типа.

такое сообщение не нужно посылать. если мы хотим согласиться, то шлем диалогу IDOK, если нет - IDCANCEL. все. похрену на кнопки.
я не совсем понимаю, зачем из скрипта нужно с чем-то не соглашаться, но всегда есть вариант послать WM_CLOSE и таким образом активировать "отмену" действия. все равно что крестик нажать на заголовке сообщения.

8

Re: языковые ресурсы QUIK

toxa пишет:

я не совсем понимаю, зачем из скрипта нужно с чем-то не соглашаться, но всегда есть вариант послать WM_CLOSE и таким образом активировать "отмену" действия. все равно что крестик нажать на заголовке сообщения.

В этом вся суть. Если дать возможность пользователю нажать "Да/Нет", то квик сам выставит заявку без trans_id, без brokerref. Какой алгоритм нужен для правильной реакции на такое событие? Событие снятия, допустим, обработал, а дальше что? Если пользователь снял заявку, то ждать больше нечего, а если сместил? Сколько ждать появления новой заявки без trans_id? Какому роботу заявка должна принадлежать? Или пользователь снял заявку и выставил другую руками с другим объемом. Куча непоняток возникает, которые обработать, в силу моего скудоумия, никак не получится, да и желания нет ломать голову.

С отслеживанием окон все очень просто, без танцев с бубном. Бот спокойно сам снимет заявку и выставит новую по нужной цене. Такой вот был план и он прекрасно работает.
Команда WM_CLOSE в контексте схожа с кнопкой "Нет/Отмена", про нее и не подумал. Спасибо!

9

Re: языковые ресурсы QUIK

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

что касается диалогов подтверждения действий, то, если я не ошибаюсь, они создаются квиком при помощи банального messagebox(), текст и caption делаются из ресурсов типа string. там не может быть сколько угодно любых кнопок, все варианты описаны в msdn: https://docs.microsoft.com/en-us/window … messagebox

10

Re: языковые ресурсы QUIK

toxa пишет:

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

Возможно это плохая идея,
когда есть один робот и все действия пользователя с заявками привязаны к одной стратегии. Такое поведение оговаривается сразу.
А когда стратегий десятка полтора-два, то тут пользователю вообще не нужно лезть, но все равно лезут своими кривыми ручками что-то поправить, а потом еще и жалуются, что роботы сломались, точнее не правильно открыли/закрыли позицию. Логи читаешь - вот они кривые ручки, все зафиксировано в логе.

Мои роботы не смотрят, что там пользователь покупает/продает им абсолютно похрен, просто запишут факт события, а вот манипуляции с заявками робота, робот обязан контролировать и контролирует.
Хочет пользователь сместить заявку - да ради бога, удалить - да пожалуйста. Как-то так.

А кнопки - да, их не много, но мне на них уже пофик совсем, т.к. WM_CLOSE прекрасно работает. Спасибо

11

Re: языковые ресурсы QUIK

выложил на гитхаб: https://github.com/untoxa/lua_quik_resources

12

Re: языковые ресурсы QUIK

toxa пишет:

волшебные константы 10107, 10101, 10102 можно подсмотреть в любом resource editor'е, для окна "Идентификация пользователя" это выглядит вот так:

10107 DIALOGEX 40, 30, 180, 85
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Идентификация пользователя"
LANGUAGE LANG_RUSSIAN, 0x1
FONT 9, "Arial"
{
   CONTROL "", 10103, COMBOBOX, CBS_DROPDOWNLIST | CBS_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP, 5, 7, 169, 98 
   CONTROL "", 10101, EDIT, ES_LEFT | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 5, 26, 169, 12 
   CONTROL "", 10102, EDIT, ES_LEFT | ES_PASSWORD | ES_AUTOHSCROLL | WS_CHILD | WS_VISIBLE | WS_BORDER | WS_TABSTOP, 5, 44, 169, 12 
   CONTROL "Вход", 1, BUTTON, BS_DEFPUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 84, 65, 44, 15 
   CONTROL "Отмена", 2, BUTTON, BS_PUSHBUTTON | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 131, 65, 44, 15 
   CONTROL "Запомнить имя", 10097, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_TABSTOP, 6, 68, 67, 8 
}

А нельзя ли уловить ID вкладок в QUIK? Идея парсить имя вкладки и запускать таблицу скрипта именно на той, на которой нужно.

13 (2020-05-17 12:20:01 отредактировано toxa)

Re: языковые ресурсы QUIK

Можно, но только они динамические, в ресурсах информации о самих закладках нет, только о контейнере с закладками.

14

Re: языковые ресурсы QUIK

тоха, приветствую! для 8.5 планируете поправить?

15

Re: языковые ресурсы QUIK

https://www.dropbox.com/s/ktfniynywbdvw … s.zip?dl=0
исходники: https://github.com/untoxa/lua_quik_resources

16

Re: языковые ресурсы QUIK

Премного благодарен!

17

Re: языковые ресурсы QUIK

toxa пишет:

Можно, но только они динамические, в ресурсах информации о самих закладках нет, только о контейнере с закладками.

Динамические в каком смысле? ID меняется при перезапуске QUIK?

Есть ещё мысль пойти другим путём. Можно привязаться к какому-нибудь названию окна. открытого на вкладке. Вопрос, можно ли определить, что это окно в текущий момент на экране?

18

Re: языковые ресурсы QUIK

создаете окно на любой вкладке. затем главное меню->окна->переместить окно на вкладку->"имя вкладки"

19

Re: языковые ресурсы QUIK

toxa пишет:

создаете окно на любой вкладке. затем главное меню->окна->переместить окно на вкладку->"имя вкладки"

Расскажу о проблеме. Пока работал на QPILE было запущено несколько скриптов и все таблицы скриптов привязывались к вкладке, на которой они были созданы. Было отдельное рабочее пространство для каждого робота. Эта информация хранилась в файле настроек QUIK (*.wnd).
В LUA нет никакой штатной привязки таблиц скриптов к вкладкам, и все таблицы роботов помещаются на активную, на момент запуска QUIK, вкладку.
Перетаскивать вручную 5-10 таблиц, конечно же, накладно.
Вот и пришла мысль, выявить какой-либо статический ID для каждой вкладки, передать его скрипту, а тот бы создавал свою таблицу на своей вкладке.

20

Re: языковые ресурсы QUIK

mihalich81 пишет:

Перетаскивать вручную 5-10 таблиц, конечно же, накладно.

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

21

Re: языковые ресурсы QUIK

kalikazandr пишет:
mihalich81 пишет:

Перетаскивать вручную 5-10 таблиц, конечно же, накладно.

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

В том то и дело, что задача размещать скрипты на разных вкладках.
Идея 1. Найти зацепку через resource editor.
Идея 2 (вчера придумал). Определять область (30*10 пикс.), где находится кнопка вкладки и при нажатии на эту кнопку (область), создавать окно скрипта. Конечно, окно QUIK должно быть развёрнуто, а вкладки всегда на своих местах. Этот вариант осуществим на данный момент, но не кажется лучшим.

22 (2020-10-24 14:06:30 отредактировано kalikazandr)

Re: языковые ресурсы QUIK

mihalich81 пишет:

В том то и дело, что задача размещать скрипты на разных вкладках.

Это плохая затея, окна скриптов должны быть там же, где окно "доступные скрипты".
В случае ахтунга будете искать нужную вкладку, пока ищете, забудете зачем искали и т.д. плюсов в таком решении не будет точно.
Как вариант, использовать VCL. На ней разместить вкладки под скрипты и vcl-форма будет "ездить" всегда с вами, пофик какая вкладка в терминале активна и где окно доступных скриптов.

23

Re: языковые ресурсы QUIK

я же написал что делать: активируете скрипт, потом программно "нажимаете" соответствующий пункт главного меню (посылаете сообщение WM_COMMAND главному окну) . "пролистать" программно главное меню довольно легко. не так легко, как найти нужный ID в resource editor, потому что эти пункты создаются динамически, но тоже не очень сложно: сначала находите базовой подменю по ID, затем листаете пункты этого подменю.

24

Re: языковые ресурсы QUIK

mihalich81 пишет:

В LUA нет никакой штатной привязки таблиц скриптов к вкладкам, и все таблицы роботов помещаются на активную, на момент запуска QUIK, вкладку.
Перетаскивать вручную 5-10 таблиц, конечно же, накладно.

Переключать на нужную вкладку, там создавать окна, после возвращать предыдущую активную вкладку.
Показано здесь:
https://quik2dde.ru/viewtopic.php?id=329