将窗口所有者设置为来自另一个调度程序线程的窗口

问题描述 投票:0回答:1

我有一个应用程序,它创建一个在它自己的调度程序上运行的单独窗口(原因很复杂,但遗憾的是需要)

我想要的是这个单独的窗口始终显示在应用程序窗口上方。根据我的阅读,这应该可以使用 pinvoke 和 SetWindowLong 实现,但我似乎无法让它工作。我没有遇到任何异常,但单独的窗口不会保留在应用程序窗口的顶部。当您选择父窗口时,它位于父窗口后面。

顺便提一下,我试图避免使用 TopMost,因为我只希望它位于父窗口上方,而不是所有其他窗口上方。

你知道我做错了什么吗?

internal class WindowHelper
{
    private const int GWL_HWNDPARENT = -8;

    [DllImport("user32.dll")]
    private static extern IntPtr SetWindowLong(IntPtr hwnd, int index, int newStyle);

    public static void SetOwnerWindow(IntPtr hwndOwned, IntPtr intPtrOwner)
    {
        try
        {
            if (hwndOwned != IntPtr.Zero && intPtrOwner != IntPtr.Zero)
            {
                SetWindowLong(hwndOwned, GWL_HWNDPARENT, intPtrOwner.ToInt32());
            }
        }
        catch { }
    }
}

public partial class MainWindow : Window
{
    IntPtr parentHandle = IntPtr.Zero;

    public MainWindow()
    {
        InitializeComponent();

        Loaded += MainWindow_Loaded;
    }

    private void MainWindow_Loaded(object sender, RoutedEventArgs e)
    {
        parentHandle = new WindowInteropHelper(this).Handle;
        CreateNewWindow();
    }

    private void CreateNewWindow()
    {
        Thread newWindowThread = new Thread(new ThreadStart(ThreadStartingPoint));
        newWindowThread.SetApartmentState(ApartmentState.STA);
        newWindowThread.IsBackground = true;
        newWindowThread.Start();
    }

    private void ThreadStartingPoint()
    {
        var tempWindow = new Window();
        tempWindow.Show();

        IntPtr childHandle = new WindowInteropHelper(tempWindow).Handle;
        WindowHelper.SetOwnerWindow(childHandle, parentHandle);

        System.Windows.Threading.Dispatcher.Run();
    }
}
wpf window dispatcher owner
1个回答
0
投票

原来我需要使用 64 位版本的

SetWindowLong

http://pinvoke.net/default.aspx/user32/SetWindowLongPtr.html

// This static method is required because legacy OSes do not support
// SetWindowLongPtr
public static IntPtr SetWindowLongPtr(HandleRef hWnd, int nIndex, IntPtr dwNewLong)
{
      if (IntPtr.Size == 8)
      return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
      else
      return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong.ToInt32()));
}

[DllImport("user32.dll", EntryPoint="SetWindowLong")]
private static extern int SetWindowLong32(HandleRef hWnd, int nIndex, int dwNewLong);

[DllImport("user32.dll", EntryPoint="SetWindowLongPtr")]
private static extern IntPtr SetWindowLongPtr64(HandleRef hWnd, int nIndex, IntPtr dwNewLong);
© www.soinside.com 2019 - 2024. All rights reserved.