将非拥有窗口始终设置在顶部 - 就像应用程序“Afloat”

2024-01-03

我设置了一个全局热键RegisterEventHotkey。当用户按下它时,它会获取当前聚焦的窗口CGWindowListCopyWindowInfo,然后我需要将它始终设置在顶部。

如果当前窗口在我的进程中(我正在从中执行代码),我可以简单地将windowNumber from CGWindowListCopyWindowInfo to a NSWindow and do setLevel:

nswin = [NSApp windowWithWindowNumber:windowNumber]
[nswin setLevel: Int(CGWindowLevelForKey(kCGFloatingWindowLevelKey))]

我的问题如果当前聚焦的窗口不在我的进程中,我将无法执行此操作。你能告诉我怎么做吗?

我尝试过的东西:

  • This app here named "Afloat" used "SIMBL" to accomplish this. From any window you can hit Cmd + A and it will set always on top. However I am trying to do with C/ObjC from my normal desktop app without the use of helpers like SIMBL.
    • Source: 强制将应用程序窗口保持在顶部 - Mac OS X https://stackoverflow.com/questions/19567781/force-keeping-app-window-on-top-mac-os-x#comment33938908_19567781
    • SIMBL: http://www.culater.net/software/SIMBL/SIMBL.php http://www.culater.net/software/SIMBL/SIMBL.php
    • Afloat: https://www.macupdate.com/app/mac/22237/afloat https://www.macupdate.com/app/mac/22237/afloat
  • 我遇到CGSSetWindowLevel in CGPrivate.h- 无证的东西 -https://gist.github.com/Noitidart/3664c5c2059c9aa6779f#file-cgsprivate-h-L63 https://gist.github.com/Noitidart/3664c5c2059c9aa6779f#file-cgsprivate-h-L63- 不过,我记得我过去尝试过类似的操作,但当我尝试连接到不在调用过程中的窗口时会出现错误。

    • 这里说——https://github.com/lipidity/CLIMac/blob/114dfee39d24809f62ccb000ea22dfda15c11ce8/src/CGS/CGSInternal/.svn/text-base/CGSConnection.h.svn-base#L82 https://github.com/lipidity/CLIMac/blob/114dfee39d24809f62ccb000ea22dfda15c11ce8/src/CGS/CGSInternal/.svn/text-base/CGSConnection.h.svn-base#L82

      只有窗口的所有者才能操作它。因此,苹果有一个通用所有者的概念,它拥有所有窗口并可以操纵它们。一次只能有一个通用所有者(Dock)。

    • 也许,有没有办法假装我的呼叫进程暂时成为码头?或许CGSGetConnectionIDForPSN对于坞站然后使用该连接?

我的用途:我正在尝试复制我的开源、免费、浏览器插件的功能 -https://addons.mozilla.org/en-US/firefox/addon/topick/ https://addons.mozilla.org/en-US/firefox/addon/topick/- 所以我的调用过程如果是Firefox。它现在可以在 Windows 和 Linux 上运行,只需要弄清楚如何在 Mac 上为非 Firefox Windows 执行此操作。


看来您想让外部进程的窗口保持在所有其他应用程序之上,而我在这里提供的代码并不能完全满足您的需求,它至少有些相似,并且可能足以满足您的需求,取决于您的用例。在这个例子中,我演示了如何保持CGWindowID在特定的之上NSWindow *。注意——NSWindow *是父窗口,它需要由您的应用程序拥有,但是CGWindowID用于子窗口可以属于任何应用程序)。如果你想要NSWindow *要成为子窗口,请更改NSWindowBelow选项NSWindowAbove.

这个解决方案有一个小问题,那就是当父窗口试图获得焦点但随后立即失去焦点时,这里和那里会出现一些轻微的闪烁 - 闪烁发生得非常快且间歇性,如果你超级强大,也许可以忽略它绝望的。

无论如何,代码是...

cocoa.mm

#import "subclass.h"
#import <Cocoa/Cocoa.h>
#import <sys/types.h>

NSWindow *cocoa_window_from_wid(CGWindowID wid) {
  return [NSApp windowWithWindowNumber:wid];
}

CGWindowID cocoa_wid_from_window(NSWindow *window) {
  return [window windowNumber];
}

