[英]Send Ctrl+Up to a window
我正在尝试向一个窗口发送消息,该窗口显示已按下 Ctrl 和向上箭头。 我已经掌握了基础知识,我可以发送可以正常注册的空格键。 但我似乎无法让ctrl + ↑工作。 选择的代码片段:
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
现在这适用于发送空间:
public static void SendKeyPress(IntPtr handle, VKeys key)
{
SendMessage(handle, (int) WMessages.WM_KEYDOWN, (int) key, 0);
SendMessage(handle, (int)WMessages.WM_KEYUP, (int)key, 0);
}
但这不适用于将Ctrl + ↑发送到 VLC 以增加音量:
public static void SendKeyPress(IntPtr handle, VKeys key, bool control)
{
int lParamKeyDown = 0;
lParamKeyDown |= 1;
lParamKeyDown |= 1 << 24;
int lParamKeyUp = lParamKeyDown;
lParamKeyUp |= 1 << 30;
lParamKeyUp |= 1 << 31; //it was down before
int lParamCtrlDown = lParamKeyDown;
int lParamCtrlUp = lParamKeyUp;
lParamKeyDown |= (int)MapVirtualKey((uint)key, 0) << 16;
lParamKeyUp |= (int)MapVirtualKey((uint)key, 0) << 16;
lParamCtrlDown |= (int)MapVirtualKey((uint)VKeys.VK_CONTROL, 0) << 16;
lParamCtrlUp |= (int)MapVirtualKey((uint)VKeys.VK_CONTROL, 0) << 16;
IntPtr controlPtr = new IntPtr((int)VKeys.VK_CONTROL);
IntPtr lParamCtrlDownPtr = new IntPtr(lParamCtrlDown);
IntPtr lParamCtrlUpPtr = new IntPtr(lParamCtrlUp);
IntPtr lParamKeyDownPtr = new IntPtr(lParamKeyDown);
IntPtr lParamKeyUpPtr = new IntPtr(lParamKeyUp);
IntPtr keyPtr = new IntPtr((int)key);
object o = new object();
HandleRef wndRef = new HandleRef(o, handle);
PostMessage(wndRef, (uint)WMessages.WM_KEYDOWN, controlPtr, lParamCtrlDownPtr);
PostMessage(wndRef, (uint) WMessages.WM_KEYDOWN, keyPtr, lParamKeyDownPtr);
PostMessage(wndRef, (uint) WMessages.WM_KEYUP, controlPtr, lParamCtrlUpPtr);
PostMessage(wndRef, (uint) WMessages.WM_KEYUP, keyPtr, lParamKeyUpPtr);
}
我错过了什么?
Edit3:消息完全相同,自从我切换到 PostMessage 后没有额外的消息,但 VLC 仍然不会增加或减少音量。
不仅是 VLC,Spotify 也不会接受相同的命令,即使 Spy++ 中的消息看起来完全相同。
我没有一个很好的方法来测试它,但是如果这两行的顺序是否可行:
SendMessage(handle, (int) WMessages.WM_KEYDOWN, (int) key, 0);
SendMessage(handle, (int) WMessages.WM_KEYDOWN, (int)VKeys.VK_CONTROL, 0);
改为:
SendMessage(handle, (int) WMessages.WM_KEYDOWN, (int)VKeys.VK_CONTROL, 0);
SendMessage(handle, (int) WMessages.WM_KEYDOWN, (int) key, 0);
以便按下的控制键基本上包裹了另一个键的按下?
我找到了一个可行的解决方案。 您使用SetKeyboardState函数按下控制键,然后您可以发送任何您想要的键。 此 Delphi 代码将 Ctrl+Right 发送到 Memo 组件。
var
s: TKeyboardState;
PrevState: byte;
begin
GetKeyboardState(s);
PrevState := s[VK_CONTROL];
s[VK_CONTROL] := 128;
SetKeyboardState(s);
SendMessage(Memo1.Handle, WM_KEYDOWN, VK_RIGHT, 0);
s[VK_CONTROL] := PrevState;
SetKeyboardState(s)
end;
我现在找到了一种将Ctrl + Right (例如)发送到另一个进程的窗口的方法。 如果hEdit
是窗口的句柄,则以下代码有效。
AttachThreadInput(GetCurrentThreadID, GetWindowThreadProcessId(hEdit, 0), true);
hEdit := SetFocus(hEdit);
keybd_event(VK_CONTROL, 0, 0, 0);
keybd_event(VK_RIGHT, 0, 0, 0);
keybd_event(VK_RIGHT, 0, KEYEVENTF_KEYUP, 0);
keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0);
SetFocus(hEdit); // restore focus
AttachThreadInput(GetCurrentThreadID, GetWindowThreadProcessId(hEdit, 0), false); // "Disconnect"
更新
这种方法的缺点是焦点会在很短的时间内发生变化。 事实上,我相信最好的解决方案是结合我之前和这篇文章:
var
s: TKeyboardState;
PrevState: byte;
AttachThreadInput(GetCurrentThreadID, GetWindowThreadProcessId(hEdit, 0), true);
GetKeyboardState(s);
PrevState := s[VK_CONTROL];
s[VK_CONTROL] := 128;
SetKeyboardState(s);
SendMessage(hEdit, WM_KEYDOWN, VK_RIGHT, 0);
s[VK_CONTROL] := PrevState;
SetKeyboardState(s);
AttachThreadInput(GetCurrentThreadID, GetWindowThreadProcessId(hEdit, 0), false);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.