我有一个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
异常:
未处理的类型&#39; System.Threading.ThreadAbortException&#39;发生在System.Windows.Forms.dll
其他信息:线程正在中止。
为了解决这个问题,我尝试了以下代码,但没有工作:
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
var frms = Globals.Ribbons.MyRibbonMenu.Forms.ToArray();
foreach (var frm in frms)
{
frm.Close();
}
}
我在哪里可以犯错?
答案 0 :(得分:3)
我使用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);
}
答案 1 :(得分:0)
编辑:我在这里添加我的答案b \ c用户答案是一个解决方法,而不是解释问题的可能性:我建议查看解决方案微软推出并根据您的需要进行修改
在此处查看我的回答:https://stackoverflow.com/a/38157476/ 根据您正在尝试收听的窗口,您可能会破坏非托管窗口监听器,遗憾的是NativeWindow.ReleaseHandle不知道如何恢复子类窗口链,而是替换您使用User32更改的窗口wndproc!DefWindowProc [this]将导致应用程序崩溃或挂起。