【问题标题】:TrackPopupMenu equivalent in OS XOS X 中的 TrackPopupMenu 等效项
【发布时间】:2020-01-19 23:58:05
【问题描述】:

Windows 有这个漂亮的小 API 可以在桌面上创建和显示弹出菜单,即使是从后台隐藏的应用程序中。 Mac 有类似的吗?

我有一个由启动器启动的后台进程(在用户上下文中),并且希望在收到来自网络的命令时显示一个弹出菜单,其中包含一些供用户选择的选项。可能吗?

后台进程本身是一个普通的 C++ 命令行程序。

【问题讨论】:

    标签: c++ objective-c macos cocoa


    【解决方案1】:

    您可以尝试使用popUpMenuPositioningItem:atLocation:inView:

    文档说:

    如果 view 为 nil,则在屏幕坐标系中解释位置。这允许您弹出一个与任何窗口断开连接的菜单。

    所以,例如:

    [myMenu popUpMenuPositioningItem:nil atLocation:[NSEvent mouseLocation] inView:nil];
    

    【讨论】:

    • 谢谢,您的建议让我走上了正确的道路,我设法编写了一个示例程序来创建一个菜单并将其显示在桌面上。但是,我必须创建一个视图(需要一个主机窗口)并将其作为 inView: 参数传递给陷阱项目选择(视图的 OnMenuSelection 方法)。我现在的挑战是让整个代码从工作线程中工作:)
    • 显然,如果我到目前为止的研究是正确的,那么从后台线程让它工作可能是不可能的。似乎 Cocoa UI 的东西要从应用程序的主线程处理。所以我必须想办法从主线程处理它(来自工作线程的某种形式的信号)。
    • 在 Cocoa 上执行此操作的规范方法是使用 dispatch_a/sync,传递主队列 (dispatch_get_main_queue())
    • 谢谢你把小零食/戏弄扔给狗! :-)
    • 效果很好!似乎 dispatch*() API 将代码块编组到指定的线程并在那里执行。这很简单,但仍然必须强调——程序员有责任管理编组代码块中引用对象的生命周期,并且要避免局部变量(来自代码块之外)。无论如何,漂亮的东西!
    【解决方案2】:

    作为记录,这是我编写的在桌面上显示菜单的代码(我不是 Mac 程序员,因此可能会出现错误,或者我的实现不一定是最佳的):

    // Dummy View class used to receive Menu Events
    @interface DummyView : NSView
    {
        NSMenuItem* nsMenuItem;
    }
    - (void) OnMenuSelection:(id)sender;
    - (NSMenuItem*)MenuItem;
    @end
    
    @implementation DummyView
    - (NSMenuItem*)MenuItem
    {
        return nsMenuItem;
    }
    
    - (void)OnMenuSelection:(id)sender
    {
        nsMenuItem = sender;
    }
    @end
    
    static void HandleRButtonDown()
    {
    @autoreleasepool {
        NSRect    graphicsRect;  // contains an origin, width, height
        graphicsRect = NSMakeRect(200, 200, 50, 100);
    
    
        [NSApplication sharedApplication];
            // Style flags:
        NSUInteger windowStyle = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskResizable;
    
        // Window bounds (x, y, width, height).
        NSRect windowRect = NSMakeRect(0, 0, 0, 0);
        NSWindow * window = [[NSWindow alloc] initWithContentRect:windowRect
                                              styleMask:windowStyle
                                              backing:NSBackingStoreBuffered
                                              defer:NO];
    
        // Window controller:
        NSWindowController * windowController = [[NSWindowController alloc] initWithWindow:window];
    
        DummyView *nsView = [[DummyView alloc] initWithFrame:graphicsRect];
        [window setContentView:nsView];
    
        // Create Menu and Dummy View
        NSMenu *nsMenu = [[NSMenu alloc] initWithTitle:@"Contextual Menu"];
        [nsMenu setAutoenablesItems:NO];
    
        NSMenuItem* item1 = [nsMenu addItemWithTitle:@"Menu Item #1" action:@selector(OnMenuSelection:) keyEquivalent:@""];
    
        [item1 setTag:100];
        [item1 setTarget:nsView];
        [item1 setEnabled:YES];
    
        NSMenuItem *item2 = [nsMenu addItemWithTitle:@"Menu Item #2" action:@selector(OnMenuSelection:) keyEquivalent:@""];
    
        [item2 setTag:200];
        [item2 setTarget:nsView];
        [item2 setEnabled:YES];
    
        [nsMenu popUpMenuPositioningItem:item1 atLocation:[NSEvent mouseLocation] inView:nsView];
    
        printf("Selected item: %d\n", (int)[[nsView MenuItem] tag]);
    }
    
    }
    

    从 main 调用 HandleRButtonDown(),您应该会在屏幕上看到一个弹出菜单。

    希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2010-11-29
      • 2012-06-06
      • 2010-09-05
      • 2011-03-28
      • 1970-01-01
      • 2015-11-20
      • 2010-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多