簡體   English   中英

Excel VSTO中的Form.Show(IWin32Window)方法在應用程序關閉時導致ThreadAbortException

[英]Form.Show(IWin32Window) method in Excel VSTO causing ThreadAbortException on application close

我有一個Excel加載項,並且我有一個想要成為Excel窗口前面的表格。 為此,我在excel功能區菜單按鈕上使用NativeWindow來實現此目的:

public partial class MyRibbonMenu
{
    public List<Form> Forms = new List<Form>();

    private void button1_Click(object sender, RibbonControlEventArgs e)
    {
        // initialize form
        Form frm = new Form();
        frm.Text = "Test Form";
        Forms.Add(frm);

        // create the native window handle
        NativeWindow nw = new NativeWindow();
        IntPtr iptr = new IntPtr(Globals.ThisAddIn.Application.Hwnd);
        nw.AssignHandle(iptr);

        // when close the form release the handle
        frm.FormClosed += (sender2, e2) =>
        {
            Forms.Remove(frm);
            nw.ReleaseHandle();
        };

        // show with owner
        frm.Show(nw);
    }

}

如果我在退出excel之前關閉表單,一切正常,那么效果很好。 但是,如果用戶要退出excel而不關閉打開的表單,則會發生ThreadAbortException異常:

System.Windows.Forms.dll中發生類型為'System.Threading.ThreadAbortException'的未處理異常

附加信息:線程被中止。

為了解決此問題,我嘗試了以下代碼,但沒有起作用:

private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
    var frms = Globals.Ribbons.MyRibbonMenu.Forms.ToArray();
    foreach (var frm in frms)
    {
        frm.Close();
    }
}

我在哪里犯錯?

我使用IWin32Window接口代替NativeWindow解決了這個問題:

public class Win32Window : System.Windows.Forms.IWin32Window
{
    public Win32Window(int windowHandle)
    {
        _windowHandle = new IntPtr(windowHandle);
    }

    IntPtr _windowHandle;

    public IntPtr Handle
    {
        get { return _windowHandle; }
    }
}

在此之后,我更改下面的表單初始化代碼:

private void button1_Click(object sender, RibbonControlEventArgs e)
{
    // initialize form
    var frm = new Form();
    frm.FormBorderStyle = FormBorderStyle.FixedSingle;
    frm.MinimizeBox = false;
    frm.MaximizeBox = false;
    frm.Text = "Test Form";
    frm.StartPosition = FormStartPosition.CenterScreen;
    Forms.Add(frm);

    // create the native window handle
    var nw = new Win32Window(Globals.ThisAddIn.Application.Hwnd);

    // show with owner
    frm.Show(nw);
}

編輯:我在這里添加我的答案b \\ c用戶答案是一種變通方法,而不是對可能出現的問題的解釋:我建議檢查Microsoft提出的解決方案並根據您的需要進行修改。

在這里看到我的答案: https : //stackoverflow.com/a/38157476/取決於您嘗試在哪個窗口上監聽您,可能是在偽造非托管窗口監聽器,不幸的是,NativeWindow.ReleaseHandle不知道如何還原子類化窗口鏈,而是用User32!DefWindowProc [this]替換您更改的Windows wndproc,這將導致應用程序崩潰或掛起。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM