c# передать Комбинацию клавиш в неактивное окно
Нужно передать Ctrl+Shift+M в неактивное окно браузера Firefox
SetForegroundWindow(HandleWnd);
SendKeys.SendWait("^+(m)");
Так работает, но окно активным становится при этом
[DllImport("user32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
public static extern bool PostMessage(int hWnd, uint Msg, int wParam, int lParam);
public static void Go()
{
HandleWnd = FindWindow(null, "Mozilla Firefox");
const uint WM_KEYDOWN = 0x0100;
const uint WM_KEYUP = 0x0101;
PostMessage(HandleWnd, WM_KEYDOWN, (int)(System.Windows.Forms.Keys.Control), 0);
PostMessage(HandleWnd, WM_KEYDOWN, (int)(System.Windows.Forms.Keys.Shift), 0);
PostMessage(HandleWnd, WM_KEYDOWN, (int)(System.Windows.Forms.Keys.M), 0);
PostMessage(HandleWnd, WM_KEYUP, (int)(System.Windows.Forms.Keys.M), 0);
PostMessage(HandleWnd, WM_KEYUP, (int)(System.Windows.Forms.Keys.Shift), 0);
PostMessage(HandleWnd, WM_KEYUP, (int)(System.Windows.Forms.Keys.Control), 0);
}
Это ближе к правильному, но не работает почему то
Ответы (1 шт):
Автор решения: aepot
→ Ссылка
Долгая история, но вот все необходимое для нажатия CTRL+SHIFT+M в Firefox, работает на свернутом окне. Дело в том что FF проверяет состояние клавиш Crtl и Shift через прямой ввод, а не через WM. Поэтому через WM достаточно отправить только букву.
[DllImport("user32.dll")]
internal static extern uint MapVirtualKey(Keys uCode, uint uMapType);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern IntPtr FindWindow(IntPtr className, string windowName);
[DllImport("user32.dll")]
static extern bool PostMessage(IntPtr hWnd, uint msg, uint wParam, uint lParam);
[DllImport("user32.dll")]
internal static extern void keybd_event(Keys bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
const uint WM_KEYDOWN = 0x100;
const uint WM_KEYUP = 0x0101;
// https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keydown
// https://docs.microsoft.com/en-us/windows/win32/inputdev/wm-keyup
public static void WindowsMessageSendKey(IntPtr hwnd, Keys keyCode, bool isDown)
{
uint scanCode = MapVirtualKey(keyCode, 0);
uint lParam = 0x00000001 | (scanCode << 16);
if (!isDown)
lParam |= 0xC0000000;
PostMessage(hwnd, isDown ? WM_KEYDOWN : WM_KEYUP, (uint)keyCode, lParam);
}
private void CtrlShiftM_Firefox()
{
IntPtr hwnd = FindWindow("MozillaWindowClass", null);
if (hwnd == IntPtr.Zero)
throw new NullReferenceException("Firefox window wasn't found. hwnd is null");
byte VK_CONTROL = (byte)MapVirtualKey(Keys.ControlKey, 0);
byte VK_SHIFT = (byte)MapVirtualKey(Keys.ShiftKey, 0);
keybd_event(Keys.ControlKey, VK_CONTROL, 0, 0);
keybd_event(Keys.ShiftKey, VK_SHIFT, 0, 0);
WindowsMessageSendKey(hwnd, Keys.M, true);
Thread.Sleep(20); // этот костыль обязателен, иначе FF не успеет отреагировать на WM, пока клавиши нажаты
WindowsMessageSendKey(hwnd, Keys.M, false);
keybd_event(Keys.ShiftKey, VK_SHIFT, 0x02, 0);
keybd_event(Keys.ControlKey, VK_CONTROL, 0x02, 0);
}
Устаревший keybd_event грамотнее заменить на более современный SendInput. Или использовать NuGet пакет InputSimulator. Но и так вроде работает.