2016-04-21 28 views
0

我是Hearthstone tracker的作者,我必須將幾個NSWindow移至Hearthstone窗口。NSWindow定位

我使用CGWindowListCopyWindowInfo得到爐石的框架。 然後,我必須把我的窗戶移到相對爐石的一些位置。

HSTracker overlays 紅色箭頭在對手牌上,綠色箭頭在轉彎按鈕上,藍色箭頭在窗口的左側和右側。

我的實際畫面設置如下:

Screen setup

這給了我下面的幀

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

爲了將對手跟蹤器(左幀)在正確的位置,這是最簡單的情況下,我用{x 0 y somepadding w 185 h hearthstoneHeight - somepadding}並得到正確的框架與此

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

    return relative 
} 

右跟蹤器使用{x hearthstoneWidth - trackerWidth, ...}

對於其他疊加放置,我用我的電流(爐石)號決議,將它們並把它們用一個簡單的數學

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

這工作得很好計算它們。除非我使用我的第二個屏幕。在這種情況下,框架似乎是正確的,但窗口的位置不好。

以下是調試窗口的屏幕截圖,其中包含{x 0 y 0 w hearthstoneWidth h hearthsoneHeight }。如果我比較爐石和我的覆蓋的幀,它們是相同的。 Debug overlay

完整的功能如下(我在「靜態類」,我只顯示revelant代碼)。我想我在計算中缺少一些東西,但我找不到。

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) 

任何幫助將讚賞:)

回答

0

我終於解決了這個問題,所以我決定後的答案,關閉這個線程...也許如果有人遇到同樣的問題一天。

的解決方案是從第一屏幕與爐石窗口的最大值爲y的。減去最大值爲y

findHearthstoneFrame最後的代碼是

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 
     } 
} 

而且frameRelative

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 
}