7

我正在开发一个屏幕截图 Mac 应用程序。我正在尝试重建按 Cmd-Ctrl-Shift-4 时发生的情况:十字光标和屏幕截图的选择矩形。

我在所有其他窗口之上使用自定义无边框 NSWindow 。我禁用了光标来绘制我自己的选择矩形。

我的问题是,一旦我单击并拖动以捕获屏幕截图,我的应用程序就会被激活(因为单击被我的屏蔽窗口拦截)。

有没有一种方法可以让我在自定义视图/窗口中接收点击,而无需激活我的应用程序?

我尝试使用NSPanel带有NSNonactivatingPanelMask标志的an,但在这种情况下,我的光标有问题:当另一个应用程序处于活动状态时,我无法绘制自己的,因为我无法隐藏其他应用程序的光标......

4

4 回答 4

3

实际上,对于这个涉及更多无证好东西的问题,我有一个新的、更好的答案。这是为了将来的后代:

NSWindow 上有一个未记录的方法可以完全满足您的要求:

@interface NSWindow (Private)
- (void )_setPreventsActivation:(bool)preventsActivation;
@end

[myWindow _setPreventsActivation:true];

当用户单击它时,这会阻止窗口激活它本身及其应用程序。

关于使用未记录 API 的标准警告当然适用:Apple 可能会在某个时候改变这一点(尽管许多 OS X 版本都存在这种情况,所以他们很有可能不会)并且使用它可能会让你的应用程序被 Mac 应用程序拒绝店铺。

于 2016-06-21T04:47:42.350 回答
1

值得一提的是,除了创建一个巨大的窗口之外,还有另一种方法可以使光标在全局范围内不可见。如果您可以使用它,它会涉及一些未记录的 API:

extern "C" {
    typedef int CGSConnection;
    void CGSSetConnectionProperty(int, int, const void *, const void *);
    int CGSMainConnectionID();
}

void allowHidingCursorForBackgroundOnlyApp()
{
    CFStringRef propertyString = CFStringCreateCopy(NULL, CFSTR("SetsCursorInBackground"));
    CGSSetConnectionProperty(CGSMainConnectionID(), CGSMainConnectionID(), propertyString, kCFBooleanTrue);
    CFRelease((CFTypeRef)propertyString);
}

将其与明智地使用事件点击来捕获和过滤鼠标点击相结合,您可以创建与内置屏幕截图功能相同的效果。

于 2016-06-21T01:52:08.180 回答
0

祈祷现在有更好的方法来做到这一点,但是当我不得不做类似的事情时,我最终让我的窗口/视图忽略所有鼠标输入,然后我使用了CGEventTap(参见Quarts 事件服务文档)来全局捕获鼠标事件(不从事件队列中删除它们)。我他们手动将它们映射到我的窗口,创建了一个自定义副本NSEvent并将其手动分派到我的窗口。

这里的巨大缺点(除了复杂性)是我记得需要以 root 身份运行才能安装事件水龙头。但是,我认为有一种方法可以通过通用访问获得许可。

我完全不确定将自定义NSEvent直接发送到窗口是否会产生与激活应用程序相同的副作用;特别是因为自 10.6 以来许多事情都发生了变化......我建议在追求它之前进行一个简单的测试,看看这是否可行。

于 2014-09-08T16:18:45.147 回答
0

还有一个想法,您可以覆盖子类- (BOOL)_isNonactivatingPanel中的私有方法NSWindow

@implementation MyWindow

- (BOOL)_isNonactivatingPanel
{
    return YES;
}

@end

瞧,你的行为类似于NSPanel:)

于 2021-01-06T10:18:51.597 回答