前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何利用 Win32 API 设置两个窗口的所有者(Owner)关系

如何利用 Win32 API 设置两个窗口的所有者(Owner)关系

作者头像
walterlv
发布2023-10-23 17:22:25
3810
发布2023-10-23 17:22:25
举报

设置两个窗口的父子关系非常简单,只需要调用 SetParent 函数即可。然而设置两个窗口的所有者(Owner)关系却没有一个简单直观的 API。那么本文介绍一下如何设置两个窗口的 Owner 关系。

设置所有者(Owner)

由于方法非常简单,所以我直接贴出 MainWindow 中的完整代码:

代码语言:javascript
复制
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        SourceInitialized += OnSourceInitialized;
    }

    private void OnSourceInitialized(object? sender, EventArgs e)
    {
        var ownerHwnd = User32.GetForegroundWindow();
        var hwnd = new WindowInteropHelper(this).Handle;
        User32.SetWindowLong(hwnd,
            GetWindowLongIndexes.GWL_HWNDPARENT,
            (nint)ownerHwnd);
    }
}

在这里,我准备好了两个窗口句柄,一个是 ownerHwnd,我随便取了当前窗口的;另一个是 hwnd 即自己的句柄。这样,程序启动的时候,便会把自己窗口的所有者设置为启动前最后一个前台窗口。

接下来是关键代码 SetWindowLong,传入三个参数:

  1. 自己窗口的句柄 hwnd
  2. GWL_HWNDPARENT 即指定所有者(在官方文档中,依然将其描述为 parent`)
  3. 所有者窗口的句柄 ownerHwnd

所需 API

在 C# 中,以上 API 函数需要定义。为了方便,你可以直接安装库 Lsj.Util.Win32 以省去所有的定义工作。

如果你不想引入库,可以用下面我准备好的定义(摘自 Lsj.Util.Win32 并简化):

代码语言:javascript
复制
public static nint SetWindowLong([In] nint hWnd, [In] GetWindowLongIndexes nIndex, [In] nint dwNewLong) => nint.Size > 4
    ? SetWindowLongPtrImp(hWnd, nIndex, dwNewLong)
    : SetWindowLongImp(hWnd, nIndex, dwNewLong.ToInt32());

[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SetWindowLongW", ExactSpelling = true, SetLastError = true)]
private static extern int SetWindowLongImp(nint hWnd, GetWindowLongIndexes nIndex, int dwNewLong);

[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SetWindowLongPtrW", ExactSpelling = true, SetLastError = true)]
private static extern nint SetWindowLongPtrImp(nint hWnd, GetWindowLongIndexes nIndex, nint dwNewLong);

public enum GetWindowLongIndexes
{
    GWL_HWNDPARENT = -8,
}

后续需求

出于兼容性考虑,即便设置为了所有者关系,Windows 系统也不会强制修改窗口的样式(例如从任务栏中去掉)。你可以考虑将窗口的 WindowStylesEx 属性中的 WS_EX_APPWINDOW 部分去掉来实现这样的效果。

代码语言:javascript
复制
var style = style & ~WindowStylesEx.WS_EX_APPWINDOW;

至于具体如何使用 GetWindowLongSetWindowLong 来实现以上目的,本文就不赘述了。

参考资料

本文会经常更新,请阅读原文: /developer/article/2350170 ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email?protected])

本文参与?腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 设置所有者(Owner)
  • 所需 API
  • 后续需求
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com