OLD | NEW |
| (Empty) |
1 // Windows Template Library - WTL version 8.0 | |
2 // Copyright (C) Microsoft Corporation. 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 Permissive License (Ms-PL) which can be found in the file | |
7 // Ms-PL.txt at the root of this distribution. | |
8 | |
9 #ifndef __ATLFRAME_H__ | |
10 #define __ATLFRAME_H__ | |
11 | |
12 #pragma once | |
13 | |
14 #ifndef __cplusplus | |
15 #error ATL requires C++ compilation (use a .cpp suffix) | |
16 #endif | |
17 | |
18 #ifndef __ATLAPP_H__ | |
19 #error atlframe.h requires atlapp.h to be included first | |
20 #endif | |
21 | |
22 #ifndef __ATLWIN_H__ | |
23 #error atlframe.h requires atlwin.h to be included first | |
24 #endif | |
25 | |
26 | |
27 /////////////////////////////////////////////////////////////////////////////// | |
28 // Classes in this file: | |
29 // | |
30 // CFrameWindowImpl<T, TBase, TWinTraits> | |
31 // CMDIWindow | |
32 // CMDIFrameWindowImpl<T, TBase, TWinTraits> | |
33 // CMDIChildWindowImpl<T, TBase, TWinTraits> | |
34 // COwnerDraw<T> | |
35 // CUpdateUIBase | |
36 // CUpdateUI<T> | |
37 // CDynamicUpdateUI<T> | |
38 // CDialogResize<T> | |
39 // CDoubleBufferImpl<T> | |
40 // CDoubleBufferWindowImpl<T, TBase, TWinTraits> | |
41 // | |
42 // Global functions: | |
43 // AtlCreateSimpleToolBar() | |
44 | |
45 | |
46 namespace WTL | |
47 { | |
48 | |
49 /////////////////////////////////////////////////////////////////////////////// | |
50 // CFrameWndClassInfo - Manages frame window Windows class information | |
51 | |
52 class CFrameWndClassInfo | |
53 { | |
54 public: | |
55 #ifndef _WIN32_WCE | |
56 enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is
the number of digits %p outputs | |
57 WNDCLASSEX m_wc; | |
58 #else // CE specific | |
59 enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set i
n the wizard generated CMainFrame::ActivatePreviousInstance to a user defined st
ring. | |
60 WNDCLASS m_wc; | |
61 #endif // !_WIN32_WCE | |
62 LPCTSTR m_lpszOrigName; | |
63 WNDPROC pWndProc; | |
64 LPCTSTR m_lpszCursorID; | |
65 BOOL m_bSystemCursor; | |
66 ATOM m_atom; | |
67 TCHAR m_szAutoName[cchAutoName]; | |
68 UINT m_uCommonResourceID; | |
69 | |
70 #ifndef _WIN32_WCE | |
71 ATOM Register(WNDPROC* pProc) | |
72 { | |
73 if (m_atom == 0) | |
74 { | |
75 CWindowCreateCriticalSectionLock lock; | |
76 if(FAILED(lock.Lock())) | |
77 { | |
78 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CFrameWndClassInfo::Register.\n")); | |
79 ATLASSERT(FALSE); | |
80 return 0; | |
81 } | |
82 | |
83 if(m_atom == 0) | |
84 { | |
85 HINSTANCE hInst = ModuleHelper::GetModuleInstanc
e(); | |
86 | |
87 if (m_lpszOrigName != NULL) | |
88 { | |
89 ATLASSERT(pProc != NULL); | |
90 LPCTSTR lpsz = m_wc.lpszClassName; | |
91 WNDPROC proc = m_wc.lpfnWndProc; | |
92 | |
93 WNDCLASSEX wc = { 0 }; | |
94 wc.cbSize = sizeof(WNDCLASSEX); | |
95 // try process local class first | |
96 if(!::GetClassInfoEx(ModuleHelper::GetMo
duleInstance(), m_lpszOrigName, &wc)) | |
97 { | |
98 // try global class | |
99 if(!::GetClassInfoEx(NULL, m_lps
zOrigName, &wc)) | |
100 { | |
101 lock.Unlock(); | |
102 return 0; | |
103 } | |
104 } | |
105 m_wc = wc; | |
106 pWndProc = m_wc.lpfnWndProc; | |
107 m_wc.lpszClassName = lpsz; | |
108 m_wc.lpfnWndProc = proc; | |
109 } | |
110 else | |
111 { | |
112 m_wc.hCursor = ::LoadCursor(m_bSystemCur
sor ? NULL : hInst, m_lpszCursorID); | |
113 } | |
114 | |
115 m_wc.hInstance = hInst; | |
116 m_wc.style &= ~CS_GLOBALCLASS; // we don't reg
ister global classes | |
117 if (m_wc.lpszClassName == NULL) | |
118 { | |
119 #if (_WIN32_WINNT >= 0x0500) || defined(_WIN64) | |
120 SecureHelper::wsprintf_x(m_szAutoName, c
chAutoName, _T("ATL:%p"), &m_wc); | |
121 #else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) | |
122 SecureHelper::wsprintf_x(m_szAutoName, c
chAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc); | |
123 #endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64)) | |
124 m_wc.lpszClassName = m_szAutoName; | |
125 } | |
126 | |
127 WNDCLASSEX wcTemp = m_wc; | |
128 m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance,
m_wc.lpszClassName, &wcTemp); | |
129 if (m_atom == 0) | |
130 { | |
131 if(m_uCommonResourceID != 0) // use it
if not zero | |
132 { | |
133 m_wc.hIcon = (HICON)::LoadImage(
ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE
_ICON, 32, 32, LR_DEFAULTCOLOR); | |
134 m_wc.hIconSm = (HICON)::LoadImag
e(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMA
GE_ICON, 16, 16, LR_DEFAULTCOLOR); | |
135 } | |
136 m_atom = ::RegisterClassEx(&m_wc); | |
137 } | |
138 } | |
139 | |
140 lock.Unlock(); | |
141 } | |
142 | |
143 if (m_lpszOrigName != NULL) | |
144 { | |
145 ATLASSERT(pProc != NULL); | |
146 ATLASSERT(pWndProc != NULL); | |
147 *pProc = pWndProc; | |
148 } | |
149 | |
150 return m_atom; | |
151 } | |
152 #else // CE specific | |
153 ATOM Register(WNDPROC* pProc) | |
154 { | |
155 if (m_atom == 0) | |
156 { | |
157 CWindowCreateCriticalSectionLock lock; | |
158 if(FAILED(lock.Lock())) | |
159 { | |
160 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to l
ock critical section in CFrameWndClassInfo::Register.\n")); | |
161 ATLASSERT(FALSE); | |
162 return 0; | |
163 } | |
164 | |
165 if(m_atom == 0) | |
166 { | |
167 HINSTANCE hInst = ModuleHelper::GetModuleInstanc
e(); | |
168 | |
169 if (m_lpszOrigName != NULL) | |
170 { | |
171 ATLASSERT(pProc != NULL); | |
172 LPCTSTR lpsz = m_wc.lpszClassName; | |
173 WNDPROC proc = m_wc.lpfnWndProc; | |
174 | |
175 WNDCLASS wc = { 0 }; | |
176 // try process local class first | |
177 if(!::GetClassInfo(ModuleHelper::GetModu
leInstance(), m_lpszOrigName, &wc)) | |
178 { | |
179 // try global class | |
180 if(!::GetClassInfo(NULL, m_lpszO
rigName, &wc)) | |
181 { | |
182 lock.Unlock(); | |
183 return 0; | |
184 } | |
185 } | |
186 m_wc = wc; | |
187 pWndProc = m_wc.lpfnWndProc; | |
188 m_wc.lpszClassName = lpsz; | |
189 m_wc.lpfnWndProc = proc; | |
190 } | |
191 else | |
192 { | |
193 #if defined(GWES_CURSOR) || defined(GWES_MCURSOR) | |
194 m_wc.hCursor = ::LoadCursor(m_bSystemCur
sor ? NULL : hInst, m_lpszCursorID); | |
195 #else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) | |
196 m_wc.hCursor = NULL; | |
197 #endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR)) | |
198 } | |
199 | |
200 m_wc.hInstance = hInst; | |
201 m_wc.style &= ~CS_GLOBALCLASS; // we don't reg
ister global classes | |
202 if (m_wc.lpszClassName == NULL) | |
203 { | |
204 wsprintf(m_szAutoName, _T("ATL:%8.8X"),
(DWORD_PTR)&m_wc); | |
205 m_wc.lpszClassName = m_szAutoName; | |
206 } | |
207 | |
208 WNDCLASS wcTemp = m_wc; | |
209 m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_
wc.lpszClassName, &wcTemp); | |
210 if (m_atom == 0) | |
211 { | |
212 if(m_uCommonResourceID != 0) // use it
if not zero | |
213 m_wc.hIcon = (HICON)::LoadImage(
ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE
_ICON, 32, 32, LR_DEFAULTCOLOR); | |
214 m_atom = ::RegisterClass(&m_wc); | |
215 } | |
216 } | |
217 | |
218 lock.Unlock(); | |
219 } | |
220 | |
221 if (m_lpszOrigName != NULL) | |
222 { | |
223 ATLASSERT(pProc != NULL); | |
224 ATLASSERT(pWndProc != NULL); | |
225 *pProc = pWndProc; | |
226 } | |
227 | |
228 return m_atom; | |
229 } | |
230 #endif // _WIN32_WCE | |
231 }; | |
232 | |
233 | |
234 /////////////////////////////////////////////////////////////////////////////// | |
235 // Macros for declaring frame window WNDCLASS | |
236 | |
237 #ifndef _WIN32_WCE | |
238 | |
239 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ | |
240 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
241 { \ | |
242 static WTL::CFrameWndClassInfo wc = \ | |
243 { \ | |
244 { sizeof(WNDCLASSEX), 0, StartWindowProc, \ | |
245 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndC
lassName, NULL }, \ | |
246 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
247 }; \ | |
248 return wc; \ | |
249 } | |
250 | |
251 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd
) \ | |
252 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
253 { \ | |
254 static WTL::CFrameWndClassInfo wc = \ | |
255 { \ | |
256 { sizeof(WNDCLASSEX), style, StartWindowProc, \ | |
257 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassNam
e, NULL }, \ | |
258 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
259 }; \ | |
260 return wc; \ | |
261 } | |
262 | |
263 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonReso
urceID) \ | |
264 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
265 { \ | |
266 static WTL::CFrameWndClassInfo wc = \ | |
267 { \ | |
268 { sizeof(WNDCLASSEX), 0, StartWindowProc, \ | |
269 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \ | |
270 OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID
\ | |
271 }; \ | |
272 return wc; \ | |
273 } | |
274 | |
275 #else // CE specific | |
276 | |
277 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \ | |
278 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
279 { \ | |
280 static WTL::CFrameWndClassInfo wc = \ | |
281 { \ | |
282 { 0, StartWindowProc, \ | |
283 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndC
lassName }, \ | |
284 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
285 }; \ | |
286 return wc; \ | |
287 } | |
288 | |
289 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd
) \ | |
290 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
291 { \ | |
292 static WTL::CFrameWndClassInfo wc = \ | |
293 { \ | |
294 { style, StartWindowProc, \ | |
295 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassNam
e }, \ | |
296 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \ | |
297 }; \ | |
298 return wc; \ | |
299 } | |
300 | |
301 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonReso
urceID) \ | |
302 static WTL::CFrameWndClassInfo& GetWndClassInfo() \ | |
303 { \ | |
304 static WTL::CFrameWndClassInfo wc = \ | |
305 { \ | |
306 { NULL, StartWindowProc, \ | |
307 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \ | |
308 OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResou
rceID \ | |
309 }; \ | |
310 return wc; \ | |
311 } | |
312 | |
313 #endif // !_WIN32_WCE | |
314 | |
315 | |
316 /////////////////////////////////////////////////////////////////////////////// | |
317 // CFrameWindowImpl | |
318 | |
319 // Client window command chaining macro (only for frame windows) | |
320 #define CHAIN_CLIENT_COMMANDS() \ | |
321 if(uMsg == WM_COMMAND && m_hWndClient != NULL) \ | |
322 ::SendMessage(m_hWndClient, uMsg, wParam, lParam); | |
323 | |
324 // standard toolbar styles | |
325 #define ATL_SIMPLE_TOOLBAR_STYLE \ | |
326 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOO
LTIPS) | |
327 // toolbar in a rebar pane | |
328 #define ATL_SIMPLE_TOOLBAR_PANE_STYLE \ | |
329 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVID
ER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT) | |
330 // standard rebar styles | |
331 #if (_WIN32_IE >= 0x0400) | |
332 #define ATL_SIMPLE_REBAR_STYLE \ | |
333 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE) | |
334 #else | |
335 #define ATL_SIMPLE_REBAR_STYLE \ | |
336 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
RBS_VARHEIGHT | RBS_BANDBORDERS) | |
337 #endif // !(_WIN32_IE >= 0x0400) | |
338 // rebar without borders | |
339 #if (_WIN32_IE >= 0x0400) | |
340 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ | |
341 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIG
HT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER) | |
342 #else | |
343 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \ | |
344 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIG
HT | RBS_BANDBORDERS | CCS_NODIVIDER) | |
345 #endif // !(_WIN32_IE >= 0x0400) | |
346 | |
347 // command bar support | |
348 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
349 | |
350 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar H
WND | |
351 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or att
ached menu | |
352 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu | |
353 | |
354 struct _AtlFrameWnd_CmdBarPopupMenu | |
355 { | |
356 int cbSize; | |
357 HMENU hMenu; | |
358 UINT uFlags; | |
359 int x; | |
360 int y; | |
361 LPTPMPARAMS lptpm; | |
362 }; | |
363 | |
364 #define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu | |
365 | |
366 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
367 | |
368 | |
369 template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits> | |
370 class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase,
TWinTraits > | |
371 { | |
372 public: | |
373 DECLARE_FRAME_WND_CLASS(NULL, 0) | |
374 | |
375 // Data members | |
376 HWND m_hWndToolBar; | |
377 HWND m_hWndStatusBar; | |
378 HWND m_hWndClient; | |
379 | |
380 HACCEL m_hAccel; | |
381 | |
382 #ifdef _WIN32_WCE | |
383 HWND m_hWndCECommandBar; | |
384 #endif // _WIN32_WCE | |
385 | |
386 struct _AtlToolBarData | |
387 { | |
388 WORD wVersion; | |
389 WORD wWidth; | |
390 WORD wHeight; | |
391 WORD wItemCount; | |
392 //WORD aItems[wItemCount] | |
393 | |
394 WORD* items() | |
395 { return (WORD*)(this+1); } | |
396 }; | |
397 | |
398 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
399 struct _ChevronMenuInfo | |
400 { | |
401 HMENU hMenu; | |
402 LPNMREBARCHEVRON lpnm; | |
403 bool bCmdBar; | |
404 }; | |
405 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
406 | |
407 // Constructor | |
408 CFrameWindowImplBase() : | |
409 #ifdef _WIN32_WCE | |
410 m_hWndCECommandBar(NULL), | |
411 #endif // _WIN32_WCE | |
412 m_hWndToolBar(NULL), | |
413 m_hWndStatusBar(NULL), | |
414 m_hWndClient(NULL), | |
415 m_hAccel(NULL) | |
416 { } | |
417 | |
418 // Methods | |
419 HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DW
ORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCre
ateParam) | |
420 { | |
421 ATLASSERT(m_hWnd == NULL); | |
422 | |
423 if(atom == 0) | |
424 return NULL; | |
425 | |
426 ModuleHelper::AddCreateWndData(&m_thunk.cd, this); | |
427 | |
428 if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD)) | |
429 MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; | |
430 if(rect.m_lpRect == NULL) | |
431 rect.m_lpRect = &TBase::rcDefault; | |
432 | |
433 HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWin
dowName, | |
434 dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m
_lpRect->right - rect.m_lpRect->left, | |
435 rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent,
MenuOrID.m_hMenu, | |
436 ModuleHelper::GetModuleInstance(), lpCreateParam); | |
437 | |
438 ATLASSERT(hWnd == NULL || m_hWnd == hWnd); | |
439 | |
440 return hWnd; | |
441 } | |
442 | |
443 static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, B
OOL bInitialSeparator = FALSE, | |
444 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL
_IDW_TOOLBAR) | |
445 { | |
446 HINSTANCE hInst = ModuleHelper::GetResourceInstance(); | |
447 HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID)
, RT_TOOLBAR); | |
448 if (hRsrc == NULL) | |
449 return NULL; | |
450 | |
451 HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc); | |
452 if (hGlobal == NULL) | |
453 return NULL; | |
454 | |
455 _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGloba
l); | |
456 if (pData == NULL) | |
457 return NULL; | |
458 ATLASSERT(pData->wVersion == 1); | |
459 | |
460 WORD* pItems = pData->items(); | |
461 int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0); | |
462 CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff; | |
463 TBBUTTON* pTBBtn = buff.Allocate(nItems); | |
464 ATLASSERT(pTBBtn != NULL); | |
465 if(pTBBtn == NULL) | |
466 return NULL; | |
467 | |
468 const int cxSeparator = 8; | |
469 | |
470 // set initial separator (half width) | |
471 if(bInitialSeparator) | |
472 { | |
473 pTBBtn[0].iBitmap = cxSeparator / 2; | |
474 pTBBtn[0].idCommand = 0; | |
475 pTBBtn[0].fsState = 0; | |
476 pTBBtn[0].fsStyle = TBSTYLE_SEP; | |
477 pTBBtn[0].dwData = 0; | |
478 pTBBtn[0].iString = 0; | |
479 } | |
480 | |
481 int nBmp = 0; | |
482 for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCo
unt; i++, j++) | |
483 { | |
484 if(pItems[i] != 0) | |
485 { | |
486 pTBBtn[j].iBitmap = nBmp++; | |
487 pTBBtn[j].idCommand = pItems[i]; | |
488 pTBBtn[j].fsState = TBSTATE_ENABLED; | |
489 pTBBtn[j].fsStyle = TBSTYLE_BUTTON; | |
490 pTBBtn[j].dwData = 0; | |
491 pTBBtn[j].iString = 0; | |
492 } | |
493 else | |
494 { | |
495 pTBBtn[j].iBitmap = cxSeparator; | |
496 pTBBtn[j].idCommand = 0; | |
497 pTBBtn[j].fsState = 0; | |
498 pTBBtn[j].fsStyle = TBSTYLE_SEP; | |
499 pTBBtn[j].dwData = 0; | |
500 pTBBtn[j].iString = 0; | |
501 } | |
502 } | |
503 | |
504 #ifndef _WIN32_WCE | |
505 HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle,
0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleIn
stance(), NULL); | |
506 if(hWnd == NULL) | |
507 { | |
508 ATLASSERT(FALSE); | |
509 return NULL; | |
510 } | |
511 #else // CE specific | |
512 dwStyle; | |
513 nID; | |
514 // The toolbar must go onto the existing CommandBar or MenuBar | |
515 HWND hWnd = hWndParent; | |
516 #endif // _WIN32_WCE | |
517 | |
518 ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L); | |
519 | |
520 // check if font is taller than our bitmaps | |
521 CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L)
; | |
522 if(font.IsNull()) | |
523 font = AtlGetDefaultGuiFont(); | |
524 LOGFONT lf = { 0 }; | |
525 font.GetLogFont(lf); | |
526 WORD cyFontHeight = (WORD)abs(lf.lfHeight); | |
527 | |
528 #ifndef _WIN32_WCE | |
529 WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID
); | |
530 if(bitsPerPixel > 4) | |
531 { | |
532 COLORREF crMask = CLR_DEFAULT; | |
533 if(bitsPerPixel == 32) | |
534 { | |
535 // 32-bit color bitmap with alpha channel (valid
for Windows XP and later) | |
536 crMask = CLR_NONE; | |
537 } | |
538 HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper
::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask,
IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE); | |
539 ATLASSERT(hImageList != NULL); | |
540 ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageLi
st); | |
541 } | |
542 else | |
543 #endif // !_WIN32_WCE | |
544 { | |
545 TBADDBITMAP tbab = { 0 }; | |
546 tbab.hInst = hInst; | |
547 tbab.nID = nResourceID; | |
548 ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab); | |
549 } | |
550 | |
551 ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn); | |
552 ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth,
__max(pData->wHeight, cyFontHeight))); | |
553 const int cxyButtonMargin = 7; | |
554 ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth
+ cxyButtonMargin, __max(pData->wHeight, cyFontHeight) + cxyButtonMargin)); | |
555 | |
556 return hWnd; | |
557 } | |
558 | |
559 #ifndef _WIN32_WCE | |
560 static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_S
IMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
561 { | |
562 // Ensure style combinations for proper rebar painting | |
563 if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER) | |
564 dwStyle &= ~WS_BORDER; | |
565 else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER)) | |
566 dwStyle |= CCS_NODIVIDER; | |
567 | |
568 // Create rebar window | |
569 HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwSty
le, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModul
eInstance(), NULL); | |
570 if(hWndReBar == NULL) | |
571 { | |
572 ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n")
); | |
573 return NULL; | |
574 } | |
575 | |
576 // Initialize and send the REBARINFO structure | |
577 REBARINFO rbi = { 0 }; | |
578 rbi.cbSize = sizeof(REBARINFO); | |
579 rbi.fMask = 0; | |
580 if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi)) | |
581 { | |
582 ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.
\n")); | |
583 ::DestroyWindow(hWndReBar); | |
584 return NULL; | |
585 } | |
586 | |
587 return hWndReBar; | |
588 } | |
589 | |
590 BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID
= ATL_IDW_TOOLBAR) | |
591 { | |
592 ATLASSERT(!::IsWindow(m_hWndToolBar)); | |
593 m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID); | |
594 return (m_hWndToolBar != NULL); | |
595 } | |
596 | |
597 static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nI
D = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bF
ullWidthAlways = FALSE) | |
598 { | |
599 ATLASSERT(::IsWindow(hWndReBar)); // must be already created | |
600 #ifdef _DEBUG | |
601 // block - check if this is really a rebar | |
602 { | |
603 TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 }; | |
604 ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLA
SSNAME)); | |
605 ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0); | |
606 } | |
607 #endif // _DEBUG | |
608 ATLASSERT(::IsWindow(hWndBand)); // must be already created | |
609 | |
610 // Get number of buttons on the toolbar | |
611 int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0,
0L); | |
612 | |
613 // Set band info structure | |
614 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() }
; | |
615 #if (_WIN32_IE >= 0x0400) | |
616 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBB
IM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE; | |
617 #else | |
618 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBB
IM_ID | RBBIM_SIZE; | |
619 #endif // !(_WIN32_IE >= 0x0400) | |
620 if(lpstrTitle != NULL) | |
621 rbBand.fMask |= RBBIM_TEXT; | |
622 rbBand.fStyle = RBBS_CHILDEDGE; | |
623 #if (_WIN32_IE >= 0x0500) | |
624 if(nBtnCount > 0) // add chevron style for toolbar with button
s | |
625 rbBand.fStyle |= RBBS_USECHEVRON; | |
626 #endif // (_WIN32_IE >= 0x0500) | |
627 if(bNewRow) | |
628 rbBand.fStyle |= RBBS_BREAK; | |
629 | |
630 rbBand.lpText = (LPTSTR)lpstrTitle; | |
631 rbBand.hwndChild = hWndBand; | |
632 if(nID == 0) // calc band ID | |
633 nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar,
RB_GETBANDCOUNT, 0, 0L); | |
634 rbBand.wID = nID; | |
635 | |
636 // Calculate the size of the band | |
637 BOOL bRet = FALSE; | |
638 RECT rcTmp = { 0 }; | |
639 if(nBtnCount > 0) | |
640 { | |
641 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBt
nCount - 1, (LPARAM)&rcTmp); | |
642 ATLASSERT(bRet); | |
643 rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right; | |
644 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; | |
645 if(bFullWidthAlways) | |
646 { | |
647 rbBand.cxMinChild = rbBand.cx; | |
648 } | |
649 else if(lpstrTitle == NULL) | |
650 { | |
651 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMR
ECT, 0, (LPARAM)&rcTmp); | |
652 ATLASSERT(bRet); | |
653 rbBand.cxMinChild = rcTmp.right; | |
654 } | |
655 else | |
656 { | |
657 rbBand.cxMinChild = 0; | |
658 } | |
659 } | |
660 else // no buttons, either not a toolbar or really has no but
tons | |
661 { | |
662 bRet = ::GetWindowRect(hWndBand, &rcTmp); | |
663 ATLASSERT(bRet); | |
664 rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rc
Tmp.left); | |
665 rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0; | |
666 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top; | |
667 } | |
668 | |
669 #if (_WIN32_IE >= 0x0400) | |
670 rbBand.cxIdeal = rbBand.cx; | |
671 #endif // (_WIN32_IE >= 0x0400) | |
672 | |
673 // Add the band | |
674 LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-
1, (LPARAM)&rbBand); | |
675 if(lRes == 0) | |
676 { | |
677 ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the
rebar.\n")); | |
678 return FALSE; | |
679 } | |
680 | |
681 #if (_WIN32_IE >= 0x0501) | |
682 DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDS
TYLE, 0, 0L); | |
683 ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBST
YLE_EX_HIDECLIPPEDBUTTONS); | |
684 #endif // (_WIN32_IE >= 0x0501) | |
685 | |
686 return TRUE; | |
687 } | |
688 | |
689 BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL b
NewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE) | |
690 { | |
691 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing r
ebar | |
692 ATLASSERT(::IsWindow(hWndBand)); // must be created | |
693 return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrT
itle, bNewRow, cxWidth, bFullWidthAlways); | |
694 } | |
695 | |
696 #if (_WIN32_IE >= 0x0400) | |
697 void SizeSimpleReBarBands() | |
698 { | |
699 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing r
ebar | |
700 | |
701 int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT,
0, 0L); | |
702 | |
703 for(int i = 0; i < nCount; i++) | |
704 { | |
705 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBAND
INFO() }; | |
706 rbBand.fMask = RBBIM_SIZE; | |
707 BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBAN
DINFO, i, (LPARAM)&rbBand); | |
708 ATLASSERT(bRet); | |
709 RECT rect = { 0, 0, 0, 0 }; | |
710 ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPAR
AM)&rect); | |
711 rbBand.cx += rect.left + rect.right; | |
712 bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO
, i, (LPARAM)&rbBand); | |
713 ATLASSERT(bRet); | |
714 } | |
715 } | |
716 #endif // (_WIN32_IE >= 0x0400) | |
717 #endif // _WIN32_WCE | |
718 | |
719 #ifndef _WIN32_WCE | |
720 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD |
WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL
_IDW_STATUS_BAR) | |
721 #else // CE specific | |
722 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD |
WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR) | |
723 #endif // _WIN32_WCE | |
724 { | |
725 ATLASSERT(!::IsWindow(m_hWndStatusBar)); | |
726 m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWn
d, nID); | |
727 return (m_hWndStatusBar != NULL); | |
728 } | |
729 | |
730 #ifndef _WIN32_WCE | |
731 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwS
tyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRI
P, UINT nID = ATL_IDW_STATUS_BAR) | |
732 #else // CE specific | |
733 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwS
tyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL
_IDW_STATUS_BAR) | |
734 #endif // _WIN32_WCE | |
735 { | |
736 const int cchMax = 128; // max text length is 127 for status b
ars (+1 for null) | |
737 TCHAR szText[cchMax]; | |
738 szText[0] = 0; | |
739 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szTex
t, cchMax); | |
740 return CreateSimpleStatusBar(szText, dwStyle, nID); | |
741 } | |
742 | |
743 #ifdef _WIN32_WCE | |
744 BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, D
WORD dwFlags = 0, int nCmdBarID = 1) | |
745 { | |
746 ATLASSERT(m_hWndCECommandBar == NULL); | |
747 ATLASSERT(m_hWndToolBar == NULL); | |
748 | |
749 m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModule
Instance(), m_hWnd, nCmdBarID); | |
750 if(m_hWndCECommandBar == NULL) | |
751 return FALSE; | |
752 | |
753 m_hWndToolBar = m_hWndCECommandBar; | |
754 | |
755 BOOL bRet = TRUE; | |
756 | |
757 if(pszMenu != NULL) | |
758 bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar,
IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu,
iButton); | |
759 | |
760 bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags,
0); | |
761 | |
762 return bRet; | |
763 } | |
764 | |
765 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) | |
766 BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwF
lags = 0, int nBmpId = 0, int cBmpImages = 0) | |
767 { | |
768 ATLASSERT(m_hWndCECommandBar == NULL); | |
769 | |
770 SHMENUBARINFO mbi = { 0 }; | |
771 mbi.cbSize = sizeof(mbi); | |
772 mbi.hwndParent = m_hWnd; | |
773 mbi.dwFlags = dwFlags; | |
774 mbi.nToolBarId = nToolBarId; | |
775 mbi.hInstRes = ModuleHelper::GetResourceInstance(); | |
776 mbi.nBmpId = nBmpId; | |
777 mbi.cBmpImages = cBmpImages; | |
778 mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar | |
779 | |
780 BOOL bRet = ::SHCreateMenuBar(&mbi); | |
781 if(bRet != FALSE) | |
782 { | |
783 m_hWndCECommandBar = mbi.hwndMB; | |
784 SizeToMenuBar(); | |
785 } | |
786 | |
787 return bRet; | |
788 } | |
789 | |
790 void SizeToMenuBar() // for menu bar only | |
791 { | |
792 ATLASSERT(::IsWindow(m_hWnd)); | |
793 ATLASSERT(::IsWindow(m_hWndCECommandBar)); | |
794 | |
795 RECT rect = { 0 }; | |
796 GetWindowRect(&rect); | |
797 RECT rectMB = { 0 }; | |
798 ::GetWindowRect(m_hWndCECommandBar, &rectMB); | |
799 int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - re
ct.top : rectMB.bottom - rect.top; | |
800 SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDE
R | SWP_NOMOVE); | |
801 } | |
802 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__) | |
803 #endif // _WIN32_WCE | |
804 | |
805 void UpdateLayout(BOOL bResizeBars = TRUE) | |
806 { | |
807 RECT rect = { 0 }; | |
808 GetClientRect(&rect); | |
809 | |
810 // position bars and offset their dimensions | |
811 UpdateBarsPosition(rect, bResizeBars); | |
812 | |
813 // resize client window | |
814 if(m_hWndClient != NULL) | |
815 ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top, | |
816 rect.right - rect.left, rect.bottom - rect.top, | |
817 SWP_NOZORDER | SWP_NOACTIVATE); | |
818 } | |
819 | |
820 void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE) | |
821 { | |
822 // resize toolbar | |
823 if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBa
r, GWL_STYLE) & WS_VISIBLE)) | |
824 { | |
825 if(bResizeBars) | |
826 { | |
827 ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0); | |
828 ::InvalidateRect(m_hWndToolBar, NULL, FALSE); | |
829 } | |
830 RECT rectTB = { 0 }; | |
831 ::GetWindowRect(m_hWndToolBar, &rectTB); | |
832 rect.top += rectTB.bottom - rectTB.top; | |
833 } | |
834 | |
835 // resize status bar | |
836 if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStat
usBar, GWL_STYLE) & WS_VISIBLE)) | |
837 { | |
838 if(bResizeBars) | |
839 ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0); | |
840 RECT rectSB = { 0 }; | |
841 ::GetWindowRect(m_hWndStatusBar, &rectSB); | |
842 rect.bottom -= rectSB.bottom - rectSB.top; | |
843 } | |
844 } | |
845 | |
846 BOOL PreTranslateMessage(MSG* pMsg) | |
847 { | |
848 if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel,
pMsg)) | |
849 return TRUE; | |
850 return FALSE; | |
851 } | |
852 | |
853 BEGIN_MSG_MAP(CFrameWindowImplBase) | |
854 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) | |
855 #ifndef _WIN32_WCE | |
856 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) | |
857 #endif // !_WIN32_WCE | |
858 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) | |
859 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) | |
860 #ifndef _WIN32_WCE | |
861 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA) | |
862 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW) | |
863 #endif // !_WIN32_WCE | |
864 END_MSG_MAP() | |
865 | |
866 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
ram*/, BOOL& bHandled) | |
867 { | |
868 if(m_hWndClient != NULL) // view will paint itself instead | |
869 return 1; | |
870 | |
871 bHandled = FALSE; | |
872 return 0; | |
873 } | |
874 | |
875 #ifndef _WIN32_WCE | |
876 LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL&
bHandled) | |
877 { | |
878 bHandled = FALSE; | |
879 | |
880 if(m_hWndStatusBar == NULL) | |
881 return 1; | |
882 | |
883 WORD wFlags = HIWORD(wParam); | |
884 if(wFlags == 0xFFFF && lParam == NULL) // menu closing | |
885 { | |
886 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L); | |
887 } | |
888 else | |
889 { | |
890 const int cchBuff = 256; | |
891 TCHAR szBuff[cchBuff]; | |
892 szBuff[0] = 0; | |
893 if(!(wFlags & MF_POPUP)) | |
894 { | |
895 WORD wID = LOWORD(wParam); | |
896 // check for special cases | |
897 if(wID >= 0xF000 && wID < 0xF1F0) // system me
nu IDs | |
898 wID = (WORD)(((wID - 0xF000) >> 4) + ATL
_IDS_SCFIRST); | |
899 else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FI
LE_MRU_LAST) // MRU items | |
900 wID = ATL_IDS_MRU_FILE; | |
901 else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <=
ATL_IDM_LAST_MDICHILD) // MDI child windows | |
902 wID = ATL_IDS_MDICHILD; | |
903 | |
904 int nRet = ::LoadString(ModuleHelper::GetResourc
eInstance(), wID, szBuff, cchBuff); | |
905 for(int i = 0; i < nRet; i++) | |
906 { | |
907 if(szBuff[i] == _T('\n')) | |
908 { | |
909 szBuff[i] = 0; | |
910 break; | |
911 } | |
912 } | |
913 } | |
914 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L); | |
915 ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NO
BORDERS), (LPARAM)szBuff); | |
916 } | |
917 | |
918 return 1; | |
919 } | |
920 #endif // !_WIN32_WCE | |
921 | |
922 LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled) | |
923 { | |
924 if(m_hWndClient != NULL) | |
925 ::SetFocus(m_hWndClient); | |
926 | |
927 bHandled = FALSE; | |
928 return 1; | |
929 } | |
930 | |
931 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled) | |
932 { | |
933 if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0) | |
934 ::PostQuitMessage(1); | |
935 | |
936 bHandled = FALSE; | |
937 return 1; | |
938 } | |
939 | |
940 #ifndef _WIN32_WCE | |
941 LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) | |
942 { | |
943 LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh; | |
944 pDispInfo->szText[0] = 0; | |
945 | |
946 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) | |
947 { | |
948 const int cchBuff = 256; | |
949 char szBuff[cchBuff]; | |
950 szBuff[0] = 0; | |
951 int nRet = ::LoadStringA(ModuleHelper::GetResourceInstan
ce(), idCtrl, szBuff, cchBuff); | |
952 for(int i = 0; i < nRet; i++) | |
953 { | |
954 if(szBuff[i] == '\n') | |
955 { | |
956 SecureHelper::strncpyA_x(pDispInfo->szTe
xt, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); | |
957 break; | |
958 } | |
959 } | |
960 #if (_WIN32_IE >= 0x0300) | |
961 if(nRet > 0) // string was loaded, save it | |
962 pDispInfo->uFlags |= TTF_DI_SETITEM; | |
963 #endif // (_WIN32_IE >= 0x0300) | |
964 } | |
965 | |
966 return 0; | |
967 } | |
968 | |
969 LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/) | |
970 { | |
971 LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh; | |
972 pDispInfo->szText[0] = 0; | |
973 | |
974 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND)) | |
975 { | |
976 const int cchBuff = 256; | |
977 wchar_t szBuff[cchBuff]; | |
978 szBuff[0] = 0; | |
979 int nRet = ::LoadStringW(ModuleHelper::GetResourceInstan
ce(), idCtrl, szBuff, cchBuff); | |
980 for(int i = 0; i < nRet; i++) | |
981 { | |
982 if(szBuff[i] == L'\n') | |
983 { | |
984 SecureHelper::strncpyW_x(pDispInfo->szTe
xt, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE); | |
985 break; | |
986 } | |
987 } | |
988 #if (_WIN32_IE >= 0x0300) | |
989 if(nRet > 0) // string was loaded, save it | |
990 pDispInfo->uFlags |= TTF_DI_SETITEM; | |
991 #endif // (_WIN32_IE >= 0x0300) | |
992 } | |
993 | |
994 return 0; | |
995 } | |
996 #endif // !_WIN32_WCE | |
997 | |
998 // Implementation - chevron menu support | |
999 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
1000 bool PrepareChevronMenu(_ChevronMenuInfo& cmi) | |
1001 { | |
1002 // get rebar and toolbar | |
1003 REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() }; | |
1004 rbbi.fMask = RBBIM_CHILD; | |
1005 BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBA
NDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi); | |
1006 ATLASSERT(bRet); | |
1007 | |
1008 // assume the band is a toolbar | |
1009 ATL::CWindow wnd = rbbi.hwndChild; | |
1010 int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT); | |
1011 if(nCount <= 0) // probably not a toolbar | |
1012 return false; | |
1013 | |
1014 // check if it's a command bar | |
1015 CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU); | |
1016 cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL); | |
1017 | |
1018 // build a menu from hidden items | |
1019 CMenuHandle menu; | |
1020 bRet = menu.CreatePopupMenu(); | |
1021 ATLASSERT(bRet); | |
1022 RECT rcClient = { 0 }; | |
1023 bRet = wnd.GetClientRect(&rcClient); | |
1024 ATLASSERT(bRet); | |
1025 for(int i = 0; i < nCount; i++) | |
1026 { | |
1027 TBBUTTON tbb = { 0 }; | |
1028 bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&t
bb); | |
1029 ATLASSERT(bRet); | |
1030 // skip hidden buttons | |
1031 if((tbb.fsState & TBSTATE_HIDDEN) != 0) | |
1032 continue; | |
1033 RECT rcButton = { 0 }; | |
1034 bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)
&rcButton); | |
1035 ATLASSERT(bRet); | |
1036 bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0); | |
1037 if(rcButton.right > rcClient.right) | |
1038 { | |
1039 if(tbb.fsStyle & BTNS_SEP) | |
1040 { | |
1041 if(menu.GetMenuItemCount() > 0) | |
1042 menu.AppendMenu(MF_SEPARATOR); | |
1043 } | |
1044 else if(cmi.bCmdBar) | |
1045 { | |
1046 const int cchBuff = 200; | |
1047 TCHAR szBuff[cchBuff] = { 0 }; | |
1048 CMenuItemInfo mii; | |
1049 mii.fMask = MIIM_TYPE | MIIM_SUBMENU; | |
1050 mii.dwTypeData = szBuff; | |
1051 mii.cch = cchBuff; | |
1052 bRet = menuCmdBar.GetMenuItemInfo(i, TRU
E, &mii); | |
1053 ATLASSERT(bRet); | |
1054 // Note: CmdBar currently supports only
drop-down items | |
1055 ATLASSERT(::IsMenu(mii.hSubMenu)); | |
1056 bRet = menu.AppendMenu(MF_STRING | MF_PO
PUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeDat
a); | |
1057 ATLASSERT(bRet); | |
1058 } | |
1059 else | |
1060 { | |
1061 // get button's text | |
1062 const int cchBuff = 200; | |
1063 TCHAR szBuff[cchBuff] = { 0 }; | |
1064 LPTSTR lpstrText = szBuff; | |
1065 TBBUTTONINFO tbbi = { 0 }; | |
1066 tbbi.cbSize = sizeof(TBBUTTONINFO); | |
1067 tbbi.dwMask = TBIF_TEXT; | |
1068 tbbi.pszText = szBuff; | |
1069 tbbi.cchText = cchBuff; | |
1070 if(wnd.SendMessage(TB_GETBUTTONINFO, tbb
.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0) | |
1071 { | |
1072 // no text for this button, try
a resource string | |
1073 lpstrText = _T(""); | |
1074 int nRet = ::LoadString(ModuleHe
lper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff); | |
1075 for(int n = 0; n < nRet; n++) | |
1076 { | |
1077 if(szBuff[n] == _T('\n')
) | |
1078 { | |
1079 lpstrText = &szB
uff[n + 1]; | |
1080 break; | |
1081 } | |
1082 } | |
1083 } | |
1084 bRet = menu.AppendMenu(MF_STRING | (bEna
bled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText); | |
1085 ATLASSERT(bRet); | |
1086 } | |
1087 } | |
1088 } | |
1089 | |
1090 if(menu.GetMenuItemCount() == 0) // no hidden buttons after al
l | |
1091 { | |
1092 menu.DestroyMenu(); | |
1093 ::MessageBeep((UINT)-1); | |
1094 return false; | |
1095 } | |
1096 | |
1097 cmi.hMenu = menu; | |
1098 return true; | |
1099 } | |
1100 | |
1101 void DisplayChevronMenu(_ChevronMenuInfo& cmi) | |
1102 { | |
1103 #ifndef TPM_VERPOSANIMATION | |
1104 const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation fl
ag | |
1105 #endif | |
1106 // convert chevron rect to screen coordinates | |
1107 ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom; | |
1108 POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom }; | |
1109 wndFrom.MapWindowPoints(NULL, &pt, 1); | |
1110 RECT rc = cmi.lpnm->rc; | |
1111 wndFrom.MapWindowPoints(NULL, &rc); | |
1112 // set up flags and rect | |
1113 UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN
| TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0); | |
1114 TPMPARAMS TPMParams = { 0 }; | |
1115 TPMParams.cbSize = sizeof(TPMPARAMS); | |
1116 TPMParams.rcExclude = rc; | |
1117 // check if this window has a command bar | |
1118 HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0,
0L); | |
1119 if(::IsWindow(hWndCmdBar)) | |
1120 { | |
1121 CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.
hMenu, uMenuFlags, pt.x, pt.y, &TPMParams }; | |
1122 ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARA
M)&CBRPopupMenu); | |
1123 } | |
1124 else | |
1125 { | |
1126 CMenuHandle menu = cmi.hMenu; | |
1127 menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &T
PMParams); | |
1128 } | |
1129 } | |
1130 | |
1131 void CleanupChevronMenu(_ChevronMenuInfo& cmi) | |
1132 { | |
1133 CMenuHandle menu = cmi.hMenu; | |
1134 // if menu is from a command bar, detach submenus so they are no
t destroyed | |
1135 if(cmi.bCmdBar) | |
1136 { | |
1137 for(int i = menu.GetMenuItemCount() - 1; i >=0; i--) | |
1138 menu.RemoveMenu(i, MF_BYPOSITION); | |
1139 } | |
1140 // destroy menu | |
1141 menu.DestroyMenu(); | |
1142 // convert chevron rect to screen coordinates | |
1143 ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom; | |
1144 RECT rc = cmi.lpnm->rc; | |
1145 wndFrom.MapWindowPoints(NULL, &rc); | |
1146 // eat next message if click is on the same button | |
1147 MSG msg = { 0 }; | |
1148 if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, P
M_NOREMOVE) && ::PtInRect(&rc, msg.pt)) | |
1149 ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDO
WN, PM_REMOVE); | |
1150 } | |
1151 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
1152 }; | |
1153 | |
1154 | |
1155 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWin
Traits> | |
1156 class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinT
raits > | |
1157 { | |
1158 public: | |
1159 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR sz
WindowName = NULL, | |
1160 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
1161 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) | |
1162 { | |
1163 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc)
; | |
1164 | |
1165 dwStyle = T::GetWndStyle(dwStyle); | |
1166 dwExStyle = T::GetWndExStyle(dwExStyle); | |
1167 | |
1168 if(rect.m_lpRect == NULL) | |
1169 rect.m_lpRect = &TBase::rcDefault; | |
1170 | |
1171 return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndPar
ent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam
); | |
1172 } | |
1173 | |
1174 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dw
Style = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) | |
1175 { | |
1176 const int cchName = 256; | |
1177 TCHAR szWindowName[cchName]; | |
1178 szWindowName[0] = 0; | |
1179 #ifndef _WIN32_WCE | |
1180 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClass
Info().m_uCommonResourceID, szWindowName, cchName); | |
1181 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MA
KEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
1182 #else // CE specific | |
1183 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClass
Info().m_uCommonResourceID, szWindowName, cchName); | |
1184 | |
1185 // This always needs to be NULL for Windows CE. | |
1186 // Frame Window menus have to go onto the CommandBar. | |
1187 // Use CreateSimpleCECommandBar | |
1188 HMENU hMenu = NULL; | |
1189 #endif // _WIN32_WCE | |
1190 | |
1191 T* pT = static_cast<T*>(this); | |
1192 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle,
dwExStyle, hMenu, lpCreateParam); | |
1193 | |
1194 if(hWnd != NULL) | |
1195 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceI
nstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
1196 | |
1197 return hWnd; | |
1198 } | |
1199 | |
1200 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPL
E_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
1201 { | |
1202 if(nResourceID == 0) | |
1203 nResourceID = T::GetWndClassInfo().m_uCommonResourceID; | |
1204 #ifndef _WIN32_WCE | |
1205 ATLASSERT(!::IsWindow(m_hWndToolBar)); | |
1206 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID,
TRUE, dwStyle, nID); | |
1207 return (m_hWndToolBar != NULL); | |
1208 #else // CE specific | |
1209 HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResou
rceID, TRUE, dwStyle, nID); | |
1210 return (hWnd != NULL); | |
1211 #endif // _WIN32_WCE | |
1212 } | |
1213 | |
1214 #ifdef _WIN32_WCE | |
1215 // CE specific variant that returns the handle of the toolbar | |
1216 HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIM
PLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
1217 { | |
1218 if(nResourceID == 0) | |
1219 nResourceID = T::GetWndClassInfo().m_uCommonResourceID; | |
1220 | |
1221 return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceI
D, TRUE, dwStyle, nID); | |
1222 } | |
1223 #endif // _WIN32_WCE | |
1224 | |
1225 // message map and handlers | |
1226 typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass; | |
1227 | |
1228 BEGIN_MSG_MAP(CFrameWindowImpl) | |
1229 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
1230 #ifndef _ATL_NO_REBAR_SUPPORT | |
1231 #if (_WIN32_IE >= 0x0400) | |
1232 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) | |
1233 #endif // (_WIN32_IE >= 0x0400) | |
1234 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
1235 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) | |
1236 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
1237 #endif // !_ATL_NO_REBAR_SUPPORT | |
1238 CHAIN_MSG_MAP(_baseClass) | |
1239 END_MSG_MAP() | |
1240 | |
1241 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bH
andled) | |
1242 { | |
1243 if(wParam != SIZE_MINIMIZED) | |
1244 { | |
1245 T* pT = static_cast<T*>(this); | |
1246 pT->UpdateLayout(); | |
1247 } | |
1248 bHandled = FALSE; | |
1249 return 1; | |
1250 } | |
1251 | |
1252 #ifndef _ATL_NO_REBAR_SUPPORT | |
1253 #if (_WIN32_IE >= 0x0400) | |
1254 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandl
ed*/) | |
1255 { | |
1256 T* pT = static_cast<T*>(this); | |
1257 pT->UpdateLayout(FALSE); | |
1258 return 0; | |
1259 } | |
1260 #endif // (_WIN32_IE >= 0x0400) | |
1261 | |
1262 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
1263 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
1264 { | |
1265 T* pT = static_cast<T*>(this); | |
1266 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; | |
1267 if(!pT->PrepareChevronMenu(cmi)) | |
1268 { | |
1269 bHandled = FALSE; | |
1270 return 1; | |
1271 } | |
1272 // display a popup menu with hidden items | |
1273 pT->DisplayChevronMenu(cmi); | |
1274 // cleanup | |
1275 pT->CleanupChevronMenu(cmi); | |
1276 return 0; | |
1277 } | |
1278 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE) | |
1279 #endif // !_ATL_NO_REBAR_SUPPORT | |
1280 }; | |
1281 | |
1282 | |
1283 /////////////////////////////////////////////////////////////////////////////// | |
1284 // AtlCreateSimpleToolBar - helper for creating simple toolbars | |
1285 | |
1286 #ifndef _WIN32_WCE | |
1287 | |
1288 inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInit
ialSeparator = FALSE, | |
1289 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOO
LBAR) | |
1290 { | |
1291 return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nReso
urceID, bInitialSeparator, dwStyle, nID); | |
1292 } | |
1293 | |
1294 #endif // !_WIN32_WCE | |
1295 | |
1296 | |
1297 /////////////////////////////////////////////////////////////////////////////// | |
1298 // CMDIWindow | |
1299 | |
1300 #ifndef _WIN32_WCE | |
1301 | |
1302 #ifndef _WTL_MDIWINDOWMENU_TEXT | |
1303 #define _WTL_MDIWINDOWMENU_TEXT _T("&Window") | |
1304 #endif | |
1305 | |
1306 class CMDIWindow : public ATL::CWindow | |
1307 { | |
1308 public: | |
1309 // Data members | |
1310 HWND m_hWndMDIClient; | |
1311 HMENU m_hMenu; | |
1312 | |
1313 // Constructors | |
1314 CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL)
, m_hMenu(NULL) | |
1315 { } | |
1316 | |
1317 CMDIWindow& operator =(HWND hWnd) | |
1318 { | |
1319 m_hWnd = hWnd; | |
1320 return *this; | |
1321 } | |
1322 | |
1323 // Operations | |
1324 HWND MDIGetActive(BOOL* lpbMaximized = NULL) | |
1325 { | |
1326 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1327 return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0,
(LPARAM)lpbMaximized); | |
1328 } | |
1329 | |
1330 void MDIActivate(HWND hWndChildToActivate) | |
1331 { | |
1332 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1333 ATLASSERT(::IsWindow(hWndChildToActivate)); | |
1334 ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChild
ToActivate, 0); | |
1335 } | |
1336 | |
1337 void MDINext(HWND hWndChild, BOOL bPrevious = FALSE) | |
1338 { | |
1339 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1340 ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild)); | |
1341 ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (L
PARAM)bPrevious); | |
1342 } | |
1343 | |
1344 void MDIMaximize(HWND hWndChildToMaximize) | |
1345 { | |
1346 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1347 ATLASSERT(::IsWindow(hWndChildToMaximize)); | |
1348 ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChild
ToMaximize, 0); | |
1349 } | |
1350 | |
1351 void MDIRestore(HWND hWndChildToRestore) | |
1352 { | |
1353 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1354 ATLASSERT(::IsWindow(hWndChildToRestore)); | |
1355 ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildT
oRestore, 0); | |
1356 } | |
1357 | |
1358 void MDIDestroy(HWND hWndChildToDestroy) | |
1359 { | |
1360 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1361 ATLASSERT(::IsWindow(hWndChildToDestroy)); | |
1362 ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildT
oDestroy, 0); | |
1363 } | |
1364 | |
1365 BOOL MDICascade(UINT uFlags = 0) | |
1366 { | |
1367 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1368 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPAR
AM)uFlags, 0); | |
1369 } | |
1370 | |
1371 BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL) | |
1372 { | |
1373 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1374 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)
uFlags, 0); | |
1375 } | |
1376 | |
1377 void MDIIconArrange() | |
1378 { | |
1379 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1380 ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0); | |
1381 } | |
1382 | |
1383 HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow) | |
1384 { | |
1385 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1386 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPA
RAM)hMenuFrame, (LPARAM)hMenuWindow); | |
1387 } | |
1388 | |
1389 HMENU MDIRefreshMenu() | |
1390 { | |
1391 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1392 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU,
0, 0); | |
1393 } | |
1394 | |
1395 // Additional operations | |
1396 static HMENU GetStandardWindowMenu(HMENU hMenu) | |
1397 { | |
1398 int nCount = ::GetMenuItemCount(hMenu); | |
1399 if(nCount == -1) | |
1400 return NULL; | |
1401 int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSI
TION); | |
1402 if(nLen == 0) | |
1403 return NULL; | |
1404 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff; | |
1405 LPTSTR lpszText = buff.Allocate(nLen + 1); | |
1406 if(lpszText == NULL) | |
1407 return NULL; | |
1408 if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYP
OSITION) != nLen) | |
1409 return NULL; | |
1410 if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0) | |
1411 return NULL; | |
1412 return ::GetSubMenu(hMenu, nCount - 2); | |
1413 } | |
1414 | |
1415 void SetMDIFrameMenu() | |
1416 { | |
1417 HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu); | |
1418 MDISetMenu(m_hMenu, hWindowMenu); | |
1419 MDIRefreshMenu(); | |
1420 ::DrawMenuBar(GetMDIFrame()); | |
1421 } | |
1422 | |
1423 HWND GetMDIFrame() const | |
1424 { | |
1425 return ::GetParent(m_hWndMDIClient); | |
1426 } | |
1427 }; | |
1428 | |
1429 #endif // !_WIN32_WCE | |
1430 | |
1431 | |
1432 /////////////////////////////////////////////////////////////////////////////// | |
1433 // CMDIFrameWindowImpl | |
1434 | |
1435 #ifndef _WIN32_WCE | |
1436 | |
1437 // MDI child command chaining macro (only for MDI frame windows) | |
1438 #define CHAIN_MDI_CHILD_COMMANDS() \ | |
1439 if(uMsg == WM_COMMAND) \ | |
1440 { \ | |
1441 HWND hWndChild = MDIGetActive(); \ | |
1442 if(hWndChild != NULL) \ | |
1443 ::SendMessage(hWndChild, uMsg, wParam, lParam); \ | |
1444 } | |
1445 | |
1446 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTr
aits> | |
1447 class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWi
nTraits > | |
1448 { | |
1449 public: | |
1450 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR sz
WindowName = NULL, | |
1451 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
1452 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL) | |
1453 { | |
1454 m_hMenu = hMenu; | |
1455 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc)
; | |
1456 | |
1457 dwStyle = T::GetWndStyle(dwStyle); | |
1458 dwExStyle = T::GetWndExStyle(dwExStyle); | |
1459 | |
1460 if(rect.m_lpRect == NULL) | |
1461 rect.m_lpRect = &TBase::rcDefault; | |
1462 | |
1463 return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndPare
nt, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam)
; | |
1464 } | |
1465 | |
1466 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dw
Style = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL) | |
1467 { | |
1468 const int cchName = 256; | |
1469 TCHAR szWindowName[cchName]; | |
1470 szWindowName[0] = 0; | |
1471 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClass
Info().m_uCommonResourceID, szWindowName, cchName); | |
1472 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MA
KEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
1473 | |
1474 T* pT = static_cast<T*>(this); | |
1475 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle,
dwExStyle, hMenu, lpCreateParam); | |
1476 | |
1477 if(hWnd != NULL) | |
1478 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceI
nstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
1479 | |
1480 return hWnd; | |
1481 } | |
1482 | |
1483 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPL
E_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
1484 { | |
1485 ATLASSERT(!::IsWindow(m_hWndToolBar)); | |
1486 if(nResourceID == 0) | |
1487 nResourceID = T::GetWndClassInfo().m_uCommonResourceID; | |
1488 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID,
TRUE, dwStyle, nID); | |
1489 return (m_hWndToolBar != NULL); | |
1490 } | |
1491 | |
1492 virtual WNDPROC GetWindowProc() | |
1493 { | |
1494 return MDIFrameWindowProc; | |
1495 } | |
1496 | |
1497 static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM
wParam, LPARAM lParam) | |
1498 { | |
1499 CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameW
indowImpl< T, TBase, TWinTraits >*)hWnd; | |
1500 // set a ptr to this message and save the old value | |
1501 #if (_ATL_VER >= 0x0700) | |
1502 ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); | |
1503 const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg; | |
1504 #else // !(_ATL_VER >= 0x0700) | |
1505 MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } }; | |
1506 const MSG* pOldMsg = pThis->m_pCurrentMsg; | |
1507 #endif // !(_ATL_VER >= 0x0700) | |
1508 pThis->m_pCurrentMsg = &msg; | |
1509 // pass to the message map to process | |
1510 LRESULT lRes = 0; | |
1511 BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wPa
ram, lParam, lRes, 0); | |
1512 // restore saved value for the current message | |
1513 ATLASSERT(pThis->m_pCurrentMsg == &msg); | |
1514 pThis->m_pCurrentMsg = pOldMsg; | |
1515 // do the default processing if message was not handled | |
1516 if(!bRet) | |
1517 { | |
1518 if(uMsg != WM_NCDESTROY) | |
1519 lRes = pThis->DefWindowProc(uMsg, wParam, lParam
); | |
1520 else | |
1521 { | |
1522 // unsubclass, if needed | |
1523 LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->
m_hWnd, GWLP_WNDPROC); | |
1524 lRes = pThis->DefWindowProc(uMsg, wParam, lParam
); | |
1525 if(pThis->m_pfnSuperWindowProc != ::DefWindowPro
c && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc) | |
1526 ::SetWindowLongPtr(pThis->m_hWnd, GWLP_W
NDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc); | |
1527 #if (_ATL_VER >= 0x0700) | |
1528 // mark window as destryed | |
1529 pThis->m_dwState |= WINSTATE_DESTROYED; | |
1530 #else // !(_ATL_VER >= 0x0700) | |
1531 // clear out window handle | |
1532 HWND hWnd = pThis->m_hWnd; | |
1533 pThis->m_hWnd = NULL; | |
1534 // clean up after window is destroyed | |
1535 pThis->OnFinalMessage(hWnd); | |
1536 #endif // !(_ATL_VER >= 0x0700) | |
1537 } | |
1538 } | |
1539 #if (_ATL_VER >= 0x0700) | |
1540 if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg
== NULL) | |
1541 { | |
1542 // clear out window handle | |
1543 HWND hWnd = pThis->m_hWnd; | |
1544 pThis->m_hWnd = NULL; | |
1545 pThis->m_dwState &= ~WINSTATE_DESTROYED; | |
1546 // clean up after window is destroyed | |
1547 pThis->OnFinalMessage(hWnd); | |
1548 } | |
1549 #endif // (_ATL_VER >= 0x0700) | |
1550 return lRes; | |
1551 } | |
1552 | |
1553 // Overriden to call DefWindowProc which uses DefFrameProc | |
1554 LRESULT DefWindowProc() | |
1555 { | |
1556 const MSG* pMsg = m_pCurrentMsg; | |
1557 LRESULT lRes = 0; | |
1558 if (pMsg != NULL) | |
1559 lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->
lParam); | |
1560 return lRes; | |
1561 } | |
1562 | |
1563 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) | |
1564 { | |
1565 return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lPa
ram); | |
1566 } | |
1567 | |
1568 BOOL PreTranslateMessage(MSG* pMsg) | |
1569 { | |
1570 if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(
pMsg)) | |
1571 return TRUE; | |
1572 return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg); | |
1573 } | |
1574 | |
1575 HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT
, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD) | |
1576 { | |
1577 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLI
PSIBLINGS | MDIS_ALLCHILDSTYLES; | |
1578 DWORD dwExStyle = WS_EX_CLIENTEDGE; | |
1579 | |
1580 CLIENTCREATESTRUCT ccs = { 0 }; | |
1581 ccs.hWindowMenu = hWindowMenu; | |
1582 ccs.idFirstChild = nFirstChildID; | |
1583 | |
1584 if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0) | |
1585 { | |
1586 // parent MDI frame's scroll styles move to the MDICLIEN
T | |
1587 dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL)); | |
1588 | |
1589 // fast way to turn off the scrollbar bits (without a re
size) | |
1590 ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | S
WP_FRAMECHANGED); | |
1591 } | |
1592 | |
1593 // Create MDICLIENT window | |
1594 m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL
, | |
1595 dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID), | |
1596 ModuleHelper::GetModuleInstance(), (LPVOID)&ccs); | |
1597 if (m_hWndClient == NULL) | |
1598 { | |
1599 ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create
MDICLIENT.\n")); | |
1600 return NULL; | |
1601 } | |
1602 | |
1603 // Move it to the top of z-order | |
1604 ::BringWindowToTop(m_hWndClient); | |
1605 | |
1606 // set as MDI client window | |
1607 m_hWndMDIClient = m_hWndClient; | |
1608 | |
1609 // update to proper size | |
1610 T* pT = static_cast<T*>(this); | |
1611 pT->UpdateLayout(); | |
1612 | |
1613 return m_hWndClient; | |
1614 } | |
1615 | |
1616 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass; | |
1617 | |
1618 BEGIN_MSG_MAP(CMDIFrameWindowImpl) | |
1619 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
1620 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) | |
1621 MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu) | |
1622 #ifndef _ATL_NO_REBAR_SUPPORT | |
1623 #if (_WIN32_IE >= 0x0400) | |
1624 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) | |
1625 #endif // (_WIN32_IE >= 0x0400) | |
1626 #if (_WIN32_IE >= 0x0500) | |
1627 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) | |
1628 #endif // (_WIN32_IE >= 0x0500) | |
1629 #endif // !_ATL_NO_REBAR_SUPPORT | |
1630 CHAIN_MSG_MAP(_baseClass) | |
1631 END_MSG_MAP() | |
1632 | |
1633 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*
bHandled*/) | |
1634 { | |
1635 if(wParam != SIZE_MINIMIZED) | |
1636 { | |
1637 T* pT = static_cast<T*>(this); | |
1638 pT->UpdateLayout(); | |
1639 } | |
1640 // message must be handled, otherwise DefFrameProc would resize
the client again | |
1641 return 0; | |
1642 } | |
1643 | |
1644 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHan
dled*/) | |
1645 { | |
1646 // don't allow CFrameWindowImplBase to handle this one | |
1647 return DefWindowProc(uMsg, wParam, lParam); | |
1648 } | |
1649 | |
1650 LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/
, BOOL& /*bHandled*/) | |
1651 { | |
1652 SetMDIFrameMenu(); | |
1653 return 0; | |
1654 } | |
1655 | |
1656 #ifndef _ATL_NO_REBAR_SUPPORT | |
1657 #if (_WIN32_IE >= 0x0400) | |
1658 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandl
ed*/) | |
1659 { | |
1660 T* pT = static_cast<T*>(this); | |
1661 pT->UpdateLayout(FALSE); | |
1662 return 0; | |
1663 } | |
1664 #endif // (_WIN32_IE >= 0x0400) | |
1665 | |
1666 #if (_WIN32_IE >= 0x0500) | |
1667 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
1668 { | |
1669 T* pT = static_cast<T*>(this); | |
1670 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; | |
1671 if(!pT->PrepareChevronMenu(cmi)) | |
1672 { | |
1673 bHandled = FALSE; | |
1674 return 1; | |
1675 } | |
1676 // display a popup menu with hidden items | |
1677 pT->DisplayChevronMenu(cmi); | |
1678 // cleanup | |
1679 pT->CleanupChevronMenu(cmi); | |
1680 return 0; | |
1681 } | |
1682 #endif // (_WIN32_IE >= 0x0500) | |
1683 #endif // !_ATL_NO_REBAR_SUPPORT | |
1684 }; | |
1685 | |
1686 #endif // !_WIN32_WCE | |
1687 | |
1688 | |
1689 /////////////////////////////////////////////////////////////////////////////// | |
1690 // CMDIChildWindowImpl | |
1691 | |
1692 #ifndef _WIN32_WCE | |
1693 | |
1694 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CMDIChildWi
nTraits> | |
1695 class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWi
nTraits > | |
1696 { | |
1697 public: | |
1698 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowN
ame = NULL, | |
1699 DWORD dwStyle = 0, DWORD dwExStyle = 0, | |
1700 UINT nMenuID = 0, LPVOID lpCreateParam = NULL) | |
1701 { | |
1702 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc)
; | |
1703 | |
1704 if(nMenuID != 0) | |
1705 m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance()
, MAKEINTRESOURCE(nMenuID)); | |
1706 | |
1707 dwStyle = T::GetWndStyle(dwStyle); | |
1708 dwExStyle = T::GetWndExStyle(dwExStyle); | |
1709 | |
1710 dwExStyle |= WS_EX_MDICHILD; // force this one | |
1711 m_pfnSuperWindowProc = ::DefMDIChildProc; | |
1712 m_hWndMDIClient = hWndParent; | |
1713 ATLASSERT(::IsWindow(m_hWndMDIClient)); | |
1714 | |
1715 if(rect.m_lpRect == NULL) | |
1716 rect.m_lpRect = &TBase::rcDefault; | |
1717 | |
1718 // If the currently active MDI child is maximized, we want to cr
eate this one maximized too | |
1719 ATL::CWindow wndParent = hWndParent; | |
1720 BOOL bMaximized = FALSE; | |
1721 wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized); | |
1722 if(bMaximized) | |
1723 wndParent.SetRedraw(FALSE); | |
1724 | |
1725 HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWn
dParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCrea
teParam); | |
1726 | |
1727 if(bMaximized) | |
1728 { | |
1729 // Maximize and redraw everything | |
1730 if(hWnd != NULL) | |
1731 MDIMaximize(hWnd); | |
1732 wndParent.SetRedraw(TRUE); | |
1733 wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_
ALLCHILDREN); | |
1734 ::SetFocus(GetMDIFrame()); // focus will be set back t
o this window | |
1735 } | |
1736 else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(
hWnd, ::GetFocus())) | |
1737 { | |
1738 ::SetFocus(hWnd); | |
1739 } | |
1740 | |
1741 return hWnd; | |
1742 } | |
1743 | |
1744 HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrW
indowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam =
NULL) | |
1745 { | |
1746 const int cchName = 256; | |
1747 TCHAR szWindowName[cchName]; | |
1748 szWindowName[0] = 0; | |
1749 if(lpcstrWindowName == NULL) | |
1750 { | |
1751 ::LoadString(ModuleHelper::GetResourceInstance(), T::Get
WndClassInfo().m_uCommonResourceID, szWindowName, cchName); | |
1752 lpcstrWindowName = szWindowName; | |
1753 } | |
1754 | |
1755 T* pT = static_cast<T*>(this); | |
1756 HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwSty
le, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam); | |
1757 | |
1758 if(hWnd != NULL) | |
1759 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceI
nstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID)); | |
1760 | |
1761 return hWnd; | |
1762 } | |
1763 | |
1764 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPL
E_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR) | |
1765 { | |
1766 ATLASSERT(!::IsWindow(m_hWndToolBar)); | |
1767 if(nResourceID == 0) | |
1768 nResourceID = T::GetWndClassInfo().m_uCommonResourceID; | |
1769 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID,
TRUE, dwStyle, nID); | |
1770 return (m_hWndToolBar != NULL); | |
1771 } | |
1772 | |
1773 BOOL UpdateClientEdge(LPRECT lpRect = NULL) | |
1774 { | |
1775 // only adjust for active MDI child window | |
1776 HWND hWndChild = MDIGetActive(); | |
1777 if(hWndChild != NULL && hWndChild != m_hWnd) | |
1778 return FALSE; | |
1779 | |
1780 // need to adjust the client edge style as max/restore happens | |
1781 DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE); | |
1782 DWORD dwNewStyle = dwStyle; | |
1783 if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0)
&& ((GetStyle() & WS_MAXIMIZE) != 0)) | |
1784 dwNewStyle &= ~(WS_EX_CLIENTEDGE); | |
1785 else | |
1786 dwNewStyle |= WS_EX_CLIENTEDGE; | |
1787 | |
1788 if(dwStyle != dwNewStyle) | |
1789 { | |
1790 // SetWindowPos will not move invalid bits | |
1791 ::RedrawWindow(m_hWndMDIClient, NULL, NULL, | |
1792 RDW_INVALIDATE | RDW_ALLCHILDREN); | |
1793 // remove/add WS_EX_CLIENTEDGE to MDI client area | |
1794 ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle
); | |
1795 ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0, | |
1796 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE |
SWP_NOSIZE | | |
1797 SWP_NOZORDER | SWP_NOCOPYBITS); | |
1798 | |
1799 // return new client area | |
1800 if (lpRect != NULL) | |
1801 ::GetClientRect(m_hWndMDIClient, lpRect); | |
1802 | |
1803 return TRUE; | |
1804 } | |
1805 | |
1806 return FALSE; | |
1807 } | |
1808 | |
1809 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass; | |
1810 BEGIN_MSG_MAP(CMDIChildWindowImpl) | |
1811 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
1812 MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged) | |
1813 MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate) | |
1814 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect) | |
1815 MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate) | |
1816 MESSAGE_HANDLER(WM_DESTROY, OnDestroy) | |
1817 #ifndef _ATL_NO_REBAR_SUPPORT | |
1818 #if (_WIN32_IE >= 0x0400) | |
1819 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize) | |
1820 #endif // (_WIN32_IE >= 0x0400) | |
1821 #if (_WIN32_IE >= 0x0500) | |
1822 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed) | |
1823 #endif // (_WIN32_IE >= 0x0500) | |
1824 #endif // !_ATL_NO_REBAR_SUPPORT | |
1825 CHAIN_MSG_MAP(_baseClass) | |
1826 END_MSG_MAP() | |
1827 | |
1828 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled
*/) | |
1829 { | |
1830 DefWindowProc(uMsg, wParam, lParam); // needed for MDI childre
n | |
1831 if(wParam != SIZE_MINIMIZED) | |
1832 { | |
1833 T* pT = static_cast<T*>(this); | |
1834 pT->UpdateLayout(); | |
1835 } | |
1836 return 0; | |
1837 } | |
1838 | |
1839 LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lPar
am, BOOL& bHandled) | |
1840 { | |
1841 // update MDI client edge and adjust MDI child rect | |
1842 LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam; | |
1843 | |
1844 if(!(lpWndPos->flags & SWP_NOSIZE)) | |
1845 { | |
1846 RECT rectClient; | |
1847 if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MA
XIMIZE) != 0)) | |
1848 { | |
1849 ::AdjustWindowRectEx(&rectClient, GetStyle(), FA
LSE, GetExStyle()); | |
1850 lpWndPos->x = rectClient.left; | |
1851 lpWndPos->y = rectClient.top; | |
1852 lpWndPos->cx = rectClient.right - rectClient.lef
t; | |
1853 lpWndPos->cy = rectClient.bottom - rectClient.to
p; | |
1854 } | |
1855 } | |
1856 | |
1857 bHandled = FALSE; | |
1858 return 1; | |
1859 } | |
1860 | |
1861 LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /
*bHandled*/) | |
1862 { | |
1863 LRESULT lRes = DefWindowProc(uMsg, wParam, lParam); | |
1864 | |
1865 // Activate this MDI window if needed | |
1866 if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT) | |
1867 { | |
1868 if(MDIGetActive() != m_hWnd) | |
1869 MDIActivate(m_hWnd); | |
1870 } | |
1871 | |
1872 return lRes; | |
1873 } | |
1874 | |
1875 LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bH
andled*/) | |
1876 { | |
1877 return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam); | |
1878 } | |
1879 | |
1880 LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
1881 { | |
1882 if((HWND)lParam == m_hWnd && m_hMenu != NULL) | |
1883 SetMDIFrameMenu(); | |
1884 else if((HWND)lParam == NULL) | |
1885 ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0); | |
1886 | |
1887 bHandled = FALSE; | |
1888 return 1; | |
1889 } | |
1890 | |
1891 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, B
OOL& bHandled) | |
1892 { | |
1893 if(m_hMenu != NULL) | |
1894 { | |
1895 ::DestroyMenu(m_hMenu); | |
1896 m_hMenu = NULL; | |
1897 } | |
1898 UpdateClientEdge(); | |
1899 bHandled = FALSE; | |
1900 return 1; | |
1901 } | |
1902 | |
1903 #ifndef _ATL_NO_REBAR_SUPPORT | |
1904 #if (_WIN32_IE >= 0x0400) | |
1905 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandl
ed*/) | |
1906 { | |
1907 T* pT = static_cast<T*>(this); | |
1908 pT->UpdateLayout(FALSE); | |
1909 return 0; | |
1910 } | |
1911 #endif // (_WIN32_IE >= 0x0400) | |
1912 | |
1913 #if (_WIN32_IE >= 0x0500) | |
1914 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled) | |
1915 { | |
1916 T* pT = static_cast<T*>(this); | |
1917 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false }; | |
1918 if(!pT->PrepareChevronMenu(cmi)) | |
1919 { | |
1920 bHandled = FALSE; | |
1921 return 1; | |
1922 } | |
1923 // display a popup menu with hidden items | |
1924 pT->DisplayChevronMenu(cmi); | |
1925 // cleanup | |
1926 pT->CleanupChevronMenu(cmi); | |
1927 return 0; | |
1928 } | |
1929 #endif // (_WIN32_IE >= 0x0500) | |
1930 #endif // !_ATL_NO_REBAR_SUPPORT | |
1931 }; | |
1932 | |
1933 #endif // !_WIN32_WCE | |
1934 | |
1935 | |
1936 /////////////////////////////////////////////////////////////////////////////// | |
1937 // COwnerDraw - MI class for owner-draw support | |
1938 | |
1939 template <class T> | |
1940 class COwnerDraw | |
1941 { | |
1942 public: | |
1943 #if (_ATL_VER < 0x0700) | |
1944 BOOL m_bHandledOD; | |
1945 | |
1946 BOOL IsMsgHandled() const | |
1947 { | |
1948 return m_bHandledOD; | |
1949 } | |
1950 void SetMsgHandled(BOOL bHandled) | |
1951 { | |
1952 m_bHandledOD = bHandled; | |
1953 } | |
1954 #endif // (_ATL_VER < 0x0700) | |
1955 | |
1956 // Message map and handlers | |
1957 BEGIN_MSG_MAP(COwnerDraw< T >) | |
1958 MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem) | |
1959 MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem) | |
1960 MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem) | |
1961 MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem) | |
1962 ALT_MSG_MAP(1) | |
1963 MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem) | |
1964 MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem) | |
1965 MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem) | |
1966 MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem) | |
1967 END_MSG_MAP() | |
1968 | |
1969 LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL
& bHandled) | |
1970 { | |
1971 T* pT = static_cast<T*>(this); | |
1972 pT->SetMsgHandled(TRUE); | |
1973 pT->DrawItem((LPDRAWITEMSTRUCT)lParam); | |
1974 bHandled = pT->IsMsgHandled(); | |
1975 return (LRESULT)TRUE; | |
1976 } | |
1977 | |
1978 LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
1979 { | |
1980 T* pT = static_cast<T*>(this); | |
1981 pT->SetMsgHandled(TRUE); | |
1982 pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam); | |
1983 bHandled = pT->IsMsgHandled(); | |
1984 return (LRESULT)TRUE; | |
1985 } | |
1986 | |
1987 LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, B
OOL& bHandled) | |
1988 { | |
1989 T* pT = static_cast<T*>(this); | |
1990 pT->SetMsgHandled(TRUE); | |
1991 bHandled = pT->IsMsgHandled(); | |
1992 return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam); | |
1993 } | |
1994 | |
1995 LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BO
OL& bHandled) | |
1996 { | |
1997 T* pT = static_cast<T*>(this); | |
1998 pT->SetMsgHandled(TRUE); | |
1999 pT->DeleteItem((LPDELETEITEMSTRUCT)lParam); | |
2000 bHandled = pT->IsMsgHandled(); | |
2001 return (LRESULT)TRUE; | |
2002 } | |
2003 | |
2004 // Overrideables | |
2005 void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/) | |
2006 { | |
2007 // must be implemented | |
2008 ATLASSERT(FALSE); | |
2009 } | |
2010 | |
2011 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) | |
2012 { | |
2013 if(lpMeasureItemStruct->CtlType != ODT_MENU) | |
2014 { | |
2015 // return default height for a system font | |
2016 T* pT = static_cast<T*>(this); | |
2017 HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID); | |
2018 CClientDC dc(hWnd); | |
2019 TEXTMETRIC tm = { 0 }; | |
2020 dc.GetTextMetrics(&tm); | |
2021 | |
2022 lpMeasureItemStruct->itemHeight = tm.tmHeight; | |
2023 } | |
2024 else | |
2025 lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_
CYMENU); | |
2026 } | |
2027 | |
2028 int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/) | |
2029 { | |
2030 // all items are equal | |
2031 return 0; | |
2032 } | |
2033 | |
2034 void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/) | |
2035 { | |
2036 // default - nothing | |
2037 } | |
2038 }; | |
2039 | |
2040 | |
2041 /////////////////////////////////////////////////////////////////////////////// | |
2042 // Update UI macros | |
2043 | |
2044 // these build the Update UI map inside a class definition | |
2045 #define BEGIN_UPDATE_UI_MAP(thisClass) \ | |
2046 static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \ | |
2047 { \ | |
2048 static const _AtlUpdateUIMap theMap[] = \ | |
2049 { | |
2050 | |
2051 #define UPDATE_ELEMENT(nID, wType) \ | |
2052 { nID, wType }, | |
2053 | |
2054 #define END_UPDATE_UI_MAP() \ | |
2055 { (WORD)-1, 0 } \ | |
2056 }; \ | |
2057 return theMap; \ | |
2058 } | |
2059 | |
2060 /////////////////////////////////////////////////////////////////////////////// | |
2061 // CUpdateUI - manages UI elements updating | |
2062 | |
2063 class CUpdateUIBase | |
2064 { | |
2065 public: | |
2066 // constants | |
2067 enum | |
2068 { | |
2069 // UI element type | |
2070 UPDUI_MENUPOPUP = 0x0001, | |
2071 UPDUI_MENUBAR = 0x0002, | |
2072 UPDUI_CHILDWINDOW = 0x0004, | |
2073 UPDUI_TOOLBAR = 0x0008, | |
2074 UPDUI_STATUSBAR = 0x0010, | |
2075 // state | |
2076 UPDUI_ENABLED = 0x0000, | |
2077 UPDUI_DISABLED = 0x0100, | |
2078 UPDUI_CHECKED = 0x0200, | |
2079 UPDUI_CHECKED2 = 0x0400, | |
2080 UPDUI_RADIO = 0x0800, | |
2081 UPDUI_DEFAULT = 0x1000, | |
2082 UPDUI_TEXT = 0x2000, | |
2083 // internal state | |
2084 UPDUI_CLEARDEFAULT = 0x4000, | |
2085 }; | |
2086 | |
2087 // element data | |
2088 struct _AtlUpdateUIElement | |
2089 { | |
2090 HWND m_hWnd; | |
2091 WORD m_wType; | |
2092 | |
2093 bool operator ==(const _AtlUpdateUIElement& e) const | |
2094 { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); } | |
2095 }; | |
2096 | |
2097 // map data | |
2098 struct _AtlUpdateUIMap | |
2099 { | |
2100 WORD m_nID; | |
2101 WORD m_wType; | |
2102 | |
2103 bool operator ==(const _AtlUpdateUIMap& e) const | |
2104 { return (m_nID == e.m_nID && m_wType == e.m_wType); } | |
2105 }; | |
2106 | |
2107 // instance data | |
2108 struct _AtlUpdateUIData | |
2109 { | |
2110 WORD m_wState; | |
2111 union | |
2112 { | |
2113 void* m_lpData; | |
2114 LPTSTR m_lpstrText; | |
2115 }; | |
2116 | |
2117 bool operator ==(const _AtlUpdateUIData& e) const | |
2118 { return (m_wState == e.m_wState && m_lpData == e.m_lpData); } | |
2119 }; | |
2120 | |
2121 ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data | |
2122 const _AtlUpdateUIMap* m_pUIMap; // static UI data | |
2123 _AtlUpdateUIData* m_pUIData; // instance UI da
ta | |
2124 WORD m_wDirtyType; // global dirty f
lag | |
2125 | |
2126 bool m_bBlockAccelerators; | |
2127 | |
2128 | |
2129 // Constructor, destructor | |
2130 CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bB
lockAccelerators(false) | |
2131 { } | |
2132 | |
2133 ~CUpdateUIBase() | |
2134 { | |
2135 if(m_pUIMap != NULL && m_pUIData != NULL) | |
2136 { | |
2137 const _AtlUpdateUIMap* pUIMap = m_pUIMap; | |
2138 _AtlUpdateUIData* pUIData = m_pUIData; | |
2139 while(pUIMap->m_nID != (WORD)-1) | |
2140 { | |
2141 if(pUIData->m_wState & UPDUI_TEXT) | |
2142 delete [] pUIData->m_lpstrText; | |
2143 pUIMap++; | |
2144 pUIData++; | |
2145 } | |
2146 delete [] m_pUIData; | |
2147 } | |
2148 } | |
2149 | |
2150 // Check for disabled commands | |
2151 bool UIGetBlockAccelerators() const | |
2152 { | |
2153 return m_bBlockAccelerators; | |
2154 } | |
2155 | |
2156 bool UISetBlockAccelerators(bool bBlock) | |
2157 { | |
2158 bool bOld = m_bBlockAccelerators; | |
2159 m_bBlockAccelerators = bBlock; | |
2160 return bOld; | |
2161 } | |
2162 | |
2163 // Add elements | |
2164 BOOL UIAddMenuBar(HWND hWnd) // menu bar (main menu) | |
2165 { | |
2166 if(hWnd == NULL) | |
2167 return FALSE; | |
2168 _AtlUpdateUIElement e; | |
2169 e.m_hWnd = hWnd; | |
2170 e.m_wType = UPDUI_MENUBAR; | |
2171 return m_UIElements.Add(e); | |
2172 } | |
2173 | |
2174 BOOL UIAddToolBar(HWND hWnd) // toolbar | |
2175 { | |
2176 if(hWnd == NULL) | |
2177 return FALSE; | |
2178 _AtlUpdateUIElement e; | |
2179 e.m_hWnd = hWnd; | |
2180 e.m_wType = UPDUI_TOOLBAR; | |
2181 return m_UIElements.Add(e); | |
2182 } | |
2183 | |
2184 BOOL UIAddStatusBar(HWND hWnd) // status bar | |
2185 { | |
2186 if(hWnd == NULL) | |
2187 return FALSE; | |
2188 _AtlUpdateUIElement e; | |
2189 e.m_hWnd = hWnd; | |
2190 e.m_wType = UPDUI_STATUSBAR; | |
2191 return m_UIElements.Add(e); | |
2192 } | |
2193 | |
2194 BOOL UIAddChildWindowContainer(HWND hWnd) // child window | |
2195 { | |
2196 if(hWnd == NULL) | |
2197 return FALSE; | |
2198 _AtlUpdateUIElement e; | |
2199 e.m_hWnd = hWnd; | |
2200 e.m_wType = UPDUI_CHILDWINDOW; | |
2201 return m_UIElements.Add(e); | |
2202 } | |
2203 | |
2204 // Message map for popup menu updates and accelerator blocking | |
2205 BEGIN_MSG_MAP(CUpdateUIBase) | |
2206 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup) | |
2207 MESSAGE_HANDLER(WM_COMMAND, OnCommand) | |
2208 END_MSG_MAP() | |
2209 | |
2210 LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/,
BOOL& bHandled) | |
2211 { | |
2212 bHandled = FALSE; | |
2213 HMENU hMenu = (HMENU)wParam; | |
2214 if(hMenu == NULL) | |
2215 return 1; | |
2216 _AtlUpdateUIData* pUIData = m_pUIData; | |
2217 if(pUIData == NULL) | |
2218 return 1; | |
2219 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2220 while(pMap->m_nID != (WORD)-1) | |
2221 { | |
2222 if(pMap->m_wType & UPDUI_MENUPOPUP) | |
2223 UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMe
nu); | |
2224 pMap++; | |
2225 pUIData++; | |
2226 } | |
2227 return 0; | |
2228 } | |
2229 | |
2230 LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL&
bHandled) | |
2231 { | |
2232 bHandled = FALSE; | |
2233 if(m_bBlockAccelerators && HIWORD(wParam) == 1) // accelerator
s only | |
2234 { | |
2235 int nID = LOWORD(wParam); | |
2236 if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED) | |
2237 { | |
2238 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCo
mmand - blocked disabled command 0x%4.4X\n"), nID); | |
2239 bHandled = TRUE; // eat the command, UI item i
s disabled | |
2240 } | |
2241 } | |
2242 return 0; | |
2243 } | |
2244 | |
2245 // methods for setting UI element state | |
2246 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE) | |
2247 { | |
2248 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2249 _AtlUpdateUIData* pUIData = m_pUIData; | |
2250 if(pUIData == NULL) | |
2251 return FALSE; | |
2252 | |
2253 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2254 { | |
2255 if(nID == (int)pMap->m_nID) | |
2256 { | |
2257 if(bEnable) | |
2258 { | |
2259 if(pUIData->m_wState & UPDUI_DISABLED) | |
2260 { | |
2261 pUIData->m_wState |= pMap->m_wTy
pe; | |
2262 pUIData->m_wState &= ~UPDUI_DISA
BLED; | |
2263 } | |
2264 } | |
2265 else | |
2266 { | |
2267 if(!(pUIData->m_wState & UPDUI_DISABLED)
) | |
2268 { | |
2269 pUIData->m_wState |= pMap->m_wTy
pe; | |
2270 pUIData->m_wState |= UPDUI_DISAB
LED; | |
2271 } | |
2272 } | |
2273 | |
2274 if(bForceUpdate) | |
2275 pUIData->m_wState |= pMap->m_wType; | |
2276 if(pUIData->m_wState & pMap->m_wType) | |
2277 m_wDirtyType |= pMap->m_wType; | |
2278 | |
2279 break; // found | |
2280 } | |
2281 } | |
2282 | |
2283 return TRUE; | |
2284 } | |
2285 | |
2286 BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE) | |
2287 { | |
2288 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2289 _AtlUpdateUIData* pUIData = m_pUIData; | |
2290 if(pUIData == NULL) | |
2291 return FALSE; | |
2292 | |
2293 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2294 { | |
2295 if(nID == (int)pMap->m_nID) | |
2296 { | |
2297 switch(nCheck) | |
2298 { | |
2299 case 0: | |
2300 if((pUIData->m_wState & UPDUI_CHECKED) |
| (pUIData->m_wState & UPDUI_CHECKED2)) | |
2301 { | |
2302 pUIData->m_wState |= pMap->m_wTy
pe; | |
2303 pUIData->m_wState &= ~(UPDUI_CHE
CKED | UPDUI_CHECKED2); | |
2304 } | |
2305 break; | |
2306 case 1: | |
2307 if(!(pUIData->m_wState & UPDUI_CHECKED)) | |
2308 { | |
2309 pUIData->m_wState |= pMap->m_wTy
pe; | |
2310 pUIData->m_wState &= ~UPDUI_CHEC
KED2; | |
2311 pUIData->m_wState |= UPDUI_CHECK
ED; | |
2312 } | |
2313 break; | |
2314 case 2: | |
2315 if(!(pUIData->m_wState & UPDUI_CHECKED2)
) | |
2316 { | |
2317 pUIData->m_wState |= pMap->m_wTy
pe; | |
2318 pUIData->m_wState &= ~UPDUI_CHEC
KED; | |
2319 pUIData->m_wState |= UPDUI_CHECK
ED2; | |
2320 } | |
2321 break; | |
2322 } | |
2323 | |
2324 if(bForceUpdate) | |
2325 pUIData->m_wState |= pMap->m_wType; | |
2326 if(pUIData->m_wState & pMap->m_wType) | |
2327 m_wDirtyType |= pMap->m_wType; | |
2328 | |
2329 break; // found | |
2330 } | |
2331 } | |
2332 | |
2333 return TRUE; | |
2334 } | |
2335 | |
2336 // variant that supports bool (checked/not-checked, no intermediate stat
e) | |
2337 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE) | |
2338 { | |
2339 return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate); | |
2340 } | |
2341 | |
2342 BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE) | |
2343 { | |
2344 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2345 _AtlUpdateUIData* pUIData = m_pUIData; | |
2346 if(pUIData == NULL) | |
2347 return FALSE; | |
2348 | |
2349 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2350 { | |
2351 if(nID == (int)pMap->m_nID) | |
2352 { | |
2353 if(bRadio) | |
2354 { | |
2355 if(!(pUIData->m_wState & UPDUI_RADIO)) | |
2356 { | |
2357 pUIData->m_wState |= pMap->m_wTy
pe; | |
2358 pUIData->m_wState |= UPDUI_RADIO
; | |
2359 } | |
2360 } | |
2361 else | |
2362 { | |
2363 if(pUIData->m_wState & UPDUI_RADIO) | |
2364 { | |
2365 pUIData->m_wState |= pMap->m_wTy
pe; | |
2366 pUIData->m_wState &= ~UPDUI_RADI
O; | |
2367 } | |
2368 } | |
2369 | |
2370 if(bForceUpdate) | |
2371 pUIData->m_wState |= pMap->m_wType; | |
2372 if(pUIData->m_wState & pMap->m_wType) | |
2373 m_wDirtyType |= pMap->m_wType; | |
2374 | |
2375 break; // found | |
2376 } | |
2377 } | |
2378 | |
2379 return TRUE; | |
2380 } | |
2381 | |
2382 BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE) | |
2383 { | |
2384 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2385 _AtlUpdateUIData* pUIData = m_pUIData; | |
2386 if(pUIData == NULL) | |
2387 return FALSE; | |
2388 if(lpstrText == NULL) | |
2389 lpstrText = _T(""); | |
2390 | |
2391 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2392 { | |
2393 if(nID == (int)pMap->m_nID) | |
2394 { | |
2395 if(pUIData->m_lpstrText == NULL || lstrcmp(pUIDa
ta->m_lpstrText, lpstrText)) | |
2396 { | |
2397 delete [] pUIData->m_lpstrText; | |
2398 pUIData->m_lpstrText = NULL; | |
2399 int nStrLen = lstrlen(lpstrText); | |
2400 ATLTRY(pUIData->m_lpstrText = new TCHAR[
nStrLen + 1]); | |
2401 if(pUIData->m_lpstrText == NULL) | |
2402 { | |
2403 ATLTRACE2(atlTraceUI, 0, _T("UIS
etText - memory allocation failed\n")); | |
2404 break; | |
2405 } | |
2406 SecureHelper::strcpy_x(pUIData->m_lpstrT
ext, nStrLen + 1, lpstrText); | |
2407 pUIData->m_wState |= (UPDUI_TEXT | pMap-
>m_wType); | |
2408 } | |
2409 | |
2410 if(bForceUpdate) | |
2411 pUIData->m_wState |= (UPDUI_TEXT | pMap-
>m_wType); | |
2412 if(pUIData->m_wState & pMap->m_wType) | |
2413 m_wDirtyType |= pMap->m_wType; | |
2414 | |
2415 break; // found | |
2416 } | |
2417 } | |
2418 | |
2419 return TRUE; | |
2420 } | |
2421 | |
2422 BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE) | |
2423 { | |
2424 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2425 _AtlUpdateUIData* pUIData = m_pUIData; | |
2426 if(pUIData == NULL) | |
2427 return FALSE; | |
2428 | |
2429 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2430 { | |
2431 if(nID == (int)pMap->m_nID) | |
2432 { | |
2433 if(bDefault) | |
2434 { | |
2435 if((pUIData->m_wState & UPDUI_DEFAULT) =
= 0) | |
2436 { | |
2437 pUIData->m_wState |= pMap->m_wTy
pe; | |
2438 pUIData->m_wState |= UPDUI_DEFAU
LT; | |
2439 } | |
2440 } | |
2441 else | |
2442 { | |
2443 if((pUIData->m_wState & UPDUI_DEFAULT) !
= 0) | |
2444 { | |
2445 pUIData->m_wState |= pMap->m_wTy
pe; | |
2446 pUIData->m_wState &= ~UPDUI_DEFA
ULT; | |
2447 pUIData->m_wState |= UPDUI_CLEAR
DEFAULT; | |
2448 } | |
2449 } | |
2450 | |
2451 if(bForceUpdate) | |
2452 pUIData->m_wState |= pMap->m_wType; | |
2453 if(pUIData->m_wState & pMap->m_wType) | |
2454 m_wDirtyType |= pMap->m_wType; | |
2455 | |
2456 break; // found | |
2457 } | |
2458 } | |
2459 | |
2460 return TRUE; | |
2461 } | |
2462 | |
2463 // methods for complete state set/get | |
2464 BOOL UISetState(int nID, DWORD dwState) | |
2465 { | |
2466 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2467 _AtlUpdateUIData* pUIData = m_pUIData; | |
2468 if(pUIData == NULL) | |
2469 return FALSE; | |
2470 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2471 { | |
2472 if(nID == (int)pMap->m_nID) | |
2473 { | |
2474 pUIData->m_wState = (WORD)(dwState | pMap->m_wTy
pe); | |
2475 m_wDirtyType |= pMap->m_wType; | |
2476 break; // found | |
2477 } | |
2478 } | |
2479 return TRUE; | |
2480 } | |
2481 | |
2482 DWORD UIGetState(int nID) | |
2483 { | |
2484 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2485 _AtlUpdateUIData* pUIData = m_pUIData; | |
2486 if(pUIData == NULL) | |
2487 return 0; | |
2488 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++) | |
2489 { | |
2490 if(nID == (int)pMap->m_nID) | |
2491 return pUIData->m_wState; | |
2492 } | |
2493 return 0; | |
2494 } | |
2495 | |
2496 // methods for updating UI | |
2497 #ifndef _WIN32_WCE | |
2498 BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE) | |
2499 { | |
2500 if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate) | |
2501 return TRUE; | |
2502 | |
2503 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2504 _AtlUpdateUIData* pUIData = m_pUIData; | |
2505 if(pUIData == NULL) | |
2506 return FALSE; | |
2507 | |
2508 while(pMap->m_nID != (WORD)-1) | |
2509 { | |
2510 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
2511 { | |
2512 if(m_UIElements[i].m_wType == UPDUI_MENUBAR) | |
2513 { | |
2514 HMENU hMenu = ::GetMenu(m_UIElements[i].
m_hWnd); | |
2515 if(hMenu != NULL && (pUIData->m_wState &
UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR)) | |
2516 UIUpdateMenuBarElement(pMap->m_n
ID, pUIData, hMenu); | |
2517 } | |
2518 if(bMainMenu) | |
2519 ::DrawMenuBar(m_UIElements[i].m_hWnd); | |
2520 } | |
2521 pMap++; | |
2522 pUIData->m_wState &= ~UPDUI_MENUBAR; | |
2523 if(pUIData->m_wState & UPDUI_TEXT) | |
2524 { | |
2525 delete [] pUIData->m_lpstrText; | |
2526 pUIData->m_lpstrText = NULL; | |
2527 pUIData->m_wState &= ~UPDUI_TEXT; | |
2528 } | |
2529 pUIData++; | |
2530 } | |
2531 | |
2532 m_wDirtyType &= ~UPDUI_MENUBAR; | |
2533 return TRUE; | |
2534 } | |
2535 #endif // !_WIN32_WCE | |
2536 | |
2537 BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE) | |
2538 { | |
2539 if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate) | |
2540 return TRUE; | |
2541 | |
2542 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2543 _AtlUpdateUIData* pUIData = m_pUIData; | |
2544 if(pUIData == NULL) | |
2545 return FALSE; | |
2546 | |
2547 while(pMap->m_nID != (WORD)-1) | |
2548 { | |
2549 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
2550 { | |
2551 if(m_UIElements[i].m_wType == UPDUI_TOOLBAR) | |
2552 { | |
2553 if((pUIData->m_wState & UPDUI_TOOLBAR) &
& (pMap->m_wType & UPDUI_TOOLBAR)) | |
2554 UIUpdateToolBarElement(pMap->m_n
ID, pUIData, m_UIElements[i].m_hWnd); | |
2555 } | |
2556 } | |
2557 pMap++; | |
2558 pUIData->m_wState &= ~UPDUI_TOOLBAR; | |
2559 pUIData++; | |
2560 } | |
2561 | |
2562 m_wDirtyType &= ~UPDUI_TOOLBAR; | |
2563 return TRUE; | |
2564 } | |
2565 | |
2566 BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE) | |
2567 { | |
2568 if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate) | |
2569 return TRUE; | |
2570 | |
2571 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2572 _AtlUpdateUIData* pUIData = m_pUIData; | |
2573 if(pUIData == NULL) | |
2574 return FALSE; | |
2575 | |
2576 while(pMap->m_nID != (WORD)-1) | |
2577 { | |
2578 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
2579 { | |
2580 if(m_UIElements[i].m_wType == UPDUI_STATUSBAR) | |
2581 { | |
2582 if((pUIData->m_wState & UPDUI_STATUSBAR)
&& (pMap->m_wType & UPDUI_STATUSBAR)) | |
2583 UIUpdateStatusBarElement(pMap->m
_nID, pUIData, m_UIElements[i].m_hWnd); | |
2584 } | |
2585 } | |
2586 pMap++; | |
2587 pUIData->m_wState &= ~UPDUI_STATUSBAR; | |
2588 if(pUIData->m_wState & UPDUI_TEXT) | |
2589 { | |
2590 delete [] pUIData->m_lpstrText; | |
2591 pUIData->m_lpstrText = NULL; | |
2592 pUIData->m_wState &= ~UPDUI_TEXT; | |
2593 } | |
2594 pUIData++; | |
2595 } | |
2596 | |
2597 m_wDirtyType &= ~UPDUI_STATUSBAR; | |
2598 return TRUE; | |
2599 } | |
2600 | |
2601 BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE) | |
2602 { | |
2603 if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate) | |
2604 return TRUE; | |
2605 | |
2606 const _AtlUpdateUIMap* pMap = m_pUIMap; | |
2607 _AtlUpdateUIData* pUIData = m_pUIData; | |
2608 if(pUIData == NULL) | |
2609 return FALSE; | |
2610 | |
2611 while(pMap->m_nID != (WORD)-1) | |
2612 { | |
2613 for(int i = 0; i < m_UIElements.GetSize(); i++) | |
2614 { | |
2615 if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW) | |
2616 { | |
2617 if((pUIData->m_wState & UPDUI_CHILDWINDO
W) && (pMap->m_wType & UPDUI_CHILDWINDOW)) | |
2618 UIUpdateChildWindow(pMap->m_nID,
pUIData, m_UIElements[i].m_hWnd); | |
2619 } | |
2620 } | |
2621 pMap++; | |
2622 pUIData->m_wState &= ~UPDUI_CHILDWINDOW; | |
2623 if(pUIData->m_wState & UPDUI_TEXT) | |
2624 { | |
2625 delete [] pUIData->m_lpstrText; | |
2626 pUIData->m_lpstrText = NULL; | |
2627 pUIData->m_wState &= ~UPDUI_TEXT; | |
2628 } | |
2629 pUIData++; | |
2630 } | |
2631 | |
2632 m_wDirtyType &= ~UPDUI_CHILDWINDOW; | |
2633 return TRUE; | |
2634 } | |
2635 | |
2636 // internal element specific methods | |
2637 static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, H
MENU hMenu) | |
2638 { | |
2639 #ifndef _WIN32_WCE | |
2640 if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0) | |
2641 { | |
2642 ::SetMenuDefaultItem(hMenu, (UINT)-1, 0); | |
2643 pUIData->m_wState &= ~UPDUI_CLEARDEFAULT; | |
2644 } | |
2645 #endif // !_WIN32_WCE | |
2646 | |
2647 CMenuItemInfo mii; | |
2648 mii.fMask = MIIM_STATE; | |
2649 mii.wID = nID; | |
2650 | |
2651 #ifndef _WIN32_WCE | |
2652 if((pUIData->m_wState & UPDUI_DISABLED) != 0) | |
2653 mii.fState |= MFS_DISABLED | MFS_GRAYED; | |
2654 else | |
2655 mii.fState |= MFS_ENABLED; | |
2656 | |
2657 if((pUIData->m_wState & UPDUI_CHECKED) != 0) | |
2658 mii.fState |= MFS_CHECKED; | |
2659 else | |
2660 mii.fState |= MFS_UNCHECKED; | |
2661 | |
2662 if((pUIData->m_wState & UPDUI_DEFAULT) != 0) | |
2663 mii.fState |= MFS_DEFAULT; | |
2664 #else // CE specific | |
2665 // ::SetMenuItemInfo() can't disable or check menu items | |
2666 // on Windows CE, so we have to do that directly | |
2667 UINT uEnable = MF_BYCOMMAND; | |
2668 if((pUIData->m_wState & UPDUI_DISABLED) != 0) | |
2669 uEnable |= MF_GRAYED; | |
2670 else | |
2671 uEnable |= MF_ENABLED; | |
2672 ::EnableMenuItem(hMenu, nID, uEnable); | |
2673 | |
2674 UINT uCheck = MF_BYCOMMAND; | |
2675 if((pUIData->m_wState & UPDUI_CHECKED) != 0) | |
2676 uCheck |= MF_CHECKED; | |
2677 else | |
2678 uCheck |= MF_UNCHECKED; | |
2679 ::CheckMenuItem(hMenu, nID, uCheck); | |
2680 #endif // _WIN32_WCE | |
2681 | |
2682 if((pUIData->m_wState & UPDUI_TEXT) != 0) | |
2683 { | |
2684 CMenuItemInfo miiNow; | |
2685 miiNow.fMask = MIIM_TYPE; | |
2686 miiNow.wID = nID; | |
2687 if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow)) | |
2688 { | |
2689 mii.fMask |= MIIM_TYPE; | |
2690 // MFT_BITMAP and MFT_SEPARATOR don't go togethe
r with MFT_STRING | |
2691 #ifndef _WIN32_WCE | |
2692 mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_
SEPARATOR)) | MFT_STRING; | |
2693 #else // CE specific | |
2694 mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) |
MFT_STRING; | |
2695 #endif // _WIN32_WCE | |
2696 mii.dwTypeData = pUIData->m_lpstrText; | |
2697 } | |
2698 } | |
2699 | |
2700 ::SetMenuItemInfo(hMenu, nID, FALSE, &mii); | |
2701 } | |
2702 | |
2703 static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, H
WND hWndToolBar) | |
2704 { | |
2705 // Note: only handles enabled/disabled, checked state, and radio
(press) | |
2706 ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIDat
a->m_wState & UPDUI_DISABLED) ? FALSE : TRUE); | |
2707 ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData
->m_wState & UPDUI_CHECKED) ? TRUE : FALSE); | |
2708 ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIDa
ta->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE); | |
2709 ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData
->m_wState & UPDUI_RADIO) ? TRUE : FALSE); | |
2710 } | |
2711 | |
2712 static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData,
HWND hWndStatusBar) | |
2713 { | |
2714 // Note: only handles text | |
2715 if(pUIData->m_wState & UPDUI_TEXT) | |
2716 ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pU
IData->m_lpstrText); | |
2717 } | |
2718 | |
2719 static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND
hWnd) | |
2720 { | |
2721 HWND hChild = ::GetDlgItem(hWnd, nID); | |
2722 | |
2723 ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FA
LSE : TRUE); | |
2724 // for check and radio, assume that window is a button | |
2725 int nCheck = BST_UNCHECKED; | |
2726 if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDU
I_RADIO) | |
2727 nCheck = BST_CHECKED; | |
2728 else if(pUIData->m_wState & UPDUI_CHECKED2) | |
2729 nCheck = BST_INDETERMINATE; | |
2730 ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L); | |
2731 if(pUIData->m_wState & UPDUI_DEFAULT) | |
2732 { | |
2733 DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0,
0L); | |
2734 if(HIWORD(dwRet) == DC_HASDEFID) | |
2735 { | |
2736 HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LO
WORD(dwRet)); | |
2737 // remove BS_DEFPUSHBUTTON | |
2738 ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTO
N, MAKELPARAM(TRUE, 0)); | |
2739 } | |
2740 ::SendMessage(hWnd, DM_SETDEFID, nID, 0L); | |
2741 } | |
2742 if(pUIData->m_wState & UPDUI_TEXT) | |
2743 ::SetWindowText(hChild, pUIData->m_lpstrText); | |
2744 } | |
2745 }; | |
2746 | |
2747 template <class T> | |
2748 class CUpdateUI : public CUpdateUIBase | |
2749 { | |
2750 public: | |
2751 CUpdateUI() | |
2752 { | |
2753 T* pT = static_cast<T*>(this); | |
2754 pT; | |
2755 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); | |
2756 m_pUIMap = pMap; | |
2757 ATLASSERT(m_pUIMap != NULL); | |
2758 int nCount; | |
2759 for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++) | |
2760 pMap++; | |
2761 | |
2762 // check for duplicates (debug only) | |
2763 #ifdef _DEBUG | |
2764 for(int i = 0; i < nCount; i++) | |
2765 { | |
2766 for(int j = 0; j < nCount; j++) | |
2767 { | |
2768 // shouldn't have duplicates in the update UI ma
p | |
2769 if(i != j) | |
2770 ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[
i].m_nID); | |
2771 } | |
2772 } | |
2773 #endif // _DEBUG | |
2774 | |
2775 ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]); | |
2776 ATLASSERT(m_pUIData != NULL); | |
2777 | |
2778 if(m_pUIData != NULL) | |
2779 memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount); | |
2780 } | |
2781 }; | |
2782 | |
2783 | |
2784 /////////////////////////////////////////////////////////////////////////////// | |
2785 // CDynamicUpdateUI - allows update elements to dynamically added and removed | |
2786 // in addition to a static update UI map | |
2787 | |
2788 template <class T> | |
2789 class CDynamicUpdateUI : public CUpdateUIBase | |
2790 { | |
2791 public: | |
2792 // Data members | |
2793 ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap; // copy of the static
UI data | |
2794 ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData; // instance UI data | |
2795 | |
2796 // Constructor/destructor | |
2797 CDynamicUpdateUI() | |
2798 { | |
2799 T* pT = static_cast<T*>(this); | |
2800 pT; | |
2801 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap(); | |
2802 ATLASSERT(pMap != NULL); | |
2803 | |
2804 for(;;) | |
2805 { | |
2806 BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap); | |
2807 ATLASSERT(bRet); | |
2808 | |
2809 if(bRet != FALSE) | |
2810 { | |
2811 _AtlUpdateUIData data = { 0, NULL }; | |
2812 bRet = m_arrUIData.Add(data); | |
2813 ATLASSERT(bRet); | |
2814 } | |
2815 | |
2816 if(pMap->m_nID == (WORD)-1) | |
2817 break; | |
2818 | |
2819 pMap++; | |
2820 } | |
2821 | |
2822 ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize()); | |
2823 | |
2824 #ifdef _DEBUG | |
2825 // check for duplicates (debug only) | |
2826 for(int i = 0; i < m_arrUIMap.GetSize(); i++) | |
2827 { | |
2828 for(int j = 0; j < m_arrUIMap.GetSize(); j++) | |
2829 { | |
2830 // shouldn't have duplicates in the update UI ma
p | |
2831 if(i != j) | |
2832 ATLASSERT(m_arrUIMap[j].m_nID != m_arrUI
Map[i].m_nID); | |
2833 } | |
2834 } | |
2835 #endif // _DEBUG | |
2836 | |
2837 // Set internal data pointers to point to the new data arrays | |
2838 m_pUIMap = m_arrUIMap.m_aT; | |
2839 m_pUIData = m_arrUIData.m_aT; | |
2840 } | |
2841 | |
2842 ~CDynamicUpdateUI() | |
2843 { | |
2844 for(int i = 0; i < m_arrUIData.GetSize(); i++) | |
2845 { | |
2846 if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0) | |
2847 delete [] m_arrUIData[i].m_lpstrText; | |
2848 } | |
2849 | |
2850 // Reset internal data pointers (memory will be released by CSim
pleArray d-tor) | |
2851 m_pUIMap = NULL; | |
2852 m_pUIData = NULL; | |
2853 } | |
2854 | |
2855 // Methods for dynamically adding and removing update elements | |
2856 bool UIAddUpdateElement(WORD nID, WORD wType) | |
2857 { | |
2858 // check for duplicates | |
2859 for(int i = 0; i < m_arrUIMap.GetSize(); i++) | |
2860 { | |
2861 // shouldn't have duplicates in the update UI map | |
2862 ATLASSERT(m_arrUIMap[i].m_nID != nID); | |
2863 if(m_arrUIMap[i].m_nID == nID) | |
2864 return false; | |
2865 } | |
2866 | |
2867 bool bRetVal = false; | |
2868 | |
2869 // Add new end element | |
2870 _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 }; | |
2871 BOOL bRet = m_arrUIMap.Add(uumEnd); | |
2872 ATLASSERT(bRet); | |
2873 | |
2874 if(bRet != FALSE) | |
2875 { | |
2876 _AtlUpdateUIData uud = { 0, NULL }; | |
2877 bRet = m_arrUIData.Add(uud); | |
2878 ATLASSERT(bRet); | |
2879 | |
2880 // Set new data to the previous end element | |
2881 if(bRet != FALSE) | |
2882 { | |
2883 int nSize = m_arrUIMap.GetSize(); | |
2884 _AtlUpdateUIMap uum = { nID, wType }; | |
2885 m_arrUIMap.SetAtIndex(nSize - 2, uum); | |
2886 m_arrUIData.SetAtIndex(nSize - 2, uud); | |
2887 | |
2888 // Set internal data pointers again, just in cas
e that memory moved | |
2889 m_pUIMap = m_arrUIMap.m_aT; | |
2890 m_pUIData = m_arrUIData.m_aT; | |
2891 | |
2892 bRetVal = true; | |
2893 } | |
2894 } | |
2895 | |
2896 return bRetVal; | |
2897 } | |
2898 | |
2899 bool UIRemoveUpdateElement(WORD nID) | |
2900 { | |
2901 bool bRetVal = false; | |
2902 | |
2903 for(int i = 0; i < m_arrUIMap.GetSize(); i++) | |
2904 { | |
2905 if(m_arrUIMap[i].m_nID == nID) | |
2906 { | |
2907 BOOL bRet = m_arrUIMap.RemoveAt(i); | |
2908 ATLASSERT(bRet); | |
2909 bRet = m_arrUIData.RemoveAt(i); | |
2910 ATLASSERT(bRet); | |
2911 | |
2912 bRetVal = true; | |
2913 break; | |
2914 } | |
2915 } | |
2916 | |
2917 return bRetVal; | |
2918 } | |
2919 }; | |
2920 | |
2921 | |
2922 /////////////////////////////////////////////////////////////////////////////// | |
2923 // CDialogResize - provides support for resizing dialog controls | |
2924 // (works for any window that has child controls) | |
2925 | |
2926 // Put CDialogResize in the list of base classes for a dialog (or even plain win
dow), | |
2927 // then implement DLGRESIZE map by specifying controls and groups of control | |
2928 // and using DLSZ_* values to specify how are they supposed to be resized. | |
2929 // | |
2930 // Notes: | |
2931 // - Resizeable border (WS_THICKFRAME style) should be set in the dialog templat
e | |
2932 // for top level dialogs (popup or overlapped), so that users can resize the d
ialog. | |
2933 // - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SI
ZE_X, | |
2934 // DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined. | |
2935 // - Order of controls is important - group controls are resized and moved based | |
2936 // on the position of the previous control in a group. | |
2937 | |
2938 // dialog resize map macros | |
2939 #define BEGIN_DLGRESIZE_MAP(thisClass) \ | |
2940 static const _AtlDlgResizeMap* GetDlgResizeMap() \ | |
2941 { \ | |
2942 static const _AtlDlgResizeMap theMap[] = \ | |
2943 { | |
2944 | |
2945 #define END_DLGRESIZE_MAP() \ | |
2946 { -1, 0 }, \ | |
2947 }; \ | |
2948 return theMap; \ | |
2949 } | |
2950 | |
2951 #define DLGRESIZE_CONTROL(id, flags) \ | |
2952 { id, flags }, | |
2953 | |
2954 #define BEGIN_DLGRESIZE_GROUP() \ | |
2955 { -1, _DLSZ_BEGIN_GROUP }, | |
2956 | |
2957 #define END_DLGRESIZE_GROUP() \ | |
2958 { -1, _DLSZ_END_GROUP }, | |
2959 | |
2960 | |
2961 template <class T> | |
2962 class CDialogResize | |
2963 { | |
2964 public: | |
2965 // Data declarations and members | |
2966 enum | |
2967 { | |
2968 DLSZ_SIZE_X = 0x00000001, | |
2969 DLSZ_SIZE_Y = 0x00000002, | |
2970 DLSZ_MOVE_X = 0x00000004, | |
2971 DLSZ_MOVE_Y = 0x00000008, | |
2972 DLSZ_REPAINT = 0x00000010, | |
2973 DLSZ_CENTER_X = 0x00000020, | |
2974 DLSZ_CENTER_Y = 0x00000040, | |
2975 | |
2976 // internal use only | |
2977 _DLSZ_BEGIN_GROUP = 0x00001000, | |
2978 _DLSZ_END_GROUP = 0x00002000, | |
2979 _DLSZ_GRIPPER = 0x00004000 | |
2980 }; | |
2981 | |
2982 struct _AtlDlgResizeMap | |
2983 { | |
2984 int m_nCtlID; | |
2985 DWORD m_dwResizeFlags; | |
2986 }; | |
2987 | |
2988 struct _AtlDlgResizeData | |
2989 { | |
2990 int m_nCtlID; | |
2991 DWORD m_dwResizeFlags; | |
2992 RECT m_rect; | |
2993 | |
2994 int GetGroupCount() const | |
2995 { | |
2996 return (int)LOBYTE(HIWORD(m_dwResizeFlags)); | |
2997 } | |
2998 | |
2999 void SetGroupCount(int nCount) | |
3000 { | |
3001 ATLASSERT(nCount > 0 && nCount < 256); | |
3002 DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0)); | |
3003 m_dwResizeFlags &= 0xFF00FFFF; | |
3004 m_dwResizeFlags |= dwCount; | |
3005 } | |
3006 | |
3007 bool operator ==(const _AtlDlgResizeData& r) const | |
3008 { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwRes
izeFlags); } | |
3009 }; | |
3010 | |
3011 ATL::CSimpleArray<_AtlDlgResizeData> m_arrData; | |
3012 SIZE m_sizeDialog; | |
3013 POINT m_ptMinTrackSize; | |
3014 bool m_bGripper; | |
3015 | |
3016 | |
3017 // Constructor | |
3018 CDialogResize() : m_bGripper(false) | |
3019 { | |
3020 m_sizeDialog.cx = 0; | |
3021 m_sizeDialog.cy = 0; | |
3022 m_ptMinTrackSize.x = -1; | |
3023 m_ptMinTrackSize.y = -1; | |
3024 } | |
3025 | |
3026 // Operations | |
3027 void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = tru
e, DWORD dwForceStyle = WS_CLIPCHILDREN) | |
3028 { | |
3029 T* pT = static_cast<T*>(this); | |
3030 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
3031 | |
3032 DWORD dwStyle = pT->GetStyle(); | |
3033 | |
3034 #ifdef _DEBUG | |
3035 // Debug only: Check if top level dialogs have a resizeable bord
er. | |
3036 if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) ==
0)) | |
3037 ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: t
op level dialog without the WS_THICKFRAME style - user cannot resize it\n")); | |
3038 #endif // _DEBUG | |
3039 | |
3040 // Force specified styles (default WS_CLIPCHILDREN reduces flick
er) | |
3041 if((dwStyle & dwForceStyle) != dwForceStyle) | |
3042 pT->ModifyStyle(0, dwForceStyle); | |
3043 | |
3044 // Adding this style removes an empty icon that dialogs with WS_
THICKFRAME have. | |
3045 // Setting icon to NULL is required when XP themes are active. | |
3046 // Note: This will not prevent adding an icon for the dialog usi
ng SetIcon() | |
3047 if((dwStyle & WS_CHILD) == 0) | |
3048 { | |
3049 pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME); | |
3050 if(pT->GetIcon(FALSE) == NULL) | |
3051 pT->SetIcon(NULL, FALSE); | |
3052 } | |
3053 | |
3054 // Cleanup in case of multiple initialization | |
3055 // block: first check for the gripper control, destroy it if nee
ded | |
3056 { | |
3057 ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_
BAR); | |
3058 if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (
m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0) | |
3059 wndGripper.DestroyWindow(); | |
3060 } | |
3061 // clear out everything else | |
3062 m_arrData.RemoveAll(); | |
3063 m_sizeDialog.cx = 0; | |
3064 m_sizeDialog.cy = 0; | |
3065 m_ptMinTrackSize.x = -1; | |
3066 m_ptMinTrackSize.y = -1; | |
3067 | |
3068 // Get initial dialog client size | |
3069 RECT rectDlg = { 0 }; | |
3070 pT->GetClientRect(&rectDlg); | |
3071 m_sizeDialog.cx = rectDlg.right; | |
3072 m_sizeDialog.cy = rectDlg.bottom; | |
3073 | |
3074 #ifndef _WIN32_WCE | |
3075 // Create gripper if requested | |
3076 m_bGripper = false; | |
3077 if(bAddGripper) | |
3078 { | |
3079 // shouldn't exist already | |
3080 ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)
)); | |
3081 if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR))) | |
3082 { | |
3083 ATL::CWindow wndGripper; | |
3084 wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, r
ectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGR
IP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR); | |
3085 ATLASSERT(wndGripper.IsWindow()); | |
3086 if(wndGripper.IsWindow()) | |
3087 { | |
3088 m_bGripper = true; | |
3089 RECT rectCtl = { 0 }; | |
3090 wndGripper.GetWindowRect(&rectCtl); | |
3091 ::MapWindowPoints(NULL, pT->m_hWnd, (LPP
OINT)&rectCtl, 2); | |
3092 _AtlDlgResizeData data = { ATL_IDW_STATU
S_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left,
rectCtl.top, rectCtl.right, rectCtl.bottom } }; | |
3093 m_arrData.Add(data); | |
3094 } | |
3095 } | |
3096 } | |
3097 #else // CE specific | |
3098 bAddGripper; // avoid level 4 warning | |
3099 #endif // _WIN32_WCE | |
3100 | |
3101 // Get min track position if requested | |
3102 if(bUseMinTrackSize) | |
3103 { | |
3104 if((dwStyle & WS_CHILD) != 0) | |
3105 { | |
3106 RECT rect = { 0 }; | |
3107 pT->GetClientRect(&rect); | |
3108 m_ptMinTrackSize.x = rect.right - rect.left; | |
3109 m_ptMinTrackSize.y = rect.bottom - rect.top; | |
3110 } | |
3111 else | |
3112 { | |
3113 RECT rect = { 0 }; | |
3114 pT->GetWindowRect(&rect); | |
3115 m_ptMinTrackSize.x = rect.right - rect.left; | |
3116 m_ptMinTrackSize.y = rect.bottom - rect.top; | |
3117 } | |
3118 } | |
3119 | |
3120 // Walk the map and initialize data | |
3121 const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap(); | |
3122 ATLASSERT(pMap != NULL); | |
3123 int nGroupStart = -1; | |
3124 for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFl
ags == 0); nCount++, pMap++) | |
3125 { | |
3126 if(pMap->m_nCtlID == -1) | |
3127 { | |
3128 switch(pMap->m_dwResizeFlags) | |
3129 { | |
3130 case _DLSZ_BEGIN_GROUP: | |
3131 ATLASSERT(nGroupStart == -1); | |
3132 nGroupStart = m_arrData.GetSize(); | |
3133 break; | |
3134 case _DLSZ_END_GROUP: | |
3135 { | |
3136 ATLASSERT(nGroupStart != -1); | |
3137 int nGroupCount = m_arrData.GetS
ize() - nGroupStart; | |
3138 m_arrData[nGroupStart].SetGroupC
ount(nGroupCount); | |
3139 nGroupStart = -1; | |
3140 } | |
3141 break; | |
3142 default: | |
3143 ATLASSERT(FALSE && _T("Invalid DLGRESIZE
Map Entry")); | |
3144 break; | |
3145 } | |
3146 } | |
3147 else | |
3148 { | |
3149 // this ID conflicts with the default gripper on
e | |
3150 ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_ID
W_STATUS_BAR) : TRUE); | |
3151 | |
3152 ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID
); | |
3153 ATLASSERT(ctl.IsWindow()); | |
3154 RECT rectCtl = { 0 }; | |
3155 ctl.GetWindowRect(&rectCtl); | |
3156 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&re
ctCtl, 2); | |
3157 | |
3158 DWORD dwGroupFlag = (nGroupStart != -1 && m_arrD
ata.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0; | |
3159 _AtlDlgResizeData data = { pMap->m_nCtlID, pMap-
>m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rect
Ctl.bottom } }; | |
3160 m_arrData.Add(data); | |
3161 } | |
3162 } | |
3163 ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the D
LGRESIZE Map")); | |
3164 } | |
3165 | |
3166 void DlgResize_UpdateLayout(int cxWidth, int cyHeight) | |
3167 { | |
3168 T* pT = static_cast<T*>(this); | |
3169 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
3170 | |
3171 // Restrict minimum size if requested | |
3172 if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -
1 && m_ptMinTrackSize.y != -1) | |
3173 { | |
3174 if(cxWidth < m_ptMinTrackSize.x) | |
3175 cxWidth = m_ptMinTrackSize.x; | |
3176 if(cyHeight < m_ptMinTrackSize.y) | |
3177 cyHeight = m_ptMinTrackSize.y; | |
3178 } | |
3179 | |
3180 BOOL bVisible = pT->IsWindowVisible(); | |
3181 if(bVisible) | |
3182 pT->SetRedraw(FALSE); | |
3183 | |
3184 for(int i = 0; i < m_arrData.GetSize(); i++) | |
3185 { | |
3186 if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) !=
0) // start of a group | |
3187 { | |
3188 int nGroupCount = m_arrData[i].GetGroupCount(); | |
3189 ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1
< m_arrData.GetSize()); | |
3190 RECT rectGroup = m_arrData[i].m_rect; | |
3191 | |
3192 int j = 1; | |
3193 for(j = 1; j < nGroupCount; j++) | |
3194 { | |
3195 rectGroup.left = __min(rectGroup.left, m
_arrData[i + j].m_rect.left); | |
3196 rectGroup.top = __min(rectGroup.top, m_a
rrData[i + j].m_rect.top); | |
3197 rectGroup.right = __max(rectGroup.right,
m_arrData[i + j].m_rect.right); | |
3198 rectGroup.bottom = __max(rectGroup.botto
m, m_arrData[i + j].m_rect.bottom); | |
3199 } | |
3200 | |
3201 for(j = 0; j < nGroupCount; j++) | |
3202 { | |
3203 _AtlDlgResizeData* pDataPrev = NULL; | |
3204 if(j > 0) | |
3205 pDataPrev = &(m_arrData[i + j -
1]); | |
3206 pT->DlgResize_PositionControl(cxWidth, c
yHeight, rectGroup, m_arrData[i + j], true, pDataPrev); | |
3207 } | |
3208 | |
3209 i += nGroupCount - 1; // increment to skip all
group controls | |
3210 } | |
3211 else // one control entry | |
3212 { | |
3213 RECT rectGroup = { 0, 0, 0, 0 }; | |
3214 pT->DlgResize_PositionControl(cxWidth, cyHeight,
rectGroup, m_arrData[i], false); | |
3215 } | |
3216 } | |
3217 | |
3218 if(bVisible) | |
3219 pT->SetRedraw(TRUE); | |
3220 | |
3221 pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UP
DATENOW | RDW_ALLCHILDREN); | |
3222 } | |
3223 | |
3224 // Message map and handlers | |
3225 BEGIN_MSG_MAP(CDialogResize) | |
3226 MESSAGE_HANDLER(WM_SIZE, OnSize) | |
3227 #ifndef _WIN32_WCE | |
3228 MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo) | |
3229 #endif // _WIN32_WCE | |
3230 END_MSG_MAP() | |
3231 | |
3232 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHan
dled*/) | |
3233 { | |
3234 T* pT = static_cast<T*>(this); | |
3235 #ifndef _WIN32_WCE | |
3236 if(m_bGripper) | |
3237 { | |
3238 ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_
BAR); | |
3239 if(wParam == SIZE_MAXIMIZED) | |
3240 wndGripper.ShowWindow(SW_HIDE); | |
3241 else if(wParam == SIZE_RESTORED) | |
3242 wndGripper.ShowWindow(SW_SHOW); | |
3243 } | |
3244 #endif // _WIN32_WCE | |
3245 if(wParam != SIZE_MINIMIZED) | |
3246 { | |
3247 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
3248 pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_L
PARAM(lParam)); | |
3249 } | |
3250 return 0; | |
3251 } | |
3252 | |
3253 #ifndef _WIN32_WCE | |
3254 LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam,
BOOL& /*bHandled*/) | |
3255 { | |
3256 if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1) | |
3257 { | |
3258 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam; | |
3259 lpMMI->ptMinTrackSize = m_ptMinTrackSize; | |
3260 } | |
3261 return 0; | |
3262 } | |
3263 #endif // _WIN32_WCE | |
3264 | |
3265 // Implementation | |
3266 bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGrou
p, _AtlDlgResizeData& data, bool bGroup, | |
3267 _AtlDlgResizeData* pDataPrev = NULL) | |
3268 { | |
3269 T* pT = static_cast<T*>(this); | |
3270 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
3271 ATL::CWindow ctl; | |
3272 RECT rectCtl = { 0 }; | |
3273 | |
3274 ctl = pT->GetDlgItem(data.m_nCtlID); | |
3275 if(!ctl.GetWindowRect(&rectCtl)) | |
3276 return false; | |
3277 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2); | |
3278 | |
3279 if(bGroup) | |
3280 { | |
3281 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) | |
3282 { | |
3283 int cxRight = rectGroup.right + cxWidth - m_size
Dialog.cx; | |
3284 int cxCtl = data.m_rect.right - data.m_rect.left
; | |
3285 rectCtl.left = rectGroup.left + (cxRight - rectG
roup.left - cxCtl) / 2; | |
3286 rectCtl.right = rectCtl.left + cxCtl; | |
3287 } | |
3288 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE
_X)) != 0) | |
3289 { | |
3290 rectCtl.left = rectGroup.left + ::MulDiv(data.m_
rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_size
Dialog.cx), rectGroup.right - rectGroup.left); | |
3291 | |
3292 if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0) | |
3293 { | |
3294 rectCtl.right = rectGroup.left + ::MulDi
v(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidt
h - m_sizeDialog.cx), rectGroup.right - rectGroup.left); | |
3295 | |
3296 if(pDataPrev != NULL) | |
3297 { | |
3298 ATL::CWindow ctlPrev = pT->GetDl
gItem(pDataPrev->m_nCtlID); | |
3299 RECT rcPrev = { 0 }; | |
3300 ctlPrev.GetWindowRect(&rcPrev); | |
3301 ::MapWindowPoints(NULL, pT->m_hW
nd, (LPPOINT)&rcPrev, 2); | |
3302 int dxAdjust = (rectCtl.left - r
cPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right); | |
3303 rcPrev.right += dxAdjust; | |
3304 ctlPrev.SetWindowPos(NULL, &rcPr
ev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); | |
3305 } | |
3306 } | |
3307 else | |
3308 { | |
3309 rectCtl.right = rectCtl.left + (data.m_r
ect.right - data.m_rect.left); | |
3310 } | |
3311 } | |
3312 | |
3313 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) | |
3314 { | |
3315 int cyBottom = rectGroup.bottom + cyHeight - m_s
izeDialog.cy; | |
3316 int cyCtl = data.m_rect.bottom - data.m_rect.top
; | |
3317 rectCtl.top = rectGroup.top + (cyBottom - rectGr
oup.top - cyCtl) / 2; | |
3318 rectCtl.bottom = rectCtl.top + cyCtl; | |
3319 } | |
3320 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE
_Y)) != 0) | |
3321 { | |
3322 rectCtl.top = rectGroup.top + ::MulDiv(data.m_re
ct.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDia
log.cy), rectGroup.bottom - rectGroup.top); | |
3323 | |
3324 if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0) | |
3325 { | |
3326 rectCtl.bottom = rectGroup.top + ::MulDi
v(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeig
ht - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top); | |
3327 | |
3328 if(pDataPrev != NULL) | |
3329 { | |
3330 ATL::CWindow ctlPrev = pT->GetDl
gItem(pDataPrev->m_nCtlID); | |
3331 RECT rcPrev = { 0 }; | |
3332 ctlPrev.GetWindowRect(&rcPrev); | |
3333 ::MapWindowPoints(NULL, pT->m_hW
nd, (LPPOINT)&rcPrev, 2); | |
3334 int dxAdjust = (rectCtl.top - rc
Prev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom); | |
3335 rcPrev.bottom += dxAdjust; | |
3336 ctlPrev.SetWindowPos(NULL, &rcPr
ev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE); | |
3337 } | |
3338 } | |
3339 else | |
3340 { | |
3341 rectCtl.bottom = rectCtl.top + (data.m_r
ect.bottom - data.m_rect.top); | |
3342 } | |
3343 } | |
3344 } | |
3345 else // no group | |
3346 { | |
3347 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0) | |
3348 { | |
3349 int cxCtl = data.m_rect.right - data.m_rect.left
; | |
3350 rectCtl.left = (cxWidth - cxCtl) / 2; | |
3351 rectCtl.right = rectCtl.left + cxCtl; | |
3352 } | |
3353 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE
_X)) != 0) | |
3354 { | |
3355 rectCtl.right = data.m_rect.right + (cxWidth - m
_sizeDialog.cx); | |
3356 | |
3357 if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0) | |
3358 rectCtl.left = rectCtl.right - (data.m_r
ect.right - data.m_rect.left); | |
3359 } | |
3360 | |
3361 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0) | |
3362 { | |
3363 int cyCtl = data.m_rect.bottom - data.m_rect.top
; | |
3364 rectCtl.top = (cyHeight - cyCtl) / 2; | |
3365 rectCtl.bottom = rectCtl.top + cyCtl; | |
3366 } | |
3367 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE
_Y)) != 0) | |
3368 { | |
3369 rectCtl.bottom = data.m_rect.bottom + (cyHeight
- m_sizeDialog.cy); | |
3370 | |
3371 if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0) | |
3372 rectCtl.top = rectCtl.bottom - (data.m_r
ect.bottom - data.m_rect.top); | |
3373 } | |
3374 } | |
3375 | |
3376 if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0) | |
3377 ctl.Invalidate(); | |
3378 | |
3379 if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOV
E_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0) | |
3380 ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOAC
TIVATE); | |
3381 | |
3382 return true; | |
3383 } | |
3384 }; | |
3385 | |
3386 | |
3387 /////////////////////////////////////////////////////////////////////////////// | |
3388 // CDoubleBufferImpl - Provides double-buffer painting support to any window | |
3389 | |
3390 template <class T> | |
3391 class CDoubleBufferImpl | |
3392 { | |
3393 public: | |
3394 // Overrideables | |
3395 void DoPaint(CDCHandle /*dc*/) | |
3396 { | |
3397 // must be implemented in a derived class | |
3398 ATLASSERT(FALSE); | |
3399 } | |
3400 | |
3401 // Message map and handlers | |
3402 BEGIN_MSG_MAP(CDoubleBufferImpl) | |
3403 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) | |
3404 MESSAGE_HANDLER(WM_PAINT, OnPaint) | |
3405 #ifndef _WIN32_WCE | |
3406 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) | |
3407 #endif // !_WIN32_WCE | |
3408 END_MSG_MAP() | |
3409 | |
3410 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lPa
ram*/, BOOL& /*bHandled*/) | |
3411 { | |
3412 return 1; // no background painting needed | |
3413 } | |
3414 | |
3415 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /
*bHandled*/) | |
3416 { | |
3417 T* pT = static_cast<T*>(this); | |
3418 ATLASSERT(::IsWindow(pT->m_hWnd)); | |
3419 | |
3420 if(wParam != NULL) | |
3421 { | |
3422 RECT rect = { 0 }; | |
3423 pT->GetClientRect(&rect); | |
3424 CMemoryDC dcMem((HDC)wParam, rect); | |
3425 pT->DoPaint(dcMem.m_hDC); | |
3426 } | |
3427 else | |
3428 { | |
3429 CPaintDC dc(pT->m_hWnd); | |
3430 CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint); | |
3431 pT->DoPaint(dcMem.m_hDC); | |
3432 } | |
3433 | |
3434 return 0; | |
3435 } | |
3436 }; | |
3437 | |
3438 | |
3439 /////////////////////////////////////////////////////////////////////////////// | |
3440 // CDoubleBufferWindowImpl - Implements a double-buffer painting window | |
3441 | |
3442 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlW
inTraits> | |
3443 class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase,
TWinTraits >, public CDoubleBufferImpl< T > | |
3444 { | |
3445 public: | |
3446 BEGIN_MSG_MAP(CDoubleBufferWindowImpl) | |
3447 CHAIN_MSG_MAP(CDoubleBufferImpl< T >) | |
3448 END_MSG_MAP() | |
3449 }; | |
3450 | |
3451 | |
3452 // command bar support | |
3453 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
3454 #undef CBRM_GETMENU | |
3455 #undef CBRM_TRACKPOPUPMENU | |
3456 #undef CBRM_GETCMDBAR | |
3457 #undef CBRPOPUPMENU | |
3458 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE) | |
3459 | |
3460 }; // namespace WTL | |
3461 | |
3462 #endif // __ATLFRAME_H__ | |
OLD | NEW |