OSDN Git Service

enable command notify on x64
[yamy/yamy.git] / windowstool.cpp
1 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
2 // windowstool.cpp\r
3 \r
4 \r
5 #include "misc.h"\r
6 \r
7 #include "windowstool.h"\r
8 #include "array.h"\r
9 \r
10 #include <windowsx.h>\r
11 #include <malloc.h>\r
12 #include <shlwapi.h>\r
13 \r
14 \r
15 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
16 // Global variables\r
17 \r
18 \r
19 // instance handle of this application\r
20 HINSTANCE g_hInst = NULL;\r
21 \r
22 \r
23 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
24 // Functions\r
25 \r
26 \r
27 // load resource string\r
28 tstring loadString(UINT i_id)\r
29 {\r
30         _TCHAR buf[1024];\r
31         if (LoadString(g_hInst, i_id, buf, NUMBER_OF(buf)))\r
32                 return tstring(buf);\r
33         else\r
34                 return _T("");\r
35 }\r
36 \r
37 \r
38 // load small icon resource\r
39 HICON loadSmallIcon(UINT i_id)\r
40 {\r
41         return reinterpret_cast<HICON>(\r
42                            LoadImage(g_hInst, MAKEINTRESOURCE(i_id), IMAGE_ICON, 16, 16, 0));\r
43 }\r
44 \r
45 \r
46 // load big icon resource\r
47 HICON loadBigIcon(UINT i_id)\r
48 {\r
49         return reinterpret_cast<HICON>(\r
50                            LoadImage(g_hInst, MAKEINTRESOURCE(i_id), IMAGE_ICON, 32, 32, 0));\r
51 }\r
52 \r
53 \r
54 // set small icon to the specified window.\r
55 // @return handle of previous icon or NULL\r
56 HICON setSmallIcon(HWND i_hwnd, UINT i_id)\r
57 {\r
58         HICON hicon = (i_id == static_cast<UINT>(-1)) ? NULL : loadSmallIcon(i_id);\r
59         return reinterpret_cast<HICON>(\r
60                            SendMessage(i_hwnd, WM_SETICON, static_cast<WPARAM>(ICON_SMALL),\r
61                                                    reinterpret_cast<LPARAM>(hicon)));\r
62 }\r
63 \r
64 \r
65 // set big icon to the specified window.\r
66 // @return handle of previous icon or NULL\r
67 HICON setBigIcon(HWND i_hwnd, UINT i_id)\r
68 {\r
69         HICON hicon = (i_id == static_cast<UINT>(-1)) ? NULL : loadBigIcon(i_id);\r
70         return reinterpret_cast<HICON>(\r
71                            SendMessage(i_hwnd, WM_SETICON, static_cast<WPARAM>(ICON_BIG),\r
72                                                    reinterpret_cast<LPARAM>(hicon)));\r
73 }\r
74 \r
75 \r
76 // remove icon from a window that is set by setSmallIcon\r
77 void unsetSmallIcon(HWND i_hwnd)\r
78 {\r
79         HICON hicon = setSmallIcon(i_hwnd, -1);\r
80         if (hicon)\r
81                 CHECK_TRUE( DestroyIcon(hicon) );\r
82 }\r
83 \r
84 \r
85 // remove icon from a window that is set by setBigIcon\r
86 void unsetBigIcon(HWND i_hwnd)\r
87 {\r
88         HICON hicon = setBigIcon(i_hwnd, -1);\r
89         if (hicon)\r
90                 CHECK_TRUE( DestroyIcon(hicon) );\r
91 }\r
92 \r
93 \r
94 // resize the window (it does not move the window)\r
95 bool resizeWindow(HWND i_hwnd, int i_w, int i_h, bool i_doRepaint)\r
96 {\r
97         UINT flag = SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;\r
98         if (!i_doRepaint)\r
99                 flag |= SWP_NOREDRAW;\r
100         return !!SetWindowPos(i_hwnd, NULL, 0, 0, i_w, i_h, flag);\r
101 }\r
102 \r
103 \r
104 // get rect of the window in client coordinates\r
105 // @return rect of the window in client coordinates\r
106 bool getChildWindowRect(HWND i_hwnd, RECT *o_rc)\r
107 {\r
108         if (!GetWindowRect(i_hwnd, o_rc))\r
109                 return false;\r
110         POINT p = { o_rc->left, o_rc->top };\r
111         HWND phwnd = GetParent(i_hwnd);\r
112         if (!phwnd)\r
113                 return false;\r
114         if (!ScreenToClient(phwnd, &p))\r
115                 return false;\r
116         o_rc->left = p.x;\r
117         o_rc->top = p.y;\r
118         p.x = o_rc->right;\r
119         p.y = o_rc->bottom;\r
120         ScreenToClient(phwnd, &p);\r
121         o_rc->right = p.x;\r
122         o_rc->bottom = p.y;\r
123         return true;\r
124 }\r
125 \r
126 \r
127 // get toplevel (non-child) window\r
128 HWND getToplevelWindow(HWND i_hwnd, bool *io_isMDI)\r
129 {\r
130         while (i_hwnd) {\r
131 #ifdef MAYU64\r
132                 LONG_PTR style = GetWindowLongPtr(i_hwnd, GWL_STYLE);\r
133 #else\r
134                 LONG style = GetWindowLong(i_hwnd, GWL_STYLE);\r
135 #endif\r
136                 if ((style & WS_CHILD) == 0)\r
137                         break;\r
138                 if (io_isMDI && *io_isMDI) {\r
139 #ifdef MAYU64\r
140                         LONG_PTR exStyle = GetWindowLongPtr(i_hwnd, GWL_EXSTYLE);\r
141 #else\r
142                         LONG exStyle = GetWindowLong(i_hwnd, GWL_EXSTYLE);\r
143 #endif\r
144                         if (exStyle & WS_EX_MDICHILD)\r
145                                 return i_hwnd;\r
146                 }\r
147                 i_hwnd = GetParent(i_hwnd);\r
148         }\r
149         if (io_isMDI)\r
150                 *io_isMDI = false;\r
151         return i_hwnd;\r
152 }\r
153 \r
154 \r
155 // move window asynchronously\r
156 void asyncMoveWindow(HWND i_hwnd, int i_x, int i_y)\r
157 {\r
158         SetWindowPos(i_hwnd, NULL, i_x, i_y, 0, 0,\r
159                                  SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
160                                  SWP_NOSIZE | SWP_NOZORDER);\r
161 }\r
162 \r
163 \r
164 // move window asynchronously\r
165 void asyncMoveWindow(HWND i_hwnd, int i_x, int i_y, int i_w, int i_h)\r
166 {\r
167         SetWindowPos(i_hwnd, NULL, i_x, i_y, i_w, i_h,\r
168                                  SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
169                                  SWP_NOZORDER);\r
170 }\r
171 \r
172 \r
173 // resize asynchronously\r
174 void asyncResize(HWND i_hwnd, int i_w, int i_h)\r
175 {\r
176         SetWindowPos(i_hwnd, NULL, 0, 0, i_w, i_h,\r
177                                  SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
178                                  SWP_NOMOVE | SWP_NOZORDER);\r
179 }\r
180 \r
181 \r
182 // get dll version\r
183 DWORD getDllVersion(const _TCHAR *i_dllname)\r
184 {\r
185         DWORD dwVersion = 0;\r
186 \r
187         if (HINSTANCE hinstDll = LoadLibrary(i_dllname)) {\r
188                 DLLGETVERSIONPROC pDllGetVersion\r
189                 = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");\r
190                 /* Because some DLLs may not implement this function, you\r
191                  * must test for it explicitly. Depending on the particular\r
192                  * DLL, the lack of a DllGetVersion function may\r
193                  * be a useful indicator of the version.\r
194                  */\r
195                 if (pDllGetVersion) {\r
196                         DLLVERSIONINFO dvi;\r
197                         ZeroMemory(&dvi, sizeof(dvi));\r
198                         dvi.cbSize = sizeof(dvi);\r
199 \r
200                         HRESULT hr = (*pDllGetVersion)(&dvi);\r
201                         if (SUCCEEDED(hr))\r
202                                 dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);\r
203                 }\r
204 \r
205                 FreeLibrary(hinstDll);\r
206         }\r
207         return dwVersion;\r
208 }\r
209 \r
210 \r
211 // workaround of SetForegroundWindow\r
212 bool setForegroundWindow(HWND i_hwnd)\r
213 {\r
214         int nForegroundID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);\r
215         int nTargetID = GetWindowThreadProcessId(i_hwnd, NULL);\r
216 \r
217         //if (!AttachThreadInput(nTargetID, nForegroundID, TRUE))\r
218         //return false;\r
219         AttachThreadInput(nTargetID, nForegroundID, TRUE);\r
220 \r
221         DWORD sp_time;\r
222         SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &sp_time, 0);\r
223         SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (void *)0, 0);\r
224 \r
225         SetForegroundWindow(i_hwnd);\r
226 \r
227         SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (void *)sp_time, 0);\r
228 \r
229         AttachThreadInput(nTargetID, nForegroundID, FALSE);\r
230         return true;\r
231 }\r
232 \r
233 \r
234 \r
235 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
236 // edit control\r
237 \r
238 \r
239 // get edit control's text size\r
240 // @return bytes of text\r
241 size_t editGetTextBytes(HWND i_hwnd)\r
242 {\r
243         return Edit_GetTextLength(i_hwnd);\r
244 }\r
245 \r
246 \r
247 // delete a line\r
248 void editDeleteLine(HWND i_hwnd, size_t i_n)\r
249 {\r
250         int len = Edit_LineLength(i_hwnd, i_n);\r
251         if (len < 0)\r
252                 return;\r
253         len += 2;\r
254         int index = Edit_LineIndex(i_hwnd, i_n);\r
255         Edit_SetSel(i_hwnd, index, index + len);\r
256         Edit_ReplaceSel(i_hwnd, _T(""));\r
257 }\r
258 \r
259 \r
260 // insert text at last\r
261 void editInsertTextAtLast(HWND i_hwnd, const tstring &i_text,\r
262                                                   size_t i_threshold)\r
263 {\r
264         if (i_text.empty())\r
265                 return;\r
266 \r
267         size_t len = editGetTextBytes(i_hwnd);\r
268 \r
269         if (i_threshold < len) {\r
270                 Edit_SetSel(i_hwnd, 0, len / 3 * 2);\r
271                 Edit_ReplaceSel(i_hwnd, _T(""));\r
272                 editDeleteLine(i_hwnd, 0);\r
273                 len = editGetTextBytes(i_hwnd);\r
274         }\r
275 \r
276         Edit_SetSel(i_hwnd, len, len);\r
277 \r
278         // \n -> \r\n\r
279         Array<_TCHAR> buf(i_text.size() * 2 + 1);\r
280         _TCHAR *d = buf.get();\r
281         const _TCHAR *str = i_text.c_str();\r
282         for (const _TCHAR *s = str; s < str + i_text.size(); ++ s) {\r
283                 if (*s == _T('\n'))\r
284                         *d++ = _T('\r');\r
285                 *d++ = *s;\r
286         }\r
287         *d = _T('\0');\r
288 \r
289         Edit_ReplaceSel(i_hwnd, buf.get());\r
290 }\r
291 \r
292 \r
293 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
294 // Windows2000/XP specific API\r
295 \r
296 \r
297 // initialize layerd window\r
298 static BOOL WINAPI initalizeLayerdWindow(\r
299         HWND i_hwnd, COLORREF i_crKey, BYTE i_bAlpha, DWORD i_dwFlags)\r
300 {\r
301         HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
302         if (!hModule) {\r
303                 return FALSE;\r
304         }\r
305         SetLayeredWindowAttributes_t proc =\r
306                 reinterpret_cast<SetLayeredWindowAttributes_t>(\r
307                         GetProcAddress(hModule, "SetLayeredWindowAttributes"));\r
308         if (setLayeredWindowAttributes) {\r
309                 setLayeredWindowAttributes = proc;\r
310                 return setLayeredWindowAttributes(i_hwnd, i_crKey, i_bAlpha, i_dwFlags);\r
311         } else {\r
312                 return FALSE;\r
313         }\r
314 }\r
315 \r
316 \r
317 // SetLayeredWindowAttributes API\r
318 SetLayeredWindowAttributes_t setLayeredWindowAttributes\r
319 = initalizeLayerdWindow;\r
320 \r
321 \r
322 // emulate MonitorFromWindow API\r
323 static HMONITOR WINAPI emulateMonitorFromWindow(HWND hwnd, DWORD dwFlags)\r
324 {\r
325         return reinterpret_cast<HMONITOR>(1); // dummy HMONITOR\r
326 }\r
327 \r
328 // initialize MonitorFromWindow API\r
329 static HMONITOR WINAPI initializeMonitorFromWindow(HWND hwnd, DWORD dwFlags)\r
330 {\r
331         HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
332         if (!hModule)\r
333                 return FALSE;\r
334 \r
335         FARPROC proc = GetProcAddress(hModule, "MonitorFromWindow");\r
336         if (proc)\r
337                 monitorFromWindow =\r
338                         reinterpret_cast<HMONITOR (WINAPI *)(HWND, DWORD)>(proc);\r
339         else\r
340                 monitorFromWindow = emulateMonitorFromWindow;\r
341 \r
342         return monitorFromWindow(hwnd, dwFlags);\r
343 }\r
344 \r
345 // MonitorFromWindow API\r
346 HMONITOR (WINAPI *monitorFromWindow)(HWND hwnd, DWORD dwFlags)\r
347 = initializeMonitorFromWindow;\r
348 \r
349 \r
350 // emulate GetMonitorInfo API\r
351 static BOOL WINAPI emulateGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi)\r
352 {\r
353         if (lpmi->cbSize != sizeof(MONITORINFO))\r
354                 return FALSE;\r
355 \r
356         lpmi->rcMonitor.left = 0;\r
357         lpmi->rcMonitor.top = 0;\r
358         lpmi->rcMonitor.right = GetSystemMetrics(SM_CXFULLSCREEN);\r
359         lpmi->rcMonitor.bottom = GetSystemMetrics(SM_CYFULLSCREEN);\r
360         SystemParametersInfo(SPI_GETWORKAREA, 0,\r
361                                                  reinterpret_cast<PVOID>(&lpmi->rcWork), FALSE);\r
362         lpmi->dwFlags = MONITORINFOF_PRIMARY;\r
363 \r
364         return TRUE;\r
365 }\r
366 \r
367 // initialize GetMonitorInfo API\r
368 static\r
369 BOOL WINAPI initializeGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi)\r
370 {\r
371         HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
372         if (!hModule)\r
373                 return FALSE;\r
374 \r
375         FARPROC proc = GetProcAddress(hModule, "GetMonitorInfoA");\r
376         if (proc)\r
377                 getMonitorInfo =\r
378                         reinterpret_cast<BOOL (WINAPI *)(HMONITOR, LPMONITORINFO)>(proc);\r
379         else\r
380                 getMonitorInfo = emulateGetMonitorInfo;\r
381 \r
382         return getMonitorInfo(hMonitor, lpmi);\r
383 }\r
384 \r
385 // GetMonitorInfo API\r
386 BOOL (WINAPI *getMonitorInfo)(HMONITOR hMonitor, LPMONITORINFO lpmi)\r
387 = initializeGetMonitorInfo;\r
388 \r
389 \r
390 // enumalte EnumDisplayMonitors API\r
391 static BOOL WINAPI emulateEnumDisplayMonitors(\r
392         HDC hdc, LPRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData)\r
393 {\r
394         lpfnEnum(reinterpret_cast<HMONITOR>(1), hdc, lprcClip, dwData);\r
395         return TRUE;\r
396 }\r
397 \r
398 // initialize EnumDisplayMonitors API\r
399 static BOOL WINAPI initializeEnumDisplayMonitors(\r
400         HDC hdc, LPRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData)\r
401 {\r
402         HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
403         if (!hModule)\r
404                 return FALSE;\r
405 \r
406         FARPROC proc = GetProcAddress(hModule, "EnumDisplayMonitors");\r
407         if (proc)\r
408                 enumDisplayMonitors =\r
409                         reinterpret_cast<BOOL (WINAPI *)(HDC, LPRECT, MONITORENUMPROC, LPARAM)>\r
410                         (proc);\r
411         else\r
412                 enumDisplayMonitors = emulateEnumDisplayMonitors;\r
413 \r
414         return enumDisplayMonitors(hdc, lprcClip, lpfnEnum, dwData);\r
415 }\r
416 \r
417 // EnumDisplayMonitors API\r
418 BOOL (WINAPI *enumDisplayMonitors)\r
419 (HDC hdc, LPRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData)\r
420 = initializeEnumDisplayMonitors;\r
421 \r
422 \r
423 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
424 // Windows2000/XP specific API\r
425 \r
426 \r
427 static BOOL WINAPI\r
428 initializeWTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)\r
429 {\r
430         LoadLibrary(_T("wtsapi32.dll"));\r
431         HMODULE hModule = GetModuleHandle(_T("wtsapi32.dll"));\r
432         if (!hModule) {\r
433                 return FALSE;\r
434         }\r
435         WTSRegisterSessionNotification_t proc =\r
436                 reinterpret_cast<WTSRegisterSessionNotification_t>(\r
437                         GetProcAddress(hModule, "WTSRegisterSessionNotification"));\r
438         if (proc) {\r
439                 wtsRegisterSessionNotification = proc;\r
440                 return wtsRegisterSessionNotification(hWnd, dwFlags);\r
441         } else {\r
442                 return 0;\r
443         }\r
444 }\r
445 \r
446 // WTSRegisterSessionNotification API\r
447 WTSRegisterSessionNotification_t wtsRegisterSessionNotification\r
448 = initializeWTSRegisterSessionNotification;\r
449 \r
450 \r
451 static BOOL WINAPI initializeWTSUnRegisterSessionNotification(HWND hWnd)\r
452 {\r
453         HMODULE hModule = GetModuleHandle(_T("wtsapi32.dll"));\r
454         if (!hModule) {\r
455                 return FALSE;\r
456         }\r
457         WTSUnRegisterSessionNotification_t proc =\r
458                 reinterpret_cast<WTSUnRegisterSessionNotification_t>(\r
459                         GetProcAddress(hModule, "WTSUnRegisterSessionNotification"));\r
460         if (proc) {\r
461                 wtsUnRegisterSessionNotification = proc;\r
462                 return wtsUnRegisterSessionNotification(hWnd);\r
463         } else {\r
464                 return 0;\r
465         }\r
466 }\r
467 \r
468 // WTSUnRegisterSessionNotification API\r
469 WTSUnRegisterSessionNotification_t wtsUnRegisterSessionNotification\r
470 = initializeWTSUnRegisterSessionNotification;\r
471 \r
472 \r
473 static DWORD WINAPI initializeWTSGetActiveConsoleSessionId(void)\r
474 {\r
475         HMODULE hModule = GetModuleHandle(_T("kernel32.dll"));\r
476         if (!hModule) {\r
477                 return FALSE;\r
478         }\r
479         WTSGetActiveConsoleSessionId_t proc =\r
480                 reinterpret_cast<WTSGetActiveConsoleSessionId_t>(\r
481                         GetProcAddress(hModule, "WTSGetActiveConsoleSessionId"));\r
482         if (proc) {\r
483                 wtsGetActiveConsoleSessionId = proc;\r
484                 return wtsGetActiveConsoleSessionId();\r
485         } else {\r
486                 return 0;\r
487         }\r
488 }\r
489 \r
490 // WTSGetActiveConsoleSessionId API\r
491 WTSGetActiveConsoleSessionId_t wtsGetActiveConsoleSessionId\r
492 = initializeWTSGetActiveConsoleSessionId;\r
493 \r
494 \r
495 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
496 // Utility\r
497 \r
498 // PathRemoveFileSpec()\r
499 tstring pathRemoveFileSpec(const tstring &i_path)\r
500 {\r
501         const _TCHAR *str = i_path.c_str();\r
502         const _TCHAR *b = _tcsrchr(str, _T('\\'));\r
503         const _TCHAR *s = _tcsrchr(str, _T('/'));\r
504         if (b && s)\r
505                 return tstring(str, MIN(b, s));\r
506         if (b)\r
507                 return tstring(str, b);\r
508         if (s)\r
509                 return tstring(str, s);\r
510         if (const _TCHAR *c = _tcsrchr(str, _T(':')))\r
511                 return tstring(str, c + 1);\r
512         return i_path;\r
513 }\r
514 \r
515 BOOL checkWindowsVersion(DWORD i_major, DWORD i_minor)\r
516 {\r
517     DWORDLONG conditionMask = 0;\r
518     OSVERSIONINFOEX osvi;\r
519         memset(&osvi, 0, sizeof(OSVERSIONINFOEX));\r
520 \r
521     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);\r
522     osvi.dwMajorVersion = i_major;\r
523     osvi.dwMinorVersion = i_minor;\r
524 \r
525     VER_SET_CONDITION(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);\r
526     VER_SET_CONDITION(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);\r
527 \r
528     // Perform the test.\r
529     return VerifyVersionInfo(&osvi, VER_MAJORVERSION | VER_MINORVERSION, conditionMask);\r
530 }\r