ä»å¤©å¤§å¹´åäºï¼ç¸ä¿¡å¤§å®¶å¬è¯´è¿WINDOWSç³»ç»ä¸çæé®ç²¾çµä¸ç±»ç软件ï¼ä¼å½å¶ä¸æ®µäººç±»æä½é¼ æ çæä½ï¼ç¶åèªå¨éå¤ï¼å轻人类éå¤å·¥ä½çå·¥ä½éï¼è¿ä¹ç®æ¯å¾å¤æ©æ¶ä»£çç®æ¯èªå¨åæä½çä¸ç§æ¹å¼å§ã
è¿æ¬¡éç¨C#çé¼ æ é©åæ¥å®ç°è¿ä¸ªæ¹æ¡ï¼ä¹æ以å«é¼ æ é©åæ¯å 为æ©æä¸æ¹äººç¿»è¯è¿ä¸ªHOOK就翻è¯æé©åï¼ç°å¨ç人å¬çäºéé¾éï¼å ¶å®ä½ å¯ä»¥ç解为就åä½ å¯ä»¥ä½¿ç¨ç°å®çæ´»ä¸çé©åæ¥æè·ææä½æäºç©ä½ä¸æ ·ï¼ç¼ç¨ä¸çé©åå¯ä»¥å¸®å©ä½ "æè·"æ"æä½"æäºäºä»¶æå½æ°ã
举ä¸ä¸ªç®åçä¾åï¼åè®¾ä½ å¨ä¸ä¸ªå¤§åè´ç©ä¸å¿ï¼ä½ æ³ç¥éæå¤å°äººè¿å ¥äºè¿ä¸ªè´ç©ä¸å¿ã为æ¤ï¼ä½ å¯ä»¥å¨å ¥å£å¤æ¾ä¸ä¸ªäººï¼æ¯å½æ人è¿å ¥è´ç©ä¸å¿æ¶ï¼è¿ä¸ªäººå°±ç¨è®°äºæ¬è®°ä¸ä¸ç¬ãè¿ä¸ªäººå°±åæ¯ä¸ä¸ª"é©å"ï¼ä»"æè·"äºè¿å ¥è´ç©ä¸å¿çäºä»¶ï¼å¹¶æ§è¡äºä¸äºæä½ï¼å³è®°ç¬è®°ï¼ãé£æ¢ç¶æé¼ æ é©åå°±è¯å®ä¹æå ¶å®é©åï¼ä¾å¦é®çé©åãWINDOWSæ¶æ¯é©åççï¼åé®çé©åå°±å¾å¥½ç解ï¼å°±æ¯è®°å½é®ççè¾å ¥ä¿¡æ¯ï¼æ´æ©æçæ¶åï¼ç¨è¿ä¸ªæ¹æ³æ¯å¯ä»¥æè·å°ç±»ä¼¼æ¸¸æç»å½è´¦å·å¯ç ãQQè´¦å·å¯ç ä¸ç±»çï¼ç°å¨è¿äºè¾å ¥ææ¬æ¡é½å级äºï¼å¨2003年以åé½æ¯è·åå°çã好äºï¼ä»å¤©æ们讲çæ¯é¼ æ é©åï¼åå½ä¸»é¢ã
é£è¦åä¸ä¸ªç±»ä¼¼æé®ç²¾çµç±»è½¯ä»¶ï¼é£ä¹é¦å å¾ééå°é¼ æ çç¸åºäºä»¶ï¼å¦å·¦é®åå»ï¼å³é®åå»ãé¼ æ 移å¨ççï¼è¿ææé®ç§»å¨çäºä»¶çæ¶é´é´é顺åºä¹éè¦ééå°ï¼å¦å没ææ¶é´é´éçæä½ä¸æ¥ä¸åç人æä½ï¼äºæ¥å¾å¤äºæ æ¯éè¦ä¸å®å»¶æ¶æè½æ£å¸¸çæä½ï¼ä¾å¦æäºè½¯ä»¶åå»åéè¦1ï¼2ç§æè½æå¼ï¼å°±å¾å»¶æ¶è¿1ï¼2ç§ã好äºï¼åºè¯ä¸å¤è¯´ï¼ç´æ¥å¼å¹²ã
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
public class RecordForm : Form
{
private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
private const int WH_MOUSE_LL = 14;
private LowLevelMouseProc _proc;
private IntPtr _hookID = IntPtr.Zero;
private List<MouseEvent> mouseEvents = new List<MouseEvent>();
private Stopwatch stopwatch = new Stopwatch();
public RecordForm()
{
_proc = HookCallback;
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
_hookID = SetHook(_proc);
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
UnhookWindowsHookEx(_hookID);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if (e.Button == MouseButtons.Right)
{
stopwatch.Reset();
mouseEvents.Clear();
stopwatch.Start();
}
else if (e.Button == MouseButtons.Left)
{
stopwatch.Stop();
Playback();
}
}
private IntPtr SetHook(LowLevelMouseProc proc)
{
using (var curProcess = System.Diagnostics.Process.GetCurrentProcess())
using (var curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_MOUSE_LL, proc, Marshal.GetHINSTANCE(curModule.ModuleName), 0);
}
}
private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && stopwatch.IsRunning)
{
MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
mouseEvents.Add(new MouseEvent(hookStruct.pt, (MouseMessages)wParam, stopwatch.ElapsedMilliseconds));
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
private void Playback()
{
long previousTime = 0;
foreach (var mouseEvent in mouseEvents)
{
Thread.Sleep((int)(mouseEvent.Time - previousTime));
previousTime = mouseEvent.Time;
INPUT input = new INPUT();
input.type = INPUT_MOUSE;
input.U.mi.dx = mouseEvent.Location.X * (65536 / Screen.PrimaryScreen.Bounds.Width); // x being coord in pixels
input.U.mi.dy = mouseEvent.Location.Y * (65536 / Screen.PrimaryScreen.Bounds.Height); // y being coord in pixels
input.U.mi.mouseData = 0;
switch (mouseEvent.Message)
{
case MouseMessages.WM_LBUTTONDOWN:
input.U.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
break;
case MouseMessages.WM_LBUTTONUP:
input.U.mi.dwFlags = MOUSEEVENTF_LEFTUP;
break;
case MouseMessages.WM_MOUSEMOVE:
input.U.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
break;
case MouseMessages.WM_MOUSEWHEEL:
input.U.mi.dwFlags = MOUSEEVENTF_WHEEL;
break;
case MouseMessages.WM_RBUTTONDOWN:
input.U.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
break;
case MouseMessages.WM_RBUTTONUP:
input.U.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
break;
}
SendInput(1, new INPUT[] { input }, Marshal.SizeOf(typeof(INPUT)));
}
}
private const int INPUT_MOUSE = 0;
private const uint MOUSEEVENTF_MOVE = 0x0001;
private const uint MOUSEEVENTF_LEFTDOWN = 0x0002;
private const uint MOUSEEVENTF_LEFTUP = 0x0004;
private const uint MOUSEEVENTF_RIGHTDOWN = 0x0008;
private const uint MOUSEEVENTF_RIGHTUP = 0x0010;
private const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
private const uint MOUSEEVENTF_WHEEL = 0x0800;
private struct INPUT
{
public int type;
public InputUnion U;
}
[StructLayout(LayoutKind.Explicit)]
private struct InputUnion
{
[FieldOffset(0)]
public MOUSEINPUT mi;
}
private struct POINT
{
public int x;
public int y;
}
private struct MOUSEINPUT
{
public int dx;
public int dy;
public uint mouseData;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
private enum MouseMessages
{
WM_LBUTTONDOWN = 0x0201,
WM_LBUTTONUP = 0x0202,
WM_MOUSEMOVE = 0x0200,
WM_MOUSEWHEEL = 0x020A,
WM_RBUTTONDOWN = 0x0204,
WM_RBUTTONUP = 0x0205,
WM_LBUTTONDBLCLK = 0x0203,
WM_RBUTTONDBLCLK = 0x0206
}
private class MouseEvent
{
public Point Location { get; }
public MouseMessages Message { get; }
public long Time { get; }
public MouseEvent(Point location, MouseMessages message, long time)
{
Location = location;
Message = message;
Time = time;
}
}
[STAThread]
public static void Main()
{
Application.Run(new RecordForm());
}
}
ä»å¤©æ²¡å 注éï¼ä»£ç é½å¾ç®åï¼ä»£ç å³æ³¨éï¼å¦æä½ å¯¹é¼ æ é©åä¸çæï¼å»ºè®®ä½ æé©åé£é¨ä»½ä»£ç æ£åºæ¥ï¼ç¬ç«å°è£ æä¸ä¸ªç±»ï¼è¿æ ·å¨æåä¸ä¸å¾å®¹æå°±æç½è¿é©ååçäºï¼é常çç®åï¼å¯¹äºï¼å 为ç¨å°äºé¼ æ é©åè¿ç±»ç³»ç»APIï¼ä¸åçWINDOWSç³»ç»è¦æ±å¯è½ä¸ä¸æ ·ï¼æäºWINDOWSç³»ç»å¯è½éè¦ä½ ç管çåæéï¼é£ä½ å°±å³é®ç¨åºç®¡çåæéæ§è¡å³å¯ã
è¿äºä¸åçé©åå¨WINDOWSç³»ç»ä¸å¯ä»¥å许许å¤å¤çäºæ ï¼ä¾å¦ï¼æ¦æªæä½ç³»ç»çæ¶æ¯ï¼æ¯å¦é¼ æ ç¹å»æé®çè¾å ¥ãä¿®æ¹æå¢å¼ºç³»ç»å½æ°æåºå½æ°çè¡ä¸ºãçæ§æè®°å½ç³»ç»æåºç¨ç¨åºçè¡ä¸ºãå½ç¶ä½ è¿å¯ä»¥ç¨å¨æäºéªæ¶çç®çä¸ï¼æ¯å¦å建é®çè®°å½å¨æå ¶ä»æ¶æ软件ï¼è¯·æ大çåæ¥ä½ 们çæ³è±¡ç©ºé´ï¼åååï¼æ ¼å±æå¼ä¼æå¾å¤æ°æè·¯ã
#ç¼ç¨#