Показать Form2 в событии Excel BeforeSave - PullRequest
0 голосов
/ 21 мая 2018

В Visual Studio 2017 я создаю приложение Windows Form с Form1, где пользователь выбирает открытую книгу 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().

1 Ответ

0 голосов
/ 21 мая 2018

Событие BeforeSave , как и другие события Interop.Excel , инициируется в другом потоке.Следовательно, вы не можете получить доступ к потоку GUI непосредственно из него.Чтобы получить доступ к потоку GUI (например, к элементам управления формой доступа, создать форму в главном потоке и т. Д.), Необходимо вызвать метод Invoke с делегатом.

Замена Form2.Show() наследующее решит проблему:

Invoke(Sub() Form2.Show())

Однако вы должны создать новый экземпляр формы, которую вы хотите загрузить.Таким образом, вместо предыдущей строки вы должны использовать что-то вроде следующего:

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, ознакомьтесь с первой статьей в ссылках.


Ссылки:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...