OSDN Git Service

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