К>Правда в документации. (А сила, брат, она в ньютонах). К>GetMessage
К>GetMessage ждёт появления виндовских сообщений в очереди сообщений текущего потока, и когда дожидается — извлекает очередное сообщение и возвращает false (если это сообщение было WM_QUIT) либо true (во всех остальных случаях).
Нет, не совсем так. Это распространенное заблуждение, но GetMessage не возвращается при приходе очередного сообщения. У потока как минимум 3 интересующих нас очереди сообщений: очередь сообщений, помещенных туда при помощи Send, ..., при помощи Post и очередь input сообщений. По крайней мере, так выглядит это извне. Так вот, GetMessage не возвращается на сообщения, посланные при помощи Send (на установленный флаг QS_SENDMESSAGE), и это явно сказано даже в документации:
function dispatches incoming sent messages until a posted message is available for retrieval
У Рихтера шаги работы GetMessage приведены как:
1. If the QS_SENDMESSAGE flag is turned on, the system sends the message to the proper window procedure. Both the GetMessage and PeekMessage functions handle this processing internally and do not return to the thread after the window procedure has processed the message; instead, these functions sit and wait for another message to process;
2. If messages are in the thread's posted-message queue, GetMessage and PeekMessage fill the MSG structure passed to these functions, and then the functions return. The thread's message loop usually calls DispatchMessage at this point to have the message processed by the appropriate window procedure.
3. If the QS_QUIT flag is turned on, GetMessage and PeekMessage return a WM_QUIT message (where the wParam parameter is the specified exit code) and reset the QS_QUIT flag.
4. If messages are in the thread's virtualized input queue, GetMessage and PeekMessage return the hardware input message.
5. If the QS_PAINT flag is turned on, GetMessage and PeekMessage return a WM_PAINT message for the proper window.
6. If the QS_TIMER flag is turned on, GetMessage and PeekMessage return a WM_TIMER message.
К>Причём программа не циклится в недрах системы, а висит на ожидании. Т.е. прервать (break) этот поток отладчиком не получится.
К>Если хочешь проверить, не ожидая — пожалуйста: PeekMessage.
Ровно такой же алгоритм, за исключением того, что эта функция не ожидает прихода posted сообщений, а просто возвращает FALSE, если их нет.
здесь удобно, что все функции, выставляющие хук находятся внутри самой dll, и таким образом получают премущество в виде shared memory section. образно говоря, внутри dll можно сделать память, которая будет общей для этой dll, даже если она была загружена в другой процесс.
ну вот, с приложение мы разобрались, осталось написать код внутри dll, сначала ставим хук, потом процедура, которая называется сабклассированием.
момент — CallNextHookEx() получает хендл хука, который был установлен. а если я устанавливаю его в одном процессе, например, в своем, а он потом вызывается другой, например из калькулятора:
1) в адресное пространство калькулятора загружается hookDll.dll
2) там ищется функция CBTProc
3) вызывается оная.
и внутри неё нам нужно вызвать следующий хук ( они там в очереди все стоят ). но SetWindowsHookEx я вызывал в другом процессе, значит и хендл хука в другом процессе. вот тут-то и пригодятся shared memory section. они позволяют сказать линкеру, что вот эта область память будет доступна для всех длл, неважно где и когда они загрузились.
конкретно, в эту область нам надо поместить HHOOK hook. в результате получается
V>Относительно статьи. Я, конечно, может и ошибаюсь, но она меня не совсем устраивает. Я писал конечно длл компоненты для 1с на си шарпе, но на другой фирме. А здесь это сделать нелегко. У нас около 30 филиалов разбросаных по Украине. и устанавливать на кждом по .NET Framework не сахар . Кроме того, есть калькуляторы, у которых установлено Вынь 98. А всего этих компьютеров насчитывается около 150 штук!
Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.
V>Неужто придется выбирать вариант "удалять гланды через анус"?
V>Вот еще одна статья: http://www.codeguru.com/Cpp/W-P/system/keyboard/article.php/c5699/ . Вот только мне не виртся, что получив HANDLE окна я не могу достучаться до WM_CHAR этого окна и получить код символа. В вышописанной статье путь конечно супер гиморный. Может посоветуете билиотеки какие?
Все, что надо делать, я уже написал. Внимательно прочитайте написаное, ипользуйте поиск по форуму. Тема сабклассинга окна в чужом приложении тут обсуждалась, и даже были примеры кода. Но еще раз — на мой взгляд, хуки вам не нужны. Все, что нужно — написать inproc com сервер, который будет загружаться при открытии нужной вам формы. Вы же ведь можете при ее открытии выполнять скрипт?
Здравствуйте, Ovl, Вы писали:
Ovl>Здравствуйте, Votblin, Вы писали:
V>>Здравствуйте, Ovl, Вы писали:
Ovl>>>Здравствуйте, Votblin, Вы писали:
V>>>>И что, действительно я смогу отловить нажатую клавишу для определенного контрола?
V>>>>ДА и непонятно как юзать этот SetWindowsHook(...)
V>>>>Не мотгли бы Вы подкинуть козу учитывая вышеприведенный код?
V>>>>Не бросайте на произвол ламера!
Ovl>>>не знаю что такое коза. но вот примеры из мсдн. Ovl>>>Using Hooks
V>>А Вы уверены, что я перехвачу нажатие кнопки именно для определенного контрола (см. вышеприведенный код) ?
Ovl>сообщение о нажатии кнопки отправляется окну, например кнопка в общем случае — это тоже окно Ovl>какому именно — можно определить по hwnd. соответственно сообщения для всех остальных окон — можно пропускать
плохо написал....
ловятся сообщения для всех окон в системе. ваше дело — отфильтровать не нужные.
к примеру
пришло сообщение окну hWnd, вызывается ваша хук-процедура.
смотрите у него parent window, если это "CVotBlinTable", то hWnd — ваш клиент. в противном случае — просто вызываете следующий хук вызовом CallNextHookProc
Дело в том, что у меня GetMessage(&msg, NULL, 0, 0) не возвращает никакого значение.
Т.е. такое впечатление, будто прога зашла куда в глубины GetMessage() и там гдето зациклилось.
Чем лечить? В чем правда?
12.09.05 15:34: Перенесено модератором из 'Этюды для программистов' — Кодт
Здравствуйте, Votblin, Вы писали:
V>Если я не туда запостил, плиз расскажите куда нужно таки?
V>Юзаем С++ в Visual Studio .NET
V>вот кусочек кода.
V>BOOL bRet = true; V>MSG msg; V>bRet = GetMessage(&msg, NULL, 0, 0);
V>Дело в том, что у меня GetMessage(&msg, NULL, 0, 0) не возвращает никакого значение. V>Т.е. такое впечатление, будто прога зашла куда в глубины GetMessage() и там гдето зациклилось.
V>Чем лечить? В чем правда?
The GetMessage function retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.
то есть она возвращается, только когда в очереди сообщений что-то появляется — операция синхронная.
проверить, есть ли что-нибдуь в очереди можно функцией PeekMessage
V>Дело в том, что у меня GetMessage(&msg, NULL, 0, 0) не возвращает никакого значение. V>Т.е. такое впечатление, будто прога зашла куда в глубины GetMessage() и там гдето зациклилось.
V>Чем лечить? В чем правда?
Правда в документации. (А сила, брат, она в ньютонах). GetMessage
GetMessage ждёт появления виндовских сообщений в очереди сообщений текущего потока, и когда дожидается — извлекает очередное сообщение и возвращает false (если это сообщение было WM_QUIT) либо true (во всех остальных случаях).
Причём программа не циклится в недрах системы, а висит на ожидании. Т.е. прервать (break) этот поток отладчиком не получится.
Если хочешь проверить, не ожидая — пожалуйста: PeekMessage.
Здравствуйте, Votblin, Вы писали:
V>И что, действительно я смогу отловить нажатую клавишу для определенного контрола?
V>ДА и непонятно как юзать этот SetWindowsHook(...)
V>Не мотгли бы Вы подкинуть козу учитывая вышеприведенный код?
V>Не бросайте на произвол ламера!
не знаю что такое коза. но вот примеры из мсдн. Using Hooks
Здравствуйте, Ovl, Вы писали:
Ovl>Здравствуйте, Votblin, Вы писали:
V>>И что, действительно я смогу отловить нажатую клавишу для определенного контрола?
V>>ДА и непонятно как юзать этот SetWindowsHook(...)
V>>Не мотгли бы Вы подкинуть козу учитывая вышеприведенный код?
V>>Не бросайте на произвол ламера!
Ovl>не знаю что такое коза. но вот примеры из мсдн. Ovl>Using Hooks
А Вы уверены, что я перехвачу нажатие кнопки именно для определенного контрола (см. вышеприведенный код) ?
Здравствуйте, Votblin, Вы писали:
V>Здравствуйте, Ovl, Вы писали:
Ovl>>Здравствуйте, Votblin, Вы писали:
V>>>И что, действительно я смогу отловить нажатую клавишу для определенного контрола?
V>>>ДА и непонятно как юзать этот SetWindowsHook(...)
V>>>Не мотгли бы Вы подкинуть козу учитывая вышеприведенный код?
V>>>Не бросайте на произвол ламера!
Ovl>>не знаю что такое коза. но вот примеры из мсдн. Ovl>>Using Hooks
V>А Вы уверены, что я перехвачу нажатие кнопки именно для определенного контрола (см. вышеприведенный код) ?
сообщение о нажатии кнопки отправляется окну, например кнопка в общем случае — это тоже окно
какому именно — можно определить по hwnd. соответственно сообщения для всех остальных окон — можно пропускать
У нас есть какая то программка (конечно же без source code). Или даже так: у нас есть 1с v8.0.
И проблема в том, что в табличной части формы спика документов не отлавливается нажатие клавиш. Чтобы их все-таки отловить, я пытаюсь "споймать" message нужного окна.
Т.о. я сначалаи выискиваю handle этого окна, а далее пытаюсь с этого найденного окна словить сообщение ну пусть WM_CHAR. В конце концов, SPY++ ведь это както делает!
V>У нас есть какая то программка (конечно же без source code). Или даже так: у нас есть 1с v8.0. V>И проблема в том, что в табличной части формы спика документов не отлавливается нажатие клавиш. Чтобы их все-таки отловить, я пытаюсь "споймать" message нужного окна. V>Т.о. я сначалаи выискиваю handle этого окна, а далее пытаюсь с этого найденного окна словить сообщение ну пусть WM_CHAR. В конце концов, SPY++ ведь это както делает!
Вы это пытаетесь делать извне или из inproc com сервера, например? Если извне, то, как уже тут говорили, на первый взгляд только хук + сабклассинг поможет. Вкратце технология была уже описана. Используем глобальный хук (например, shell или cbt), внедряемся в целевое приложение, загружаем dll, в которой будет наша процедура сабклассинга, сабклассируем. Можно, конечно, просто глобальный хук на WNDPROC или клавиатуру, но описанная выше методика гораздо более кошерна. Но все равно, и тот, и тот вариант — это как удалять гланды через анус. Лучше написать com расширение для 1c, загружать его из скрипта и из него сабклассировать окно. Это будет и переносимо, и без каких-либо хаков.
Пример можно посмотреть тут: http://gzip.rsdn.ru/article/dotnet/cs1c.xml
В общем, главное попасть в адресное пространство 1с. А уж там перехватить\обработать нужные сообщения проблем не будет. Кстати, наверняка для нужного вам контрола есть и более легальные варианты, чем сабклассирование. Может, стоит спросить на специализированном форуме?
Здравствуйте, Andrew S, Вы писали:
V>>У нас есть какая то программка (конечно же без source code). Или даже так: у нас есть 1с v8.0. V>>И проблема в том, что в табличной части формы спика документов не отлавливается нажатие клавиш. Чтобы их все-таки отловить, я пытаюсь "споймать" message нужного окна. V>>Т.о. я сначалаи выискиваю handle этого окна, а далее пытаюсь с этого найденного окна словить сообщение ну пусть WM_CHAR. В конце концов, SPY++ ведь это както делает!
AS>Вы это пытаетесь делать извне или из inproc com сервера, например? Если извне, то, как уже тут говорили, на первый взгляд только хук + сабклассинг поможет. Вкратце технология была уже описана. Используем глобальный хук (например, shell или cbt), внедряемся в целевое приложение, загружаем dll, в которой будет наша процедура сабклассинга, сабклассируем. Можно, конечно, просто глобальный хук на WNDPROC или клавиатуру, но описанная выше методика гораздо более кошерна. Но все равно, и тот, и тот вариант — это как удалять гланды через анус. Лучше написать com расширение для 1c, загружать его из скрипта и из него сабклассировать окно. Это будет и переносимо, и без каких-либо хаков. AS>Пример можно посмотреть тут: http://gzip.rsdn.ru/article/dotnet/cs1c.xml
AS>В общем, главное попасть в адресное пространство 1с. А уж там перехватить\обработать нужные сообщения проблем не будет. Кстати, наверняка для нужного вам контрола есть и более легальные варианты, чем сабклассирование. Может, стоит спросить на специализированном форуме?
Уважаемый, я в 1с кручусь уже 6 лет, так что поверьте — не поможет обращение в другие форумы. А то что Вы написали не совсем мне понятно, поскольку в с++ я не такой уж мастак осоебнно в WinAPI.
А прмерчик гляну обязательно, но уже утром пожалуй — спать пора!
AS>>В общем, главное попасть в адресное пространство 1с. А уж там перехватить\обработать нужные сообщения проблем не будет. Кстати, наверняка для нужного вам контрола есть и более легальные варианты, чем сабклассирование. Может, стоит спросить на специализированном форуме?
V>Уважаемый, я в 1с кручусь уже 6 лет, так что поверьте — не поможет обращение в другие форумы. А то что Вы написали не совсем мне понятно, поскольку в с++ я не такой уж мастак осоебнно в WinAPI.
В то, что обращение в другие форумы, специализированные под 1с, не поможет — я не верю. Лично я знаю ребят, которые с 1с могут сделать все что угодно.
Ну а касательно выделенной фразы — а что вы ждали? Готового кода? И каким образом С++ связано с WinApi, уже не понимаю я
AS>В то, что обращение в другие форумы, специализированные под 1с, не поможет — я не верю. Лично я знаю ребят, которые с 1с могут сделать все что угодно.
Не верьте, это Ваше дело. Но, проверно, а вот в это поверьте. Самое интересное, что фича с быстрым поиском документов в 1с 77 была. Но в 1с 8.0 с целью улучшения производительности исчезла в том виде, что была в 1с 7.7. Однако что в 1с77 что в 1с80 нет функции, которая реагирует на нажатие клавиатуры. С героической фирмы ABBYY я слышал лишь только слабые повякивания, смысл которых сводился сначала в кпроверки а лицензионная у меня 1с, потом лицензионный у меня виндовз, а потом что у меня за конфйигурация (УТ, УПП, или еще что нибудь, причем не дай Бог самописная!). Вот и два месяца назад я договорился аж получить наконецто диск ИТС, который так до сих пор и не пришел... Так что, то что касается франче — тема больная. Ну а то что, 1с-ки действительно на все руки мастера — это често, особенно не которые работают о франчах, а фикси. Ибо во франчах человек в-основном занят внедрением, а фикси или фрилансер — он занят разработкой конкретной.
Относительно статьи. Я, конечно, может и ошибаюсь, но она меня не совсем устраивает. Я писал конечно длл компоненты для 1с на си шарпе, но на другой фирме. А здесь это сделать нелегко. У нас около 30 филиалов разбросаных по Украине. и устанавливать на кждом по .NET Framework не сахар . Кроме того, есть калькуляторы, у которых установлено Вынь 98. А всего этих компьютеров насчитывается около 150 штук!
Неужто придется выбирать вариант "удалять гланды через анус"?
Вот еще одна статья: http://www.codeguru.com/Cpp/W-P/system/keyboard/article.php/c5699/ . Вот только мне не виртся, что получив HANDLE окна я не могу достучаться до WM_CHAR этого окна и получить код символа. В вышописанной статье путь конечно супер гиморный. Может посоветуете билиотеки какие?
Здравствуйте, Andrew S, Вы писали:
V>>Ну создам я очередную компоненту, что тогда делать то? Как перехватить?
AS>Применить сабклассирование. Находите нужное окно, сабклассируете его, и в своей WNDPROC обрабатываете нужные сообщения.
ОК, Andrew S. Спасибо. Вы супер. сейчас попробую. Эхх...
Здравствуйте, Andrew S, Вы писали:
V>>Относительно статьи. Я, конечно, может и ошибаюсь, но она меня не совсем устраивает. Я писал конечно длл компоненты для 1с на си шарпе, но на другой фирме. А здесь это сделать нелегко. У нас около 30 филиалов разбросаных по Украине. и устанавливать на кждом по .NET Framework не сахар . Кроме того, есть калькуляторы, у которых установлено Вынь 98. А всего этих компьютеров насчитывается около 150 штук!
AS>Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.
AS>>Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.
Ovl>а com на 98-ой есть? или патчитить калькуляторы?
Странный вопрос. Com есть на 95-х. 1с же активно использует ActiveX\Com объекты, насколько я помню по своему давнему опыту общения с этим сабпродуктом.
Здравствуйте, Andrew S, Вы писали:
AS>>>Нда, что делает с человеком занятие 1с. При чем тут Net? Там был показан способ создания Com сервера для 1c. С тем же успехом это можно сделать и на ATL.
Ovl>>а com на 98-ой есть? или патчитить калькуляторы?
AS>Странный вопрос. Com есть на 95-х. 1с же активно использует ActiveX\Com объекты, насколько я помню по своему давнему опыту общения с этим сабпродуктом.
вопрос не странный. просто я не знаю когда именно появился ком, не думал, что это было до появления 98.
однако в msdn:
HRESULT CoInitialize(
LPVOID pvReserved
);
Windows NT/2000/XP: Requires Windows NT 3.1 or later.
Windows 95/98: Requires Windows 95 or later.
Header: Declared in objbase.h.
Library: Use ole32.lib.
а вот насчет activeX — интуиция мне подсказывает, что наличие activeX коррелирует с наличием IE4.0
Здравствуйте, Andrew S, Вы писали:
Ovl>>посмотрел я посты — действительно, хук + сабклассинг более верно.
AS>Я думаю, не нужен там хук. 1c позволяет писать под себя плагины.
тем проще. однако я из кода не видно, что написание хука труднее.
в любом случае — это один из альтернативных вариантов. не пригодится ему — пригодится другому..
Здравствуйте, Andrew S, Вы писали:
Ovl>>а вот насчет activeX — интуиция мне подсказывает, что наличие activeX коррелирует с наличием IE4.0
AS>Интуиция вас обманывает. Для начала неплохо разобраться, что такое ActiveX
да, неплохо бы...
хотя мне бы программировать научится — и то удачно
Здравствуйте, Votblin, Вы писали:
V>Все конечно здорово, вот только не понятно что находится в
V>SubсlassWindow( (HWND) wParam );
V>Наверно у Вас эта длл магическим образом скомпилировалась...
Здравствуйте, Votblin, Вы писали:
V>Здравствуйте, Votblin, Вы писали:
V>>Все конечно здорово, вот только не понятно что находится в
V>>SubсlassWindow( (HWND) wParam );
V>>Наверно у Вас эта длл магическим образом скомпилировалась...
V>Всё ясно... Видать обиделся....
скорее просто не заметил или пропустил
это функция есть в листингах ранее
Здравствуйте, Votblin, Вы писали:
V>Сори, янаверно тебя уже достал конкретно, но в
V>void SubclassWindow( HWND hwnd ) V>{ V> if ( oldProc == NULL ) V>{ V> oldProc = SetClassLongPtr( hwnd, GCLP_WNDPROC, NewWndProc ); V> } V>}
V>Определенно тот не то с возращаемым параметром и третим параметром тоже
Здравствуйте, Ovl, Вы писали:
Ovl>Здравствуйте, Votblin, Вы писали:
V>>А как юзать эту длл теперь.
V>>Важный момент...
Ovl>загрузить LoadLibrary, получить адрес процедуры, после чего вызвать оттуда функцию SetHook. Ovl>это я написал в листинге. смотри там внимательнее.
Ovl>зы. пришло письмецо — не от вас?
Вав!!! Какая романтичная история с хуками и dll'ми! Гы-гы-гы, извините не удержал_со
Сам когда с этим возился
Если не трудно, напишите потом чем все это закончилось, а то я не люблю читать романы без хеппи-эндов, гы-гы-гы ...
Здравствуйте, ExceptionGranted, Вы писали:
EG>Вав!!! Какая романтичная история с хуками и dll'ми! Гы-гы-гы, извините не удержал_со EG>Сам когда с этим возился EG>Если не трудно, напишите потом чем все это закончилось, а то я не люблю читать романы без хеппи-эндов, гы-гы-гы ...
хэппи энда не будет видимо
пример с CBT хуком у меня глючил