OSDN Git Service

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