在日常的程序開發中,有時我們想讓自己編寫的程序運行在顯示器一定的分辨率和色彩數目下。如何讓程序自動修改當前的顯示器設置呢?這首先得從顯示器的工作原理談起。
一、相關原理
我們知道,顯示器所顯示的內容對應於顯存,在顯示器上最小的單位是象素(Pixel,這裡僅考慮邏輯象素),顯存的最小的單位是位(Bits)。 顯示器工作的特征主要體現在色彩數和分辨率兩方面。顯示器所顯示的色彩的數目取決於單位象素所使用的顯存的位數(Bits)。在顯存中,如果8位顯存(即一個向象素使用了一字節的顯存)對應於顯示器上的一個象素,那麼顯示器所顯示的色彩數目為28=256色;同樣,如果當前的色彩為16位,那麼顯示器所顯示的色彩數目為216=65536種色彩。顯示器的分辨率指的是水平分辨率和垂直分辨率,經常所說的800X600,就是指在水平方面上所顯示的象素為800個,在垂直方面上所顯示的象素為600個。
在VC中提供了修改顯示設備(如顯示器、打印機等等,本文只就顯示器而言)屬性的函數:ChangeDisplaySettings,該函數能夠按照你的需要對顯示設備作出相應的修改。其函數申明如下:
LONG ChangeDisplaySettings(
LPDEVMODE lpDevMode,
DWord dwflags
);
其參數的含義如下:
lpDevMode:一個指向DEVMODE數據結構的指針,DEVMODE的數據結構描述了欲設定顯示器的各類屬性值。通常情況下使用到的參數有:
dmSize:所用DEVMODE數據結構的大小(以Bytes為單位)
dmBitsPerPel :每象素所使用的顯存位數(Bits)
dmPelsWidth Pixel width :水平分辨率(點數)
dmPelsHeight Pixel height :垂直分辨率(點數)
dmDisplayFrequency Mode frequency :顯示刷新率,以赫茲為單位
dmFields:通常情況下,不同的顯示設備(如打印機)用到的DEVMODE數據結構的內容不同,比如設定打印機時,你不會用到dmDisplayFrequency屬性。所以,在你使用DEVMODE數據結構時,應向系統說明你具體用到的有效數據成員,dmFIElds的用處便在於此。如果在程序中只用到dmPelsWidth(水平分辨率)和dmPelsHeight(垂直分辨率),那麼該值應為DM_PELSWIDTH|DM_PELSHEIGHT。
Dwflags:表明對顯示設備的修改方式。具體取值有以下幾種:
0 :動態改變顯示設備屬性
CDS_UPDATEREGISTRY:動態改變顯示設備屬性並修改注冊表相關設置,下次啟動計算機時,本次所做的修改依然有效
CDS_TEST: 測試所做的修改是否有效
該函數的返回值:
DISP_CHANGE_SUCCESSFUL:修改成功
DISP_CHANGE_RESTART :修改後需重新啟動(在顯示器設定中選擇了“應用新的顏色前重新啟動計算機”)
DISP_CHANGE_FAILED :修改失敗
DISP_CHANGE_BADMODE:修改模式錯誤(比如你的顯示器是單色的,但你卻將之修改為256色的)
當If lpDevMode為NULL且dwflags 為0時, 顯示設備使用注冊表當前值。
以上是ChangeDisplaySettings常見的用法,更詳細的參數說明請參見MSDN。
二、實戰演練
下面舉一具體的例子來說明在VC中如何修改顯示器的分辨率和色彩。假設我們想將當前顯示器的分辨率設為800X600,並使用24位色(色彩為224種)。
步驟1、新建一MFC AppWizard項目,本文為節約篇幅起見,在向導的第一步中選擇基於對話框(Dialog Baseed)的程序。在向導的其余步驟中全部使用默認值。
步驟2、在對話框中新添加一按鈕,標題設為“測試”。
步驟3、雙擊“測試”按鈕,系統提示新建一函數OnButton1對應於該按鈕的CLICK事件。OnButton1函數的具體代碼如下:
void CChange_fenbianDlg::OnButton1()
{
DEVMODE lpDevMode;
lpDevMode.dmBitsPerPel=24;
lpDevMode.dmPelsWidth=800;
lpDevMode.dmPelsHeight=600;
lpDevMode.dmSize=sizeof(lpDevMode);
lpDevMode.dmFIElds =DM_PELSWIDTH|DM_PELSHEIGHT|DM_BITSPERPEL;
LONG result;
result=ChangeDisplaySettings(&lpDevMode,0);
if (result==DISP_CHANGE_SUCCESSFUL)
{
AfxMessageBox("修改成功!");
ChangeDisplaySettings(&lpDevMode,CDS_UPDATEREGISTRY);
//使用CDS_UPDATEREGISTRY表示次修改是持久的,
//並在注冊表中寫入了相關的數據
}
else
{
AfxMessageBox("修改失敗,恢復原有設置!");
ChangeDisplaySettings(NULL,0);
}
}
說明:上述函數中對ChangeDisplaySettings的返回值result沒有作過多的分析,在實際操作中出於程序穩健的角度出發,可以對ChangeDisplaySettings的返回值作出更加詳細的判斷,以找出修改不成功的原因