OSDN Git Service

change EOL style to CRLF to adjust to default setting of Visual Studio
[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   {\r
132 #ifdef MAYU64\r
133     LONG_PTR style = GetWindowLongPtr(i_hwnd, GWL_STYLE);\r
134 #else\r
135     LONG style = GetWindowLong(i_hwnd, GWL_STYLE);\r
136 #endif\r
137     if ((style & WS_CHILD) == 0)\r
138       break;\r
139     if (io_isMDI && *io_isMDI)\r
140     {\r
141 #ifdef MAYU64\r
142       LONG_PTR exStyle = GetWindowLongPtr(i_hwnd, GWL_EXSTYLE);\r
143 #else\r
144       LONG exStyle = GetWindowLong(i_hwnd, GWL_EXSTYLE);\r
145 #endif\r
146       if (exStyle & WS_EX_MDICHILD)\r
147         return i_hwnd;\r
148     }\r
149     i_hwnd = GetParent(i_hwnd);\r
150   }\r
151   if (io_isMDI)\r
152     *io_isMDI = false;\r
153   return i_hwnd;\r
154 }\r
155 \r
156 \r
157 // move window asynchronously\r
158 void asyncMoveWindow(HWND i_hwnd, int i_x, int i_y)\r
159 {\r
160   SetWindowPos(i_hwnd, NULL, i_x, i_y, 0, 0,\r
161                SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
162                SWP_NOSIZE | SWP_NOZORDER);\r
163 }\r
164 \r
165 \r
166 // move window asynchronously\r
167 void asyncMoveWindow(HWND i_hwnd, int i_x, int i_y, int i_w, int i_h)\r
168 {\r
169   SetWindowPos(i_hwnd, NULL, i_x, i_y, i_w, i_h,\r
170                SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
171                SWP_NOZORDER);\r
172 }\r
173 \r
174 \r
175 // resize asynchronously\r
176 void asyncResize(HWND i_hwnd, int i_w, int i_h)\r
177 {\r
178   SetWindowPos(i_hwnd, NULL, 0, 0, i_w, i_h,\r
179                SWP_ASYNCWINDOWPOS | SWP_NOACTIVATE | SWP_NOOWNERZORDER |\r
180                SWP_NOMOVE | SWP_NOZORDER);\r
181 }\r
182 \r
183 \r
184 // get dll version\r
185 DWORD getDllVersion(const _TCHAR *i_dllname)\r
186 {\r
187   DWORD dwVersion = 0;\r
188   \r
189   if (HINSTANCE hinstDll = LoadLibrary(i_dllname))\r
190   {\r
191     DLLGETVERSIONPROC pDllGetVersion\r
192       = (DLLGETVERSIONPROC)GetProcAddress(hinstDll, "DllGetVersion");\r
193     /* Because some DLLs may not implement this function, you\r
194      * must test for it explicitly. Depending on the particular \r
195      * DLL, the lack of a DllGetVersion function may\r
196      * be a useful indicator of the version.\r
197      */\r
198     if (pDllGetVersion)\r
199     {\r
200       DLLVERSIONINFO dvi;\r
201       ZeroMemory(&dvi, sizeof(dvi));\r
202       dvi.cbSize = sizeof(dvi);\r
203 \r
204       HRESULT hr = (*pDllGetVersion)(&dvi);\r
205       if (SUCCEEDED(hr))\r
206         dwVersion = PACKVERSION(dvi.dwMajorVersion, dvi.dwMinorVersion);\r
207     }\r
208         \r
209     FreeLibrary(hinstDll);\r
210   }\r
211   return dwVersion;\r
212 }\r
213 \r
214 \r
215 // workaround of SetForegroundWindow\r
216 bool setForegroundWindow(HWND i_hwnd)\r
217 {\r
218   int nForegroundID = GetWindowThreadProcessId(GetForegroundWindow(), NULL);\r
219   int nTargetID = GetWindowThreadProcessId(i_hwnd, NULL);\r
220   \r
221   //if (!AttachThreadInput(nTargetID, nForegroundID, TRUE))\r
222   //return false;\r
223   AttachThreadInput(nTargetID, nForegroundID, TRUE);\r
224 \r
225   DWORD sp_time;\r
226   SystemParametersInfo(SPI_GETFOREGROUNDLOCKTIMEOUT, 0, &sp_time, 0);\r
227   SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (void *)0, 0);\r
228 \r
229   SetForegroundWindow(i_hwnd);\r
230 \r
231   SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (void *)sp_time, 0);\r
232   \r
233   AttachThreadInput(nTargetID, nForegroundID, FALSE);\r
234   return true;\r
235 }\r
236 \r
237 \r
238 \r
239 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
240 // edit control\r
241 \r
242 \r
243 // get edit control's text size\r
244 // @return bytes of text\r
245 size_t editGetTextBytes(HWND i_hwnd)\r
246 {\r
247   return Edit_GetTextLength(i_hwnd);\r
248 }\r
249 \r
250 \r
251 // delete a line\r
252 void editDeleteLine(HWND i_hwnd, size_t i_n)\r
253 {\r
254   int len = Edit_LineLength(i_hwnd, i_n);\r
255   if (len < 0)\r
256     return;\r
257   len += 2;\r
258   int index = Edit_LineIndex(i_hwnd, i_n);\r
259   Edit_SetSel(i_hwnd, index, index + len);\r
260   Edit_ReplaceSel(i_hwnd, _T(""));\r
261 }\r
262   \r
263 \r
264 // insert text at last\r
265 void editInsertTextAtLast(HWND i_hwnd, const tstring &i_text,\r
266                           size_t i_threshold)\r
267 {\r
268   if (i_text.empty())\r
269     return;\r
270   \r
271   size_t len = editGetTextBytes(i_hwnd);\r
272   \r
273   if (i_threshold < len)\r
274   {\r
275     Edit_SetSel(i_hwnd, 0, len / 3 * 2);\r
276     Edit_ReplaceSel(i_hwnd, _T(""));\r
277     editDeleteLine(i_hwnd, 0);\r
278     len = editGetTextBytes(i_hwnd);\r
279   }\r
280   \r
281   Edit_SetSel(i_hwnd, len, len);\r
282   \r
283   // \n -> \r\n\r
284   Array<_TCHAR> buf(i_text.size() * 2 + 1);\r
285   _TCHAR *d = buf.get();\r
286   const _TCHAR *str = i_text.c_str();\r
287   for (const _TCHAR *s = str; s < str + i_text.size(); ++ s)\r
288   {\r
289     if (*s == _T('\n'))\r
290       *d++ = _T('\r');\r
291     *d++ = *s;\r
292   }\r
293   *d = _T('\0');\r
294   \r
295   Edit_ReplaceSel(i_hwnd, buf.get());\r
296 }\r
297 \r
298 \r
299 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
300 // Windows2000/XP specific API\r
301 \r
302 \r
303 // initialize layerd window\r
304 static BOOL WINAPI initalizeLayerdWindow(\r
305   HWND i_hwnd, COLORREF i_crKey, BYTE i_bAlpha, DWORD i_dwFlags)\r
306 {\r
307   HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
308   if (!hModule) {\r
309     return FALSE;\r
310   }\r
311   SetLayeredWindowAttributes_t proc = \r
312     reinterpret_cast<SetLayeredWindowAttributes_t>(\r
313       GetProcAddress(hModule, "SetLayeredWindowAttributes"));\r
314   if (setLayeredWindowAttributes) {\r
315     setLayeredWindowAttributes = proc;\r
316     return setLayeredWindowAttributes(i_hwnd, i_crKey, i_bAlpha, i_dwFlags);\r
317   } else {\r
318     return FALSE;\r
319   }\r
320 }\r
321 \r
322 \r
323 // SetLayeredWindowAttributes API\r
324 SetLayeredWindowAttributes_t setLayeredWindowAttributes\r
325   = initalizeLayerdWindow;\r
326 \r
327 \r
328 // emulate MonitorFromWindow API\r
329 static HMONITOR WINAPI emulateMonitorFromWindow(HWND hwnd, DWORD dwFlags)\r
330 {\r
331   return reinterpret_cast<HMONITOR>(1); // dummy HMONITOR\r
332 }\r
333 \r
334 // initialize MonitorFromWindow API\r
335 static HMONITOR WINAPI initializeMonitorFromWindow(HWND hwnd, DWORD dwFlags)\r
336 {\r
337   HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
338   if (!hModule)\r
339     return FALSE;\r
340 \r
341   FARPROC proc = GetProcAddress(hModule, "MonitorFromWindow");\r
342   if(proc)\r
343     monitorFromWindow =\r
344       reinterpret_cast<HMONITOR (WINAPI *)(HWND, DWORD)>(proc);\r
345   else\r
346     monitorFromWindow = emulateMonitorFromWindow;\r
347 \r
348   return monitorFromWindow(hwnd, dwFlags);\r
349 }\r
350 \r
351 // MonitorFromWindow API\r
352 HMONITOR (WINAPI *monitorFromWindow)(HWND hwnd, DWORD dwFlags)\r
353     = initializeMonitorFromWindow;\r
354 \r
355 \r
356 // emulate GetMonitorInfo API\r
357 static BOOL WINAPI emulateGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi)\r
358 {\r
359   if(lpmi->cbSize != sizeof(MONITORINFO))\r
360     return FALSE;\r
361 \r
362   lpmi->rcMonitor.left = 0;\r
363   lpmi->rcMonitor.top = 0;\r
364   lpmi->rcMonitor.right = GetSystemMetrics(SM_CXFULLSCREEN);\r
365   lpmi->rcMonitor.bottom = GetSystemMetrics(SM_CYFULLSCREEN);\r
366   SystemParametersInfo(SPI_GETWORKAREA, 0,\r
367                        reinterpret_cast<PVOID>(&lpmi->rcWork), FALSE);\r
368   lpmi->dwFlags = MONITORINFOF_PRIMARY;\r
369 \r
370   return TRUE;\r
371 }\r
372 \r
373 // initialize GetMonitorInfo API\r
374 static\r
375 BOOL WINAPI initializeGetMonitorInfo(HMONITOR hMonitor, LPMONITORINFO lpmi)\r
376 {\r
377   HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
378   if (!hModule)\r
379     return FALSE;\r
380 \r
381   FARPROC proc = GetProcAddress(hModule, "GetMonitorInfoA");\r
382   if(proc)\r
383     getMonitorInfo =\r
384       reinterpret_cast<BOOL (WINAPI *)(HMONITOR, LPMONITORINFO)>(proc);\r
385   else\r
386     getMonitorInfo = emulateGetMonitorInfo;\r
387 \r
388   return getMonitorInfo(hMonitor, lpmi);\r
389 }\r
390 \r
391 // GetMonitorInfo API\r
392 BOOL (WINAPI *getMonitorInfo)(HMONITOR hMonitor, LPMONITORINFO lpmi)\r
393   = initializeGetMonitorInfo;\r
394 \r
395 \r
396 // enumalte EnumDisplayMonitors API\r
397 static BOOL WINAPI emulateEnumDisplayMonitors(\r
398   HDC hdc, LPRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData)\r
399 {\r
400   lpfnEnum(reinterpret_cast<HMONITOR>(1), hdc, lprcClip, dwData);\r
401   return TRUE;\r
402 }\r
403 \r
404 // initialize EnumDisplayMonitors API\r
405 static BOOL WINAPI initializeEnumDisplayMonitors(\r
406   HDC hdc, LPRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData)\r
407 {\r
408   HMODULE hModule = GetModuleHandle(_T("user32.dll"));\r
409   if (!hModule)\r
410     return FALSE;\r
411 \r
412   FARPROC proc = GetProcAddress(hModule, "EnumDisplayMonitors");\r
413   if(proc)\r
414     enumDisplayMonitors =\r
415       reinterpret_cast<BOOL (WINAPI *)(HDC, LPRECT, MONITORENUMPROC, LPARAM)>\r
416       (proc);\r
417   else\r
418     enumDisplayMonitors = emulateEnumDisplayMonitors;\r
419 \r
420   return enumDisplayMonitors(hdc, lprcClip, lpfnEnum, dwData);\r
421 }\r
422 \r
423 // EnumDisplayMonitors API\r
424 BOOL (WINAPI *enumDisplayMonitors)\r
425     (HDC hdc, LPRECT lprcClip, MONITORENUMPROC lpfnEnum, LPARAM dwData)\r
426   = initializeEnumDisplayMonitors;\r
427 \r
428 \r
429 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
430 // Windows2000/XP specific API\r
431 \r
432 \r
433 static BOOL WINAPI\r
434 initializeWTSRegisterSessionNotification(HWND hWnd, DWORD dwFlags)\r
435 {\r
436   LoadLibrary(_T("wtsapi32.dll"));\r
437   HMODULE hModule = GetModuleHandle(_T("wtsapi32.dll"));\r
438   if (!hModule) {\r
439     return FALSE;\r
440   }\r
441   WTSRegisterSessionNotification_t proc = \r
442     reinterpret_cast<WTSRegisterSessionNotification_t>(\r
443       GetProcAddress(hModule, "WTSRegisterSessionNotification"));\r
444   if (proc) {\r
445     wtsRegisterSessionNotification = proc;\r
446     return wtsRegisterSessionNotification(hWnd, dwFlags);\r
447   } else {\r
448     return 0;\r
449   }\r
450 }\r
451 \r
452 // WTSRegisterSessionNotification API\r
453 WTSRegisterSessionNotification_t wtsRegisterSessionNotification\r
454   = initializeWTSRegisterSessionNotification;\r
455 \r
456 \r
457 static BOOL WINAPI initializeWTSUnRegisterSessionNotification(HWND hWnd)\r
458 {\r
459   HMODULE hModule = GetModuleHandle(_T("wtsapi32.dll"));\r
460   if (!hModule) {\r
461     return FALSE;\r
462   }\r
463   WTSUnRegisterSessionNotification_t proc = \r
464     reinterpret_cast<WTSUnRegisterSessionNotification_t>(\r
465       GetProcAddress(hModule, "WTSUnRegisterSessionNotification"));\r
466   if (proc) {\r
467     wtsUnRegisterSessionNotification = proc;\r
468     return wtsUnRegisterSessionNotification(hWnd);\r
469   } else {\r
470     return 0;\r
471   }\r
472 }\r
473 \r
474 // WTSUnRegisterSessionNotification API\r
475 WTSUnRegisterSessionNotification_t wtsUnRegisterSessionNotification\r
476   = initializeWTSUnRegisterSessionNotification;\r
477 \r
478 \r
479 static DWORD WINAPI initializeWTSGetActiveConsoleSessionId(void)\r
480 {\r
481   HMODULE hModule = GetModuleHandle(_T("kernel32.dll"));\r
482   if (!hModule) {\r
483     return FALSE;\r
484   }\r
485   WTSGetActiveConsoleSessionId_t proc = \r
486     reinterpret_cast<WTSGetActiveConsoleSessionId_t>(\r
487       GetProcAddress(hModule, "WTSGetActiveConsoleSessionId"));\r
488   if (proc) {\r
489     wtsGetActiveConsoleSessionId = proc;\r
490     return wtsGetActiveConsoleSessionId();\r
491   } else {\r
492     return 0;\r
493   }\r
494 }\r
495 \r
496 // WTSGetActiveConsoleSessionId API\r
497 WTSGetActiveConsoleSessionId_t wtsGetActiveConsoleSessionId\r
498   = initializeWTSGetActiveConsoleSessionId;\r
499 \r
500 \r
501 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
502 // Utility\r
503 \r
504 // PathRemoveFileSpec()\r
505 tstring pathRemoveFileSpec(const tstring &i_path)\r
506 {\r
507   const _TCHAR *str = i_path.c_str();\r
508   const _TCHAR *b = _tcsrchr(str, _T('\\'));\r
509   const _TCHAR *s = _tcsrchr(str, _T('/'));\r
510   if (b && s)\r
511     return tstring(str, MIN(b, s));\r
512   if (b)\r
513     return tstring(str, b);\r
514   if (s)\r
515     return tstring(str, s);\r
516   if (const _TCHAR *c = _tcsrchr(str, _T(':')))\r
517     return tstring(str, c + 1);\r
518   return i_path;\r
519 }\r