外观
嵌入exe
引入外部exe操作
在 C# 中,可以使用 Process 类来启动并与外部应用程序进行交互。示例代码片段,可以用来将外部 EXE 文件加载到 WinForm 程序中,并与之交互:
using System;
using System.Diagnostics;
using System.Windows.Forms;
class Program
{
static void Main(string[] args)
{
// 启动外部应用程序
Process process = new Process();
process.StartInfo.FileName = "notepad.exe"; // 替换为要启动的外部 EXE 文件名
process.Start();
// 等待应用程序启动
process.WaitForInputIdle();
// 将外部应用程序嵌入 WinForm 程序中
IntPtr hProcess = process.Handle;
IntPtr hParent = this.Handle; // 替换为 WinForm 窗体的句柄
SetParent(hProcess, hParent);
MoveWindow(hProcess, 0, 0, this.ClientSize.Width, this.ClientSize.Height, true);
}
// 导入 Win32 API 函数和常量
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
[DllImport("user32.dll")]
static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
}首先使用 Process 类启动外部应用程序,并等待它启动完成。然后,使用 SetParent 函数将外部应用程序的主窗口句柄设置为 WinForm 窗体的子窗口,并使用 MoveWindow 函数将其调整为与 WinForm 窗体相同的大小和位置。这样,外部应用程序将被嵌入到 WinForm 程序中,并可以与之交互。
监听指定程序事件(切换窗体焦点)
SetWinEventHook 函数是 Windows API 中的一个函数,用于设置一个钩子函数,以便在发生指定系统事件时通知指定的回调函数。 要监听指定进程切换了窗体,可以使用 SetWinEventHook 函数来设置一个钩子函数,以便在系统发送 EVENT_SYSTEM_FOREGROUND 系统事件时通知指定的回调函数。 示例代码片段,可以用来演示 SetWinEventHook 函数的用法,以便在指定进程切换窗体时输出一条消息:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
class Program
{
// 导入 Win32 API 函数和常量
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
const uint EVENT_SYSTEM_FOREGROUND = 3;
// 定义 WinEventDelegate 委托类型
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime);
static void Main(string[] args)
{
int processId = 1234; // 替换为要监听窗体切换的进程 ID
// 创建 WinEventDelegate 委托实例
WinEventDelegate winEventDelegate = new WinEventDelegate(WinEventCallback);
// 设置系统事件钩子
IntPtr hWinEventHook = SetWinEventHook(EVENT_SYSTEM_FOREGROUND, EVENT_SYSTEM_FOREGROUND, IntPtr.Zero, winEventDelegate, (uint)processId, 0, 0);
// 等待用户按下 Enter 键退出程序
Console.ReadLine();
// 卸载系统事件钩子
UnhookWinEvent(hWinEventHook);
}
static void WinEventCallback(IntPtr hWinEventHook, uint eventType, IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
Console.WriteLine("窗体切换了:{0}", hwnd);
}
}首先使用进程 ID 创建一个 WinEventDelegate 委托实例。然后,我们使用 SetWinEventHook 函数来设置一个 EVENT_SYSTEM_FOREGROUND 系统事件的钩子,并将委托实例传递给它。此钩子将在指定进程切换窗体时触发,并将其相关参数传递给委托实例。在 WinEventCallback 回调函数中,我们输出了窗体句柄。
/// 根据进程id和句柄获取窗口下的控件
public void GetWindowChild(int processId,IntPtr handle)
{
Thread.Sleep(500);
// 获取进程的所有窗口句柄,包括子窗口
IntPtr currentWindowHandle = GetWindow(handle, 5 /* GW_CHILD */);
while (currentWindowHandle != IntPtr.Zero)
{
uint processIdForWindow;
GetWindowThreadProcessId(currentWindowHandle, out processIdForWindow);
if (processIdForWindow == processId)
{
Debug.WriteLine(currentWindowHandle);
ShowWindowAsync(currentWindowHandle, SW_HIDE);
}
currentWindowHandle = GetWindow(currentWindowHandle, 2 /* GW_HWNDNEXT */);
}
}