WinUI3中编程获取DLL弹出的Win32窗口并添加菜单
可行性判断与C#实现方案
可行性结论
完全可行。你调用的DLL弹出的是标准Win32窗口,Windows系统提供了原生API支持枚举系统内的窗口、识别目标窗口并为其添加菜单,通过C#的P/Invoke机制就能调用这些API完成需求。
C#实现步骤与代码
1. 声明所需Win32 API的P/Invoke签名
首先在C#中声明要用到的Win32函数和常量:
using System; using System.Runtime.InteropServices; using System.Text; public static class Win32Api { // 枚举所有顶层窗口 [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); // 枚举窗口的回调委托 public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); // 获取窗口标题 [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); // 获取窗口类名 [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpString, int nMaxCount); // 创建空菜单 [DllImport("user32.dll")] public static extern IntPtr CreateMenu(); // 向菜单添加项 [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern bool AppendMenu(IntPtr hMenu, uint uFlags, uint uIDNewItem, string lpNewItem); // 为窗口设置菜单 [DllImport("user32.dll")] public static extern bool SetMenu(IntPtr hWnd, IntPtr hMenu); // 菜单项常量 public const uint MF_STRING = 0x00000000; }
2. 调用DLL弹出窗口并定位目标窗口
调用你的DLL弹出窗口后,通过枚举窗口找到目标窗口的句柄。这里以窗口标题作为识别条件(可替换为类名匹配):
// 存储找到的目标窗口句柄 private static IntPtr _targetWindowHandle = IntPtr.Zero; public static IntPtr FindTargetWindow(string windowTitle) { _targetWindowHandle = IntPtr.Zero; // 枚举所有顶层窗口 Win32Api.EnumWindows((hWnd, lParam) => { StringBuilder title = new StringBuilder(256); Win32Api.GetWindowText(hWnd, title, title.Capacity); // 匹配窗口标题 if (title.ToString().Equals(windowTitle, StringComparison.OrdinalIgnoreCase)) { _targetWindowHandle = hWnd; return false; // 找到后停止枚举 } return true; }, IntPtr.Zero); return _targetWindowHandle; } // 调用示例 // 1. 声明你的DLL导出方法 [DllImport("YourCrossPlatformUI.dll")] public static extern void ShowCrossPlatformWindow(); // 执行流程 ShowCrossPlatformWindow(); // 等待窗口弹出(可根据实际情况调整等待时间,或循环检测直到找到窗口) System.Threading.Thread.Sleep(500); IntPtr targetHwnd = FindTargetWindow("目标窗口标题");
3. 为目标窗口创建并添加菜单
成功获取窗口句柄后,创建菜单并绑定到窗口:
public static void AddMenuToWindow(IntPtr hWnd) { if (hWnd == IntPtr.Zero) return; // 创建菜单 IntPtr hMenu = Win32Api.CreateMenu(); // 添加菜单项 Win32Api.AppendMenu(hMenu, Win32Api.MF_STRING, 1001, "&文件"); Win32Api.AppendMenu(hMenu, Win32Api.MF_STRING, 1002, "&编辑"); Win32Api.AppendMenu(hMenu, Win32Api.MF_STRING, 1003, "&帮助"); // 为窗口设置菜单 Win32Api.SetMenu(hWnd, hMenu); } // 调用示例 if (targetHwnd != IntPtr.Zero) { AddMenuToWindow(targetHwnd); }
注意事项
- 窗口识别准确性:如果窗口标题可能变化,建议通过窗口类名识别(使用
GetClassName方法),类名可通过Spy++工具查看DLL窗口的类定义。 - 异步等待逻辑:DLL弹出窗口可能存在延迟,直接枚举可能找不到,可改为循环检测直到找到窗口或超时。
- 权限问题:确保WinUI3进程与DLL窗口的进程权限一致,避免因权限不足无法修改窗口菜单。
内容的提问来源于stack exchange,提问作者Siva
相关产品推荐
相关产品推荐

