前面介绍了如何使用api更改widnows系统的分辨率。只能更改主屏幕分辨率,这节介绍如何更改多个屏幕的分辨率
要更改多个屏幕的分辨我们需要使用如下函数:
WINUSERAPI LONG WINAPI ChangeDisplaySettingsEx(
_In_opt_ LPCWSTR lpszDeviceName,
_In_opt_ DEVMODEW* lpDevMode,
_Reserved_ HWND hwnd,
_In_ DWORD dwflags,
_In_opt_ LPVOID lParam);
ChangeDisplaySettings函数虽然也有lpszDeviceName参数,但是经过测试并不生效,始终改变的是主屏的分辨率。
要更改屏幕分辨率我们需要枚举出这个屏幕支持的分辨率是多少,不支持的分辨率设置是会失败的。
QVector<DisplayInfo> MainWindow::enumSupportDisplayByScreenNumber(int screenNumber, int minDisplayWidth, int minDisplayHeight)
{
DEVMODE mode;
ZeroMemory(&mode, sizeof(mode));
mode.dmSize = sizeof(mode);
int i = 0;
QString deviceName = QApplication::screens()[screenNumber]->name();
bool result = EnumDisplaySettingsEx(deviceName.toStdWString().c_str(), i, &mode, 0);
QString str = "%1*%2";
QVector<DisplayInfo> ret;
while (result)
{
DisplayInfo info;
strcpy((char *)info.mode.dmDeviceName, deviceName.toStdString().c_str());
info.width = mode.dmPelsWidth;
info.height = mode.dmPelsHeight;
info.name = deviceName;
info.mode = mode;
qDebug()<<"ddddddd:"<<QString::fromWCharArray(mode.dmDeviceName);
if(!ret.contains(info) && mode.dmPelsWidth>= minDisplayWidth && mode.dmPelsHeight>=minDisplayHeight)
{
ret.push_back(info);
}
result = EnumDisplaySettingsEx(deviceName.toStdWString().c_str(), ++i, &mode, 0);
}
return ret;
}
该函数根据屏幕序号获取支持的分辨率并可以将太小的分辨率抛弃。DisplayInfo用于保存屏幕基本信息
struct DisplayInfo
{
int width;
int height;
QString name;
DEVMODE mode;
};
然后根据选择的屏幕需要进行分辨率更改
DisplayInfo info = findDisplayInfoByScreenNumber(ui->comboBox_2->currentText(), ui->comboBox->currentText());
DEVMODE lpDevMode = info.mode;
lpDevMode.dmPelsWidth=info.width;
lpDevMode.dmPelsHeight=info.height;
LONG result;
result=ChangeDisplaySettingsEx(info.name.toStdWString().c_str(), &lpDevMode,0, 0, 0);
if (result==DISP_CHANGE_SUCCESSFUL)
{
qDebug()<<QStringLiteral("修改成功!");
//使用CDS_UPDATEREGISTRY表示次修改是持久的
ChangeDisplaySettingsEx(info.name.toStdWString().c_str(), &lpDevMode,0, CDS_UPDATEREGISTRY, 0);
}
else
{
qDebug()<<QStringLiteral("修改失败,恢复原有设置!");
ChangeDisplaySettingsEx(info.name.toStdWString().c_str(), NULL,0, 0, 0);
}
完整代码:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <qt_windows.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
struct DisplayInfo
{
int width;
int height;
QString name;
DEVMODE mode;
};
bool operator==(const DisplayInfo info1, const DisplayInfo info2);
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pushButton_clicked();
void on_pushButton_2_clicked();
void slotscreennumberchanged(const QString &number);
private:
QVector<DisplayInfo> enumSupportDisplayByScreenNumber(int screenNumber, int minDisplayWidth = 800, int minDisplayHeight = 600);
DisplayInfo findDisplayInfoByScreenNumber(const QString screenNumber, const QString &display);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <qt_windows.h>
#include <QDebug>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QComboBox>
bool operator==(const DisplayInfo info1, const DisplayInfo info2)
{
return (info1.width == info2.width) && (info1.height == info2.height);
}
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->comboBox_2, SIGNAL(currentIndexChanged(QString)), this, SLOT(slotscreennumberchanged(QString)));
for(int i=0; i<QApplication::screens().count(); ++i)
ui->comboBox_2->addItem(QString::number(i));
slotscreennumberchanged(ui->comboBox_2->currentText());
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
DisplayInfo info = findDisplayInfoByScreenNumber(ui->comboBox_2->currentText(), ui->comboBox->currentText());
DEVMODE lpDevMode = info.mode;
lpDevMode.dmPelsWidth=info.width;
lpDevMode.dmPelsHeight=info.height;
LONG result;
result=ChangeDisplaySettingsEx(info.name.toStdWString().c_str(), &lpDevMode,0, 0, 0);
if (result==DISP_CHANGE_SUCCESSFUL)
{
qDebug()<<QStringLiteral("修改成功!");
//使用CDS_UPDATEREGISTRY表示次修改是持久的
ChangeDisplaySettingsEx(info.name.toStdWString().c_str(), &lpDevMode,0, CDS_UPDATEREGISTRY, 0);
}
else
{
qDebug()<<QStringLiteral("修改失败,恢复原有设置!");
ChangeDisplaySettingsEx(info.name.toStdWString().c_str(), NULL,0, 0, 0);
}
}
QVector<DisplayInfo> MainWindow::enumSupportDisplayByScreenNumber(int screenNumber, int minDisplayWidth, int minDisplayHeight)
{
DEVMODE mode;
ZeroMemory(&mode, sizeof(mode));
mode.dmSize = sizeof(mode);
int i = 0;
QString deviceName = QApplication::screens()[screenNumber]->name();
bool result = EnumDisplaySettingsEx(deviceName.toStdWString().c_str(), i, &mode, 0);
QString str = "%1*%2";
QVector<DisplayInfo> ret;
while (result)
{
DisplayInfo info;
strcpy((char *)info.mode.dmDeviceName, deviceName.toStdString().c_str());
info.width = mode.dmPelsWidth;
info.height = mode.dmPelsHeight;
info.name = deviceName;
info.mode = mode;
qDebug()<<"ddddddd:"<<QString::fromWCharArray(mode.dmDeviceName);
if(!ret.contains(info) && mode.dmPelsWidth>= minDisplayWidth && mode.dmPelsHeight>=minDisplayHeight)
{
ret.push_back(info);
}
result = EnumDisplaySettingsEx(deviceName.toStdWString().c_str(), ++i, &mode, 0);
}
return ret;
}
DisplayInfo MainWindow::findDisplayInfoByScreenNumber(const QString screenNumber, const QString &display)
{
QVector<DisplayInfo> rets = enumSupportDisplayByScreenNumber(screenNumber.toInt(), 800, 600);
foreach(DisplayInfo info, rets)
{
QString str = QString::number(info.width) + "*" + QString::number(info.height);
if(display == str)
return info;
}
return DisplayInfo();
}
void MainWindow::on_pushButton_2_clicked()
{
enumSupportDisplayByScreenNumber(1, 800, 600);
}
void MainWindow::slotscreennumberchanged(const QString &number)
{
ui->comboBox->clear();
QVector<DisplayInfo> rets = enumSupportDisplayByScreenNumber(number.toInt(), 800, 600);
foreach(DisplayInfo str, rets)
{
ui->comboBox->addItem(QString::number(str.width) + "*" + QString::number(str.height));
}
}