C# 为什么';子窗体是否与父窗体出现在同一屏幕上?

C# 为什么';子窗体是否与父窗体出现在同一屏幕上?,c#,winforms,vsto,handle,multiple-monitors,C#,Winforms,Vsto,Handle,Multiple Monitors,更新 private void ObjButtonFoo_Click(object sender, RibbonControlEventArgs e) { NativeWindow winWordMain = new NativeWindow(); winWordMain.AssignHandle(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.Hwnd)); IntPtr(Globals.ThisAddIn.A

更新

private void ObjButtonFoo_Click(object sender, RibbonControlEventArgs e)
{
    NativeWindow winWordMain = new NativeWindow();
    winWordMain.AssignHandle(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.Hwnd));
    IntPtr(Globals.ThisAddIn.Application.ActiveWindow.Hwnd);

    using (ClsFormFoo objFormFoo = new ClsFormFoo()
    {
        objFormFoo.ShowDialog(winWordMain);
    }

    winWordMain.ReleaseHandle();
}
我接受了鲁弗斯L的回答,并做了一些修改,相关代码如下

public partial class ClsOfficeRibbonFooTab
{

    private void FooTab_Load(object sender, RibbonUIEventArgs e)
    {
         .
         .
         .
    }

    private void CheckResolution()
    {
        // set the left position so that the expanded version of the form fits on the screen
        Screen screen = Screen.FromHandle(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.Hwnd));

        if (screen.Bounds.Width < 1360 || screen.Bounds.Height < 768)
        {
            throw new FormatException(String.Format("The {0} is supported on screens with a resolution of 1360 by 768 or greater. Your screen is {1} by {2}", "Some caption text", screen.Bounds.Width, screen.Bounds.Height));
        }
    }

    private void ObjButtonFoo_Click(object sender, RibbonControlEventArgs e)
    {
        using (ClsFormFoo objFormFoo = new ClsFormFoo(parentWindow: Globals.ThisAddIn.Application.ActiveWindow))
        {
            CheckResolution();
            objFormFoo.ShowDialog();
        }
    }
}

public partial class ClsFormFoo : Form
{
    // This form is a fixed dialog with a flyout on the right side. 
    // expandedWidth is a const set to the max width of this fixed dialog (i.e., the dialog with the flyout extended)
    const int expandedWidth = 1345;

    public ClsFormFoo(Microsoft.Office.Interop.Word.Window parentWindow)
    {
        InitializeComponent();
        Top = parentWindow.Top;
    }

    private void ClsFormFoo_Load(object sender, EventArgs e)
    {
        Screen screen = Screen.FromHandle(new IntPtr(Globals.ThisAddIn.Application.ActiveWindow.Hwnd));

        // set the left position so that the expanded version of the form fits on the screen for all legal resolutions
        int halfScreenWidth = (int)(screen.WorkingArea.Width / 2);
        // This form is a fixed dialog with a flyout on the right side. 
        // expandedWidth is a const set to the max width of this fixed dialog (i.e., the dialog with the flyout extended)
        int halfFormWidth = (int)(expandedWidth / 2);
        this.Left = screen.Bounds.Left + ((int)(halfScreenWidth - halfFormWidth));
    }
}
winWordMain


我不需要VSTO来测试这一点,但在我看来,您只需获取用作父窗体的
ActiveWindow的位置,然后将其用作定位子窗体的参考:

private void allRootsWithChilds_CheckedChanged(object sender, EventArgs e)
{
    var winWordMain = new NativeWindow();
    var parent = Globals.ThisAddIn.Application.ActiveWindow;
    winWordMain.AssignHandle(new IntPtr(parent.Hwnd));

    using (var objFormFoo = new ClsFormFoo())
    {
        // Set the Left and Top properties so this form is centered over the parent
        objFormFoo.Left = parent.Left + (parent.Width - objFormFoo.Width) / 2;
        objFormFoo.Top = parent.Top + (parent.Height - objFormFoo.Height) / 2;

        objFormFoo.ShowDialog(winWordMain);
    }

    winWordMain.ReleaseHandle();
}

我不需要VSTO来测试这一点,但在我看来,您可以只获取您用作父窗体的
ActiveWindow
的位置,然后将其用作定位子窗体的参考:

private void allRootsWithChilds_CheckedChanged(object sender, EventArgs e)
{
    var winWordMain = new NativeWindow();
    var parent = Globals.ThisAddIn.Application.ActiveWindow;
    winWordMain.AssignHandle(new IntPtr(parent.Hwnd));

    using (var objFormFoo = new ClsFormFoo())
    {
        // Set the Left and Top properties so this form is centered over the parent
        objFormFoo.Left = parent.Left + (parent.Width - objFormFoo.Width) / 2;
        objFormFoo.Top = parent.Top + (parent.Height - objFormFoo.Height) / 2;

        objFormFoo.ShowDialog(winWordMain);
    }

    winWordMain.ReleaseHandle();
}

我曾经在C#上做过一个简单的屏幕保护程序。我使用以下代码在所需屏幕或所有屏幕上打开屏幕保护程序

您必须从所需屏幕获取
边界
,并将其传递给表单

