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

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

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

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

  • Посещение

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

    5

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

  1. Вы имеете в виду, убрать эту строчку: Result := CallNextHookEx(CurrentHook, nCode, wParam, lparam); Я полагал, что "следующий хук" относится к возможному нажатию следующей клавиши, которое хранится в очереди. Разве это не так? И что присваивать результату в таком случае? Ноль?
  2. Выявилась проблемка. Когда FormKeyDown вызывался как обработчик события, в самом его конце выполнялся оператор Key:=0. Это обнуляло нажатие клавиши, гарантировало, что оно не сработает каким-то дополнительным, непредвиденным образом. В новой конфигурации это не работает, я уже столкнулся с досадными побочными эффектами. Нажатие нужно обнулить в обработчике хука KeyboardProc. Но как?
  3. Да, с виртуальным кодом клавиши проблем нет. Сложнее оказалось с параметром 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; Придирчиво еще не тестировал, но в первом приближении всё работает.
  4. Загвоздка в моей дремучести, которую не ликвидировать враз. Нашел описание GetAsyncKeyState, но это несколько не о том, туда надо передавать параметром уже известный код клавиши. А что за снанкод? Где про него можно узнать?
  5. Попробовал, и получилось! С веббраузером проблем не наблюдается - даже когда фокус на нем, управление переходит в KeyboardProc. Осталось последнее: понять, как из KeyboardProc(nCode: integer; wParam: integer; lParam: integer) вызвать FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState). В идеале хотелось бы суметь передать без искажений все три параметра: Key, KeyChar и Shift.
  6. RaiseLastOSError помог установить причину: System Error. Code: 1428. Cannot set nonlocal hook without a module handle Только не знаю пока, как это трактовать и что с этим делать. Интересно и то, что с WH_KEYBOARD_LL хук срабатывает: CurrentHook ненулевой, и по нажатию клавиши управление переходит в KeyboardProc. Но ведь это, как я понял, глобальный хук, он будет перехватывать нажатия у других приложений. А это уже будет лишним.
  7. Ссылка внятная, спасибо. Но пока не помогло. Вот такой конструктор формы у меня: constructor TForm1.Create(AOwner: TComponent); begin inherited; CurrentHook := SetWindowsHookEx(WH_KEYBOARD, @KeyboardProc, HInstance, 0); end; На отладчике вижу, что после его выполнения CurrentHook как был равен нулю, так и остался. Одно это уже подозрительно. И в функцию KeyboardProc управление не попадает, какие клавиши ни нажимай. Кстати, в комментариях по ссылке вот еще что пишут: У меня 64. Не в этом ли закавыка? Или же сказанное относится лишь к WH_KEYBOARD_LL ? Я не смог понять.
  8. Очень обяжете. Можно даже сразу на электронную почту: vsСОБАКАsusi.ru
  9. В декабре я задавал здесь вопрос о борьбе с перехватами нажатий клавиш компонентом TWebBrowser. Продвинутый пользователь Kami посоветовал тогда, раз уж меня интересует только Windows, поставить хук на клавиатуру. Поделился полезной ссылкой. Добавил, что можно еще много чего нагуглить. Что-то действительно нагуглилось - но не в том объеме, чтобы я смог четко понять, как это следует делать. Вопросов много. Куда именно должна быть воткнута функция KeyboardProc? Что в ней должно содержаться, чтобы управление передавалось уже написанному обработчику события FormKeyDown? Многие также упоминают о возникающих проблемах с юникодом, и хорошо было бы понять, как уберечься от них. Буду очень признателен, если кто-нибудь осветит эту темную для меня материю.
  10. Как преобразовать тип HString в обычную строку? Нагуглил упоминания о функции TWindowsString.HStringToString, которая должна находиться в System.WinrtHelpers. Но такого юнита в поставке Delphi не наблюдаю. Может, его можно где-нибудь раздобыть? Или существуют иные способы?
  11. Простите мне мое невежество, но в каком именно месте можно на них взглянуть?
  12. Пытаясь разобраться с проблемой размещения файлов в UWP-приложениях, пришел к необходимости создать в своем коде объект класса ApplicationData. Этот класс описан на соответствующей странице майкрософтовской документации, где в самом начале обозначено следующее: Namespace: Windows.Storage Assemblies: Windows.Storage.dll, Windows.dll Юнита с именем Windows.Storage или Winapi.Windows.Storage я в поставке Delphi не наблюдаю. Неудивительно, что попытки вставить соответствующие идентификаторы в раздел uses ни к чему не ведут. Как в таких случаях поступают? Откуда берут необходимое?
  13. На форуме Эмбаркадеро этот вопрос я задал еще на прошлой неделе - то ли в четверг, то ли в пятницу. Получил сообщение: мол, ваш вопрос будет опубликован после того, как его просмотрит модератор. Сегодня уже среда, а модератор всё спит. Довольно странно функционирует этот форум, я уже не в первый раз замечаю. Существуют ли, интересно, способы как-то на них воздействовать? Обращался также к известному дельфийскому эксперту Марко Канту по электронной почте. Он несколько раз ответил - но видно было, что даже он в этих вопросах пока плавает. Теперь вовсе замолчал. Если в конце концов разберусь, то статья будет, обещаю. Но буксую уже второй месяц, и уверенности, что разберусь, всё меньше.
  14. Хочу еще раз обратиться к коллективному разуму в надежде все-таки разобраться с тем, как должен быть устроен пакет appx для размещения в Microsoft Store. А именно - как организовать размещение настроек и пользовательских файлов в специально отведенных для этого папках, а не в установочном каталоге, что запрещено. Вся информация, которую я смог к сегодняшнему дню накопать, размещена на этой странице майкрософтовской документации и сводится к тому, что при инсталляции пакета appx автоматически создается хранилище пользовательских данных из трех папок. Цитирую: one for local files, one for roaming files, and one for temporary files. В общем-то, это удобно - по крайней мере, не нужно заботиться о деинсталляции: ровно эти же папки при удалении программы и сотрутся. Вопрос в том, как к этому хранилищу обратиться. В идеале, конечно же, хотелось бы иметь возможность уже в Deployment Manager обозначить для некоторых файлов, что они должны быть положены в это хранилище, а не в установочный каталог. Но как это можно сделать и можно ли сделать вообще, мне понять не удалось. Списка констант для параметра Remote Path я найти не смог, а отдельные упоминаемые тут и там константы ('res', 'assets', 'classes', 'library') явно относятся к мобильным платформам, а не к Windows. Если так поступить нельзя, остается класть всё в установочный каталог, а при первом запуске приложения переносить в нужное место. Но опять же: как приложению заполучить полный адрес этого места? Ведь это вовсе не привычные нам CSIDL_APPDATA и не CSIDL_COMMON_APPDATA, это нечто новое, доселе невиданное, в документации называемое "local app data store". На той же странице есть пример соответствующего кода с использованием класса ApplicationData, но он написан на незнакомом мне C#. Там есть также ссылки на описание класса ApplicationData, но по ссылкам тоже C# и C++. Был бы очень признателен, если бы кто-нибудь показал мне, как заполучить адрес local app data store средствами Delphi.
  15. Проверил, в FMX под Windows не работает. После выполнения GetProcAddress отладчик показывает, что i=nil. Да и бог с ним, что не работает. Я вижу, что тривиального решения нет - именно это и хотел узнать. А способ с отдельным юнитом меня вполне устраивает.
  16. Специального смысла нет. Я просто был уверен, что существует некий способ такого обращения, и мне было досадно, что я его не знаю. В практическом же плане меня вполне устроит и подсказанный способ - тем более, что юнит с глобально используемыми процедурами в моем проекте уже есть, мне просто не пришло в голову разместить там же глобальные переменные.
  17. Выходит, только так, а напрямую нельзя. Ну что ж, буду знать теперь, спасибо.
  18. Неловко спрашивать о таком на третьем десятке лет программирования на Delphi, но всё же спрошу. Вот предельно простой код: program MyProgram; uses MyUnit in 'MyUnit.pas' {MyForm}; var MyVariable: Boolean=False; {$R *.res} begin Application.Initialize; Application.CreateForm(TMyForm, MyForm); Application.Run; end. Как мне обратиться к переменной MyVariable из юнита MyUnit?
  19. А вот, кстати, не факт, что дело в манифесте или вообще в каких-то правах. Тот же Марко Канту оказался столь любезен, что прислал мне ссылку на страницу майкрософтовской документации, где написано: мол, при установке любого UWP-приложения автоматически формируется хранилище пользовательских данных из трех папок, цитирую: one for local files, one for roaming files, and one for temporary files. Получается, что ни в каких AppData ничего создавать и не нужно, система сама всё создаст в подходящем месте. Мне, однако, остается непонятным, как приложению заполучить полный адрес этого хранилища - конкретно, папки для Local app data.На указанной странице есть инструкции, но они написаны на незнакомом мне C#. Есть также ссылки на документацию об используемом классе ApplicationData, там C# и C++, тоже малопонятный. Не поможет ли кто-нибудь перетолмачить это дело на Delphi?
  20. Обратился по электронной почте к известному специалисту Марко Канту. Он тоже не знает никаких констант для Remote path и считает, что приложение должно само распихивать файлы по каталогам при первом запуске. А на вопрос, отчего у меня так не выходит и не нужны ли здесь какие-то дополнительные права и привилегии, ответил так: "An UWP pass has limited access to the file system. I really don't remember which folder you can write to, and which are off limits... There is Microsoft documentation covering it." Мое приложение пытается создать и использовать папку в каталоге CSIDL_COMMON_APPDATA. Неужели это может быть по умолчанию запрещено?
  21. Меня тоже такая мысль посещала. Но как это проверить? И главное, где раздобыть эти права, если дело действительно в них?
  22. Не понял вопроса. Вы спрашиваете, чего именно нельзя создать при запуске? Или (если бы была запятая после слова "что") спрашиваете, отчего я не могу при запуске создать означенного каталога? Если второе, то да, как я уже написал, отчего-то нельзя. То есть, на моем компе можно, а на их конце - где тестировщики из Microsoft Store гоняют мою программу - она на этом месте валится. Почему валится, они не объясняют.
  23. Целый месяц бодаюсь с Microsoft Store, пытаясь разместить у них свое UWP-приложение в виде пакета appx. Получаю отлуп за отлупом. Проблема: приложение должно располагать папкой для пользователя, отличной от установочного каталога, где он мог бы сохранять файлы. Там же должны храниться файлы настроек. Раньше, создавая дистрибутив в InnoSetup, я всегда предусматривал создание такой папки по адресу <user>\AppData\Roaming\MyApp. Теперь всё полагается указывать в разделе Deployment - но как там указать такой адрес? Вроде бы, есть графа "Remote path", и логично существовать каким-то макросам для нее, вроде AppData - но никакой информации на эту тему я найти не смог. Видел лишь упоминания таких макросов, как res, assets, classes, library - однако все они, как я понял, относятся к мобильным платформам. Попытки обходных маневров не удались. Сначала я решил всё класть в установочный каталог, а при первом запуске создавать нужную папку и перебрасывать в нее несколько файлов. На моем компьютере это работает, но при тестировании в Microsoft Store отчего-то валится (присылают скриншот с сообщением "Access is denied"). То ли нельзя стирать файлы в установочном каталоге, то ли нельзя в таком режиме создавать новый каталог. Потом я прочитал где-то, что UWP-приложениям всё равно, где лежат файлы, они могут их менять даже в установочном каталоге. Попробовал всё валить в одну кучу и так работать. Увы, опять отрапортовали о падении ("The app tries to create a file under WindowsApps folder"). Получается, что все-таки нужно как-то заставить appx-дистрибутив создавать при установке папку по адресу <user>\AppData\Roaming\MyApp. Но как? Спрашивал на experts-exchange, там знатоков не нашлось. Если и здесь нет, может, кто-нибудь хотя бы подскажет, в каких местах есть смысл спросить?
×
×
  • Создать...