bool cocoa_wid_exists(CGWindowID wid) {
  bool result = false;
  const CGWindowLevel kScreensaverWindowLevel = CGWindowLevelForKey(kCGScreenSaverWindowLevelKey);
  CFArrayRef windowArray = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
  CFIndex windowCount = 0;
  if ((windowCount = CFArrayGetCount(windowArray))) {
    for (CFIndex i = 0; i < windowCount; i++) {
      NSDictionary *windowInfoDictionary =
      (__bridge NSDictionary *)((CFDictionaryRef)CFArrayGetValueAtIndex(windowArray, i));
      NSNumber *ownerPID = (NSNumber *)(windowInfoDictionary[(id)kCGWindowOwnerPID]);
      NSNumber *level = (NSNumber *)(windowInfoDictionary[(id)kCGWindowLayer]);
      if (level.integerValue < kScreensaverWindowLevel) {
        NSNumber *windowID = windowInfoDictionary[(id)kCGWindowNumber];
        if (wid == windowID.integerValue) {
          result = true;
          break;
        }
      }
    }
  }
  CFRelease(windowArray);
  return result;
}

pid_t cocoa_pid_from_wid(CGWindowID wid) {
  pid_t pid;
  const CGWindowLevel kScreensaverWindowLevel = CGWindowLevelForKey(kCGScreenSaverWindowLevelKey);
  CFArrayRef windowArray = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
  CFIndex windowCount = 0;
  if ((windowCount = CFArrayGetCount(windowArray))) {
    for (CFIndex i = 0; i < windowCount; i++) {
      NSDictionary *windowInfoDictionary =
      (__bridge NSDictionary *)((CFDictionaryRef)CFArrayGetValueAtIndex(windowArray, i));
      NSNumber *ownerPID = (NSNumber *)(windowInfoDictionary[(id)kCGWindowOwnerPID]);
      NSNumber *level = (NSNumber *)(windowInfoDictionary[(id)kCGWindowLayer]);
      if (level.integerValue < kScreensaverWindowLevel) {
        NSNumber *windowID = windowInfoDictionary[(id)kCGWindowNumber];
        if (wid == windowID.integerValue) {
          pid = ownerPID.integerValue;
          break;
        }
      }
    }
  }
  CFRelease(windowArray);
  return pid;
}

unsigned long cocoa_get_wid_or_pid(bool wid) {
  unsigned long result;
  const CGWindowLevel kScreensaverWindowLevel = CGWindowLevelForKey(kCGScreenSaverWindowLevelKey);
  CFArrayRef windowArray = CGWindowListCopyWindowInfo(kCGWindowListOptionAll, kCGNullWindowID);
  CFIndex windowCount = 0;
  if ((windowCount = CFArrayGetCount(windowArray))) {
    for (CFIndex i = 0; i < windowCount; i++) {
      NSDictionary *windowInfoDictionary =
      (__bridge NSDictionary *)((CFDictionaryRef)CFArrayGetValueAtIndex(windowArray, i));
      NSNumber *ownerPID = (NSNumber *)(windowInfoDictionary[(id)kCGWindowOwnerPID]);
      NSNumber *level = (NSNumber *)(windowInfoDictionary[(id)kCGWindowLayer]);
      if (level.integerValue == 0) {
        NSNumber *windowID = windowInfoDictionary[(id)kCGWindowNumber];
        result = wid ? windowID.integerValue : ownerPID.integerValue;
        break;
      }
    }
  }
  CFRelease(windowArray);
  return result;
}

void cocoa_wid_to_top(CGWindowID wid) {
  CFIndex appCount = [[[NSWorkspace sharedWorkspace] runningApplications] count];
  for (CFIndex i = 0; i < appCount; i++) {
    NSWorkspace *sharedWS = [NSWorkspace sharedWorkspace];
    NSArray *runningApps = [sharedWS runningApplications];
    NSRunningApplication *currentApp = [runningApps objectAtIndex:i];
    if (cocoa_pid_from_wid(wid) == [currentApp processIdentifier]) {
      NSRunningApplication *appWithPID = currentApp;
      NSUInteger options = NSApplicationActivateAllWindows;
      options |= NSApplicationActivateIgnoringOtherApps;
      [appWithPID activateWithOptions:options];
      break;
    }
  }
}

