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

如何模拟MSP的Application.ProjectAfterClose事件维护ComboBox项目列表?

解决MSP项目关闭时ComboBox列表更新的最后一个项目检测问题

问题背景

我需要让ComboBox始终同步显示所有已打开的MSP项目,要求在项目打开、关闭时实时更新列表。目前项目打开的逻辑已经实现,但关闭环节存在两个核心问题:

  • 仅用ProjectBeforeCloseEvent会在保存弹窗弹出前触发,用户可能取消关闭操作,导致列表误更新
  • 用ProjectBeforeCloseEvent+WindowActivateEvent的临时方案,无法检测用户取消关闭最后一个项目的场景(此时没有新窗口激活,WindowActivateEvent不会触发)
  • 不想用定时器轮询的方式来检测项目状态

已经优化代码避免了未关闭项目却误删列表项的问题,但最后一个项目关闭的检测这个核心问题仍未解决。

现有实现代码

private void _prjApp_WindowActivateEvent(MSP.Window activatedWindow)
{
    List<string> prjFileNames = ReturnOpenProjFileNames();

    if (projectOpened)
    {
        foreach (var prjName in prjFileNames)
        {
            if (cbMSP.Items.Contains(prjName) == false)
            {
                AddMSPToComboBox(prjName);
            }
        }
    }

    if (projectClosed)
    {
        for (int i = cbMSP.Items.Count - 1; i >= 0; i--)
        {
            string prjName = cbMSP.Items[i].ToString();

            if (prjFileNames.Contains(prjName) == false)
            {
                DeleteMSPInComboBox(prjName);
            }
        }
    }

    projectClosed = false;
    projectOpened = false;
}

注:用projectOpened和projectClosed两个布尔变量关联ProjectBeforeCloseEvent和NewProjectEvent,减少切换活动项目时的不必要代码执行。

解决方案

核心思路

通过记录待关闭项目的临时标记,结合MSP的ProjectAfterSave和Quit事件,精准判断项目是否真的被关闭,覆盖所有场景包括最后一个项目的处理。

具体实现步骤

  1. 新增全局变量记录待关闭的项目名称
private string _pendingCloseProject;
  1. 修改ProjectBeforeCloseEvent,只记录待关闭项目,不直接更新列表
private void _prjApp_ProjectBeforeCloseEvent(MSP.Project p, ref bool Cancel)
{
    _pendingCloseProject = p.Name; // 暂存待关闭的项目名
}
  1. 监听ProjectAfterSave事件,确认项目是否真的关闭
private void _prjApp_ProjectAfterSaveEvent(MSP.Project p)
{
    if (!string.IsNullOrEmpty(_pendingCloseProject))
    {
        List<string> currentOpenProjects = ReturnOpenProjFileNames();
        // 检查待关闭项目是否还在打开列表里,不在就更新ComboBox
        if (!currentOpenProjects.Contains(_pendingCloseProject))
        {
            DeleteMSPInComboBox(_pendingCloseProject);
            _pendingCloseProject = null;
        }
    }
}
  1. 监听Application.Quit事件,处理最后一个项目关闭导致MSP退出的场景
private void _prjApp_QuitEvent()
{
    cbMSP.Items.Clear();
    _pendingCloseProject = null;
}
  1. 优化WindowActivateEvent,补充待关闭项目的状态检查
    在原有逻辑基础上,增加以下代码:
// 检查是否有待关闭的项目需要验证状态
if (!string.IsNullOrEmpty(_pendingCloseProject))
{
    List<string> currentOpen = ReturnOpenProjFileNames();
    if (!currentOpen.Contains(_pendingCloseProject))
    {
        DeleteMSPInComboBox(_pendingCloseProject);
        _pendingCloseProject = null;
    }
    else
    {
        // 用户取消了关闭操作,清空待关闭标记
        _pendingCloseProject = null;
    }
}

方案优势

  • 不需要定时器轮询,完全通过MSP原生事件驱动
  • 覆盖所有关闭场景:用户正常关闭、取消关闭、最后一个项目关闭退出
  • 避免了ProjectBeforeCloseEvent触发过早导致的误更新问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 10:35:55