forked from imniko/SetDPI
-
Notifications
You must be signed in to change notification settings - Fork 0
/
DpiHelper.cpp
156 lines (128 loc) · 4.28 KB
/
DpiHelper.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#include "DpiHelper.h"
#include <memory>
#include <cassert>
bool DpiHelper::GetPathsAndModes(std::vector<DISPLAYCONFIG_PATH_INFO>& pathsV, std::vector<DISPLAYCONFIG_MODE_INFO>& modesV, int flags)
{
UINT32 numPaths = 0, numModes = 0;
auto status = GetDisplayConfigBufferSizes(flags, &numPaths, &numModes);
if (ERROR_SUCCESS != status)
{
return false;
}
std::unique_ptr<DISPLAYCONFIG_PATH_INFO[]> paths(new DISPLAYCONFIG_PATH_INFO[numPaths]);
std::unique_ptr<DISPLAYCONFIG_MODE_INFO[]> modes(new DISPLAYCONFIG_MODE_INFO[numModes]);
status = QueryDisplayConfig(flags, &numPaths, paths.get(), &numModes, modes.get(), nullptr);
if (ERROR_SUCCESS != status)
{
return false;
}
for (unsigned int i = 0; i < numPaths; i++)
{
pathsV.push_back(paths[i]);
}
for (unsigned int i = 0; i < numModes; i++)
{
modesV.push_back(modes[i]);
}
return true;
}
DpiHelper::DpiHelper()
{
}
DpiHelper::~DpiHelper()
{
}
DpiHelper::DPIScalingInfo DpiHelper::GetDPIScalingInfo(LUID adapterID, UINT32 sourceID)
{
DPIScalingInfo dpiInfo = {};
DpiHelper::DISPLAYCONFIG_SOURCE_DPI_SCALE_GET requestPacket = {};
requestPacket.header.type = (DISPLAYCONFIG_DEVICE_INFO_TYPE)DpiHelper::DISPLAYCONFIG_DEVICE_INFO_TYPE_CUSTOM::DISPLAYCONFIG_DEVICE_INFO_GET_DPI_SCALE;
requestPacket.header.size = sizeof(requestPacket);
assert(0x20 == sizeof(requestPacket));//if this fails => OS has changed somthing, and our reverse enginnering knowledge about the API is outdated
requestPacket.header.adapterId = adapterID;
requestPacket.header.id = sourceID;
auto res = ::DisplayConfigGetDeviceInfo(&requestPacket.header);
if (ERROR_SUCCESS == res)
{//success
if (requestPacket.curScaleRel < requestPacket.minScaleRel)
{
requestPacket.curScaleRel = requestPacket.minScaleRel;
}
else if (requestPacket.curScaleRel > requestPacket.maxScaleRel)
{
requestPacket.curScaleRel = requestPacket.maxScaleRel;
}
std::int32_t minAbs = abs((int)requestPacket.minScaleRel);
if (DpiHelper::CountOf(DpiVals) >= (size_t)(minAbs + requestPacket.maxScaleRel + 1))
{//all ok
dpiInfo.current = DpiVals[minAbs + requestPacket.curScaleRel];
dpiInfo.recommended = DpiVals[minAbs];
dpiInfo.maximum = DpiVals[minAbs + requestPacket.maxScaleRel];
dpiInfo.bInitDone = true;
}
else
{
//Error! Probably DpiVals array is outdated
return dpiInfo;
}
}
else
{
//DisplayConfigGetDeviceInfo() failed
return dpiInfo;
}
return dpiInfo;
}
bool DpiHelper::SetDPIScaling(LUID adapterID, UINT32 sourceID, UINT32 dpiPercentToSet)
{
DPIScalingInfo dPIScalingInfo = GetDPIScalingInfo(adapterID, sourceID);
if (dpiPercentToSet == dPIScalingInfo.current)
{
return true;
}
if (dpiPercentToSet < dPIScalingInfo.mininum)
{
dpiPercentToSet = dPIScalingInfo.mininum;
}
else if (dpiPercentToSet > dPIScalingInfo.maximum)
{
dpiPercentToSet = dPIScalingInfo.maximum;
}
int idx1 = -1, idx2 = -1;
int i = 0;
for (const auto& val : DpiVals)
{
if (val == dpiPercentToSet)
{
idx1 = i;
}
if (val == dPIScalingInfo.recommended)
{
idx2 = i;
}
i++;
}
if ((idx1 == -1) || (idx2 == -1))
{
//Error cannot find dpi value
return false;
}
int dpiRelativeVal = idx1 - idx2;
DpiHelper::DISPLAYCONFIG_SOURCE_DPI_SCALE_SET setPacket = {};
setPacket.header.adapterId = adapterID;
setPacket.header.id = sourceID;
setPacket.header.size = sizeof(setPacket);
assert(0x18 == sizeof(setPacket));//if this fails => OS has changed somthing, and our reverse enginnering knowledge about the API is outdated
setPacket.header.type = (DISPLAYCONFIG_DEVICE_INFO_TYPE)DpiHelper::DISPLAYCONFIG_DEVICE_INFO_TYPE_CUSTOM::DISPLAYCONFIG_DEVICE_INFO_SET_DPI_SCALE;
setPacket.scaleRel = (UINT32)dpiRelativeVal;
auto res = ::DisplayConfigSetDeviceInfo(&setPacket.header);
if (ERROR_SUCCESS == res)
{
return true;
}
else
{
return false;
}
return true;
}