void cocoa_wid_set_pwid(CGWindowID wid, CGWindowID pwid) {
  [cocoa_window_from_wid(pwid) setChildWindowWithNumber:wid];
}

子类.mm

#import "subclass.h"
#import <Cocoa/Cocoa.h>

CGWindowID cocoa_wid = kCGNullWindowID;
CGWindowID cocoa_pwid = kCGNullWindowID;

@implementation NSWindow(subclass)

- (void)setChildWindowWithNumber:(CGWindowID)wid {
  [[NSNotificationCenter defaultCenter] addObserver:self
    selector:@selector(windowDidBecomeKey:)
    name:NSWindowDidUpdateNotification object:self];
  cocoa_pwid = [self windowNumber]; cocoa_wid = wid;
  [self orderWindow:NSWindowBelow relativeTo:wid];
}

- (void)windowDidBecomeKey:(NSNotification *)notification {
  if (cocoa_wid_exists(cocoa_wid)) {
    [self setCanHide:NO];
    [self orderWindow:NSWindowBelow relativeTo:cocoa_wid];
  } else {
    cocoa_wid = kCGNullWindowID;
    [self setCanHide:YES];
  }
}

@end

子类.h

#import <Cocoa/Cocoa.h>

bool cocoa_wid_exists(CGWindowID wid);

@interface NSWindow(subclass)

- (void)setChildWindowWithNumber:(CGWindowID)wid;
- (void)windowDidBecomeKey:(NSNotification *)notification;

@end

我加倍努力并添加了一些功能来帮助您检索适当的CGWindowID基于最前面的CGWindowID,如果你知道正确的CGWindowID事先,通过 AppleScript,或者您喜欢的任何方式,您可以使用cocoa_wid_to_top(wid),(如果用户允许),但是这对于同时拥有多个可见窗口的进程来说效果不佳,因为它会带来与给定关联的进程 ID 所拥有的所有窗口CGWindowID到顶部,所以你可能没有CGWindowID您必然希望位于窗口堆栈的绝对顶部。您可能希望将窗口置于堆栈顶部的原因是,在某些情况下,可能会打开一个窗口,您希望创建一个子窗口,但它出现在父窗口下方的屏幕上,从而强制您必须单击它才能有效地建立窗口的父/子关系。

文档如下...

NSWindow *cocoa_window_from_wid(CGWindowID wid);返回一个NSWindow *从给定的CGWindowID,假设CGWindowID属于当前应用程序,否则无效CGWindowID返回,可以用常量表示kCGNullWindowID.

CGWindowID cocoa_wid_from_window(NSWindow *window);返回一个CGWindowID从给定的NSWindow *,假设NSWindow *属于当前应用程序,否则我相信你会遇到段错误。这就是我的测试中当你知道某个值的值时会发生的情况NSWindow *并尝试在不属于它的应用程序中使用它,所以不要尝试。

bool cocoa_wid_exists(CGWindowID wid);退货true如果一个窗口基于指定的CGWindowID存在,不包括您的屏幕保护程序和桌面元素,false如果没有。

pid_t cocoa_pid_from_wid(CGWindowID wid);一个辅助函数cocoa_wid_to_top(wid)它返回进程 ID,(或pid_t),与给定的关联CGWindowID.

unsigned long cocoa_get_wid_or_pid(bool wid);返回最前面CGWindowID if wid is true,否则是最前面的进程 ID,(或pid_t),就是结果。注意返回类型unsigned long可以安全地往返于CGWindowID or pid_t如所须。

void cocoa_wid_to_top(CGWindowID wid);尝试将属于该进程 ID 的所有窗口(或pid_t),与给定的关联CGWindowID成为最顶级的应用程序。

现在最重要的功能...

void cocoa_wid_set_pwid(CGWindowID wid, CGWindowID pwid);根据指定分配父窗口CGWindowID到与正确关联的给定子窗口CGWindowID。父窗口 ID,(或pwid),必须由当前应用程序拥有,而子窗口 id,(或wid),可能属于任何应用程序,不包括屏幕保护程序和桌面元素。如果父窗口或子窗口不复存在,它们就失去父子关系以避免被回收CGWindowID来自继承关系。如果父母或孩子CGWindowID不存在,它们将被设置为kCGNullWindowID,这可靠地结束了关系。

