PageRenderTime 104ms CodeModel.GetById 13ms app.highlight 76ms RepoModel.GetById 1ms app.codeStats 1ms

/thirdparty/wtl/atlframe.h

http://crashrpt.googlecode.com/
C++ Header | 3678 lines | 2942 code | 488 blank | 248 comment | 696 complexity | 418035ec778967ae3632c7f33f3fcf3c MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// Windows Template Library - WTL version 8.1
   2// Copyright (C) Microsoft Corporation. All rights reserved.
   3//
   4// This file is a part of the Windows Template Library.
   5// The use and distribution terms for this software are covered by the
   6// Common Public License 1.0 (http://opensource.org/licenses/cpl1.0.php)
   7// which can be found in the file CPL.TXT at the root of this distribution.
   8// By using this software in any fashion, you are agreeing to be bound by
   9// the terms of this license. You must not remove this notice, or
  10// any other, from this software.
  11
  12#ifndef __ATLFRAME_H__
  13#define __ATLFRAME_H__
  14
  15#pragma once
  16
  17#ifndef __ATLAPP_H__
  18	#error atlframe.h requires atlapp.h to be included first
  19#endif
  20
  21#ifndef __ATLWIN_H__
  22	#error atlframe.h requires atlwin.h to be included first
  23#endif
  24
  25
  26///////////////////////////////////////////////////////////////////////////////
  27// Classes in this file:
  28//
  29// CFrameWindowImpl<T, TBase, TWinTraits>
  30// CMDIWindow
  31// CMDIFrameWindowImpl<T, TBase, TWinTraits>
  32// CMDIChildWindowImpl<T, TBase, TWinTraits>
  33// COwnerDraw<T>
  34// CUpdateUIBase
  35// CUpdateUI<T>
  36// CDynamicUpdateUI<T>
  37// CAutoUpdateUI<T>
  38// CDialogResize<T>
  39// CDoubleBufferImpl<T>
  40// CDoubleBufferWindowImpl<T, TBase, TWinTraits>
  41//
  42// Global functions:
  43//   AtlCreateSimpleToolBar()
  44
  45
  46namespace WTL
  47{
  48
  49///////////////////////////////////////////////////////////////////////////////
  50// CFrameWndClassInfo - Manages frame window Windows class information
  51
  52class CFrameWndClassInfo
  53{
  54public:
  55#ifndef _WIN32_WCE
  56	enum { cchAutoName = 5 + sizeof(void*) * 2 };   // sizeof(void*) * 2 is the number of digits %p outputs
  57	WNDCLASSEX m_wc;
  58#else // CE specific
  59	enum { cchAutoName = MAX_PATH };   // MAX_PATH because this can be set in the wizard generated CMainFrame::ActivatePreviousInstance to a user defined string.
  60	WNDCLASS m_wc;
  61#endif // !_WIN32_WCE
  62	LPCTSTR m_lpszOrigName;
  63	WNDPROC pWndProc;
  64	LPCTSTR m_lpszCursorID;
  65	BOOL m_bSystemCursor;
  66	ATOM m_atom;
  67	TCHAR m_szAutoName[cchAutoName];
  68	UINT m_uCommonResourceID;
  69
  70#ifndef _WIN32_WCE
  71	ATOM Register(WNDPROC* pProc)
  72	{
  73		if (m_atom == 0)
  74		{
  75			CWindowCreateCriticalSectionLock lock;
  76			if(FAILED(lock.Lock()))
  77			{
  78				ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
  79				ATLASSERT(FALSE);
  80				return 0;
  81			}
  82
  83			if(m_atom == 0)
  84			{
  85				HINSTANCE hInst = ModuleHelper::GetModuleInstance();
  86
  87				if (m_lpszOrigName != NULL)
  88				{
  89					ATLASSERT(pProc != NULL);
  90					LPCTSTR lpsz = m_wc.lpszClassName;
  91					WNDPROC proc = m_wc.lpfnWndProc;
  92
  93					WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
  94					// try process local class first
  95					if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
  96					{
  97						// try global class
  98						if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
  99						{
 100							lock.Unlock();
 101							return 0;
 102						}
 103					}
 104					m_wc = wc;
 105					pWndProc = m_wc.lpfnWndProc;
 106					m_wc.lpszClassName = lpsz;
 107					m_wc.lpfnWndProc = proc;
 108				}
 109				else
 110				{
 111					m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
 112				}
 113
 114				m_wc.hInstance = hInst;
 115				m_wc.style &= ~CS_GLOBALCLASS;   // we don't register global classes
 116				if (m_wc.lpszClassName == NULL)
 117				{
 118#if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
 119					SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc);
 120#else // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
 121					SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
 122#endif // !((_WIN32_WINNT >= 0x0500) || defined(_WIN64))
 123					m_wc.lpszClassName = m_szAutoName;
 124				}
 125
 126				WNDCLASSEX wcTemp = m_wc;
 127				m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
 128				if (m_atom == 0)
 129				{
 130					if(m_uCommonResourceID != 0)   // use it if not zero
 131					{
 132						m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
 133						m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
 134					}
 135					m_atom = ::RegisterClassEx(&m_wc);
 136				}
 137			}
 138
 139			lock.Unlock();
 140		}
 141
 142		if (m_lpszOrigName != NULL)
 143		{
 144			ATLASSERT(pProc != NULL);
 145			ATLASSERT(pWndProc != NULL);
 146			*pProc = pWndProc;
 147		}
 148
 149		return m_atom;
 150	}
 151#else // CE specific
 152	ATOM Register(WNDPROC* pProc)
 153	{
 154		if (m_atom == 0)
 155		{
 156			CWindowCreateCriticalSectionLock lock;
 157			if(FAILED(lock.Lock()))
 158			{
 159				ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
 160				ATLASSERT(FALSE);
 161				return 0;
 162			}
 163
 164			if(m_atom == 0)
 165			{
 166				HINSTANCE hInst = ModuleHelper::GetModuleInstance();
 167
 168				if (m_lpszOrigName != NULL)
 169				{
 170					ATLASSERT(pProc != NULL);
 171					LPCTSTR lpsz = m_wc.lpszClassName;
 172					WNDPROC proc = m_wc.lpfnWndProc;
 173
 174					WNDCLASS wc = { 0 };
 175					// try process local class first
 176					if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
 177					{
 178						// try global class
 179						if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
 180						{
 181							lock.Unlock();
 182							return 0;
 183						}
 184					}
 185					m_wc = wc;
 186					pWndProc = m_wc.lpfnWndProc;
 187					m_wc.lpszClassName = lpsz;
 188					m_wc.lpfnWndProc = proc;
 189				}
 190				else
 191				{
 192#if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
 193					m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
 194#else // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
 195					m_wc.hCursor = NULL;
 196#endif // !(defined(GWES_CURSOR) || defined(GWES_MCURSOR))
 197				}
 198
 199				m_wc.hInstance = hInst;
 200				m_wc.style &= ~CS_GLOBALCLASS;   // we don't register global classes
 201				if (m_wc.lpszClassName == NULL)
 202				{
 203					wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
 204					m_wc.lpszClassName = m_szAutoName;
 205				}
 206
 207				WNDCLASS wcTemp = m_wc;
 208				m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
 209				if (m_atom == 0)
 210				{
 211					if(m_uCommonResourceID != 0)   // use it if not zero
 212						m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
 213					m_atom = ::RegisterClass(&m_wc);
 214				}
 215			}
 216
 217			lock.Unlock();
 218		}
 219
 220		if (m_lpszOrigName != NULL)
 221		{
 222			ATLASSERT(pProc != NULL);
 223			ATLASSERT(pWndProc != NULL);
 224			*pProc = pWndProc;
 225		}
 226
 227		return m_atom;
 228	}
 229#endif // _WIN32_WCE
 230};
 231
 232
 233///////////////////////////////////////////////////////////////////////////////
 234// Macros for declaring frame window WNDCLASS
 235
 236#ifndef _WIN32_WCE
 237
 238#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
 239static WTL::CFrameWndClassInfo& GetWndClassInfo() \
 240{ \
 241	static WTL::CFrameWndClassInfo wc = \
 242	{ \
 243		{ sizeof(WNDCLASSEX), 0, StartWindowProc, \
 244		  0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
 245		NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
 246	}; \
 247	return wc; \
 248}
 249
 250#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
 251static WTL::CFrameWndClassInfo& GetWndClassInfo() \
 252{ \
 253	static WTL::CFrameWndClassInfo wc = \
 254	{ \
 255		{ sizeof(WNDCLASSEX), style, StartWindowProc, \
 256		  0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
 257		NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
 258	}; \
 259	return wc; \
 260}
 261
 262#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
 263static WTL::CFrameWndClassInfo& GetWndClassInfo() \
 264{ \
 265	static WTL::CFrameWndClassInfo wc = \
 266	{ \
 267		{ sizeof(WNDCLASSEX), 0, StartWindowProc, \
 268		  0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
 269		OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
 270	}; \
 271	return wc; \
 272}
 273
 274#else // CE specific
 275
 276#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
 277static WTL::CFrameWndClassInfo& GetWndClassInfo() \
 278{ \
 279	static WTL::CFrameWndClassInfo wc = \
 280	{ \
 281		{ 0, StartWindowProc, \
 282		  0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
 283		NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
 284	}; \
 285	return wc; \
 286}
 287
 288#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
 289static WTL::CFrameWndClassInfo& GetWndClassInfo() \
 290{ \
 291	static WTL::CFrameWndClassInfo wc = \
 292	{ \
 293		{ style, StartWindowProc, \
 294		  0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
 295		NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
 296	}; \
 297	return wc; \
 298}
 299
 300#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
 301static WTL::CFrameWndClassInfo& GetWndClassInfo() \
 302{ \
 303	static WTL::CFrameWndClassInfo wc = \
 304	{ \
 305		{ NULL, StartWindowProc, \
 306		  0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
 307		OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
 308	}; \
 309	return wc; \
 310}
 311
 312#endif // !_WIN32_WCE
 313
 314
 315///////////////////////////////////////////////////////////////////////////////
 316// CFrameWindowImpl
 317
 318// Client window command chaining macro (only for frame windows)
 319#define CHAIN_CLIENT_COMMANDS() \
 320	if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
 321		::SendMessage(m_hWndClient, uMsg, wParam, lParam);
 322
 323// standard toolbar styles
 324#define ATL_SIMPLE_TOOLBAR_STYLE \
 325	(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
 326// toolbar in a rebar pane
 327#define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
 328	(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
 329// standard rebar styles
 330#if (_WIN32_IE >= 0x0400)
 331  #define ATL_SIMPLE_REBAR_STYLE \
 332	(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
 333#else
 334  #define ATL_SIMPLE_REBAR_STYLE \
 335	(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
 336#endif // !(_WIN32_IE >= 0x0400)
 337// rebar without borders
 338#if (_WIN32_IE >= 0x0400)
 339  #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
 340	(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
 341#else
 342  #define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
 343	(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
 344#endif // !(_WIN32_IE >= 0x0400)
 345
 346// command bar support
 347#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
 348
 349#define CBRM_GETCMDBAR			(WM_USER + 301) // returns command bar HWND
 350#define CBRM_GETMENU			(WM_USER + 302) // returns loaded or attached menu
 351#define CBRM_TRACKPOPUPMENU		(WM_USER + 303) // displays a popup menu
 352
 353struct _AtlFrameWnd_CmdBarPopupMenu
 354{
 355	int cbSize;
 356	HMENU hMenu;
 357	UINT uFlags;
 358	int x;
 359	int y;
 360	LPTPMPARAMS lptpm;
 361};
 362
 363#define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
 364
 365#endif // !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
 366
 367
 368template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
 369class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits >
 370{
 371public:
 372	DECLARE_FRAME_WND_CLASS(NULL, 0)
 373
 374#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
 375	struct _ChevronMenuInfo
 376	{
 377		HMENU hMenu;
 378		LPNMREBARCHEVRON lpnm;
 379		bool bCmdBar;
 380	};
 381#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
 382
 383// Data members
 384	HWND m_hWndToolBar;
 385	HWND m_hWndStatusBar;
 386	HWND m_hWndClient;
 387
 388#ifdef _WIN32_WCE
 389	HWND m_hWndCECommandBar;
 390#endif // _WIN32_WCE
 391
 392	HACCEL m_hAccel;
 393
 394// Constructor
 395	CFrameWindowImplBase() : 
 396		m_hWndToolBar(NULL), 
 397		m_hWndStatusBar(NULL), 
 398		m_hWndClient(NULL), 
 399#ifdef _WIN32_WCE
 400		m_hWndCECommandBar(NULL),
 401#endif // _WIN32_WCE
 402		m_hAccel(NULL)
 403	{ }
 404
 405// Methods
 406	HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
 407	{
 408		ATLASSERT(m_hWnd == NULL);
 409
 410		if(atom == 0)
 411			return NULL;
 412
 413		ModuleHelper::AddCreateWndData(&m_thunk.cd, this);
 414
 415		if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
 416			MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
 417		if(rect.m_lpRect == NULL)
 418			rect.m_lpRect = &TBase::rcDefault;
 419
 420		HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
 421			dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
 422			rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
 423			ModuleHelper::GetModuleInstance(), lpCreateParam);
 424
 425		ATLASSERT(hWnd == NULL || m_hWnd == hWnd);
 426
 427		return hWnd;
 428	}
 429
 430	static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, 
 431			DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
 432	{
 433		HINSTANCE hInst = ModuleHelper::GetResourceInstance();
 434		HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
 435		if (hRsrc == NULL)
 436			return NULL;
 437
 438		HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
 439		if (hGlobal == NULL)
 440			return NULL;
 441
 442		_AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
 443		if (pData == NULL)
 444			return NULL;
 445		ATLASSERT(pData->wVersion == 1);
 446
 447		WORD* pItems = pData->items();
 448		int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
 449		CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff;
 450		TBBUTTON* pTBBtn = buff.Allocate(nItems);
 451		ATLASSERT(pTBBtn != NULL);
 452		if(pTBBtn == NULL)
 453			return NULL;
 454
 455		const int cxSeparator = 8;
 456
 457		// set initial separator (half width)
 458		if(bInitialSeparator)
 459		{
 460			pTBBtn[0].iBitmap = cxSeparator / 2;
 461			pTBBtn[0].idCommand = 0;
 462			pTBBtn[0].fsState = 0;
 463			pTBBtn[0].fsStyle = TBSTYLE_SEP;
 464			pTBBtn[0].dwData = 0;
 465			pTBBtn[0].iString = 0;
 466		}
 467
 468		int nBmp = 0;
 469		for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
 470		{
 471			if(pItems[i] != 0)
 472			{
 473				pTBBtn[j].iBitmap = nBmp++;
 474				pTBBtn[j].idCommand = pItems[i];
 475				pTBBtn[j].fsState = TBSTATE_ENABLED;
 476				pTBBtn[j].fsStyle = TBSTYLE_BUTTON;
 477				pTBBtn[j].dwData = 0;
 478				pTBBtn[j].iString = 0;
 479			}
 480			else
 481			{
 482				pTBBtn[j].iBitmap = cxSeparator;
 483				pTBBtn[j].idCommand = 0;
 484				pTBBtn[j].fsState = 0;
 485				pTBBtn[j].fsStyle = TBSTYLE_SEP;
 486				pTBBtn[j].dwData = 0;
 487				pTBBtn[j].iString = 0;
 488			}
 489		}
 490
 491#ifndef _WIN32_WCE
 492		HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
 493		if(hWnd == NULL)
 494		{
 495			ATLASSERT(FALSE);
 496			return NULL;
 497		}
 498#else // CE specific
 499		dwStyle;
 500		nID;
 501		// The toolbar must go onto the existing CommandBar or MenuBar
 502		HWND hWnd = hWndParent;
 503#endif // _WIN32_WCE
 504
 505		::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
 506
 507		// check if font is taller than our bitmaps
 508		CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
 509		if(font.IsNull())
 510			font = (HFONT)::GetStockObject(SYSTEM_FONT);
 511		LOGFONT lf = { 0 };
 512		font.GetLogFont(lf);
 513		WORD cyFontHeight = (WORD)abs(lf.lfHeight);
 514
 515#ifndef _WIN32_WCE
 516		WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID);
 517		if(bitsPerPixel > 4)
 518		{
 519			COLORREF crMask = CLR_DEFAULT;
 520			if(bitsPerPixel == 32)
 521			{
 522				// 32-bit color bitmap with alpha channel (valid for Windows XP and later)
 523				crMask = CLR_NONE;
 524			}
 525			HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
 526			ATLASSERT(hImageList != NULL);
 527			::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
 528		}
 529		else
 530#endif // !_WIN32_WCE
 531		{
 532			TBADDBITMAP tbab = { 0 };
 533			tbab.hInst = hInst;
 534			tbab.nID = nResourceID;
 535			::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
 536		}
 537
 538		::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
 539		::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight)));
 540		const int cxyButtonMargin = 7;
 541		::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, max(pData->wHeight, cyFontHeight) + cxyButtonMargin));
 542
 543		return hWnd;
 544	}
 545
 546#ifndef _WIN32_WCE
 547	static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
 548	{
 549		// Ensure style combinations for proper rebar painting
 550		if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
 551			dwStyle &= ~WS_BORDER;
 552		else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
 553			dwStyle |= CCS_NODIVIDER;
 554
 555		// Create rebar window
 556		HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
 557		if(hWndReBar == NULL)
 558		{
 559			ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
 560			return NULL;
 561		}
 562
 563		// Initialize and send the REBARINFO structure
 564		REBARINFO rbi = { sizeof(REBARINFO), 0 };
 565		if(::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi) == 0)
 566		{
 567			ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n"));
 568			::DestroyWindow(hWndReBar);
 569			return NULL;
 570		}
 571
 572		return hWndReBar;
 573	}
 574
 575	BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
 576	{
 577		ATLASSERT(!::IsWindow(m_hWndToolBar));
 578		m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID);
 579		return (m_hWndToolBar != NULL);
 580	}
 581
 582	static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
 583	{
 584		ATLASSERT(::IsWindow(hWndReBar));   // must be already created
 585#ifdef _DEBUG
 586		// block - check if this is really a rebar
 587		{
 588			TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 };
 589			::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
 590			ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
 591		}
 592#endif // _DEBUG
 593		ATLASSERT(::IsWindow(hWndBand));   // must be already created
 594
 595		// Get number of buttons on the toolbar
 596		int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L);
 597
 598		// Set band info structure
 599		REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
 600#if (_WIN32_IE >= 0x0400)
 601		rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE;
 602#else
 603		rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE;
 604#endif // !(_WIN32_IE >= 0x0400)
 605		if(lpstrTitle != NULL)
 606			rbBand.fMask |= RBBIM_TEXT;
 607		rbBand.fStyle = RBBS_CHILDEDGE;
 608#if (_WIN32_IE >= 0x0500)
 609		if(nBtnCount > 0)   // add chevron style for toolbar with buttons
 610			rbBand.fStyle |= RBBS_USECHEVRON;
 611#endif // (_WIN32_IE >= 0x0500)
 612		if(bNewRow)
 613			rbBand.fStyle |= RBBS_BREAK;
 614
 615		rbBand.lpText = (LPTSTR)lpstrTitle;
 616		rbBand.hwndChild = hWndBand;
 617		if(nID == 0)   // calc band ID
 618			nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
 619		rbBand.wID = nID;
 620
 621		// Calculate the size of the band
 622		BOOL bRet = FALSE;
 623		RECT rcTmp = { 0 };
 624		if(nBtnCount > 0)
 625		{
 626			bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp);
 627			ATLASSERT(bRet);
 628			rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right;
 629			rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
 630			if(bFullWidthAlways)
 631			{
 632				rbBand.cxMinChild = rbBand.cx;
 633			}
 634			else if(lpstrTitle == NULL)
 635			{
 636				bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp);
 637				ATLASSERT(bRet);
 638				rbBand.cxMinChild = rcTmp.right;
 639			}
 640			else
 641			{
 642				rbBand.cxMinChild = 0;
 643			}
 644		}
 645		else	// no buttons, either not a toolbar or really has no buttons
 646		{
 647			bRet = ::GetWindowRect(hWndBand, &rcTmp);
 648			ATLASSERT(bRet);
 649			rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left);
 650			rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0;
 651			rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
 652		}
 653
 654#if (_WIN32_IE >= 0x0400)
 655		rbBand.cxIdeal = rbBand.cx;
 656#endif // (_WIN32_IE >= 0x0400)
 657
 658		// Add the band
 659		LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
 660		if(lRes == 0)
 661		{
 662			ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n"));
 663			return FALSE;
 664		}
 665
 666#if (_WIN32_IE >= 0x0501)
 667		DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L);
 668		::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
 669#endif // (_WIN32_IE >= 0x0501)
 670
 671		return TRUE;
 672	}
 673
 674	BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
 675	{
 676		ATLASSERT(::IsWindow(m_hWndToolBar));   // must be an existing rebar
 677		ATLASSERT(::IsWindow(hWndBand));        // must be created
 678		return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways);
 679	}
 680
 681#if (_WIN32_IE >= 0x0400)
 682	void SizeSimpleReBarBands()
 683	{
 684		ATLASSERT(::IsWindow(m_hWndToolBar));   // must be an existing rebar
 685
 686		int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L);
 687
 688		for(int i = 0; i < nCount; i++)
 689		{
 690			REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
 691			rbBand.fMask = RBBIM_SIZE;
 692			BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand);
 693			ATLASSERT(bRet);
 694			RECT rect = { 0, 0, 0, 0 };
 695			::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect);
 696			rbBand.cx += rect.left + rect.right;
 697			bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand);
 698			ATLASSERT(bRet);
 699		}
 700	}
 701#endif // (_WIN32_IE >= 0x0400)
 702#endif // _WIN32_WCE
 703
 704#ifndef _WIN32_WCE
 705	BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
 706#else // CE specific
 707	BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
 708#endif // _WIN32_WCE
 709	{
 710		ATLASSERT(!::IsWindow(m_hWndStatusBar));
 711		m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
 712		return (m_hWndStatusBar != NULL);
 713	}
 714
 715#ifndef _WIN32_WCE
 716	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)
 717#else // CE specific
 718	BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
 719#endif // _WIN32_WCE
 720	{
 721		const int cchMax = 128;   // max text length is 127 for status bars (+1 for null)
 722		TCHAR szText[cchMax] = { 0 };
 723		::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
 724		return CreateSimpleStatusBar(szText, dwStyle, nID);
 725	}
 726
 727#ifdef _WIN32_WCE
 728	BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1)
 729	{
 730		ATLASSERT(m_hWndCECommandBar == NULL);
 731		ATLASSERT(m_hWndToolBar == NULL);
 732
 733		m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID);
 734		if(m_hWndCECommandBar == NULL)
 735			return FALSE;
 736
 737		m_hWndToolBar = m_hWndCECommandBar;
 738
 739		BOOL bRet = TRUE;
 740
 741		if(pszMenu != NULL)
 742			bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton);
 743
 744		bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0);
 745
 746		return bRet;
 747	}
 748
 749#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
 750	BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0)
 751	{
 752		ATLASSERT(m_hWndCECommandBar == NULL);
 753
 754		SHMENUBARINFO mbi = { 0 };
 755		mbi.cbSize = sizeof(mbi);
 756		mbi.hwndParent = m_hWnd;
 757		mbi.dwFlags = dwFlags;
 758		mbi.nToolBarId = nToolBarId;
 759		mbi.hInstRes  = ModuleHelper::GetResourceInstance();
 760		mbi.nBmpId = nBmpId;
 761		mbi.cBmpImages = cBmpImages;
 762		mbi.hwndMB = NULL;   // This gets set by SHCreateMenuBar
 763
 764		BOOL bRet = ::SHCreateMenuBar(&mbi);
 765		if(bRet != FALSE)
 766		{
 767			m_hWndCECommandBar = mbi.hwndMB;
 768			SizeToMenuBar();
 769		}
 770
 771		return bRet;
 772	}
 773
 774	void SizeToMenuBar()   // for menu bar only
 775	{
 776		ATLASSERT(::IsWindow(m_hWnd));
 777		ATLASSERT(::IsWindow(m_hWndCECommandBar));
 778
 779		RECT rect = { 0 };
 780		GetWindowRect(&rect);
 781		RECT rectMB = { 0 };
 782		::GetWindowRect(m_hWndCECommandBar, &rectMB);
 783		int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
 784		SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
 785	}
 786#endif // defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
 787#endif // _WIN32_WCE
 788
 789	void UpdateLayout(BOOL bResizeBars = TRUE)
 790	{
 791		RECT rect = { 0 };
 792		GetClientRect(&rect);
 793
 794		// position bars and offset their dimensions
 795		UpdateBarsPosition(rect, bResizeBars);
 796
 797		// resize client window
 798		if(m_hWndClient != NULL)
 799			::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
 800				rect.right - rect.left, rect.bottom - rect.top,
 801				SWP_NOZORDER | SWP_NOACTIVATE);
 802	}
 803
 804	void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
 805	{
 806		// resize toolbar
 807		if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
 808		{
 809			if(bResizeBars != FALSE)
 810			{
 811				::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
 812				::InvalidateRect(m_hWndToolBar, NULL, TRUE);
 813			}
 814			RECT rectTB = { 0 };
 815			::GetWindowRect(m_hWndToolBar, &rectTB);
 816			rect.top += rectTB.bottom - rectTB.top;
 817		}
 818
 819		// resize status bar
 820		if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
 821		{
 822			if(bResizeBars != FALSE)
 823				::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
 824			RECT rectSB = { 0 };
 825			::GetWindowRect(m_hWndStatusBar, &rectSB);
 826			rect.bottom -= rectSB.bottom - rectSB.top;
 827		}
 828	}
 829
 830	BOOL PreTranslateMessage(MSG* pMsg)
 831	{
 832		if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
 833			return TRUE;
 834		return FALSE;
 835	}
 836
 837	BEGIN_MSG_MAP(CFrameWindowImplBase)
 838		MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
 839#ifndef _WIN32_WCE
 840		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
 841#endif // !_WIN32_WCE
 842		MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
 843		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
 844#ifndef _WIN32_WCE
 845		NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA)
 846		NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW)
 847#endif // !_WIN32_WCE
 848	END_MSG_MAP()
 849
 850	LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
 851	{
 852		if(m_hWndClient != NULL)   // view will paint itself instead
 853			return 1;
 854
 855		bHandled = FALSE;
 856		return 0;
 857	}
 858
 859#ifndef _WIN32_WCE
 860	LRESULT OnMenuSelect(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
 861	{
 862		bHandled = FALSE;
 863
 864		if(m_hWndStatusBar == NULL)
 865			return 1;
 866
 867		WORD wFlags = HIWORD(wParam);
 868		if(wFlags == 0xFFFF && lParam == NULL)   // menu closing
 869		{
 870			::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
 871		}
 872		else
 873		{
 874			const int cchBuff = 256;
 875			TCHAR szBuff[cchBuff] = { 0 };
 876			if(!(wFlags & MF_POPUP))
 877			{
 878				WORD wID = LOWORD(wParam);
 879				// check for special cases
 880				if(wID >= 0xF000 && wID < 0xF1F0)   // system menu IDs
 881					wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
 882				else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST)   // MRU items
 883					wID = ATL_IDS_MRU_FILE;
 884				else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD)   // MDI child windows
 885					wID = ATL_IDS_MDICHILD;
 886
 887				int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff);
 888				for(int i = 0; i < nRet; i++)
 889				{
 890					if(szBuff[i] == _T('\n'))
 891					{
 892						szBuff[i] = 0;
 893						break;
 894					}
 895				}
 896			}
 897			::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
 898			::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
 899		}
 900
 901		return 1;
 902	}
 903#endif // !_WIN32_WCE
 904
 905	LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
 906	{
 907		if(m_hWndClient != NULL)
 908			::SetFocus(m_hWndClient);
 909
 910		bHandled = FALSE;
 911		return 1;
 912	}
 913
 914	LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
 915	{
 916		if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0)
 917			::PostQuitMessage(1);
 918
 919		bHandled = FALSE;
 920		return 1;
 921	}
 922
 923#ifndef _WIN32_WCE
 924	LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
 925	{
 926		LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh;
 927		pDispInfo->szText[0] = 0;
 928
 929		if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
 930		{
 931			const int cchBuff = 256;
 932			char szBuff[cchBuff] = { 0 };
 933			int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
 934			for(int i = 0; i < nRet; i++)
 935			{
 936				if(szBuff[i] == '\n')
 937				{
 938					SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
 939					break;
 940				}
 941			}
 942#if (_WIN32_IE >= 0x0300)
 943			if(nRet > 0)   // string was loaded, save it
 944				pDispInfo->uFlags |= TTF_DI_SETITEM;
 945#endif // (_WIN32_IE >= 0x0300)
 946		}
 947
 948		return 0;
 949	}
 950
 951	LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& /*bHandled*/)
 952	{
 953		LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh;
 954		pDispInfo->szText[0] = 0;
 955
 956		if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
 957		{
 958			const int cchBuff = 256;
 959			wchar_t szBuff[cchBuff] = { 0 };
 960			int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
 961			for(int i = 0; i < nRet; i++)
 962			{
 963				if(szBuff[i] == L'\n')
 964				{
 965					SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
 966					break;
 967				}
 968			}
 969#if (_WIN32_IE >= 0x0300)
 970			if(nRet > 0)   // string was loaded, save it
 971				pDispInfo->uFlags |= TTF_DI_SETITEM;
 972#endif // (_WIN32_IE >= 0x0300)
 973		}
 974
 975		return 0;
 976	}
 977#endif // !_WIN32_WCE
 978
 979// Implementation - chevron menu support
 980#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
 981	bool PrepareChevronMenu(_ChevronMenuInfo& cmi)
 982	{
 983		// get rebar and toolbar
 984		REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
 985		rbbi.fMask = RBBIM_CHILD;
 986		BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi);
 987		ATLASSERT(bRet);
 988
 989		// assume the band is a toolbar
 990		ATL::CWindow wnd = rbbi.hwndChild;
 991		int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT);
 992		if(nCount <= 0)   // probably not a toolbar
 993			return false;
 994
 995		// check if it's a command bar
 996		CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU);
 997		cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL);
 998
 999		// build a menu from hidden items
