移动无边框 NSWindow 完全被 Web View 覆盖

发布于 2024-12-02 23:54:01 字数 153 浏览 0 评论 0原文

在我的 COCOA 应用程序中,我实现了一个自定义无边框窗口。 Window 的内容区域完全被 WebView 覆盖。我希望当用户单击并将鼠标拖动到内容区域中的任意位置时,此无边框窗口会移动。我尝试覆盖 isMovableByWindowBackground 但没有用。我该如何解决这个问题?

In my COCOA application I have implemented a custom borderless window. The content area of the Window is fully covered by a WebView. I want this borderless window to move when user clicks and drag mouse anywhere in the content area. I tried by overriding isMovableByWindowBackground but no use. How can I fix this problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

云归处 2024-12-09 23:54:01

在 WebView 上调用 -setMovableByWindowBackround:YES 并使窗口具有纹理可能会起作用。

Calling -setMovableByWindowBackround:YES on the WebView and making the window textured might work.

远山浅 2024-12-09 23:54:01

我就是这样做的。

#import "BorderlessWindow.h"


@implementation BorderlessWindow

@synthesize initialLocation;

- (id)initWithContentRect:(NSRect)contentRect
            styleMask:(NSUInteger)windowStyle
              backing:(NSBackingStoreType)bufferingType
                defer:(BOOL)deferCreation
{
if((self = [super initWithContentRect:contentRect 
                                  styleMask:NSBorderlessWindowMask 
                              backing:NSBackingStoreBuffered 
                                defer:NO]))
{
    return self;
}

return nil;
}

- (BOOL) canBecomeKeyWindow
{
return YES;
}

- (BOOL) acceptsFirstResponder
{
return YES;
}

- (NSTimeInterval)animationResizeTime:(NSRect)newWindowFrame
{
return 0.1;
}

- (void)sendEvent:(NSEvent *)theEvent
{
if([theEvent type] == NSKeyDown)
{
    if([theEvent keyCode] == 36)
        return;
}

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 
{
NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
NSRect windowFrame = [self frame];
NSPoint newOrigin = windowFrame.origin;

NSPoint currentLocation = [theEvent locationInWindow];
if(initialLocation.y > windowFrame.size.height - 40)
{
    newOrigin.x += (currentLocation.x - initialLocation.x);
    newOrigin.y += (currentLocation.y - initialLocation.y);

    if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height))
    {
        newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
    }

    [self setFrameOrigin:newOrigin];
}
}


@end

和.h文件:

#import <Cocoa/Cocoa.h>
@interface BorderlessWindow : NSWindow {
NSPoint initialLocation;
}

- (id)initWithContentRect:(NSRect)contentRect
            styleMask:(NSUInteger)windowStyle
              backing:(NSBackingStoreType)bufferingType
                defer:(BOOL)deferCreation;

 @property (assign) NSPoint initialLocation;

 @end

This is how I did it.

#import "BorderlessWindow.h"


@implementation BorderlessWindow

@synthesize initialLocation;

- (id)initWithContentRect:(NSRect)contentRect
            styleMask:(NSUInteger)windowStyle
              backing:(NSBackingStoreType)bufferingType
                defer:(BOOL)deferCreation
{
if((self = [super initWithContentRect:contentRect 
                                  styleMask:NSBorderlessWindowMask 
                              backing:NSBackingStoreBuffered 
                                defer:NO]))
{
    return self;
}

return nil;
}

- (BOOL) canBecomeKeyWindow
{
return YES;
}

- (BOOL) acceptsFirstResponder
{
return YES;
}

- (NSTimeInterval)animationResizeTime:(NSRect)newWindowFrame
{
return 0.1;
}