请注意,此代码已在 Catalina 中进行了测试,并且确实按照撰写本文时所宣传的那样工作。

要使用我在 C 或 C++ 代码中提供的 cocoa 函数,您可以在标头中执行此操作:

typedef void NSWindow;
typedef unsigned long CGWindowID;

extern "C" NSWindow *cocoa_window_from_wid(CGWindowID wid);
extern "C" CGWindowID cocoa_wid_from_window(NSWindow *window);
extern "C" bool cocoa_wid_exists(CGWindowID wid);
extern "C" pid_t cocoa_pid_from_wid(CGWindowID wid);
extern "C" unsigned long cocoa_get_wid_or_pid(bool wid);
extern "C" void cocoa_wid_to_top(CGWindowID wid);
extern "C" void cocoa_wid_set_pwid(CGWindowID wid, CGWindowID pwid);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将非拥有窗口始终设置在顶部 - 就像应用程序“Afloat” 的相关文章

  • 推入 UINavigationController 时隐藏 FBFriendPickerViewController 导航栏

    介绍一个实例FBFriendPickerViewController using presentViewController animated completion 非常简单 该类似乎是针对该用例的 但是 我想推送一个实例FBFriendP
  • 如何在 macOS 上将 Git 升级到最新版本?

    我刚刚购买了一台装有 OS X Lion 的新 Mac 我在终端中检查了默认安装的 git 版本 我得到了答案 git version gt git version 1 7 5 4 我想将 git 升级到最新版本 1 7 8 3 因此我下载
  • MySQL 数据库无法在 XAMPP for Mac 上启动

    突然我在 mac 上遇到了这个问题 我无法启动我的 MySQL 数据库 我只能启动 ProFTPD 和 Apache Web Server 这是应用程序日志 Starting all servers Starting MySQL Datab
  • 如何在 MacBook Pro 上的 Docker 容器内运行 tkinter?

    我正在尝试运行一个使用以下命令的 python GUI 应用程序tkinter我的 MacBook Pro 上的 docker 容器内的模块 所以我安装了XQuartz https www xquartz org 并跟随本教程 https
  • 无法在 Windows 上使用 Gnustep 编译 Objective C

    嗨 我是初学者 学习目标c 我发现错误 hello m 1 34 Foundation Foundation h 没有这样的文件或目录 我开始知道我需要制作一个 make 文件 我可以知道如何制作 make 文件吗 无需创建 makefil
  • 我如何获取用户的电子邮件? iPhone SDK

    我需要获取 Mail app 中使用的用户的电子邮件地址 如何使用 iPhone SDK 做到这一点 谢谢你 简短的回答 你不能 如果需要 您应该提示用户输入电子邮件地址
  • 如何检查 BOOL 是否为空?

    有没有办法在将值分配给 BOOL 之前检查该值是否为 NULL Nil 例如 我在 NSDictionary 中有一个值可以是 TRUE FALSE NULL mySTUser current user following results
  • 在不同的捆绑包上测试 iPhone 应用内购买?

    我们有一组 iPhone 应用程序的 Beta 测试人员 最近 我们在应用程序中添加了应用内购买功能 在此之前 我们会使用单独的捆绑 ID 和名称向 Beta 测试人员发送临时版本 以便他们可以在手机上拥有商店版本和临时版本 然而 似乎我们
  • 如何使用MKMapView完成加载委托,可能的“完成显示”委托?

    当用户在选择注释后点击 保存 时 我尝试保存地图视图的缩略图 当用户尚未放大该注释时会出现问题 因此尚未加载关闭缩放级别 这就是用户点击保存后我正在做的事情 将布尔值 saving 设置为 true 居中并放大注释 无动画 当调用mapVi
  • CBPeripheral 名称有时为 null

    我正在开发一个应用程序来与蓝牙 LE 外围设备进行通信 我目前正在测试的外围设备是其中之一these http www ti com tool cc2540dk mini 有趣的是 有时当我发现它时 我会得到它的正确名称 SimpleBLE
  • GMSMapView 中的倒多边形

    我必须在我的 iPhone 项目中使用 Google 地图 并且我正在使用 GMSPolygon 来绘制多边形 但是如何填充地图上除多边形内部之外的所有位置 就像下图一样 谢谢 我玩过你的问题 主要思想是用多边形填充整个地球 然后为您的特定
  • 是什么导致了这个 iPhone 崩溃日志?

    我有点卡住了 需要解决这个问题 因为我的一个应用程序出现了随机崩溃 而这些崩溃并不总是能够重现 这是崩溃日志之一 Incident Identifier 59865612 9F00 44EA 9474 2BF607AD662E CrashR
  • Objective-C / C 给出枚举默认值

    我在某处读到过关于给枚举默认值的内容 如下所示 typedef enum MarketNavigationTypeNone 0 MarketNavigationTypeHeirachy 1 MarketNavigationTypeMarke
  • iOS中的performSelector有什么用

    的作用是什么执行选择器 比较 self btnClicked and self performSelector selector btnClicked void btnClicked NSLog Method Called 两者都对我来说工
  • 玻璃效果 UIView

    我想知道如何在 UIView 上添加玻璃效果 我想像这样的效果 http pttrns com pickers detail 0dc9d9f6c6a7577613b3453768eee3b3在灰色半透明视图上 您 可以在这里看到 Thank
  • 如何检测Retina高清显示屏?

    UIScreen有一个新的 nativeScaleiOS 8 中的属性 但文档没有提及它 property nonatomic readonly CGFloat nativeScale 还有一个scale属性 但文档说它是 2 用于视网膜显
  • PrepareForSegue之谜

    我在两个不同的 VC 中有一个prepareForSegue 方法 一个使用一个if声明 而另一个旨在使用switch 除了名称之外 代码几乎相同 这个效果很好 void prepareForSegue UIStoryboardSegue
  • 如何更改已上传的 Firebase 存储图像文件名?

    我需要更改已上传到 firebase 存储中的文件名 因为 在 firebase 存储中上传图像后 我将 url 保存在 firebase 数据库中的特定子 文件夹 下 但是 当我将图像移动到另一个子 文件夹 时 我需要根据新名称更改存储中
  • 将 CALayer 旋转 90 度?

    如何旋转CALayer90度 我需要旋转所有内容 包括子图层和坐标系 Obj C theLayer transform CATransform3DMakeRotation 90 0 180 0 M PI 0 0 0 0 1 0 Swift
  • XCode 4.2.1 在 Lion 10.7.2 上启动时崩溃

    这周我买了大约 10 年来的第一台 Mac 是的 这是一台二手 Mac Pro 2x2GHz 双核 Xeon 2GB RAM 它全新安装了 Mac OS X Lion 10 7 2 我只安装了 OmniOutlner Pro Textmat

