開發支援多顯示器的Windows程式

來源:互聯網
上載者:User

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決定:
MONITOR_DEFAULTTONULL時返回NULL
MONITOR_DEFAULTTOPRIMARY時返回代表主顯示器的HMONITOR控制代碼
MONITOR_DEFAULTTONEAREST時返回最靠近矩形的顯示器的HMONITOR控制代碼

3. HMONITOR MonitorFromWindow(HWND hwnd,DWORD dwFlags)
  與MonitorFromRect類似,但輸入是一個代表視窗的控制代碼hwnd而不是指向矩形的指標。

4. BOOL GetMonitorInfo(HMONITOR hMonitor,LPMONITORINFO lpmi)
  GetMonitorInfo返回由hMonitor代表的顯示器的有關資訊,這些資訊儲存在指向MONITORINFO結構的指標——lpmi中。

typedef struct tagMONITORINFO

{  

    DWORD  cbSize; 

    RECT   rcMonitor; 

    RECT   rcWork; 

    DWORD  dwFlags; 

} MONITORINFO, *LPMONITORINFO;

這些資訊包括用RECT結構表示的顯示器的顯示地區的大小(如果這個顯示器不是主顯示器,RECT的座標可能為負數),以及用RECT結構表示的顯示器的工作區域的大小,工作區域是顯示地區中除去系統工作列和應用程式捷徑欄所剩下的地區,還能夠判斷此顯示器是否為主顯示器,並返回一個標誌(判斷dwFlags是否包含MONITORINFOF_PRIMARY來判斷是否為主顯示器)。

5.BOOL EnumDisplayMonitors(HDC hdc,LPCRECT lprcClip,MONITORENUMPROC lpfnEnum,LPARAM dwData)
  hdc是一個代表顯示裝置環境的控制代碼,lprcClip是指向一個矩形地區的指標。把這個矩形地區和裝置環境中的可見地區取交集,得到的地區可能分布在多個顯示器的顯示地區中,EnumDisplayMonitors對每一個包含交集的顯示地區調用一次MonitorEnumProc類型的函數。DwData為傳遞給MonitorEnumProc函數的資料。

6.BOOL CALLBACK MonitorEnumProc(HMONITOR hmonitor,HDC hdcMonitor,LPRC lprcMonitor, DWORD dwData)
  MonitorEnumProc是一個被EnumDisplayMonitors函數調用的回呼函數,它的內容可以由使用者自訂。利用這兩個函數,使用者在進行跨多個顯示器的顯示時就可以利用每一個顯示器的不同的顯示特性。
  當然,並不是所有畫圖程式都必須調用這兩個函數,這時你假設所有的顯示器都使用同樣顏色的解析度。

7.EnumDisplayDevices(LPVOID lpReserved,int iDeviceNum,DISPLAY_DEVICE×pDisplayDevice,DWORD dwFlags)
  EnumDisplayDevices列出系統中某個顯示裝置(以iDeviceNum為序號)的資訊。與GetMonitorInfo相比,GetMonitorInfo對應的顯示器必須是Windows虛擬桌面的一部分,而EnumDisplayDevices可以列出包括處於獨立顯示模式下的系統所安裝的所有顯示器的資訊。它返回的資訊儲存在DISPLAY_DEVICE結構中,包括顯示裝置名稱、對顯示裝置的描述和顯示裝置的狀態。

以上API使用舉例:
1.判斷視窗是否在有效座標內:
HMONITOR hMonitor = MonitorFromWindow(m_hWnd, MONITOR_DEFAULTTONULL);
如果hMonitor 為NULL,則視窗不在任何顯示器中,此時視窗位置是無法看到的。
即使hMonitor 控制代碼有效,視窗也可能被擋在工作列後面,因此還要繼續拿到視窗所在螢幕的工作區域來判斷視窗是否可見。
if (hMonitor)
{
  MONITORINFO info;
  info.cbSize = sizeof(MONITORINFO);
  if (GetMonitorInfo(hMonitor, &info))
  {
    //拿到視窗的座標跟info.rcWork進來判斷看視窗座標是否有效
  }


2.判斷矩形所在螢幕是否是主顯示器:
HMONITOR hMonitor = MonitorFromRect(&rcTitle, MONITOR_DEFAULTTONULL);
if (hMonitor)
{
  MONITORINFO info;
  info.cbSize = sizeof(MONITORINFO);
  if (GetMonitorInfo(hMonitor, &info) && info.dwFlags & MONITORINFOF_PRIMARY)
  {
    //矩形大部分地區在主顯示器當中
  }


一些要注意的點:
1.通過SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&rcWorkArea, 0)拿到的工作區域範圍是主顯示器的的工作區域,視窗如果需要支援多顯示器就不能簡單地這樣計算工作區域。替換方案是使用GetSystemMetrics,通過用SM_XVIRTUALSCREEN、SM_YVIRTUALSCREEN、SM_CXVIRTUALSCREEN和SM_CYVIRTUALSCREEN參數分別可以得到虛擬桌面左上方的座標和整個的長度和寬度(虛擬桌面即把多個顯示器作為計算在一個作為一個案頭)。

2.單顯示器下負座標或大於SM_CXSCREEN和SM_CYSCREEN部分的視窗將被隱藏,而在多顯示器模式下這些都是合法的,因此支援多顯示器時對視窗位置的判斷不建議直接使用(0,0)和(CXSCREEN,CYSCREEN)地區,而應該選擇上面提到的虛擬桌面座標。


3.在恢複原來儲存的視窗位置之前,要檢查一下這些視窗座標的有效性。例如用上面提到的判斷是否顯示在某個顯示器中,判斷是否在顯示器可工作區域中,判斷是否在虛擬桌面座標合理範圍內。


4.一些Windows的API調用只處理的單顯示器的情況,在調用時要考慮多顯示器的情況。如通過CenterWindow(CWnd::GetDesktopWindow())來設定視窗置中螢幕時是以主畫面置中的,如果需要考慮到主視窗在副顯示器顯示其快顯視窗要置中在副顯示器的話,就要加入必要的處理,暫時沒有找到CenterWindow傳入參數使其在副顯示器置中,這種辦法是以副顯示器中的主視窗置中或人為計算其在副顯示器中的置中座標SetWindowPos一把。


5.(此點為暫時現象總結,仍需進一步驗證)切換顯示器模式時,顯示器的控制代碼會改變,即使所在顯示器沒有變,通過MonitorFrom*****得到的控制代碼也可能不同。如果視窗沒有設定ToolWindow屬性,在切換顯示器模式(無論是雙屏的切換或是單屏解析度的改變),系統會主動改變視窗的位置來適應解析度或是顯示器的改變,這個位置改變不會引起OnWindowPosChanging訊息,在OnWindowPosChanged中打日誌看到,lpwndpos->flags為0x815,即SWP_NOSIZE & SWP_NOZORDER & SWP_NOACTIVATE & 0x800。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.