ChangeDisplaySettings / EnumDisplaySettings
LONG ChangeDisplaySettings(LPDEVMODE lpDevMode, DWORD dwFlags);
BOOL EnumDisplaySettings(LPCTSTR lpszDeviceName, DWORD iModeNum, LPDEVMODE lpDevMode);
| 欄位 | 用途 |
|---|---|
| dmFields | 指定哪些欄位有效 (位元組合) |
| dmPelsWidth | 水平解析度 (像素) |
| dmPelsHeight | 垂直解析度 |
| dmBitsPerPel | 色深 (8/16/24/32) |
| dmDisplayFrequency | 重新整理率 (Hz) |
| dmPosition | 多螢幕位置 |
#define DM_PELSWIDTH 0x00080000
#define DM_PELSHEIGHT 0x00100000
#define DM_BITSPERPEL 0x00040000
#define DM_DISPLAYFREQUENCY 0x00400000
#define DM_POSITION 0x00200000
void __fastcall TForm1::GetCurrentResolution()
{
int x = GetSystemMetrics(SM_CXSCREEN);
int y = GetSystemMetrics(SM_CYSCREEN);
ShowMessage("目前解析度: " + IntToStr(x) + " x " + IntToStr(y));
}
bool __fastcall TForm1::SetResolution(int width, int height, int freq = 0, int bpp = 0)
{
DEVMODE dm = {0};
dm.dmSize = sizeof(DEVMODE);
// 1. 取得當前模式作為基礎
if (!EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dm))
return false;
// 2. 設定欲變更欄位
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
if (freq > 0) {
dm.dmFields |= DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = freq;
}
if (bpp > 0) {
dm.dmFields |= DM_BITSPERPEL;
dm.dmBitsPerPel = bpp;
}
// 3. 嘗試變更 (CDS_TEST 先測試)
LONG result = ChangeDisplaySettings(&dm, CDS_TEST);
if (result != DISP_CHANGE_SUCCESSFUL)
return false;
// 4. 正式套用
result = ChangeDisplaySettings(&dm, CDS_UPDATEREGISTRY); // 寫入登錄持久化
return result == DISP_CHANGE_SUCCESSFUL;
}
// 按鈕事件
void __fastcall TForm1::BitBtn1Click(TObject *Sender) { SetResolution(800, 600); }
void __fastcall TForm1::BitBtn2Click(TObject *Sender) { SetResolution(1024, 768); }
| 返回值 | 常數 | 含義 |
|---|---|---|
| 0 | DISP_CHANGE_SUCCESSFUL | 成功 |
| -1 | DISP_CHANGE_RESTART | 需重啟 (舊版驅動) |
| -2 | DISP_CHANGE_FAILED | 驅動拒絕/模式不支援 |
| -3 | DISP_CHANGE_BADMODE | 模式無效 |
| -4 | DISP_CHANGE_NOTUPDATED | 登錄更新失敗 |
| -5 | DISP_CHANGE_BADFLAGS | 旗標錯誤 |
| -6 | DISP_CHANGE_BADPARAM | 參數錯誤 |
// 列舉所有顯示裝置
DISPLAY_DEVICE dd = {0}; dd.cb = sizeof(dd);
for (DWORD i = 0; EnumDisplayDevices(NULL, i, &dd, 0); i++) {
if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) {
DEVMODE dm = {0}; dm.dmSize = sizeof(dm);
EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm);
// 針對 dd.DeviceName 呼叫 ChangeDisplaySettings
}
}
CDS_TEST 先驗證模式支援,避免螢幕黑屏無法恢復。CDS_UPDATEREGISTRY 持久化,否則重啟後恢復預設。ChangeDisplaySettings(NULL, 0)。\\.\DISPLAY1 等)。
// 更底層、支援 HDR、VRR、多平面覆疊
IDXGIFactory *pFactory; CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&pFactory);
IDXGIAdapter *pAdapter; pFactory->EnumAdapters(0, &pAdapter);
IDXGIOutput *pOutput; pAdapter->EnumOutputs(0, &pOutput);
DXGI_MODE_DESC mode = { width, height, {freq,1}, DXGI_FORMAT_R8G8B8A8_UNORM, 0, DXGI_MODE_SCALING_UNSPECIFIED, DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED };
pOutput->FindClosestMatchingMode(&mode, &matchedMode, NULL);

ChangeDisplaySettings 雖屬經典 API,但在不支援新式 DisplayConfig 的舊系統、簡易工具、腳本控制場景下仍是首選。