kami
-
Постов
643 -
Зарегистрирован
-
Посещение
-
Победитель дней
41
Сообщения, опубликованные kami
-
-
7 минут назад, Вадим Смоленский сказал:
Вы имеете в виду, убрать эту строчку:
Нет, не убрать. В целях нормального функционирования в подавляющем большинстве случаев вы должны вызвать следующий хук. И только в исключительных ситуациях (в данном случае - когда клавишу нельзя "пропустить" дальше) - не вызывать.
7 минут назад, Вадим Смоленский сказал:Я полагал, что "следующий хук" относится к возможному нажатию следующей клавиши, которое хранится в очереди. Разве это не так?
А вы считаете, что единственный на всю систему установили хук на клавиатуру ? :))) Их десятки, если не сотни. Тот же WH_KEYBOARD: система будет вызывать последовательно все KeyboardProc в порядке (емнип), обратном времени установки хука. Естественно, если вы скажете системе "можно отдать на обработку следующему хуку".
7 минут назад, Вадим Смоленский сказал:И что присваивать результату в таком случае? Ноль
Внимательно читаем раздел Result в https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644984(v=vs.85).aspx
Там, оказывается, уже всё предусмотрено и потенциально не надо даже пропускать вызов последующего хука. Хотя - лучше пропустить.
-
Но результат функции хука нужно присвоить обязательно, вне зависимости от вызова следующего!
-
10 минут назад, Вадим Смоленский сказал:
Нажатие нужно обнулить в обработчике хука KeyboardProc. Но как?
не вызывать следующий хук
-
-
Более того - там уже есть виртуальный код клавиши. Еще проще.
-
1 минуту назад, Вадим Смоленский сказал:
А что за снанкод?
https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644984(v=vs.85).aspx
-
1 час назад, Вадим Смоленский сказал:
В идеале хотелось бы суметь передать без искажений все три параметра: Key, KeyChar и Shift.
Так а в чем загвоздка-то?
внутри этого хука доступен сканкод нажатой клавиши. Есть GetAsyncKeyState и много чего еще -
15 минут назад, Вадим Смоленский сказал:
Только не знаю пока, как это трактовать и что с этим делать.
по тексту этой ошибки гуглится очень многое.
Основной посыл: для WH_KEYBOARD, если указывать HInstance, то он должен быть инстансом dll. Потому что exe не инжектнется в чужой процесс.
Можно указать вместо HInstance - 0, а последний параметр выставить в TThread.Current.ThreadID, но (повторюсь) я не уверен, что веббраузер работает только в контексте основного потока приложения.
-
9 часов назад, Вадим Смоленский сказал:
Вот такой конструктор формы у меня:
Было бы неплохо почитать, чем отличается WH_KEYBOARD от WH_KEYBOARD_LL. Принципы действия абсолютно разные.
ЦитатаThis hook may be called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
Вполне возможно, что окна браузера находятся в другом потоке. Посему для начала экспериментов вам нужен именно WH_KEYBOARD_LL
9 часов назад, Вадим Смоленский сказал:CurrentHook как был равен нулю, так и остался
Ну так нужно же понимать причину - почему он равен нулю. Обращаемся к первоисточнику.
ЦитатаIf the function fails, the return value is NULL. To get extended error information, call GetLastError.
Смотрите, что вернется и узнавайте причину. Можно так:
if CurrentHook = 0 then RaiseLastOSError.
9 часов назад, Вадим Смоленский сказал:У меня 64. Не в этом ли закавыка?
Нет. Здесь имеется ввиду не разрядность операционной системы, а именно разрядность процессов, запущенных в ней (в 64-битный процесс может быть загружена только 64-битная dll. В 32бита - 32). Кроме того, _LL хуки не зависят от разрядности процесса, поскольку работают в контексте установившего хук потока, им dll не требуется.
-
3 часа назад, Вадим Смоленский сказал:
Куда именно должна быть воткнута функция KeyboardProc?
Да куда угодно. Любой модуль, но скорее всего - модуль той формы, на которой лежит веббраузер (его же нужно "обойти"). Там же (например - в конструкторе / деструкторе формы) - регистрация и удаление хука.
3 часа назад, Вадим Смоленский сказал:Что в ней должно содержаться, чтобы управление передавалось уже написанному обработчику события FormKeyDown?
Ну вот например: https://ru.stackoverflow.com/a/538552/192901 (просмотрел бегло, но криминала нет, по крайней мере - система не помрет, что, кстати, весьма возможно при использовании глобальных хуков).
вместо SendMessage подставить myForm.OnKeyDown(...);
возможно - придется несколько поменять внутреннюю логику самого хука. Но основа останется без изменений: внутрь хука получается структура, описывающая "что произошло с клавиатурой". Вы ее обрабатываете, вызываете нужные методы и отдаете управление опять системе.
-
На windows спокойно задействуется механизм отлова утечек.
Можно использовать куцый штатный (в dpr первой командой указать ReportMemoryLeaksOnShutdown := True
или воспользоваться сторонними расширенными. Например - MadExcept имеет возможность показывать утечки памяти и ресурсов.
-
-
31 минуту назад, Archi_Ku сказал:
В чем прелесть?
Если вы можете гарантировать, что Sender всегда будет типа TmyThread, то преимущество в использовании absolute есть:
вы можете сразу работать с полем th как с экземпляром своего потока. Что это дает? Ну, допустим у вас запущено несколько потоков, каждый по завершению вызывает этот обработчик. Если в обработчике использовать поле класса, то вы будете работать с одним (скорее всего - последним созданным) экземпляром потока. А если оперировать Sender-ом, то работа будет вестись именно с тем, кто вызвал метод.
Повторюсь - если можете гарантировать, что Sender будет нужного вам типа.
Но лучше все-таки не надеяться на это, а выполнять явные преобразования:
procedure TForm1.ThreadEnd(Sender:TObject); var th: TMyThread; begin if Sender is TmyThread then th:=TmyThread(Sender) else th:=nil; if not Assigned(th) then exit; // а вот далее th уже явно указывает на экземпляр TMyThread.
-
Под iOS и Win я делал собственную клавиатуру, которая работала вместо системной (исключительно внутри своего приложения). При этом сами компоненты (тот же TEdit) не затрагивались, т.е. поведение клавиатуры оставалось абсолютно прозрачным. Подключили модуль - работает своя клавиатура. Отключили - работает системная.
Если вы можете доработать ее и под андроид - могу выложить в открытый доступ. Предупреждаю, что сделать методом "чуть изменим код под другую платформу" не выйдет - подходы у всех систем принципиально отличаются друг от друга.
-
А что мешает использовать этот класс? Это не визуальный компонент, на форму его класть не надо.
-
2 часа назад, rust gg сказал:
когда приходит частое количество пакетов,
начинает приложение клиента тормозить.
Так не вызывайте отрисовку на каждый принятый пакет.
Пусть принятые данные кладутся в очередь (например - TQueue).
Когда назревает необходимость отрисовки (допустим, по таймеру) - из очереди выгребаются все пакеты и данные рисуются сразу, всем скопом.По потоку: в соответствии с общими правилами - некорректно создавать объект в одном потоке и начинать его использовать в одном потоке, а основное использование вести в другом. Это я про TIDTCPClient. Перенесите его создание и уничтожение (кстати - а где деструктор?) в Execute вашего потока.
2 часа назад, rust gg сказал:поток отрабатывает сообщения с сервера, но видит выводит только первый ответ с сервера
На основании чего такой вывод? Я про первую часть - "поток отрабатывает сообщения с сервера"?
-
8 часов назад, ENERGY сказал:
самое сложное это вытащить из указателя дженерик класс.
В рантайме нет никаких дженериков. Компилятор преобразует все дженерики в реальные списки с необходимой типизацией. Поэтому - действительно никак. Вполне возможно, что даже is TObjectList<TMyClass> не сработает - компилятор вполне вправе посчитать исходный класс TObjectList<TMyClass> не тем, с которым производится is.
8 часов назад, ENERGY сказал:я бы отнаследовался от него и сделал свой метод Add
Это неправильно. Потому что есть еще Insert, есть Update (в том числе - и InsertRange). Правильно - перекрыть метод Notify или реализовать обработчик события OnNotify (последнее даже создания наследников не требует).
Вообще, если по каким-то причинам необходимо знать "владельца", было бы совсем хорошо сделать наследника от TRectangle, который будет реализовывать интерфейс наподобие такого:
IOwneredIntf = interface ['{ADF563F3-B4CE-4E96-9559-F0FFC2936D5Z}'] function GetOwner: TObject; procedure SetOwner(const Value: TObject); property Owner: TObject read GetOwner write SetOwner; end;
Список, который хочет установить владельческие отношения с этим TRectangle, в своем методе Notify приводит его к интерфейсу и устанавливает intf.Owner:=Self
Ну и в обратном порядке - тоже.
При этом появляется возможность работать со списком не только TRectangle, а вообще чем угодно, что поддерживает указанный интерфейс.
И если список сделать тоже с поддержкой интерфейса (не знаю, какие методы в нем необходимы), то и сам объект может работать со своим владельцем абсолютно не интересуясь его типом.
-
Можно это обойти (и довольно неплохо, не костыльно)... но это нужно кодить. Готового механизма нет.
-
8 часов назад, Alex7wrt сказал:
уществует ли способ определить, к какому из TObjectList принадлежит элемент?
нет. Потому что элемент не принадлежит никакому листу.
Это список знает, что при удалении элемента нужно сделать ему Free / заNil-ить ссылку на элемент. Только список.
Сам объект (элемент списка) не подозревает о том, что он кому-то там "принадлежит".
-
1 минуту назад, krapotkin сказал:
16-18
Не, оказывается я ошибся еще больше. Чтобы окончательно выяснить - залез на https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644906(v=vs.85).aspx
USER_TIMER_MINIMUM (0x0000000A), - минимально возможный интервал = 10мс. Но это недостижимый идеал :)))
-
1 час назад, Tumaso сказал:
Навскидку - у либы с glscene.org есть подобный таймер, банально сделан через отдельный поток
Графические движки не пользуются таймерами, это чревато гигантскими лагами.
QueryPerfomanceCounter и т.п. -
В 04.04.2018 в 19:18, Rokweb сказал:
Таймер с интервалом 1мс заметно подтормаживает
Ни одна операционная система (за исключением систем реального времени) не обеспечит вам такую точность. Среда разработки здесь ни при чем. Совсем.
К примеру, на Windows минимально возможный интервал таймера, емнип, 55мс.
При этом нужно понимать, что событие таймера сработает только тогда, когда главный поток не будет ничем занят. А это, поверьте, случается достаточно редко. Грубо говоря - событие отработает "по остаточному принципу". Т.е. в реальности даже 55мс на Windows будет обеспечено далеко не всегда. Что уж говорить про мобильные платформы.
Вам нужно пересмотреть алгоритм работы.
-
5 минут назад, Edward Tarasov сказал:
и именно этот сайт не пашет из приложения
Платформа-то хоть какая? WB использует штатный (нативный) браузер, там многое зависит от качества связки с ним.
-
В 29.03.2018 в 17:24, Akad сказал:
Стандартные парсеры что xml, что json от эмбы абсурдно усложнены, не стабильны и постоянно плюются эксепшен
Вы их готовить не умеете. Стабильности XMLDoc на мобильной платформе можно только позавидовать, т.к. там используется OmniXML. А на Win - парсер Microsoft, который используется чуть меньше, чем везде на Windows.
И - да, я знаю что говорю. В боевом проекте на мобильной платформе стандартный XMLDocument использую (емнип) с 2016 года, начиная с XE7 и по 10.2 включительно. Ни разу не было проблем, связанных с ним.
Хук на клавиатуру
в Windows
Опубликовано
Мало. If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the rest of the hook chain or the target window procedure.
Не вижу ничего запутанного. В штатной ситуации - вызываете следующий хук. А когда нужно, чтобы клавиша не добралась до адресата - не вызываете.
Или же - вызываете, но Result возвращаете <>0.
Я не знаю, какой из двух вариантов лучше - я давно уже не работал с WinAPI в этом ракурсе. Эксперименты вам всё покажут, там делов на 20 минут.
Разные механизмы работы. Оба - system-wide.