Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Сообщение WM_KEYUP


Автор: Nastya 4.2.2003, 23:41
Такая ситуация. Пустое диалоговое окно. Обрабатываю сообщенеи WM_KEYUP, WM_KEYDOWN. Все хорошо. Стоит поставить на него или статик или кнопку(любой элемент) и сообщение уже "достается" тому элементу и до самого окна не доходит. Что желать.
А если элементов на окне не один.

Автор: Baa 5.2.2003, 00:23
легким движением руки этого порешить не получилось (в виду не особо хорошего знания MFC)
Возможные варианты решения:
Если делать прогу без MFC, то там все просто...
Можно использовать DirectInput.
з.ы. грамотные люди, я бы тож очень хотел знать ответ на этот вопрос smile.gif

Автор: Guest_Paradox 5.2.2003, 00:38
Дело в том что как только появляется на форме некоторый визуальный компонент Windows передает фокус ему и все сообщения начинает получать этот компонент и соответственно обрабатывать их своими обработчиками по умолчанию. Надо просто убрать с него фокус ввода, если интересно отвечу подробнее...

Автор: Vaulter 5.2.2003, 00:49
создай кнопку со стилем PARENTNOTIFY что то типа того. тогда сообщения от контрола будут идти в окно в форме WM_NOTIFY сообщения. но от самого окна также должно все идти как и раньше

Автор: Nastya 5.2.2003, 01:12
Цитата
Надо просто убрать с него фокус ввода, если интересно отвечу подробнее...


Надо...
Спасибо...

Автор: HexoGen(i)us 9.2.2003, 07:42
Одна из возможных проблем: для того что бы убрать фокус ввода с компонента на окне как мне кажется само окно должно иметь возможность получить этот фокус... для этого окно нужно создавать со стилем WS_TABSTOP
второе что нам нужно это сделать так что бы если кнопка по каким либо причинам получила фокус то чтобы она его тут же отдавала (типа не тронь бяку)
Для этого мы можем задать ей стиль BS_NOTIFY и она будет пересылать все свои нотификационные сообщения родительскому окну...

А вот сами сообщения
#define BN_CLICKED 0
#define BN_PAINT 1
#define BN_HILITE 2
#define BN_UNHILITE 3
#define BN_DISABLE 4
#define BN_DOUBLECLICKED 5
#if(WINVER >= 0x0400)
#define BN_PUSHED BN_HILITE
#define BN_UNPUSHED BN_UNHILITE
#define BN_DBLCLK BN_DOUBLECLICKED
#define BN_SETFOCUS 6
#define BN_KILLFOCUS 7
#endif /* WINVER >= 0x0400 */

Вобщем я так понимаю тебе нужно отлавливать нотификационное сообщение BN_SETFOCUS (возможно и сообщение при нажатии WM_COMMAND)
и передавать фокус своему окну SetFocus(HandleMyWindow);

Извини если все это не сработает... если честно я не знаю как правильно работать с сообщениями хотя и приходится их постоянно использовать...
я все это опробывал в билдере а в нем сообщения перехватываются как я понимаю не так как в VC++
если не получится пиши smile.gif поставлю себе VC++ и будем думать вместе...

Автор: Chegal 26.2.2005, 08:45
Может уже не актуально, но вдруг кому-то понадобится (сам искал все утро):
для обработки ЛЮБЫХ сообщений до того как они будут переданы соответствующим дочерним окнам
используем в MFC - BOOL PreTranslateMessage(MSG* pMsg) т.е. CTRL+w ->Messages->PreTranslateMessage
(можно и вручную), после чего для обработки, например, клавиатуры вставляем код:

BOOL CCommanderDlg::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
if (pMsg->message==WM_KEYDOWN && pMsg->wParam== VK_DOWN) {
AfxMessageBox("Нажата клавиша вниз!");
}
return CDialog::PreTranslateMessage(pMsg);
}


Автор: Гость_ghost 16.6.2005, 01:34
не с++, все на API.

есть диалог, на нем два десятка EditBox и две кнопки

