Изменить курсор для полноэкранного NSWindow - PullRequest
3 голосов
/ 16 ноября 2011

Я пытаюсь создать оверлейное окно, которое позволит рисовать на уровне ShieldingWindowLevel, однако, когда окно появляется, курсор остается указателем по умолчанию. Я хотел бы изменить это на перекрестие. Наличие контроллера NSCursors перед тем, как я сбит с толку, почему resetCursorRects никогда не вызывается.

Я вручную создаю окно следующим образом (в моем классе AppController):

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Create the window
    NSRect frame = [[NSScreen mainScreen] frame];

    // Provide a small area on the right to move the cursor in-and-out of the window.
    frame.size.width = frame.size.width - 20; 
    self.window  = [[NSWindow alloc] initWithContentRect:frame
                                               styleMask:NSBorderlessWindowMask
                                                 backing:NSBackingStoreBuffered
                                                   defer:NO];
    [self.window setAcceptsMouseMovedEvents:YES];
    [self.window setOpaque:NO];
    [self.window setLevel:CGShieldingWindowLevel()];
    [self.window setBackgroundColor:[NSColor colorWithDeviceRed:0.0 green:0.0 blue:1.0 alpha:0.2]];

    // Create the subview
    ScreenOverlayView *subview = [[ScreenOverlayView alloc] initWithFrame:NSZeroRect];
    [[self.window contentView] addSubview:subview];

    // Add subview and show window
    [self.window setContentView:subview];
    [self.window makeFirstResponder:subview];
    [self.window orderFrontRegardless];
}

Со следующим подклассом NSView:

@implementation ScreenOverlayView
- (void) resetCursorRects {
    [super resetCursorRects];
    [self addCursorRect: [self bounds]
                 cursor: [NSCursor crosshairCursor]];
} 
// ...
@end

Я создал пример проекта для демонстрации этого случая и разместил его на github , наиболее интересные файлы: ScreenOverlayView.m и AppDelegate.m .

Я должен отметить, что я также потратил много времени, пытаясь заставить это работать с NSTrackingArea, как вы можете видеть в примере проекта. Область слежения работает, если мышь входит в вид после того, как она появилась, но не в том случае, если она находится внутри, чтобы начать с нее. Использование MouseEnter и MouseLeave было бы хорошо, если бы у меня был какой-то способ установить начальный курсор, но он будет изменяться только на долю секунды, прежде чем вернуться обратно.

Как я могу получить resetCursorRects для вызова -ИЛИ- Как я могу установить курсор, когда я перемещаю его в суперпредставление?

1 Ответ

3 голосов
/ 16 ноября 2011

Ключ в том, что вам действительно нужно создать собственный подкласс NSWindow, чтобы противодействовать поведению по умолчанию, которое имеют окна без полей (NSBorderlessWindowMask).

Обновленная версия вашего примера проекта на http://www.markdouma.com/developer/full-screen-overlay.zip.

В нем я создал собственный класс MDScreenOverlayWindow, который переопределяет метод canBecomeKeyWindow NSWindow, как показано ниже:

// Windows created with NSBorderlessWindowMask normally can't be key,
  but we want ours to be
- (BOOL)canBecomeKeyWindow {
    return YES;
}

Это позволит вашему взгляду стать ключевым и, в основном, всем остальным для правильной работы.

Другая вещь, которая может быть заметна, - это метод drawRect:. (Похоже, вы пришли из iOS). Возможно, вы захотите взглянуть на NSBezierPath, так как это может упростить часть вашего кода для рисования. Например, я полагаю, что код рисования, который вы имели, может быть объединен в следующее:

- (void)drawRect:(NSRect)rect {
    // the color should probably be "pre-multiplied" by the alpha
    // premultiplied version:
    [[NSColor colorWithCalibratedRed:0.8 green:0.0 blue:0.0 alpha:0.8] set];
    [NSBezierPath setDefaultLineWidth:2.0];
    [NSBezierPath strokeLineFromPoint:currentLocation toPoint:downLocation];
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...