本文來自網易雲社區
作者:梁敏
一、多屏設置
-
在設置-系統-可以點擊顯示器1和2,可以進行單獨設置;
-
“使之成為我的主顯示器”可以設置當前顯示器是主屏;主屏的選擇會決定整個虛擬屏幕坐標起點的位置。
-
多顯示器可以設置擴展,復制和獨立展示。(獨立顯示是只在顯示屏1 或者2上顯示)
-
擴展 - 設計,辦公等場景。對於應用的意義則在於我們可以在兩個或多個顯示器上,分別打開不同的窗口,比如在一個顯示器上顯示網頁,另一個顯示器上進行文檔編輯,在多任務應用時會非常方便。
-
復制 - 會議、教學、商業展示。也就是說多屏顯示系統中的每個顯示設備,所顯示的內容都是一樣的,這一特點使它適合用在商務以及教學場合,比如大學課堂上講課時或在會議上進行演示等。 - 設置完成后,和擴展模式中各顯示器可以設置成各自的最佳分辨率不同,復制模式只能根據較低得分辨率進行設置,類似水桶效應:多屏顯示系統中最小分辨率的設備決定整個畫面的分辨率。所以在復制模式下,如果兩款顯示設備的分辨率不一樣,則具有較高分辨率的顯示設備,畫面的質量必然受到影響,這也是復制模式的一個局限。
-
獨立。
-
設置是否在多顯示器上顯示任務欄,如圖:
-
是否在所有顯示器上顯示任務欄
-
所有任務欄
-
主任務欄和打開了窗口的任務欄
-
打開了窗口的任務欄
二、虛擬桌面坐標
-
主屏幕(Primary Screen)和擴展屏幕
-
主顯示屏的左上角決定了虛擬桌面的起始坐標(0,0)。其他顯示器的顯示區域的坐標由他和主顯示屏的相對位置決定。
-
擴展屏幕有多個。
-
虛擬屏幕(Virtual Screen)
-
主屏和擴展屏組成的整個屏幕,就是虛擬屏幕。主屏和擴展屏,並非整齊排列,擴展屏可以放在主屏四周任何地方,但要相鄰。
-
虛擬桌面中的坐標是連續的,因此顯示器2的坐標是主顯示器1的顯示區域的繼續。例如如下顯示器1分辨率1680x1050,顯示器2分辨率1440x900,顯示器2位於主顯示器的正右方,則第二個顯示區域的坐標是從(1680,0)到(3119,899)。
如果設置顯示器2是主屏,顯示器2的坐標是(0,0)->(1439,899),顯示器1的坐標(-1679,1049)
三、系統相關API
Microsoft為支持多顯示器模式提供了一些新的API調用,下面具體介紹它們的功能:
1.HMONITOR MonitorFromPoint(POINT pt,DWORD dwFlags)
MonitorFromPoint返回包含特定點(pt)的一個顯示器句柄。如果pt不屬於任何一個顯示器,返回的顯示器句柄由dwFlags標志決定:
MONITOR_DEFAULTTONULL時返回NULL;
MONITOR_DEFAULTTOPRIMARY時返回代表主顯示器的HMONITOR句柄;
MONITOR_DEFAULTTONEAREST時返回最靠近pt點的顯示器的HMONITOR句柄。
2.HMONITOR MonitorFromRect(LPCRECT lprc,DWORD dwFlags)
MonitorFromRect返回包含lprc代表的矩形的顯示器句柄;如果包含此矩形的顯示區域不止一個,則返回包含矩形最大部分的顯示器句柄;如果矩形不屬於任何一個顯示區域,返回的句柄由dwFlags決定,規則與MonitorFromPoint相同。
3. HMONITOR MonitorFromWindow(HWND hwnd,DWORD dwFlags)
與MonitorFromRect類似,但輸入是一個代表窗口的句柄hwnd而不是指向矩形的指針。
4.BOOL GetMonitorInfo(HMONITOR hMonitor,LPMONITORINFO lpmi)
GetMonitorInfo返回由hMonitor代表的顯示器的有關信息,這些信息存儲在指向MONITORINFO結構的指針——lpmi中。這些信息包括用RECT結構表示的顯示器的顯示區域的大小(如果這個顯示器不是主顯示器,RECT的坐標可能為負數),以及用RECT結構表示的顯示器的工作區域的大小,工作區域是顯示區域中除去系統任務欄和應用程序快捷方式欄所剩下的區域,還能夠判斷此顯示器是否為主顯示器,並返回一個標志。
5.GetSystemMetrics
獲取坐標的時候用VIRTUALSCREEN參數
GetSystemMetrics(SM_CXVIRTUALSCREEN);//虛擬桌面寬度
GetSystemMetrics(SM_CYVIRTUALSCREEN);//虛擬桌面高度
GetSystemMetrics(SM_XVIRTUALSCREEN );//虛擬桌面左上角X坐標
GetSystemMetrics(SM_YVIRTUALSCREEN );//虛擬桌面左上角Y坐標
特別注意的是,多顯示器的時候,SM_XVIRTUALSCREEN和SM_YVIRTUALSCREEN是可以為負值的。所以多顯示器處理時,邊界不要以為是(0,0)->(cx,cy)。多顯示器的坐標是以主屏幕的左上角為(0,0)。 使用SM_CXSCREEN,SM_CYSCREEN獲取只是主屏大小。
四、GUI擴展屏開發
GUI在多屏開發時主要問題是:當用戶將主屏窗口移動到副屏后,需要記錄窗口所處屏幕的信息。點擊彈出菜單或者創建新窗口時,需要根據當前所處屏幕計算位置。
已經在我們代碼里做了如下處理,開發時注意:
-
在用Window::CenterWindow顯示新建窗口,如果希望窗口顯示在和某窗口A在同一個顯示器時,且窗口A不是新建窗口的父窗口,需要把該窗口A的句柄傳入。例如我們的主窗口mainwnd,從主窗口新建窗口和主窗口在同一個顯示器時,window->CenterWindow(mainwnd->GetHWND())。第二個參數wndCenter,代表是否要以指定窗口的居中顯示。如果已經設置了父窗口,不需要這么設置,對於父窗口的。在CenterWindow在計算位置時會根據傳入的窗口句柄所在顯示器計算位置。SingletonShow這里也擴展了參數,可以傳入窗口句柄。
void Window::CenterWindow(HWND hwndFrom, bool wndCenter/* = false*/)
eg:nim_ui::WindowsManager::SingletonShow<AboutForm>(AboutForm::kClassName, GetHWND());
-
在調用彈出的msgbox時,一定指定父窗口,這樣彈出的msgbox就會和父窗口保持一致,不需其他處理。ShowMsgBox(m_hWnd, L"******", cb, L"", L"確定", L"");
-
在判斷是否超出當前顯示器邊界的時候,這里要使用虛擬桌面的坐標來進行判斷。
網易雲大禮包:https://www.163yun.com/gift
本文來自網易雲社區,經作者梁敏授權發布
相關文章:
【推薦】 SpringBoot入門(五)——自定義配置
【推薦】 多大規模的數據才值得用大數據的方式來處理?
【推薦】 Android 模擬器 下載、編譯及調試