в главном цикле диалога ловлю любые изменения в любом EditBox которые EditBox видимо посылает сам (типа я изменился)
проблема.
не могу отловить WM_KEYDOWN для служебных клавиш (Insert/Home/End)

Могу конечно создать личный обработчик для каждого EditBox, но как то уж очень грамоздко.
у кого какие идеи ??
smile

Автор: chaos 16.6.2005, 06:10
Цитата
не могу отловить WM_KEYDOWN для служебных клавиш (Insert/Home/End)


а по моему для этого WM_SYSKEYDOWN нужен

Автор: Гость_ghost 16.6.2005, 17:37
WM_SYSKEYDOWN ловит Shift/Ctrl/Alt ;(

Автор: Earnest 17.6.2005, 20:23
Цитата
Могу конечно создать личный обработчик для каждого EditBox, но как то уж очень грамоздко.
у кого какие идеи ??


1) Обработчик может быть один -> новая WindowProc -> класс для всех ваших edit'ов.
2) По-моему Hook, повешенный на окно, должен ловить сообщения детям/от детей, но точно не помню...

Автор: Fantasist 18.6.2005, 20:12
Цитата(Earnest @ 17.6.2005, 17:23)
2) По-моему Hook, повешенный на окно, должен ловить сообщения детям/от детей, но точно не помню...


О каких Нооках идет речь? Если те, что SetWindwsHookEx - так они вешаются только на поток/процесс.

А так просто своя WindowProc обычно выручает.


Автор: Earnest 20.6.2005, 08:02
Да, SetWindowsHookEx, WH_KEYBOARD, можно повесить на поток, которому принадлежит окно и ловить весь клавиатурный ввод. Хотя в hook-процедуру окно не передается, но узнать, кто сейчас в фокусе, не проблема.
Но не могу не согласиться, что для данной задачи проще и естественнее своя WindowProc.

Автор: Guest 20.6.2005, 19:24
>>для данной задачи проще и естественнее своя WindowProc.

Куда уже проще

Код

BOOL CALLBACK cogoDlgProc( HWND dialog, UINT message, WPARAM wParam, LPARAM lParam )
{

switch ( message )
{
  case WM_INITDIALOG :
    initialize_dialog( dialog ) ;
    return TRUE ;
  case WM_COMMAND :    
    do_Command( dialog, message, wParam, lParam ) ; 
    return TRUE;
  case WM_CLOSE :
    close_Dialog( dialog ) ; 
    return TRUE ;
  default :
    return FALSE ;
}
}


Только case WM_COMMAND на нажатие клавиш Home/End не реагирует
Пришлось создать новую EditBoxProc v case WM_INITDIALOG :

SetWindowLong( GetDlgItem( dialog, NUM_0 ),GWL_WNDPROC, (LONG) EditBoxProc ) ;

а потом в EditBoxProc ловить WM_KEYDOWN


Все же попробую SetWindowsHookEx, может получится

Автор: Earnest 20.6.2005, 19:40
Цитата
Только case WM_COMMAND на нажатие клавиш Home/End не реагирует

Естественно, это не WM_COMMAND, а WM_KEYDOWN, причем приходящие одному из дочерних окон.

Цитата
Пришлось создать новую EditBoxProc v case WM_INITDIALOG :

Собственно, именно это и имелось в виду.

Автор: Guest 20.6.2005, 20:06
WM_KEYDOWN в главный цикл не попадает, а писать "новую EditBoxProc в case WM_INITDIALOG" для каждого EditBoxа кажется не совсем уместным, к тому же к етим EditBoxам уже добавилось 4 ComboBоxа, и что появится дальше никому не ихвестно smile

Автор: Guest 20.6.2005, 21:15
поставил SetWindowsHookEx, cool.

при иницизлизации
KeyboardHook = SetWindowsHookEx( WH_KEYBOARD , (HOOKPROC) HookOnKeyboard, NULL , GetCurrentThreadId());


Код

LRESULT CALLBACK HookOnKeyboard(int nCode,WPARAM wParam,LPARAM lParam )
{
  Beep(1000,1000); 
}

Теперь другая проблемма, ф-я KeybardProc отрабатывет дважды,а на breakpoint остнавливается один раз smile

