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

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