comparison foosdk/wtl/Include/atlapp.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 // Windows Template Library - WTL version 10.0
2 // Copyright (C) Microsoft Corporation, WTL Team. All rights reserved.
3 //
4 // This file is a part of the Windows Template Library.
5 // The use and distribution terms for this software are covered by the
6 // Microsoft Public License (http://opensource.org/licenses/MS-PL)
7 // which can be found in the file MS-PL.txt at the root folder.
8
9 #ifndef __ATLAPP_H__
10 #define __ATLAPP_H__
11
12 #pragma once
13
14 #ifndef __cplusplus
15 #error WTL requires C++ compilation (use a .cpp suffix)
16 #endif
17
18 #ifndef __ATLBASE_H__
19 #error atlapp.h requires atlbase.h to be included first
20 #endif
21
22 #ifdef _WIN32_WCE
23 #error WTL10 doesn't support Windows CE
24 #endif
25
26 #ifdef _ATL_NO_COMMODULE
27 #error WTL requires that _ATL_NO_COMMODULE is not defined
28 #endif
29
30 #ifdef _ATL_NO_WIN_SUPPORT
31 #error WTL requires that _ATL_NO_WIN_SUPPORT is not defined
32 #endif
33
34 #if (_MSC_VER < 1400)
35 #error WTL10 requires C++ compiler version 14 (Visual C++ 2005) or higher
36 #endif
37
38 #if (WINVER < 0x0501)
39 #error WTL requires WINVER >= 0x0501
40 #endif
41
42 #if (_WIN32_WINNT < 0x0501)
43 #error WTL requires _WIN32_WINNT >= 0x0501
44 #endif
45
46 #if (_WIN32_IE < 0x0600)
47 #error WTL requires _WIN32_IE >= 0x0600
48 #endif
49
50 #if (_ATL_VER < 0x0800)
51 #error WTL10 requires ATL version 8 or higher
52 #endif
53
54 #ifdef _ATL_MIN_CRT
55 #error WTL10 doesn't support _ATL_MIN_CRT
56 #endif
57
58 #ifdef _ATL_NO_MSIMG
59 #error WTL10 doesn't support _ATL_NO_MSIMG
60 #endif
61
62 #include <limits.h>
63 #ifdef _MT
64 #include <process.h> // for _beginthreadex
65 #endif
66
67 #include <commctrl.h>
68 #pragma comment(lib, "comctl32.lib")
69
70 #include <commdlg.h>
71 #include <shellapi.h>
72
73 // Check for VS2005 without newer WinSDK
74 #if (_MSC_VER == 1400) && !defined(RB_GETEXTENDEDSTYLE)
75 #error WTL10 requires WinSDK 6.0 ot higher
76 #endif
77
78 #include <uxtheme.h>
79 #pragma comment(lib, "uxtheme.lib")
80
81 #if defined(_SYSINFOAPI_H_) && defined(NOT_BUILD_WINDOWS_DEPRECATE)
82 #include <VersionHelpers.h>
83 #endif
84
85 #include "atlres.h"
86
87
88 ///////////////////////////////////////////////////////////////////////////////
89 // WTL version number
90
91 #define _WTL_VER 0x1000 // version 10.0
92
93
94 ///////////////////////////////////////////////////////////////////////////////
95 // Classes in this file:
96 //
97 // CMessageFilter
98 // CIdleHandler
99 // CMessageLoop
100 //
101 // CAppModule
102 // CServerAppModule
103 //
104 // Global functions:
105 // AtlInitCommonControls()
106 // AtlGetDefaultGuiFont()
107 // AtlCreateControlFont()
108 // AtlCreateBoldFont()
109 // AtlGetStringPtr()
110
111
112 ///////////////////////////////////////////////////////////////////////////////
113 // Miscellaneous global support
114
115 // define useful macros from winuser.h
116 #ifndef IS_INTRESOURCE
117 #define IS_INTRESOURCE(_r) (((ULONG_PTR)(_r) >> 16) == 0)
118 #endif // IS_INTRESOURCE
119
120 // protect template members from windowsx.h macros
121 #ifdef _INC_WINDOWSX
122 #undef SubclassWindow
123 #endif // _INC_WINDOWSX
124
125 // define useful macros from windowsx.h
126 #ifndef GET_X_LPARAM
127 #define GET_X_LPARAM(lParam) ((int)(short)LOWORD(lParam))
128 #endif
129 #ifndef GET_Y_LPARAM
130 #define GET_Y_LPARAM(lParam) ((int)(short)HIWORD(lParam))
131 #endif
132
133 // Dummy structs for compiling with /CLR
134 #ifdef _MANAGED
135 __if_not_exists(_IMAGELIST::_IMAGELIST) { struct _IMAGELIST { }; }
136 __if_not_exists(_TREEITEM::_TREEITEM) { struct _TREEITEM { }; }
137 __if_not_exists(_PSP::_PSP) { struct _PSP { }; }
138 #endif
139
140 // Forward declaration for ATL11 fix
141 #if (_ATL_VER >= 0x0B00)
142 namespace ATL { HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor); }
143 #endif
144
145 #ifndef WM_MOUSEHWHEEL
146 #define WM_MOUSEHWHEEL 0x020E
147 #endif
148
149 // Used for stack allocations with ATL::CTempBuffer
150 #ifndef _WTL_STACK_ALLOC_THRESHOLD
151 #define _WTL_STACK_ALLOC_THRESHOLD 512
152 #endif
153
154
155 namespace WTL
156 {
157
158 DECLARE_TRACE_CATEGORY(atlTraceUI)
159 #ifdef _DEBUG
160 __declspec(selectany) ATL::CTraceCategory atlTraceUI(_T("atlTraceUI"));
161 #endif // _DEBUG
162
163 // Common Controls initialization helper
164 inline BOOL AtlInitCommonControls(DWORD dwFlags)
165 {
166 INITCOMMONCONTROLSEX iccx = { sizeof(INITCOMMONCONTROLSEX), dwFlags };
167 BOOL bRet = ::InitCommonControlsEx(&iccx);
168 ATLASSERT(bRet);
169 return bRet;
170 }
171
172 // Default GUI font helper - "MS Shell Dlg" stock font
173 inline HFONT AtlGetDefaultGuiFont()
174 {
175 return (HFONT)::GetStockObject(DEFAULT_GUI_FONT);
176 }
177
178 // Control font helper - default font for controls not in a dialog
179 // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
180 inline HFONT AtlCreateControlFont()
181 {
182 LOGFONT lf = {};
183 ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
184 HFONT hFont = ::CreateFontIndirect(&lf);
185 ATLASSERT(hFont != NULL);
186 return hFont;
187 }
188
189 // Bold font helper
190 // (NOTE: Caller owns the font, and should destroy it when it's no longer needed)
191 inline HFONT AtlCreateBoldFont(HFONT hFont = NULL)
192 {
193 LOGFONT lf = {};
194 if(hFont == NULL)
195 ATLVERIFY(::SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, 0) != FALSE);
196 else
197 ATLVERIFY(::GetObject(hFont, sizeof(LOGFONT), &lf) == sizeof(LOGFONT));
198 lf.lfWeight = FW_BOLD;
199 HFONT hFontBold = ::CreateFontIndirect(&lf);
200 ATLASSERT(hFontBold != NULL);
201 return hFontBold;
202 }
203
204 // Resource string pointer
205 inline LPCWSTR AtlGetStringPtr(UINT uID, int* pch = NULL)
206 {
207 LPCWSTR lpstr = NULL;
208 int nRet = ::LoadStringW(ATL::_AtlBaseModule.GetResourceInstance(), uID, (LPWSTR)&lpstr, 0);
209 if(pch != NULL)
210 *pch = nRet;
211 return lpstr;
212 }
213
214
215 ///////////////////////////////////////////////////////////////////////////////
216 // RunTimeHelper - helper functions for Windows version and structure sizes
217
218 #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
219
220 #ifndef _SIZEOF_STRUCT
221 #define _SIZEOF_STRUCT(structname, member) (((int)((LPBYTE)(&((structname*)0)->member) - ((LPBYTE)((structname*)0)))) + sizeof(((structname*)0)->member))
222 #endif
223
224 #if (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
225 #define REBARBANDINFO_V6_SIZE _SIZEOF_STRUCT(REBARBANDINFO, cxHeader)
226 #endif // (_WIN32_WINNT >= 0x0600) && !defined(REBARBANDINFO_V6_SIZE)
227
228 #if (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
229 #define LVGROUP_V5_SIZE _SIZEOF_STRUCT(LVGROUP, uAlign)
230 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVGROUP_V5_SIZE)
231
232 #if (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
233 #define LVTILEINFO_V5_SIZE _SIZEOF_STRUCT(LVTILEINFO, puColumns)
234 #endif // (_WIN32_WINNT >= 0x0600) && !defined(LVTILEINFO_V5_SIZE)
235
236 #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
237 #define MCHITTESTINFO_V1_SIZE _SIZEOF_STRUCT(MCHITTESTINFO, st)
238 #endif // defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN) && !defined(MCHITTESTINFO_V1_SIZE)
239
240 #if (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
241 #define NONCLIENTMETRICS_V1_SIZE _SIZEOF_STRUCT(NONCLIENTMETRICS, lfMessageFont)
242 #endif // (WINVER >= 0x0600) && !defined(NONCLIENTMETRICS_V1_SIZE)
243
244 #ifndef TTTOOLINFO_V2_SIZE
245 #define TTTOOLINFO_V2_SIZE _SIZEOF_STRUCT(TTTOOLINFO, lParam)
246 #endif
247
248 #endif // !_WTL_NO_RUNTIME_STRUCT_SIZE
249
250 namespace RunTimeHelper
251 {
252 inline bool IsCommCtrl6()
253 {
254 DWORD dwMajor = 0, dwMinor = 0;
255 HRESULT hRet = ATL::AtlGetCommCtrlVersion(&dwMajor, &dwMinor);
256 return (SUCCEEDED(hRet) && (dwMajor >= 6));
257 }
258
259 inline bool IsVista()
260 {
261 #ifdef _versionhelpers_H_INCLUDED_
262 return ::IsWindowsVistaOrGreater();
263 #else // !_versionhelpers_H_INCLUDED_
264 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
265 BOOL bRet = ::GetVersionEx(&ovi);
266 return ((bRet != FALSE) && (ovi.dwMajorVersion >= 6));
267 #endif // _versionhelpers_H_INCLUDED_
268 }
269
270 inline bool IsThemeAvailable()
271 {
272 return IsCommCtrl6() && (::IsThemeActive() != FALSE) && (::IsAppThemed() != FALSE);
273 }
274
275 inline bool IsWin7()
276 {
277 #ifdef _versionhelpers_H_INCLUDED_
278 return ::IsWindows7OrGreater();
279 #else // !_versionhelpers_H_INCLUDED_
280 OSVERSIONINFO ovi = { sizeof(OSVERSIONINFO) };
281 BOOL bRet = ::GetVersionEx(&ovi);
282 return ((bRet != FALSE) && ((ovi.dwMajorVersion > 6) || ((ovi.dwMajorVersion == 6) && (ovi.dwMinorVersion >= 1))));
283 #endif // _versionhelpers_H_INCLUDED_
284 }
285
286 inline bool IsRibbonUIAvailable()
287 {
288 static INT iRibbonUI = -1;
289
290 #if defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
291 if (iRibbonUI == -1)
292 {
293 HMODULE hRibbonDLL = ::LoadLibrary(_T("propsys.dll"));
294 if (hRibbonDLL != NULL)
295 {
296 const GUID CLSID_UIRibbonFramework = { 0x926749fa, 0x2615, 0x4987, { 0x88, 0x45, 0xc3, 0x3e, 0x65, 0xf2, 0xb9, 0x57 } };
297 // block - create instance
298 {
299 ATL::CComPtr<IUnknown> pIUIFramework;
300 iRibbonUI = SUCCEEDED(pIUIFramework.CoCreateInstance(CLSID_UIRibbonFramework)) ? 1 : 0;
301 }
302 ::FreeLibrary(hRibbonDLL);
303 }
304 else
305 {
306 iRibbonUI = 0;
307 }
308 }
309 #endif // defined(NTDDI_WIN7) && (NTDDI_VERSION >= NTDDI_WIN7)
310
311 return (iRibbonUI == 1);
312 }
313
314 inline UINT SizeOf_REBARBANDINFO()
315 {
316 UINT uSize = sizeof(REBARBANDINFO);
317 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
318 if(!(IsVista() && IsCommCtrl6()))
319 uSize = REBARBANDINFO_V6_SIZE;
320 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
321 return uSize;
322 }
323
324 inline UINT SizeOf_LVGROUP()
325 {
326 UINT uSize = sizeof(LVGROUP);
327 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
328 if(!IsVista())
329 uSize = LVGROUP_V5_SIZE;
330 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
331 return uSize;
332 }
333
334 inline UINT SizeOf_LVTILEINFO()
335 {
336 UINT uSize = sizeof(LVTILEINFO);
337 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
338 if(!IsVista())
339 uSize = LVTILEINFO_V5_SIZE;
340 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (_WIN32_WINNT >= 0x0600)
341 return uSize;
342 }
343
344 inline UINT SizeOf_MCHITTESTINFO()
345 {
346 UINT uSize = sizeof(MCHITTESTINFO);
347 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
348 if(!(IsVista() && IsCommCtrl6()))
349 uSize = MCHITTESTINFO_V1_SIZE;
350 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_LONGHORN)
351 return uSize;
352 }
353
354 inline UINT SizeOf_NONCLIENTMETRICS()
355 {
356 UINT uSize = sizeof(NONCLIENTMETRICS);
357 #if !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
358 if(!IsVista())
359 uSize = NONCLIENTMETRICS_V1_SIZE;
360 #endif // !defined(_WTL_NO_RUNTIME_STRUCT_SIZE) && (WINVER >= 0x0600)
361 return uSize;
362 }
363
364 inline UINT SizeOf_TOOLINFO()
365 {
366 UINT uSize = sizeof(TOOLINFO);
367 #ifndef _WTL_NO_RUNTIME_STRUCT_SIZE
368 if(!IsVista())
369 uSize = TTTOOLINFO_V2_SIZE;
370 #endif
371 return uSize;
372 }
373 } // namespace RunTimeHelper
374
375
376 ///////////////////////////////////////////////////////////////////////////////
377 // ModuleHelper - helper functions for ATL (deprecated)
378
379 namespace ModuleHelper
380 {
381 inline HINSTANCE GetModuleInstance()
382 {
383 return ATL::_AtlBaseModule.GetModuleInstance();
384 }
385
386 inline HINSTANCE GetResourceInstance()
387 {
388 return ATL::_AtlBaseModule.GetResourceInstance();
389 }
390
391 inline void AddCreateWndData(ATL::_AtlCreateWndData* pData, void* pObject)
392 {
393 ATL::_AtlWinModule.AddCreateWndData(pData, pObject);
394 }
395
396 inline void* ExtractCreateWndData()
397 {
398 return ATL::_AtlWinModule.ExtractCreateWndData();
399 }
400 } // namespace ModuleHelper
401
402
403 ///////////////////////////////////////////////////////////////////////////////
404 // SecureHelper - WTL10 requires use of secure functions
405 // these are here only for compatibility with existing projects
406
407 namespace SecureHelper
408 {
409 inline void strcpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
410 {
411 ATL::Checked::strcpy_s(lpstrDest, cchDest, lpstrSrc);
412 }
413
414 inline void strcpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
415 {
416 ATL::Checked::wcscpy_s(lpstrDest, cchDest, lpstrSrc);
417 }
418
419 inline void strcpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
420 {
421 #ifdef _UNICODE
422 strcpyW_x(lpstrDest, cchDest, lpstrSrc);
423 #else
424 strcpyA_x(lpstrDest, cchDest, lpstrSrc);
425 #endif
426 }
427
428 inline errno_t strncpyA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc, size_t cchCount)
429 {
430 return ATL::Checked::strncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
431 }
432
433 inline errno_t strncpyW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc, size_t cchCount)
434 {
435 return ATL::Checked::wcsncpy_s(lpstrDest, cchDest, lpstrSrc, cchCount);
436 }
437
438 inline errno_t strncpy_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc, size_t cchCount)
439 {
440 #ifdef _UNICODE
441 return strncpyW_x(lpstrDest, cchDest, lpstrSrc, cchCount);
442 #else
443 return strncpyA_x(lpstrDest, cchDest, lpstrSrc, cchCount);
444 #endif
445 }
446
447 inline void strcatA_x(char* lpstrDest, size_t cchDest, const char* lpstrSrc)
448 {
449 ATL::Checked::strcat_s(lpstrDest, cchDest, lpstrSrc);
450 }
451
452 inline void strcatW_x(wchar_t* lpstrDest, size_t cchDest, const wchar_t* lpstrSrc)
453 {
454 ATL::Checked::wcscat_s(lpstrDest, cchDest, lpstrSrc);
455 }
456
457 inline void strcat_x(LPTSTR lpstrDest, size_t cchDest, LPCTSTR lpstrSrc)
458 {
459 #ifdef _UNICODE
460 strcatW_x(lpstrDest, cchDest, lpstrSrc);
461 #else
462 strcatA_x(lpstrDest, cchDest, lpstrSrc);
463 #endif
464 }
465
466 inline void memcpy_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
467 {
468 ATL::Checked::memcpy_s(pDest, cbDest, pSrc, cbSrc);
469 }
470
471 inline void memmove_x(void* pDest, size_t cbDest, const void* pSrc, size_t cbSrc)
472 {
473 ATL::Checked::memmove_s(pDest, cbDest, pSrc, cbSrc);
474 }
475
476 inline int vsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
477 {
478 return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
479 }
480
481 inline int wvsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, va_list args)
482 {
483 return _vstprintf_s(lpstrBuff, cchBuff, lpstrFormat, args);
484 }
485
486 inline int sprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
487 {
488 va_list args;
489 va_start(args, lpstrFormat);
490 int nRes = vsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
491 va_end(args);
492 return nRes;
493 }
494
495 inline int wsprintf_x(LPTSTR lpstrBuff, size_t cchBuff, LPCTSTR lpstrFormat, ...)
496 {
497 va_list args;
498 va_start(args, lpstrFormat);
499 int nRes = wvsprintf_x(lpstrBuff, cchBuff, lpstrFormat, args);
500 va_end(args);
501 return nRes;
502 }
503 } // namespace SecureHelper
504
505
506 ///////////////////////////////////////////////////////////////////////////////
507 // MinCrtHelper - WTL10 doesn't support _ATL_MIN_CRT,
508 // these are here only for compatibility with existing projects
509
510 namespace MinCrtHelper
511 {
512 inline int _isspace(TCHAR ch)
513 {
514 return _istspace(ch);
515 }
516
517 inline int _isdigit(TCHAR ch)
518 {
519 return _istdigit(ch);
520 }
521
522 inline int _atoi(LPCTSTR str)
523 {
524 return _ttoi(str);
525 }
526
527 inline LPCTSTR _strrchr(LPCTSTR str, TCHAR ch)
528 {
529 return _tcsrchr(str, ch);
530 }
531
532 inline LPTSTR _strrchr(LPTSTR str, TCHAR ch)
533 {
534 return _tcsrchr(str, ch);
535 }
536 } // namespace MinCrtHelper
537
538
539 ///////////////////////////////////////////////////////////////////////////////
540 // GenericWndClass - generic window class usable for subclassing
541
542 // Use in dialog templates to specify a placeholder to be subclassed
543 // Specify as a custom control with class name WTL_GenericWindow
544 // Call Rregister() before creating dialog (for example, in WinMain)
545 namespace GenericWndClass
546 {
547 inline LPCTSTR GetName()
548 {
549 return _T("WTL_GenericWindow");
550 }
551
552 inline ATOM Register()
553 {
554 WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
555 wc.lpfnWndProc = ::DefWindowProc;
556 wc.hInstance = ModuleHelper::GetModuleInstance();
557 wc.hCursor = ::LoadCursor(NULL, IDC_ARROW);
558 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
559 wc.lpszClassName = GetName();
560 ATOM atom = ::RegisterClassEx(&wc);
561 ATLASSERT(atom != 0);
562 return atom;
563 }
564
565 inline BOOL Unregister() // only needed for DLLs or tmp use
566 {
567 return ::UnregisterClass(GetName(), ModuleHelper::GetModuleInstance());
568 }
569 } // namespace GenericWndClass
570
571
572 ///////////////////////////////////////////////////////////////////////////////
573 // CMessageFilter - Interface for message filter support
574
575 class CMessageFilter
576 {
577 public:
578 virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
579 };
580
581
582 ///////////////////////////////////////////////////////////////////////////////
583 // CIdleHandler - Interface for idle processing
584
585 class CIdleHandler
586 {
587 public:
588 virtual BOOL OnIdle() = 0;
589 };
590
591
592 ///////////////////////////////////////////////////////////////////////////////
593 // CMessageLoop - message loop implementation
594
595 class CMessageLoop
596 {
597 public:
598 ATL::CSimpleArray<CMessageFilter*> m_aMsgFilter;
599 ATL::CSimpleArray<CIdleHandler*> m_aIdleHandler;
600 MSG m_msg;
601
602 CMessageLoop()
603 { }
604
605 virtual ~CMessageLoop()
606 { }
607
608 // Message filter operations
609 BOOL AddMessageFilter(CMessageFilter* pMessageFilter)
610 {
611 return m_aMsgFilter.Add(pMessageFilter);
612 }
613
614 BOOL RemoveMessageFilter(CMessageFilter* pMessageFilter)
615 {
616 return m_aMsgFilter.Remove(pMessageFilter);
617 }
618
619 // Idle handler operations
620 BOOL AddIdleHandler(CIdleHandler* pIdleHandler)
621 {
622 return m_aIdleHandler.Add(pIdleHandler);
623 }
624
625 BOOL RemoveIdleHandler(CIdleHandler* pIdleHandler)
626 {
627 return m_aIdleHandler.Remove(pIdleHandler);
628 }
629
630 // message loop
631 int Run()
632 {
633 BOOL bDoIdle = TRUE;
634 int nIdleCount = 0;
635 BOOL bRet;
636
637 for(;;)
638 {
639 while(bDoIdle && !::PeekMessage(&m_msg, NULL, 0, 0, PM_NOREMOVE))
640 {
641 if(!OnIdle(nIdleCount++))
642 bDoIdle = FALSE;
643 }
644
645 bRet = ::GetMessage(&m_msg, NULL, 0, 0);
646
647 if(bRet == -1)
648 {
649 ATLTRACE2(atlTraceUI, 0, _T("::GetMessage returned -1 (error)\n"));
650 continue; // error, don't process
651 }
652 else if(!bRet)
653 {
654 ATLTRACE2(atlTraceUI, 0, _T("CMessageLoop::Run - exiting\n"));
655 break; // WM_QUIT, exit message loop
656 }
657
658 if(!PreTranslateMessage(&m_msg))
659 {
660 ::TranslateMessage(&m_msg);
661 ::DispatchMessage(&m_msg);
662 }
663
664 if(IsIdleMessage(&m_msg))
665 {
666 bDoIdle = TRUE;
667 nIdleCount = 0;
668 }
669 }
670
671 return (int)m_msg.wParam;
672 }
673
674 static BOOL IsIdleMessage(MSG* pMsg)
675 {
676 // These messages should NOT cause idle processing
677 switch(pMsg->message)
678 {
679 case WM_MOUSEMOVE:
680 case WM_NCMOUSEMOVE:
681 case WM_PAINT:
682 case 0x0118: // WM_SYSTIMER (caret blink)
683 return FALSE;
684 }
685
686 return TRUE;
687 }
688
689 // Overrideables
690 // Override to change message filtering
691 virtual BOOL PreTranslateMessage(MSG* pMsg)
692 {
693 // loop backwards
694 for(int i = m_aMsgFilter.GetSize() - 1; i >= 0; i--)
695 {
696 CMessageFilter* pMessageFilter = m_aMsgFilter[i];
697 if((pMessageFilter != NULL) && pMessageFilter->PreTranslateMessage(pMsg))
698 return TRUE;
699 }
700 return FALSE; // not translated
701 }
702
703 // override to change idle processing
704 virtual BOOL OnIdle(int /*nIdleCount*/)
705 {
706 for(int i = 0; i < m_aIdleHandler.GetSize(); i++)
707 {
708 CIdleHandler* pIdleHandler = m_aIdleHandler[i];
709 if(pIdleHandler != NULL)
710 pIdleHandler->OnIdle();
711 }
712 return FALSE; // don't continue
713 }
714 };
715
716
717 ///////////////////////////////////////////////////////////////////////////////
718 // CStaticDataInitCriticalSectionLock and CWindowCreateCriticalSectionLock
719 // internal classes to manage critical sections for ATL (deprecated)
720
721 class CStaticDataInitCriticalSectionLock
722 {
723 public:
724 ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
725
726 CStaticDataInitCriticalSectionLock() : m_cslock(ATL::_pAtlModule->m_csStaticDataInitAndTypeInfo, false)
727 { }
728
729 HRESULT Lock()
730 {
731 return m_cslock.Lock();
732 }
733
734 void Unlock()
735 {
736 m_cslock.Unlock();
737 }
738 };
739
740
741 class CWindowCreateCriticalSectionLock
742 {
743 public:
744 ATL::CComCritSecLock<ATL::CComCriticalSection> m_cslock;
745
746 CWindowCreateCriticalSectionLock() : m_cslock(ATL::_AtlWinModule.m_csWindowCreate, false)
747 { }
748
749 HRESULT Lock()
750 {
751 return m_cslock.Lock();
752 }
753
754 void Unlock()
755 {
756 m_cslock.Unlock();
757 }
758 };
759
760
761 ///////////////////////////////////////////////////////////////////////////////
762 // CAppModule - module class for an application
763
764 #if (_MSC_VER == 1400) // VS2005
765 #pragma warning(push)
766 #pragma warning(disable : 4244)
767 #pragma warning(disable : 4312)
768 #endif
769
770 class CAppModule : public ATL::CComModule
771 {
772 public:
773 DWORD m_dwMainThreadID;
774 ATL::CSimpleMap<DWORD, CMessageLoop*>* m_pMsgLoopMap;
775 ATL::CSimpleArray<HWND>* m_pSettingChangeNotify;
776
777 // Overrides of CComModule::Init and Term
778 HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
779 {
780 HRESULT hRet = CComModule::Init(pObjMap, hInstance, pLibID);
781 if(FAILED(hRet))
782 return hRet;
783
784 m_dwMainThreadID = ::GetCurrentThreadId();
785 typedef ATL::CSimpleMap<DWORD, CMessageLoop*> _mapClass;
786 m_pMsgLoopMap = NULL;
787 ATLTRY(m_pMsgLoopMap = new _mapClass);
788 if(m_pMsgLoopMap == NULL)
789 return E_OUTOFMEMORY;
790 m_pSettingChangeNotify = NULL;
791
792 return hRet;
793 }
794
795 void Term()
796 {
797 TermSettingChangeNotify();
798 delete m_pMsgLoopMap;
799 CComModule::Term();
800 }
801
802 // Message loop map methods
803 BOOL AddMessageLoop(CMessageLoop* pMsgLoop)
804 {
805 CStaticDataInitCriticalSectionLock lock;
806 if(FAILED(lock.Lock()))
807 {
808 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddMessageLoop.\n"));
809 ATLASSERT(FALSE);
810 return FALSE;
811 }
812
813 ATLASSERT(pMsgLoop != NULL);
814 ATLASSERT(m_pMsgLoopMap->Lookup(::GetCurrentThreadId()) == NULL); // not in map yet
815
816 BOOL bRet = m_pMsgLoopMap->Add(::GetCurrentThreadId(), pMsgLoop);
817
818 lock.Unlock();
819
820 return bRet;
821 }
822
823 BOOL RemoveMessageLoop()
824 {
825 CStaticDataInitCriticalSectionLock lock;
826 if(FAILED(lock.Lock()))
827 {
828 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveMessageLoop.\n"));
829 ATLASSERT(FALSE);
830 return FALSE;
831 }
832
833 BOOL bRet = m_pMsgLoopMap->Remove(::GetCurrentThreadId());
834
835 lock.Unlock();
836
837 return bRet;
838 }
839
840 CMessageLoop* GetMessageLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const
841 {
842 CStaticDataInitCriticalSectionLock lock;
843 if(FAILED(lock.Lock()))
844 {
845 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::GetMessageLoop.\n"));
846 ATLASSERT(FALSE);
847 return NULL;
848 }
849
850 CMessageLoop* pLoop = m_pMsgLoopMap->Lookup(dwThreadID);
851
852 lock.Unlock();
853
854 return pLoop;
855 }
856
857 // Setting change notify methods
858 // Note: Call this from the main thread for MSDI apps
859 BOOL InitSettingChangeNotify(DLGPROC pfnDlgProc = _SettingChangeDlgProc)
860 {
861 CStaticDataInitCriticalSectionLock lock;
862 if(FAILED(lock.Lock()))
863 {
864 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::InitSettingChangeNotify.\n"));
865 ATLASSERT(FALSE);
866 return FALSE;
867 }
868
869 if(m_pSettingChangeNotify == NULL)
870 {
871 typedef ATL::CSimpleArray<HWND> _notifyClass;
872 ATLTRY(m_pSettingChangeNotify = new _notifyClass);
873 ATLASSERT(m_pSettingChangeNotify != NULL);
874 }
875
876 BOOL bRet = (m_pSettingChangeNotify != NULL);
877 if(bRet && (m_pSettingChangeNotify->GetSize() == 0))
878 {
879 // init everything
880 _ATL_EMPTY_DLGTEMPLATE templ;
881 HWND hNtfWnd = ::CreateDialogIndirect(GetModuleInstance(), &templ, NULL, pfnDlgProc);
882 ATLASSERT(::IsWindow(hNtfWnd));
883 if(::IsWindow(hNtfWnd))
884 {
885 ::SetWindowLongPtr(hNtfWnd, GWLP_USERDATA, (LONG_PTR)this);
886 bRet = m_pSettingChangeNotify->Add(hNtfWnd);
887 }
888 else
889 {
890 bRet = FALSE;
891 }
892 }
893
894 lock.Unlock();
895
896 return bRet;
897 }
898
899 void TermSettingChangeNotify()
900 {
901 CStaticDataInitCriticalSectionLock lock;
902 if(FAILED(lock.Lock()))
903 {
904 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::TermSettingChangeNotify.\n"));
905 ATLASSERT(FALSE);
906 return;
907 }
908
909 if((m_pSettingChangeNotify != NULL) && (m_pSettingChangeNotify->GetSize() > 0))
910 ::DestroyWindow((*m_pSettingChangeNotify)[0]);
911 delete m_pSettingChangeNotify;
912 m_pSettingChangeNotify = NULL;
913
914 lock.Unlock();
915 }
916
917 BOOL AddSettingChangeNotify(HWND hWnd)
918 {
919 CStaticDataInitCriticalSectionLock lock;
920 if(FAILED(lock.Lock()))
921 {
922 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::AddSettingChangeNotify.\n"));
923 ATLASSERT(FALSE);
924 return FALSE;
925 }
926
927 ATLASSERT(::IsWindow(hWnd));
928 BOOL bRet = FALSE;
929 if(InitSettingChangeNotify() != FALSE)
930 bRet = m_pSettingChangeNotify->Add(hWnd);
931
932 lock.Unlock();
933
934 return bRet;
935 }
936
937 BOOL RemoveSettingChangeNotify(HWND hWnd)
938 {
939 CStaticDataInitCriticalSectionLock lock;
940 if(FAILED(lock.Lock()))
941 {
942 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CAppModule::RemoveSettingChangeNotify.\n"));
943 ATLASSERT(FALSE);
944 return FALSE;
945 }
946
947 BOOL bRet = FALSE;
948 if(m_pSettingChangeNotify != NULL)
949 bRet = m_pSettingChangeNotify->Remove(hWnd);
950
951 lock.Unlock();
952
953 return bRet;
954 }
955
956 // Implementation - setting change notify dialog template and dialog procedure
957 struct _ATL_EMPTY_DLGTEMPLATE : DLGTEMPLATE
958 {
959 _ATL_EMPTY_DLGTEMPLATE()
960 {
961 memset(this, 0, sizeof(_ATL_EMPTY_DLGTEMPLATE));
962 style = WS_POPUP;
963 }
964 WORD wMenu, wClass, wTitle;
965 };
966
967 static INT_PTR CALLBACK _SettingChangeDlgProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
968 {
969 if(uMsg == WM_SETTINGCHANGE)
970 {
971 CAppModule* pModule = (CAppModule*)::GetWindowLongPtr(hWnd, GWLP_USERDATA);
972 ATLASSERT(pModule != NULL);
973 ATLASSERT(pModule->m_pSettingChangeNotify != NULL);
974 const UINT uTimeout = 1500; // ms
975 for(int i = 1; i < pModule->m_pSettingChangeNotify->GetSize(); i++)
976 ::SendMessageTimeout((*pModule->m_pSettingChangeNotify)[i], uMsg, wParam, lParam, SMTO_ABORTIFHUNG, uTimeout, NULL);
977
978 return TRUE;
979 }
980
981 return FALSE;
982 }
983 };
984
985 #if (_MSC_VER == 1400) // VS2005
986 #pragma warning(pop)
987 #endif
988
989
990 ///////////////////////////////////////////////////////////////////////////////
991 // CServerAppModule - module class for a COM server application
992
993 class CServerAppModule : public CAppModule
994 {
995 public:
996 HANDLE m_hEventShutdown;
997 bool m_bActivity;
998 DWORD m_dwTimeOut;
999 DWORD m_dwPause;
1000
1001 // Override of CAppModule::Init
1002 HRESULT Init(ATL::_ATL_OBJMAP_ENTRY* pObjMap, HINSTANCE hInstance, const GUID* pLibID = NULL)
1003 {
1004 m_dwTimeOut = 5000;
1005 m_dwPause = 1000;
1006 return CAppModule::Init(pObjMap, hInstance, pLibID);
1007 }
1008
1009 void Term()
1010 {
1011 if((m_hEventShutdown != NULL) && ::CloseHandle(m_hEventShutdown))
1012 m_hEventShutdown = NULL;
1013 CAppModule::Term();
1014 }
1015
1016 // COM Server methods
1017 LONG Unlock() throw()
1018 {
1019 LONG lRet = CComModule::Unlock();
1020 if(lRet == 0)
1021 {
1022 m_bActivity = true;
1023 ::SetEvent(m_hEventShutdown); // tell monitor that we transitioned to zero
1024 }
1025 return lRet;
1026 }
1027
1028 void MonitorShutdown()
1029 {
1030 for(;;)
1031 {
1032 ::WaitForSingleObject(m_hEventShutdown, INFINITE);
1033 DWORD dwWait = 0;
1034 do
1035 {
1036 m_bActivity = false;
1037 dwWait = ::WaitForSingleObject(m_hEventShutdown, m_dwTimeOut);
1038 }
1039 while(dwWait == WAIT_OBJECT_0);
1040 // timed out
1041 if(!m_bActivity && (m_nLockCnt == 0)) // if no activity let's really bail
1042 {
1043 #if defined(_WIN32_DCOM) && defined(_ATL_FREE_THREADED)
1044 ::CoSuspendClassObjects();
1045 if(!m_bActivity && (m_nLockCnt == 0))
1046 #endif
1047 break;
1048 }
1049 }
1050 // This handle should be valid now. If it isn't,
1051 // check if _Module.Term was called first (it shouldn't)
1052 if(::CloseHandle(m_hEventShutdown))
1053 m_hEventShutdown = NULL;
1054 ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0);
1055 }
1056
1057 bool StartMonitor()
1058 {
1059 m_hEventShutdown = ::CreateEvent(NULL, false, false, NULL);
1060 if(m_hEventShutdown == NULL)
1061 return false;
1062 DWORD dwThreadID = 0;
1063 #ifdef _MT
1064 HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (UINT (WINAPI*)(void*))MonitorProc, this, 0, (UINT*)&dwThreadID);
1065 #else
1066 HANDLE hThread = ::CreateThread(NULL, 0, MonitorProc, this, 0, &dwThreadID);
1067 #endif
1068 bool bRet = (hThread != NULL);
1069 if(bRet)
1070 ::CloseHandle(hThread);
1071 return bRet;
1072 }
1073
1074 static DWORD WINAPI MonitorProc(void* pv)
1075 {
1076 CServerAppModule* p = (CServerAppModule*)pv;
1077 p->MonitorShutdown();
1078 return 0;
1079 }
1080 };
1081
1082
1083 ///////////////////////////////////////////////////////////////////////////////
1084 // CRegKeyEx - not used any more, here only for compatibility with old projects
1085
1086 typedef ATL::CRegKey CRegKeyEx;
1087
1088 } // namespace WTL
1089
1090
1091 ///////////////////////////////////////////////////////////////////////////////
1092 // CString forward reference (enables CString use in atluser.h and atlgdi.h)
1093
1094 #if (defined(_WTL_USE_CSTRING) || defined(_WTL_FORWARD_DECLARE_CSTRING)) && !defined(__ATLSTR_H__)
1095 #include <atlstr.h>
1096 #endif
1097
1098 // CString namespace
1099 #define _CSTRING_NS ATL
1100
1101 // Type classes namespace
1102 #define _WTYPES_NS
1103
1104
1105 ///////////////////////////////////////////////////////////////////////////////
1106 // General DLL version helpers (removed in ATL11)
1107
1108 #if (_ATL_VER >= 0x0B00)
1109
1110 namespace ATL
1111 {
1112
1113 inline HRESULT AtlGetDllVersion(HINSTANCE hInstDLL, DLLVERSIONINFO* pDllVersionInfo)
1114 {
1115 ATLASSERT(pDllVersionInfo != NULL);
1116 if(pDllVersionInfo == NULL)
1117 return E_INVALIDARG;
1118
1119 // We must get this function explicitly because some DLLs don't implement it.
1120 DLLGETVERSIONPROC pfnDllGetVersion = (DLLGETVERSIONPROC)::GetProcAddress(hInstDLL, "DllGetVersion");
1121 if(pfnDllGetVersion == NULL)
1122 return E_NOTIMPL;
1123
1124 return (*pfnDllGetVersion)(pDllVersionInfo);
1125 }
1126
1127 inline HRESULT AtlGetDllVersion(LPCTSTR lpstrDllName, DLLVERSIONINFO* pDllVersionInfo)
1128 {
1129 HINSTANCE hInstDLL = ::LoadLibrary(lpstrDllName);
1130 if(hInstDLL == NULL)
1131 return E_FAIL;
1132 HRESULT hRet = AtlGetDllVersion(hInstDLL, pDllVersionInfo);
1133 ::FreeLibrary(hInstDLL);
1134 return hRet;
1135 }
1136
1137 // Common Control Versions:
1138 // Win95/WinNT 4.0 maj=4 min=00
1139 // IE 3.x maj=4 min=70
1140 // IE 4.0 maj=4 min=71
1141 inline HRESULT AtlGetCommCtrlVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
1142 {
1143 ATLASSERT((pdwMajor != NULL) && (pdwMinor != NULL));
1144 if((pdwMajor == NULL) || (pdwMinor == NULL))
1145 return E_INVALIDARG;
1146
1147 DLLVERSIONINFO dvi;
1148 ::ZeroMemory(&dvi, sizeof(dvi));
1149 dvi.cbSize = sizeof(dvi);
1150 HRESULT hRet = AtlGetDllVersion(_T("comctl32.dll"), &dvi);
1151
1152 if(SUCCEEDED(hRet))
1153 {
1154 *pdwMajor = dvi.dwMajorVersion;
1155 *pdwMinor = dvi.dwMinorVersion;
1156 }
1157 else if(hRet == E_NOTIMPL)
1158 {
1159 // If DllGetVersion is not there, then the DLL is a version
1160 // previous to the one shipped with IE 3.x
1161 *pdwMajor = 4;
1162 *pdwMinor = 0;
1163 hRet = S_OK;
1164 }
1165
1166 return hRet;
1167 }
1168
1169 // Shell Versions:
1170 // Win95/WinNT 4.0 maj=4 min=00
1171 // IE 3.x, IE 4.0 without Web Integrated Desktop maj=4 min=00
1172 // IE 4.0 with Web Integrated Desktop maj=4 min=71
1173 // IE 4.01 with Web Integrated Desktop maj=4 min=72
1174 inline HRESULT AtlGetShellVersion(LPDWORD pdwMajor, LPDWORD pdwMinor)
1175 {
1176 ATLASSERT((pdwMajor != NULL) && (pdwMinor != NULL));
1177 if((pdwMajor == NULL) || (pdwMinor == NULL))
1178 return E_INVALIDARG;
1179
1180 DLLVERSIONINFO dvi;
1181 ::ZeroMemory(&dvi, sizeof(dvi));
1182 dvi.cbSize = sizeof(dvi);
1183 HRESULT hRet = AtlGetDllVersion(_T("shell32.dll"), &dvi);
1184
1185 if(SUCCEEDED(hRet))
1186 {
1187 *pdwMajor = dvi.dwMajorVersion;
1188 *pdwMinor = dvi.dwMinorVersion;
1189 }
1190 else if(hRet == E_NOTIMPL)
1191 {
1192 // If DllGetVersion is not there, then the DLL is a version
1193 // previous to the one shipped with IE 4.x
1194 *pdwMajor = 4;
1195 *pdwMinor = 0;
1196 hRet = S_OK;
1197 }
1198
1199 return hRet;
1200 }
1201
1202 } // namespace ATL
1203
1204 #endif // (_ATL_VER >= 0x0B00)
1205
1206
1207 // These are always included
1208 #include "atlwinx.h"
1209 #include "atluser.h"
1210 #include "atlgdi.h"
1211
1212 #ifndef _WTL_NO_AUTOMATIC_NAMESPACE
1213 using namespace WTL;
1214 #endif // !_WTL_NO_AUTOMATIC_NAMESPACE
1215
1216 #endif // __ATLAPP_H__