«

Can drag webview to move window in cococa?

1. 问题

如果cococa程序,在一个没有titlebar的window里只有一个webview,是否能够拖曳这个webview来拖动整个window呢?当然,直接拖是不行的,webview会先接受这个拖曳drag事件。

对于window中除webview以外的其他控件,其实可以直接重载NSWindow的mouseDownmouseDragged方法来实现要的效果,但是webview不行,它需要另外重载NSWindow的sendEvent来实现mouse事件的额外操作。

另外,需要注意的是没有titlebar的window,相当于[self.window setStyleMask:(NSBorderlessWindowMask)].对于使用NSBorderlessWindowMask这个'Window Style Masks'时,需要额外实现canBecomeKeyWindow or canBecomeMainWindow返回YES,从而让这 个window成为当前主窗口。Apple官方文档对此的说明如下:

The window displays none of the usual peripheral elements. Useful only for display or caching purposes. A window that uses NSBorderlessWindowMask can’t become key or main, unless you implement canBecomeKeyWindow or canBecomeMainWindow to return YES. Note that you can set a window’s or panel’s style mask to NSBorderlessWindowMask in Interface Builder by deselecting Title Bar in the Appearance section of the Attributes inspector.

2. 代码

将现有window设置成下面这个BorderlessWindow即可。

.h文件:

#import <Cocoa/Cocoa.h>

@interface BorderlessWindow : NSWindow

@end

.m文件

#import "BorderlessWindow.h"

@interface BorderlessWindow()

@property (assign) NSPoint initialLocation;

@end

@implementation BorderlessWindow

- (BOOL)canBecomeKeyWindow
{
    return YES;
}

- (BOOL)canBecomeMainWindow
{
    return YES;
}

- (void)sendEvent:(NSEvent *)theEvent
{
    if ([theEvent type] == NSLeftMouseDown)
    {
        [self mouseDown:theEvent];
    }
    else if ([theEvent type] == NSLeftMouseDragged)
    {
        [self mouseDragged:theEvent];
    }

    [super sendEvent:theEvent];
}

- (void)mouseDown:(NSEvent *)theEvent
{
    self.initialLocation = [theEvent locationInWindow];
}

- (void)mouseDragged:(NSEvent *)theEvent
{
    NSPoint currentLocation;
    NSPoint newOrigin;

    NSRect  screenFrame = [[NSScreen mainScreen] frame];
    NSRect  windowFrame = [self frame];

    currentLocation = [NSEvent mouseLocation];
    newOrigin.x = currentLocation.x - self.initialLocation.x;
    newOrigin.y = currentLocation.y - self.initialLocation.y;

    // Don't let window get dragged up under the menu bar
    if( (newOrigin.y+windowFrame.size.height) > (screenFrame.origin.y+screenFrame.size.height) ){
        newOrigin.y=screenFrame.origin.y + (screenFrame.size.height-windowFrame.size.height);
    }

    //go ahead and move the window to the new location
    [self setFrameOrigin:newOrigin];
}
3. 参考
分享