有遇到這種情況嗎?當(dāng)你有一臺(tái)外借顯示器和一臺(tái) Macbook,而且你的顯示器是有支架可以移動(dòng)的!有時(shí)候,我把筆記本放在顯示器右邊寫(xiě)代碼,而有時(shí)候,我把顯示器放在電腦正上方碼字,而有時(shí)候,我還想把顯示器豎起來(lái)??(喂,你怎么那么無(wú)聊?。。└杏X(jué)每次到設(shè)置-顯示器排列里面拖太麻煩了?(其實(shí)并沒(méi)有 QAQ)讓我們用簡(jiǎn)單的幾行 Swift 代碼實(shí)現(xiàn)一個(gè) Mac 程序剞劂他吧!
獲取目前顯示器信息
- 獲取顯示器配置比較簡(jiǎn)單,我們可以通過(guò)一行代碼搞定它。
NSScreen.screens()
- 獲取的結(jié)果是一個(gè) NSScreen數(shù)組。
- 對(duì)于每個(gè) NSScreen 對(duì)象,我們可以用screen.deviceDescription 獲取顯示器信息的 NSDictionary 基本信息字典,從而獲取我們需要的基本信息,長(zhǎng)這樣。
let screen_info = screen.deviceDescription
print(screen_info)
// ["NSDeviceBitsPerSample": 8, "NSDeviceColorSpaceName": NSCalibratedRGBColorSpace, "NSScreenNumber": 69680128, "NSDeviceSize": NSSize: {1440, 900}, "NSDeviceResolution": NSSize: {72, 72}, "NSDeviceIsScreen": YES]
screen_id = screen_info["NSScreenNumber"] as! CGDirectDisplayID // screen_id 用來(lái)指定要配置的顯示器
let screen_size = screen_info["NSDeviceSize"] as! NSSize
screen_width = Int32(screen_size.width)
screen_height = Int32(screen_size.height)
let position = screen.frame
position_x = Int32(position.origin.x)
position_y = Int32(position.origin.y)
- 之后,自己處理這些信息的保存,用于后續(xù)一鍵配置顯示器排列中使用~
配置顯示器信息
-
首先我們要?jiǎng)?chuàng)建一個(gè) config 指針用于后續(xù)各種配置
import AppKit let config = UnsafeMutablePointer<CGDisplayConfigRef?>.allocate(capacity:1) -
調(diào)用 CGBeginDisplayConfiguration開(kāi)始配置顯示器
CGBeginDisplayConfiguration(config)現(xiàn)在開(kāi)始配置。
for display in displays{ //假設(shè)這里有個(gè) display s 數(shù)組存儲(chǔ)了各個(gè)顯示器的相關(guān)信息(display 為自定義結(jié)構(gòu)體) let error:CGError if display.position_x == 0 && display.position_y == 0{ //坐標(biāo)為(0,0)的顯示器可以直接設(shè)置無(wú)需計(jì)算坐標(biāo)矯正 error = CGConfigureDisplayOrigin(config.pointee, display.screen_id, 0, 0) }else{ //其他顯示器需要計(jì)算坐標(biāo)偏移,將在下面講解。 error = CGConfigureDisplayOrigin(config.pointee, display.screen_id, display.position_x, -display.position_y - display.screen_height + main_height) } if error != .success{ //若配置失敗,取消配置,防止內(nèi)存泄漏等現(xiàn)象 CGCancelDisplayConfiguration(config.pointee) return } }為什么需要計(jì)算坐標(biāo)偏移呢?
如下圖,在我們之前通過(guò) NSScreen.screens 獲取的 Screen 坐標(biāo)中,坐標(biāo)系的原點(diǎn)是主顯示器的左下角,也就是說(shuō)所有顯示器都是以左下角為基準(zhǔn)計(jì)算偏移量的。如下圖。

downleft.png
而我們通過(guò) api 進(jìn)行排列設(shè)置的時(shí)候,很坑的是此時(shí)系統(tǒng)坐標(biāo)系是以顯示器的左上角為原點(diǎn)計(jì)算偏移量的!如下圖。注意此時(shí)主顯示器設(shè)置的坐標(biāo)依然是(0,0),而其他顯示器的坐標(biāo)的 y 軸就需要進(jìn)行小小的轉(zhuǎn)換。對(duì)了,系統(tǒng)坐標(biāo)系中,x 坐標(biāo)軸是從左往右,而` y 軸坐標(biāo)是從上往下`。不要弄錯(cuò)了 ORZ。

upleft.png
于是,目前來(lái)看,公式應(yīng)該是這樣的(簡(jiǎn)單小學(xué)數(shù)學(xué)?)主顯示器 y 軸分辨率 - 所設(shè)置顯示器豎向辨率大小 - 所設(shè)置顯示器之前所獲得y軸坐標(biāo)
- 完成顯示器配置
``` Swift
let error = CGCompleteDisplayConfiguration(config.pointee, .permanently) //設(shè)置配置為永久
if error != .success{
CGCancelDisplayConfiguration(config.pointee)
}
```
## Finished!