为什么在表单关闭之前调用FormDeactivate?

时间:2016-06-28 21:52:19

标签: c# winforms excel-interop winforms-interop

我有一个使用Excel Interop生成Excel电子表格的Winforms应用程序。

当我尝试以这种方式保存工作表时:

_xlBook.SaveAs(filename, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Excel.XlSaveAsAccessMode.xlExclusive, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);

...它会失败,告诉我,“ System.Runtime.InteropServices.InvalidComObjectException未处理   的HResult = -2146233049   Message =无法使用已与其基础RCW分离的COM对象。

但这没有多大意义 - 我没有做任何与线程等有关的事情;这是一个非常普通的香草实用程序。代码中引用的唯一其他地方_xlBook是:

1)

private Excel.Workbook _xlBook;

2)

_xlBook = _xlApp.Workbooks.Add(Type.Missing);

3)

_xlSheets = _xlBook.Worksheets;
_xlSheet = (Excel.Worksheet)_xlSheets.Item[1];

4)

_xlBook.Close(false);
Marshal.ReleaseComObject(_xlBook);

从表单的Deactivate事件调用最后一部分_xlBook被处理掉的部分,该事件是:

private void FormMain_Deactivate(object sender, EventArgs e)
{
    DeinitializeExcelObjects();
}

问题是(我在所有引用_xlBook的地方放置断点后发现)在调用 _xlBook.SaveAs()之前调用了FormMain_Deactivate(),当调用它时单击“运行”按钮。

一旦我在FormMain_Deactivate()中注释掉对DeinitializeExcelObjects()的调用,并在调用_xlBook.SaveAs()之后立即调用它,它工作正常 - 创建并保存文件时没有任何错误消息。

那么为什么在表单关闭之前调用FormDeactivate呢?如果这是“按照设计”,那么这个事件就会被错误地命名。

1 个答案:

答案 0 :(得分:4)

您已将代码放在错误的位置。 :-)似乎你误解了激活和停用的含义(至少就Windows而言)。

每当激活不同的窗口时都会发生停用,并且当您的表单被销毁时,即使该窗口是Windows桌面,其他窗口也必须变为活动状态。 FormDeactivate 可以被多次调用(例如当用户切换到不同的应用程序,甚至是您自己的应用程序中的不同窗口时)。重要的是要注意,这也适用于激活; FormActivate 也可以多次触发。

如果您希望在关闭表单时运行代码,请将其放在 FormClose 事件处理程序中。