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

kami

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

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

  • Посещение

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

    41

Весь контент kami

  1. Мало. 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.
  2. Нет, не убрать. В целях нормального функционирования в подавляющем большинстве случаев вы должны вызвать следующий хук. И только в исключительных ситуациях (в данном случае - когда клавишу нельзя "пропустить" дальше) - не вызывать. А вы считаете, что единственный на всю систему установили хук на клавиатуру ? :))) Их десятки, если не сотни. Тот же WH_KEYBOARD: система будет вызывать последовательно все KeyboardProc в порядке (емнип), обратном времени установки хука. Естественно, если вы скажете системе "можно отдать на обработку следующему хуку". Внимательно читаем раздел Result в https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644984(v=vs.85).aspx Там, оказывается, уже всё предусмотрено и потенциально не надо даже пропускать вызов последующего хука. Хотя - лучше пропустить.
  3. Но результат функции хука нужно присвоить обязательно, вне зависимости от вызова следующего!
  4. не вызывать следующий хук
  5. наверное, действительно никто. Но вот методом интуитивного тыка это находится на раз. Должно быть так: А у вас, видимо, стоит emacs
  6. Более того - там уже есть виртуальный код клавиши. Еще проще.
  7. https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644984(v=vs.85).aspx
  8. Так а в чем загвоздка-то? внутри этого хука доступен сканкод нажатой клавиши. Есть GetAsyncKeyState и много чего еще
  9. по тексту этой ошибки гуглится очень многое. Основной посыл: для WH_KEYBOARD, если указывать HInstance, то он должен быть инстансом dll. Потому что exe не инжектнется в чужой процесс. Можно указать вместо HInstance - 0, а последний параметр выставить в TThread.Current.ThreadID, но (повторюсь) я не уверен, что веббраузер работает только в контексте основного потока приложения.
  10. Было бы неплохо почитать, чем отличается WH_KEYBOARD от WH_KEYBOARD_LL. Принципы действия абсолютно разные. Вполне возможно, что окна браузера находятся в другом потоке. Посему для начала экспериментов вам нужен именно WH_KEYBOARD_LL Ну так нужно же понимать причину - почему он равен нулю. Обращаемся к первоисточнику. Смотрите, что вернется и узнавайте причину. Можно так: if CurrentHook = 0 then RaiseLastOSError. Нет. Здесь имеется ввиду не разрядность операционной системы, а именно разрядность процессов, запущенных в ней (в 64-битный процесс может быть загружена только 64-битная dll. В 32бита - 32). Кроме того, _LL хуки не зависят от разрядности процесса, поскольку работают в контексте установившего хук потока, им dll не требуется.
  11. Да куда угодно. Любой модуль, но скорее всего - модуль той формы, на которой лежит веббраузер (его же нужно "обойти"). Там же (например - в конструкторе / деструкторе формы) - регистрация и удаление хука. Ну вот например: https://ru.stackoverflow.com/a/538552/192901 (просмотрел бегло, но криминала нет, по крайней мере - система не помрет, что, кстати, весьма возможно при использовании глобальных хуков). вместо SendMessage подставить myForm.OnKeyDown(...); возможно - придется несколько поменять внутреннюю логику самого хука. Но основа останется без изменений: внутрь хука получается структура, описывающая "что произошло с клавиатурой". Вы ее обрабатываете, вызываете нужные методы и отдаете управление опять системе.
  12. На windows спокойно задействуется механизм отлова утечек. Можно использовать куцый штатный (в dpr первой командой указать ReportMemoryLeaksOnShutdown := True или воспользоваться сторонними расширенными. Например - MadExcept имеет возможность показывать утечки памяти и ресурсов.
  13. Здесь ничего не меняли? (ну, Target, само собой должен быть Android)
  14. Если вы можете гарантировать, что 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.
  15. Под iOS и Win я делал собственную клавиатуру, которая работала вместо системной (исключительно внутри своего приложения). При этом сами компоненты (тот же TEdit) не затрагивались, т.е. поведение клавиатуры оставалось абсолютно прозрачным. Подключили модуль - работает своя клавиатура. Отключили - работает системная. Если вы можете доработать ее и под андроид - могу выложить в открытый доступ. Предупреждаю, что сделать методом "чуть изменим код под другую платформу" не выйдет - подходы у всех систем принципиально отличаются друг от друга.
  16. А что мешает использовать этот класс? Это не визуальный компонент, на форму его класть не надо.
  17. Так не вызывайте отрисовку на каждый принятый пакет. Пусть принятые данные кладутся в очередь (например - TQueue). Когда назревает необходимость отрисовки (допустим, по таймеру) - из очереди выгребаются все пакеты и данные рисуются сразу, всем скопом. По потоку: в соответствии с общими правилами - некорректно создавать объект в одном потоке и начинать его использовать в одном потоке, а основное использование вести в другом. Это я про TIDTCPClient. Перенесите его создание и уничтожение (кстати - а где деструктор?) в Execute вашего потока. На основании чего такой вывод? Я про первую часть - "поток отрабатывает сообщения с сервера"?
  18. В рантайме нет никаких дженериков. Компилятор преобразует все дженерики в реальные списки с необходимой типизацией. Поэтому - действительно никак. Вполне возможно, что даже is TObjectList<TMyClass> не сработает - компилятор вполне вправе посчитать исходный класс TObjectList<TMyClass> не тем, с которым производится is. Это неправильно. Потому что есть еще 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, а вообще чем угодно, что поддерживает указанный интерфейс. И если список сделать тоже с поддержкой интерфейса (не знаю, какие методы в нем необходимы), то и сам объект может работать со своим владельцем абсолютно не интересуясь его типом.
  19. Можно это обойти (и довольно неплохо, не костыльно)... но это нужно кодить. Готового механизма нет.
  20. нет. Потому что элемент не принадлежит никакому листу. Это список знает, что при удалении элемента нужно сделать ему Free / заNil-ить ссылку на элемент. Только список. Сам объект (элемент списка) не подозревает о том, что он кому-то там "принадлежит".
  21. Не, оказывается я ошибся еще больше. Чтобы окончательно выяснить - залез на https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms644906(v=vs.85).aspx USER_TIMER_MINIMUM (0x0000000A), - минимально возможный интервал = 10мс. Но это недостижимый идеал :)))
  22. Графические движки не пользуются таймерами, это чревато гигантскими лагами. QueryPerfomanceCounter и т.п.
  23. Ни одна операционная система (за исключением систем реального времени) не обеспечит вам такую точность. Среда разработки здесь ни при чем. Совсем. К примеру, на Windows минимально возможный интервал таймера, емнип, 55мс. При этом нужно понимать, что событие таймера сработает только тогда, когда главный поток не будет ничем занят. А это, поверьте, случается достаточно редко. Грубо говоря - событие отработает "по остаточному принципу". Т.е. в реальности даже 55мс на Windows будет обеспечено далеко не всегда. Что уж говорить про мобильные платформы. Вам нужно пересмотреть алгоритм работы.
  24. kami

    webbrowser

    Платформа-то хоть какая? WB использует штатный (нативный) браузер, там многое зависит от качества связки с ним.
  25. Вы их готовить не умеете. Стабильности XMLDoc на мобильной платформе можно только позавидовать, т.к. там используется OmniXML. А на Win - парсер Microsoft, который используется чуть меньше, чем везде на Windows. И - да, я знаю что говорю. В боевом проекте на мобильной платформе стандартный XMLDocument использую (емнип) с 2016 года, начиная с XE7 и по 10.2 включительно. Ни разу не было проблем, связанных с ним.
×
×
  • Создать...