2016-04-21 22 views
0

Ich bin der Autor eines Hearthstone tracker, und ich muss mehrere NSWindow über Hearthstone-Fenster verschieben.NSWindow Positionierung

Ich bekomme den Rahmen von Hearthstone mit CGWindowListCopyWindowInfo. Dann muss ich meine Fenster an einigen Positionen relativ zu Hearthstone bewegen.

HSTracker overlays Die roten Pfeile sind über Gegner Karten, grüner Pfeil ist über Drehknopf und blaue Pfeile sind auf der linken und rechten Seite des Fensters.

Mein aktueller Bildschirmaufbau ist die folgende:

Screen setup

, die mir die folgende Frames

// screen 1 : {x 0 y 0 w 1.440 h 900} 
// screen 2 : {x 1.440 y -180 w 1.920 h 1.080} 

den Gegner Tracker Um Platz gibt (den linken Rahmen) an der richtigen Stelle, die ist der einfachste Fall, ich benutze {x 0 y somepadding w 185 h hearthstoneHeight - somepadding} und bekomme den richtigen Rahmen mit diesem

func relativeFrame(frame: NSRect) -> NSRect { 
    var relative = frame 
    relative.origin.x = NSMinX(hearthstoneFrame) + NSMinX(frame) 
    relative.origin.y = NSMinY(hearthstoneFrame) + NSMinY(frame) 

    return relative 
} 

Die richtige Tracker platziert {x hearthstoneWidth - trackerWidth, ...} mit

Für andere Overlays, benutzte ich meine aktuelle (Hearthstone) Auflösung, sie zu platzieren und sie berechnen ziemlich gut eine einfache mathematische mit

x = x/1404.0 * NSWidth(hearthstoneFrame) 
y = y/840.0 * NSHeight(hearthstoneFrame) 

Dies funktioniert. Außer wenn ich meinen zweiten Bildschirm benutze. In diesem Fall scheinen die Rahmen korrekt zu sein, aber die Position des Fensters ist nicht gut.

Hier ist ein Screenshot eines Debug-Fensters mit {x 0 y 0 w hearthstoneWidth h hearthsoneHeight }. Wenn ich die Rahmen von Hearthstone und meinem Overlay vergleiche, sind sie identisch. Debug overlay

Die komplette Funktion ist die folgende (Ich bin in einer "statischen Klasse", ich zeige nur den Code des Offenbaren). Ich denke, ich vermisse etwas in der Berechnung, aber ich kann nicht finden was. schließlich dieses Problem gelöst, damit ich die Antwort schreiben beschlossen, diesen Thread zu schließen ... und vielleicht, wenn jemand das gleiche Problem 1 Tag Gesicht

class frameRelative { 
    static var hearthstoneFrame = NSZeroRect 
    static func findHearthstoneFrame() { 
     let options = CGWindowListOption(arrayLiteral: .ExcludeDesktopElements) 
     let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0)) 
     if let info = (windowListInfo as NSArray? as? [[String: AnyObject]])? 
      .filter({ 
       !$0.filter({ $0.0 == "kCGWindowName" && $0.1 as? String == "Hearthstone" }).isEmpty 
      }) 
      .first { 
       var rect = NSRect() 
       let bounds = info["kCGWindowBounds"] as! CFDictionary 
       CGRectMakeWithDictionaryRepresentation(bounds, &rect) 
       rect.size.height -= titleBarHeight // remove the 22px from the title 
       hearthstoneFrame = rect 
     } 
    } 

    static func frameRelative(frame: NSRect, _ isRelative: Bool = false) -> NSRect { 
     var relative = frame 
     var pointX = NSMinX(relative) 
     var pointY = NSMinY(relative) 

     if isRelative { 
      pointX = pointX/1404.0 * NSWidth(hearthstoneFrame) 
      pointY = pointY/840.0 * NSHeight(hearthstoneFrame) 
     } 

     let x: CGFloat = NSMinX(hearthstoneFrame) + pointX 
     let y = NSMinY(hearthstoneFrame) + pointY 

     relative.origin = NSMakePoint(x, y) 
     return relative 
    } 
} 

// somewhere here 
let frame = NSMakeRect(0, 0, hearthstoneWidth, hearthstoneHeight) 
let relativeFrame = SizeHelper.frameRelative(frame) 
myWindow.setFrame(relativeFrame, display: true) 

wird jede Hilfe dankbar :)

Antwort

0

ich.

Die Lösung war es, den max y vom ersten Bildschirm mit dem max y des Hearthstone Fenster zu subtrahieren.

Der endgültige Code von findHearthstoneFrame ist

static func findHearthstoneFrame() { 
    let options = CGWindowListOption(arrayLiteral: .ExcludeDesktopElements) 
     let windowListInfo = CGWindowListCopyWindowInfo(options, CGWindowID(0)) 
     if let info = (windowListInfo as NSArray? as? [[String: AnyObject]])?.filter({ 
      !$0.filter({ $0.0 == "kCGWindowName" 
       && $0.1 as? String == "Hearthstone" }).isEmpty 
     }).first { 
      if let id = info["kCGWindowNumber"] as? Int { 
       self.windowId = CGWindowID(id) 
      } 
      var rect = NSRect() 
      let bounds = info["kCGWindowBounds"] as! CFDictionary 
      CGRectMakeWithDictionaryRepresentation(bounds, &rect) 

      if let screen = NSScreen.screens()?.first { 
       rect.origin.y = NSMaxY(screen.frame) - NSMaxY(rect) 
      } 

      self._frame = rect 
     } 
} 

Und die frameRelative ist

static let BaseWidth: CGFloat = 1440.0 
static let BaseHeight: CGFloat = 922.0 
var scaleX: CGFloat { 
    return NSWidth(_frame)/SizeHelper.BaseWidth 
} 

var scaleY: CGFloat { 
    // 22 is the height of the title bar 
    return (NSHeight(_frame) - 22)/SizeHelper.BaseHeight 
} 
func frameRelative(frame: NSRect, relative: Bool = true) -> NSRect { 
    var pointX = NSMinX(frame) 
    var pointY = NSMinY(frame) 
    let width = NSWidth(frame) 
    let height = NSHeight(frame) 

    if relative { 
     pointX = pointX * scaleX 
     pointY = pointY * scaleY 
    } 

    let x: CGFloat = NSMinX(self.frame) + pointX 
    let y: CGFloat = NSMinY(self.frame) + pointY 

    let relativeFrame = NSRect(x: x, y: y, width: width, height: height) 
    return relativeFrame 
}