You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 21:55:09