由于工作需要,我需要制作一个小工具来更改系统分辨率。
小工具需要支持多显示器,每个显示器要能分别设置分辨率
功能很简单,由于不需要做的好看,只要功能可用即可,使用了MFC(只是为了方便)
乱七八糟的逻辑不说,只说几个关键函数:
1.枚举系统显示器
void CDisplaySettingsDlg::FillDeviceCombo()
{
m_comboDevices.Clear();
m_comboDevices.ResetContent();
DWORD dwAdaptorIndex = 0;
DISPLAY_DEVICE ddv;
ZeroMemory(&ddv, sizeof(DISPLAY_DEVICE));
ddv.cb = sizeof(DISPLAY_DEVICE);
while (EnumDisplayDevices(NULL, dwAdaptorIndex++, &ddv, 0))
{
if (!(ddv.StateFlags&DISPLAY_DEVICE_MIRRORING_DRIVER)
&& (ddv.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP))
{
m_comboDevices.AddString(ddv.DeviceName);
}
ZeroMemory(&ddv, sizeof(DISPLAY_DEVICE));
ddv.cb = sizeof(DISPLAY_DEVICE);
}
m_comboDevices.SetCurSel(0);
}
2.枚举显示器支持的分辨率
void CDisplaySettingsDlg::RefreshSettingsCombo()
{
ClearSettingsCombo();
CString strDeviceName;
CString strAdd;
m_comboDevices.GetWindowText(strDeviceName);
int currentCX = 0;
int currentCY = 0;
{
DEVMODE dev;
ZeroMemory(&dev, sizeof(dev));
dev.dmSize = sizeof(dev);
if (EnumDisplaySettings(strDeviceName, ENUM_CURRENT_SETTINGS, &dev))
{
currentCX = dev.dmPelsWidth;
currentCY = dev.dmPelsHeight;
}
}
LPDISPLAYOPTION pOptionPre = NULL;
int iModeNum = 0;
while (true)
{
DEVMODE dev;
ZeroMemory(&dev, sizeof(dev));
dev.dmSize = sizeof(dev);
if (EnumDisplaySettings(strDeviceName, iModeNum, &dev))
{
int cx = dev.dmPelsWidth;
int cy = dev.dmPelsHeight;
if (pOptionPre && pOptionPre->IsLike(cx, cy))
{
iModeNum++;
continue;
}
LPDISPLAYOPTION pNew = new DISPLAYOPTION(cx, cy);
m_vecOptions.push_back(pNew);
pOptionPre = pNew;
}
else
{
break;
}
iModeNum++;
}
std::sort(m_vecOptions.begin(), m_vecOptions.end(), DISPLAYOPTION::biggerWidth);
int curSel = 0;
int index = 0;
for (auto opt : m_vecOptions)
{
strAdd.Format(L"%d * %d", opt->cx, opt->cy);
if (opt->cx == currentCX && opt->cy == currentCY)
{
curSel = index;
}
if (index == 0)
{
strAdd += L"(推荐)";
}
m_comboSettings.SetItemDataPtr(m_comboSettings.AddString(strAdd), opt);
index++;
}
m_comboSettings.SetCurSel(curSel);
}
你可能会看到sort函数,这个就是为了让分辨率从大到小排序,默认的枚举顺序是从小到大,如果正好是你需要的,你就干掉sort和那个把条目存到vector的逻辑。 我存到vector然后sort仅仅是为了排序。
3.应用用户选择的分辨率
void CDisplaySettingsDlg::OnCbnSelchangeComboSettings()
{
int curSel = m_comboSettings.GetCurSel();
CString strDeviceName;
m_comboDevices.GetWindowText(strDeviceName);
if (curSel >= 0)
{
LPDISPLAYOPTION pData = (LPDISPLAYOPTION)m_comboSettings.GetItemDataPtr(curSel);
if (pData)
{
DEVMODE dev;
ZeroMemory(&dev, sizeof(dev));
dev.dmSize = sizeof(dev);
dev.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dev.dmPelsWidth = pData->cx;
dev.dmPelsHeight = pData->cy;
ChangeDisplaySettingsEx(strDeviceName, &dev, NULL,
CDS_GLOBAL | CDS_UPDATEREGISTRY, NULL);
}
}
}
这些代码都是直接摘抄自我的工程的,直接跑应该有问题,不过只看关键函数就够了