Тема: Хук на события мыши

Идея следующая, получать в скрипте событие нажатия кнопок мыши и дескриптор объекта, над которым это событие произошло.
Например, всем известная панель управления заявками в окне котировок:
Нажатие пользователем на кнопки "C"; "R" и прочие приводит к мгновенному закрытию/развороту позиции без всяких предупреждений и вопросов со стороны квика, потому что такие действия выгодны брокеру (арка упорно не хочет вешать на эти кнопки сообщение о подтверждении действия), а роботы и не в курсе, что юзер что-то там чудит/скальперит, просаживает депо одним словом.
Событие движения метки на графике из точки А в точку Б происходит при зажатой левой кнопки мыши (ЛКМ), соответсвенно проверку на изменение этой метки можно делать только, когда ЛКМ не нажата и не получать промежуточные значения меток.
Это удобно для реализации меточных стопов/профитов/реверсов/ программно созданных линий трендов.

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

2

Re: Хук на события мыши

на самом деле, механика не очень мудреная, сделать это довольно просто, если владеешь си, или, скажем, delphi.
1. делаем helper-dll:
1.1 создаем dll, которая на DLL_PROCESS_ATTACH определяет hwnd основного окна квика, имеющего класс InfoClass, в том процессе, в котором эта dll загружена.
1.2 там же, находим все уже созданные дочерние окна, имеющие класс CHART, находящиеся в окне HostWindow, находящиеся в MDIClient, который уже в окне InfoClass.
1.3 для всех найденных окон ставим хук на wndproc
1.4 субклассируем класс CHART, чтобы вновь созданные окна имели нужный нам wndproc
1.5 в этом wndproc мы перехватываем, ну скажем, WM_LBUTTONUP, делаем postmessage в некое окно, о котором ниже. далее аккуратно вызываем прежний wndproc, аккуратно возвращаем результат прежнего wndproc.

2. делаем lua-dll:
2.1 при загрузке lua-dll загружаем helper-dll, в случае, если она не была ранее загружена другим экземпляром lua-dll.
2.2 создаем окно, в котором мы хотим получать нотификации.
2.3 сообщаем helper-dll хендл этого окна (например, через экспортируемую helper-dll функцию)
2.4 создаем lua-функцию process(), в которой мы крутим messageloop этого окна, полученные сообщения - есть сообщения посланные из helper-dll. вызываем callback'и lua OnLButtonUp(x,y...).
2.5 при выгрузке lua-dll не забываем сообщить нулевой хендл в helper-dll, иначе сообщения будут уходить случайному новому окну.
2.6 helper-dll никогда не выгружаем. выгрузится вместе с квиком.

3. в QLUA скрипте:
3.1 загружаем lua-dll
3.2 определяем колбэк OnLButtonUp, пишем что нам там нужно.
3.3 в main() крутим process()

мне лень это программировать, есть желающие?

3

Re: Хук на события мыши

вот, есть заготовка в виде проекта multilist: https://www.dropbox.com/s/7efuodbysetlx … t.zip?dl=0 из этой темы: https://quik2dde.ru/viewtopic.php?pid=2474#p2474

4

Re: Хук на события мыши

Спасибо, очень интересно.

5

Re: Хук на события мыши

Мне не совсем понятно как это использовать.
Ну нажал / отпустил пользователь мышь.
А где нажал? над каким объектом? что и куда переместил? какой масштаб на графиках сейчас?

Т.е. отловить-то можно события мыши, но как интерпретировать эти события разумно?

6 (2019-11-07 10:34:17 отредактировано toxa)

Re: Хук на события мыши

если я правильно понимаю документацию квика по поводу апи меток на графике, то метки устанавливаются в координатах время-цена, по-этому не важно, какой у графика масштаб. если стоит задача определить перетаскивание метки, то сейчас логичным решением выглядит мониторинг всех меток по таймеру, и если координаты изменились, то делаем что-то. но если наш таймер срабатывает в момент перетаскивания, то мы получаем промежуточное значение. если мы ставим по этому событию заявку, то заявка будет в цикле переставляться вместе с движением метки, что нехорошо. если мы перехватим отжатие мыши на графике, то, пролистав все метки и сравнив координаты сможем вычислить изменившуюся метку ПОСЛЕ перетаскивания. ну, предположим, над каким окном отжал - это как раз не проблема. проблема преобразовать хендл окна в ТЭГ графика, такой же, как в lua api. но, если подумать, то и это решаемо. даже без тэга однократно перебрать все метки недолго.
если пользователь ничего не делает, а просто тупо кликает мышкой по графику, то мы, конечно, пролистываем метки каждый раз, но тоже ничего не делаем, так как ни одна не поменялась.

7

Re: Хук на события мыши

Ребята, вы сильно заморочились, в скрипте я знаю заранее все id меток и их привязку на графике,
и отслеживаю конкретную метку в каждой итерации, не все, хотя их там есть более одной.
Делаю проверку, что YVALUE совпадает с его прошлым значением, если это так, то ничего не делаю, иначе, начинаю менять цены, которые нужно округлить и поправить саму метку по округленной цене.
Мало того, когда я меняю параметры метки может создаться ее клон, ну вот такой вот квик.
На практике не получается сместить метку быстро и точно! естественно бот видит все промежуточные значения (может быть несколько десятков или даже сотен), которые могут быть ошибочными или создать несколько дубликатов метки, которые нужно удалить руками (с десяток другой).
Если я буду знать, что сейчас нажата левая кнопка мыши, то конкретно за метками я не буду следить и не важно над каким компонентом сейчас указатель мыши. Если ЛКМ не нажата, то посмотрю.
Знание компонента для этого не нужно, оно нужно для кнопок стакана. Т.к. на кнопку стакана никто не нажимает и не держит нажатой левую кнопку мыши, то и событие там несколько другое, точнее оно будет в прошлом - была нажата ЛКМ над кнопкой стакана "R" или "С" после чего квик сгенерирует свою заявку без trans_id, без broker_ref, которая как минимум приведет к полному закрытию позиции, открытую десятком роботов. И вот тут нужно понимание, что это кнопка стакана и возвращать caption стакана: {была нажата R, BRZ9 [FORTS: Фьючерсы] Котировки} вот такое сообщение бот должен увидеть в новой итерации и декскриптор объекта как бы и не нужен. Если это не его инструмент, то и не будет ничего делать. Такое собщение я не могу удалять, т.к. какой робот должен это сделать? Но их много и не будет, ну максимум десяток за день.
Сейчас приходится отслеживать все пользовательские заявки, которые не имеют trans_id и делать проверку, что позиция не закрыта полностью или не развернулась, и эта проверка не быстрая и ее не хочется делать.

8

Re: Хук на события мыши

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

9

Re: Хук на события мыши

toxa пишет:

и, кстати, разве при выключенной панели инструментов в стакане эти горячие кнопки работают?

нет, но ее загадочным образом не отключают, с фразой: "а если мне надо срочно принять решение..."

10

Re: Хук на события мыши

значит сам себе злобный буратино

11

Re: Хук на события мыши

toxa пишет:

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

действительно так, в текущей реализации я не могу знать что метка "отпущена" и ее перерисовываю по новым координатам (округленный YVALUE) вот в этот момент SetLabelParams генерирует клона, не всегда, но бывает.

12

Re: Хук на события мыши

toxa пишет:

значит сам себе злобный буратино

ну еще и претензии имеются, почему его алгоритм открыл позицию согласно алгоритма, не как думал буратино, когда писал ТЗ

13

Re: Хук на события мыши

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