Здравствуйте, Carc, Вы писали:
CEM>>Не, там совсем вроде без хука, хотя написано что это типа как хук(так и есть, но) там события посылаются мессаджами подписанному окну. Т.е. не надо писать отдельную функцию для хука. Я у себя эту штуку внедрил сразу, программа сразу стала легче и шустрее(та, которая в соседней ветке). C>Я про это и говорю: там в общем сводилось всё что-то вроде RegisterWindowMessage ("Чего_то_Shell_Hook_дай_мне_зараза_строка_вроде") и получаем сообщения в оконную. Но!!!
Эээ, стоп, погоди, к RegisterWindowMessage или всё-таки RegisterShellHookWindow? Вторая, которую я использовал, задокументирована и с ней вроде всё ок с 5-й НТи. Или вторая как-то сводится к первой?
Я ещё не зарелизился, но уже насторожился
Здравствуйте, CEMb, Вы писали:
CEM>Здравствуйте, Carc, Вы писали:
CEM>>>Не, там совсем вроде без хука, хотя написано что это типа как хук(так и есть, но) там события посылаются мессаджами подписанному окну. Т.е. не надо писать отдельную функцию для хука. Я у себя эту штуку внедрил сразу, программа сразу стала легче и шустрее(та, которая в соседней ветке). C>>Я про это и говорю: там в общем сводилось всё что-то вроде RegisterWindowMessage ("Чего_то_Shell_Hook_дай_мне_зараза_строка_вроде") и получаем сообщения в оконную. Но!!!
CEM>Эээ, стоп, погоди, к RegisterWindowMessage или всё-таки RegisterShellHookWindow? Вторая, которую я использовал, задокументирована и с ней вроде всё ок с 5-й НТи. Или вторая как-то сводится к первой? CEM>Я ещё не зарелизился, но уже насторожился
О!!! Век живи, век учись. А я это про эту новую приблуду RegisterShellHookWindow и не знал даже... Похоже они в 2К сделали документированный фасад к внутренней возможности. Сие уже совершенно друго-о-о-ое дело!
СПАСИБО за инфу!
Но кстати похоже что она, эта новая функция, по сути и делает то, что делала старая. Там тоже было надо регнуть мессагу через RegisterWindowMessage и именно с ней и получать инфу о смене языка... Я так, навскидку, строку для RegisterWindowMessage не помню, но что-то вроде того там и юзалось!
Здравствуйте, CEMb, Вы писали:
CEM>Здравствуйте, Carc, Вы писали:
CEM>>>Не, там совсем вроде без хука, хотя написано что это типа как хук(так и есть, но) там события посылаются мессаджами подписанному окну. Т.е. не надо писать отдельную функцию для хука. Я у себя эту штуку внедрил сразу, программа сразу стала легче и шустрее(та, которая в соседней ветке). C>>Я про это и говорю: там в общем сводилось всё что-то вроде RegisterWindowMessage ("Чего_то_Shell_Hook_дай_мне_зараза_строка_вроде") и получаем сообщения в оконную. Но!!!
CEM>Эээ, стоп, погоди, к RegisterWindowMessage или всё-таки RegisterShellHookWindow? Вторая, которую я использовал, задокументирована и с ней вроде всё ок с 5-й НТи. Или вторая как-то сводится к первой? CEM>Я ещё не зарелизился, но уже насторожился
Вот что подозрительно...
В описании RegisterShellHookWindow нет славного и столь нужного параметра HSHELL_LANGUAGE, коий явно присутствует в hook-функции для ShellHook. Так что получится ли так отловить смену языка таким образом — непонятно!?! Настораживает это однако
Здравствуйте, Carc, Вы писали:
CEM>>Я ещё не зарелизился, но уже насторожился C>Вот что подозрительно... C>В описании RegisterShellHookWindow нет славного и столь нужного параметра HSHELL_LANGUAGE, коий явно присутствует в hook-функции для ShellHook. Так что получится ли так отловить смену языка таким образом — непонятно!?! Настораживает это однако
Ага, непонятно. Но в хедере константа есть. (может просто в доке забыли описать, в мсдн-е много ошибок, особенно в коде, вчера ещё одну нашёл) Вобщем надо просто протестить этот момент и узнать, работает или нет. Всё упирается в топикстартера
Здравствуйте, CEMb, Вы писали:
CEM>Здравствуйте, Carc, Вы писали:
CEM>>>Я ещё не зарелизился, но уже насторожился C>>Вот что подозрительно... C>>В описании RegisterShellHookWindow нет славного и столь нужного параметра HSHELL_LANGUAGE, коий явно присутствует в hook-функции для ShellHook. Так что получится ли так отловить смену языка таким образом — непонятно!?! Настораживает это однако
CEM>Ага, непонятно. Но в хедере константа есть. (может просто в доке забыли описать, в мсдн-е много ошибок, особенно в коде, вчера ещё одну нашёл) Вобщем надо просто протестить этот момент и узнать, работает или нет. Всё упирается в топикстартера
Отрепортись плз, если пойдет и смена языка, ладно!?! Не в службу, а в дружбу...
Здравствуйте, Carc, Вы писали:
CEM>>>>Я ещё не зарелизился, но уже насторожился C>>>Вот что подозрительно... C>>>В описании RegisterShellHookWindow нет славного и столь нужного параметра HSHELL_LANGUAGE, коий явно присутствует в hook-функции для ShellHook. Так что получится ли так отловить смену языка таким образом — непонятно!?! Настораживает это однако
CEM>>Ага, непонятно. Но в хедере константа есть. (может просто в доке забыли описать, в мсдн-е много ошибок, особенно в коде, вчера ещё одну нашёл) Вобщем надо просто протестить этот момент и узнать, работает или нет. Всё упирается в топикстартера C>Отрепортись плз, если пойдет и смена языка, ладно!?! Не в службу, а в дружбу...
Отрепорчиваюсь: не работает (Win7 x64)
У меня уже было приложение с этим хуком, я поставитл отладку на все сообщения. По смене языка не прилетало ничего
Здравствуйте, CEMb, Вы писали:
CEM>Здравствуйте, Carc, Вы писали:
CEM>собственно меня с толку сбило название константы, я ловил тем же хуком HSHELL_REDRAW
А причем тут HSHELL_REDRAW? Каким образом это влияет на смену языка!?! Redraw по разным причинам может вызываться...
Здравствуйте, Carc, Вы писали:
C>Все просто: C>1) SetWindowsHookEx + WH_SHELL + HSHELL_LANGUAGE — получаем все извещения о смене языка.
C>2) SetWindowsHookEx + WH_CBT + HCBT_ACTIVATE|HCBT_SETFOCUS — получаем все переключения между окнами.
Спасибо, так и сделал.
Но почему-то WH_SHELL (nCmd==HSHELL_LANGUAGE) вызывается по нескольку раз при переключении активного (foreground) окна (т.е. похоже, что устанавливать хук WH_CBT нет смысла). Например, MFC диалог с List box'ом, при клике на лист бокс (когда диалог был неактивен), вызывает hook callback 4 раза с одним и тем же языком. При клике на заголовке неактивного MfС диалога — 3 раза подряд.
При нажатии Ctrl+Shift — callback вызывается один раз, как и положено.
Здравствуйте, Michaels1, Вы писали:
M>Здравствуйте, Carc, Вы писали:
C>>Все просто: C>>1) SetWindowsHookEx + WH_SHELL + HSHELL_LANGUAGE — получаем все извещения о смене языка.
C>>2) SetWindowsHookEx + WH_CBT + HCBT_ACTIVATE|HCBT_SETFOCUS — получаем все переключения между окнами.
M>Спасибо, так и сделал.
M>Но почему-то WH_SHELL (nCmd==HSHELL_LANGUAGE) вызывается по нескольку раз при переключении активного (foreground) окна (т.е. похоже, что устанавливать хук WH_CBT нет смысла). Например, MFC диалог с List box'ом, при клике на лист бокс (когда диалог был неактивен), вызывает hook callback 4 раза с одним и тем же языком. При клике на заголовке неактивного MfС диалога — 3 раза подряд.
M>При нажатии Ctrl+Shift — callback вызывается один раз, как и положено.
Ну в принципе можно ловить переключение окон и в WH_SHELL + HSHELL_WINDOWACTIVATED. Дело в другом. WH_CBT нужен чтобы знать кому именно потом послать WM_LANGCHANGEREQUEST, для этого он и нужен.
Хотя по любому — локаль принадлежит потоку, а не окну. В принципе в подавляющем большинстве случаев можно отослать и окну верхнего уровня, переключение которых мы увидим в WH_SHELL. Но, вообще говоря, чисто теоретически на окне верхнего уровня может лежать дочернее окно, которое крутит свой цикл обработки сообщений в другом потоке. Соответственно, тогда у него вполне может быть и независимая текущая локаль (язык). Такое конечно не часто увидишь. И вообще, нужно будет внимательно смотреть на конкретные детали. Но вот, к примеру MDI-дочки, которые работают в своем собственном потоке, независимо от главного потока MDI-мамы... Как в этом случае? WH_SHELL даст нам поймать переключение mdi-дочек или нет?
Вот для чего нужен WH_CBT, чтобы знать где фокус именно сию секунду. Ну и потом можно разводить и не такие ананизъмы. Если поковыряться, то как-то по моему можно и просто дочернее окошко (WS_CHILD) положить на парент-окошко, но со своим собственным потоком для выборки сообщений. Уж не помню, нафига это надо, но то что как-то можно было — в форуме здесь мелькало. Соответственно, в таких случаях WH_SHELL один-единственный задачу решать не будет.
PS: информация к размышлению: MS WebBrowser как дочерний контрол. Он дочерний, но дофига чего он там ассинхронно сам крутит. Это уже недра COM, и тут всё несколько совсем иначе будет. Но это как раз вполне жизненный пример на тему "куда думать": дочернесть дочернестью — а поток все-таки другой.
Здравствуйте, Carc, Вы писали:
C>Но, вообще говоря, чисто теоретически на окне верхнего уровня может лежать дочернее окно, которое крутит свой цикл обработки сообщений в другом потоке. Соответственно, тогда у него вполне может быть и независимая текущая локаль (язык). Такое конечно не часто увидишь. И вообще, нужно будет внимательно смотреть на конкретные детали. Но вот, к примеру MDI-дочки, которые работают в своем собственном потоке, независимо от главного потока MDI-мамы... Как в этом случае? WH_SHELL даст нам поймать переключение mdi-дочек или нет?
C>PS: информация к размышлению: MS WebBrowser как дочерний контрол. Он дочерний, но дофига чего он там ассинхронно сам крутит. Это уже недра COM, и тут всё несколько совсем иначе будет. Но это как раз вполне жизненный пример на тему "куда думать": дочернесть дочернестью — а поток все-таки другой.
Эти несколько HSHELL_LANG, которые система вызывает подряд для одного окна, являются проблемой вот почему:
мне нужно при включении одного языка зажечь scrolllock, а при другом языке — погасить.
Зажигаю его я вот так:
Но, поскольку я получаю несколько (четное к-во) callback вызовов, когда меняется раскладка, функция turnon() также вызывается неск. раз подряд быстро, и за это время состояние скролл лока не успевает поменяться (GetKeyState() возвращает одно и то же значение). В "буфер клавиатуры" выдается 2 пары keybd_event() и скролл лок просто мигает вместо того чтоб зажечься.
Вот теперь думаю как зажечь скролл "атомарно", если это возможно, чтоб он не гас при четном к-ве вызовов turnon().
Может у кого-нибудь есть идеи?
Здравствуйте, Michaels1, Вы писали:
M>Здравствуйте, Carc, Вы писали:
C>>Но, вообще говоря, чисто теоретически на окне верхнего уровня может лежать дочернее окно, которое крутит свой цикл обработки сообщений в другом потоке. Соответственно, тогда у него вполне может быть и независимая текущая локаль (язык). Такое конечно не часто увидишь. И вообще, нужно будет внимательно смотреть на конкретные детали. Но вот, к примеру MDI-дочки, которые работают в своем собственном потоке, независимо от главного потока MDI-мамы... Как в этом случае? WH_SHELL даст нам поймать переключение mdi-дочек или нет?
C>>PS: информация к размышлению: MS WebBrowser как дочерний контрол. Он дочерний, но дофига чего он там ассинхронно сам крутит. Это уже недра COM, и тут всё несколько совсем иначе будет. Но это как раз вполне жизненный пример на тему "куда думать": дочернесть дочернестью — а поток все-таки другой.
M>Эти несколько HSHELL_LANG, которые система вызывает подряд для одного окна, являются проблемой вот почему: M>мне нужно при включении одного языка зажечь scrolllock, а при другом языке — погасить. M>Зажигаю его я вот так:
M>void turnon() { M> if(!GetKeyState(VK_SCROLL)) { M> keybd_event( VK_SCROLL , 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0); M> keybd_event( VK_SCROLL , 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0); M> } M>}
M>Но, поскольку я получаю несколько (четное к-во) callback вызовов, когда меняется раскладка, функция turnon() также вызывается неск. раз подряд быстро, и за это время состояние скролл лока не успевает поменяться (GetKeyState() возвращает одно и то же значение). В "буфер клавиатуры" выдается 2 пары keybd_event() и скролл лок просто мигает вместо того чтоб зажечься.
M>Вот теперь думаю как зажечь скролл "атомарно", если это возможно, чтоб он не гас при четном к-ве вызовов turnon(). M>Может у кого-нибудь есть идеи?
Ну если в лоб, то зажигать Scroll Lock отложенно... Как-то так примерно.
1) Запоминаем время получения последнего HSHELL_LANG и взводим какой-нить оконный таймер (WM_TIMER) ну скажем на 500 миллисекунд.
2) Получаем WM_TIMER и проверяем время последнего получения HSHELL_LANG.
Если оно скажем меньше 500 мс, то ждем еще. Если больше — т.е. кагбэ последний HSHELL_LANG пришел уже "давно" — то включаем\выключаем Scroll Lock и заканчиваем ждать.
Ну это так. Костыль конечно. Опять же можно и без WM_TIMER делать, а в каком-нибудь фоновом потоке все ожидания выполнять. Это не суть важно как. Общая идея примерно такая же. В случае с потоком несколько аккуратнее приходится код писать, но зато работать чище будет — все косяки разом себя покажут.