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

Revit中实现IWin32Window的非模态Form窗口重复创建问题求助

Revit非模态输出窗口单实例优化问题

我参照相关逻辑开发了一个随Revit启动、关闭的非模态WinForm窗口,用于显示Revit文档操作的动作/命令输出信息。目前功能正常,但存在每次执行Revit命令都会创建新窗口实例的问题,希望实现仅保留一个窗口,通过隐藏/显示来响应操作。

以下是优化后的完整代码实现及说明:

Win Form类

public partial class CmdWindowHandleForm : Form
{
    public string LabelText
    {
        get { return _labelText.Text; }
        set { _labelText.Text = value; }
    }

    public CmdWindowHandleForm()
    {
        InitializeComponent();
    }

    // 实现日志追加方法
    public void AddText(string message)
    {
        _labelText.Text += $"{message}{Environment.NewLine}";
        // 自动滚动到最新内容
        _labelText.ScrollToCaret();
    }
}

partial class CmdWindowHandleForm
{
    private System.ComponentModel.IContainer components = null;
    private Label _labelText;

    private void InitializeComponent()
    {
        this.components = new System.ComponentModel.Container();

        this._labelText = new Label();
        this._labelText.Text = string.Empty;
        // 优化布局:填充窗口、支持自动换行和滚动
        this._labelText.AutoSize = false;
        this._labelText.Dock = DockStyle.Fill;
        this._labelText.Padding = new Padding(5);
        this._labelText.Font = new Font("Consolas", 9F);
        this._labelText.WordWrap = true;
        this._labelText.AutoScroll = true;

        this.Controls.Add(this._labelText);
        this.Size = new Size(450, 350);
        this.Text = "Revit操作日志控制台";
    }
}

实现IWin32Window的WindowHandle类

public class WindowHandle : IWin32Window
{
    public IntPtr Handle
    {
        get { return _handleWindow; }
    }

    IntPtr _handleWindow;

    public WindowHandle(IntPtr handleWindow)
    {
        _handleWindow = handleWindow;
    }
}

随Revit运行的静态InfoConsole类(核心优化)

public static class InfoConsole
{
    private static WindowHandle _hWndRevit = null;
    private static CmdWindowHandleForm _window = null;

    public static void Show(string message)
    {
        if (_hWndRevit == null)
        {
            Process process = Process.GetCurrentProcess();
            IntPtr h = process.MainWindowHandle;
            _hWndRevit = new WindowHandle(h);
        } 

        // 检查窗口实例是否存在或已被释放
        if (_window == null || _window.IsDisposed)
        {
            _window = new CmdWindowHandleForm();
            // 绑定关闭事件,释放后重置引用
            _window.FormClosed += (sender, e) => 
            {
                _window = null;
            };
            // 以非模态方式显示,绑定Revit主窗口为父窗口
            _window.Show(_hWndRevit);
            // 设置窗口属性:不显示在任务栏、可前置
            _window.ShowInTaskbar = false;
            _window.TopMost = true;
        }
        else
        {
            // 窗口已存在,确保可见并前置
            if (!_window.Visible)
            {
                _window.Visible = true;
            }
            _window.BringToFront();
        }

        _window.AddText(message);
    }
}

命令调用代码

InfoConsole.Show(outputMessage);

核心优化点说明

  • 实例有效性校验:将原判断_window == null升级为_window == null || _window.IsDisposed,避免用户手动关闭窗口后,引用仍存在但窗口已释放的无效状态。
  • 关闭事件绑定:在窗口创建时绑定FormClosed事件,用户关闭窗口时自动重置_window引用,确保下次调用能正常重建。
  • 窗口状态管理:显示时自动前置窗口,避免被Revit主窗口遮挡;仅在窗口不可见时设置可见性,减少不必要的状态切换。
  • UI体验优化:给Label添加自动滚动、换行和等宽字体,提升日志可读性;设置窗口默认大小和标题,增强辨识度。

内容的提问来源于stack exchange,提问作者Lukasz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:10:43