Автор: Earnest 21.6.2005, 07:50
1) Может, это WM_KEYDOWN и WM_KEYUP ?

2) Если клавишу держать "long enough", код WM_KEYDOWN повторяется, см. описание WM_KEYDOWN в MSDN
Цитата

...
lParam
Specifies the repeat count, scan code, extended-key flag, context code, previous key-state flag, and transition-state flag, as shown in the following table.
0-15
Specifies the repeat count for the current message. The value is the number of times the keystroke is autorepeated as a result of the user holding down the key. If the keystroke is held long enough, multiple messages are sent. However, the repeat count is not cumulative.
...

Автор: Fantasist 21.6.2005, 08:13
Цитата(Earnest @ 20.6.2005, 05:02)
Да, SetWindowsHookEx, WH_KEYBOARD, можно повесить на поток, которому принадлежит окно и ловить весь клавиатурный ввод. Хотя в hook-процедуру окно не передается, но узнать, кто сейчас в фокусе, не проблема.


Безусловно это не проблема, однако было утверждение о вешании хука на окно, вот я и уточнил, о чем речь.
Далее. Я считаю использование хуков в данном случае это из пушки по воробьям. Во-первых, они явно создают лишнюю нагрузку. Во-вторых, сама идиология перехвата сообщений внутри своей программы мне кажется странноватой. В твоей программе control flow должен контролироваться логикой программы, а не перехватами.

Цитата(Earnest @ 20.6.2005, 05:02)
Но не могу не согласиться, что для данной задачи проще и естественнее своя WindowProc.


Своя WindowProc - это не обязательно своя реализация ее. Из своей WindowProc вполне можно вызвать стандартную, сохранив ее перед этим вызвав GetWindowLong();

Автор: Earnest 21.6.2005, 17:08
Цитата(Fantasist @ 21.6.2005, 08:13)
Я считаю использование хуков в данном случае это из пушки по воробьям. Во-первых, они явно создают лишнюю нагрузку. Во-вторых, сама идиология перехвата сообщений внутри своей программы мне кажется странноватой. В твоей программе control flow должен контролироваться логикой программы, а не перехватами.

В общем, конечно, правильно. Но...
Цитата(Guest @ 20.6.2005, 20:06)
к тому же к етим EditBoxам уже добавилось 4 ComboBоxа, и что появится дальше никому не ихвестно

Нельзя не посочувствовать автору... Писать хоть и тривиальные, но разные обработчики для новых типов контролов ... бр ...
Хотя я бы, наверно, в такой гипотетической ситуации (только API, без с++), написала свой модальный цикл, как это делается в том же MFC. И уж там, между GetMessage и DispatchMessagе можно делать все что угодно.

Автор: Гость_ghost 24.6.2005, 21:06
может оно и из пушки по воробьям smile

Но в dialog у меня что то типа GRID для базы, за последнюю неделю добаволось еше пару комбов и с десяток edit, дурдом, на МФС можно было бы за неделю все сделать(я думаю) может даже ActiveX какой впихнуть, а тут толко Си


1) Может, это WM_KEYDOWN и WM_KEYUP ?
тогда бы он на breakpoint остановился бы


короче, в HookOnKeyboard HIWORD(lParam) приходит один раз с нормальным кодом
и тут же с какойто хернеЙ которая > 49000 , что ето такое нигде не нашел smile
да черт с ней .

Работает ? Не трогай : smile

Автор: Earnest 24.6.2005, 22:15
Цитата
) Может, это WM_KEYDOWN и WM_KEYUP ?
тогда бы он на breakpoint остановился бы


Не обязательно. На WM_KEYDOWN остановится, а WM_KEYUP уже в другой процесс попадет... Т.к. активно в этот момент будет окно отладчика. Поймать KEYUP можно только, если пропускать KEYDOWN...

Цитата
короче, в HookOnKeyboard HIWORD(lParam) приходит один раз с нормальным кодом
и тут же с какойто ... которая > 49000 , что ето такое нигде не нашел

Набери в MSDN WM_KEYDOWN и все тебе про параметры расскажут - там битовая структура. Если надо, конечно...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)