有遇到這種情況嗎辙浑?當(dāng)你有一臺外借顯示器和一臺 Macbook激涤,而且你的顯示器是有支架可以移動的!有時(shí)候判呕,我把筆記本放在顯示器右邊寫代碼倦踢,而有時(shí)候,我把顯示器放在電腦正上方碼字侠草,而有時(shí)候辱挥,我還想把顯示器豎起來?边涕?(喂晤碘,你怎么那么無聊肮游ⅰ!)感覺每次到設(shè)置-顯示器排列里面拖太麻煩了园爷?(其實(shí)并沒有 QAQ)讓我們用簡單的幾行 Swift 代碼實(shí)現(xiàn)一個 Mac 程序剞劂他吧宠蚂!
獲取目前顯示器信息
- 獲取顯示器配置比較簡單,我們可以通過一行代碼搞定它童社。
NSScreen.screens()
- 獲取的結(jié)果是一個 NSScreen數(shù)組求厕。
- 對于每個 NSScreen 對象,我們可以用screen.deviceDescription 獲取顯示器信息的 NSDictionary 基本信息字典扰楼,從而獲取我們需要的基本信息呀癣,長這樣。
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 用來指定要配置的顯示器
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ù)一鍵配置顯示器排列中使用~
配置顯示器信息
-
首先我們要創(chuàng)建一個 config 指針用于后續(xù)各種配置
import AppKit let config = UnsafeMutablePointer<CGDisplayConfigRef?>.allocate(capacity:1)
-
調(diào)用 CGBeginDisplayConfiguration開始配置顯示器
CGBeginDisplayConfiguration(config)
現(xiàn)在開始配置。
for display in displays{ //假設(shè)這里有個 display s 數(shù)組存儲了各個顯示器的相關(guān)信息(display 為自定義結(jié)構(gòu)體) let error:CGError if display.position_x == 0 && display.position_y == 0{ //坐標(biāo)為(0腾节,0)的顯示器可以直接設(shè)置無需計(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)偏移呢?
如下圖劈榨,在我們之前通過 NSScreen.screens 獲取的 Screen 坐標(biāo)中访递,坐標(biāo)系的原點(diǎn)是主顯示器的左下角,也就是說所有顯示器都是以左下角為基準(zhǔn)計(jì)算偏移量的同辣。如下圖拷姿。
而我們通過 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)換。對了,系統(tǒng)坐標(biāo)系中棒妨,x 坐標(biāo)軸是從左往右踪古,而` y 軸坐標(biāo)是從上往下`。不要弄錯了 ORZ券腔。
于是伏穆,目前來看,公式應(yīng)該是這樣的(簡單小學(xué)數(shù)學(xué)纷纫?)主顯示器 y 軸分辨率 - 所設(shè)置顯示器豎向辨率大小 - 所設(shè)置顯示器之前所獲得y軸坐標(biāo)
- 完成顯示器配置
``` Swift
let error = CGCompleteDisplayConfiguration(config.pointee, .permanently) //設(shè)置配置為永久
if error != .success{
CGCancelDisplayConfiguration(config.pointee)
}
```
## Finished枕扫!