OSDN Git Service

first commit
[dokopop/dokopop.git] / DCHook / MonitorScale.cpp
1 #include <windows.h>
2 #include <tchar.h>
3
4 #if WINVER<0x0601
5 #define QDC_ALL_PATHS                   0x00000001
6 #define QDC_ONLY_ACTIVE_PATHS           0x00000002
7 #define QDC_DATABASE_CURRENT            0x00000004
8 typedef enum
9 {
10     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_OTHER                   = -1,
11     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HD15                    =  0,
12     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SVIDEO                  =  1,
13     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPOSITE_VIDEO         =  2,
14     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_COMPONENT_VIDEO         =  3,
15     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DVI                     =  4,
16     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_HDMI                    =  5,
17     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_LVDS                    =  6,
18     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_D_JPN                   =  8,
19     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDI                     =  9,
20     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EXTERNAL    = 10,
21     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_DISPLAYPORT_EMBEDDED    = 11,
22     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EXTERNAL            = 12,
23     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_UDI_EMBEDDED            = 13,
24     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_SDTVDONGLE              = 14,
25     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_INTERNAL                = 0x80000000,
26     DISPLAYCONFIG_OUTPUT_TECHNOLOGY_FORCE_UINT32            = 0xFFFFFFFF
27 } DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY;
28 typedef enum
29 {
30     DISPLAYCONFIG_ROTATION_IDENTITY     = 1,
31     DISPLAYCONFIG_ROTATION_ROTATE90     = 2,
32     DISPLAYCONFIG_ROTATION_ROTATE180    = 3,
33     DISPLAYCONFIG_ROTATION_ROTATE270    = 4,
34     DISPLAYCONFIG_ROTATION_FORCE_UINT32 = 0xFFFFFFFF
35 } DISPLAYCONFIG_ROTATION;
36 typedef enum
37 {
38     DISPLAYCONFIG_SCALING_IDENTITY                  = 1,
39     DISPLAYCONFIG_SCALING_CENTERED                  = 2,
40     DISPLAYCONFIG_SCALING_STRETCHED                 = 3,
41     DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX    = 4,
42     DISPLAYCONFIG_SCALING_CUSTOM                    = 5,
43     DISPLAYCONFIG_SCALING_PREFERRED                 = 128,
44     DISPLAYCONFIG_SCALING_FORCE_UINT32              = 0xFFFFFFFF
45 } DISPLAYCONFIG_SCALING;
46 typedef struct DISPLAYCONFIG_RATIONAL
47 {
48     UINT32    Numerator;
49     UINT32    Denominator;
50 } DISPLAYCONFIG_RATIONAL;
51 typedef enum
52 {
53         DISPLAYCONFIG_SCANLINE_ORDERING_UNSPECIFIED                 = 0,
54         DISPLAYCONFIG_SCANLINE_ORDERING_PROGRESSIVE                 = 1,
55         DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED                  = 2,
56         DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_UPPERFIELDFIRST  = DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED,
57         DISPLAYCONFIG_SCANLINE_ORDERING_INTERLACED_LOWERFIELDFIRST  = 3,
58         DISPLAYCONFIG_SCANLINE_ORDERING_FORCE_UINT32                = 0xFFFFFFFF
59 } DISPLAYCONFIG_SCANLINE_ORDERING;
60 typedef enum
61 {
62     DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE = 1,
63     DISPLAYCONFIG_MODE_INFO_TYPE_TARGET = 2,
64     DISPLAYCONFIG_MODE_INFO_TYPE_FORCE_UINT32 = 0xFFFFFFFF
65 } DISPLAYCONFIG_MODE_INFO_TYPE;
66 typedef struct DISPLAYCONFIG_2DREGION
67 {
68     UINT32 cx;
69     UINT32 cy;
70 } DISPLAYCONFIG_2DREGION;
71 typedef struct DISPLAYCONFIG_VIDEO_SIGNAL_INFO
72 {
73         UINT64                          pixelRate;
74         DISPLAYCONFIG_RATIONAL          hSyncFreq;
75         DISPLAYCONFIG_RATIONAL          vSyncFreq;
76         DISPLAYCONFIG_2DREGION          activeSize;
77         DISPLAYCONFIG_2DREGION          totalSize;
78         UINT32                          videoStandard;
79         DISPLAYCONFIG_SCANLINE_ORDERING scanLineOrdering;
80 } DISPLAYCONFIG_VIDEO_SIGNAL_INFO;
81 typedef enum
82 {
83     DISPLAYCONFIG_PIXELFORMAT_8BPP          = 1,
84     DISPLAYCONFIG_PIXELFORMAT_16BPP         = 2,
85     DISPLAYCONFIG_PIXELFORMAT_24BPP         = 3,
86     DISPLAYCONFIG_PIXELFORMAT_32BPP         = 4,
87     DISPLAYCONFIG_PIXELFORMAT_NONGDI        = 5,
88     DISPLAYCONFIG_PIXELFORMAT_FORCE_UINT32  = 0xffffffff
89 } DISPLAYCONFIG_PIXELFORMAT;
90 typedef enum
91 {
92       DISPLAYCONFIG_TOPOLOGY_INTERNAL       = 0x00000001,
93       DISPLAYCONFIG_TOPOLOGY_CLONE          = 0x00000002,
94       DISPLAYCONFIG_TOPOLOGY_EXTEND         = 0x00000004,
95       DISPLAYCONFIG_TOPOLOGY_EXTERNAL       = 0x00000008,
96       DISPLAYCONFIG_TOPOLOGY_FORCE_UINT32   = 0xFFFFFFFF
97 } DISPLAYCONFIG_TOPOLOGY_ID;
98 typedef enum
99 {
100       DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME             = 1,
101       DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME             = 2,
102       DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_PREFERRED_MODE   = 3,
103       DISPLAYCONFIG_DEVICE_INFO_GET_ADAPTER_NAME            = 4,
104       DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_PERSISTENCE      = 5,
105       DISPLAYCONFIG_DEVICE_INFO_FORCE_UINT32                = 0xFFFFFFFF
106 } DISPLAYCONFIG_DEVICE_INFO_TYPE;
107
108 typedef struct DISPLAYCONFIG_PATH_SOURCE_INFO
109 {
110         LUID    adapterId;
111         UINT32  id;
112         UINT32  modeInfoIdx;
113         UINT32  statusFlags;
114 } DISPLAYCONFIG_PATH_SOURCE_INFO;
115 typedef struct DISPLAYCONFIG_PATH_TARGET_INFO
116 {
117         LUID                                    adapterId;
118         UINT32                                  id;
119         UINT32                                  modeInfoIdx;
120         DISPLAYCONFIG_VIDEO_OUTPUT_TECHNOLOGY   outputTechnology;
121         DISPLAYCONFIG_ROTATION                  rotation;
122         DISPLAYCONFIG_SCALING                   scaling;
123         DISPLAYCONFIG_RATIONAL                  refreshRate;
124         DISPLAYCONFIG_SCANLINE_ORDERING         scanLineOrdering;
125         BOOL                                    targetAvailable;
126         UINT32                                  statusFlags;
127 } DISPLAYCONFIG_PATH_TARGET_INFO;
128 typedef struct DISPLAYCONFIG_PATH_INFO
129 {
130         DISPLAYCONFIG_PATH_SOURCE_INFO  sourceInfo;
131         DISPLAYCONFIG_PATH_TARGET_INFO  targetInfo;
132         UINT32                          flags;
133 } DISPLAYCONFIG_PATH_INFO;
134 typedef struct DISPLAYCONFIG_TARGET_MODE
135 {
136     DISPLAYCONFIG_VIDEO_SIGNAL_INFO   targetVideoSignalInfo;
137 } DISPLAYCONFIG_TARGET_MODE;
138 typedef struct DISPLAYCONFIG_SOURCE_MODE
139 {
140     UINT32                      width;
141     UINT32                      height;
142     DISPLAYCONFIG_PIXELFORMAT   pixelFormat;
143     POINTL                      position;
144 } DISPLAYCONFIG_SOURCE_MODE;
145 typedef struct DISPLAYCONFIG_MODE_INFO
146 {
147         DISPLAYCONFIG_MODE_INFO_TYPE    infoType;
148         UINT32                          id;
149         LUID                            adapterId;
150         union
151         {
152                 DISPLAYCONFIG_TARGET_MODE   targetMode;
153                 DISPLAYCONFIG_SOURCE_MODE   sourceMode;
154         };
155 } DISPLAYCONFIG_MODE_INFO;
156 typedef struct DISPLAYCONFIG_DEVICE_INFO_HEADER
157 {
158         DISPLAYCONFIG_DEVICE_INFO_TYPE  type;
159         UINT32                          size;
160         LUID                            adapterId;
161         UINT32                          id;
162 } DISPLAYCONFIG_DEVICE_INFO_HEADER;
163
164 #endif
165
166 typedef WINUSERAPI LONG (WINAPI *FNGetDisplayConfigBufferSizes)(UINT32 flags, UINT32* numPathArrayElements, UINT32* numModeInfoArrayElements);
167 typedef WINUSERAPI LONG (WINAPI *FNSetDisplayConfig)(UINT32 numPathArrayElements, DISPLAYCONFIG_PATH_INFO* pathArray, UINT32 numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO* modeInfoArray, UINT32 flags);
168 typedef WINUSERAPI LONG (WINAPI *FNQueryDisplayConfig)(UINT32 flags, UINT32* numPathArrayElements, DISPLAYCONFIG_PATH_INFO* pathArray, UINT32* numModeInfoArrayElements, DISPLAYCONFIG_MODE_INFO* modeInfoArray, DISPLAYCONFIG_TOPOLOGY_ID* currentTopologyId);
169 typedef WINUSERAPI LONG (WINAPI *FNDisplayConfigGetDeviceInfo)(DISPLAYCONFIG_DEVICE_INFO_HEADER* requestPacket);
170
171 class TDllHandle {
172 protected:
173         HINSTANCE hInst;
174 public:
175         TDllHandle(HINSTANCE _hInst)
176                 :hInst(_hInst)
177         {
178         }
179         ~TDllHandle(){
180                 if (hInst) FreeLibrary(hInst);
181         }
182         HINSTANCE inst(){ return hInst; }
183         operator HINSTANCE (){ return hInst; }
184         FARPROC GetProcAddress(LPCSTR name)
185                 { return ::GetProcAddress(hInst, name); }
186 };
187
188 static TDllHandle *dllHandle = NULL;
189 static FNGetDisplayConfigBufferSizes _GetDisplayConfigBufferSizes;
190 static FNQueryDisplayConfig _QueryDisplayConfig;
191 static bool called = false;
192 static HMONITOR hPrevMonitor = NULL;
193 static int prevDpi = 0;
194 class TDestructor {
195 public:
196         ~TDestructor(){ if (dllHandle){ delete dllHandle; dllHandle = NULL; } }
197 } destructor;
198
199 int GetMonitorScale()
200 {
201         int dpi = 96;
202
203         if (!called){
204                 called = true;
205                 HINSTANCE hDll = LoadLibrary( _T("user32") );
206                 if (!hDll)
207                         return dpi;
208
209                 TDllHandle hInst(hDll);
210                 dllHandle = new TDllHandle(hDll);
211
212                 _GetDisplayConfigBufferSizes = (FNGetDisplayConfigBufferSizes)dllHandle->GetProcAddress("GetDisplayConfigBufferSizes");
213                 if (!_GetDisplayConfigBufferSizes) return dpi;
214                 _QueryDisplayConfig = (FNQueryDisplayConfig)dllHandle->GetProcAddress("QueryDisplayConfig");
215                 if (!_QueryDisplayConfig) return dpi;
216         }
217
218         if (!dllHandle) return dpi;
219
220         POINT pt;
221         GetCursorPos( &pt );
222         HMONITOR hMonitor = MonitorFromPoint( pt, MONITOR_DEFAULTTONULL );
223         if (!hMonitor) return dpi;
224
225         if (hMonitor == hPrevMonitor){
226                 return prevDpi;
227         }
228         hPrevMonitor = hMonitor;
229
230         MONITORINFOEX LogicalMonitorInfo;
231         LogicalMonitorInfo.cbSize = sizeof(MONITORINFOEX);
232         GetMonitorInfo(hMonitor, &LogicalMonitorInfo);
233         int LogicalMonitorWidth = LogicalMonitorInfo.rcMonitor.right - LogicalMonitorInfo.rcMonitor.left;
234
235         int LogicalDesktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
236
237         UINT32 numofpath;
238         UINT32 numofmode;
239         _GetDisplayConfigBufferSizes(QDC_DATABASE_CURRENT, &numofpath, &numofmode);
240
241         DISPLAYCONFIG_PATH_INFO *dpis = new DISPLAYCONFIG_PATH_INFO[numofpath];
242         DISPLAYCONFIG_MODE_INFO *pModeInfoArray = new DISPLAYCONFIG_MODE_INFO[numofmode];
243         DISPLAYCONFIG_TOPOLOGY_ID tid;
244         _QueryDisplayConfig(QDC_DATABASE_CURRENT, &numofpath, dpis, &numofmode, pModeInfoArray, &tid);  //TODO: Windows7 or later
245
246         int PhysicalDesktopWidth = LogicalDesktopWidth;
247         int PhysicalMonitorWidth = LogicalMonitorWidth;
248         
249         for (int i=0;i<(int)numofmode;i++){
250                 if (pModeInfoArray[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_SOURCE){
251                         //DBW("%d: %d", i, pModeInfoArray[i].sourceMode.width);
252                         PhysicalDesktopWidth = pModeInfoArray[i].sourceMode.width;
253                         //int PhysicalDesktopWidth = 
254                         //int ScaleFactor = (LogicalMonitorWidth/LogicalDesktopWidth) / (PhysicalMonitorWidth/PhysicalDesktopWidth)
255                         //return 96 * 1;
256                 } else
257                 if (pModeInfoArray[i].infoType == DISPLAYCONFIG_MODE_INFO_TYPE_TARGET){
258                         PhysicalMonitorWidth = pModeInfoArray[i].targetMode.targetVideoSignalInfo.activeSize.cx;
259                         //DBW("%d: %d", i, PhysicalMonitorWidth);
260                 }
261         }
262
263         //int PhysicalMonitorWidth = pModeInfoArray[i].sourceMode.width;
264         //int ScaleFactor = (LogicalMonitorWidth/LogicalDesktopWidth) / (PhysicalMonitorWidth/PhysicalDesktopWidth)
265
266         delete[] dpis;
267         delete[] pModeInfoArray;
268
269         return prevDpi = dpi * PhysicalDesktopWidth / LogicalDesktopWidth;
270 }