Windows可以將多個(gè)顯示器映射為虛擬桌面,使我們可以利用這一點(diǎn)設(shè)計(jì)出方便工作的應(yīng)用程序。例如Powerpoint就充分發(fā)揮了雙顯示器的優(yōu)勢(shì)(大多數(shù)的筆記本電腦都支持),它可以在一個(gè)顯示器上播放幻燈片,而在另一個(gè)顯示器上顯示備注,可以控制播放的進(jìn)程,使使用者做商務(wù)演說(shuō)的時(shí)候非常等心應(yīng)手。那么我們?cè)趺撮_(kāi)發(fā)這種應(yīng)用程序呢?這篇文章將向你展示如果用Delphi實(shí)現(xiàn)使用多顯示器的應(yīng)用程序。
Windows還支持克隆顯示方式,每個(gè)顯示器輸出同樣的內(nèi)容,這對(duì)某些應(yīng)用也是有意義的。還有些顯卡雖然也支持兩個(gè)顯示器,不過(guò)他們并不是真正意義上的多顯示器,而是虛擬高分辨率顯示模式(如2048×768或者1024×1536),通過(guò)顯卡將畫(huà)面分別顯示到兩個(gè)顯示器上。這兩種顯示模式都不是本文介紹的zhongdian,而且也非常簡(jiǎn)單,所以我們也就不再贅述了。
Windows最多支持10個(gè)顯示器,Windows將所有顯示器映射為一個(gè)大的虛擬桌面。可以將顯示器理解為桌面某個(gè)局部的視圖。在顯示屬性中可以根據(jù)顯示器的物理位置任意排布這些顯示器。如果顯示器的排列不規(guī)則,虛擬桌面上的某些部分可能無(wú)法顯示在任何一個(gè)顯示器上。為了不使一個(gè)窗體顯示在兩個(gè)顯示器之間等原因的考慮,Windows將一個(gè)顯示器作為主顯示器。啟動(dòng)計(jì)算機(jī)時(shí),登錄對(duì)話框就顯示在主顯示器中。絕大多數(shù)程序啟動(dòng)示,都會(huì)顯示在主監(jiān)視器中。
根據(jù)上述介紹,不難發(fā)現(xiàn)幾個(gè)重要的概念:桌面、顯示器、主顯示器等。首先必須先弄清楚這些概念以及他們之前的關(guān)系。這是掌握多顯示器應(yīng)用程序開(kāi)發(fā)方法的重點(diǎn)。理解了這些概念,其他的部分就非常好理解了。
桌面實(shí)際上是指Windows可顯示的邏輯區(qū)域。實(shí)際上是可以將一個(gè)窗體顯示到桌面之外的。然而這并不是說(shuō)桌面的所有部分都會(huì)顯示在某臺(tái)顯示器上(原因如前所述);但反過(guò)來(lái)說(shuō),任何一個(gè)顯示器顯示的內(nèi)容都必然是桌面的一部分。
桌面是一個(gè)矩形區(qū)域,可以通過(guò)頂點(diǎn)坐標(biāo)(Top,Left)和寬高來(lái)描述桌面的尺寸。為什么還需要頂點(diǎn)坐標(biāo)呢?因?yàn)轫旤c(diǎn)坐標(biāo)不是想當(dāng)然的(0,0)。那么(0,0)在哪里呢?說(shuō)來(lái)話長(zhǎng),還是讓我們先來(lái)回顧一下剛才提到地一個(gè)概念——主顯示器吧。Windows希望一般的程序初始的時(shí)候顯示到主顯示器,因?yàn)槿藗兞?xí)慣于關(guān)注一個(gè)離自己最近的顯示器。而Windows也不可能強(qiáng)制用戶把最左邊一個(gè)顯示器作為主顯示器,這樣一來(lái)應(yīng)用程序?yàn)榱税炎约猴@示到主顯示器,就需要費(fèi)腦筋的計(jì)算。然而,多數(shù)用戶都只有一個(gè)顯示器(兩個(gè)顯示器實(shí)在太占地方了),而一般的應(yīng)用程序也不希望大費(fèi)周章的去計(jì)算主顯示器在哪里,自己應(yīng)該顯示在什么位置。所以Windows提出了一個(gè)合理的解決方案:以主顯示器的頂點(diǎn)坐標(biāo)作為坐標(biāo)系的原點(diǎn)。這樣一來(lái),普通的程序之需要想在單顯示器環(huán)境中一樣考慮問(wèn)題就可以了。
顯示器是桌面的局部視圖。就好像透過(guò)窗戶看窗外的風(fēng)景,站在不同的窗前就可以看到不同的畫(huà)面。同樣的,顯示器也是一個(gè)矩形區(qū)域,同樣可以通過(guò)頂點(diǎn)坐標(biāo)(Top,Left)和寬高來(lái)描述它的尺寸。頂點(diǎn)坐標(biāo)是相對(duì)于桌面坐標(biāo)系原點(diǎn)的,也就是相對(duì)于主顯示器的頂點(diǎn)。
工作區(qū)的概念比較簡(jiǎn)單,它是指顯示器中除了任務(wù)條和其他停靠在桌面上的窗體之外的矩形區(qū)域。
Windows為多顯示器應(yīng)用程序的開(kāi)發(fā)提供了一組API。VCL將這些API封裝起來(lái),非常自然的融入整個(gè)Framework之中,使得開(kāi)發(fā)多顯示器應(yīng)用程序變得非常簡(jiǎn)單。下面就介紹與之相關(guān)的內(nèi)容。
在VCL之中大家最熟悉的恐怕非TCustomForm莫屬了,它是所有窗體的基類。TCustomForm的Position屬性用來(lái)設(shè)置窗體的現(xiàn)實(shí)位置,其可選值中有兩個(gè)是值得關(guān)心的:一個(gè)是poScreenCenter,當(dāng)Position屬性被設(shè)置成poScreenCenter時(shí),窗體會(huì)顯示到主顯示器的中央;另一個(gè)是poDesktopCenter,當(dāng)Position屬性被設(shè)置成poDesktopCenter時(shí),窗體顯示在整個(gè)桌面的中央。如果把這個(gè)屬性設(shè)成poDesktopCenter,程序又運(yùn)行在一個(gè)有多臺(tái)顯示器的系統(tǒng)上,那么這個(gè)窗口就會(huì)顯示在兩個(gè)顯示器之間,會(huì)給用戶帶來(lái)不必要的麻煩。因此即使我們的程序不是針對(duì)多顯示器而設(shè)計(jì)的,也應(yīng)該細(xì)心處理這個(gè)值。另外一個(gè)屬性是DefaultMonitor,它的作用與Position有些類似,決定窗口最初顯示在哪個(gè)顯示器內(nèi)。它有四個(gè)備選值:dmDesktop,dmPRimary,dmMainForm和dmActiveForm。他們的含義如下:
Value | Meaning |
dmDesktop | 不特別處理 |
dmPrimary | 將窗體顯示到第一個(gè)顯示器上。這又是一個(gè)陷阱,字面上理解是主顯示器,而事實(shí)上它是指Screen.Monitor[0]這個(gè)顯示器。 |
dmMainForm | 將窗體顯示到主窗體所在的顯示器 |
dmActiveForm | 將窗體顯示到桌面上活動(dòng)窗體所在的顯示器 |
TCustomForm還有一個(gè)只讀的共有屬性(沒(méi)有Published)Monitor,它提供了訪問(wèn)窗體所在顯示器實(shí)例的引用,這個(gè)值與DefaultMonitor是有緊密的關(guān)聯(lián)的。
那么怎么在使窗體在不同的顯示器之間移動(dòng)呢?這并不困難,估計(jì)你也想到了。這里介紹兩種方法:
第一, 可以設(shè)置TCustomForm的Top和Left使窗體顯示在桌面的任意位置。正如前面所述,桌面是由所有顯示器組成的。它們有共同的坐標(biāo)系,所以可以根據(jù)顯示器的邏輯位置決定窗體的位置。現(xiàn)在的問(wèn)題是如何獲得每個(gè)顯示器的邏輯位置和尺寸,后面就會(huì)介紹。
第二, 可以調(diào)用TCustomForm的MakeFullyVisible方法將窗體完全顯示到指定的顯示器之中。可以通過(guò)這個(gè)方法避免窗口在兩個(gè)顯示器上各顯示一部分。
剛才我們提出了一個(gè)問(wèn)題:如何獲得每個(gè)顯示器的邏輯位置和尺寸。為了解答這個(gè)問(wèn)題,需要再介紹連個(gè)類:TScreen和TMonitor。
TScreen描述與顯示設(shè)備有關(guān)的一些信息,我們主要關(guān)心與顯示器邏輯位置和尺寸有關(guān)的信息。其他方面的內(nèi)容可以在Delphi的文檔中獲知。在程序運(yùn)行的時(shí)候VCL自動(dòng)創(chuàng)建一個(gè)TScreen的實(shí)例——全局變量,所以通常情況下程序是不需要實(shí)例化TScreen的。
TScreen有一組形如Desktop*的屬性,這些屬性描述了整個(gè)桌面的尺寸和各頂點(diǎn)坐標(biāo)。還有對(duì)開(kāi)發(fā)多顯示器應(yīng)用程序有重要意義的連個(gè)屬性:MonitorCount和Monitors。通過(guò)這兩個(gè)屬性我們可以枚舉出系統(tǒng)中所有的顯示器(TMonitor)的實(shí)例,每個(gè)實(shí)例都反映了相應(yīng)顯示器的相對(duì)位置和分辨率等信息(后文會(huì)詳細(xì)說(shuō)明)。
在TScreen的眾多屬性之中,我們會(huì)找到Height和Width這兩個(gè)屬性。要特別警惕它們不是指整個(gè)桌面的尺寸,而是指主顯示器的高度和寬度。這非常容易讓人產(chǎn)生錯(cuò)覺(jué),無(wú)以為是整個(gè)桌面的尺寸。與之類似的還有形如WorkArea*的一組屬性,它們描述了主顯示器的工作區(qū)域的尺寸和各頂點(diǎn)坐標(biāo)。是不是覺(jué)得少了什么?為什么沒(méi)有獲取主顯示器相對(duì)位置的屬性?原因就像前面所說(shuō)的:Windows是以主顯示器的左上角為坐標(biāo)系原點(diǎn)的,所以主顯示器的相對(duì)位置必然是(0,0)。
除了這些屬性之外,還要介紹TScreen的三個(gè)成員函數(shù):MonitorFromPoint,MonitorFromRect和MonitorFromWindow。顧名思義,他們分別是獲取個(gè)坐標(biāo)、某個(gè)區(qū)域和某個(gè)窗口所在的顯示器的實(shí)例。在實(shí)際的開(kāi)發(fā)中可能也會(huì)用到。
最好,再來(lái)看看TMonitor類。它封裝了物理顯示器的有關(guān)屬性——這些屬性都是只讀的。下表簡(jiǎn)單介紹了這些屬性的含義,它們對(duì)編寫(xiě)多顯示器應(yīng)用程序非常有用:
屬性 | 說(shuō)明 |
Handle | 獲取該顯示器的Windows句柄 |
MonitorNum | 獲取顯示器的編號(hào) |
Primary | 獲取該顯示器是否是主顯示器。又且僅有一個(gè)顯示器的Primary是True。 |
Top | 獲取顯示器的上邊界 |
Left | 獲取顯示器的左邊界 |
Height | 獲取顯示器的高度 |
Width | 獲取顯示器的寬度 |
BoundsRect | 獲取顯示器的對(duì)應(yīng)桌面的區(qū)域,它與上面四個(gè)屬性是等價(jià)的 |
WorkareaRect | 獲取顯示器的工作區(qū)對(duì)應(yīng)桌面的區(qū)域。 |
清楚地了解了TScreen和TMonitor之后,前面的問(wèn)題也就自然解決了。到這里,本文已經(jīng)介紹了開(kāi)發(fā)多顯示器應(yīng)用程序所需的全部知識(shí)。相信你可以利用這些知識(shí)開(kāi)發(fā)出非常實(shí)用的軟件產(chǎn)品。
附:你可以下載一個(gè)DEMO,幫助理解本文。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注