- (void)sendEvent:(NSEvent *)theEvent
{
if([theEvent type] == NSKeyDown)
{
    if([theEvent keyCode] == 36)
        return;
}

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 
{
NSRect screenVisibleFrame = [[NSScreen mainScreen] visibleFrame];
NSRect windowFrame = [self frame];
NSPoint newOrigin = windowFrame.origin;

NSPoint currentLocation = [theEvent locationInWindow];
if(initialLocation.y > windowFrame.size.height - 40)
{
    newOrigin.x += (currentLocation.x - initialLocation.x);
    newOrigin.y += (currentLocation.y - initialLocation.y);

    if ((newOrigin.y + windowFrame.size.height) > (screenVisibleFrame.origin.y + screenVisibleFrame.size.height))
    {
        newOrigin.y = screenVisibleFrame.origin.y + (screenVisibleFrame.size.height - windowFrame.size.height);
    }

    [self setFrameOrigin:newOrigin];
}
}


@end

And .h file:

#import <Cocoa/Cocoa.h>
@interface BorderlessWindow : NSWindow {
NSPoint initialLocation;
}

- (id)initWithContentRect:(NSRect)contentRect
            styleMask:(NSUInteger)windowStyle
              backing:(NSBackingStoreType)bufferingType
                defer:(BOOL)deferCreation;

 @property (assign) NSPoint initialLocation;

 @end
若无相欠,怎会相见 2024-12-09 23:54:01

由于这是 Google 上的热门搜索...所提供的方法对我来说不起作用,因为 WKWebView 在鼠标事件到达窗口之前拦截了它们。我必须创建 WKWebView 的子类并在那里完成工作(h/t 到 Apple 的照片编辑器/WindowDraggableButton.swift 示例)。

我使用 Xamarin,但代码非常简单......以下是重要的部分:

// How far from the top of the window you are allowed to grab the window
// to begin the drag...the title bar height, basically
public Int32 DraggableAreaHeight { get; set; } = 28;

public override void MouseDown(NSEvent theEvent)
{
    base.MouseDown(theEvent);

    var clickLocation = theEvent.LocationInWindow;
    var windowHeight = Window.Frame.Height;

    if (clickLocation.Y > (windowHeight - DraggableAreaHeight))
        _dragShouldRepositionWindow = true;
}

public override void MouseUp(NSEvent theEvent)
{
    base.MouseUp(theEvent);
    _dragShouldRepositionWindow = false;
}

public override void MouseDragged(NSEvent theEvent)
{
    base.MouseDragged(theEvent);
    if (_dragShouldRepositionWindow)
    {
        this.Window.PerformWindowDrag(theEvent);
    }
}

Since this is the top hit on Google...the provided approach didn't work for me as WKWebView intercepts the mouse events before they reach the window. I had to instead create a subclass of WKWebView and do the work there (h/t to Apple's Photo Editor/WindowDraggableButton.swift example).

I use Xamarin, but the code is pretty simple...here are the important bits:

// How far from the top of the window you are allowed to grab the window
// to begin the drag...the title bar height, basically
public Int32 DraggableAreaHeight { get; set; } = 28;

public override void MouseDown(NSEvent theEvent)
{
    base.MouseDown(theEvent);

    var clickLocation = theEvent.LocationInWindow;
    var windowHeight = Window.Frame.Height;

    if (clickLocation.Y > (windowHeight - DraggableAreaHeight))
        _dragShouldRepositionWindow = true;
}

public override void MouseUp(NSEvent theEvent)
{
    base.MouseUp(theEvent);
    _dragShouldRepositionWindow = false;
}

public override void MouseDragged(NSEvent theEvent)
{
    base.MouseDragged(theEvent);
    if (_dragShouldRepositionWindow)
    {
        this.Window.PerformWindowDrag(theEvent);
    }
}

凤舞天涯 2024-12-09 23:54:01

@starkos 在 https://stackoverflow.com/a/54987061/140927 提供了正确的答案以下只是 ObjC在 WKWebView 的子类中实现:

BOOL _dragShouldRepositionWindow = NO;

- (void)mouseDown:(NSEvent *)event {
    [super mouseDown:event];
    NSPoint loc = event.locationInWindow;
    CGFloat height = self.window.frame.size.height;
    if (loc.y > height - 28) {
        _dragShouldRepositionWindow = YES;
    }
}

- (void)mouseUp:(NSEvent *)event {
    [super mouseUp:event];
    _dragShouldRepositionWindow = NO;
}

- (void)mouseDragged:(NSEvent *)event {
    [super mouseDragged:event];
    if (_dragShouldRepositionWindow) {
        [self.window performWindowDragWithEvent:event];
    }
}

有关如何操作标题栏的更多信息,请参阅 https://github.com/lukakerr/NSWindowStyles

@starkos porvided the correct answer at https://stackoverflow.com/a/54987061/140927 The following is just the ObjC implementation in a subclass of WKWebView:

BOOL _dragShouldRepositionWindow = NO;

- (void)mouseDown:(NSEvent *)event {
    [super mouseDown:event];
    NSPoint loc = event.locationInWindow;
    CGFloat height = self.window.frame.size.height;
    if (loc.y > height - 28) {
        _dragShouldRepositionWindow = YES;
    }
}

- (void)mouseUp:(NSEvent *)event {
    [super mouseUp:event];
    _dragShouldRepositionWindow = NO;
}

- (void)mouseDragged:(NSEvent *)event {
    [super mouseDragged:event];
    if (_dragShouldRepositionWindow) {
        [self.window performWindowDragWithEvent:event];
    }
}

For further info about how to manipulate the title bar, see https://github.com/lukakerr/NSWindowStyles

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文