WM_KEYDOWN на две клавиши
От: Andrew__S Россия  
Дата: 21.06.03 04:53
Оценка:
Здравствуйте.
Приношу свои извинения за повтор вопроса. Но поиск так и не помог.
Есть многооконная программа (это, наверное, не важно). В одно из ее
окон надо послать комбинацию клавиш с CTRL. Т.е., например, CTRL+B.
Пишу (в C++ Builder-е):

SendMessage(hWnd,WM_KEYDOWN, VK_CONTROL, 0);
SendMessage(hWnd,WM_KEYDOWN, 0x42, 0);
SendMessage(hWnd,WM_KEYUP...
SendMessage(hWnd,WM_KEYUP...


CTRL не удерживается...
Да, и 0 как LPARAM не работает, хотя везде в примерах (в т.ч. здесь) — 0.

Откуда ноги растут?
Спасибо.
Re: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 21.06.03 05:50
Оценка:
Здравствуйте, Andrew__S, Вы писали:

A__>Здравствуйте.

A__>Приношу свои извинения за повтор вопроса. Но поиск так и не помог.
A__>Есть многооконная программа (это, наверное, не важно). В одно из ее
A__>окон надо послать комбинацию клавиш с CTRL. Т.е., например, CTRL+B.
A__>Пишу (в C++ Builder-е):

A__>
A__>SendMessage(hWnd,WM_KEYDOWN, VK_CONTROL, 0);
A__>SendMessage(hWnd,WM_KEYDOWN, 0x42, 0);
A__>SendMessage(hWnd,WM_KEYUP...
A__>SendMessage(hWnd,WM_KEYUP...
A__>


A__>CTRL не удерживается...

A__>Да, и 0 как LPARAM не работает, хотя везде в примерах (в т.ч. здесь) — 0.

Ноги растут именно от того, что ты на 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.
Я так понял, что обработчик у того окна твой собственный. Возьми и поставь в WM_KEYDOWN точку прерывания, но не на входе, а то ты комбинацию так и не отловишь, а с проверкой того бита в скан коде, который сигнализирует о нажатых extended key. И на всякий случай, чтобы уж точно быть уверенным, если это тоже обрабатывается соответствующим образом, то и WM_KEYUP. Исделай соответствующие вызовы:

SendMessage(hWnd, WM_KEYDOWN, 0x42, scan);
SendMessage(hWnd, WM_KEYUP, 0x42, scan); — если это необходимо, потому что если ты просто хочешь вызвать обработчик, то keydown достаточно.
Если ты хочешь смоделировать реальное нажатие клавиш, то это совсем другая история.

И не забывай о возможных последствиях работы SendMessage. Если тебе просто нужно поставить в очередь сообщение, то PostMessage тебе вполне достаточно и есть еще один схожый механизм SendMessageTimeout, который иногда предотвращает зависание.
Re[2]: WM_KEYDOWN на две клавиши
От: Andrew__S Россия  
Дата: 21.06.03 09:03
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>Я так понял, что обработчик у того окна твой собственный.


В том и дело, что окна не мои...

A>SendMessage(hWnd, WM_KEYDOWN, 0x42, scan);

A>SendMessage(hWnd, WM_KEYUP, 0x42, scan); — если это необходимо, потому что если ты просто хочешь вызвать обработчик, то keydown достаточно.

Если уточнить задачу — у приложения (или только у его окна — не совсем уверен)
есть "горячая" комбинация CTRL+B. Ее нажатие и надо изобразить...

A>И не забывай о возможных последствиях работы SendMessage. Если тебе просто нужно поставить в очередь сообщение, то PostMessage тебе вполне достаточно и есть еще один схожый механизм SendMessageTimeout, который иногда предотвращает зависание.


Т.е. в моем случае надо через Postmessage?
Re[3]: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 21.06.03 10:09
Оценка:
Здравствуйте, Andrew__S, Вы писали:

A__>Т.е. в моем случае надо через Postmessage?


Я думаю, что лучше PostMessage, хотя вариантов масса.
Тут еще нужно полностью оценить, каков эффект должен быть от этого нажатия.
Если достаточно окну сообщить о нажатии CTRL+B, то PostMessage достаточно, но на всякий случай WM_KEYUP отправь тоже.
Re[4]: WM_KEYDOWN на две клавиши
От: BlackHeretic Израиль  
Дата: 22.06.03 12:16
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>Здравствуйте, Andrew__S, Вы писали:


A__>>Т.е. в моем случае надо через Postmessage?


A>Я думаю, что лучше PostMessage, хотя вариантов масса.

A>Тут еще нужно полностью оценить, каков эффект должен быть от этого нажатия.
A>Если достаточно окну сообщить о нажатии CTRL+B, то PostMessage достаточно, но на всякий случай WM_KEYUP отправь тоже.

Покопайся тут — поможет
VOID keybd_event(
  BYTE bVk,               // virtual-key code
  BYTE bScan,             // hardware scan code
  DWORD dwFlags,          // function options
  ULONG_PTR dwExtraInfo   // additional keystroke data
);
ICQ 156156278
Re[5]: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 23.06.03 08:05
Оценка:
Здравствуйте, BlackHeretic, Вы писали:

BH>Покопайся тут — поможет

BH>
BH>VOID keybd_event(
BH>  BYTE bVk,               // virtual-key code
BH>  BYTE bScan,             // hardware scan code
BH>  DWORD dwFlags,          // function options
BH>  ULONG_PTR dwExtraInfo   // additional keystroke data
BH>);
BH>


это уже несколько другое. Ему нужно было просто окну сообщить о нажатии комбинации клавиш, а keybd_event это эмуляция самого нажатия. В данном случае — это лишнее. Но посмотреть не помешает, если до этого ни разу не использовал.
Re[6]: WM_KEYDOWN на две клавиши
От: Аноним  
Дата: 23.06.03 08:54
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>Здравствуйте, BlackHeretic, Вы писали:


BH>>Покопайся тут — поможет

BH>>
BH>>VOID keybd_event(
BH>>  BYTE bVk,               // virtual-key code
BH>>  BYTE bScan,             // hardware scan code
BH>>  DWORD dwFlags,          // function options
BH>>  ULONG_PTR dwExtraInfo   // additional keystroke data
BH>>);
BH>>


A>это уже несколько другое. Ему нужно было просто окну сообщить о нажатии комбинации клавиш, а keybd_event это эмуляция самого нажатия. В данном случае — это лишнее. Но посмотреть не помешает, если до этого ни разу не использовал.



Так какже всетаки послать чужой программе комбинацию клавиш — например знак вопроса (нажатый шифт плюс клавиша '/') ? Ведь в параметре lp функциии WM_KEYDOWN нет данных о состоянии управляющих клавиш Шифт и Контрол
Re[7]: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 23.06.03 09:34
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Так какже всетаки послать чужой программе комбинацию клавиш — например знак вопроса (нажатый шифт плюс клавиша '/') ? Ведь в параметре lp функциии WM_KEYDOWN нет данных о состоянии управляющих клавиш Шифт и Контрол


[MSDN]
24-бит значения LPARAM — Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
[/MSDN]
Re[8]: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 23.06.03 09:45
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>[MSDN]

A>24-бит значения LPARAM — Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
A>[/MSDN]

Если все таки lParam не даст желаемого результата, то тебе поможет раздел — Keyboard Input Functions:

GetKeyState и все тому подобное.
Re[9]: WM_KEYDOWN на две клавиши
От: Аноним  
Дата: 23.06.03 10:40
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>Здравствуйте, Alexmoon, Вы писали:


A>>[MSDN]

A>>24-бит значения LPARAM — Specifies whether the key is an extended key, such as the right-hand ALT and CTRL keys that appear on an enhanced 101- or 102-key keyboard. The value is 1 if it is an extended key; otherwise, it is 0.
A>>[/MSDN]


К сожалению все это несколько не в кассу: данный параметр показывает является ли нажатая клавиша расширенной — т.е. правым ALT или правым CTRL а не комбинацией.
Последовательное нажатие сначала Shift потом '/' тоже не проходит:
PostMessage(hwork,WM_KEYDOWN,(WPARAM)0x10,0x002a0001); // нажат Shift
PostMessage(hwork,WM_KEYDOWN,(WPARAM)0xbf,0x00350001); // нажат '/'
PostMessage(hwork,WM_KEYUP,(WPARAM)0xbf,0xC0350099);
PostMessage(hwork,WM_KEYUP,(WPARAM)0x10,0xC02a0001);

Причем данные сообщения я ловлю в Spy когда вручную печатаю знак вопроса в чужой программе. Но программный посыл их из моей программы не проходит — печатается знак '/'


По поводу GetKeyState — в том то и дело что обработчик сообщений НЕ МОЙ. Ежели б я отлавливал комбинацию то было бы все просто, анализировал бы данной функцией нажатия клавиш и все ок, вся головная боль в том что надо посылать в ЧУЖУЮ программу, которая реагирует токо на WM_KEYDOWN, а для чужой проги я немогу установить SetKeyState



A>Если все таки lParam не даст желаемого результата, то тебе поможет раздел — Keyboard Input Functions:


A>GetKeyState и все тому подобное.
Re[10]: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 23.06.03 11:04
Оценка:
Здравствуйте, Аноним, Вы писали:

A>>Если все таки lParam не даст желаемого результата, то тебе поможет раздел — Keyboard Input Functions:


A>>GetKeyState и все тому подобное.


Тогда можно сделать и keybd_event, но не забывай о том, что эмуляция реального нажатия и на это сообщение срегагирует то окно, которое находится в фокусе. Чтобы без визуализации временно передать фокус другому окну в другом потоке, так наверное будет правильнее сказать, чем приложении, поскольку окно это собственность потока, тебе нужно сделать AttachThreadInput(my_dwthread, remote_dwthread, true), потом сделать SetFocus(need_hWnd), что передаст ему фокус IO, но не визуальный, потом перед тем как нажимать клавиши, чтобы убдиться в их срабатывании ты вызови WaitForInputIdle(remote_hProcess, 100), 100 чтобы себя не повесить и если не будет возвращать 0, то после нескольких попыток ты будешь знать, что поток висит, а если все таки вернет ноль, то генерируй необходимый тебе keybd_event и на всякий случай, чтобы дождаться его обработки, если конечно нужно или масса других вариантов синхронизации, тот же WaitForInput..., после чего делаешь смело SetFocus своему окну и напослед разъединяешь очереди обоих потоков AttachThreadInput(my_dwthread, remote_dwthread, false) и по моему это все не должно отличаться от реального сценария по функциональности. За неточности извини. Сам еще не делал. Придумывал на лету и по памяти.
Re[11]: WM_KEYDOWN на две клавиши
От: Аноним  
Дата: 23.06.03 11:32
Оценка:
Здравствуйте, Alexmoon, Вы писали:

A>Здравствуйте, Аноним, Вы писали:


A>>>Если все таки lParam не даст желаемого результата, то тебе поможет раздел — Keyboard Input Functions:


A>>>GetKeyState и все тому подобное.


A>Тогда можно сделать и keybd_event, но не забывай о том, что эмуляция реального нажатия и на это сообщение срегагирует то окно, которое находится в фокусе. Чтобы без визуализации временно передать фокус другому окну в другом потоке, так наверное будет правильнее сказать, чем приложении, поскольку окно это собственность потока, тебе нужно сделать AttachThreadInput(my_dwthread, remote_dwthread, true), потом сделать SetFocus(need_hWnd), что передаст ему фокус IO, но не визуальный, потом перед тем как нажимать клавиши, чтобы убдиться в их срабатывании ты вызови WaitForInputIdle(remote_hProcess, 100), 100 чтобы себя не повесить и если не будет возвращать 0, то после нескольких попыток ты будешь знать, что поток висит, а если все таки вернет ноль, то генерируй необходимый тебе keybd_event и на всякий случай, чтобы дождаться его обработки, если конечно нужно или масса других вариантов синхронизации, тот же WaitForInput..., после чего делаешь смело SetFocus своему окну и напослед разъединяешь очереди обоих потоков AttachThreadInput(my_dwthread, remote_dwthread, false) и по моему это все не должно отличаться от реального сценария по функциональности. За неточности извини. Сам еще не делал. Придумывал на лету и по памяти.



Дело в том что при ближайшем рассмотрении в функции keybd_event тоже нет признаков установки клавиш шифт и контрол, но тем не менее мысль об AttachThreadInput хорошая, по крайней мере можно будет попытаться сделать SetKeyState. Вопрос в том как найти thread чужого окна зная токо его hwnd ?
Re[12]: WM_KEYDOWN на две клавиши
От: Alexmoon Украина  
Дата: 23.06.03 11:42
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Дело в том что при ближайшем рассмотрении в функции keybd_event тоже нет признаков установки клавиш шифт и контрол, но тем не менее мысль об AttachThreadInput хорошая, по крайней мере можно будет попытаться сделать SetKeyState. Вопрос в том как найти thread чужого окна зная токо его hwnd ?


при ближайшем рассмотрении и не при ближайшем клавишу ALT устанавливать не нужно. Нужно нажать ALT, затем 'B', потом отпустить 'B' и на последок отпустить ALT. Четыре вызова keybd_event. А насчет определения координат окна:

//the return value is the identifier of the thread that created the window.
DWORD GetWindowThreadProcessId(
  HWND hWnd,             // handle to window
  LPDWORD lpdwProcessId  // process identifier
);

//вообще для удобства поиска информации запомни одно правило.
//если ты хочешь определить координаты окна, то начни поиск с раздела - Window Functions
//если не поможет в первом приближении определится, то тогда можно повторить разделы - Using and About Windows
Re[13]: WM_KEYDOWN на две клавиши
От: Аноним  
Дата: 23.06.03 14:05
Оценка:
Спасибки большие
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.