OSDN Git Service

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