Добавлено: 25 Октябрь 2004, 19:41
Хочу поделиться. Жду здоровой критики, советов, замечаний...
Решаем проблему переключения в WinXP и введение в сабклассинг.
часть 1 (не лезет вся, чевой-то
)
Общеизвестный факт того, что в приложениях, написанных на любой версии Clarion,
и работающих в среде WindowsXP, не переключается раскладка клавиатуры с русской
на английскую и наоборот, давно выводит из себя пользователей и заставляет
разработчиков искать различные способы переключения клавиатуры. Среди уже
известных способов наибольшей популярностью пользуются следующие четыре:
- удаление из памяти модуля ctfmon.exe;
- установка альтернативного переключателя клавиатуры (Ninja или Punto Switcher);
- использование шаблона Юрия Философова entrypoint.tpl;
- и, наконец, было подмечено, что, если выполнять переключение клавиатуры не
обычным ctrl+shift/alt+shift, а ctrl+shift shift/alt+shift shift (то есть
нажимая дважды shift, не отпуская ctrl(alt)), то переключение происходит. Что
и было некоторыми разработчиками взято даже на эксплуатацию.
Причина непереключения клавиатуры кроется в висящем в памяти приложении ctfmon.exe,
появляющемся там после установки на компьютер Microsoft Office любой версии.
Что же это за программа? Вот что примерно написано на сайте Microsoft:
"Ctfmon.exe активизирует процессор текстового ввода (TIP) компонента "альтернативный ввод данных" и языковую панель Microsoft Office. Ctfmon.exe производит мониторинг активных окон и предоставляет поддержку клавиатуры перевода, распознавания речи и рукописных символов и других технологий альтернативного ввода данных. Ctfmon.exe остаётся в памяти даже после того, как все приложения Microsoft Office закрыты."
Проблема, которую необходимо решить для того, чтобы выполнялось нормальное
переключение раскладки клавиатуры, состоит в следующем. При нажатии комбинации клавиш, отвечающих за переключение клавиатуры, в процедуру-обработчик сообщений элемента окна поступают ДВА сообщения одновременно о том, что нужно переключить клавиатуру. Что и происходит: туда и обратно. В итоге имеем то, что было до нажатия клавиш.
Что же делать? Подсказку я нашёл в шаблоне Юрия Философова.
Для того, чтобы переключение произошло, необходимо запретить выполнение второй команды на переключение. Следовательно, нужно перехватывать передаваемые в процедуру-обработчик сообщения, отлавливать сообщения о переключении и передавать их в процедуру через одно.
Вот примерно для таких задач есть такая штука, как сабклассинг. Долгое время я читал советы о том, что нужно "просабклассить то-то и то-то и отлавливать то-то и то-то". И вот я знаю, что имелось в виду (надеюсь)!
Чтобы перехватывать сообщения, передаваемые в процедуру-обработчик сообщений элемента окна, нужно завести в программе процедуру, имеющую такой же интерфейс, что и процедура-обработчик:
Первый параметр - окно, принимающее сообщения;
второй параметр - идентификатор сообщения;
третий и четвёртый параметры - дополнительная информация, зависящая от сообщения.
Теперь нам надо "обмануть" программу, заставив посылать сообщения от компонентов окна в нашу процедуру. Для этого в Clarion есть два свойства элемента: Prop:WndProc и Prop:ClientWndProc.
Свойство Prop:WndProc позволяет установить или считать адрес процедуры-обработчика сообщений окна или определённого элемента управления; свойство Prop:ClientWndProc - установить или считать адрес процедуры-обработчика клиентской части окна (т.е. всего окна, за исключением заголовка м строки статуса).
После того, как мы выполним все необходимые нам действия, желательно (а скорее всего просто необходимо) вернуть всё-таки управление процедуре-обработчику, на этот раз с помощью API-функции, вызывающей и передающей информацию сообщения в указанную процедуру:
Здесь первый параметр - адрес той самой процедуры-обработчика, которую мы просабклассили. Его
мы должны запомнить:
Следовательно, порядок действий таков:
перед тем, как произойдёт какое-либо событие, мы должны:
1) запомнить адрес процедуры-обработчика для окна или его элемента:
2) вместо адреса процедуры-обработчика подсунуть программе адрес нашей процедуры.
В нашем обработчике:
3) выполнить нужные нам действия, проанализировав второй передаваемый параметр (идентификатор сообщения);
4) вернуть управление в настоящий обработчик:
5) желательно потом вернуть упаравление в настоящий обработчик совсем:
В Help Клариона есть подробные примеры того, как это работает и для чего это можно использовать.
Написал: Aragorn(147)
Решаем проблему переключения в WinXP и введение в сабклассинг.
часть 1 (не лезет вся, чевой-то

Общеизвестный факт того, что в приложениях, написанных на любой версии Clarion,
и работающих в среде WindowsXP, не переключается раскладка клавиатуры с русской
на английскую и наоборот, давно выводит из себя пользователей и заставляет
разработчиков искать различные способы переключения клавиатуры. Среди уже
известных способов наибольшей популярностью пользуются следующие четыре:
- удаление из памяти модуля ctfmon.exe;
- установка альтернативного переключателя клавиатуры (Ninja или Punto Switcher);
- использование шаблона Юрия Философова entrypoint.tpl;
- и, наконец, было подмечено, что, если выполнять переключение клавиатуры не
обычным ctrl+shift/alt+shift, а ctrl+shift shift/alt+shift shift (то есть
нажимая дважды shift, не отпуская ctrl(alt)), то переключение происходит. Что
и было некоторыми разработчиками взято даже на эксплуатацию.
Причина непереключения клавиатуры кроется в висящем в памяти приложении ctfmon.exe,
появляющемся там после установки на компьютер Microsoft Office любой версии.
Что же это за программа? Вот что примерно написано на сайте Microsoft:
"Ctfmon.exe активизирует процессор текстового ввода (TIP) компонента "альтернативный ввод данных" и языковую панель Microsoft Office. Ctfmon.exe производит мониторинг активных окон и предоставляет поддержку клавиатуры перевода, распознавания речи и рукописных символов и других технологий альтернативного ввода данных. Ctfmon.exe остаётся в памяти даже после того, как все приложения Microsoft Office закрыты."
Проблема, которую необходимо решить для того, чтобы выполнялось нормальное
переключение раскладки клавиатуры, состоит в следующем. При нажатии комбинации клавиш, отвечающих за переключение клавиатуры, в процедуру-обработчик сообщений элемента окна поступают ДВА сообщения одновременно о том, что нужно переключить клавиатуру. Что и происходит: туда и обратно. В итоге имеем то, что было до нажатия клавиш.
Что же делать? Подсказку я нашёл в шаблоне Юрия Философова.
Для того, чтобы переключение произошло, необходимо запретить выполнение второй команды на переключение. Следовательно, нужно перехватывать передаваемые в процедуру-обработчик сообщения, отлавливать сообщения о переключении и передавать их в процедуру через одно.
Вот примерно для таких задач есть такая штука, как сабклассинг. Долгое время я читал советы о том, что нужно "просабклассить то-то и то-то и отлавливать то-то и то-то". И вот я знаю, что имелось в виду (надеюсь)!
Чтобы перехватывать сообщения, передаваемые в процедуру-обработчик сообщений элемента окна, нужно завести в программе процедуру, имеющую такой же интерфейс, что и процедура-обработчик:
Код: Выделить всё
SubClassFunc Procedure(UShort,Short,UShort,Long),Long,Pacal
...
SubClassFunc Procedure(hWnd, wMsg, wParam, lParam)
Code
...
второй параметр - идентификатор сообщения;
третий и четвёртый параметры - дополнительная информация, зависящая от сообщения.
Теперь нам надо "обмануть" программу, заставив посылать сообщения от компонентов окна в нашу процедуру. Для этого в Clarion есть два свойства элемента: Prop:WndProc и Prop:ClientWndProc.
Свойство Prop:WndProc позволяет установить или считать адрес процедуры-обработчика сообщений окна или определённого элемента управления; свойство Prop:ClientWndProc - установить или считать адрес процедуры-обработчика клиентской части окна (т.е. всего окна, за исключением заголовка м строки статуса).
После того, как мы выполним все необходимые нам действия, желательно (а скорее всего просто необходимо) вернуть всё-таки управление процедуре-обработчику, на этот раз с помощью API-функции, вызывающей и передающей информацию сообщения в указанную процедуру:
Код: Выделить всё
CallWindowProc Procedure(Long,Unsigned,Signed,Unsigned,Long),Long,Pascal
мы должны запомнить:
Код: Выделить всё
SavedProc Long
...
SavedProc = <окно или элемент>{Prop:WindProc}
перед тем, как произойдёт какое-либо событие, мы должны:
1) запомнить адрес процедуры-обработчика для окна или его элемента:
Код: Выделить всё
SavedProc = <окно или элемент>{Prop:WindProc}
Код: Выделить всё
<окно или элемент>{Prop:WindProc} = Address(SubClassFunc)
3) выполнить нужные нам действия, проанализировав второй передаваемый параметр (идентификатор сообщения);
4) вернуть управление в настоящий обработчик:
Код: Выделить всё
Return(CallwindowProc(SavedProc, hWnd, wMsg, wParam, lParam)
Код: Выделить всё
<окно или элемент>{Prop:WindProc} = SavedProc
Написал: Aragorn(147)