Вадим Смоленский

Пользователи
  • Публикаций

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

  • Посещение

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

    4

Весь контент Вадим Смоленский

  1. Вадим Смоленский

    Перехват сообщений в Windows

    Для задач, связанных с вводом японского текста, мне нужно научиться перехватывать системное сообщение WM_IME_NOTIFY. Насколько могу судить, в FireMonkey эти вещи делаются (если вообще делаются) принципиально иначе, нежели в VCL. Конкретного ничего не нагуглил. Не поможет ли кто?
  2. Вадим Смоленский

    Перехват сообщений в Windows

    Да вот, kami говорит, что в FireMonkey всё по-другому...
  3. Вадим Смоленский

    Перехват сообщений в Windows

    Попробовал повторить у себя. Получилось странно. Во время запуска приложения управление множество раз переходит в NewWndProc, в том числе и дважды с сообщением WM_IME_NOTIFY. Но как только главное окно появилось на экране - больше ни разу, ни с какими сообщениями вообще. Что-то где-то недокручено, такое впечатление...
  4. Вадим Смоленский

    Перехват сообщений в Windows

    Можно считать, что в рамках окна. Спасибо, Некрасов-сан. Выглядит интригующе. Но я не могу понять, как управление перейдет в процедуру WMIMENotify. Она ведь у вас вообще нигде не вызывается. P.S. А, понял. Она вызывается в FMX.Platform.Win: WM_IME_NOTIFY: begin Result := WMImeNotify(LForm, hwnd, uMsg, wParam, lParam); end;
  5. Вадим Смоленский

    Windows.Services.Store namespace

    В многомесячной борьбе с Microsoft Store за размещение у них своего Windows-приложения я продвинулся настолько, что вплотную подошел к организации взимания денег с покупателей посредством механизма add-ons (in-app purchases). Но здесь меня ждала очередная засада. Необходимые программные инструменты, главным из которых считается класс StoreContext, лежат в пространстве имен Windows.Services.Store; файлы с такими именами (windows.services.store.h и windows.services.store.idl) в Windows 10 действительно находятся; но в Delphi я не могу найти юнита с чем-то подобным. Хотя на одном форуме видел утверждение годичной давности, что в релизе 10.2 Tokyo это уже есть. Не может ли кто-нибудь пролить свет? Не там ищу? Все-таки еще не добавили? Или, может, это появилось лишь в самой последней сборке 10.2.3? У меня стоит 10.2.2. Обещание написать подробную статью по итогам моих мытарств остается в силе. На этом пути столько подводных камней и неочевидных ходов, что грех о них не поведать. Но сначала нужно дойти до победного конца.
  6. Вадим Смоленский

    Windows.Services.Store namespace

    Спасибо. Вижу, что не у одного меня такая проблема. Библиотека по ссылке - это что-то дотнетовское, едва ли подойдет. Придется, видимо, подождать до релиза 10.3. Хотя вот еще нашелся интересный компонент. Платный, но стоит попробовать, думаю.
  7. Вадим Смоленский

    Постоянная потеря фокуса под Wine

    В феврале я сетовал, что мое Windows-приложение не хочет нормально запускаться в Linux под Wine 3.0. Но время идет, вышел Wine 3.6 - и теперь один из тестировщиков радостно сообщил, что всё заработало, за вычетом одного досадного момента. А именно: приложение способно сохранять фокус ввода лишь долю секунды, потом теряет. Соответственно, невозможно ничего ввести в текстовые боксы, разве только одну-две буквы. Можно щелкнуть по заголовку приложения, оно опять получит фокус - и через мгновение снова потеряет. Куда именно при этом переходит фокус, непонятно. Тестировщик утверждает, что только мое приложение ведет себя так, все остальные работают нормально. Нет ли у кого-нибудь идей? Что нужно проверить?
  8. Год назад в одной из веток проскочила ссылка на китайский сайт (http://www.raysoftware.cn/?p=559), где предлагалось готовое решение для показа анимированных гифок средствами FireMonkey на любых платформах. Сейчас эта ссылка, как и весь сайт raysoftware.cn, упорно не открывается; по счастью, контент сохранился в гугловском кэше. Я скопировал оттуда код юнита и перевел гуглом все китайские комментарии на английский, добавив их в скобках. Там был еще сопроводительный текст, в котором автор излагал мотивы, побудившие его взяться за эту проблему; каких-то важных технических деталей я в этом тексте не увидел. Привожу весь юнит ниже и очень надеюсь, что кто-нибудь из продвинутых коллег объяснит мне, как именно этим кодом можно воспользоваться, чтобы показать пользователю анимированный файл в формате GIF. Моей программерской квалификации, к сожалению, не хватает.
  9. Вадим Смоленский

    Обработка анимированных GIF по рецепту китайского коллеги

    Хорошо, если получится исправить. В моем-то проекте гифки самые простые, без прозрачности и черезстрочности, так что я ничего такого и не заметил.
  10. Вадим Смоленский

    Хук на клавиатуру

    В декабре я задавал здесь вопрос о борьбе с перехватами нажатий клавиш компонентом TWebBrowser. Продвинутый пользователь Kami посоветовал тогда, раз уж меня интересует только Windows, поставить хук на клавиатуру. Поделился полезной ссылкой. Добавил, что можно еще много чего нагуглить. Что-то действительно нагуглилось - но не в том объеме, чтобы я смог четко понять, как это следует делать. Вопросов много. Куда именно должна быть воткнута функция KeyboardProc? Что в ней должно содержаться, чтобы управление передавалось уже написанному обработчику события FormKeyDown? Многие также упоминают о возникающих проблемах с юникодом, и хорошо было бы понять, как уберечься от них. Буду очень признателен, если кто-нибудь осветит эту темную для меня материю.
  11. Вадим Смоленский

    Хук на клавиатуру

    Да нет, всё понятно теперь. Я просто упустил из вида, что внутри функции CallNextHookEx еще много всякого разного может происходить и ее выходное значение в данном случае - не самое главное. Кстати, в отладчике посмотрел - оно в штатном режиме действительно получается нулевым. Так что теперь в тех случаях, когда нажатие клавиши точно обработано моим приложением и я больше не хочу от него никаких сюрпризов, просто присваиваю Result:=1. Всё работает, как часы. Огромное спасибо!
  12. Вадим Смоленский

    Хук на клавиатуру

    Это непонятно. Какой именно <>0? Любой кроме ноля? А если, как советуют, присвоить CallNextHookEx(CurrentHook, nCode, wParam, lparam), то это всегда будет ноль, что ли?
  13. Вадим Смоленский

    Хук на клавиатуру

    Такого раздела там нет. Вы, видимо, имели в виду раздел "Return value". В частности, там сказано, что CallNextHookEx нужно вызывать в том случае, если (цитирую) the hook procedure did not process the message. То есть, насколько я понял, если моя процедура FormKeyDown установила Key:=0, то это можно трактовать в том ключе, что message обработан, и тогда CallNextHookEx вызывать необязательно. Так или не так? Ваши рекомендации меня запутали: строчку убирать не надо, я должен вызвать следующий хук, но лучше этот вызов пропустить. Как это всё трактовать в терминах конкретных действий? Я так и не смог понять разницы между WH_KEYBOARD_LL и WH_KEYBOARD. Мне казалось, что лишь первый вариант относится ко всей системе целиком и проверяется всеми приложениями, где есть хук, в то время как второй ограничен лишь одним-единственным приложением. Всё сложнее?
  14. Вадим Смоленский

    Хук на клавиатуру

    Вы имеете в виду, убрать эту строчку: Result := CallNextHookEx(CurrentHook, nCode, wParam, lparam); Я полагал, что "следующий хук" относится к возможному нажатию следующей клавиши, которое хранится в очереди. Разве это не так? И что присваивать результату в таком случае? Ноль?
  15. Вадим Смоленский

    Хук на клавиатуру

    Выявилась проблемка. Когда FormKeyDown вызывался как обработчик события, в самом его конце выполнялся оператор Key:=0. Это обнуляло нажатие клавиши, гарантировало, что оно не сработает каким-то дополнительным, непредвиденным образом. В новой конфигурации это не работает, я уже столкнулся с досадными побочными эффектами. Нажатие нужно обнулить в обработчике хука KeyboardProc. Но как?
  16. Вадим Смоленский

    Хук на клавиатуру

    Да, с виртуальным кодом клавиши проблем нет. Сложнее оказалось с параметром Shift - но нагуглилась страничка с хорошим примером, там я взял всё, что мне было нужно. Вот как теперь выглядит функция: function KeyboardProc(nCode: integer; wParam: integer; lParam: integer ): LongWord; stdcall; var W: Word; C: Char; KeyUp : Boolean; KeyState: TKeyboardState; TheShift: TShiftState; begin if (nCode < 0) then begin Result := CallNextHookEx(CurrentHook, nCode, wParam, lParam); Exit; end; KeyUp := ((lParam AND (1 shl 31)) <> 0); if not KeyUp then begin W:=wParam; C:=Chr(wParam); TheShift:=[]; if GetKeyboardState(KeyState) then begin if (lParam AND (1 shl 29))<>0 then TheShift:=[ssAlt]; if (GetKeyState(VK_CONTROL) AND (1 shl 15))<>0 then TheShift:=TheShift+[ssCtrl]; if (GetKeyState(VK_SHIFT) AND (1 shl 15))<>0 then TheShift:=TheShift+[ssShift]; end; Form1.FormKeyDown(Form1,W,C,TheShift); end; Result := CallNextHookEx(CurrentHook, nCode, wParam, lparam); end; Придирчиво еще не тестировал, но в первом приближении всё работает.
  17. Вадим Смоленский

    Хук на клавиатуру

    Загвоздка в моей дремучести, которую не ликвидировать враз. Нашел описание GetAsyncKeyState, но это несколько не о том, туда надо передавать параметром уже известный код клавиши. А что за снанкод? Где про него можно узнать?
  18. Вадим Смоленский

    Хук на клавиатуру

    Попробовал, и получилось! С веббраузером проблем не наблюдается - даже когда фокус на нем, управление переходит в KeyboardProc. Осталось последнее: понять, как из KeyboardProc(nCode: integer; wParam: integer; lParam: integer) вызвать FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState). В идеале хотелось бы суметь передать без искажений все три параметра: Key, KeyChar и Shift.
  19. Вадим Смоленский

    Хук на клавиатуру

    RaiseLastOSError помог установить причину: System Error. Code: 1428. Cannot set nonlocal hook without a module handle Только не знаю пока, как это трактовать и что с этим делать. Интересно и то, что с WH_KEYBOARD_LL хук срабатывает: CurrentHook ненулевой, и по нажатию клавиши управление переходит в KeyboardProc. Но ведь это, как я понял, глобальный хук, он будет перехватывать нажатия у других приложений. А это уже будет лишним.
  20. Вадим Смоленский

    Хук на клавиатуру

    Ссылка внятная, спасибо. Но пока не помогло. Вот такой конструктор формы у меня: constructor TForm1.Create(AOwner: TComponent); begin inherited; CurrentHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, HInstance, 0); end; На отладчике вижу, что после его выполнения CurrentHook как был равен нулю, так и остался. Одно это уже подозрительно. И в функцию KeyboardProc управление не попадает, какие клавиши ни нажимай. Кстати, в комментариях по ссылке вот еще что пишут: У меня 64. Не в этом ли закавыка? Или же сказанное относится лишь к WH_KEYBOARD_LL ? Я не смог понять.
  21. Вадим Смоленский

    Хук на клавиатуру

    Очень обяжете. Можно даже сразу на электронную почту: vsСОБАКАsusi.ru
  22. Вадим Смоленский

    Конвертация HString в string

    Точно, есть! Спасибо.
  23. Вадим Смоленский

    Конвертация HString в string

    Как преобразовать тип HString в обычную строку? Нагуглил упоминания о функции TWindowsString.HStringToString, которая должна находиться в System.WinrtHelpers. Но такого юнита в поставке Delphi не наблюдаю. Может, его можно где-нибудь раздобыть? Или существуют иные способы?
  24. Вадим Смоленский

    Доступ к классу ApplicationData

    Пытаясь разобраться с проблемой размещения файлов в UWP-приложениях, пришел к необходимости создать в своем коде объект класса ApplicationData. Этот класс описан на соответствующей странице майкрософтовской документации, где в самом начале обозначено следующее: Namespace: Windows.Storage Assemblies: Windows.Storage.dll, Windows.dll Юнита с именем Windows.Storage или Winapi.Windows.Storage я в поставке Delphi не наблюдаю. Неудивительно, что попытки вставить соответствующие идентификаторы в раздел uses ни к чему не ведут. Как в таких случаях поступают? Откуда берут необходимое?
  25. Вадим Смоленский

    Доступ к классу ApplicationData

    Простите мне мое невежество, но в каком именно месте можно на них взглянуть?