keyDown 未被调用

问题描述 投票:0回答:4

我有一个名为 SurfaceView 的自定义 NSView。它是 NSWindow 的 contentView,处理鼠标单击和绘图等基本事件。但无论我做什么,它都不会处理 keyDown 函数。我已经覆盖了 AcceptFirstResponder 但没有任何反应。

如果重要的话,我使用自定义 NSEvent 循环运行应用程序,如下所示:

NSDictionary* info = [[NSBundle mainBundle] infoDictionary];
NSString* mainNibName = [info objectForKey:@"NSMainNibFile"];

NSApplication* app = [NSApplication sharedApplication];
NSNib* mainNib = [[NSNib alloc] initWithNibNamed:mainNibName bundle:[NSBundle mainBundle]];
[mainNib instantiateNibWithOwner:app topLevelObjects:nil];

[app finishLaunching];

while(true)
{   
    NSEvent* event = [app nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate date] inMode:NSDefaultRunLoopMode dequeue:YES];
    [app sendEvent:event];

    // Some code is execute here every frame to do some tasks...

    usleep(5000);
}

这是 SurfaceView 代码:

@interface SurfaceView : NSView
{
    Panel* panel;
}

@property (nonatomic) Panel* panel;

- (void)drawRect:(NSRect)dirtyRect;
- (BOOL)isFlipped;
- (void)mouseDown:(NSEvent *)theEvent;
- (void)mouseDragged:(NSEvent *)theEvent;
- (void)mouseUp:(NSEvent *)theEvent;
- (void)keyDown:(NSEvent *)theEvent;
- (BOOL)acceptsFirstResponder;
- (BOOL)becomeFirstResponder;

@end

--

@implementation SurfaceView

@synthesize panel;

- (BOOL)acceptsFirstResponder
{
    return YES;
};

- (void)keyDown:(NSEvent *)theEvent
{
    // this function is never called
};

...

@end

这是我创建视图的方法:

NSWindow* window = [[NSWindow alloc] initWithContentRect:NSMakeRect(left, top, wide, tall) styleMask:NSBorderlessWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask backing:NSBackingStoreBuffered defer:NO];

...

[window makeKeyAndOrderFront:nil];

SurfaceView* mainView = [SurfaceView alloc];
[mainView initWithFrame:NSMakeRect(0, 0, wide, tall)];
mainView.panel = panel;
[window setContentView:mainView];
[window setInitialFirstResponder:mainView];
[window setNextResponder:mainView];
[window makeFirstResponder:mainView];
objective-c cocoa keyboard nswindow keydown
4个回答
29
投票

我发现是什么阻止了

keyDown
事件被调用。这是
NSBorderlessWindowMask
掩码,它可以防止窗口成为关键窗口和主窗口。所以我创建了
NSWindow
的子类,称为
BorderlessWindow
:

@interface BorderlessWindow : NSWindow
{
}

@end

@implementation BorderlessWindow

- (BOOL)canBecomeKeyWindow
{
    return YES;
}

- (BOOL)canBecomeMainWindow
{
    return YES;
}

@end

2
投票

除了回答之外:勾选您的 IB 复选框中的

NSWindow

应检查

Title Bar
。它类似于
NSBorderlessWindowMask

enter image description here


0
投票

在我的例子中,我必须重写

NSView
NSWindow 上的 keyDown 方法(创建了两者的自定义)。在 keyDown 覆盖中的
NSWindow
中,我必须调用

- (void) keyDown:(NSEvent *) event {

    if (self.firstResponder != self) {
    
        [self.firstResponder keyDown:event];
    }
}

让事件到达视图。当然,我还必须首先在

NSWindow
上调用 makeFirstResponder 并将
contentView
传递给它:

[window makeFirstResponder: [window contentView] ];

0
投票

接受的答案节省了我大量的时间

我使用 Swift 5 + Xcode 15 进行了测试,以下是如何在 Swift 中编写它

class BorderlessWindow: NSWindow {
  override var canBecomeKey: Bool {
    return true
  }

  override var canBecomeMain: Bool {
    return true
  }
}

另外,我发现

canBecomeMain
没有必要。
canBecomeKey
一个人就足以解决问题了。

© www.soinside.com 2019 - 2024. All rights reserved.