【问题标题】:How to keep window on top of another window in a different thread?如何将窗口保持在不同线程中的另一个窗口之上?
【发布时间】:2009-05-08 14:06:16
【问题描述】:

我有一个承载一些 WPF UI(通过 ElementHost)的 WinForms 表单(称为“MyForm”)。我在与主 UI 线程不同的线程上显示此表单。

我希望“MyForm”保留在主应用程序窗口的顶部,因此我使用 Show 方法的 Show(IWin32Window) 重载来显示表单,传入的 IWin32Window 是主应用程序窗口。

该窗口通过“启动器表单”间接显示,该表单是单独的 STA 线程(传递给 Application.Run 的线程)的“应用程序表单”。原因是您无法在通过 Application.Run 启动表单时指定所有者窗口。

这是启动 MyForm 的代码(用作 STA 线程的 ThreadStart):

void MyWindowThread()
{
  myForm = new MyForm();
  var launcherForm = new LauncherForm(myForm, mainWindow);
  Application.Run(new ApplicationContext(launcherForm));
  // launcherForm will Show myForm when it itself is shown.
}

“启动器”表单:

public partial class LauncherForm : Form
{
  private readonly MyForm _myForm;
  private readonly IWin32Window _mainWindow;

  public WizardUILauncherForm(MyForm myForm, IWin32Window mainWindow)
  {
    _myForm = myForm;
    _mainWindow = mainWindow;
    InitializeComponent();
  }

  protected override void OnShown(EventArgs e)
  {
    // show the actual form that the user will interact with, on top of mainWindow.
    _myForm.Show(_mainWindow);
  }
}

这几乎可行。 'MyForm' 停留在主应用程序窗口的顶部,但直到我将鼠标悬停在带有工具提示的 WPF 控件上。显示工具提示时,“MyForm”会消失在主应用程序窗口后面。当我将鼠标悬停在窗体上的 WinForms 控件以显示其工具提示时,不会发生这种情况 - 它似乎特定于 WPF 控件。

只有当 MyForm 是前台窗口时才会发生这种情况。

请注意,当我使用 MyForm 作为应用程序表单(跳过启动器)并覆盖 MyForm 的 OnLoad 方法以使用 SetWindowLong 设置其所有者时,我遇到了同样的问题。这是一种较少涉及的方式,但我想使用一种不使用 P-Invoke 的机制,看看这是否会更好。两种方法的破坏方式相同。

更新 测试应用程序暗示此问题特定于在 Visual Studio 向导扩展中显示 UI。我想这会让它更加利基,甚至更不可能被回答!

【问题讨论】:

    标签: wpf windows winforms


    【解决方案1】:

    以下 MSDN 文章是关于 WinAPI 调用的,但希望它能让您对不同线程之间的窗口激活有所了解(我假设您无论如何都必须直接 P/Invoke 到 WinAPI 中,除非您可以避免在多个线程上使用您的 UI ):

    Multiple Threads in the User Interface

    (特别是参见窗口焦点和激活注意事项部分

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-04
      • 2011-03-20
      • 1970-01-01
      • 1970-01-01
      • 2013-01-30
      • 1970-01-01
      相关资源
      最近更新 更多