随机推荐

  • 在 Google 地图 API 中获取最多(超过 20)个结果

    我在用Google maps API version 3以及使用 javascript 进行地点文本搜索 但我只得到 20 个结果 如何获得 20 多个结果 例如 100 或 200 左右 默认值为 20 但最多可以有 60 个 但是它们将
  • 序言,复制列表

    我试图掌握一些基本的序言 但在这个过程中有点挣扎 具体来说 我正在尝试遍历项目列表并将其逐项复制到新列表中 我可以让它反转 但我发现不反转会更棘手 我一直在尝试以下操作 copy L R accCp L R accCp R accCp H
  • 如何找出使用了哪个可绘制资源?

    我想知道运行来自 ldpi mdpi hdpi 或 xhdpi 的应用程序时使用了哪个可绘制资源 您应该能够按照所述获取设备的显示属性here https stackoverflow com a 3166582 1029225然后通过将结果
  • 无法使用最新的 Firebase 框架读取/写入 Nest Firebase 值

    我一直在尝试将 Nest 集成到我的 iOS 应用程序中 遵循有关用户身份验证的所有说明 然后调用 Nest API 我使用 Nest 的 iOS 示例应用程序作为参考 https github com nestlabs iOS NestD
  • Apache Camel 计时器:“周期”与“固定速率”

    period 和 fixedRate 一起的确切用法是什么 这真的有意义吗 因为如果我指定了 周期 值 那么无论如何计时器都会在该间隔后触发 所以 fixedRate 标志的确切用途是什么 我很困惑请帮助我 您可以在以下位置阅读 java
  • 如果 CSS“user-select=none”元素的文本位于元素之间,则该元素的文本将被复制

    看看这个片段 noselect webkit touch callout none iOS Safari webkit user select none Safari khtml user select none Konqueror HTM
  • 在 RDD[(String, Int)] 上 saveAsTextFile 时如何删除记录周围的括号?

    我在用着saveAsTextFile path 以便将输出保存为文本文件 以便稍后将结果导入数据库 输出看起来像这样 value1 value2 如何去掉括号 您可以尝试以下非常基本的操作 rdd map x gt x 1 x 2 save
  • 如何替换 therubyracer javascript 运行时

    我该如何更换therubyracer宝石 我真的被困住了 我们一直在使用therubyracer我们的 Rails 资产管道的 gem 然而 它使用的依赖项已经过期并且存在安全漏洞 最新版本0 12 3是从 2017 年 1 月 5 日开始
  • 在电脑上未安装python的情况下运行python脚本

    我创建了一些数据处理脚本 它们需要每天执行 但是PC的数量接近150台 我无法在所有PC上手动安装Python 所以我需要一种方法让这些在这些 Windows 系统上工作 我尝试使用 PyInstaller 创建 exe 并将其放置在服务器
  • 自动完成内的 InputLabelProps 不受尊重

    我正在尝试使标签在内部可供选择和复制Autocomplete组件通过设置InputLabelProps sx userSelect text inside renderInput 理想情况下 我希望可以单击或双击来选择标签文本 export
  • 访问 Silverlight DataTemplate 内的元素

    尽管已经有一些相关问题 但我无法找到以下问题的干净解决方案 如果我有一个被多次使用的数据模板 例如 TreeViewItem Header 模板 我如何才能仅更改某些 TreeView 项目的模板 例如 假设我的 TVI HeaderTem
  • 处理证书时发生未知错误

    我有一个自签名证书 我想在我的 websockets 服务器上使用它来处理来自 wss localhost 443 的请求 我从任何网络浏览器连接到服务器 但是 我似乎无法正确进行身份验证 每次我尝试通过 Advanced Rest Cli
  • Play Framework 2.2.1 (Java) 中的 AspectJ

    我想将 AspectJ Weaving 包含在 Play 2 2 1 项目中 我只找到一个答案解释如何将 AspectJ 添加到 Play 2 1 1 项目 https stackoverflow com a 16606135 346421
  • 如何在 UIAlertView 中对齐消息?

    我想知道如何设置警报视图的委托消息的对齐方式 任何人都有解决方案 请回复一些代码 这只是之前答案的稍微简化版本 但我喜欢保持简单 for UIView view in alert subviews if view class isSubcl
  • iPhone 5 及以下版本应用程序崩溃

    我发布了一个简单的游戏 可以在 iPhone 5s 6 6s 和 iPad 上正常运行 但当在 iPhone 5 5c 4S 或 4 上运行时 应用程序会在出现以下代码时崩溃 let delay Int arc4random uniform
  • Junit 断言双数组

    我如何断言两个数组doubles 包含相同的元素 有一些方法可以断言整数数组和其他基本类型包含相同的元素 但不适用于doubles JUnit 4 12 有 实际上它已经是 4 6 的一部分 这是 github 上可用的最旧版本 org j
  • 如何查明特定设备是否支持 SIM 硬件?

    我想根据 SIM 硬件是否存在来禁用我的应用程序中与 CALL 和 SMS 相关的功能 现在 初学者的方法是使用以下命令检查电话类型 if telephonyManager1 getPhoneType TelephonyManager PH
  • 使用带有 fields_for 的数组

    如何使用 fields for 迭代对象数组 全部相同模型 该数组包含由 current user 创建的对象 我目前有 p class fields p
  • 如何解决错误:在此服务器上找不到请求的地址 - CakePHP

    我在我的项目中使用 CakePHP 2 X 但陷入了困境 首先让你知道我使用表单实现了搜索功能POST方法 但为此我发现分页错误 过滤器将不支持下一页 所以我将表单方法更改为GET 现在工作正常 不完全是我所需要的 所有请求的数据都显示在
  • 将非拥有窗口始终设置在顶部 - 就像应用程序“Afloat”

    我设置了一个全局热键RegisterEventHotkey 当用户按下它时 它会获取当前聚焦的窗口CGWindowListCopyWindowInfo 然后我需要将它始终设置在顶部 如果当前窗口在我的进程中 我正在从中执行代码 我可以简单地