Macos 实现自定义Cocoa事件跟踪循环

Macos 实现自定义Cocoa事件跟踪循环,macos,cocoa,Macos,Cocoa,我正在开发一个定制的跨平台UI库,它需要一个同步的“ShowPopup”方法来显示一个弹出窗口,运行一个事件循环直到它完成,并在单击弹出窗口外或按escape时自动取消。键盘、鼠标和滚轮事件需要发送到弹出窗口,但其他事件(绘制、绘制、计时器等)需要在循环运行时发送到其常规目标 编辑:为了澄清,我所说的弹出窗口是指这种菜单式的弹出窗口,而不是警报/对话框等 在Windows上,我通过调用GetMessage/DispatchMessage并根据需要过滤和分派消息来实现这一点。很好 然而,我对Co

我正在开发一个定制的跨平台UI库,它需要一个同步的“ShowPopup”方法来显示一个弹出窗口,运行一个事件循环直到它完成,并在单击弹出窗口外或按escape时自动取消。键盘、鼠标和滚轮事件需要发送到弹出窗口,但其他事件(绘制、绘制、计时器等)需要在循环运行时发送到其常规目标

编辑:为了澄清,我所说的弹出窗口是指这种菜单式的弹出窗口,而不是警报/对话框等

在Windows上,我通过调用GetMessage/DispatchMessage并根据需要过滤和分派消息来实现这一点。很好

然而,我对Cocoa/OSX的经验要少得多,并且发现整个事件循环/调度范式有点混乱。我看过下面的文章,它解释了如何实现一个鼠标跟踪循环,这与我所需要的非常相似:

但是。。。关于这件事我有些担心

  • 链接文章指出:“在事件跟踪循环期间,应用程序的主线程无法处理任何其他请求,计时器可能不会启动”。可能不会?为什么不,当不,如何确保他们这样做

  • 状态为“与指定事件类型之一不匹配的事件保留在队列中”的文档。这似乎有点奇怪。这是否意味着如果一个事件循环只要求鼠标事件,那么一旦循环完成,任何按下的键都将被处理?那太奇怪了

  • 是否可以在不移除消息的情况下查看事件队列中的消息。例如:Windows版的my library使用此功能在单击外部时关闭弹出窗口,但将单击事件保留在队列中,以便在弹出窗口外部单击另一个按钮时不需要再次单击

  • 我读了很多关于运行循环模式的书,但还是不太明白。如果能很好地解释一下这些是干什么用的,那就太好了

  • 是否有其他为弹出窗口实现事件循环的好例子。对于内置的NSApplication运行循环,更好的方法是使用伪代码

  • 另一种说法是。。。Windows的
    peek消息(…,PM\u REMOVE)
    peek消息(…,PM\u NOREMOVE)
    DispatchMessage()
    的等价物是什么

    非常感谢您的帮助。

    当您使用这个术语时,“弹出窗口”到底是什么?这个术语在不同的GUI API中有不同的含义。它只是一个模态对话框窗口吗


    问题编辑更新:

    看起来您只是想实现一个自定义菜单。苹果公司提供了一个示例项目,说明了这项技术。这是WWDC 2010年会议视频之一的伴奏


    根据具体需要,您可能希望使用
    NSAlert
    。或者,您可以使用自定义窗口,只需使用
    NSApplication
    -runModalForWindow:
    方法以模式运行它

    为了满足用户在窗口外单击时结束模式会话的要求,可以使用本地事件监视器。《Cocoa事件处理指南》(modern,current)中甚至有这样一个功能示例:

    综上所述,以下是(希望不再相关)您具体问题的答案:

  • 链接文章指出:“应用程序的主线程在事件跟踪循环期间无法处理任何其他请求,并且 计时器可能不会开火”。可能不会?为什么不,当不,怎么做 真的吗
  • 因为定时器被安排在特定的运行循环模式或一组模式中。见下文问题4的答案。在运行事件跟踪循环时,通常会使用事件跟踪模式,因此未在该模式下调度的计时器将不会运行

    您可以为事件跟踪循环使用默认模式,但这确实不是一个好主意。它可能会导致意外的重新进入

    假设弹出窗口类似于模式窗口,您可能应该使用
    nsmodalpanelrunlopmode

  • 文件 状态“与指定事件类型之一不匹配的事件是 在队列中留下了。”。这似乎有点奇怪。这是否意味着如果 一个事件循环只要求鼠标事件,然后任何按下的键都将被激活 循环完成后处理?那太奇怪了
  • 是的,这就是它的意思。由你来阻止这种奇怪的结果。如果你读一读这十年的Cocoa事件处理指南,你会发现有-P

  • 是否可以在不移除消息的情况下查看事件队列中的消息。我的库的Windows版本使用此关闭 在外部单击时弹出窗口,但将单击事件保留在 排队,以便在弹出窗口外单击另一个按钮不会 需要再次单击
  • 对。您是否注意到
    nexteventmachingmask:untilDate:inMode:dequeue:
    的“dequeue:”参数?如果您为此传递了
    NO
    ,则事件将留在队列中

  • 我读了很多关于运行循环模式的书,但还是不太明白。如果能很好地解释一下这些是干什么用的,那就太好了
  • 如果你不知道自己对什么感到困惑,不知道对方是如何让你失望的,你很难知道该告诉你什么

    您是否熟悉使用循环
    select()
    poll()
    epoll()
    kevent()
    处理多个异步通信通道?有点像,但自动化程度更高。您不仅构建了一个数据结构,其中列出了要监视的输入源以及您感兴趣的输入源上的特定事件,而且每个输入源都有一个与之关联的回调。运行run循环就像cal