// Constructor
public NameForm(Rectangle bounds)
{
    InitializeComponent();

    this.Bounds = bounds;
}

// In my case, this is opening the screensaver on all screens
foreach (Screen screen in Screen.AllScreens)
{
    NameForm form = new NameForm (screen.Bounds);
    form.Show();
}

我曾经在C#上做过一个简单的屏幕保护程序。我使用以下代码在所需屏幕或所有屏幕上打开屏幕保护程序

您必须从所需屏幕获取
边界
,并将其传递给表单

// Constructor
public NameForm(Rectangle bounds)
{
    InitializeComponent();

    this.Bounds = bounds;
}

// In my case, this is opening the screensaver on all screens
foreach (Screen screen in Screen.AllScreens)
{
    NameForm form = new NameForm (screen.Bounds);
    form.Show();
}

您只需将表单的
StartPosition
属性设置为
FormStartPosition.CenterParent
值:

loginForm.StartPosition = FormStartPosition.CenterParent;
loginForm.ShowDialog(parentWindowdle);

您只需将表单的
StartPosition
属性设置为
FormStartPosition.CenterParent
值:

loginForm.StartPosition = FormStartPosition.CenterParent;
loginForm.ShowDialog(parentWindowdle);


如果消息散布在多个监视器上,您会有什么期望?你只是想把你的表格放在单词的中心吗?还是你在试图检测监视器?@RufusL:记不起我在哪里见过它,但我想我读到,如果一个应用程序跨监视器,Windows会报告该应用程序在监视器上,而监视器上有应用程序的大部分窗口。在任何情况下,我都希望窗体集中在Windows报告应用程序所在的屏幕上。我的更新代码(基于您的答案)实现了这一点。如果单词散布在多个监视器上,您希望看到什么?你只是想把你的表格放在单词的中心吗?还是你在试图检测监视器?@RufusL:记不起我在哪里见过它,但我想我读到,如果一个应用程序跨监视器,Windows会报告该应用程序在监视器上,而监视器上有应用程序的大部分窗口。在任何情况下,我都希望窗体集中在Windows报告应用程序所在的屏幕上。我更新的代码(基于您的答案)实现了这一点,可能是因为我使用的是
ShowDialog(IWin32Window对象)
和/或是因为它是一个VSTO加载项,在本例中,父项是Word应用程序,但您的方法不起作用。我做了您建议的更改,当我在辅助监视器上看到Word时,
objFormFoo
继续出现在主监视器上。此外,我的objFormFoo的显式宽度和高度设置(它是一个
FixedDialog
)将被忽略,而objFormFoo显示的宽度和高度是我无法显示的explain@NovaSysEng我会亲自尝试,并说你的结果很糟糕-我忘了在我的
ClsFormFoo
代码中,我自己修改
Left”属性,以便根据屏幕分辨率居中。当我使用您的代码并注释掉我的代码时,
objFormFoo`与Word本身出现在同一屏幕上。但是,我在设计器中建立的ClsFormFoo高度设置是用传入的父屏幕边界对象的
高度设置重写的。因此,我不得不接受鲁弗斯L的解决方案。它仅修改将
objFormFoo
移动到与父项相同屏幕所需的属性。@NovaSysEng尝试将
表单的
开始位置设置为
手动
。由于
bounds
包含屏幕的大小,因此
表单将全屏打开。你需要自己改变这个。以及起始位置(
位置
)。从所需屏幕的边界开始。可能是因为我使用的是
ShowDialog(IWin32Window对象)
和/或是因为它是一个VSTO加载项,在本例中父项是Word应用程序,但您的方法不起作用。我做了您建议的更改,当我在辅助监视器上看到Word时,
objFormFoo
继续出现在主监视器上。此外,我的objFormFoo的显式宽度和高度设置(它是一个
FixedDialog
)将被忽略,而objFormFoo显示的宽度和高度是我无法显示的explain@NovaSysEng我会亲自尝试,并说你的结果很糟糕-我忘了在我的
ClsFormFoo
代码中,我自己修改
Left”属性,以便根据屏幕分辨率居中。当我使用您的代码并注释掉我的代码时,
objFormFoo`与Word本身出现在同一屏幕上。但是,我在设计器中建立的ClsFormFoo高度设置是用传入的父屏幕边界对象的
高度设置重写的。因此,我不得不接受鲁弗斯L的解决方案。它仅修改将
objFormFoo
移动到与父项相同屏幕所需的属性。@NovaSysEng尝试将
表单的
开始位置设置为
手动
。由于
bounds
包含屏幕的大小,因此
表单将全屏打开。你需要自己改变这个。以及起始位置(
位置
)。从所需屏幕的边界开始。请参见“我的操作”中的“更新”。无需进行任何数学计算。
StartPosition
属性是否正是为此目的而创建的?@EugeneAstafiev
表单
有一个弹出按钮。我需要使用最坏的情况(1345像素宽)计算左/顶,这样当窗体第一次出现(900像素宽)时,当弹出按钮出现时,它仍然适合屏幕。此外,该应用程序支持屏幕分辨率1360x768-1920x1080
StartPosition
在我的例子中是
Manual
,即,我不想或不需要Windows定位我的表单。有关更多信息,请参阅