例子比较简单,讲道理其实一分钟就应该做好的,但是我却做了一周。原因也很扯淡,遇到了两个问题。
1、鼠标传递过去,位置变化极小。
2、键盘传递过去,按一次变成了按两次。
昨天看了一天,解决了,解决原因是:重新编译+重启了电脑。
心态崩了
为啥心态崩了呢,因为重新编译+重启了电脑,我试了很多次,但是只有昨天成功了。之后也都一直成功。所以到底为啥之前就不行呢,不知道。简而言之,要么是我抽风,要么是电脑抽风, 但是代码却没问题。
???
不说了,反正代码是对的就行了,至于问题就交给微软吧。
其实代码都不用多说,都是些很简单的东西,首先是一个从网上找的鼠标键盘模拟和钩子类。然后被控端用钩子检测鼠标和键盘的动作然后发送,控制端收到消息之后在本地模拟出鼠标键盘的操作。
鼠标的动作:
const int MOUSEEVENTF_MOVE = 0x0001; // 移动鼠标
const int MOUSEEVENTF_LEFTDOWN = 0x0002; // 模拟鼠标左键按下
const int MOUSEEVENTF_LEFTUP = 0x0004; //模拟鼠标左键抬起
const int MOUSEEVENTF_RIGHTDOWN = 0x0008; //模拟鼠标右键按下
const int MOUSEEVENTF_RIGHTUP = 0x0010; // 模拟鼠标右键抬起
const int MOUSEEVENTF_MIDDLEDOWN = 0x0020; //模拟鼠标中键按下
const int MOUSEEVENTF_MIDDLEUP = 0x0040; //模拟鼠标中键抬起
const int MOUSEEVENTF_ABSOLUTE = 0x8000; //标示是否采用绝对坐标
const int MOUSEEVENTF_WHEEL = 0x0800; //标示滚轮
键盘的动作:
public int KeyCode; //key
public int KeyType; //0按下 1抬起
代码直接贴上来:钩子和模拟:
namespace FFcontrolled
{
/// <summary>
/// 鼠标和键盘钩子的抽象类
/// </summary>
public abstract class GlobalHook
{
#region Windows API Code
[StructLayout(LayoutKind.Sequential)]
protected class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
protected class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
protected class MouseLLHookStruct
{
public POINT pt;
public int mouseData;
public int flags;
public int time;
public int dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
protected class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
protected static extern int SetWindowsHookEx(
int idHook,
HookProc lpfn,
IntPtr hMod,
int dwThreadId);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(String modulename);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookExW(
int idHook,
HookProc lpfn,
IntPtr hmod,
uint dwThreadID);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
protected static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
protected static extern int CallNextHookEx(
int idHook,
int nCode,
int wParam,
IntPtr lParam);
[DllImport("user32")]
protected static extern int ToAscii(
int uVirtKey,
int uScanCode,
byte[] lpbKeyState,
byte[] lpwTransKey,
int fuState);
[DllImport("user32")]
protected static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
protected static extern short GetKeyState(int vKey);
protected delegate int HookProc(int nCode, int wParam, IntPtr lParam);
protected const int WH_MOUSE_LL = 14;
protected const int WH_KEYBOARD_LL = 13;
protected const int WH_MOUSE = 7;
protected const int WH_KEYBOARD = 2;
protected const int WM_MOUSEMOVE = 0x200;
protected const int WM_LBUTTONDOWN = 0x201;
protected const int WM_RBUTTONDOWN = 0x204;
protected const int WM_MBUTTONDOWN = 0x207;
protected const int WM_LBUTTONUP = 0x202;
protected const int WM_RBUTTONUP = 0x205;
protected const int WM_MBUTTONUP = 0x208;
protected const int WM_LBUTTONDBLCLK = 0x203;
protected const int WM_RBUTTONDBLCLK = 0x206;
protected const int WM_MBUTTONDBLCLK = 0x209;
protected const int WM_MOUSEWHEEL = 0x020A;
protected const int WM_KEYDOWN = 0x100;
protected const int WM_KEYUP = 0x101;
protected const int WM_SYSKEYDOWN = 0x104;
protected const int WM_SYSKEYUP = 0x105;
protected const byte VK_SHIFT = 0x10;
protected const byte VK_CAPITAL = 0x14;
protected const byte VK_NUMLOCK = 0x90;
protected const byte VK_LSHIFT = 0xA0;
protected const byte VK_RSHIFT = 0xA1;
protected const byte VK_LCONTROL = 0xA2;
protected const byte VK_RCONTROL = 0x3;
protected const byte VK_LALT = 0xA4;
protected const byte VK_RALT = 0xA5;
protected const byte LLKHF_ALTDOWN = 0x20;
#endregion
#region Private Variables
protected int _hookType;
protected int _handleToHook;
protected bool _isStarted;
protected HookProc _hookCallback;
#endregion
#region Properties
public bool IsStarted
{
get
{
return _isStarted;
}
}
#endregion
#region Constructor
public GlobalHook()
{
//绑定ApplicationExit事件
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
}
#endregion
#region Methods
public void Start()
{
if (!_isStarted &&
_hookType != 0)
{
//确保_hookCallback不是一个空的引用
//如果是,GC会随机回收它,并且一个空的引用会爆出异常