1000		CMenuHandle menu;
1001		bRet = menu.CreatePopupMenu();
1002		ATLASSERT(bRet);
1003		RECT rcClient = { 0 };
1004		bRet = wnd.GetClientRect(&rcClient);
1005		ATLASSERT(bRet);
1006		for(int i = 0; i < nCount; i++)
1007		{
1008			TBBUTTON tbb = { 0 };
1009			bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb);
1010			ATLASSERT(bRet);
1011			// skip hidden buttons
1012			if((tbb.fsState & TBSTATE_HIDDEN) != 0)
1013				continue;
1014			RECT rcButton = { 0 };
1015			bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton);
1016			ATLASSERT(bRet);
1017			bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0);
1018			if(rcButton.right > rcClient.right)
1019			{
1020				if(tbb.fsStyle & BTNS_SEP)
1021				{
1022					if(menu.GetMenuItemCount() > 0)
1023						menu.AppendMenu(MF_SEPARATOR);
1024				}
1025				else if(cmi.bCmdBar)
1026				{
1027					const int cchBuff = 200;
1028					TCHAR szBuff[cchBuff] = { 0 };
1029					CMenuItemInfo mii;
1030					mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
1031					mii.dwTypeData = szBuff;
1032					mii.cch = cchBuff;
1033					bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
1034					ATLASSERT(bRet);
1035					// Note: CmdBar currently supports only drop-down items
1036					ATLASSERT(::IsMenu(mii.hSubMenu));
1037					bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
1038					ATLASSERT(bRet);
1039				}
1040				else
1041				{
1042					// get button's text
1043					const int cchBuff = 200;
1044					TCHAR szBuff[cchBuff] = { 0 };
1045					LPTSTR lpstrText = szBuff;
1046					TBBUTTONINFO tbbi = { 0 };
1047					tbbi.cbSize = sizeof(TBBUTTONINFO);
1048					tbbi.dwMask = TBIF_TEXT;
1049					tbbi.pszText = szBuff;
1050					tbbi.cchText = cchBuff;
1051					if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0)
1052					{
1053						// no text for this button, try a resource string
1054						lpstrText = _T("");
1055						int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff);
1056						for(int n = 0; n < nRet; n++)
1057						{
1058							if(szBuff[n] == _T('\n'))
1059							{
1060								lpstrText = &szBuff[n + 1];
1061								break;
1062							}
1063						}
1064					}
1065					bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText);
1066					ATLASSERT(bRet);
1067				}
1068			}
1069		}
1070
1071		if(menu.GetMenuItemCount() == 0)   // no hidden buttons after all
1072		{
1073			menu.DestroyMenu();
1074			::MessageBeep((UINT)-1);
1075			return false;
1076		}
1077
1078		cmi.hMenu = menu;
1079		return true;
1080	}
1081
1082	void DisplayChevronMenu(_ChevronMenuInfo& cmi)
1083	{
1084#ifndef TPM_VERPOSANIMATION
1085		const UINT TPM_VERPOSANIMATION = 0x1000L;   // Menu animation flag
1086#endif
1087		// convert chevron rect to screen coordinates
1088		ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
1089		POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom };
1090		wndFrom.MapWindowPoints(NULL, &pt, 1);
1091		RECT rc = cmi.lpnm->rc;
1092		wndFrom.MapWindowPoints(NULL, &rc);
1093		// set up flags and rect
1094		UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
1095		TPMPARAMS TPMParams = { 0 };
1096		TPMParams.cbSize = sizeof(TPMPARAMS);
1097		TPMParams.rcExclude = rc;
1098		// check if this window has a command bar
1099		HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
1100		if(::IsWindow(hWndCmdBar))
1101		{
1102			CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams };
1103			::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu);
1104		}
1105		else
1106		{
1107			CMenuHandle menu = cmi.hMenu;
1108			menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams);
1109		}
1110	}
1111
1112	void CleanupChevronMenu(_ChevronMenuInfo& cmi)
1113	{
1114		CMenuHandle menu = cmi.hMenu;
1115		// if menu is from a command bar, detach submenus so they are not destroyed
1116		if(cmi.bCmdBar)
1117		{
1118			for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
1119				menu.RemoveMenu(i, MF_BYPOSITION);
1120		}
1121		// destroy menu
1122		menu.DestroyMenu();
1123		// convert chevron rect to screen coordinates
1124		ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
1125		RECT rc = cmi.lpnm->rc;
1126		wndFrom.MapWindowPoints(NULL, &rc);
1127		// eat next message if click is on the same button
1128		MSG msg = { 0 };
1129		if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt))
1130			::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
1131	}
1132#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1133};
1134
1135
1136template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
1137class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
1138{
1139public:
1140	HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1141			DWORD dwStyle = 0, DWORD dwExStyle = 0,
1142			HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
1143	{
1144		ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
1145
1146		dwStyle = T::GetWndStyle(dwStyle);
1147		dwExStyle = T::GetWndExStyle(dwExStyle);
1148
1149		if(rect.m_lpRect == NULL)
1150			rect.m_lpRect = &TBase::rcDefault;
1151
1152		return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
1153	}
1154
1155	HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
1156	{
1157		const int cchName = 256;
1158		TCHAR szWindowName[cchName] = { 0 };
1159#ifndef _WIN32_WCE
1160		::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1161		HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1162#else // CE specific
1163		::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1164
1165		// This always needs to be NULL for Windows CE.
1166		// Frame Window menus have to go onto the CommandBar.
1167		// Use CreateSimpleCECommandBar
1168		HMENU hMenu = NULL;
1169#endif // _WIN32_WCE
1170
1171		T* pT = static_cast<T*>(this);
1172		HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
1173
1174		if(hWnd != NULL)
1175			m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1176
1177		return hWnd;
1178	}
1179
1180	BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1181	{
1182		if(nResourceID == 0)
1183			nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1184#ifndef _WIN32_WCE
1185		ATLASSERT(!::IsWindow(m_hWndToolBar));
1186		m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
1187		return (m_hWndToolBar != NULL);
1188#else // CE specific
1189		HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
1190		return (hWnd != NULL);
1191#endif // _WIN32_WCE
1192	}
1193
1194#ifdef _WIN32_WCE
1195	// CE specific variant that returns the handle of the toolbar
1196	HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1197	{
1198		if(nResourceID == 0)
1199			nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1200
1201		return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
1202	}
1203#endif // _WIN32_WCE
1204
1205// message map and handlers
1206	typedef CFrameWindowImplBase< TBase, TWinTraits >   _baseClass;
1207
1208	BEGIN_MSG_MAP(CFrameWindowImpl)
1209		MESSAGE_HANDLER(WM_SIZE, OnSize)
1210#ifndef _ATL_NO_REBAR_SUPPORT
1211#if (_WIN32_IE >= 0x0400)
1212		NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
1213#endif // (_WIN32_IE >= 0x0400)
1214#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1215		NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
1216#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1217#endif // !_ATL_NO_REBAR_SUPPORT
1218		CHAIN_MSG_MAP(_baseClass)
1219	END_MSG_MAP()
1220
1221	LRESULT OnSize(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
1222	{
1223		if(wParam != SIZE_MINIMIZED)
1224		{
1225			T* pT = static_cast<T*>(this);
1226			pT->UpdateLayout();
1227		}
1228		bHandled = FALSE;
1229		return 1;
1230	}
1231
1232#ifndef _ATL_NO_REBAR_SUPPORT
1233#if (_WIN32_IE >= 0x0400)
1234	LRESULT OnReBarAutoSize(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
1235	{
1236		T* pT = static_cast<T*>(this);
1237		pT->UpdateLayout(FALSE);
1238		return 0;
1239	}
1240#endif // (_WIN32_IE >= 0x0400)
1241
1242#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1243	LRESULT OnChevronPushed(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
1244	{
1245		T* pT = static_cast<T*>(this);
1246		_ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
1247		if(!pT->PrepareChevronMenu(cmi))
1248		{
1249			bHandled = FALSE;
1250			return 1;
1251		}
1252		// display a popup menu with hidden items
1253		pT->DisplayChevronMenu(cmi);
1254		// cleanup
1255		pT->CleanupChevronMenu(cmi);
1256		return 0;
1257	}
1258#endif // (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
1259#endif // !_ATL_NO_REBAR_SUPPORT
1260};
1261
1262
1263///////////////////////////////////////////////////////////////////////////////
1264// AtlCreateSimpleToolBar - helper for creating simple toolbars
1265
1266#ifndef _WIN32_WCE
1267
1268inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE, 
1269		DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1270{
1271	return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID);
1272}
1273
1274#endif // !_WIN32_WCE
1275
1276
1277///////////////////////////////////////////////////////////////////////////////
1278// CMDIWindow
1279
1280#ifndef _WIN32_WCE
1281
1282#ifndef _WTL_MDIWINDOWMENU_TEXT
1283#define _WTL_MDIWINDOWMENU_TEXT	_T("&Window")
1284#endif
1285
1286class CMDIWindow : public ATL::CWindow
1287{
1288public:
1289// Data members
1290	HWND m_hWndMDIClient;
1291	HMENU m_hMenu;
1292
1293// Constructors
1294	CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL)
1295	{ }
1296
1297	CMDIWindow& operator =(HWND hWnd)
1298	{
1299		m_hWnd = hWnd;
1300		return *this;
1301	}
1302
1303// Operations
1304	HWND MDIGetActive(BOOL* lpbMaximized = NULL)
1305	{
1306		ATLASSERT(::IsWindow(m_hWndMDIClient));
1307		return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
1308	}
1309
1310	void MDIActivate(HWND hWndChildToActivate)
1311	{
1312		ATLASSERT(::IsWindow(m_hWndMDIClient));
1313		ATLASSERT(::IsWindow(hWndChildToActivate));
1314		::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
1315	}
1316
1317	void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
1318	{
1319		ATLASSERT(::IsWindow(m_hWndMDIClient));
1320		ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
1321		::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
1322	}
1323
1324	void MDIMaximize(HWND hWndChildToMaximize)
1325	{
1326		ATLASSERT(::IsWindow(m_hWndMDIClient));
1327		ATLASSERT(::IsWindow(hWndChildToMaximize));
1328		::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
1329	}
1330
1331	void MDIRestore(HWND hWndChildToRestore)
1332	{
1333		ATLASSERT(::IsWindow(m_hWndMDIClient));
1334		ATLASSERT(::IsWindow(hWndChildToRestore));
1335		::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0);
1336	}
1337
1338	void MDIDestroy(HWND hWndChildToDestroy)
1339	{
1340		ATLASSERT(::IsWindow(m_hWndMDIClient));
1341		ATLASSERT(::IsWindow(hWndChildToDestroy));
1342		::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
1343	}
1344
1345	BOOL MDICascade(UINT uFlags = 0)
1346	{
1347		ATLASSERT(::IsWindow(m_hWndMDIClient));
1348		return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
1349	}
1350
1351	BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
1352	{
1353		ATLASSERT(::IsWindow(m_hWndMDIClient));
1354		return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
1355	}
1356
1357	void MDIIconArrange()
1358	{
1359		ATLASSERT(::IsWindow(m_hWndMDIClient));
1360		::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
1361	}
1362
1363	HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
1364	{
1365		ATLASSERT(::IsWindow(m_hWndMDIClient));
1366		return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
1367	}
1368
1369	HMENU MDIRefreshMenu()
1370	{
1371		ATLASSERT(::IsWindow(m_hWndMDIClient));
1372		return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
1373	}
1374
1375// Additional operations
1376	static HMENU GetStandardWindowMenu(HMENU hMenu)
1377	{
1378		int nCount = ::GetMenuItemCount(hMenu);
1379		if(nCount == -1)
1380			return NULL;
1381		int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
1382		if(nLen == 0)
1383			return NULL;
1384		CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
1385		LPTSTR lpszText = buff.Allocate(nLen + 1);
1386		if(lpszText == NULL)
1387			return NULL;
1388		if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
1389			return NULL;
1390		if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0)
1391			return NULL;
1392		return ::GetSubMenu(hMenu, nCount - 2);
1393	}
1394
1395	void SetMDIFrameMenu()
1396	{
1397		HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
1398		MDISetMenu(m_hMenu, hWindowMenu);
1399		MDIRefreshMenu();
1400		::DrawMenuBar(GetMDIFrame());
1401	}
1402
1403	HWND GetMDIFrame() const
1404	{
1405		return ::GetParent(m_hWndMDIClient);
1406	}
1407};
1408
1409#endif // !_WIN32_WCE
1410
1411
1412///////////////////////////////////////////////////////////////////////////////
1413// CMDIFrameWindowImpl
1414
1415#ifndef _WIN32_WCE
1416
1417// MDI child command chaining macro (only for MDI frame windows)
1418#define CHAIN_MDI_CHILD_COMMANDS() \
1419	if(uMsg == WM_COMMAND) \
1420	{ \
1421		HWND hWndChild = MDIGetActive(); \
1422		if(hWndChild != NULL) \
1423			::SendMessage(hWndChild, uMsg, wParam, lParam); \
1424	}
1425
1426template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
1427class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
1428{
1429public:
1430	HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
1431			DWORD dwStyle = 0, DWORD dwExStyle = 0,
1432			HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
1433	{
1434		m_hMenu = hMenu;
1435		ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
1436
1437		dwStyle = T::GetWndStyle(dwStyle);
1438		dwExStyle = T::GetWndExStyle(dwExStyle);
1439
1440		if(rect.m_lpRect == NULL)
1441			rect.m_lpRect = &TBase::rcDefault;
1442
1443		return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
1444	}
1445
1446	HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
1447	{
1448		const int cchName = 256;
1449		TCHAR szWindowName[cchName] = { 0 };
1450		::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
1451		HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1452
1453		T* pT = static_cast<T*>(this);
1454		HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
1455
1456		if(hWnd != NULL)
1457			m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
1458
1459		return hWnd;
1460	}
1461
1462	BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
1463	{
1464		ATLASSERT(!::IsWindow(m_hWndToolBar));
1465		if(nResourceID == 0)
1466			nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
1467		m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
1468		return (m_hWndToolBar != NULL);
1469	}
1470
1471	virtual WNDPROC GetWindowProc()
1472	{
1473		return MDIFrameWindowProc;
1474	}
1475
1476	static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1477	{
1478		CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
1479		// set a ptr to this message and save the old value
1480#if (_ATL_VER >= 0x0700)
1481		ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
1482		const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
1483#else // !(_ATL_VER >= 0x0700)
1484		MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
1485		const MSG* pOldMsg = pThis->m_pCurrentMsg;
1486#endif // !(_ATL_VER >= 0x0700)
1487		pThis->m_pCurrentMsg = &msg;
1488		// pass to the message map to process
1489		LRESULT lRes = 0;
1490		BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
1491		// restore saved value for the current message
1492		ATLASSERT(pThis->m_pCurrentMsg == &msg);
1493		pThis->m_pCurrentMsg = pOldMsg;
1494		// do the default processing if message was not handled
1495		if(!bRet)
1496		{
1497			if(uMsg != WM_NCDESTROY)
1498				lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
1499			else
1500			{
1501				// unsubclass, if needed
1502				LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
1503				lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
1504				if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
1505					::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
1506#if (_ATL_VER >= 0x0700)
1507				// mark window as destryed
1508				pThis->m_dwState |= WINSTATE_DESTROYED;
1509#else // !(_ATL_VER >= 0x0700)
1510				// clear out window handle
1511				HWND hWnd = pThis->m_hWnd;
1512				pThis->m_hWnd = NULL;
1513				// clean up after window is destroyed
1514				pThis->OnFinalMessage(hWnd);
1515#endif // !(_ATL_VER >= 0x0700)
1516			}
1517		}
1518#if (_ATL_VER >= 0x0700)
1519		if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL)
1520		{
1521			// clear out window handle
1522			HWND hWnd = pThis->m_hWnd;
1523			pThis->m_hWnd = NULL;
1524			pThis->m_dwState &= ~WINSTATE_DESTROYED;
1525			// clean up after window is destroyed
1526			pThis->OnFinalMessage(hWnd);
1527		}
1528#endif // (_ATL_VER >= 0x0700)
1529		return lRes;
1530	}
1531
1532	// Overriden to call DefWindowProc which uses DefFrameProc
1533	LRESULT DefWindowProc()
1534	{
1535		const MSG* pMsg = m_pCurrentMsg;
1536		LRESULT lRes = 0;
1537		if (pMsg != NULL)
1538			lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
1539		return lRes;
1540	}
1541
1542	LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
1543	{
1544		return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam);
1545	}
1546
1547	BOOL PreTranslateMessage(MSG* pMsg)
1548	{
1549		if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
1550			return TRUE;
1551		return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg);
1552	}
1553
1554	HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
1555	{
1556		DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
1557		DWORD dwExStyle = WS_EX_CLIENTEDGE;
1558
1559		CLIENTCREATESTRUCT ccs = { 0 };
1560		ccs.hWindowMenu = hWindowMenu;
1561		ccs.idFirstChild = nFirstChildID;
1562
1563		if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0)
1564		{
1565			// parent MDI frame's scroll styles move to the MDICLIENT
1566			dwStyl

Large files files are truncated, but you can click here to view the full file