Здравствуйте.
Приношу свои извинения за повтор вопроса. Но поиск так и не помог.
Есть многооконная программа (это, наверное, не важно). В одно из ее
окон надо послать комбинацию клавиш с CTRL. Т.е., например, CTRL+B.
Пишу (в C++ Builder-е):
Здравствуйте, Andrew__S, Вы писали:
A__>Здравствуйте. A__>Приношу свои извинения за повтор вопроса. Но поиск так и не помог. A__>Есть многооконная программа (это, наверное, не важно). В одно из ее A__>окон надо послать комбинацию клавиш с CTRL. Т.е., например, CTRL+B. A__>Пишу (в C++ Builder-е):
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, который иногда предотвращает зависание.
Здравствуйте, Alexmoon, Вы писали:
A>Я так понял, что обработчик у того окна твой собственный.
В том и дело, что окна не мои...
A>SendMessage(hWnd, WM_KEYDOWN, 0x42, scan); A>SendMessage(hWnd, WM_KEYUP, 0x42, scan); — если это необходимо, потому что если ты просто хочешь вызвать обработчик, то keydown достаточно.
Если уточнить задачу — у приложения (или только у его окна — не совсем уверен)
есть "горячая" комбинация CTRL+B. Ее нажатие и надо изобразить...
A>И не забывай о возможных последствиях работы SendMessage. Если тебе просто нужно поставить в очередь сообщение, то PostMessage тебе вполне достаточно и есть еще один схожый механизм SendMessageTimeout, который иногда предотвращает зависание.
Здравствуйте, Andrew__S, Вы писали:
A__>Т.е. в моем случае надо через Postmessage?
Я думаю, что лучше PostMessage, хотя вариантов масса.
Тут еще нужно полностью оценить, каков эффект должен быть от этого нажатия.
Если достаточно окну сообщить о нажатии CTRL+B, то PostMessage достаточно, но на всякий случай WM_KEYUP отправь тоже.
Здравствуйте, Alexmoon, Вы писали:
A>Здравствуйте, Andrew__S, Вы писали:
A__>>Т.е. в моем случае надо через Postmessage?
A>Я думаю, что лучше PostMessage, хотя вариантов масса. A>Тут еще нужно полностью оценить, каков эффект должен быть от этого нажатия. A>Если достаточно окну сообщить о нажатии CTRL+B, то PostMessage достаточно, но на всякий случай WM_KEYUP отправь тоже.
это уже несколько другое. Ему нужно было просто окну сообщить о нажатии комбинации клавиш, а keybd_event это эмуляция самого нажатия. В данном случае — это лишнее. Но посмотреть не помешает, если до этого ни разу не использовал.
Re[6]: WM_KEYDOWN на две клавиши
От:
Аноним
Дата:
23.06.03 08:54
Оценка:
Здравствуйте, Alexmoon, Вы писали:
A>Здравствуйте, BlackHeretic, Вы писали:
BH>>Покопайся тут — поможет BH>>
A>это уже несколько другое. Ему нужно было просто окну сообщить о нажатии комбинации клавиш, а keybd_event это эмуляция самого нажатия. В данном случае — это лишнее. Но посмотреть не помешает, если до этого ни разу не использовал.
Так какже всетаки послать чужой программе комбинацию клавиш — например знак вопроса (нажатый шифт плюс клавиша '/') ? Ведь в параметре lp функциии WM_KEYDOWN нет данных о состоянии управляющих клавиш Шифт и Контрол
Здравствуйте, Аноним, Вы писали:
А>Так какже всетаки послать чужой программе комбинацию клавиш — например знак вопроса (нажатый шифт плюс клавиша '/') ? Ведь в параметре 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]
Здравствуйте, 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 и все тому подобное.
Здравствуйте, Аноним, Вы писали:
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 ?
Здравствуйте, Аноним, Вы писали:
А>Дело в том что при ближайшем рассмотрении в функции 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