我正在尝试向按下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,即使消息在Spy ++中看起来完全相同,Spotify也不会接受相同的命令。
答案 0 :(得分:4)
我没有很好的方法来测试它,但是如果这两行的顺序会有效:
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);
这样控制键关闭基本上包裹了另一个键的压力?
答案 1 :(得分:2)
我找到了一个有效的解决方案。您使用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;
答案 2 :(得分:2)
我现在找到一种方法将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);