1 // Windows Template Library - WTL version 8.0
\r
2 // Copyright (C) Microsoft Corporation. All rights reserved.
\r
4 // This file is a part of the Windows Template Library.
\r
5 // The use and distribution terms for this software are covered by the
\r
6 // Common Public License 1.0 (http://opensource.org/osi3.0/licenses/cpl1.0.php)
\r
7 // which can be found in the file CPL.TXT at the root of this distribution.
\r
8 // By using this software in any fashion, you are agreeing to be bound by
\r
9 // the terms of this license. You must not remove this notice, or
\r
10 // any other, from this software.
\r
12 #ifndef __ATLFRAME_H__
\r
13 #define __ATLFRAME_H__
\r
18 #error ATL requires C++ compilation (use a .cpp suffix)
\r
21 #ifndef __ATLAPP_H__
\r
22 #error atlframe.h requires atlapp.h to be included first
\r
25 #ifndef __ATLWIN_H__
\r
26 #error atlframe.h requires atlwin.h to be included first
\r
30 ///////////////////////////////////////////////////////////////////////////////
\r
31 // Classes in this file:
\r
33 // CFrameWindowImpl<T, TBase, TWinTraits>
\r
35 // CMDIFrameWindowImpl<T, TBase, TWinTraits>
\r
36 // CMDIChildWindowImpl<T, TBase, TWinTraits>
\r
40 // CDynamicUpdateUI<T>
\r
42 // CDoubleBufferImpl<T>
\r
43 // CDoubleBufferWindowImpl<T, TBase, TWinTraits>
\r
45 // Global functions:
\r
46 // AtlCreateSimpleToolBar()
\r
52 ///////////////////////////////////////////////////////////////////////////////
\r
53 // CFrameWndClassInfo - Manages frame window Windows class information
\r
55 class CFrameWndClassInfo
\r
59 enum { cchAutoName = 5 + sizeof(void*) * 2 }; // sizeof(void*) * 2 is the number of digits %p outputs
\r
61 #else // CE specific
\r
62 enum { cchAutoName = MAX_PATH }; // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string.
\r
64 #endif // !_WIN32_WCE
\r
65 LPCTSTR m_lpszOrigName;
\r
67 LPCTSTR m_lpszCursorID;
\r
68 BOOL m_bSystemCursor;
\r
70 TCHAR m_szAutoName[cchAutoName];
\r
71 UINT m_uCommonResourceID;
\r
74 ATOM Register(WNDPROC* pProc)
\r
78 CWindowCreateCriticalSectionLock lock;
\r
79 if(FAILED(lock.Lock()))
\r
81 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
\r
88 HINSTANCE hInst = ModuleHelper::GetModuleInstance();
\r
90 if (m_lpszOrigName != NULL)
\r
92 ATLASSERT(pProc != NULL);
\r
93 LPCTSTR lpsz = m_wc.lpszClassName;
\r
94 WNDPROC proc = m_wc.lpfnWndProc;
\r
96 WNDCLASSEX wc = { 0 };
\r
97 wc.cbSize = sizeof(WNDCLASSEX);
\r
98 // try process local class first
\r
99 if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
\r
101 // try global class
\r
102 if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
\r
109 pWndProc = m_wc.lpfnWndProc;
\r
110 m_wc.lpszClassName = lpsz;
\r
111 m_wc.lpfnWndProc = proc;
\r
115 m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
\r
118 m_wc.hInstance = hInst;
\r
119 m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
\r
120 if (m_wc.lpszClassName == NULL)
\r
122 #if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
\r
123 SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc);
\r
124 #else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
\r
125 SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
\r
126 #endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
\r
127 m_wc.lpszClassName = m_szAutoName;
\r
130 WNDCLASSEX wcTemp = m_wc;
\r
131 m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
\r
134 if(m_uCommonResourceID != 0) // use it if not zero
\r
136 m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
\r
137 m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
\r
139 m_atom = ::RegisterClassEx(&m_wc);
\r
146 if (m_lpszOrigName != NULL)
\r
148 ATLASSERT(pProc != NULL);
\r
149 ATLASSERT(pWndProc != NULL);
\r
155 #else // CE specific
\r
156 ATOM Register(WNDPROC* pProc)
\r
160 CWindowCreateCriticalSectionLock lock;
\r
161 if(FAILED(lock.Lock()))
\r
163 ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
\r
170 HINSTANCE hInst = ModuleHelper::GetModuleInstance();
\r
172 if (m_lpszOrigName != NULL)
\r
174 ATLASSERT(pProc != NULL);
\r
175 LPCTSTR lpsz = m_wc.lpszClassName;
\r
176 WNDPROC proc = m_wc.lpfnWndProc;
\r
178 WNDCLASS wc = { 0 };
\r
179 // try process local class first
\r
180 if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
\r
182 // try global class
\r
183 if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
\r
190 pWndProc = m_wc.lpfnWndProc;
\r
191 m_wc.lpszClassName = lpsz;
\r
192 m_wc.lpfnWndProc = proc;
\r
196 #if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
\r
197 m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
\r
198 #else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
\r
199 m_wc.hCursor = NULL;
\r
200 #endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
\r
203 m_wc.hInstance = hInst;
\r
204 m_wc.style &= ~CS_GLOBALCLASS; // we don't register global classes
\r
205 if (m_wc.lpszClassName == NULL)
\r
207 wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
\r
208 m_wc.lpszClassName = m_szAutoName;
\r
211 WNDCLASS wcTemp = m_wc;
\r
212 m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
\r
215 if(m_uCommonResourceID != 0) // use it if not zero
\r
216 m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
\r
217 m_atom = ::RegisterClass(&m_wc);
\r
224 if (m_lpszOrigName != NULL)
\r
226 ATLASSERT(pProc != NULL);
\r
227 ATLASSERT(pWndProc != NULL);
\r
233 #endif // _WIN32_WCE
\r
237 ///////////////////////////////////////////////////////////////////////////////
\r
238 // Macros for declaring frame window WNDCLASS
\r
242 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
\r
243 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
\r
245 static WTL::CFrameWndClassInfo wc = \
\r
247 { sizeof(WNDCLASSEX), 0, StartWindowProc, \
\r
248 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
\r
249 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
\r
254 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
\r
255 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
\r
257 static WTL::CFrameWndClassInfo wc = \
\r
259 { sizeof(WNDCLASSEX), style, StartWindowProc, \
\r
260 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
\r
261 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
\r
266 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
\r
267 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
\r
269 static WTL::CFrameWndClassInfo wc = \
\r
271 { sizeof(WNDCLASSEX), 0, StartWindowProc, \
\r
272 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
\r
273 OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
\r
278 #else // CE specific
\r
280 #define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
\r
281 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
\r
283 static WTL::CFrameWndClassInfo wc = \
\r
285 { 0, StartWindowProc, \
\r
286 0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
\r
287 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
\r
292 #define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
\r
293 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
\r
295 static WTL::CFrameWndClassInfo wc = \
\r
297 { style, StartWindowProc, \
\r
298 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
\r
299 NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
\r
304 #define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
\r
305 static WTL::CFrameWndClassInfo& GetWndClassInfo() \
\r
307 static WTL::CFrameWndClassInfo wc = \
\r
309 { NULL, StartWindowProc, \
\r
310 0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
\r
311 OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
\r
316 #endif // !_WIN32_WCE
\r
319 ///////////////////////////////////////////////////////////////////////////////
\r
320 // CFrameWindowImpl
\r
322 // Client window command chaining macro (only for frame windows)
\r
323 #define CHAIN_CLIENT_COMMANDS() \
\r
324 if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
\r
325 ::SendMessage(m_hWndClient, uMsg, wParam, lParam);
\r
327 // standard toolbar styles
\r
328 #define ATL_SIMPLE_TOOLBAR_STYLE \
\r
329 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
\r
330 // toolbar in a rebar pane
\r
331 #define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
\r
332 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
\r
333 // standard rebar styles
\r
334 #if (_WIN32_IE >= 0x0400)
\r
335 #define ATL_SIMPLE_REBAR_STYLE \
\r
336 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
\r
338 #define ATL_SIMPLE_REBAR_STYLE \
\r
339 (WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
\r
340 #endif // !(_WIN32_IE >= 0x0400)
\r
341 // rebar without borders
\r
342 #if (_WIN32_IE >= 0x0400)
\r
343 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
\r
344 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
\r
346 #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
\r
347 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
\r
348 #endif // !(_WIN32_IE >= 0x0400)
\r
350 // command bar support
\r
351 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
\r
353 #define CBRM_GETCMDBAR (WM_USER + 301) // returns command bar HWND
\r
354 #define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu
\r
355 #define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu
\r
357 struct _AtlFrameWnd_CmdBarPopupMenu
\r
367 #define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
\r
369 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
\r
372 template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
\r
373 class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits >
\r
376 DECLARE_FRAME_WND_CLASS(NULL, 0)
\r
379 HWND m_hWndToolBar;
\r
380 HWND m_hWndStatusBar;
\r
386 HWND m_hWndCECommandBar;
\r
387 #endif // _WIN32_WCE
\r
389 struct _AtlToolBarData
\r
395 //WORD aItems[wItemCount]
\r
398 { return (WORD*)(this+1); }
\r
401 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
402 struct _ChevronMenuInfo
\r
405 LPNMREBARCHEVRON lpnm;
\r
408 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
411 CFrameWindowImplBase() :
\r
413 m_hWndCECommandBar(NULL),
\r
414 #endif // _WIN32_WCE
\r
415 m_hWndToolBar(NULL),
\r
416 m_hWndStatusBar(NULL),
\r
417 m_hWndClient(NULL),
\r
422 HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
\r
424 ATLASSERT(m_hWnd == NULL);
\r
429 ModuleHelper::AddCreateWndData(&m_thunk.cd, this);
\r
431 if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
\r
432 MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
\r
433 if(rect.m_lpRect == NULL)
\r
434 rect.m_lpRect = &TBase::rcDefault;
\r
436 HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
\r
437 dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
\r
438 rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
\r
439 ModuleHelper::GetModuleInstance(), lpCreateParam);
\r
441 ATLASSERT(hWnd == NULL || m_hWnd == hWnd);
\r
446 static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
\r
447 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
449 HINSTANCE hInst = ModuleHelper::GetResourceInstance();
\r
450 HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
\r
454 HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
\r
455 if (hGlobal == NULL)
\r
458 _AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
\r
461 ATLASSERT(pData->wVersion == 1);
\r
463 WORD* pItems = pData->items();
\r
464 int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
\r
465 CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff;
\r
466 TBBUTTON* pTBBtn = buff.Allocate(nItems);
\r
467 ATLASSERT(pTBBtn != NULL);
\r
471 const int cxSeparator = 8;
\r
473 // set initial separator (half width)
\r
474 if(bInitialSeparator)
\r
476 pTBBtn[0].iBitmap = cxSeparator / 2;
\r
477 pTBBtn[0].idCommand = 0;
\r
478 pTBBtn[0].fsState = 0;
\r
479 pTBBtn[0].fsStyle = TBSTYLE_SEP;
\r
480 pTBBtn[0].dwData = 0;
\r
481 pTBBtn[0].iString = 0;
\r
485 for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
\r
489 pTBBtn[j].iBitmap = nBmp++;
\r
490 pTBBtn[j].idCommand = pItems[i];
\r
491 pTBBtn[j].fsState = TBSTATE_ENABLED;
\r
492 pTBBtn[j].fsStyle = TBSTYLE_BUTTON;
\r
493 pTBBtn[j].dwData = 0;
\r
494 pTBBtn[j].iString = 0;
\r
498 pTBBtn[j].iBitmap = cxSeparator;
\r
499 pTBBtn[j].idCommand = 0;
\r
500 pTBBtn[j].fsState = 0;
\r
501 pTBBtn[j].fsStyle = TBSTYLE_SEP;
\r
502 pTBBtn[j].dwData = 0;
\r
503 pTBBtn[j].iString = 0;
\r
508 HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
\r
514 #else // CE specific
\r
517 // The toolbar must go onto the existing CommandBar or MenuBar
\r
518 HWND hWnd = hWndParent;
\r
519 #endif // _WIN32_WCE
\r
521 ::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
\r
523 // check if font is taller than our bitmaps
\r
524 CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
\r
526 font = AtlGetDefaultGuiFont();
\r
527 LOGFONT lf = { 0 };
\r
528 font.GetLogFont(lf);
\r
529 WORD cyFontHeight = (WORD)abs(lf.lfHeight);
\r
532 WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID);
\r
533 if(bitsPerPixel > 4)
\r
535 COLORREF crMask = CLR_DEFAULT;
\r
536 if(bitsPerPixel == 32)
\r
538 // 32-bit color bitmap with alpha channel (valid for Windows XP and later)
\r
541 HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
\r
542 ATLASSERT(hImageList != NULL);
\r
543 ::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
\r
546 #endif // !_WIN32_WCE
\r
548 TBADDBITMAP tbab = { 0 };
\r
549 tbab.hInst = hInst;
\r
550 tbab.nID = nResourceID;
\r
551 ::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
\r
554 ::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
\r
555 ::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight)));
\r
556 const int cxyButtonMargin = 7;
\r
557 ::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, max(pData->wHeight, cyFontHeight) + cxyButtonMargin));
\r
563 static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
565 // Ensure style combinations for proper rebar painting
\r
566 if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
\r
567 dwStyle &= ~WS_BORDER;
\r
568 else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
\r
569 dwStyle |= CCS_NODIVIDER;
\r
571 // Create rebar window
\r
572 HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
\r
573 if(hWndReBar == NULL)
\r
575 ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
\r
579 // Initialize and send the REBARINFO structure
\r
580 REBARINFO rbi = { 0 };
\r
581 rbi.cbSize = sizeof(REBARINFO);
\r
583 if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi))
\r
585 ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n"));
\r
586 ::DestroyWindow(hWndReBar);
\r
593 BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
595 ATLASSERT(!::IsWindow(m_hWndToolBar));
\r
596 m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID);
\r
597 return (m_hWndToolBar != NULL);
\r
600 static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
\r
602 ATLASSERT(::IsWindow(hWndReBar)); // must be already created
\r
604 // block - check if this is really a rebar
\r
606 TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 };
\r
607 ::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
\r
608 ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
\r
611 ATLASSERT(::IsWindow(hWndBand)); // must be already created
\r
613 // Get number of buttons on the toolbar
\r
614 int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L);
\r
616 // Set band info structure
\r
617 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
\r
618 #if (_WIN32_IE >= 0x0400)
\r
619 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE;
\r
621 rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE;
\r
622 #endif // !(_WIN32_IE >= 0x0400)
\r
623 if(lpstrTitle != NULL)
\r
624 rbBand.fMask |= RBBIM_TEXT;
\r
625 rbBand.fStyle = RBBS_CHILDEDGE;
\r
626 #if (_WIN32_IE >= 0x0500)
\r
627 if(nBtnCount > 0) // add chevron style for toolbar with buttons
\r
628 rbBand.fStyle |= RBBS_USECHEVRON;
\r
629 #endif // (_WIN32_IE >= 0x0500)
\r
631 rbBand.fStyle |= RBBS_BREAK;
\r
633 rbBand.lpText = (LPTSTR)lpstrTitle;
\r
634 rbBand.hwndChild = hWndBand;
\r
635 if(nID == 0) // calc band ID
\r
636 nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
\r
639 // Calculate the size of the band
\r
641 RECT rcTmp = { 0 };
\r
644 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp);
\r
646 rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right;
\r
647 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
\r
648 if(bFullWidthAlways)
\r
650 rbBand.cxMinChild = rbBand.cx;
\r
652 else if(lpstrTitle == NULL)
\r
654 bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp);
\r
656 rbBand.cxMinChild = rcTmp.right;
\r
660 rbBand.cxMinChild = 0;
\r
663 else // no buttons, either not a toolbar or really has no buttons
\r
665 bRet = ::GetWindowRect(hWndBand, &rcTmp);
\r
667 rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left);
\r
668 rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0;
\r
669 rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
\r
672 #if (_WIN32_IE >= 0x0400)
\r
673 rbBand.cxIdeal = rbBand.cx;
\r
674 #endif // (_WIN32_IE >= 0x0400)
\r
677 LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
\r
680 ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n"));
\r
684 #if (_WIN32_IE >= 0x0501)
\r
685 DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L);
\r
686 ::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
\r
687 #endif // (_WIN32_IE >= 0x0501)
\r
692 BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
\r
694 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar
\r
695 ATLASSERT(::IsWindow(hWndBand)); // must be created
\r
696 return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways);
\r
699 #if (_WIN32_IE >= 0x0400)
\r
700 void SizeSimpleReBarBands()
\r
702 ATLASSERT(::IsWindow(m_hWndToolBar)); // must be an existing rebar
\r
704 int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L);
\r
706 for(int i = 0; i < nCount; i++)
\r
708 REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
\r
709 rbBand.fMask = RBBIM_SIZE;
\r
710 BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand);
\r
712 RECT rect = { 0, 0, 0, 0 };
\r
713 ::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect);
\r
714 rbBand.cx += rect.left + rect.right;
\r
715 bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand);
\r
719 #endif // (_WIN32_IE >= 0x0400)
\r
720 #endif // _WIN32_WCE
\r
723 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
\r
724 #else // CE specific
\r
725 BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
\r
726 #endif // _WIN32_WCE
\r
728 ATLASSERT(!::IsWindow(m_hWndStatusBar));
\r
729 m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
\r
730 return (m_hWndStatusBar != NULL);
\r
734 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
\r
735 #else // CE specific
\r
736 BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
\r
737 #endif // _WIN32_WCE
\r
739 const int cchMax = 128; // max text length is 127 for status bars (+1 for null)
\r
740 TCHAR szText[cchMax];
\r
742 ::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
\r
743 return CreateSimpleStatusBar(szText, dwStyle, nID);
\r
747 BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1)
\r
749 ATLASSERT(m_hWndCECommandBar == NULL);
\r
750 ATLASSERT(m_hWndToolBar == NULL);
\r
752 m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID);
\r
753 if(m_hWndCECommandBar == NULL)
\r
756 m_hWndToolBar = m_hWndCECommandBar;
\r
760 if(pszMenu != NULL)
\r
761 bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton);
\r
763 bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0);
\r
768 #if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
\r
769 BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0)
\r
771 ATLASSERT(m_hWndCECommandBar == NULL);
\r
773 SHMENUBARINFO mbi = { 0 };
\r
774 mbi.cbSize = sizeof(mbi);
\r
775 mbi.hwndParent = m_hWnd;
\r
776 mbi.dwFlags = dwFlags;
\r
777 mbi.nToolBarId = nToolBarId;
\r
778 mbi.hInstRes = ModuleHelper::GetResourceInstance();
\r
779 mbi.nBmpId = nBmpId;
\r
780 mbi.cBmpImages = cBmpImages;
\r
781 mbi.hwndMB = NULL; // This gets set by SHCreateMenuBar
\r
783 BOOL bRet = ::SHCreateMenuBar(&mbi);
\r
786 m_hWndCECommandBar = mbi.hwndMB;
\r
793 void SizeToMenuBar() // for menu bar only
\r
795 ATLASSERT(::IsWindow(m_hWnd));
\r
796 ATLASSERT(::IsWindow(m_hWndCECommandBar));
\r
799 GetWindowRect(&rect);
\r
800 RECT rectMB = { 0 };
\r
801 ::GetWindowRect(m_hWndCECommandBar, &rectMB);
\r
802 int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
\r
803 SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
\r
805 #endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
\r
806 #endif // _WIN32_WCE
\r
808 void UpdateLayout(BOOL bResizeBars = TRUE)
\r
811 GetClientRect(&rect);
\r
813 // position bars and offset their dimensions
\r
814 UpdateBarsPosition(rect, bResizeBars);
\r
816 // resize client window
\r
817 if(m_hWndClient != NULL)
\r
818 ::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
\r
819 rect.right - rect.left, rect.bottom - rect.top,
\r
820 SWP_NOZORDER | SWP_NOACTIVATE);
\r
823 void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
\r
826 if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
\r
830 ::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
\r
831 ::InvalidateRect(m_hWndToolBar, NULL, FALSE);
\r
833 RECT rectTB = { 0 };
\r
834 ::GetWindowRect(m_hWndToolBar, &rectTB);
\r
835 rect.top += rectTB.bottom - rectTB.top;
\r
838 // resize status bar
\r
839 if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
\r
842 ::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
\r
843 RECT rectSB = { 0 };
\r
844 ::GetWindowRect(m_hWndStatusBar, &rectSB);
\r
845 rect.bottom -= rectSB.bottom - rectSB.top;
\r
849 BOOL PreTranslateMessage(MSG* pMsg)
\r
851 if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
\r
856 BEGIN_MSG_MAP(CFrameWindowImplBase)
\r
857 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
\r
859 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
\r
860 #endif // !_WIN32_WCE
\r
861 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
\r
862 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
\r
864 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA)
\r
865 NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW)
\r
866 #endif // !_WIN32_WCE
\r
869 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
\r
871 if(m_hWndClient != NULL) // view will paint itself instead
\r
879 LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
\r
883 if(m_hWndStatusBar == NULL)
\r
886 WORD wFlags = HIWORD(wParam);
\r
887 if(wFlags == 0xFFFF && lParam == NULL) // menu closing
\r
889 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
\r
893 const int cchBuff = 256;
\r
894 TCHAR szBuff[cchBuff];
\r
896 if(!(wFlags & MF_POPUP))
\r
898 WORD wID = LOWORD(wParam);
\r
899 // check for special cases
\r
900 if(wID >= 0xF000 && wID < 0xF1F0) // system menu IDs
\r
901 wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
\r
902 else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST) // MRU items
\r
903 wID = ATL_IDS_MRU_FILE;
\r
904 else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD) // MDI child windows
\r
905 wID = ATL_IDS_MDICHILD;
\r
907 int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff);
\r
908 for(int i = 0; i < nRet; i++)
\r
910 if(szBuff[i] == _T('\n'))
\r
917 ::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
\r
918 ::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
\r
923 #endif // !_WIN32_WCE
\r
925 LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
\r
927 if(m_hWndClient != NULL)
\r
928 ::SetFocus(m_hWndClient);
\r
934 LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
\r
936 if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0)
\r
937 ::PostQuitMessage(1);
\r
944 LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
\r
946 LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh;
\r
947 pDispInfo->szText[0] = 0;
\r
949 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
\r
951 const int cchBuff = 256;
\r
952 char szBuff[cchBuff];
\r
954 int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
\r
955 for(int i = 0; i < nRet; i++)
\r
957 if(szBuff[i] == '\n')
\r
959 SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
\r
963 #if (_WIN32_IE >= 0x0300)
\r
964 if(nRet > 0) // string was loaded, save it
\r
965 pDispInfo->uFlags |= TTF_DI_SETITEM;
\r
966 #endif // (_WIN32_IE >= 0x0300)
\r
972 LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
\r
974 LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh;
\r
975 pDispInfo->szText[0] = 0;
\r
977 if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
\r
979 const int cchBuff = 256;
\r
980 wchar_t szBuff[cchBuff];
\r
982 int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
\r
983 for(int i = 0; i < nRet; i++)
\r
985 if(szBuff[i] == L'\n')
\r
987 SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
\r
991 #if (_WIN32_IE >= 0x0300)
\r
992 if(nRet > 0) // string was loaded, save it
\r
993 pDispInfo->uFlags |= TTF_DI_SETITEM;
\r
994 #endif // (_WIN32_IE >= 0x0300)
\r
999 #endif // !_WIN32_WCE
\r
1001 // Implementation - chevron menu support
\r
1002 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
1003 bool PrepareChevronMenu(_ChevronMenuInfo& cmi)
\r
1005 // get rebar and toolbar
\r
1006 REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
\r
1007 rbbi.fMask = RBBIM_CHILD;
\r
1008 BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi);
\r
1011 // assume the band is a toolbar
\r
1012 ATL::CWindow wnd = rbbi.hwndChild;
\r
1013 int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT);
\r
1014 if(nCount <= 0) // probably not a toolbar
\r
1017 // check if it's a command bar
\r
1018 CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU);
\r
1019 cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL);
\r
1021 // build a menu from hidden items
\r
1023 bRet = menu.CreatePopupMenu();
\r
1025 RECT rcClient = { 0 };
\r
1026 bRet = wnd.GetClientRect(&rcClient);
\r
1028 for(int i = 0; i < nCount; i++)
\r
1030 TBBUTTON tbb = { 0 };
\r
1031 bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb);
\r
1033 // skip hidden buttons
\r
1034 if((tbb.fsState & TBSTATE_HIDDEN) != 0)
\r
1036 RECT rcButton = { 0 };
\r
1037 bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton);
\r
1039 bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0);
\r
1040 if(rcButton.right > rcClient.right)
\r
1042 if(tbb.fsStyle & BTNS_SEP)
\r
1044 if(menu.GetMenuItemCount() > 0)
\r
1045 menu.AppendMenu(MF_SEPARATOR);
\r
1047 else if(cmi.bCmdBar)
\r
1049 const int cchBuff = 200;
\r
1050 TCHAR szBuff[cchBuff] = { 0 };
\r
1051 CMenuItemInfo mii;
\r
1052 mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
\r
1053 mii.dwTypeData = szBuff;
\r
1054 mii.cch = cchBuff;
\r
1055 bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
\r
1057 // Note: CmdBar currently supports only drop-down items
\r
1058 ATLASSERT(::IsMenu(mii.hSubMenu));
\r
1059 bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
\r
1064 // get button's text
\r
1065 const int cchBuff = 200;
\r
1066 TCHAR szBuff[cchBuff] = { 0 };
\r
1067 LPTSTR lpstrText = szBuff;
\r
1068 TBBUTTONINFO tbbi = { 0 };
\r
1069 tbbi.cbSize = sizeof(TBBUTTONINFO);
\r
1070 tbbi.dwMask = TBIF_TEXT;
\r
1071 tbbi.pszText = szBuff;
\r
1072 tbbi.cchText = cchBuff;
\r
1073 if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0)
\r
1075 // no text for this button, try a resource string
\r
1076 lpstrText = _T("");
\r
1077 int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff);
\r
1078 for(int n = 0; n < nRet; n++)
\r
1080 if(szBuff[n] == _T('\n'))
\r
1082 lpstrText = &szBuff[n + 1];
\r
1087 bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText);
\r
1093 if(menu.GetMenuItemCount() == 0) // no hidden buttons after all
\r
1095 menu.DestroyMenu();
\r
1096 ::MessageBeep((UINT)-1);
\r
1104 void DisplayChevronMenu(_ChevronMenuInfo& cmi)
\r
1106 #ifndef TPM_VERPOSANIMATION
\r
1107 const UINT TPM_VERPOSANIMATION = 0x1000L; // Menu animation flag
\r
1109 // convert chevron rect to screen coordinates
\r
1110 ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
\r
1111 POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom };
\r
1112 wndFrom.MapWindowPoints(NULL, &pt, 1);
\r
1113 RECT rc = cmi.lpnm->rc;
\r
1114 wndFrom.MapWindowPoints(NULL, &rc);
\r
1115 // set up flags and rect
\r
1116 UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
\r
1117 TPMPARAMS TPMParams = { 0 };
\r
1118 TPMParams.cbSize = sizeof(TPMPARAMS);
\r
1119 TPMParams.rcExclude = rc;
\r
1120 // check if this window has a command bar
\r
1121 HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
\r
1122 if(::IsWindow(hWndCmdBar))
\r
1124 CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams };
\r
1125 ::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu);
\r
1129 CMenuHandle menu = cmi.hMenu;
\r
1130 menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams);
\r
1134 void CleanupChevronMenu(_ChevronMenuInfo& cmi)
\r
1136 CMenuHandle menu = cmi.hMenu;
\r
1137 // if menu is from a command bar, detach submenus so they are not destroyed
\r
1140 for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
\r
1141 menu.RemoveMenu(i, MF_BYPOSITION);
\r
1144 menu.DestroyMenu();
\r
1145 // convert chevron rect to screen coordinates
\r
1146 ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
\r
1147 RECT rc = cmi.lpnm->rc;
\r
1148 wndFrom.MapWindowPoints(NULL, &rc);
\r
1149 // eat next message if click is on the same button
\r
1151 if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt))
\r
1152 ::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
\r
1154 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
1158 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
\r
1159 class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
\r
1162 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
\r
1163 DWORD dwStyle = 0, DWORD dwExStyle = 0,
\r
1164 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
\r
1166 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
\r
1168 dwStyle = T::GetWndStyle(dwStyle);
\r
1169 dwExStyle = T::GetWndExStyle(dwExStyle);
\r
1171 if(rect.m_lpRect == NULL)
\r
1172 rect.m_lpRect = &TBase::rcDefault;
\r
1174 return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
\r
1177 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
\r
1179 const int cchName = 256;
\r
1180 TCHAR szWindowName[cchName];
\r
1181 szWindowName[0] = 0;
\r
1182 #ifndef _WIN32_WCE
\r
1183 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
\r
1184 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
\r
1185 #else // CE specific
\r
1186 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
\r
1188 // This always needs to be NULL for Windows CE.
\r
1189 // Frame Window menus have to go onto the CommandBar.
\r
1190 // Use CreateSimpleCECommandBar
\r
1191 HMENU hMenu = NULL;
\r
1192 #endif // _WIN32_WCE
\r
1194 T* pT = static_cast<T*>(this);
\r
1195 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
\r
1198 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
\r
1203 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
1205 if(nResourceID == 0)
\r
1206 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
\r
1207 #ifndef _WIN32_WCE
\r
1208 ATLASSERT(!::IsWindow(m_hWndToolBar));
\r
1209 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
\r
1210 return (m_hWndToolBar != NULL);
\r
1211 #else // CE specific
\r
1212 HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
\r
1213 return (hWnd != NULL);
\r
1214 #endif // _WIN32_WCE
\r
1218 // CE specific variant that returns the handle of the toolbar
\r
1219 HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
1221 if(nResourceID == 0)
\r
1222 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
\r
1224 return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
\r
1226 #endif // _WIN32_WCE
\r
1228 // message map and handlers
\r
1229 typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass;
\r
1231 BEGIN_MSG_MAP(CFrameWindowImpl)
\r
1232 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
1233 #ifndef _ATL_NO_REBAR_SUPPORT
\r
1234 #if (_WIN32_IE >= 0x0400)
\r
1235 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
\r
1236 #endif // (_WIN32_IE >= 0x0400)
\r
1237 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
1238 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
\r
1239 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
1240 #endif // !_ATL_NO_REBAR_SUPPORT
\r
1241 CHAIN_MSG_MAP(_baseClass)
\r
1244 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
\r
1246 if(wParam != SIZE_MINIMIZED)
\r
1248 T* pT = static_cast<T*>(this);
\r
1249 pT->UpdateLayout();
\r
1255 #ifndef _ATL_NO_REBAR_SUPPORT
\r
1256 #if (_WIN32_IE >= 0x0400)
\r
1257 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
\r
1259 T* pT = static_cast<T*>(this);
\r
1260 pT->UpdateLayout(FALSE);
\r
1263 #endif // (_WIN32_IE >= 0x0400)
\r
1265 #if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
1266 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
\r
1268 T* pT = static_cast<T*>(this);
\r
1269 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
\r
1270 if(!pT->PrepareChevronMenu(cmi))
\r
1275 // display a popup menu with hidden items
\r
1276 pT->DisplayChevronMenu(cmi);
\r
1278 pT->CleanupChevronMenu(cmi);
\r
1281 #endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
\r
1282 #endif // !_ATL_NO_REBAR_SUPPORT
\r
1286 ///////////////////////////////////////////////////////////////////////////////
\r
1287 // AtlCreateSimpleToolBar - helper for creating simple toolbars
\r
1289 #ifndef _WIN32_WCE
\r
1291 inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
\r
1292 DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
1294 return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID);
\r
1297 #endif // !_WIN32_WCE
\r
1300 ///////////////////////////////////////////////////////////////////////////////
\r
1303 #ifndef _WIN32_WCE
\r
1305 #ifndef _WTL_MDIWINDOWMENU_TEXT
\r
1306 #define _WTL_MDIWINDOWMENU_TEXT _T("&Window")
\r
1309 class CMDIWindow : public ATL::CWindow
\r
1313 HWND m_hWndMDIClient;
\r
1317 CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL)
\r
1320 CMDIWindow& operator =(HWND hWnd)
\r
1327 HWND MDIGetActive(BOOL* lpbMaximized = NULL)
\r
1329 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1330 return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
\r
1333 void MDIActivate(HWND hWndChildToActivate)
\r
1335 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1336 ATLASSERT(::IsWindow(hWndChildToActivate));
\r
1337 ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
\r
1340 void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
\r
1342 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1343 ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
\r
1344 ::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
\r
1347 void MDIMaximize(HWND hWndChildToMaximize)
\r
1349 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1350 ATLASSERT(::IsWindow(hWndChildToMaximize));
\r
1351 ::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
\r
1354 void MDIRestore(HWND hWndChildToRestore)
\r
1356 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1357 ATLASSERT(::IsWindow(hWndChildToRestore));
\r
1358 ::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0);
\r
1361 void MDIDestroy(HWND hWndChildToDestroy)
\r
1363 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1364 ATLASSERT(::IsWindow(hWndChildToDestroy));
\r
1365 ::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
\r
1368 BOOL MDICascade(UINT uFlags = 0)
\r
1370 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1371 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
\r
1374 BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
\r
1376 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1377 return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
\r
1380 void MDIIconArrange()
\r
1382 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1383 ::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
\r
1386 HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
\r
1388 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1389 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
\r
1392 HMENU MDIRefreshMenu()
\r
1394 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1395 return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
\r
1398 // Additional operations
\r
1399 static HMENU GetStandardWindowMenu(HMENU hMenu)
\r
1401 int nCount = ::GetMenuItemCount(hMenu);
\r
1404 int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
\r
1407 CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
\r
1408 LPTSTR lpszText = buff.Allocate(nLen + 1);
\r
1409 if(lpszText == NULL)
\r
1411 if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
\r
1413 if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0)
\r
1415 return ::GetSubMenu(hMenu, nCount - 2);
\r
1418 void SetMDIFrameMenu()
\r
1420 HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
\r
1421 MDISetMenu(m_hMenu, hWindowMenu);
\r
1423 ::DrawMenuBar(GetMDIFrame());
\r
1426 HWND GetMDIFrame() const
\r
1428 return ::GetParent(m_hWndMDIClient);
\r
1432 #endif // !_WIN32_WCE
\r
1435 ///////////////////////////////////////////////////////////////////////////////
\r
1436 // CMDIFrameWindowImpl
\r
1438 #ifndef _WIN32_WCE
\r
1440 // MDI child command chaining macro (only for MDI frame windows)
\r
1441 #define CHAIN_MDI_CHILD_COMMANDS() \
\r
1442 if(uMsg == WM_COMMAND) \
\r
1444 HWND hWndChild = MDIGetActive(); \
\r
1445 if(hWndChild != NULL) \
\r
1446 ::SendMessage(hWndChild, uMsg, wParam, lParam); \
\r
1449 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
\r
1450 class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
\r
1453 HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
\r
1454 DWORD dwStyle = 0, DWORD dwExStyle = 0,
\r
1455 HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
\r
1458 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
\r
1460 dwStyle = T::GetWndStyle(dwStyle);
\r
1461 dwExStyle = T::GetWndExStyle(dwExStyle);
\r
1463 if(rect.m_lpRect == NULL)
\r
1464 rect.m_lpRect = &TBase::rcDefault;
\r
1466 return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
\r
1469 HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
\r
1471 const int cchName = 256;
\r
1472 TCHAR szWindowName[cchName];
\r
1473 szWindowName[0] = 0;
\r
1474 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
\r
1475 HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
\r
1477 T* pT = static_cast<T*>(this);
\r
1478 HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
\r
1481 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
\r
1486 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
1488 ATLASSERT(!::IsWindow(m_hWndToolBar));
\r
1489 if(nResourceID == 0)
\r
1490 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
\r
1491 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
\r
1492 return (m_hWndToolBar != NULL);
\r
1495 virtual WNDPROC GetWindowProc()
\r
1497 return MDIFrameWindowProc;
\r
1500 static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
1502 CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
\r
1503 // set a ptr to this message and save the old value
\r
1504 #if (_ATL_VER >= 0x0700)
\r
1505 ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
\r
1506 const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
\r
1507 #else // !(_ATL_VER >= 0x0700)
\r
1508 MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
\r
1509 const MSG* pOldMsg = pThis->m_pCurrentMsg;
\r
1510 #endif // !(_ATL_VER >= 0x0700)
\r
1511 pThis->m_pCurrentMsg = &msg;
\r
1512 // pass to the message map to process
\r
1514 BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
\r
1515 // restore saved value for the current message
\r
1516 ATLASSERT(pThis->m_pCurrentMsg == &msg);
\r
1517 pThis->m_pCurrentMsg = pOldMsg;
\r
1518 // do the default processing if message was not handled
\r
1521 if(uMsg != WM_NCDESTROY)
\r
1522 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
\r
1525 // unsubclass, if needed
\r
1526 LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
\r
1527 lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
\r
1528 if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
\r
1529 ::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
\r
1530 #if (_ATL_VER >= 0x0700)
\r
1531 // mark window as destryed
\r
1532 pThis->m_dwState |= WINSTATE_DESTROYED;
\r
1533 #else // !(_ATL_VER >= 0x0700)
\r
1534 // clear out window handle
\r
1535 HWND hWnd = pThis->m_hWnd;
\r
1536 pThis->m_hWnd = NULL;
\r
1537 // clean up after window is destroyed
\r
1538 pThis->OnFinalMessage(hWnd);
\r
1539 #endif // !(_ATL_VER >= 0x0700)
\r
1542 #if (_ATL_VER >= 0x0700)
\r
1543 if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL)
\r
1545 // clear out window handle
\r
1546 HWND hWnd = pThis->m_hWnd;
\r
1547 pThis->m_hWnd = NULL;
\r
1548 pThis->m_dwState &= ~WINSTATE_DESTROYED;
\r
1549 // clean up after window is destroyed
\r
1550 pThis->OnFinalMessage(hWnd);
\r
1552 #endif // (_ATL_VER >= 0x0700)
\r
1556 // Overriden to call DefWindowProc which uses DefFrameProc
\r
1557 LRESULT DefWindowProc()
\r
1559 const MSG* pMsg = m_pCurrentMsg;
\r
1562 lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
\r
1566 LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
\r
1568 return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam);
\r
1571 BOOL PreTranslateMessage(MSG* pMsg)
\r
1573 if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
\r
1575 return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg);
\r
1578 HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
\r
1580 DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
\r
1581 DWORD dwExStyle = WS_EX_CLIENTEDGE;
\r
1583 CLIENTCREATESTRUCT ccs = { 0 };
\r
1584 ccs.hWindowMenu = hWindowMenu;
\r
1585 ccs.idFirstChild = nFirstChildID;
\r
1587 if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0)
\r
1589 // parent MDI frame's scroll styles move to the MDICLIENT
\r
1590 dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL));
\r
1592 // fast way to turn off the scrollbar bits (without a resize)
\r
1593 ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED);
\r
1596 // Create MDICLIENT window
\r
1597 m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL,
\r
1598 dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID),
\r
1599 ModuleHelper::GetModuleInstance(), (LPVOID)&ccs);
\r
1600 if (m_hWndClient == NULL)
\r
1602 ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create MDICLIENT.\n"));
\r
1606 // Move it to the top of z-order
\r
1607 ::BringWindowToTop(m_hWndClient);
\r
1609 // set as MDI client window
\r
1610 m_hWndMDIClient = m_hWndClient;
\r
1612 // update to proper size
\r
1613 T* pT = static_cast<T*>(this);
\r
1614 pT->UpdateLayout();
\r
1616 return m_hWndClient;
\r
1619 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass;
\r
1621 BEGIN_MSG_MAP(CMDIFrameWindowImpl)
\r
1622 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
1623 MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
\r
1624 MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
\r
1625 #ifndef _ATL_NO_REBAR_SUPPORT
\r
1626 #if (_WIN32_IE >= 0x0400)
\r
1627 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
\r
1628 #endif // (_WIN32_IE >= 0x0400)
\r
1629 #if (_WIN32_IE >= 0x0500)
\r
1630 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
\r
1631 #endif // (_WIN32_IE >= 0x0500)
\r
1632 #endif // !_ATL_NO_REBAR_SUPPORT
\r
1633 CHAIN_MSG_MAP(_baseClass)
\r
1636 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1638 if(wParam != SIZE_MINIMIZED)
\r
1640 T* pT = static_cast<T*>(this);
\r
1641 pT->UpdateLayout();
\r
1643 // message must be handled, otherwise DefFrameProc would resize the client again
\r
1647 LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
\r
1649 // don't allow CFrameWindowImplBase to handle this one
\r
1650 return DefWindowProc(uMsg, wParam, lParam);
\r
1653 LRESULT OnMDISetMenu(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
1655 SetMDIFrameMenu();
\r
1659 #ifndef _ATL_NO_REBAR_SUPPORT
\r
1660 #if (_WIN32_IE >= 0x0400)
\r
1661 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
\r
1663 T* pT = static_cast<T*>(this);
\r
1664 pT->UpdateLayout(FALSE);
\r
1667 #endif // (_WIN32_IE >= 0x0400)
\r
1669 #if (_WIN32_IE >= 0x0500)
\r
1670 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
\r
1672 T* pT = static_cast<T*>(this);
\r
1673 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
\r
1674 if(!pT->PrepareChevronMenu(cmi))
\r
1679 // display a popup menu with hidden items
\r
1680 pT->DisplayChevronMenu(cmi);
\r
1682 pT->CleanupChevronMenu(cmi);
\r
1685 #endif // (_WIN32_IE >= 0x0500)
\r
1686 #endif // !_ATL_NO_REBAR_SUPPORT
\r
1689 #endif // !_WIN32_WCE
\r
1692 ///////////////////////////////////////////////////////////////////////////////
\r
1693 // CMDIChildWindowImpl
\r
1695 #ifndef _WIN32_WCE
\r
1697 template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CMDIChildWinTraits>
\r
1698 class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
\r
1701 HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
\r
1702 DWORD dwStyle = 0, DWORD dwExStyle = 0,
\r
1703 UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
\r
1705 ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
\r
1708 m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
\r
1710 dwStyle = T::GetWndStyle(dwStyle);
\r
1711 dwExStyle = T::GetWndExStyle(dwExStyle);
\r
1713 dwExStyle |= WS_EX_MDICHILD; // force this one
\r
1714 m_pfnSuperWindowProc = ::DefMDIChildProc;
\r
1715 m_hWndMDIClient = hWndParent;
\r
1716 ATLASSERT(::IsWindow(m_hWndMDIClient));
\r
1718 if(rect.m_lpRect == NULL)
\r
1719 rect.m_lpRect = &TBase::rcDefault;
\r
1721 // If the currently active MDI child is maximized, we want to create this one maximized too
\r
1722 ATL::CWindow wndParent = hWndParent;
\r
1723 BOOL bMaximized = FALSE;
\r
1724 wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
\r
1726 wndParent.SetRedraw(FALSE);
\r
1728 HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam);
\r
1732 // Maximize and redraw everything
\r
1734 MDIMaximize(hWnd);
\r
1735 wndParent.SetRedraw(TRUE);
\r
1736 wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
\r
1737 ::SetFocus(GetMDIFrame()); // focus will be set back to this window
\r
1739 else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus()))
\r
1747 HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
\r
1749 const int cchName = 256;
\r
1750 TCHAR szWindowName[cchName];
\r
1751 szWindowName[0] = 0;
\r
1752 if(lpcstrWindowName == NULL)
\r
1754 ::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
\r
1755 lpcstrWindowName = szWindowName;
\r
1758 T* pT = static_cast<T*>(this);
\r
1759 HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam);
\r
1762 m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
\r
1767 BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
\r
1769 ATLASSERT(!::IsWindow(m_hWndToolBar));
\r
1770 if(nResourceID == 0)
\r
1771 nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
\r
1772 m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
\r
1773 return (m_hWndToolBar != NULL);
\r
1776 BOOL UpdateClientEdge(LPRECT lpRect = NULL)
\r
1778 // only adjust for active MDI child window
\r
1779 HWND hWndChild = MDIGetActive();
\r
1780 if(hWndChild != NULL && hWndChild != m_hWnd)
\r
1783 // need to adjust the client edge style as max/restore happens
\r
1784 DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE);
\r
1785 DWORD dwNewStyle = dwStyle;
\r
1786 if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0) && ((GetStyle() & WS_MAXIMIZE) != 0))
\r
1787 dwNewStyle &= ~(WS_EX_CLIENTEDGE);
\r
1789 dwNewStyle |= WS_EX_CLIENTEDGE;
\r
1791 if(dwStyle != dwNewStyle)
\r
1793 // SetWindowPos will not move invalid bits
\r
1794 ::RedrawWindow(m_hWndMDIClient, NULL, NULL,
\r
1795 RDW_INVALIDATE | RDW_ALLCHILDREN);
\r
1796 // remove/add WS_EX_CLIENTEDGE to MDI client area
\r
1797 ::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
\r
1798 ::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0,
\r
1799 SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
\r
1800 SWP_NOZORDER | SWP_NOCOPYBITS);
\r
1802 // return new client area
\r
1803 if (lpRect != NULL)
\r
1804 ::GetClientRect(m_hWndMDIClient, lpRect);
\r
1812 typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass;
\r
1813 BEGIN_MSG_MAP(CMDIChildWindowImpl)
\r
1814 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
1815 MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
\r
1816 MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
\r
1817 MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
\r
1818 MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate)
\r
1819 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
\r
1820 #ifndef _ATL_NO_REBAR_SUPPORT
\r
1821 #if (_WIN32_IE >= 0x0400)
\r
1822 NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
\r
1823 #endif // (_WIN32_IE >= 0x0400)
\r
1824 #if (_WIN32_IE >= 0x0500)
\r
1825 NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
\r
1826 #endif // (_WIN32_IE >= 0x0500)
\r
1827 #endif // !_ATL_NO_REBAR_SUPPORT
\r
1828 CHAIN_MSG_MAP(_baseClass)
\r
1831 LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
\r
1833 DefWindowProc(uMsg, wParam, lParam); // needed for MDI children
\r
1834 if(wParam != SIZE_MINIMIZED)
\r
1836 T* pT = static_cast<T*>(this);
\r
1837 pT->UpdateLayout();
\r
1842 LRESULT OnWindowPosChanged(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1844 // update MDI client edge and adjust MDI child rect
\r
1845 LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam;
\r
1847 if(!(lpWndPos->flags & SWP_NOSIZE))
\r
1850 if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MAXIMIZE) != 0))
\r
1852 ::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle());
\r
1853 lpWndPos->x = rectClient.left;
\r
1854 lpWndPos->y = rectClient.top;
\r
1855 lpWndPos->cx = rectClient.right - rectClient.left;
\r
1856 lpWndPos->cy = rectClient.bottom - rectClient.top;
\r
1864 LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
\r
1866 LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
\r
1868 // Activate this MDI window if needed
\r
1869 if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT)
\r
1871 if(MDIGetActive() != m_hWnd)
\r
1872 MDIActivate(m_hWnd);
\r
1878 LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
\r
1880 return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam);
\r
1883 LRESULT OnMDIActivate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1885 if((HWND)lParam == m_hWnd && m_hMenu != NULL)
\r
1886 SetMDIFrameMenu();
\r
1887 else if((HWND)lParam == NULL)
\r
1888 ::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0);
\r
1894 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
\r
1896 if(m_hMenu != NULL)
\r
1898 ::DestroyMenu(m_hMenu);
\r
1901 UpdateClientEdge();
\r
1906 #ifndef _ATL_NO_REBAR_SUPPORT
\r
1907 #if (_WIN32_IE >= 0x0400)
\r
1908 LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
\r
1910 T* pT = static_cast<T*>(this);
\r
1911 pT->UpdateLayout(FALSE);
\r
1914 #endif // (_WIN32_IE >= 0x0400)
\r
1916 #if (_WIN32_IE >= 0x0500)
\r
1917 LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
\r
1919 T* pT = static_cast<T*>(this);
\r
1920 _ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
\r
1921 if(!pT->PrepareChevronMenu(cmi))
\r
1926 // display a popup menu with hidden items
\r
1927 pT->DisplayChevronMenu(cmi);
\r
1929 pT->CleanupChevronMenu(cmi);
\r
1932 #endif // (_WIN32_IE >= 0x0500)
\r
1933 #endif // !_ATL_NO_REBAR_SUPPORT
\r
1936 #endif // !_WIN32_WCE
\r
1939 ///////////////////////////////////////////////////////////////////////////////
\r
1940 // COwnerDraw - MI class for owner-draw support
\r
1942 template <class T>
\r
1946 #if (_ATL_VER < 0x0700)
\r
1947 BOOL m_bHandledOD;
\r
1949 BOOL IsMsgHandled() const
\r
1951 return m_bHandledOD;
\r
1953 void SetMsgHandled(BOOL bHandled)
\r
1955 m_bHandledOD = bHandled;
\r
1957 #endif // (_ATL_VER < 0x0700)
\r
1959 // Message map and handlers
\r
1960 BEGIN_MSG_MAP(COwnerDraw< T >)
\r
1961 MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
\r
1962 MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
\r
1963 MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)
\r
1964 MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)
\r
1966 MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
\r
1967 MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
\r
1968 MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)
\r
1969 MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)
\r
1972 LRESULT OnDrawItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1974 T* pT = static_cast<T*>(this);
\r
1975 pT->SetMsgHandled(TRUE);
\r
1976 pT->DrawItem((LPDRAWITEMSTRUCT)lParam);
\r
1977 bHandled = pT->IsMsgHandled();
\r
1978 return (LRESULT)TRUE;
\r
1981 LRESULT OnMeasureItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1983 T* pT = static_cast<T*>(this);
\r
1984 pT->SetMsgHandled(TRUE);
\r
1985 pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam);
\r
1986 bHandled = pT->IsMsgHandled();
\r
1987 return (LRESULT)TRUE;
\r
1990 LRESULT OnCompareItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
1992 T* pT = static_cast<T*>(this);
\r
1993 pT->SetMsgHandled(TRUE);
\r
1994 bHandled = pT->IsMsgHandled();
\r
1995 return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam);
\r
1998 LRESULT OnDeleteItem(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
\r
2000 T* pT = static_cast<T*>(this);
\r
2001 pT->SetMsgHandled(TRUE);
\r
2002 pT->DeleteItem((LPDELETEITEMSTRUCT)lParam);
\r
2003 bHandled = pT->IsMsgHandled();
\r
2004 return (LRESULT)TRUE;
\r
2008 void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/)
\r
2010 // must be implemented
\r
2014 void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
\r
2016 if(lpMeasureItemStruct->CtlType != ODT_MENU)
\r
2018 // return default height for a system font
\r
2019 T* pT = static_cast<T*>(this);
\r
2020 HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID);
\r
2021 CClientDC dc(hWnd);
\r
2022 TEXTMETRIC tm = { 0 };
\r
2023 dc.GetTextMetrics(&tm);
\r
2025 lpMeasureItemStruct->itemHeight = tm.tmHeight;
\r
2028 lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU);
\r
2031 int CompareItem(LPCOMPAREITEMSTRUCT /*lpCompareItemStruct*/)
\r
2033 // all items are equal
\r
2037 void DeleteItem(LPDELETEITEMSTRUCT /*lpDeleteItemStruct*/)
\r
2039 // default - nothing
\r
2044 ///////////////////////////////////////////////////////////////////////////////
\r
2045 // Update UI macros
\r
2047 // these build the Update UI map inside a class definition
\r
2048 #define BEGIN_UPDATE_UI_MAP(thisClass) \
\r
2049 static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \
\r
2051 static const _AtlUpdateUIMap theMap[] = \
\r
2054 #define UPDATE_ELEMENT(nID, wType) \
\r
2057 #define END_UPDATE_UI_MAP() \
\r
2063 ///////////////////////////////////////////////////////////////////////////////
\r
2064 // CUpdateUI - manages UI elements updating
\r
2066 class CUpdateUIBase
\r
2072 // UI element type
\r
2073 UPDUI_MENUPOPUP = 0x0001,
\r
2074 UPDUI_MENUBAR = 0x0002,
\r
2075 UPDUI_CHILDWINDOW = 0x0004,
\r
2076 UPDUI_TOOLBAR = 0x0008,
\r
2077 UPDUI_STATUSBAR = 0x0010,
\r
2079 UPDUI_ENABLED = 0x0000,
\r
2080 UPDUI_DISABLED = 0x0100,
\r
2081 UPDUI_CHECKED = 0x0200,
\r
2082 UPDUI_CHECKED2 = 0x0400,
\r
2083 UPDUI_RADIO = 0x0800,
\r
2084 UPDUI_DEFAULT = 0x1000,
\r
2085 UPDUI_TEXT = 0x2000,
\r
2087 UPDUI_CLEARDEFAULT = 0x4000,
\r
2091 struct _AtlUpdateUIElement
\r
2096 bool operator ==(const _AtlUpdateUIElement& e) const
\r
2097 { return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); }
\r
2101 struct _AtlUpdateUIMap
\r
2106 bool operator ==(const _AtlUpdateUIMap& e) const
\r
2107 { return (m_nID == e.m_nID && m_wType == e.m_wType); }
\r
2111 struct _AtlUpdateUIData
\r
2117 LPTSTR m_lpstrText;
\r
2120 bool operator ==(const _AtlUpdateUIData& e) const
\r
2121 { return (m_wState == e.m_wState && m_lpData == e.m_lpData); }
\r
2124 ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements; // elements data
\r
2125 const _AtlUpdateUIMap* m_pUIMap; // static UI data
\r
2126 _AtlUpdateUIData* m_pUIData; // instance UI data
\r
2127 WORD m_wDirtyType; // global dirty flag
\r
2129 bool m_bBlockAccelerators;
\r
2132 // Constructor, destructor
\r
2133 CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bBlockAccelerators(false)
\r
2138 if(m_pUIMap != NULL && m_pUIData != NULL)
\r
2140 const _AtlUpdateUIMap* pUIMap = m_pUIMap;
\r
2141 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2142 while(pUIMap->m_nID != (WORD)-1)
\r
2144 if(pUIData->m_wState & UPDUI_TEXT)
\r
2145 delete [] pUIData->m_lpstrText;
\r
2149 delete [] m_pUIData;
\r
2153 // Check for disabled commands
\r
2154 bool UIGetBlockAccelerators() const
\r
2156 return m_bBlockAccelerators;
\r
2159 bool UISetBlockAccelerators(bool bBlock)
\r
2161 bool bOld = m_bBlockAccelerators;
\r
2162 m_bBlockAccelerators = bBlock;
\r
2167 BOOL UIAddMenuBar(HWND hWnd) // menu bar (main menu)
\r
2171 _AtlUpdateUIElement e;
\r
2173 e.m_wType = UPDUI_MENUBAR;
\r
2174 return m_UIElements.Add(e);
\r
2177 BOOL UIAddToolBar(HWND hWnd) // toolbar
\r
2181 _AtlUpdateUIElement e;
\r
2183 e.m_wType = UPDUI_TOOLBAR;
\r
2184 return m_UIElements.Add(e);
\r
2187 BOOL UIAddStatusBar(HWND hWnd) // status bar
\r
2191 _AtlUpdateUIElement e;
\r
2193 e.m_wType = UPDUI_STATUSBAR;
\r
2194 return m_UIElements.Add(e);
\r
2197 BOOL UIAddChildWindowContainer(HWND hWnd) // child window
\r
2201 _AtlUpdateUIElement e;
\r
2203 e.m_wType = UPDUI_CHILDWINDOW;
\r
2204 return m_UIElements.Add(e);
\r
2207 // Message map for popup menu updates and accelerator blocking
\r
2208 BEGIN_MSG_MAP(CUpdateUIBase)
\r
2209 MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
\r
2210 MESSAGE_HANDLER(WM_COMMAND, OnCommand)
\r
2213 LRESULT OnInitMenuPopup(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
\r
2216 HMENU hMenu = (HMENU)wParam;
\r
2219 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2220 if(pUIData == NULL)
\r
2222 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2223 while(pMap->m_nID != (WORD)-1)
\r
2225 if(pMap->m_wType & UPDUI_MENUPOPUP)
\r
2226 UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
\r
2233 LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
\r
2236 if(m_bBlockAccelerators && HIWORD(wParam) == 1) // accelerators only
\r
2238 int nID = LOWORD(wParam);
\r
2239 if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED)
\r
2241 ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID);
\r
2242 bHandled = TRUE; // eat the command, UI item is disabled
\r
2248 // methods for setting UI element state
\r
2249 BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
\r
2251 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2252 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2253 if(pUIData == NULL)
\r
2256 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2258 if(nID == (int)pMap->m_nID)
\r
2262 if(pUIData->m_wState & UPDUI_DISABLED)
\r
2264 pUIData->m_wState |= pMap->m_wType;
\r
2265 pUIData->m_wState &= ~UPDUI_DISABLED;
\r
2270 if(!(pUIData->m_wState & UPDUI_DISABLED))
\r
2272 pUIData->m_wState |= pMap->m_wType;
\r
2273 pUIData->m_wState |= UPDUI_DISABLED;
\r
2278 pUIData->m_wState |= pMap->m_wType;
\r
2279 if(pUIData->m_wState & pMap->m_wType)
\r
2280 m_wDirtyType |= pMap->m_wType;
\r
2289 BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE)
\r
2291 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2292 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2293 if(pUIData == NULL)
\r
2296 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2298 if(nID == (int)pMap->m_nID)
\r
2303 if((pUIData->m_wState & UPDUI_CHECKED) || (pUIData->m_wState & UPDUI_CHECKED2))
\r
2305 pUIData->m_wState |= pMap->m_wType;
\r
2306 pUIData->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2);
\r
2310 if(!(pUIData->m_wState & UPDUI_CHECKED))
\r
2312 pUIData->m_wState |= pMap->m_wType;
\r
2313 pUIData->m_wState &= ~UPDUI_CHECKED2;
\r
2314 pUIData->m_wState |= UPDUI_CHECKED;
\r
2318 if(!(pUIData->m_wState & UPDUI_CHECKED2))
\r
2320 pUIData->m_wState |= pMap->m_wType;
\r
2321 pUIData->m_wState &= ~UPDUI_CHECKED;
\r
2322 pUIData->m_wState |= UPDUI_CHECKED2;
\r
2328 pUIData->m_wState |= pMap->m_wType;
\r
2329 if(pUIData->m_wState & pMap->m_wType)
\r
2330 m_wDirtyType |= pMap->m_wType;
\r
2339 // variant that supports bool (checked/not-checked, no intermediate state)
\r
2340 BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
\r
2342 return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate);
\r
2345 BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE)
\r
2347 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2348 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2349 if(pUIData == NULL)
\r
2352 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2354 if(nID == (int)pMap->m_nID)
\r
2358 if(!(pUIData->m_wState & UPDUI_RADIO))
\r
2360 pUIData->m_wState |= pMap->m_wType;
\r
2361 pUIData->m_wState |= UPDUI_RADIO;
\r
2366 if(pUIData->m_wState & UPDUI_RADIO)
\r
2368 pUIData->m_wState |= pMap->m_wType;
\r
2369 pUIData->m_wState &= ~UPDUI_RADIO;
\r
2374 pUIData->m_wState |= pMap->m_wType;
\r
2375 if(pUIData->m_wState & pMap->m_wType)
\r
2376 m_wDirtyType |= pMap->m_wType;
\r
2385 BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE)
\r
2387 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2388 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2389 if(pUIData == NULL)
\r
2391 if(lpstrText == NULL)
\r
2392 lpstrText = _T("");
\r
2394 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2396 if(nID == (int)pMap->m_nID)
\r
2398 if(pUIData->m_lpstrText == NULL || lstrcmp(pUIData->m_lpstrText, lpstrText))
\r
2400 delete [] pUIData->m_lpstrText;
\r
2401 pUIData->m_lpstrText = NULL;
\r
2402 int nStrLen = lstrlen(lpstrText);
\r
2403 ATLTRY(pUIData->m_lpstrText = new TCHAR[nStrLen + 1]);
\r
2404 if(pUIData->m_lpstrText == NULL)
\r
2406 ATLTRACE2(atlTraceUI, 0, _T("UISetText - memory allocation failed\n"));
\r
2409 SecureHelper::strcpy_x(pUIData->m_lpstrText, nStrLen + 1, lpstrText);
\r
2410 pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
\r
2414 pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
\r
2415 if(pUIData->m_wState & pMap->m_wType)
\r
2416 m_wDirtyType |= pMap->m_wType;
\r
2425 BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE)
\r
2427 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2428 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2429 if(pUIData == NULL)
\r
2432 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2434 if(nID == (int)pMap->m_nID)
\r
2438 if((pUIData->m_wState & UPDUI_DEFAULT) == 0)
\r
2440 pUIData->m_wState |= pMap->m_wType;
\r
2441 pUIData->m_wState |= UPDUI_DEFAULT;
\r
2446 if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
\r
2448 pUIData->m_wState |= pMap->m_wType;
\r
2449 pUIData->m_wState &= ~UPDUI_DEFAULT;
\r
2450 pUIData->m_wState |= UPDUI_CLEARDEFAULT;
\r
2455 pUIData->m_wState |= pMap->m_wType;
\r
2456 if(pUIData->m_wState & pMap->m_wType)
\r
2457 m_wDirtyType |= pMap->m_wType;
\r
2466 // methods for complete state set/get
\r
2467 BOOL UISetState(int nID, DWORD dwState)
\r
2469 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2470 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2471 if(pUIData == NULL)
\r
2473 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2475 if(nID == (int)pMap->m_nID)
\r
2477 pUIData->m_wState = (WORD)(dwState | pMap->m_wType);
\r
2478 m_wDirtyType |= pMap->m_wType;
\r
2485 DWORD UIGetState(int nID)
\r
2487 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2488 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2489 if(pUIData == NULL)
\r
2491 for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
\r
2493 if(nID == (int)pMap->m_nID)
\r
2494 return pUIData->m_wState;
\r
2499 // methods for updating UI
\r
2500 #ifndef _WIN32_WCE
\r
2501 BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE)
\r
2503 if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate)
\r
2506 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2507 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2508 if(pUIData == NULL)
\r
2511 while(pMap->m_nID != (WORD)-1)
\r
2513 for(int i = 0; i < m_UIElements.GetSize(); i++)
\r
2515 if(m_UIElements[i].m_wType == UPDUI_MENUBAR)
\r
2517 HMENU hMenu = ::GetMenu(m_UIElements[i].m_hWnd);
\r
2518 if(hMenu != NULL && (pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR))
\r
2519 UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
\r
2522 ::DrawMenuBar(m_UIElements[i].m_hWnd);
\r
2525 pUIData->m_wState &= ~UPDUI_MENUBAR;
\r
2526 if(pUIData->m_wState & UPDUI_TEXT)
\r
2528 delete [] pUIData->m_lpstrText;
\r
2529 pUIData->m_lpstrText = NULL;
\r
2530 pUIData->m_wState &= ~UPDUI_TEXT;
\r
2535 m_wDirtyType &= ~UPDUI_MENUBAR;
\r
2538 #endif // !_WIN32_WCE
\r
2540 BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE)
\r
2542 if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate)
\r
2545 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2546 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2547 if(pUIData == NULL)
\r
2550 while(pMap->m_nID != (WORD)-1)
\r
2552 for(int i = 0; i < m_UIElements.GetSize(); i++)
\r
2554 if(m_UIElements[i].m_wType == UPDUI_TOOLBAR)
\r
2556 if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR))
\r
2557 UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
\r
2561 pUIData->m_wState &= ~UPDUI_TOOLBAR;
\r
2565 m_wDirtyType &= ~UPDUI_TOOLBAR;
\r
2569 BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE)
\r
2571 if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate)
\r
2574 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2575 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2576 if(pUIData == NULL)
\r
2579 while(pMap->m_nID != (WORD)-1)
\r
2581 for(int i = 0; i < m_UIElements.GetSize(); i++)
\r
2583 if(m_UIElements[i].m_wType == UPDUI_STATUSBAR)
\r
2585 if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR))
\r
2586 UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
\r
2590 pUIData->m_wState &= ~UPDUI_STATUSBAR;
\r
2591 if(pUIData->m_wState & UPDUI_TEXT)
\r
2593 delete [] pUIData->m_lpstrText;
\r
2594 pUIData->m_lpstrText = NULL;
\r
2595 pUIData->m_wState &= ~UPDUI_TEXT;
\r
2600 m_wDirtyType &= ~UPDUI_STATUSBAR;
\r
2604 BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE)
\r
2606 if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate)
\r
2609 const _AtlUpdateUIMap* pMap = m_pUIMap;
\r
2610 _AtlUpdateUIData* pUIData = m_pUIData;
\r
2611 if(pUIData == NULL)
\r
2614 while(pMap->m_nID != (WORD)-1)
\r
2616 for(int i = 0; i < m_UIElements.GetSize(); i++)
\r
2618 if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW)
\r
2620 if((pUIData->m_wState & UPDUI_CHILDWINDOW) && (pMap->m_wType & UPDUI_CHILDWINDOW))
\r
2621 UIUpdateChildWindow(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
\r
2625 pUIData->m_wState &= ~UPDUI_CHILDWINDOW;
\r
2626 if(pUIData->m_wState & UPDUI_TEXT)
\r
2628 delete [] pUIData->m_lpstrText;
\r
2629 pUIData->m_lpstrText = NULL;
\r
2630 pUIData->m_wState &= ~UPDUI_TEXT;
\r
2635 m_wDirtyType &= ~UPDUI_CHILDWINDOW;
\r
2639 // internal element specific methods
\r
2640 static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu)
\r
2642 #ifndef _WIN32_WCE
\r
2643 if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0)
\r
2645 ::SetMenuDefaultItem(hMenu, (UINT)-1, 0);
\r
2646 pUIData->m_wState &= ~UPDUI_CLEARDEFAULT;
\r
2648 #endif // !_WIN32_WCE
\r
2650 CMenuItemInfo mii;
\r
2651 mii.fMask = MIIM_STATE;
\r
2654 #ifndef _WIN32_WCE
\r
2655 if((pUIData->m_wState & UPDUI_DISABLED) != 0)
\r
2656 mii.fState |= MFS_DISABLED | MFS_GRAYED;
\r
2658 mii.fState |= MFS_ENABLED;
\r
2660 if((pUIData->m_wState & UPDUI_CHECKED) != 0)
\r
2661 mii.fState |= MFS_CHECKED;
\r
2663 mii.fState |= MFS_UNCHECKED;
\r
2665 if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
\r
2666 mii.fState |= MFS_DEFAULT;
\r
2667 #else // CE specific
\r
2668 // ::SetMenuItemInfo() can't disable or check menu items
\r
2669 // on Windows CE, so we have to do that directly
\r
2670 UINT uEnable = MF_BYCOMMAND;
\r
2671 if((pUIData->m_wState & UPDUI_DISABLED) != 0)
\r
2672 uEnable |= MF_GRAYED;
\r
2674 uEnable |= MF_ENABLED;
\r
2675 ::EnableMenuItem(hMenu, nID, uEnable);
\r
2677 UINT uCheck = MF_BYCOMMAND;
\r
2678 if((pUIData->m_wState & UPDUI_CHECKED) != 0)
\r
2679 uCheck |= MF_CHECKED;
\r
2681 uCheck |= MF_UNCHECKED;
\r
2682 ::CheckMenuItem(hMenu, nID, uCheck);
\r
2683 #endif // _WIN32_WCE
\r
2685 if((pUIData->m_wState & UPDUI_TEXT) != 0)
\r
2687 CMenuItemInfo miiNow;
\r
2688 miiNow.fMask = MIIM_TYPE;
\r
2690 if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow))
\r
2692 mii.fMask |= MIIM_TYPE;
\r
2693 // MFT_BITMAP and MFT_SEPARATOR don't go together with MFT_STRING
\r
2694 #ifndef _WIN32_WCE
\r
2695 mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_SEPARATOR)) | MFT_STRING;
\r
2696 #else // CE specific
\r
2697 mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) | MFT_STRING;
\r
2698 #endif // _WIN32_WCE
\r
2699 mii.dwTypeData = pUIData->m_lpstrText;
\r
2703 ::SetMenuItemInfo(hMenu, nID, FALSE, &mii);
\r
2706 static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar)
\r
2708 // Note: only handles enabled/disabled, checked state, and radio (press)
\r
2709 ::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
\r
2710 ::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE);
\r
2711 ::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE);
\r
2712 ::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE);
\r
2715 static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar)
\r
2717 // Note: only handles text
\r
2718 if(pUIData->m_wState & UPDUI_TEXT)
\r
2719 ::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpstrText);
\r
2722 static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND hWnd)
\r
2724 HWND hChild = ::GetDlgItem(hWnd, nID);
\r
2726 ::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
\r
2727 // for check and radio, assume that window is a button
\r
2728 int nCheck = BST_UNCHECKED;
\r
2729 if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO)
\r
2730 nCheck = BST_CHECKED;
\r
2731 else if(pUIData->m_wState & UPDUI_CHECKED2)
\r
2732 nCheck = BST_INDETERMINATE;
\r
2733 ::SendMessage(hChild, BM_SETCHECK, nCheck, 0L);
\r
2734 if(pUIData->m_wState & UPDUI_DEFAULT)
\r
2736 DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0, 0L);
\r
2737 if(HIWORD(dwRet) == DC_HASDEFID)
\r
2739 HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LOWORD(dwRet));
\r
2740 // remove BS_DEFPUSHBUTTON
\r
2741 ::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
\r
2743 ::SendMessage(hWnd, DM_SETDEFID, nID, 0L);
\r
2745 if(pUIData->m_wState & UPDUI_TEXT)
\r
2746 ::SetWindowText(hChild, pUIData->m_lpstrText);
\r
2750 template <class T>
\r
2751 class CUpdateUI : public CUpdateUIBase
\r
2756 T* pT = static_cast<T*>(this);
\r
2758 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
\r
2760 ATLASSERT(m_pUIMap != NULL);
\r
2762 for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++)
\r
2765 // check for duplicates (debug only)
\r
2767 for(int i = 0; i < nCount; i++)
\r
2769 for(int j = 0; j < nCount; j++)
\r
2771 // shouldn't have duplicates in the update UI map
\r
2773 ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[i].m_nID);
\r
2778 ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]);
\r
2779 ATLASSERT(m_pUIData != NULL);
\r
2781 if(m_pUIData != NULL)
\r
2782 memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount);
\r
2787 ///////////////////////////////////////////////////////////////////////////////
\r
2788 // CDynamicUpdateUI - allows update elements to dynamically added and removed
\r
2789 // in addition to a static update UI map
\r
2791 template <class T>
\r
2792 class CDynamicUpdateUI : public CUpdateUIBase
\r
2796 ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap; // copy of the static UI data
\r
2797 ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData; // instance UI data
\r
2799 // Constructor/destructor
\r
2800 CDynamicUpdateUI()
\r
2802 T* pT = static_cast<T*>(this);
\r
2804 const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
\r
2805 ATLASSERT(pMap != NULL);
\r
2809 BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap);
\r
2814 _AtlUpdateUIData data = { 0, NULL };
\r
2815 bRet = m_arrUIData.Add(data);
\r
2819 if(pMap->m_nID == (WORD)-1)
\r
2825 ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize());
\r
2828 // check for duplicates (debug only)
\r
2829 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
\r
2831 for(int j = 0; j < m_arrUIMap.GetSize(); j++)
\r
2833 // shouldn't have duplicates in the update UI map
\r
2835 ATLASSERT(m_arrUIMap[j].m_nID != m_arrUIMap[i].m_nID);
\r
2840 // Set internal data pointers to point to the new data arrays
\r
2841 m_pUIMap = m_arrUIMap.m_aT;
\r
2842 m_pUIData = m_arrUIData.m_aT;
\r
2845 ~CDynamicUpdateUI()
\r
2847 for(int i = 0; i < m_arrUIData.GetSize(); i++)
\r
2849 if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0)
\r
2850 delete [] m_arrUIData[i].m_lpstrText;
\r
2853 // Reset internal data pointers (memory will be released by CSimpleArray d-tor)
\r
2858 // Methods for dynamically adding and removing update elements
\r
2859 bool UIAddUpdateElement(WORD nID, WORD wType)
\r
2861 // check for duplicates
\r
2862 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
\r
2864 // shouldn't have duplicates in the update UI map
\r
2865 ATLASSERT(m_arrUIMap[i].m_nID != nID);
\r
2866 if(m_arrUIMap[i].m_nID == nID)
\r
2870 bool bRetVal = false;
\r
2872 // Add new end element
\r
2873 _AtlUpdateUIMap uumEnd = { (WORD)-1, 0 };
\r
2874 BOOL bRet = m_arrUIMap.Add(uumEnd);
\r
2879 _AtlUpdateUIData uud = { 0, NULL };
\r
2880 bRet = m_arrUIData.Add(uud);
\r
2883 // Set new data to the previous end element
\r
2886 int nSize = m_arrUIMap.GetSize();
\r
2887 _AtlUpdateUIMap uum = { nID, wType };
\r
2888 m_arrUIMap.SetAtIndex(nSize - 2, uum);
\r
2889 m_arrUIData.SetAtIndex(nSize - 2, uud);
\r
2891 // Set internal data pointers again, just in case that memory moved
\r
2892 m_pUIMap = m_arrUIMap.m_aT;
\r
2893 m_pUIData = m_arrUIData.m_aT;
\r
2902 bool UIRemoveUpdateElement(WORD nID)
\r
2904 bool bRetVal = false;
\r
2906 for(int i = 0; i < m_arrUIMap.GetSize(); i++)
\r
2908 if(m_arrUIMap[i].m_nID == nID)
\r
2910 BOOL bRet = m_arrUIMap.RemoveAt(i);
\r
2912 bRet = m_arrUIData.RemoveAt(i);
\r
2925 ///////////////////////////////////////////////////////////////////////////////
\r
2926 // CDialogResize - provides support for resizing dialog controls
\r
2927 // (works for any window that has child controls)
\r
2929 // Put CDialogResize in the list of base classes for a dialog (or even plain window),
\r
2930 // then implement DLGRESIZE map by specifying controls and groups of control
\r
2931 // and using DLSZ_* values to specify how are they supposed to be resized.
\r
2934 // - Resizeable border (WS_THICKFRAME style) should be set in the dialog template
\r
2935 // for top level dialogs (popup or overlapped), so that users can resize the dialog.
\r
2936 // - Some flags cannot be combined; for instance DLSZ_CENTER_X overrides DLSZ_SIZE_X,
\r
2937 // DLSZ_SIZE_X overrides DLSZ_MOVE_X. X and Y flags can be combined.
\r
2938 // - Order of controls is important - group controls are resized and moved based
\r
2939 // on the position of the previous control in a group.
\r
2941 // dialog resize map macros
\r
2942 #define BEGIN_DLGRESIZE_MAP(thisClass) \
\r
2943 static const _AtlDlgResizeMap* GetDlgResizeMap() \
\r
2945 static const _AtlDlgResizeMap theMap[] = \
\r
2948 #define END_DLGRESIZE_MAP() \
\r
2954 #define DLGRESIZE_CONTROL(id, flags) \
\r
2957 #define BEGIN_DLGRESIZE_GROUP() \
\r
2958 { -1, _DLSZ_BEGIN_GROUP },
\r
2960 #define END_DLGRESIZE_GROUP() \
\r
2961 { -1, _DLSZ_END_GROUP },
\r
2964 template <class T>
\r
2965 class CDialogResize
\r
2968 // Data declarations and members
\r
2971 DLSZ_SIZE_X = 0x00000001,
\r
2972 DLSZ_SIZE_Y = 0x00000002,
\r
2973 DLSZ_MOVE_X = 0x00000004,
\r
2974 DLSZ_MOVE_Y = 0x00000008,
\r
2975 DLSZ_REPAINT = 0x00000010,
\r
2976 DLSZ_CENTER_X = 0x00000020,
\r
2977 DLSZ_CENTER_Y = 0x00000040,
\r
2979 // internal use only
\r
2980 _DLSZ_BEGIN_GROUP = 0x00001000,
\r
2981 _DLSZ_END_GROUP = 0x00002000,
\r
2982 _DLSZ_GRIPPER = 0x00004000
\r
2985 struct _AtlDlgResizeMap
\r
2988 DWORD m_dwResizeFlags;
\r
2991 struct _AtlDlgResizeData
\r
2994 DWORD m_dwResizeFlags;
\r
2997 int GetGroupCount() const
\r
2999 return (int)LOBYTE(HIWORD(m_dwResizeFlags));
\r
3002 void SetGroupCount(int nCount)
\r
3004 ATLASSERT(nCount > 0 && nCount < 256);
\r
3005 DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0));
\r
3006 m_dwResizeFlags &= 0xFF00FFFF;
\r
3007 m_dwResizeFlags |= dwCount;
\r
3010 bool operator ==(const _AtlDlgResizeData& r) const
\r
3011 { return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwResizeFlags); }
\r
3014 ATL::CSimpleArray<_AtlDlgResizeData> m_arrData;
\r
3015 SIZE m_sizeDialog;
\r
3016 POINT m_ptMinTrackSize;
\r
3021 CDialogResize() : m_bGripper(false)
\r
3023 m_sizeDialog.cx = 0;
\r
3024 m_sizeDialog.cy = 0;
\r
3025 m_ptMinTrackSize.x = -1;
\r
3026 m_ptMinTrackSize.y = -1;
\r
3030 void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true, DWORD dwForceStyle = WS_CLIPCHILDREN)
\r
3032 T* pT = static_cast<T*>(this);
\r
3033 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
3035 DWORD dwStyle = pT->GetStyle();
\r
3038 // Debug only: Check if top level dialogs have a resizeable border.
\r
3039 if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) == 0))
\r
3040 ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n"));
\r
3043 // Force specified styles (default WS_CLIPCHILDREN reduces flicker)
\r
3044 if((dwStyle & dwForceStyle) != dwForceStyle)
\r
3045 pT->ModifyStyle(0, dwForceStyle);
\r
3047 // Adding this style removes an empty icon that dialogs with WS_THICKFRAME have.
\r
3048 // Setting icon to NULL is required when XP themes are active.
\r
3049 // Note: This will not prevent adding an icon for the dialog using SetIcon()
\r
3050 if((dwStyle & WS_CHILD) == 0)
\r
3052 pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME);
\r
3053 if(pT->GetIcon(FALSE) == NULL)
\r
3054 pT->SetIcon(NULL, FALSE);
\r
3057 // Cleanup in case of multiple initialization
\r
3058 // block: first check for the gripper control, destroy it if needed
\r
3060 ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
\r
3061 if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0)
\r
3062 wndGripper.DestroyWindow();
\r
3064 // clear out everything else
\r
3065 m_arrData.RemoveAll();
\r
3066 m_sizeDialog.cx = 0;
\r
3067 m_sizeDialog.cy = 0;
\r
3068 m_ptMinTrackSize.x = -1;
\r
3069 m_ptMinTrackSize.y = -1;
\r
3071 // Get initial dialog client size
\r
3072 RECT rectDlg = { 0 };
\r
3073 pT->GetClientRect(&rectDlg);
\r
3074 m_sizeDialog.cx = rectDlg.right;
\r
3075 m_sizeDialog.cy = rectDlg.bottom;
\r
3077 #ifndef _WIN32_WCE
\r
3078 // Create gripper if requested
\r
3079 m_bGripper = false;
\r
3082 // shouldn't exist already
\r
3083 ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)));
\r
3084 if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)))
\r
3086 ATL::CWindow wndGripper;
\r
3087 wndGripper.Create(_T("SCROLLBAR"), pT->m_hWnd, rectDlg, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SBS_SIZEBOX | SBS_SIZEGRIP | SBS_SIZEBOXBOTTOMRIGHTALIGN, 0, ATL_IDW_STATUS_BAR);
\r
3088 ATLASSERT(wndGripper.IsWindow());
\r
3089 if(wndGripper.IsWindow())
\r
3091 m_bGripper = true;
\r
3092 RECT rectCtl = { 0 };
\r
3093 wndGripper.GetWindowRect(&rectCtl);
\r
3094 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
\r
3095 _AtlDlgResizeData data = { ATL_IDW_STATUS_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
\r
3096 m_arrData.Add(data);
\r
3100 #else // CE specific
\r
3101 bAddGripper; // avoid level 4 warning
\r
3102 #endif // _WIN32_WCE
\r
3104 // Get min track position if requested
\r
3105 if(bUseMinTrackSize)
\r
3107 if((dwStyle & WS_CHILD) != 0)
\r
3109 RECT rect = { 0 };
\r
3110 pT->GetClientRect(&rect);
\r
3111 m_ptMinTrackSize.x = rect.right - rect.left;
\r
3112 m_ptMinTrackSize.y = rect.bottom - rect.top;
\r
3116 RECT rect = { 0 };
\r
3117 pT->GetWindowRect(&rect);
\r
3118 m_ptMinTrackSize.x = rect.right - rect.left;
\r
3119 m_ptMinTrackSize.y = rect.bottom - rect.top;
\r
3123 // Walk the map and initialize data
\r
3124 const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap();
\r
3125 ATLASSERT(pMap != NULL);
\r
3126 int nGroupStart = -1;
\r
3127 for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++)
\r
3129 if(pMap->m_nCtlID == -1)
\r
3131 switch(pMap->m_dwResizeFlags)
\r
3133 case _DLSZ_BEGIN_GROUP:
\r
3134 ATLASSERT(nGroupStart == -1);
\r
3135 nGroupStart = m_arrData.GetSize();
\r
3137 case _DLSZ_END_GROUP:
\r
3139 ATLASSERT(nGroupStart != -1);
\r
3140 int nGroupCount = m_arrData.GetSize() - nGroupStart;
\r
3141 m_arrData[nGroupStart].SetGroupCount(nGroupCount);
\r
3146 ATLASSERT(FALSE && _T("Invalid DLGRESIZE Map Entry"));
\r
3152 // this ID conflicts with the default gripper one
\r
3153 ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE);
\r
3155 ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID);
\r
3156 ATLASSERT(ctl.IsWindow());
\r
3157 RECT rectCtl = { 0 };
\r
3158 ctl.GetWindowRect(&rectCtl);
\r
3159 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
\r
3161 DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0;
\r
3162 _AtlDlgResizeData data = { pMap->m_nCtlID, pMap->m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
\r
3163 m_arrData.Add(data);
\r
3166 ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the DLGRESIZE Map"));
\r
3169 void DlgResize_UpdateLayout(int cxWidth, int cyHeight)
\r
3171 T* pT = static_cast<T*>(this);
\r
3172 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
3174 // Restrict minimum size if requested
\r
3175 if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
\r
3177 if(cxWidth < m_ptMinTrackSize.x)
\r
3178 cxWidth = m_ptMinTrackSize.x;
\r
3179 if(cyHeight < m_ptMinTrackSize.y)
\r
3180 cyHeight = m_ptMinTrackSize.y;
\r
3183 BOOL bVisible = pT->IsWindowVisible();
\r
3185 pT->SetRedraw(FALSE);
\r
3187 for(int i = 0; i < m_arrData.GetSize(); i++)
\r
3189 if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) != 0) // start of a group
\r
3191 int nGroupCount = m_arrData[i].GetGroupCount();
\r
3192 ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize());
\r
3193 RECT rectGroup = m_arrData[i].m_rect;
\r
3196 for(j = 1; j < nGroupCount; j++)
\r
3198 rectGroup.left = min(rectGroup.left, m_arrData[i + j].m_rect.left);
\r
3199 rectGroup.top = min(rectGroup.top, m_arrData[i + j].m_rect.top);
\r
3200 rectGroup.right = max(rectGroup.right, m_arrData[i + j].m_rect.right);
\r
3201 rectGroup.bottom = max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom);
\r
3204 for(j = 0; j < nGroupCount; j++)
\r
3206 _AtlDlgResizeData* pDataPrev = NULL;
\r
3208 pDataPrev = &(m_arrData[i + j - 1]);
\r
3209 pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i + j], true, pDataPrev);
\r
3212 i += nGroupCount - 1; // increment to skip all group controls
\r
3214 else // one control entry
\r
3216 RECT rectGroup = { 0, 0, 0, 0 };
\r
3217 pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i], false);
\r
3222 pT->SetRedraw(TRUE);
\r
3224 pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
\r
3227 // Message map and handlers
\r
3228 BEGIN_MSG_MAP(CDialogResize)
\r
3229 MESSAGE_HANDLER(WM_SIZE, OnSize)
\r
3230 #ifndef _WIN32_WCE
\r
3231 MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
\r
3232 #endif // _WIN32_WCE
\r
3235 LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
\r
3237 T* pT = static_cast<T*>(this);
\r
3238 #ifndef _WIN32_WCE
\r
3241 ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
\r
3242 if(wParam == SIZE_MAXIMIZED)
\r
3243 wndGripper.ShowWindow(SW_HIDE);
\r
3244 else if(wParam == SIZE_RESTORED)
\r
3245 wndGripper.ShowWindow(SW_SHOW);
\r
3247 #endif // _WIN32_WCE
\r
3248 if(wParam != SIZE_MINIMIZED)
\r
3250 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
3251 pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
\r
3256 #ifndef _WIN32_WCE
\r
3257 LRESULT OnGetMinMaxInfo(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
\r
3259 if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
\r
3261 LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
\r
3262 lpMMI->ptMinTrackSize = m_ptMinTrackSize;
\r
3266 #endif // _WIN32_WCE
\r
3269 bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGroup, _AtlDlgResizeData& data, bool bGroup,
\r
3270 _AtlDlgResizeData* pDataPrev = NULL)
\r
3272 T* pT = static_cast<T*>(this);
\r
3273 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
3275 RECT rectCtl = { 0 };
\r
3277 ctl = pT->GetDlgItem(data.m_nCtlID);
\r
3278 if(!ctl.GetWindowRect(&rectCtl))
\r
3280 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
\r
3284 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
\r
3286 int cxRight = rectGroup.right + cxWidth - m_sizeDialog.cx;
\r
3287 int cxCtl = data.m_rect.right - data.m_rect.left;
\r
3288 rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2;
\r
3289 rectCtl.right = rectCtl.left + cxCtl;
\r
3291 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
\r
3293 rectCtl.left = rectGroup.left + ::MulDiv(data.m_rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
\r
3295 if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0)
\r
3297 rectCtl.right = rectGroup.left + ::MulDiv(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
\r
3299 if(pDataPrev != NULL)
\r
3301 ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
\r
3302 RECT rcPrev = { 0 };
\r
3303 ctlPrev.GetWindowRect(&rcPrev);
\r
3304 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
\r
3305 int dxAdjust = (rectCtl.left - rcPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right);
\r
3306 rcPrev.right += dxAdjust;
\r
3307 ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
\r
3312 rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left);
\r
3316 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
\r
3318 int cyBottom = rectGroup.bottom + cyHeight - m_sizeDialog.cy;
\r
3319 int cyCtl = data.m_rect.bottom - data.m_rect.top;
\r
3320 rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2;
\r
3321 rectCtl.bottom = rectCtl.top + cyCtl;
\r
3323 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
\r
3325 rectCtl.top = rectGroup.top + ::MulDiv(data.m_rect.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
\r
3327 if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0)
\r
3329 rectCtl.bottom = rectGroup.top + ::MulDiv(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
\r
3331 if(pDataPrev != NULL)
\r
3333 ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
\r
3334 RECT rcPrev = { 0 };
\r
3335 ctlPrev.GetWindowRect(&rcPrev);
\r
3336 ::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
\r
3337 int dxAdjust = (rectCtl.top - rcPrev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom);
\r
3338 rcPrev.bottom += dxAdjust;
\r
3339 ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
\r
3344 rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top);
\r
3350 if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
\r
3352 int cxCtl = data.m_rect.right - data.m_rect.left;
\r
3353 rectCtl.left = (cxWidth - cxCtl) / 2;
\r
3354 rectCtl.right = rectCtl.left + cxCtl;
\r
3356 else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
\r
3358 rectCtl.right = data.m_rect.right + (cxWidth - m_sizeDialog.cx);
\r
3360 if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0)
\r
3361 rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left);
\r
3364 if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
\r
3366 int cyCtl = data.m_rect.bottom - data.m_rect.top;
\r
3367 rectCtl.top = (cyHeight - cyCtl) / 2;
\r
3368 rectCtl.bottom = rectCtl.top + cyCtl;
\r
3370 else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
\r
3372 rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeDialog.cy);
\r
3374 if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0)
\r
3375 rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top);
\r
3379 if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0)
\r
3382 if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_SIZE_Y | DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | DLSZ_CENTER_X | DLSZ_CENTER_Y)) != 0)
\r
3383 ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE);
\r
3390 ///////////////////////////////////////////////////////////////////////////////
\r
3391 // CDoubleBufferImpl - Provides double-buffer painting support to any window
\r
3393 template <class T>
\r
3394 class CDoubleBufferImpl
\r
3398 void DoPaint(CDCHandle /*dc*/)
\r
3400 // must be implemented in a derived class
\r
3404 // Message map and handlers
\r
3405 BEGIN_MSG_MAP(CDoubleBufferImpl)
\r
3406 MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
\r
3407 MESSAGE_HANDLER(WM_PAINT, OnPaint)
\r
3408 #ifndef _WIN32_WCE
\r
3409 MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
\r
3410 #endif // !_WIN32_WCE
\r
3413 LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
3415 return 1; // no background painting needed
\r
3418 LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
\r
3420 T* pT = static_cast<T*>(this);
\r
3421 ATLASSERT(::IsWindow(pT->m_hWnd));
\r
3423 if(wParam != NULL)
\r
3425 RECT rect = { 0 };
\r
3426 pT->GetClientRect(&rect);
\r
3427 CMemoryDC dcMem((HDC)wParam, rect);
\r
3428 pT->DoPaint(dcMem.m_hDC);
\r
3432 CPaintDC dc(pT->m_hWnd);
\r
3433 CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint);
\r
3434 pT->DoPaint(dcMem.m_hDC);
\r
3442 ///////////////////////////////////////////////////////////////////////////////
\r
3443 // CDoubleBufferWindowImpl - Implements a double-buffer painting window
\r
3445 template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
\r
3446 class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CDoubleBufferImpl< T >
\r
3449 BEGIN_MSG_MAP(CDoubleBufferWindowImpl)
\r
3450 CHAIN_MSG_MAP(CDoubleBufferImpl< T >)
\r
3455 // command bar support
\r
3456 #if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
\r
3457 #undef CBRM_GETMENU
\r
3458 #undef CBRM_TRACKPOPUPMENU
\r
3459 #undef CBRM_GETCMDBAR
\r
3460 #undef CBRPOPUPMENU
\r
3461 #endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
\r
3463 }; // namespace WTL
\r
3465 #endif // __ATLFRAME_H__
\r