以前用来魔兽挂机的,因为那时候要排队2个小时,上了就不想下,其实就是简单的每隔一段时间跳跃一下,这样不至于太久不动被服务器T掉。不知道按键精灵怎么后台,就是魔兽不是当前窗口也可以操作。原理就是找到魔兽窗口句柄向它发送空格消息
xaml代码
<Window x:Class="WOW.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="魔兽世界挂机工具" Height="350" Width="525"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="100"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*"></ColumnDefinition> <ColumnDefinition Width="200"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <StackPanel Grid.Column="1" Grid.Row="1"> <WrapPanel> <TextBlock Text="魔兽世界句柄:" Width="80"></TextBlock> <TextBox IsEnabled="False" Width="50" x:Name="txtHandler"></TextBox> </WrapPanel> <WrapPanel Margin="0,10,0,0"> <TextBlock Text="时间间隔(s):" Width="80"></TextBlock> <TextBox Text="30" Width="50" x:Name="txtInterval"></TextBox> </WrapPanel> <WrapPanel Margin="0,10,0,0"> <Button Content="启动(F10)" x:Name="btnSubmit" Click="btnSubmit_Click"></Button> </WrapPanel> </StackPanel> </Grid> </Window>
后台代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WOW
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(int hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); //设置由不同线程产生的窗口的显示状态
[DllImport("user32.dll")]
private static extern bool IsIconic(IntPtr hWnd); //是否最小化
[DllImport("user32.dll")]
private static extern bool IsZoomed(IntPtr hWnd); //是否最大化
[DllImport("user32.dll")]
private static extern IntPtr SetActiveWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll")]
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);
[DllImport("user32.dll")]
private static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);
//ShowWindow参数
private const int SW_HIDE = 0;
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
private const int SW_SHOWNOACTIVATE = 4;
private const int SW_RESTORE = 9;
private const int SW_SHOWDEFAULT = 10;
//SendMessage参数
private const int WM_KEYDOWN = 0X100;
private const int WM_KEYUP = 0X101;
private const int WM_SYSCHAR = 0X106;
private const int WM_SYSKEYUP = 0X105;
private const int WM_SYSKEYDOWN = 0X104;
private const int WM_CHAR = 0X102;
#region 遍历所有窗口得到句柄
//定义委托方法CallBack,枚举窗口API(EnumWindows),得到窗口名API(GetWindowTextW)和得到窗口类名API(GetClassNameW)
public delegate bool CallBack(int hwnd, int lParam);
[DllImport("user32")]
public static extern int EnumWindows(CallBack x, int y);
[DllImport("user32.dll")]
private static extern int GetWindowTextW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]
private static extern int GetClassNameW(IntPtr hWnd, [MarshalAs(UnmanagedType.LPWStr)]StringBuilder lpString, int nMaxCount);
public bool Recall(int hwnd, int lParam)
{
StringBuilder sb = new StringBuilder(256);
IntPtr PW = new IntPtr(hwnd);
GetWindowTextW(PW, sb, sb.Capacity); //得到窗口名并保存在strName中
string strName = sb.ToString();
GetClassNameW(PW, sb, sb.Capacity); //得到窗口类名并保存在strClass中
string strClass = sb.ToString();
// this.listBox1.Items.Add(strName + " " + strClass);
if (strName.IndexOf("窗口名关键字") >= 0 && strClass.IndexOf("类名关键字") >= 0)
{
return false; //返回false中止EnumWindows遍历
}
else
{
return true; //返回true继续EnumWindows遍历
}
}
#endregion
/// <summary>
/// 发送一个字符串
/// </summary>
/// <param name="myIntPtr">窗口句柄</param>
/// <param name="Input">字符串</param>
public void InputStr(IntPtr myIntPtr, string Input)
{
byte[] ch = (ASCIIEncoding.ASCII.GetBytes(Input));
for (int i = 0; i < ch.Length; i++)
{
SendMessage(myIntPtr, WM_SYSKEYDOWN, Convert.ToInt32(ch[i]), 0);
SendMessage(myIntPtr, WM_SYSKEYUP, Convert.ToInt32(ch[i]), 0);
// SendMessage(PW, WM_CHAR, ch, 0);
}
}
// 利用鼠标和键盘模拟向窗口发送数据
//SetWindowPos(PW, (IntPtr)(-1), 0, 0, 0, 0, 0x0040 | 0x0001); //设置窗口位置
//SetCursorPos(476, 177); //设置鼠标位置
//mouse_event(0x0002, 0, 0, 0, 0); //模拟鼠标按下操作
//mouse_event(0x0004, 0, 0, 0, 0); //模拟鼠标放开操作
//SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X20, 0); //输入空格(0x20)
//SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X09, 0); //输入TAB(0x09)
//SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X0D, 0); //输入ENTER(0x0d)
//向魔兽世界发送空格
private void SendWowSpace()
{
while (true)
{
IntPtr myIntPtr = FindWindow(null, "魔兽世界"); //null为类名,可以用Spy++得到,也可以为空
// ShowWindow(myIntPtr, SW_RESTORE); //将窗口还原
// SetForegroundWindow(myIntPtr); //如果没有ShowWindow,此方法不能设置最小化的窗口
if (myIntPtr != null)
{
SendMessage(myIntPtr, WM_SYSKEYDOWN, 0X20, 0); //输入空格(0x20)
SendMessage(myIntPtr, WM_SYSKEYUP, 0X20, 0);
}
Thread.Sleep(Convert.ToInt32(this.txtInterval.Text) * 1000);
}
}
Thread th = null;
private void btnSubmit_Click(object sender, RoutedEventArgs e)
{
if (this.btnSubmit.Tag == null)
{
th = new Thread(new ThreadStart(SendWowSpace));
th.Start();
this.btnSubmit.Content = "停止(F12)";
this.btnSubmit.Tag = 1;
//遍历所有窗口得到句柄
//CallBack myCallBack = new CallBack(Recall);
//EnumWindows(myCallBack, 0);
//打开窗口
// Process proc = Process.Start(@"目标程序路径");
//SetActiveWindow(proc.MainWindowHandle);
// SetForegroundWindow(proc.MainWindowHandle);
//打开窗口
//Process proc = Process.Start(@"e:\\魔兽世界\\WOW.exe");
// proc.Start(); 与下面句等同效果?
//SetActiveWindow(proc.MainWindowHandle);
}
else
{
#region 停止
try
{
this.btnSubmit.Content = "启动(F10)";
this.btnSubmit.Tag = null;
th.Abort();
}
catch
{
}
#endregion
}
}
}
}
珂珂的个人博客 - 一个程序猿的个人网站