【问题标题】:Cocoa window dragging可可窗口拖动
【发布时间】:2012-06-09 18:17:39
【问题描述】:

我正在使用 addGlobalMonitorForEventsMatchingMask 来监听 Co​​coa 中的事件:

[NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDraggedMask 
                                       handler:^(NSEvent *event) {
    NSLog(@"Dragged...");
}];

虽然我想知道我是否正在拖动/移动一个窗口(以及哪个窗口,我可以找到焦点窗口,但在按住命令并拖动一个窗口时它不会获得焦点据我所知.)

那么,我可以检测我是否在拖动窗口吗?

更新:

我现在有一个类:“SATest : NSObject <NSWindowDelegate>”,我在其中实现了 windowDidMove 方法(稍后可能还有 windowWillMove。)不过,现在下一步是将其附加到一个窗口,对吗?所以我现在的问题是:如何将代理附加到所有应用程序的所有窗口?

更新 2:

我现在可以在屏幕上找到所有打开窗口的列表:

AXUIElementRef _systemWideElement;
_systemWideElement = AXUIElementCreateSystemWide();

CFArrayRef _windows;
AXUIElementCopyAttributeValues(_systemWideElement, kAXWindowsAttribute, 0, 100, &_windows);

现在我必须遍历窗口,并且每个得到它的 NSWindow 以便我可以将我的委托添加到它:[window setDelegate:self];

更新3:要清楚,这个问题是关于检测所有应用程序的所有窗口的拖动。不仅是我自己的应用程序的窗口。

另外,我对这个事件和窗口管理的东西很陌生,所以不需要让你的回答简短我很高兴阅读了很多:P

谢谢! -P

【问题讨论】:

    标签: objective-c macos cocoa


    【解决方案1】:

    要确定窗口是否被拖动,您需要一个对象作为窗口的委托,通过响应 NSWindowDelegate 协议的以下消息:

    1. windowWillMove - 这告诉代理窗口即将移动。
    2. windowDidMove - 这告诉代理窗口已经移动。

    您可以通过发送 object 到发送到这些方法的通知参数来检索有问题的 NSWindow 对象:

    例如

    NSWindow draggedWindow = [notification object];
    

    更多信息可以在here找到。

    更新:

    为了响应您关于获取所有窗口的此信息的请求,NSApplication 类提供了一个方法,该方法返回应用程序拥有的所有窗口的数组。获取此信息的典型方法是使用 NSApplicationDelegate 方法之一来获取对您的应用程序对象的引用。

    例如,在您的应用委托(伪代码)中:

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {
        NSApplication * app = [aNotification object];
        // you now have a reference to your application.
        // and can iterate over the collection of windows and call
        // [window setDelegate:self]; for each window.
    }
    

    请注意,在添加和删除窗口时,您需要添加/删除代理。这样做的最佳方法是 – applicationDidUpdate:

    这应该足以让您开始解决问题。

    【讨论】:

    • 我在这里有点困惑,我得到了我的类:“@interface SATest : NSObject ”,我实现了 windowDidMove 方法。虽然我如何将它附加到窗口? (我从哪里得到这个窗口:P 我试图让所有应用程序的所有窗口都打开这个移动的东西。)
    • 您需要在您的 nib 文件中创建一个实例,然后按住 Ctrl 键并从该对象拖动到窗口以将其设置为该窗口的代理。或者,您可以在 AppDelegate 上实现 以保存在 nib 文件中创建新对象。
    • 我还没有尝试过,但这不只是我自己的应用程序的窗口吗?我也在尝试从其他应用程序中获取它。我想知道当前运行的任何应用程序的任何窗口何时移动。虽然要尝试一些东西,但谢谢!
    • 是的,这仅适用于您的应用程序。我进行了一些搜索,每当您遇到问题时,都会提到可访问性 API。我对可访问性 API 一无所知,以前从未使用过它,因此无法进一步帮助您。
    【解决方案2】:

    正如 Benjamin 所建议的,答案在于可访问性 API。甚至在我问这个问题之前,我就在这周围看了一会儿,但从来没有让它做我想做的事。我现在找到了一个很好的解决方案。

    在高层次上,我执行以下操作:

    1. 聆听鼠标按下事件并记住您单击的窗口及其位置。
    2. 监听鼠标上移事件并检查位置是否发生变化,如果发生变化,您就知道您移动了一个窗口

    如果您还想知道是否调整了大小,您可以对大小执行类似的操作。可能有更好的解决方案,但经过几天的尝试,这是我让它按我想要的方式工作的唯一方法。

    希望这对正在寻找类似内容的人有所帮助。

    -巴勃罗

    【讨论】:

      猜你喜欢
      • 2011-10-31
      • 2016-10-09
      • 2014-07-07
      • 1970-01-01
      • 1970-01-01
      • 2011-04-29
      • 2016-02-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多