动态更改NSWindow的isMovableByWindowBackground并且是可移动的

时间:2017-11-25 23:49:37

标签: cocoa

我一直试图解决这个非常令人沮丧的问题,我希望有人可以提供帮助。我正在尝试创建一个有多个视图的NSWindow。视图可以相互重叠。这些是要求。

  • 如下图所示的蓝色NSView可以移动窗口。
  • 黄色NSView无法移动窗口。这是另一个NSView实例,位于蓝色NSView下面。
  • 运动需要感觉像任何其他窗户运动一样。
  • 将窗户一直拖到顶部的事情应该激活Expose(Sierra和High Sierra)。

enter image description here

首次尝试

我试过以下尝试过这个。不幸的是,这根本不起作用。

在NSWindow

override func awakeFromNib() {
    self.refreshElements()
    self.titlebarAppearsTransparent = true
    self.isMovableByWindowBackground = true
}

在我的自定义视图中

class Blue: NSView {
    public override var mouseDownCanMoveWindow: Bool { return true }
}

class Yellow: NSView {
    public override var mouseDownCanMoveWindow: Bool { return false }
}

第二次尝试

然后我尝试在Blue中实施mouseDown mouseDraggedmouseUp。我会在窗口上计算鼠标移动和self.setFrame(frameRect:display:animate:)。这工作正常,我可以控制移动窗口,但它有几个问题。一个无论窗口运动总是慢一点。即使我将animate属性设置为false,我认为它也是动画。它也没有像其他窗口那样激活Expose。

第三次尝试

这与我可以通过一个主要问题达到我想要的行为一样接近。最初的mouseDown没有注册。因此,您无法单击蓝色视图并拖动并移动窗口。你有mouseDown,mouseUp,然后再次mouseDown,以便拖动来移动窗口。

public class MyWindow: NSWindow {

    @IBOutlet var blue: NSView!
    @IBOutlet var yellow: NSView!

    public override func awakeFromNib() {
        self.titlebarAppearsTransparent = true
        self.isMovable = false
        self.isMovableByWindowBackground = true
    }

    public override func mouseDown(with event: NSEvent) {
        let point = event.locationInWindow

        let move = NSPointInRect(point, self.blue.frame)
        self.isMovableByWindowBackground = move
        self.isMovable = move

        super.mouseDown(with: event)
    }
    public override func mouseDragged(with event: NSEvent) {
        super.mouseDragged(with: event)
    }

}

我首选的方法是方法3.它是最干净的代码,除了不必要点击然后再次点击以使事情发挥作用之外的其他一切都是完美的。我的问题是,在动态设置为允许移动后,如何强制初始点击也向窗口注册?

1 个答案:

答案 0 :(得分:1)

自macOS 10.11起,NSWindow已为此目的使用方法performDrag(with:)。它启动窗口拖动就像用户点击并拖动标题栏时所做的那样。您的蓝色视图可以简单地在其覆盖mouseDown()

中调用它

mouseDownCanMoveWindow的问题在于它只是将问题传递给超级视图。除非所有祖先观看窗口的内容视图都返回true,否则无关紧要。