Перейти к содержанию
Fire Monkey от А до Я

kami

Пользователи
  • Постов

    643
  • Зарегистрирован

  • Посещение

  • Победитель дней

    41

Сообщения, опубликованные kami

  1. 2 минуты назад, Вадим Смоленский сказал:

    тогда CallNextHookEx вызывать необязательно. Так или не так?

    Мало. 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.

    3 минуты назад, Вадим Смоленский сказал:

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

    Не вижу ничего запутанного. В штатной ситуации - вызываете следующий хук. А когда нужно, чтобы клавиша не добралась до адресата - не вызываете.
    Или же - вызываете, но Result возвращаете <>0.
    Я не знаю, какой из двух вариантов лучше - я давно уже не работал с WinAPI в этом ракурсе. Эксперименты вам всё покажут, там делов на 20 минут.

    5 минут назад, Вадим Смоленский сказал:

    Я так и не смог понять разницы между WH_KEYBOARD_LL и WH_KEYBOARD.

    Разные механизмы работы. Оба - system-wide.

  2. 7 минут назад, Вадим Смоленский сказал:

    Вы имеете в виду, убрать эту строчку:

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

     

    7 минут назад, Вадим Смоленский сказал:

    Я полагал, что "следующий хук" относится к возможному нажатию следующей клавиши, которое хранится в очереди. Разве это не так?

    А вы считаете, что единственный на всю систему установили хук на клавиатуру ? :))) Их десятки, если не сотни. Тот же WH_KEYBOARD: система будет вызывать последовательно все KeyboardProc в порядке (емнип), обратном времени установки хука. Естественно, если вы скажете системе "можно отдать на обработку следующему хуку".

     

    7 минут назад, Вадим Смоленский сказал:

    И что присваивать результату в таком случае? Ноль

    Внимательно читаем раздел Result в https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644984(v=vs.85).aspx

    Там, оказывается, уже всё предусмотрено и потенциально не надо даже пропускать вызов последующего хука. Хотя - лучше пропустить.

  3. 1 час назад, Вадим Смоленский сказал:

    В идеале хотелось бы суметь передать без искажений все три параметра: Key, KeyChar и Shift. 

    Так а в чем загвоздка-то?
    внутри этого хука доступен сканкод нажатой клавиши. Есть GetAsyncKeyState и много чего еще

  4. 15 минут назад, Вадим Смоленский сказал:

    Только не знаю пока, как это трактовать и что с этим делать.

    по тексту этой ошибки гуглится очень многое.

    Основной посыл: для WH_KEYBOARD, если указывать HInstance, то он должен быть инстансом dll. Потому что exe не инжектнется в чужой процесс.

    Можно указать вместо HInstance - 0, а последний параметр выставить в TThread.Current.ThreadID, но (повторюсь) я не уверен, что веббраузер работает только в контексте основного потока приложения.

  5. 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 не требуется.

  6. 3 часа назад, Вадим Смоленский сказал:

    Куда именно должна быть воткнута функция KeyboardProc?

    Да куда угодно. Любой модуль, но скорее всего - модуль той формы, на которой лежит веббраузер (его же нужно "обойти"). Там же (например - в конструкторе / деструкторе формы) - регистрация и удаление хука.

    3 часа назад, Вадим Смоленский сказал:

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

    Ну вот например: https://ru.stackoverflow.com/a/538552/192901  (просмотрел бегло, но криминала нет, по крайней мере - система не помрет, что, кстати, весьма возможно при использовании глобальных хуков).

    вместо SendMessage подставить myForm.OnKeyDown(...);

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

     

  7. На windows спокойно задействуется механизм отлова утечек.

    Можно использовать куцый штатный (в  dpr первой командой указать ReportMemoryLeaksOnShutdown := True

    или воспользоваться сторонними расширенными. Например - MadExcept имеет возможность показывать утечки памяти и ресурсов.

  8. 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.

     

  9. Под iOS и Win я делал собственную клавиатуру, которая работала вместо системной (исключительно внутри своего приложения). При этом сами компоненты (тот же TEdit) не затрагивались, т.е. поведение клавиатуры оставалось абсолютно прозрачным. Подключили модуль - работает своя клавиатура. Отключили - работает системная.

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

  10. 2 часа назад, rust gg сказал:

    когда приходит частое количество пакетов,

    начинает приложение клиента тормозить.

    Так не вызывайте отрисовку на каждый принятый пакет.
    Пусть принятые данные кладутся в очередь (например - TQueue).
    Когда назревает необходимость отрисовки (допустим, по таймеру) - из очереди выгребаются все пакеты и данные рисуются сразу, всем скопом.

    По потоку: в соответствии с общими правилами - некорректно создавать объект в одном потоке и начинать его использовать в одном потоке, а основное использование вести в другом. Это я про TIDTCPClient. Перенесите его создание и уничтожение (кстати - а где деструктор?) в Execute вашего потока.

    2 часа назад, rust gg сказал:

    поток отрабатывает сообщения с сервера, но видит выводит только первый ответ с сервера

    На основании чего такой вывод? Я про первую часть - "поток отрабатывает сообщения с сервера"?

  11. 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, а вообще чем угодно, что поддерживает указанный интерфейс.

    И если список сделать тоже с поддержкой интерфейса (не знаю, какие методы в нем необходимы), то и сам объект может работать со своим владельцем абсолютно не интересуясь его типом.

  12. 8 часов назад, Alex7wrt сказал:

    уществует ли способ определить, к какому из  TObjectList принадлежит элемент

    нет. Потому что элемент не принадлежит никакому листу.

    Это список знает, что при удалении элемента нужно сделать ему Free / заNil-ить ссылку на элемент. Только список.

    Сам объект (элемент списка) не подозревает о том, что он кому-то там "принадлежит".

  13. 1 минуту назад, krapotkin сказал:

    16-18

    Не, оказывается я ошибся еще больше. Чтобы окончательно выяснить - залез на https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644906(v=vs.85).aspx

    USER_TIMER_MINIMUM (0x0000000A), -  минимально возможный интервал = 10мс. Но это недостижимый идеал :)))

  14. 1 час назад, Tumaso сказал:

    Навскидку - у либы с glscene.org есть подобный таймер, банально сделан через отдельный поток

    Графические движки не пользуются таймерами, это чревато гигантскими лагами.
    QueryPerfomanceCounter и т.п.

  15. В 04.04.2018 в 19:18, Rokweb сказал:

    Таймер с интервалом 1мс заметно подтормаживает

    Ни одна операционная система (за исключением систем реального времени) не обеспечит вам такую точность. Среда разработки здесь ни при чем. Совсем.

    К примеру, на Windows минимально возможный интервал таймера, емнип, 55мс.

    При этом нужно понимать, что событие таймера сработает только тогда, когда главный поток не будет ничем занят. А это, поверьте, случается достаточно редко. Грубо говоря - событие отработает "по остаточному принципу".  Т.е. в реальности даже 55мс на Windows будет обеспечено далеко не всегда. Что уж говорить про мобильные платформы.

    Вам нужно пересмотреть алгоритм работы.

  16. 5 минут назад, Edward Tarasov сказал:

    и именно этот сайт не пашет из приложения

    Платформа-то хоть какая? WB использует штатный (нативный) браузер, там многое зависит от качества связки с ним.

  17. В 29.03.2018 в 17:24, Akad сказал:

    Стандартные парсеры что xml, что json от эмбы абсурдно усложнены, не стабильны и постоянно плюются эксепшен

    Вы их готовить не умеете. Стабильности XMLDoc на мобильной платформе можно только позавидовать, т.к. там используется OmniXML. А на Win - парсер Microsoft, который используется чуть меньше, чем везде на Windows.

    И - да, я знаю что говорю. В боевом проекте на мобильной платформе стандартный XMLDocument использую (емнип) с 2016 года, начиная с XE7 и по 10.2 включительно. Ни разу не было проблем, связанных с ним.

×
×
  • Создать...