单击NSWindow / NSView时阻止激活应用程序

时间:2014-09-08 15:46:41

标签: macos cocoa screenshot nswindow nspanel

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

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

我的问题是,只要我点击&拖动以捕获屏幕截图,我的应用程序被激活(因为点击被我的屏蔽窗口截获)。

有没有办法在我的自定义视图/窗口中接收点击而不让我的应用程序被激活?

我尝试使用带有NSPanel标记的NSNonactivatingPanelMask,但在这种情况下,我遇到了光标问题:当另一个应用处于活动状态时,我无法自行绘制,因为我可以不要隐藏其他应用的光标......

4 个答案:

答案 0 :(得分:2)

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

NSWindow上有一个没有记录的方法,可以完全按照您的要求进行操作:

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

[myWindow _setPreventsActivation:true];

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

关于使用未记录的API的标准警告当然适用:Apple可能会在某些时候改变它(虽然它已经存在许多OS X版本,所以他们很可能不会这样做)并且使用它可能会使您的应用程序被拒绝Mac应用程序商店。

答案 1 :(得分:0)

祈祷现在有更好的方法可以做到这一点,但是当我不得不做类似的事情时,我最终让我的窗口/视图忽略了所有鼠标输入,然后我使用了{{ 1}}(参见Quarts Event Services documentation)全局捕获鼠标事件(不从事件队列中删除它们)。我把它们手动映射到我的窗口,创建了一个自定义副本CGEventTap并手动将它发送到我的窗口。

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

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

答案 2 :(得分:0)

对于它的价值,除了创建一个巨大的窗口之外,还有另一种方法可以使光标全局不可见。如果你可以使用它,它涉及一些未记录的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);
}

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

答案 3 :(得分:0)

还有一个想法,你可以在 - (BOOL)_isNonactivatingPanel 子类中重写 NSWindow 私有方法:

@implementation MyWindow

- (BOOL)_isNonactivatingPanel
{
    return YES;
}

@end

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