2016-11-02 28 views
1

私はMS WordアプリケーションアドインをVSTOで書いています。新しいLetterドキュメントを作成するためのボタンが含まれています。ドキュメントがインスタンス化されると、情報を取得するためのWPFダイアログが表示され、その情報がドキュメントに挿入されます。Modal WPFダイアログがMS Wordの後ろにずれ込む理由

まれに、WPFダイアログがMS Wordの後ろにずれます。ダイアログがモーダルなので、私はWinword.exeプロセスを終了する必要があります。 WPFダイアログに次のコードを使用します。 OfficeDialogサブクラスは、ダイアログをMS-Wordダイアログのように見せるために使用されます。上でない

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); 

}

+0

親ウィンドウからダイアログを独立して使用できますか? (モーダルのため、無効にする必要があるOfficeウィンドウを使用する) – Peter

答えて

1

モーダルダイアログが誤って設定所有者の結果です。すでに所有者を現在のプロセスのMainWindowHandleに設定しました。しかし、特に複数のWord文書を開いている場合、これはあなたが望むものではないかもしれません。

私は(ワード2013で導入された)次のプロパティに依存することをお勧めしたい:

document.ActiveWindow.HWnd; 

別にWordのプロセスを強制終了する必要があってはならないということから。すべてのウィンドウを最小化するだけで十分です(たとえば、Windowsキー+ M

関連する問題