WPF Office Add-In: Как установить позицию диалога для отображения в центре родительского окна
Это расширение вопроса здесь.
Я внес следующие незначительные изменения в код для работы в случае надстройки Office.
Microsoft.Office.Interop.Outlook.Application app = Globals.ThisAddIn.Application;
if (app.ActiveWindow() != null)
{
this.Left = app.ActiveWindow().Left + (app.ActiveWindow().Width - this.Width) / 2;
this.Top = app.ActiveWindow().Top + (app.ActiveWindow().Height - this.Height) / 2;
}
Это нормально работает в нормальных условиях, но не в условиях HiDPI (например, на Mac с высоким разрешением). Всплывающие окна отображаются за пределами экрана в правом нижнем углу. Глядя на число app.ActiveWindow(). Ширина кажется огромной по сравнению с другими значениями.
Мне не удалось заставить работать хорошее решение @chessweb, поскольку окно вызова - это кнопка с ленты.
Любая идея?
2 ответа
Ну, после небольшого тестирования, я получаю следующее решение, которое хорошо работает.
Microsoft.Office.Interop.Outlook.Application app = Globals.ThisAddIn.Application;
if (app.ActiveWindow() != null) {
double WidthRatio = (1 / SystemParameters.FullPrimaryScreenWidth) *
System.Windows.Forms.Screen.FromHandle(new
WindowInteropHelper(this).Handle).Bounds.Width;
double HeightRatio = (1 / SystemParameters.FullPrimaryScreenHeight) *
System.Windows.Forms.Screen.FromHandle(new
WindowInteropHelper(this).Handle).Bounds.Height;
this.Left = (app.ActiveWindow().Left + (app.ActiveWindow().Width - this.Width * WidthRatio) / 2) / WidthRatio;
this.Top = (app.ActiveWindow().Top + (app.ActiveWindow().Height - this.Height * HeightRatio) / 2) / HeightRatio;
}
Обратите внимание, что:
- По причине, которую я не могу объяснить, соотношение высот не является идеальным ( 1.12 вместо 1, когда нет масштабирования / 2.12 при работе с коэффициентом масштабирования 2)
- В предположении, что масштабные коэффициенты высоты и ширины равны, можно использовать только один и, таким образом, обратиться к первой точке
Любые комментарии / отзывы будут оценены.
Я могу придумать несколько способов, но вот как я, вероятно, подхожу к этому:
- Получить дескриптор из активного окна Outlook.
- Установить родителя в вашем окне.
Чтобы получить ручку, используйте это:
using System.Runtime.InteropServices;
//use pInvoke to find the window
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//now use it
public static void Test(long handle)
{
Microsoft.Office.Interop.Outlook.Application app = Globals.ThisAddIn.Application;
IntPtr hWnd = (IntPtr)FindWindow("rctrl_renwnd32\0", app.ActiveWindow().Caption);
TestingWindowView win = new TestingWindowView(hWnd);
win.ShowDialog();
}
Затем в конструкторе вашего окна вы можете использовать WindowInteropHelper
назначить владельца:
using System.Windows.Interop;
public TestingWindowView(IntPtr handle)
{
InitializeComponent();
new WindowInteropHelper(this).Owner = handle;
}
и теперь в xaml вы можете сделать это:
WindowStartupLocation="CenterOwner"
Я уверен, что есть другие способы получить ручку для Outlook, но этот проверен и проверен.
надеюсь, это поможет