using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Threading;
public class MirServerNpcReloader
{
public static bool IsConnection { get; set; } = true;
public static class Win32Api
{
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindow (string lpClassName, string lpWindowName);
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindowEx (IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr SendMessage (IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetClassName (IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport ("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int GetWindowText (IntPtr hWnd, StringBuilder lpString, int nMaxCount);
public const uint BM_CLICK = 0x00F5;
public const uint WM_LBUTTONDOWN = 0x0201;
public const uint WM_LBUTTONUP = 0x0202;
}
public static bool ReloadMirServerNpc ()
{
try
{
if (!IsConnection)
{
throw new Exception ("连接未开启,请先开启连接。");
}
string M2ServerWindowTitle = "M2Server";
string GameCenterWindowTitle = "GameCenter";
string TMainmenuClassName = "TFormMain";
IntPtr targetWindowHandle = IntPtr.Zero;
string windowType = string.Empty;
targetWindowHandle = Win32Api.FindWindow (null, M2ServerWindowTitle);
if (targetWindowHandle != IntPtr.Zero)
{
windowType = "M2Server";
Console.WriteLine ($"找到M2Server窗口,句柄:0x{targetWindowHandle.ToInt64 ():X}");
}
else
{
targetWindowHandle = Win32Api.FindWindow (null, GameCenterWindowTitle);
if (targetWindowHandle != IntPtr.Zero)
{
windowType = "GameCenter";
Console.WriteLine ($"找到GameCenter窗口,句柄:0x{targetWindowHandle.ToInt64 ():X}");
}
}
if (targetWindowHandle == IntPtr.Zero)
{
string errorMsg = "未找到M2Server或GameCenter窗口,请确保服务端已启动!";
throw new Exception (errorMsg);
}
IntPtr mainmenuHandle = Win32Api.FindWindowEx (targetWindowHandle, IntPtr.Zero, TMainmenuClassName, null);
if (mainmenuHandle != IntPtr.Zero)
{
Console.WriteLine ($"找到TMainmenu控件,句柄:0x{mainmenuHandle.ToInt64 ():X}");
StringBuilder className = new StringBuilder (256);
Win32Api.GetClassName (mainmenuHandle, className, className.Capacity);
Console.WriteLine ($"控件类名:{className}");
StringBuilder text = new StringBuilder (256);
Win32Api.GetWindowText (mainmenuHandle, text, text.Capacity);
Console.WriteLine ($"控件文本:{text}");
IntPtr clickResult = Win32Api.SendMessage (mainmenuHandle, Win32Api.BM_CLICK, IntPtr.Zero, IntPtr.Zero);
if (clickResult != IntPtr.Zero)
{
Console.WriteLine ("成功发送按钮点击消息,触发NPC重载事件");
}
else
{
Win32Api.SendMessage (mainmenuHandle, Win32Api.WM_LBUTTONDOWN, IntPtr.Zero, IntPtr.Zero);
Thread.Sleep (50);
Win32Api.SendMessage (mainmenuHandle, Win32Api.WM_LBUTTONUP, IntPtr.Zero, IntPtr.Zero);
Console.WriteLine ("成功发送鼠标模拟消息,触发NPC重载事件");
}
return true;
}
else
{
string errorMsg = $"在{windowType}窗口中未找到TMainmenu控件!";
throw new Exception (errorMsg);
}
}
catch (Exception ex)
{
Console.WriteLine ($"执行失败:{ex.Message}");
throw;
}
}
public static class ButtonHook
{
private delegate IntPtr HookProc (int nCode, IntPtr wParam, IntPtr lParam);
private static HookProc _mouseHookProc;
private static IntPtr _mouseHookHandle = IntPtr.Zero;
private static IntPtr _targetControlHandle = IntPtr.Zero;
[DllImport ("user32.dll", SetLastError = true)]
private static extern IntPtr SetWindowsHookEx (int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport ("user32.dll", SetLastError = true)]
private static extern bool UnhookWindowsHookEx (IntPtr hhk);
[DllImport ("user32.dll", SetLastError = true)]
private static extern IntPtr CallNextHookEx (IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport ("kernel32.dll", SetLastError = true)]
private static extern IntPtr GetModuleHandle (string lpModuleName);
private const int WH_MOUSE_LL = 14;
private const int WM_LBUTTONUP = 0x0202;
[DllImport ("user32.dll", SetLastError = true)]
private static extern IntPtr WindowFromPoint (POINT pt);
[StructLayout (LayoutKind.Sequential)]
private struct POINT
{
public int x;
public int y;
}
[StructLayout (LayoutKind.Sequential)]
private struct MSLLHOOKSTRUCT
{
public POINT pt;
public uint mouseData;
public uint flags;
public uint time;
public IntPtr dwExtraInfo;
}
public static bool StartHook (IntPtr targetControlHandle)
{
_targetControlHandle = targetControlHandle;
if (_mouseHookHandle != IntPtr.Zero) return false;
_mouseHookProc = MouseHookCallback;
IntPtr moduleHandle = GetModuleHandle (null);
_mouseHookHandle = SetWindowsHookEx (WH_MOUSE_LL, _mouseHookProc, moduleHandle, 0);
return _mouseHookHandle != IntPtr.Zero;
}
public static bool StopHook ()
{
if (_mouseHookHandle == IntPtr.Zero) return true;
bool result = UnhookWindowsHookEx (_mouseHookHandle);
_mouseHookHandle = IntPtr.Zero;
return result;
}
private static IntPtr MouseHookCallback (int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam.ToInt32 () == WM_LBUTTONUP)
{
MSLLHOOKSTRUCT mouseStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure (lParam, typeof (MSLLHOOKSTRUCT));
IntPtr clickedHandle = WindowFromPoint (mouseStruct.pt);
if (clickedHandle == _targetControlHandle)
{
Console.WriteLine ("Hook到目标按钮触发事件!开始执行NPC重载...");
ReloadMirServerNpc ();
}
}
return CallNextHookEx (_mouseHookHandle, nCode, wParam, lParam);
}
}
public static void Main (string[] args)
{
IntPtr targetWindow = Win32Api.FindWindow (null, "M2Server");
if (targetWindow == IntPtr.Zero)
{
targetWindow = Win32Api.FindWindow (null, "GameCenter");
}
if (targetWindow != IntPtr.Zero)
{
IntPtr targetControl = Win32Api.FindWindowEx (targetWindow, IntPtr.Zero, "TFormMain", null);
if (targetControl != IntPtr.Zero)
{
bool hookStarted = ButtonHook.StartHook (targetControl);
Console.WriteLine (hookStarted ? "钩子启动成功,等待捕获按钮事件..." : "钩子启动失败");
}
}
ReloadMirServerNpc ();
Console.ReadLine ();
ButtonHook.StopHook ();
}
}