2013-09-27 24 views
1

我正在爲Excel創建一個VSTO插件,而且我的第一次嘗試可行,但我對設計不滿意。由於標準的VSTO只處理Windows窗體。我現在正在接觸WPF,並發現佈局和動畫的選項可以帶來更好的用戶體驗。VSTO Excel插件中的獨立WPF表單將無法保持聚焦​​

我現在已經發現我可以添加一個WPF項目到VSTO解決方案,並調用這種形式...非常好!

問題是,當我打開我這樣做的一種形式:

Dim NewForm as New NewForm 
NewForm.Show() 

這工作得很好,和窗體打開,但如果我嘗試輸入文本框,表格下降背後Excel和文本進入Excel中的活動單元格。

如果我做的:

Dim NewForm as New NewForm 
NewForm.ShowDialog() 

它工作正常。不幸的是,我不能讓我的應用程序使用表單。我怎樣才能解決這個問題?

+0

下面是這個問題的答案。 http://stackoverflow.com/questions/5869359/wpf-modeless-dialog-from-ms-excel-add-in – Kiru

回答

2

我用下面的類: https://dl.dropboxusercontent.com/u/62538279/Help/OfficeDialog.cs

你會注意到的ShowDialog()方法被替換

類也使對話框看起來像一個Word VBA形式(東西我的客戶往往希望)

我dialog.xaml.cs類是什麼樣子(和XAML匹配):

public partial class myDialog : OfficeDialog 

- 編輯 -

這是源代碼。我一直在遇到麻煩。它偶爾會滑倒的應用程序背後(很少)

http://stackoverflow.com/questions/40374059/why-does-my-modal-wpf-dialog-slip-behind-ms-word/40401198#40401198

using System; 
using System.Diagnostics; 
using System.Runtime.InteropServices; 
using System.Windows; 
using System.Windows.Interop; 

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; 

    /// <summary> 
    /// Sometimes get System.ComponentModel.Win32Exception: Invalid window handle 
    /// I'm pretty sure that this is because Word is shit at handling windows and has an internal memory leak 
    /// http://stackoverflow.com/questions/222649/winforms-issue-error-creating-window-handle 
    /// I'm not sure why this error isn't trapped and logged by the try catch below. Somehow it bubbles up to the calling routine.. 
    /// </summary> 
    public OfficeDialog() 
    { 
     this.ShowInTaskbar = false; 
     //this.Topmost = true; 

     //Uri uri = new Uri("PresentationFramework.Aero;V3.0.0.0;31bf3856ad364e35;component\\themes/aero.normalcolor.xaml", UriKind.Relative); 
     //Uri uri = new Uri("PresentationFramework.Classic;V3.0.0.0;31bf3856ad364e35;component\\themes/classic.xaml", UriKind.Relative); 
     //Resources.MergedDictionaries.Add(Application.LoadComponent(uri) as ResourceDictionary); 

     //var helper = new WindowInteropHelper(this); 
     //using (Process currentProcess = Process.GetCurrentProcess()) 
     // helper.Owner = currentProcess.MainWindowHandle; 
    } 

    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); 
      //this.Topmost = true; 
      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); 
     //using (Process currentProcess = Process.GetCurrentProcess()) 
     // SetCentering(this, currentProcess.MainWindowHandle); 
    } 

    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

鏈接不起作用。你能粘貼OfficeDialog.cs的源代碼嗎? –