为什么我的Modal WPF对话框在MS Word后面滑动 [英] Why does my Modal WPF dialog slip behind MS Word

查看:92
本文介绍了为什么我的Modal WPF对话框在MS Word后面滑动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用VSTO编写的MS Word应用程序加载项.它包含一个用于创建新的Letter文档的按钮.当按下一个文档实例化时,将显示一个WPF对话框以捕获信息,然后将该信息插入到文档中.

I have a MS Word Application Add-in written with VSTO. It contains a button used to create new Letter documents. When pressed a document is instantiated, a WPF dialog is displayed to capture information and then the information is inserted into the document.

在极少数情况下,WPF对话框会落后于MS Word.然后,我必须杀死Winword.exe进程,因为对话框是Modal对话框. 我在WPF对话框中使用以下代码. OfficeDialog子类用于使对话框看起来像MS-Word对话框.

On rare occasions, the WPF dialog slips behind MS Word. I then have to kill the Winword.exe process because the dialog is Modal. I use the following code for my WPF dialog. The OfficeDialog sub class is used to make the dialog look like a MS-Word dialog.

var view = new LetterDetailsView(ViewModel);
view.ShowDialog();

public class OfficeDialog : Window
{
    [DllImport("user32.dll")]
    static extern int GetWindowLong(IntPtr hwnd, int index);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
    [DllImport("user32.dll")]
    static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);
    [DllImport("user32.dll")]
    static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

    const int GWL_EXSTYLE = -20;
    const int WS_EX_DLGMODALFRAME = 0x0001;
    const int SWP_NOSIZE = 0x0001;
    const int SWP_NOMOVE = 0x0002;
    const int SWP_NOZORDER = 0x0004;
    const int SWP_FRAMECHANGED = 0x0020;
    const uint WM_SETICON = 0x0080;
    const int ICON_SMALL = 0;
    const int ICON_BIG = 1;

    public OfficeDialog()
    {
        this.ShowInTaskbar = false;
    }

    public new void ShowDialog()
    {
        try
        {
            var helper = new WindowInteropHelper(this);
            using (Process currentProcess = Process.GetCurrentProcess())
                helper.Owner = currentProcess.MainWindowHandle;
            base.ShowDialog();
        }
        catch (System.ComponentModel.Win32Exception ex)
        {
            Message.LogWarning(ex);
            var helper = new WindowInteropHelper(this);
            using (Process currentProcess = Process.GetCurrentProcess())
                helper.Owner = currentProcess.MainWindowHandle;
            base.ShowDialog();
        }
    }

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        RemoveIcon(this);
        HideMinimizeAndMaximizeButtons(this);
    }

    public static void HideMinimizeAndMaximizeButtons(Window window)
    {
        const int GWL_STYLE = -16;

        IntPtr hwnd = new WindowInteropHelper(window).Handle;
        long value = GetWindowLong(hwnd, GWL_STYLE);

        SetWindowLong(hwnd, GWL_STYLE, (int)(value & -131073 & -65537));
    }

    public static void RemoveIcon(Window w)
    {
        // Get this window's handle 
        IntPtr hwnd = new WindowInteropHelper(w).Handle;

        // Change the extended window style to not show a window icon
        int extendedStyle = OfficeDialog.GetWindowLong(hwnd, GWL_EXSTYLE);
        OfficeDialog.SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME);

        // reset the icon, both calls important
        OfficeDialog.SendMessage(hwnd, WM_SETICON, (IntPtr)ICON_SMALL, IntPtr.Zero);
        OfficeDialog.SendMessage(hwnd, WM_SETICON, (IntPtr)ICON_BIG, IntPtr.Zero);

        // Update the window's non-client area to reflect the changes
        OfficeDialog.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
    }

    static void SetCentering(Window win, IntPtr ownerHandle)
    {
        bool isWindow = IsWindow(ownerHandle);
        if (!isWindow) //Don't try and centre the window if the ownerHandle is invalid.  To resolve issue with invalid window handle error
        {
            //Message.LogInfo(string.Format("ownerHandle IsWindow: {0}", isWindow));
            return;
        }
        //Show in center of owner if win form.
        if (ownerHandle.ToInt32() != 0)
        {
            var helper = new WindowInteropHelper(win);
            helper.Owner = ownerHandle;
            win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
        }
        else
            win.WindowStartupLocation = WindowStartupLocation.CenterOwner;
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    static extern bool IsWindow(IntPtr hWnd);

}

推荐答案

模式对话框不位于顶部是由于所有者设置不正确造成的.您已经将所有者设置为当前进程的MainWindowHandle;但是,特别是在打开多个Word文档的情况下,这可能不是您想要的.

A modal dialog not being on top is the result of an incorrectly set owner. You already set the owner to the MainWindowHandle of the current process; however, in particular with multiple Word documents open, this might not be what you want.

我建议使用以下属性(Word 2013引入):

I'd suggest to rely on the following property (introduced with Word 2013):

document.ActiveWindow.HWnd;

除此之外,不需要杀死Word进程.足以最小化所有窗口(例如,按 Windows键+ M )

Apart from that there should not be the need to kill the Word process. It should be sufficient to minimize all windows (e.g. by pressing Windows Key + M)

这篇关于为什么我的Modal WPF对话框在MS Word后面滑动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