为什么在关闭窗体之前调用 FormDeactivate?
Why is FormDeactivate called before the form is closed?
我有一个 Winforms 应用程序,它使用 Excel Interop 生成 Excel 传播sheet。
当我尝试以这种方式保存 sheet 时:
_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=COM 对象已经与其底层 RCW 分离,无法使用。"
虽然这没有多大意义 - 我并没有对线程等做任何花哨的事情;这是一个非常普通的香草实用程序。代码中唯一引用 _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);
处理 _xlBook 的最后一部分是从表单的停用事件调用的,该事件是:
private void FormMain_Deactivate(object sender, EventArgs e)
{
DeinitializeExcelObjects();
}
问题是(我在所有引用 _xlBook 的地方设置断点后发现的)FormMain_Deactivate() 在 [=47 之前被调用=]() 被调用,当 "Run" 按钮被点击时被调用。
一旦我在 FormMain_Deactivate() 中注释掉对 DeinitializeExcelObjects() 的调用,并在调用 _xlBook.SaveAs() 之后立即调用它,它工作正常- 文件的创建和保存没有任何错误消息。
那么为什么在窗体关闭之前调用FormDeactivate呢?如果这是某种原因 "as designed,",则该事件的命名非常错误。
您将代码放在了错误的位置。 :-) 看来您误解了激活和停用的含义(至少就 Windows 而言)。
每当不同的 window 被激活时就会发生停用,显然当你的表单被销毁时,不同的 window 必须被激活,即使那个 window 是 Windows 桌面。 FormDeactivate 可以调用多次(例如当用户切换到不同的应用程序时,甚至是您自己的应用程序中的不同 window)。请务必注意,这也适用于 activation; FormActivate 也可以触发多次。
如果您希望代码在关闭表单时 运行,请将其放入 FormClose 事件处理程序中。
我有一个 Winforms 应用程序,它使用 Excel Interop 生成 Excel 传播sheet。
当我尝试以这种方式保存 sheet 时:
_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=COM 对象已经与其底层 RCW 分离,无法使用。"
虽然这没有多大意义 - 我并没有对线程等做任何花哨的事情;这是一个非常普通的香草实用程序。代码中唯一引用 _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);
处理 _xlBook 的最后一部分是从表单的停用事件调用的,该事件是:
private void FormMain_Deactivate(object sender, EventArgs e)
{
DeinitializeExcelObjects();
}
问题是(我在所有引用 _xlBook 的地方设置断点后发现的)FormMain_Deactivate() 在 [=47 之前被调用=]() 被调用,当 "Run" 按钮被点击时被调用。
一旦我在 FormMain_Deactivate() 中注释掉对 DeinitializeExcelObjects() 的调用,并在调用 _xlBook.SaveAs() 之后立即调用它,它工作正常- 文件的创建和保存没有任何错误消息。
那么为什么在窗体关闭之前调用FormDeactivate呢?如果这是某种原因 "as designed,",则该事件的命名非常错误。
您将代码放在了错误的位置。 :-) 看来您误解了激活和停用的含义(至少就 Windows 而言)。
每当不同的 window 被激活时就会发生停用,显然当你的表单被销毁时,不同的 window 必须被激活,即使那个 window 是 Windows 桌面。 FormDeactivate 可以调用多次(例如当用户切换到不同的应用程序时,甚至是您自己的应用程序中的不同 window)。请务必注意,这也适用于 activation; FormActivate 也可以触发多次。
如果您希望代码在关闭表单时 运行,请将其放入 FormClose 事件处理程序中。