如何接受编辑和关闭包含自定义视图的弹出菜单?

时间:2014-02-14 18:56:04

标签: objective-c macos cocoa nsview nsmenu

我希望在编辑表格视图中的特定列时添加使用日期选择器的功能,并使用here中的代码段,该代码段效果很好。但是NSDatePicker不适合我的需要,因此我使用自己的自定义视图,使用IB创建并通过NSViewController子类加载来编辑日期。

但是我无法弄清楚如何以接受编辑的方式关闭弹出菜单,即在YES中返回userAcceptedEdit

BOOL userAcceptedEdit = [menu popUpMenuPositioningItem:nil
                                            atLocation:frame.origin
                                                inView:tableView];

NSDatePicker是菜单视图时,此功能正常,但不适用于我的自定义视图。

我正在自定义视图中的文本字段中捕获回车键操作,但我能弄清楚的是如何取消导致userAcceptedEdit == NO的菜单跟踪:

MyCustomViewController.mm

- (IBAction)textFieldAction:(id)sender {
    logdbg(@"Action");
    NSMenu* menu = [[self.view enclosingMenuItem] menu];
    [menu cancelTracking];
}

Apple的应用程序菜单和弹出列表编程主题Views in Menu Items部分也没有涵盖它......

编辑以下是a sample project,说明了这个问题。

有人可以提供一些指导吗?

2 个答案:

答案 0 :(得分:2)

哈!做到了。将NSTextField更改为NSTextView,将其分类,然后我们转到:

@interface LNTextView : NSTextView

@end

@implementation LNTextView

- (void)keyDown:(NSEvent *)theEvent
{
    if(theEvent.keyCode == 36)
    {
        [[self window] keyDown:theEvent];
    }
}

@end

我注意到,通常情况下,当NSDatePicker上按下回车键时,keyDown:最终会进入菜单窗口然后被接受。所以这就是我在这里所做的。 NSTextField在内部使用文字视图,因此无法听到keyDown:条消息,因此需要切换为完整版NSTextView

您仍然可以使用文字字段,并在操作方法中使用NSEvent创建新的+ (NSEvent *)keyEventWithType:(NSEventType)type location:(NSPoint)location modifierFlags:(NSUInteger)flags timestamp:(NSTimeInterval)time windowNumber:(NSInteger)windowNum context:(NSGraphicsContext *)context characters:(NSString *)characters charactersIgnoringModifiers:(NSString *)unmodCharacters isARepeat:(BOOL)repeatKey keyCode:(unsigned short)code,将其传递到字段的窗口,而不是在菜单上调用cancelTracking。< / p>

答案 1 :(得分:2)

您还应该能够将textFields的委托设置为NSViewController,在ViewController中实现NSTextFieldDelegate并执行类似的操作

- (void)controlTextDidEndEditing:(NSNotification *)aNotification{
    // NSTextField * textField = [aNotification object];
    NSUInteger whyEnd = [[[aNotification userInfo] objectForKey:@"NSTextMovement"] unsignedIntValue];
    if(whyEnd == NSReturnTextMovement){
        // Create new event here using the below routine

        /*
        [[self window] keyDown: [NSEvent keyEventWithType:(NSEventType)type 
                                                 location:(NSPoint)location 
                                            modifierFlags:(NSUInteger)flags 
                                                timestamp:(NSTimeInterval)time 
                                             windowNumber:(NSInteger)windowNum 
                                                  context:(NSGraphicsContext *)context 
                                               characters:(NSString *)characters 
                              charactersIgnoringModifiers:(NSString *)unmodCharacters 
                                                isARepeat:(BOOL)repeatKey
                                                  keyCode:(unsigned short)code]
         ];
         */ 
    }
 }

在这里,您实际上是通过创建一个新事件传递给父视图来将通知转换为EVENT

还应注意,这将成为所有文本字段的中央“调度”返回捕获器。

以下是使用NSEvent创建方法的一个很棒的链接: http://advinprog.blogspot.com/2008/06/so-you-want-to-post-keyboard-event-in.html

在这篇文章中请注意如何模拟key_down和key_up !!!