在Visual Studio 2017中,我创建了一个带有Form1
的Windows窗体应用程序,用户在其中选择一个打开的Excel工作簿来收听其BeforeSave
事件。
保存该工作簿后,程序会检测到该工作簿,然后从工作表中选择一些特定数据并打开Form2
该数据。
我遇到的问题是,当我在Form2
事件上加载BeforeSave
时,其控件(如标签,按钮,文本框等)无法正确显示。它们看起来像带有背景颜色的盒子。
此处我的代码缩小并更改为重要的部分:
' Reference:
' Microsoft Excel 15.0 Object Library
Imports Microsoft.Office.Interop
Public Class Form1
Private xlApp As Excel.Application
Public Shared WithEvents xlBook As Excel.Workbook
Private Shared Sub Workbook_BeforeSave(SaveAsUI As Boolean, ByRef Cancel As Boolean) Handles xlBook.BeforeSave
Form2.Show()
'Form1.Close()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Try
xlApp = Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")
xlBook = xlApp.Workbooks(1)
Catch
MsgBox("Excel isn't opened.")
Close()
End Try
End Sub
End Class
修改:使用Application.Run(Form2)
有效(不知道原因),但我也无法使用Form1
关闭Form1.Close()
。
答案 0 :(得分:1)
BeforeSave
事件与其他Interop.Excel
事件一样,是在另一个线程上引发的。因此,您无法直接从中访问GUI线程。为了访问GUI线程(例如,访问表单控件,在主线程上创建表单等),您需要使用委托调用Invoke
方法。
用以下内容替换Form2.Show()
可以解决问题:
Invoke(Sub() Form2.Show())
但是,您应该创建要加载的表单的 new 实例。因此,您应该使用以下内容代替上一行:
Private Sub Workbook_BeforeSave(SaveAsUI As Boolean,
ByRef Cancel As Boolean) Handles xlBook.BeforeSave
Invoke(Sub()
Dim frm As New Form2
frm.Show()
End Sub)
End Sub
要了解有关WinForms线程安全调用的更多信息,请查看参考文献中的第一篇文章。