#ifndef __ATLFRAME_H__
#define __ATLFRAME_H__
#pragma once
#ifndef __cplusplus
#error ATL requires C++ compilation (use a .cpp suffix)
#endif
#ifndef __ATLAPP_H__
#error atlframe.h requires atlapp.h to be included first
#endif
#ifndef __ATLWIN_H__
#error atlframe.h requires atlwin.h to be included first
#endif
namespace WTL
{
class CFrameWndClassInfo
{
public:
#ifndef _WIN32_WCE
enum { cchAutoName = 5 + sizeof(void*) * 2 };
WNDCLASSEX m_wc;
#else
enum { cchAutoName = MAX_PATH };
WNDCLASS m_wc;
#endif
LPCTSTR m_lpszOrigName;
WNDPROC pWndProc;
LPCTSTR m_lpszCursorID;
BOOL m_bSystemCursor;
ATOM m_atom;
TCHAR m_szAutoName[cchAutoName];
UINT m_uCommonResourceID;
#ifndef _WIN32_WCE
ATOM Register(WNDPROC* pProc)
{
if (m_atom == 0)
{
CWindowCreateCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
ATLASSERT(FALSE);
return 0;
}
if(m_atom == 0)
{
HINSTANCE hInst = ModuleHelper::GetModuleInstance();
if (m_lpszOrigName != NULL)
{
ATLASSERT(pProc != NULL);
LPCTSTR lpsz = m_wc.lpszClassName;
WNDPROC proc = m_wc.lpfnWndProc;
WNDCLASSEX wc = { 0 };
wc.cbSize = sizeof(WNDCLASSEX);
if(!::GetClassInfoEx(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
{
if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
{
lock.Unlock();
return 0;
}
}
m_wc = wc;
pWndProc = m_wc.lpfnWndProc;
m_wc.lpszClassName = lpsz;
m_wc.lpfnWndProc = proc;
}
else
{
m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
}
m_wc.hInstance = hInst;
m_wc.style &= ~CS_GLOBALCLASS;
if (m_wc.lpszClassName == NULL)
{
#if (_WIN32_WINNT >= 0x0500) || defined(_WIN64)
SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%p"), &m_wc);
#else
SecureHelper::wsprintf_x(m_szAutoName, cchAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
#endif
m_wc.lpszClassName = m_szAutoName;
}
WNDCLASSEX wcTemp = m_wc;
m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
if (m_atom == 0)
{
if(m_uCommonResourceID != 0)
{
m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
m_wc.hIconSm = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
}
m_atom = ::RegisterClassEx(&m_wc);
}
}
lock.Unlock();
}
if (m_lpszOrigName != NULL)
{
ATLASSERT(pProc != NULL);
ATLASSERT(pWndProc != NULL);
*pProc = pWndProc;
}
return m_atom;
}
#else
ATOM Register(WNDPROC* pProc)
{
if (m_atom == 0)
{
CWindowCreateCriticalSectionLock lock;
if(FAILED(lock.Lock()))
{
ATLTRACE2(atlTraceUI, 0, _T("ERROR : Unable to lock critical section in CFrameWndClassInfo::Register.\n"));
ATLASSERT(FALSE);
return 0;
}
if(m_atom == 0)
{
HINSTANCE hInst = ModuleHelper::GetModuleInstance();
if (m_lpszOrigName != NULL)
{
ATLASSERT(pProc != NULL);
LPCTSTR lpsz = m_wc.lpszClassName;
WNDPROC proc = m_wc.lpfnWndProc;
WNDCLASS wc = { 0 };
if(!::GetClassInfo(ModuleHelper::GetModuleInstance(), m_lpszOrigName, &wc))
{
if(!::GetClassInfo(NULL, m_lpszOrigName, &wc))
{
lock.Unlock();
return 0;
}
}
m_wc = wc;
pWndProc = m_wc.lpfnWndProc;
m_wc.lpszClassName = lpsz;
m_wc.lpfnWndProc = proc;
}
else
{
#if defined(GWES_CURSOR) || defined(GWES_MCURSOR)
m_wc.hCursor = ::LoadCursor(m_bSystemCursor ? NULL : hInst, m_lpszCursorID);
#else
m_wc.hCursor = NULL;
#endif
}
m_wc.hInstance = hInst;
m_wc.style &= ~CS_GLOBALCLASS;
if (m_wc.lpszClassName == NULL)
{
wsprintf(m_szAutoName, _T("ATL:%8.8X"), (DWORD_PTR)&m_wc);
m_wc.lpszClassName = m_szAutoName;
}
WNDCLASS wcTemp = m_wc;
m_atom = (ATOM)::GetClassInfo(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
if (m_atom == 0)
{
if(m_uCommonResourceID != 0)
m_wc.hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
m_atom = ::RegisterClass(&m_wc);
}
}
lock.Unlock();
}
if (m_lpszOrigName != NULL)
{
ATLASSERT(pProc != NULL);
ATLASSERT(pWndProc != NULL);
*pProc = pWndProc;
}
return m_atom;
}
#endif
};
#ifndef _WIN32_WCE
#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
static WTL::CFrameWndClassInfo& GetWndClassInfo() \
{ \
static WTL::CFrameWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), 0, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName, NULL }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
static WTL::CFrameWndClassInfo& GetWndClassInfo() \
{ \
static WTL::CFrameWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), style, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
static WTL::CFrameWndClassInfo& GetWndClassInfo() \
{ \
static WTL::CFrameWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), 0, StartWindowProc, \
0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
#else
#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
static WTL::CFrameWndClassInfo& GetWndClassInfo() \
{ \
static WTL::CFrameWndClassInfo wc = \
{ \
{ 0, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(COLOR_WINDOW + 1), NULL, WndClassName }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
#define DECLARE_FRAME_WND_CLASS_EX(WndClassName, uCommonResourceID, style, bkgnd) \
static WTL::CFrameWndClassInfo& GetWndClassInfo() \
{ \
static WTL::CFrameWndClassInfo wc = \
{ \
{ style, StartWindowProc, \
0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName }, \
NULL, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
#define DECLARE_FRAME_WND_SUPERCLASS(WndClassName, OrigWndClassName, uCommonResourceID) \
static WTL::CFrameWndClassInfo& GetWndClassInfo() \
{ \
static WTL::CFrameWndClassInfo wc = \
{ \
{ NULL, StartWindowProc, \
0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName }, \
OrigWndClassName, NULL, IDC_ARROW, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
#endif
#define CHAIN_CLIENT_COMMANDS() \
if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
::SendMessage(m_hWndClient, uMsg, wParam, lParam);
#define ATL_SIMPLE_TOOLBAR_STYLE \
(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
#define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
#if (_WIN32_IE >= 0x0400)
#define ATL_SIMPLE_REBAR_STYLE \
(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE)
#else
#define ATL_SIMPLE_REBAR_STYLE \
(WS_CHILD | WS_VISIBLE | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS)
#endif
#if (_WIN32_IE >= 0x0400)
#define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | RBS_AUTOSIZE | CCS_NODIVIDER)
#else
#define ATL_SIMPLE_REBAR_NOBORDER_STYLE \
(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS | CCS_NODIVIDER)
#endif
#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
#define CBRM_GETCMDBAR (WM_USER + 301)
#define CBRM_GETMENU (WM_USER + 302)
#define CBRM_TRACKPOPUPMENU (WM_USER + 303)
struct _AtlFrameWnd_CmdBarPopupMenu
{
int cbSize;
HMENU hMenu;
UINT uFlags;
int x;
int y;
LPTPMPARAMS lptpm;
};
#define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
#endif
template <class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
class ATL_NO_VTABLE CFrameWindowImplBase : public ATL::CWindowImplBaseT< TBase, TWinTraits >
{
public:
DECLARE_FRAME_WND_CLASS(NULL, 0)
HWND m_hWndToolBar;
HWND m_hWndStatusBar;
HWND m_hWndClient;
HACCEL m_hAccel;
#ifdef _WIN32_WCE
HWND m_hWndCECommandBar;
#endif
struct _AtlToolBarData
{
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
WORD* items()
{ return (WORD*)(this+1); }
};
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
struct _ChevronMenuInfo
{
HMENU hMenu;
LPNMREBARCHEVRON lpnm;
bool bCmdBar;
};
#endif
CFrameWindowImplBase() :
#ifdef _WIN32_WCE
m_hWndCECommandBar(NULL),
#endif
m_hWndToolBar(NULL),
m_hWndStatusBar(NULL),
m_hWndClient(NULL),
m_hAccel(NULL)
{ }
HWND Create(HWND hWndParent, ATL::_U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, ATL::_U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
{
ATLASSERT(m_hWnd == NULL);
if(atom == 0)
return NULL;
ModuleHelper::AddCreateWndData(&m_thunk.cd, this);
if(MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD))
MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this;
if(rect.m_lpRect == NULL)
rect.m_lpRect = &TBase::rcDefault;
HWND hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName,
dwStyle, rect.m_lpRect->left, rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left,
rect.m_lpRect->bottom - rect.m_lpRect->top, hWndParent, MenuOrID.m_hMenu,
ModuleHelper::GetModuleInstance(), lpCreateParam);
ATLASSERT(hWnd == NULL || m_hWnd == hWnd);
return hWnd;
}
static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
HINSTANCE hInst = ModuleHelper::GetResourceInstance();
HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(nResourceID), RT_TOOLBAR);
if (hRsrc == NULL)
return NULL;
HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
if (hGlobal == NULL)
return NULL;
_AtlToolBarData* pData = (_AtlToolBarData*)::LockResource(hGlobal);
if (pData == NULL)
return NULL;
ATLASSERT(pData->wVersion == 1);
WORD* pItems = pData->items();
int nItems = pData->wItemCount + (bInitialSeparator ? 1 : 0);
CTempBuffer<TBBUTTON, _WTL_STACK_ALLOC_THRESHOLD> buff;
TBBUTTON* pTBBtn = buff.Allocate(nItems);
ATLASSERT(pTBBtn != NULL);
if(pTBBtn == NULL)
return NULL;
const int cxSeparator = 8;
if(bInitialSeparator)
{
pTBBtn[0].iBitmap = cxSeparator / 2;
pTBBtn[0].idCommand = 0;
pTBBtn[0].fsState = 0;
pTBBtn[0].fsStyle = TBSTYLE_SEP;
pTBBtn[0].dwData = 0;
pTBBtn[0].iString = 0;
}
int nBmp = 0;
for(int i = 0, j = bInitialSeparator ? 1 : 0; i < pData->wItemCount; i++, j++)
{
if(pItems[i] != 0)
{
pTBBtn[j].iBitmap = nBmp++;
pTBBtn[j].idCommand = pItems[i];
pTBBtn[j].fsState = TBSTATE_ENABLED;
pTBBtn[j].fsStyle = TBSTYLE_BUTTON;
pTBBtn[j].dwData = 0;
pTBBtn[j].iString = 0;
}
else
{
pTBBtn[j].iBitmap = cxSeparator;
pTBBtn[j].idCommand = 0;
pTBBtn[j].fsState = 0;
pTBBtn[j].fsStyle = TBSTYLE_SEP;
pTBBtn[j].dwData = 0;
pTBBtn[j].iString = 0;
}
}
#ifndef _WIN32_WCE
HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
if(hWnd == NULL)
{
ATLASSERT(FALSE);
return NULL;
}
#else
dwStyle;
nID;
HWND hWnd = hWndParent;
#endif
::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
if(font.IsNull())
font = AtlGetDefaultGuiFont();
LOGFONT lf = { 0 };
font.GetLogFont(lf);
WORD cyFontHeight = (WORD)abs(lf.lfHeight);
#ifndef _WIN32_WCE
WORD bitsPerPixel = AtlGetBitmapResourceBitsPerPixel(nResourceID);
if(bitsPerPixel > 4)
{
COLORREF crMask = CLR_DEFAULT;
if(bitsPerPixel == 32)
{
crMask = CLR_NONE;
}
HIMAGELIST hImageList = ImageList_LoadImage(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, crMask, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
ATLASSERT(hImageList != NULL);
::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
}
else
#endif
{
TBADDBITMAP tbab = { 0 };
tbab.hInst = hInst;
tbab.nID = nResourceID;
::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
}
::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, __max(pData->wHeight, cyFontHeight)));
const int cxyButtonMargin = 7;
::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + cxyButtonMargin, __max(pData->wHeight, cyFontHeight) + cxyButtonMargin));
return hWnd;
}
#ifndef _WIN32_WCE
static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
dwStyle &= ~WS_BORDER;
else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
dwStyle |= CCS_NODIVIDER;
HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), ModuleHelper::GetModuleInstance(), NULL);
if(hWndReBar == NULL)
{
ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
return NULL;
}
REBARINFO rbi = { 0 };
rbi.cbSize = sizeof(REBARINFO);
rbi.fMask = 0;
if(!::SendMessage(hWndReBar, RB_SETBARINFO, 0, (LPARAM)&rbi))
{
ATLTRACE2(atlTraceUI, 0, _T("Failed to initialize rebar.\n"));
::DestroyWindow(hWndReBar);
return NULL;
}
return hWndReBar;
}
BOOL CreateSimpleReBar(DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
ATLASSERT(!::IsWindow(m_hWndToolBar));
m_hWndToolBar = CreateSimpleReBarCtrl(m_hWnd, dwStyle, nID);
return (m_hWndToolBar != NULL);
}
static BOOL AddSimpleReBarBandCtrl(HWND hWndReBar, HWND hWndBand, int nID = 0, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
{
ATLASSERT(::IsWindow(hWndReBar));
#ifdef _DEBUG
{
TCHAR lpszClassName[sizeof(REBARCLASSNAME)] = { 0 };
::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
}
#endif
ATLASSERT(::IsWindow(hWndBand));
int nBtnCount = (int)::SendMessage(hWndBand, TB_BUTTONCOUNT, 0, 0L);
REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
#if (_WIN32_IE >= 0x0400)
rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE | RBBIM_IDEALSIZE;
#else
rbBand.fMask = RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_ID | RBBIM_SIZE;
#endif
if(lpstrTitle != NULL)
rbBand.fMask |= RBBIM_TEXT;
rbBand.fStyle = RBBS_CHILDEDGE;
#if (_WIN32_IE >= 0x0500)
if(nBtnCount > 0)
rbBand.fStyle |= RBBS_USECHEVRON;
#endif
if(bNewRow)
rbBand.fStyle |= RBBS_BREAK;
rbBand.lpText = (LPTSTR)lpstrTitle;
rbBand.hwndChild = hWndBand;
if(nID == 0)
nID = ATL_IDW_BAND_FIRST + (int)::SendMessage(hWndReBar, RB_GETBANDCOUNT, 0, 0L);
rbBand.wID = nID;
BOOL bRet = FALSE;
RECT rcTmp = { 0 };
if(nBtnCount > 0)
{
bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, nBtnCount - 1, (LPARAM)&rcTmp);
ATLASSERT(bRet);
rbBand.cx = (cxWidth != 0) ? cxWidth : rcTmp.right;
rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
if(bFullWidthAlways)
{
rbBand.cxMinChild = rbBand.cx;
}
else if(lpstrTitle == NULL)
{
bRet = (BOOL)::SendMessage(hWndBand, TB_GETITEMRECT, 0, (LPARAM)&rcTmp);
ATLASSERT(bRet);
rbBand.cxMinChild = rcTmp.right;
}
else
{
rbBand.cxMinChild = 0;
}
}
else
{
bRet = ::GetWindowRect(hWndBand, &rcTmp);
ATLASSERT(bRet);
rbBand.cx = (cxWidth != 0) ? cxWidth : (rcTmp.right - rcTmp.left);
rbBand.cxMinChild = bFullWidthAlways ? rbBand.cx : 0;
rbBand.cyMinChild = rcTmp.bottom - rcTmp.top;
}
#if (_WIN32_IE >= 0x0400)
rbBand.cxIdeal = rbBand.cx;
#endif
LRESULT lRes = ::SendMessage(hWndReBar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
if(lRes == 0)
{
ATLTRACE2(atlTraceUI, 0, _T("Failed to add a band to the rebar.\n"));
return FALSE;
}
#if (_WIN32_IE >= 0x0501)
DWORD dwExStyle = (DWORD)::SendMessage(hWndBand, TB_GETEXTENDEDSTYLE, 0, 0L);
::SendMessage(hWndBand, TB_SETEXTENDEDSTYLE, 0, dwExStyle | TBSTYLE_EX_HIDECLIPPEDBUTTONS);
#endif
return TRUE;
}
BOOL AddSimpleReBarBand(HWND hWndBand, LPCTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
{
ATLASSERT(::IsWindow(m_hWndToolBar));
ATLASSERT(::IsWindow(hWndBand));
return AddSimpleReBarBandCtrl(m_hWndToolBar, hWndBand, 0, lpstrTitle, bNewRow, cxWidth, bFullWidthAlways);
}
#if (_WIN32_IE >= 0x0400)
void SizeSimpleReBarBands()
{
ATLASSERT(::IsWindow(m_hWndToolBar));
int nCount = (int)::SendMessage(m_hWndToolBar, RB_GETBANDCOUNT, 0, 0L);
for(int i = 0; i < nCount; i++)
{
REBARBANDINFO rbBand = { RunTimeHelper::SizeOf_REBARBANDINFO() };
rbBand.fMask = RBBIM_SIZE;
BOOL bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_GETBANDINFO, i, (LPARAM)&rbBand);
ATLASSERT(bRet);
RECT rect = { 0, 0, 0, 0 };
::SendMessage(m_hWndToolBar, RB_GETBANDBORDERS, i, (LPARAM)&rect);
rbBand.cx += rect.left + rect.right;
bRet = (BOOL)::SendMessage(m_hWndToolBar, RB_SETBANDINFO, i, (LPARAM)&rbBand);
ATLASSERT(bRet);
}
}
#endif
#endif
#ifndef _WIN32_WCE
BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
#else
BOOL CreateSimpleStatusBar(LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
#endif
{
ATLASSERT(!::IsWindow(m_hWndStatusBar));
m_hWndStatusBar = ::CreateStatusWindow(dwStyle, lpstrText, m_hWnd, nID);
return (m_hWndStatusBar != NULL);
}
#ifndef _WIN32_WCE
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)
#else
BOOL CreateSimpleStatusBar(UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, UINT nID = ATL_IDW_STATUS_BAR)
#endif
{
const int cchMax = 128;
TCHAR szText[cchMax];
szText[0] = 0;
::LoadString(ModuleHelper::GetResourceInstance(), nTextID, szText, cchMax);
return CreateSimpleStatusBar(szText, dwStyle, nID);
}
#ifdef _WIN32_WCE
BOOL CreateSimpleCECommandBar(LPTSTR pszMenu = NULL, WORD iButton = 0, DWORD dwFlags = 0, int nCmdBarID = 1)
{
ATLASSERT(m_hWndCECommandBar == NULL);
ATLASSERT(m_hWndToolBar == NULL);
m_hWndCECommandBar = ::CommandBar_Create(ModuleHelper::GetModuleInstance(), m_hWnd, nCmdBarID);
if(m_hWndCECommandBar == NULL)
return FALSE;
m_hWndToolBar = m_hWndCECommandBar;
BOOL bRet = TRUE;
if(pszMenu != NULL)
bRet &= ::CommandBar_InsertMenubarEx(m_hWndCECommandBar, IS_INTRESOURCE(pszMenu) ? ModuleHelper::GetResourceInstance() : NULL, pszMenu, iButton);
bRet &= ::CommandBar_AddAdornments(m_hWndCECommandBar, dwFlags, 0);
return bRet;
}
#if defined(_AYGSHELL_H_) || defined(__AYGSHELL_H__)
BOOL CreateSimpleCEMenuBar(UINT nToolBarId = ATL_IDW_MENU_BAR, DWORD dwFlags = 0, int nBmpId = 0, int cBmpImages = 0)
{
ATLASSERT(m_hWndCECommandBar == NULL);
SHMENUBARINFO mbi = { 0 };
mbi.cbSize = sizeof(mbi);
mbi.hwndParent = m_hWnd;
mbi.dwFlags = dwFlags;
mbi.nToolBarId = nToolBarId;
mbi.hInstRes = ModuleHelper::GetResourceInstance();
mbi.nBmpId = nBmpId;
mbi.cBmpImages = cBmpImages;
mbi.hwndMB = NULL;
BOOL bRet = ::SHCreateMenuBar(&mbi);
if(bRet != FALSE)
{
m_hWndCECommandBar = mbi.hwndMB;
SizeToMenuBar();
}
return bRet;
}
void SizeToMenuBar()
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(::IsWindow(m_hWndCECommandBar));
RECT rect = { 0 };
GetWindowRect(&rect);
RECT rectMB = { 0 };
::GetWindowRect(m_hWndCECommandBar, &rectMB);
int cy = ::IsWindowVisible(m_hWndCECommandBar) ? rectMB.top - rect.top : rectMB.bottom - rect.top;
SetWindowPos(NULL, 0, 0, rect.right - rect.left, cy, SWP_NOZORDER | SWP_NOMOVE);
}
#endif
#endif
void UpdateLayout(BOOL bResizeBars = TRUE)
{
RECT rect = { 0 };
GetClientRect(&rect);
UpdateBarsPosition(rect, bResizeBars);
if(m_hWndClient != NULL)
::SetWindowPos(m_hWndClient, NULL, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOZORDER | SWP_NOACTIVATE);
}
void UpdateBarsPosition(RECT& rect, BOOL bResizeBars = TRUE)
{
if(m_hWndToolBar != NULL && ((DWORD)::GetWindowLong(m_hWndToolBar, GWL_STYLE) & WS_VISIBLE))
{
if(bResizeBars)
{
::SendMessage(m_hWndToolBar, WM_SIZE, 0, 0);
::InvalidateRect(m_hWndToolBar, NULL, FALSE);
}
RECT rectTB = { 0 };
::GetWindowRect(m_hWndToolBar, &rectTB);
rect.top += rectTB.bottom - rectTB.top;
}
if(m_hWndStatusBar != NULL && ((DWORD)::GetWindowLong(m_hWndStatusBar, GWL_STYLE) & WS_VISIBLE))
{
if(bResizeBars)
::SendMessage(m_hWndStatusBar, WM_SIZE, 0, 0);
RECT rectSB = { 0 };
::GetWindowRect(m_hWndStatusBar, &rectSB);
rect.bottom -= rectSB.bottom - rectSB.top;
}
}
BOOL PreTranslateMessage(MSG* pMsg)
{
if(m_hAccel != NULL && ::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
return TRUE;
return FALSE;
}
BEGIN_MSG_MAP(CFrameWindowImplBase)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
#endif
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
#ifndef _WIN32_WCE
NOTIFY_CODE_HANDLER(TTN_GETDISPINFOA, OnToolTipTextA)
NOTIFY_CODE_HANDLER(TTN_GETDISPINFOW, OnToolTipTextW)
#endif
END_MSG_MAP()
LRESULT OnEraseBackground(UINT , WPARAM , LPARAM , BOOL& bHandled)
{
if(m_hWndClient != NULL)
return 1;
bHandled = FALSE;
return 0;
}
#ifndef _WIN32_WCE
LRESULT OnMenuSelect(UINT , WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
bHandled = FALSE;
if(m_hWndStatusBar == NULL)
return 1;
WORD wFlags = HIWORD(wParam);
if(wFlags == 0xFFFF && lParam == NULL)
{
::SendMessage(m_hWndStatusBar, SB_SIMPLE, FALSE, 0L);
}
else
{
const int cchBuff = 256;
TCHAR szBuff[cchBuff];
szBuff[0] = 0;
if(!(wFlags & MF_POPUP))
{
WORD wID = LOWORD(wParam);
if(wID >= 0xF000 && wID < 0xF1F0)
wID = (WORD)(((wID - 0xF000) >> 4) + ATL_IDS_SCFIRST);
else if(wID >= ID_FILE_MRU_FIRST && wID <= ID_FILE_MRU_LAST)
wID = ATL_IDS_MRU_FILE;
else if(wID >= ATL_IDM_FIRST_MDICHILD && wID <= ATL_IDM_LAST_MDICHILD)
wID = ATL_IDS_MDICHILD;
int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), wID, szBuff, cchBuff);
for(int i = 0; i < nRet; i++)
{
if(szBuff[i] == _T('\n'))
{
szBuff[i] = 0;
break;
}
}
}
::SendMessage(m_hWndStatusBar, SB_SIMPLE, TRUE, 0L);
::SendMessage(m_hWndStatusBar, SB_SETTEXT, (255 | SBT_NOBORDERS), (LPARAM)szBuff);
}
return 1;
}
#endif
LRESULT OnSetFocus(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
if(m_hWndClient != NULL)
::SetFocus(m_hWndClient);
bHandled = FALSE;
return 1;
}
LRESULT OnDestroy(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
if((GetStyle() & (WS_CHILD | WS_POPUP)) == 0)
::PostQuitMessage(1);
bHandled = FALSE;
return 1;
}
#ifndef _WIN32_WCE
LRESULT OnToolTipTextA(int idCtrl, LPNMHDR pnmh, BOOL& )
{
LPNMTTDISPINFOA pDispInfo = (LPNMTTDISPINFOA)pnmh;
pDispInfo->szText[0] = 0;
if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
{
const int cchBuff = 256;
char szBuff[cchBuff];
szBuff[0] = 0;
int nRet = ::LoadStringA(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
for(int i = 0; i < nRet; i++)
{
if(szBuff[i] == '\n')
{
SecureHelper::strncpyA_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
break;
}
}
#if (_WIN32_IE >= 0x0300)
if(nRet > 0)
pDispInfo->uFlags |= TTF_DI_SETITEM;
#endif
}
return 0;
}
LRESULT OnToolTipTextW(int idCtrl, LPNMHDR pnmh, BOOL& )
{
LPNMTTDISPINFOW pDispInfo = (LPNMTTDISPINFOW)pnmh;
pDispInfo->szText[0] = 0;
if((idCtrl != 0) && !(pDispInfo->uFlags & TTF_IDISHWND))
{
const int cchBuff = 256;
wchar_t szBuff[cchBuff];
szBuff[0] = 0;
int nRet = ::LoadStringW(ModuleHelper::GetResourceInstance(), idCtrl, szBuff, cchBuff);
for(int i = 0; i < nRet; i++)
{
if(szBuff[i] == L'\n')
{
SecureHelper::strncpyW_x(pDispInfo->szText, _countof(pDispInfo->szText), &szBuff[i + 1], _TRUNCATE);
break;
}
}
#if (_WIN32_IE >= 0x0300)
if(nRet > 0)
pDispInfo->uFlags |= TTF_DI_SETITEM;
#endif
}
return 0;
}
#endif
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
bool PrepareChevronMenu(_ChevronMenuInfo& cmi)
{
REBARBANDINFO rbbi = { RunTimeHelper::SizeOf_REBARBANDINFO() };
rbbi.fMask = RBBIM_CHILD;
BOOL bRet = (BOOL)::SendMessage(cmi.lpnm->hdr.hwndFrom, RB_GETBANDINFO, cmi.lpnm->uBand, (LPARAM)&rbbi);
ATLASSERT(bRet);
ATL::CWindow wnd = rbbi.hwndChild;
int nCount = (int)wnd.SendMessage(TB_BUTTONCOUNT);
if(nCount <= 0)
return false;
CMenuHandle menuCmdBar = (HMENU)wnd.SendMessage(CBRM_GETMENU);
cmi.bCmdBar = (menuCmdBar.m_hMenu != NULL);
CMenuHandle menu;
bRet = menu.CreatePopupMenu();
ATLASSERT(bRet);
RECT rcClient = { 0 };
bRet = wnd.GetClientRect(&rcClient);
ATLASSERT(bRet);
for(int i = 0; i < nCount; i++)
{
TBBUTTON tbb = { 0 };
bRet = (BOOL)wnd.SendMessage(TB_GETBUTTON, i, (LPARAM)&tbb);
ATLASSERT(bRet);
if((tbb.fsState & TBSTATE_HIDDEN) != 0)
continue;
RECT rcButton = { 0 };
bRet = (BOOL)wnd.SendMessage(TB_GETITEMRECT, i, (LPARAM)&rcButton);
ATLASSERT(bRet);
bool bEnabled = ((tbb.fsState & TBSTATE_ENABLED) != 0);
if(rcButton.right > rcClient.right)
{
if(tbb.fsStyle & BTNS_SEP)
{
if(menu.GetMenuItemCount() > 0)
menu.AppendMenu(MF_SEPARATOR);
}
else if(cmi.bCmdBar)
{
const int cchBuff = 200;
TCHAR szBuff[cchBuff] = { 0 };
CMenuItemInfo mii;
mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
mii.dwTypeData = szBuff;
mii.cch = cchBuff;
bRet = menuCmdBar.GetMenuItemInfo(i, TRUE, &mii);
ATLASSERT(bRet);
ATLASSERT(::IsMenu(mii.hSubMenu));
bRet = menu.AppendMenu(MF_STRING | MF_POPUP | (bEnabled ? MF_ENABLED : MF_GRAYED), (UINT_PTR)mii.hSubMenu, mii.dwTypeData);
ATLASSERT(bRet);
}
else
{
const int cchBuff = 200;
TCHAR szBuff[cchBuff] = { 0 };
LPTSTR lpstrText = szBuff;
TBBUTTONINFO tbbi = { 0 };
tbbi.cbSize = sizeof(TBBUTTONINFO);
tbbi.dwMask = TBIF_TEXT;
tbbi.pszText = szBuff;
tbbi.cchText = cchBuff;
if(wnd.SendMessage(TB_GETBUTTONINFO, tbb.idCommand, (LPARAM)&tbbi) == -1 || lstrlen(szBuff) == 0)
{
lpstrText = _T("");
int nRet = ::LoadString(ModuleHelper::GetResourceInstance(), tbb.idCommand, szBuff, cchBuff);
for(int n = 0; n < nRet; n++)
{
if(szBuff[n] == _T('\n'))
{
lpstrText = &szBuff[n + 1];
break;
}
}
}
bRet = menu.AppendMenu(MF_STRING | (bEnabled ? MF_ENABLED : MF_GRAYED), tbb.idCommand, lpstrText);
ATLASSERT(bRet);
}
}
}
if(menu.GetMenuItemCount() == 0)
{
menu.DestroyMenu();
::MessageBeep((UINT)-1);
return false;
}
cmi.hMenu = menu;
return true;
}
void DisplayChevronMenu(_ChevronMenuInfo& cmi)
{
#ifndef TPM_VERPOSANIMATION
const UINT TPM_VERPOSANIMATION = 0x1000L;
#endif
ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
POINT pt = { cmi.lpnm->rc.left, cmi.lpnm->rc.bottom };
wndFrom.MapWindowPoints(NULL, &pt, 1);
RECT rc = cmi.lpnm->rc;
wndFrom.MapWindowPoints(NULL, &rc);
UINT uMenuFlags = TPM_LEFTBUTTON | TPM_VERTICAL | TPM_LEFTALIGN | TPM_TOPALIGN | (!AtlIsOldWindows() ? TPM_VERPOSANIMATION : 0);
TPMPARAMS TPMParams = { 0 };
TPMParams.cbSize = sizeof(TPMPARAMS);
TPMParams.rcExclude = rc;
HWND hWndCmdBar = (HWND)::SendMessage(m_hWnd, CBRM_GETCMDBAR, 0, 0L);
if(::IsWindow(hWndCmdBar))
{
CBRPOPUPMENU CBRPopupMenu = { sizeof(CBRPOPUPMENU), cmi.hMenu, uMenuFlags, pt.x, pt.y, &TPMParams };
::SendMessage(hWndCmdBar, CBRM_TRACKPOPUPMENU, 0, (LPARAM)&CBRPopupMenu);
}
else
{
CMenuHandle menu = cmi.hMenu;
menu.TrackPopupMenuEx(uMenuFlags, pt.x, pt.y, m_hWnd, &TPMParams);
}
}
void CleanupChevronMenu(_ChevronMenuInfo& cmi)
{
CMenuHandle menu = cmi.hMenu;
if(cmi.bCmdBar)
{
for(int i = menu.GetMenuItemCount() - 1; i >=0; i--)
menu.RemoveMenu(i, MF_BYPOSITION);
}
menu.DestroyMenu();
ATL::CWindow wndFrom = cmi.lpnm->hdr.hwndFrom;
RECT rc = cmi.lpnm->rc;
wndFrom.MapWindowPoints(NULL, &rc);
MSG msg = { 0 };
if(::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_NOREMOVE) && ::PtInRect(&rc, msg.pt))
::PeekMessage(&msg, m_hWnd, WM_LBUTTONDOWN, WM_LBUTTONDOWN, PM_REMOVE);
}
#endif
};
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CFrameWinTraits>
class ATL_NO_VTABLE CFrameWindowImpl : public CFrameWindowImplBase< TBase, TWinTraits >
{
public:
HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
{
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
dwStyle = T::GetWndStyle(dwStyle);
dwExStyle = T::GetWndExStyle(dwExStyle);
if(rect.m_lpRect == NULL)
rect.m_lpRect = &TBase::rcDefault;
return CFrameWindowImplBase< TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
}
HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
{
const int cchName = 256;
TCHAR szWindowName[cchName];
szWindowName[0] = 0;
#ifndef _WIN32_WCE
::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
#else
::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
HMENU hMenu = NULL;
#endif
T* pT = static_cast<T*>(this);
HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
if(hWnd != NULL)
m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
return hWnd;
}
BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
if(nResourceID == 0)
nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
#ifndef _WIN32_WCE
ATLASSERT(!::IsWindow(m_hWndToolBar));
m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
return (m_hWndToolBar != NULL);
#else
HWND hWnd= T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
return (hWnd != NULL);
#endif
}
#ifdef _WIN32_WCE
HWND CreateSimpleCEToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
if(nResourceID == 0)
nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
return T::CreateSimpleToolBarCtrl(m_hWndCECommandBar, nResourceID, TRUE, dwStyle, nID);
}
#endif
typedef CFrameWindowImplBase< TBase, TWinTraits > _baseClass;
BEGIN_MSG_MAP(CFrameWindowImpl)
MESSAGE_HANDLER(WM_SIZE, OnSize)
#ifndef _ATL_NO_REBAR_SUPPORT
#if (_WIN32_IE >= 0x0400)
NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
#endif
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
#endif
#endif
CHAIN_MSG_MAP(_baseClass)
END_MSG_MAP()
LRESULT OnSize(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
{
if(wParam != SIZE_MINIMIZED)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
bHandled = FALSE;
return 1;
}
#ifndef _ATL_NO_REBAR_SUPPORT
#if (_WIN32_IE >= 0x0400)
LRESULT OnReBarAutoSize(int , LPNMHDR , BOOL& )
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout(FALSE);
return 0;
}
#endif
#if (_WIN32_IE >= 0x0500) && !defined(_WIN32_WCE)
LRESULT OnChevronPushed(int , LPNMHDR pnmh, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
_ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
if(!pT->PrepareChevronMenu(cmi))
{
bHandled = FALSE;
return 1;
}
pT->DisplayChevronMenu(cmi);
pT->CleanupChevronMenu(cmi);
return 0;
}
#endif
#endif
};
#ifndef _WIN32_WCE
inline HWND AtlCreateSimpleToolBar(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
return CFrameWindowImplBase<>::CreateSimpleToolBarCtrl(hWndParent, nResourceID, bInitialSeparator, dwStyle, nID);
}
#endif
#ifndef _WIN32_WCE
#ifndef _WTL_MDIWINDOWMENU_TEXT
#define _WTL_MDIWINDOWMENU_TEXT _T("&Window")
#endif
class CMDIWindow : public ATL::CWindow
{
public:
HWND m_hWndMDIClient;
HMENU m_hMenu;
CMDIWindow(HWND hWnd = NULL) : ATL::CWindow(hWnd), m_hWndMDIClient(NULL), m_hMenu(NULL)
{ }
CMDIWindow& operator =(HWND hWnd)
{
m_hWnd = hWnd;
return *this;
}
HWND MDIGetActive(BOOL* lpbMaximized = NULL)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
return (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, (LPARAM)lpbMaximized);
}
void MDIActivate(HWND hWndChildToActivate)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
ATLASSERT(::IsWindow(hWndChildToActivate));
::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM)hWndChildToActivate, 0);
}
void MDINext(HWND hWndChild, BOOL bPrevious = FALSE)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
ATLASSERT(hWndChild == NULL || ::IsWindow(hWndChild));
::SendMessage(m_hWndMDIClient, WM_MDINEXT, (WPARAM)hWndChild, (LPARAM)bPrevious);
}
void MDIMaximize(HWND hWndChildToMaximize)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
ATLASSERT(::IsWindow(hWndChildToMaximize));
::SendMessage(m_hWndMDIClient, WM_MDIMAXIMIZE, (WPARAM)hWndChildToMaximize, 0);
}
void MDIRestore(HWND hWndChildToRestore)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
ATLASSERT(::IsWindow(hWndChildToRestore));
::SendMessage(m_hWndMDIClient, WM_MDIRESTORE, (WPARAM)hWndChildToRestore, 0);
}
void MDIDestroy(HWND hWndChildToDestroy)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
ATLASSERT(::IsWindow(hWndChildToDestroy));
::SendMessage(m_hWndMDIClient, WM_MDIDESTROY, (WPARAM)hWndChildToDestroy, 0);
}
BOOL MDICascade(UINT uFlags = 0)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDICASCADE, (WPARAM)uFlags, 0);
}
BOOL MDITile(UINT uFlags = MDITILE_HORIZONTAL)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
return (BOOL)::SendMessage(m_hWndMDIClient, WM_MDITILE, (WPARAM)uFlags, 0);
}
void MDIIconArrange()
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
::SendMessage(m_hWndMDIClient, WM_MDIICONARRANGE, 0, 0);
}
HMENU MDISetMenu(HMENU hMenuFrame, HMENU hMenuWindow)
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuFrame, (LPARAM)hMenuWindow);
}
HMENU MDIRefreshMenu()
{
ATLASSERT(::IsWindow(m_hWndMDIClient));
return (HMENU)::SendMessage(m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
}
static HMENU GetStandardWindowMenu(HMENU hMenu)
{
int nCount = ::GetMenuItemCount(hMenu);
if(nCount == -1)
return NULL;
int nLen = ::GetMenuString(hMenu, nCount - 2, NULL, 0, MF_BYPOSITION);
if(nLen == 0)
return NULL;
CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff;
LPTSTR lpszText = buff.Allocate(nLen + 1);
if(lpszText == NULL)
return NULL;
if(::GetMenuString(hMenu, nCount - 2, lpszText, nLen + 1, MF_BYPOSITION) != nLen)
return NULL;
if(lstrcmp(lpszText, _WTL_MDIWINDOWMENU_TEXT) != 0)
return NULL;
return ::GetSubMenu(hMenu, nCount - 2);
}
void SetMDIFrameMenu()
{
HMENU hWindowMenu = GetStandardWindowMenu(m_hMenu);
MDISetMenu(m_hMenu, hWindowMenu);
MDIRefreshMenu();
::DrawMenuBar(GetMDIFrame());
}
HWND GetMDIFrame() const
{
return ::GetParent(m_hWndMDIClient);
}
};
#endif
#ifndef _WIN32_WCE
#define CHAIN_MDI_CHILD_COMMANDS() \
if(uMsg == WM_COMMAND) \
{ \
HWND hWndChild = MDIGetActive(); \
if(hWndChild != NULL) \
::SendMessage(hWndChild, uMsg, wParam, lParam); \
}
template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CFrameWinTraits>
class ATL_NO_VTABLE CMDIFrameWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
{
public:
HWND Create(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
HMENU hMenu = NULL, LPVOID lpCreateParam = NULL)
{
m_hMenu = hMenu;
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
dwStyle = T::GetWndStyle(dwStyle);
dwExStyle = T::GetWndExStyle(dwExStyle);
if(rect.m_lpRect == NULL)
rect.m_lpRect = &TBase::rcDefault;
return CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, hMenu, atom, lpCreateParam);
}
HWND CreateEx(HWND hWndParent = NULL, ATL::_U_RECT rect = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
{
const int cchName = 256;
TCHAR szWindowName[cchName];
szWindowName[0] = 0;
::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
HMENU hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
T* pT = static_cast<T*>(this);
HWND hWnd = pT->Create(hWndParent, rect, szWindowName, dwStyle, dwExStyle, hMenu, lpCreateParam);
if(hWnd != NULL)
m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
return hWnd;
}
BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
ATLASSERT(!::IsWindow(m_hWndToolBar));
if(nResourceID == 0)
nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
return (m_hWndToolBar != NULL);
}
virtual WNDPROC GetWindowProc()
{
return MDIFrameWindowProc;
}
static LRESULT CALLBACK MDIFrameWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
CMDIFrameWindowImpl< T, TBase, TWinTraits >* pThis = (CMDIFrameWindowImpl< T, TBase, TWinTraits >*)hWnd;
#if (_ATL_VER >= 0x0700)
ATL::_ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam);
const ATL::_ATL_MSG* pOldMsg = pThis->m_pCurrentMsg;
#else
MSG msg = { pThis->m_hWnd, uMsg, wParam, lParam, 0, { 0, 0 } };
const MSG* pOldMsg = pThis->m_pCurrentMsg;
#endif
pThis->m_pCurrentMsg = &msg;
LRESULT lRes = 0;
BOOL bRet = pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
ATLASSERT(pThis->m_pCurrentMsg == &msg);
pThis->m_pCurrentMsg = pOldMsg;
if(!bRet)
{
if(uMsg != WM_NCDESTROY)
lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
else
{
LONG_PTR pfnWndProc = ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC);
lRes = pThis->DefWindowProc(uMsg, wParam, lParam);
if(pThis->m_pfnSuperWindowProc != ::DefWindowProc && ::GetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC) == pfnWndProc)
::SetWindowLongPtr(pThis->m_hWnd, GWLP_WNDPROC, (LONG_PTR)pThis->m_pfnSuperWindowProc);
#if (_ATL_VER >= 0x0700)
pThis->m_dwState |= WINSTATE_DESTROYED;
#else
HWND hWnd = pThis->m_hWnd;
pThis->m_hWnd = NULL;
pThis->OnFinalMessage(hWnd);
#endif
}
}
#if (_ATL_VER >= 0x0700)
if(pThis->m_dwState & WINSTATE_DESTROYED && pThis->m_pCurrentMsg == NULL)
{
HWND hWnd = pThis->m_hWnd;
pThis->m_hWnd = NULL;
pThis->m_dwState &= ~WINSTATE_DESTROYED;
pThis->OnFinalMessage(hWnd);
}
#endif
return lRes;
}
LRESULT DefWindowProc()
{
const MSG* pMsg = m_pCurrentMsg;
LRESULT lRes = 0;
if (pMsg != NULL)
lRes = DefWindowProc(pMsg->message, pMsg->wParam, pMsg->lParam);
return lRes;
}
LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
return ::DefFrameProc(m_hWnd, m_hWndMDIClient, uMsg, wParam, lParam);
}
BOOL PreTranslateMessage(MSG* pMsg)
{
if(CFrameWindowImplBase<TBase, TWinTraits>::PreTranslateMessage(pMsg))
return TRUE;
return ::TranslateMDISysAccel(m_hWndMDIClient, pMsg);
}
HWND CreateMDIClient(HMENU hWindowMenu = NULL, UINT nID = ATL_IDW_CLIENT, UINT nFirstChildID = ATL_IDM_FIRST_MDICHILD)
{
DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;
DWORD dwExStyle = WS_EX_CLIENTEDGE;
CLIENTCREATESTRUCT ccs = { 0 };
ccs.hWindowMenu = hWindowMenu;
ccs.idFirstChild = nFirstChildID;
if((GetStyle() & (WS_HSCROLL | WS_VSCROLL)) != 0)
{
dwStyle |= (GetStyle() & (WS_HSCROLL | WS_VSCROLL));
ModifyStyle(WS_HSCROLL | WS_VSCROLL, 0, SWP_NOREDRAW | SWP_FRAMECHANGED);
}
m_hWndClient = ::CreateWindowEx(dwExStyle, _T("MDIClient"), NULL,
dwStyle, 0, 0, 1, 1, m_hWnd, (HMENU)LongToHandle(nID),
ModuleHelper::GetModuleInstance(), (LPVOID)&ccs);
if (m_hWndClient == NULL)
{
ATLTRACE2(atlTraceUI, 0, _T("MDI Frame failed to create MDICLIENT.\n"));
return NULL;
}
::BringWindowToTop(m_hWndClient);
m_hWndMDIClient = m_hWndClient;
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
return m_hWndClient;
}
typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass;
BEGIN_MSG_MAP(CMDIFrameWindowImpl)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_MDISETMENU, OnMDISetMenu)
#ifndef _ATL_NO_REBAR_SUPPORT
#if (_WIN32_IE >= 0x0400)
NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
#endif
#if (_WIN32_IE >= 0x0500)
NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
#endif
#endif
CHAIN_MSG_MAP(_baseClass)
END_MSG_MAP()
LRESULT OnSize(UINT , WPARAM wParam, LPARAM , BOOL& )
{
if(wParam != SIZE_MINIMIZED)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
return 0;
}
LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
{
return DefWindowProc(uMsg, wParam, lParam);
}
LRESULT OnMDISetMenu(UINT , WPARAM , LPARAM , BOOL& )
{
SetMDIFrameMenu();
return 0;
}
#ifndef _ATL_NO_REBAR_SUPPORT
#if (_WIN32_IE >= 0x0400)
LRESULT OnReBarAutoSize(int , LPNMHDR , BOOL& )
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout(FALSE);
return 0;
}
#endif
#if (_WIN32_IE >= 0x0500)
LRESULT OnChevronPushed(int , LPNMHDR pnmh, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
_ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
if(!pT->PrepareChevronMenu(cmi))
{
bHandled = FALSE;
return 1;
}
pT->DisplayChevronMenu(cmi);
pT->CleanupChevronMenu(cmi);
return 0;
}
#endif
#endif
};
#endif
#ifndef _WIN32_WCE
template <class T, class TBase = CMDIWindow, class TWinTraits = ATL::CMDIChildWinTraits>
class ATL_NO_VTABLE CMDIChildWindowImpl : public CFrameWindowImplBase<TBase, TWinTraits >
{
public:
HWND Create(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
DWORD dwStyle = 0, DWORD dwExStyle = 0,
UINT nMenuID = 0, LPVOID lpCreateParam = NULL)
{
ATOM atom = T::GetWndClassInfo().Register(&m_pfnSuperWindowProc);
if(nMenuID != 0)
m_hMenu = ::LoadMenu(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(nMenuID));
dwStyle = T::GetWndStyle(dwStyle);
dwExStyle = T::GetWndExStyle(dwExStyle);
dwExStyle |= WS_EX_MDICHILD;
m_pfnSuperWindowProc = ::DefMDIChildProc;
m_hWndMDIClient = hWndParent;
ATLASSERT(::IsWindow(m_hWndMDIClient));
if(rect.m_lpRect == NULL)
rect.m_lpRect = &TBase::rcDefault;
ATL::CWindow wndParent = hWndParent;
BOOL bMaximized = FALSE;
wndParent.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
if(bMaximized)
wndParent.SetRedraw(FALSE);
HWND hWnd = CFrameWindowImplBase<TBase, TWinTraits >::Create(hWndParent, rect.m_lpRect, szWindowName, dwStyle, dwExStyle, (UINT)0U, atom, lpCreateParam);
if(bMaximized)
{
if(hWnd != NULL)
MDIMaximize(hWnd);
wndParent.SetRedraw(TRUE);
wndParent.RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);
::SetFocus(GetMDIFrame());
}
else if(hWnd != NULL && ::IsWindowVisible(m_hWnd) && !::IsChild(hWnd, ::GetFocus()))
{
::SetFocus(hWnd);
}
return hWnd;
}
HWND CreateEx(HWND hWndParent, ATL::_U_RECT rect = NULL, LPCTSTR lpcstrWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, LPVOID lpCreateParam = NULL)
{
const int cchName = 256;
TCHAR szWindowName[cchName];
szWindowName[0] = 0;
if(lpcstrWindowName == NULL)
{
::LoadString(ModuleHelper::GetResourceInstance(), T::GetWndClassInfo().m_uCommonResourceID, szWindowName, cchName);
lpcstrWindowName = szWindowName;
}
T* pT = static_cast<T*>(this);
HWND hWnd = pT->Create(hWndParent, rect, lpcstrWindowName, dwStyle, dwExStyle, T::GetWndClassInfo().m_uCommonResourceID, lpCreateParam);
if(hWnd != NULL)
m_hAccel = ::LoadAccelerators(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE(T::GetWndClassInfo().m_uCommonResourceID));
return hWnd;
}
BOOL CreateSimpleToolBar(UINT nResourceID = 0, DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
ATLASSERT(!::IsWindow(m_hWndToolBar));
if(nResourceID == 0)
nResourceID = T::GetWndClassInfo().m_uCommonResourceID;
m_hWndToolBar = T::CreateSimpleToolBarCtrl(m_hWnd, nResourceID, TRUE, dwStyle, nID);
return (m_hWndToolBar != NULL);
}
BOOL UpdateClientEdge(LPRECT lpRect = NULL)
{
HWND hWndChild = MDIGetActive();
if(hWndChild != NULL && hWndChild != m_hWnd)
return FALSE;
DWORD dwStyle = ::GetWindowLong(m_hWndMDIClient, GWL_EXSTYLE);
DWORD dwNewStyle = dwStyle;
if(hWndChild != NULL && ((GetExStyle() & WS_EX_CLIENTEDGE) == 0) && ((GetStyle() & WS_MAXIMIZE) != 0))
dwNewStyle &= ~(WS_EX_CLIENTEDGE);
else
dwNewStyle |= WS_EX_CLIENTEDGE;
if(dwStyle != dwNewStyle)
{
::RedrawWindow(m_hWndMDIClient, NULL, NULL,
RDW_INVALIDATE | RDW_ALLCHILDREN);
::SetWindowLong(m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
::SetWindowPos(m_hWndMDIClient, NULL, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
SWP_NOZORDER | SWP_NOCOPYBITS);
if (lpRect != NULL)
::GetClientRect(m_hWndMDIClient, lpRect);
return TRUE;
}
return FALSE;
}
typedef CFrameWindowImplBase<TBase, TWinTraits > _baseClass;
BEGIN_MSG_MAP(CMDIChildWindowImpl)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
MESSAGE_HANDLER(WM_MDIACTIVATE, OnMDIActivate)
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
#ifndef _ATL_NO_REBAR_SUPPORT
#if (_WIN32_IE >= 0x0400)
NOTIFY_CODE_HANDLER(RBN_AUTOSIZE, OnReBarAutoSize)
#endif
#if (_WIN32_IE >= 0x0500)
NOTIFY_CODE_HANDLER(RBN_CHEVRONPUSHED, OnChevronPushed)
#endif
#endif
CHAIN_MSG_MAP(_baseClass)
END_MSG_MAP()
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
{
DefWindowProc(uMsg, wParam, lParam);
if(wParam != SIZE_MINIMIZED)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
return 0;
}
LRESULT OnWindowPosChanged(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
{
LPWINDOWPOS lpWndPos = (LPWINDOWPOS)lParam;
if(!(lpWndPos->flags & SWP_NOSIZE))
{
RECT rectClient;
if(UpdateClientEdge(&rectClient) && ((GetStyle() & WS_MAXIMIZE) != 0))
{
::AdjustWindowRectEx(&rectClient, GetStyle(), FALSE, GetExStyle());
lpWndPos->x = rectClient.left;
lpWndPos->y = rectClient.top;
lpWndPos->cx = rectClient.right - rectClient.left;
lpWndPos->cy = rectClient.bottom - rectClient.top;
}
}
bHandled = FALSE;
return 1;
}
LRESULT OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
{
LRESULT lRes = DefWindowProc(uMsg, wParam, lParam);
if(lRes == MA_ACTIVATE || lRes == MA_ACTIVATEANDEAT)
{
if(MDIGetActive() != m_hWnd)
MDIActivate(m_hWnd);
}
return lRes;
}
LRESULT OnMenuSelect(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& )
{
return ::SendMessage(GetMDIFrame(), uMsg, wParam, lParam);
}
LRESULT OnMDIActivate(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
{
if((HWND)lParam == m_hWnd && m_hMenu != NULL)
SetMDIFrameMenu();
else if((HWND)lParam == NULL)
::SendMessage(GetMDIFrame(), WM_MDISETMENU, 0, 0);
bHandled = FALSE;
return 1;
}
LRESULT OnDestroy(UINT , WPARAM , LPARAM , BOOL& bHandled)
{
if(m_hMenu != NULL)
{
::DestroyMenu(m_hMenu);
m_hMenu = NULL;
}
UpdateClientEdge();
bHandled = FALSE;
return 1;
}
#ifndef _ATL_NO_REBAR_SUPPORT
#if (_WIN32_IE >= 0x0400)
LRESULT OnReBarAutoSize(int , LPNMHDR , BOOL& )
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout(FALSE);
return 0;
}
#endif
#if (_WIN32_IE >= 0x0500)
LRESULT OnChevronPushed(int , LPNMHDR pnmh, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
_ChevronMenuInfo cmi = { NULL, (LPNMREBARCHEVRON)pnmh, false };
if(!pT->PrepareChevronMenu(cmi))
{
bHandled = FALSE;
return 1;
}
pT->DisplayChevronMenu(cmi);
pT->CleanupChevronMenu(cmi);
return 0;
}
#endif
#endif
};
#endif
template <class T>
class COwnerDraw
{
public:
#if (_ATL_VER < 0x0700)
BOOL m_bHandledOD;
BOOL IsMsgHandled() const
{
return m_bHandledOD;
}
void SetMsgHandled(BOOL bHandled)
{
m_bHandledOD = bHandled;
}
#endif
BEGIN_MSG_MAP(COwnerDraw< T >)
MESSAGE_HANDLER(WM_DRAWITEM, OnDrawItem)
MESSAGE_HANDLER(WM_MEASUREITEM, OnMeasureItem)
MESSAGE_HANDLER(WM_COMPAREITEM, OnCompareItem)
MESSAGE_HANDLER(WM_DELETEITEM, OnDeleteItem)
ALT_MSG_MAP(1)
MESSAGE_HANDLER(OCM_DRAWITEM, OnDrawItem)
MESSAGE_HANDLER(OCM_MEASUREITEM, OnMeasureItem)
MESSAGE_HANDLER(OCM_COMPAREITEM, OnCompareItem)
MESSAGE_HANDLER(OCM_DELETEITEM, OnDeleteItem)
END_MSG_MAP()
LRESULT OnDrawItem(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->SetMsgHandled(TRUE);
pT->DrawItem((LPDRAWITEMSTRUCT)lParam);
bHandled = pT->IsMsgHandled();
return (LRESULT)TRUE;
}
LRESULT OnMeasureItem(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->SetMsgHandled(TRUE);
pT->MeasureItem((LPMEASUREITEMSTRUCT)lParam);
bHandled = pT->IsMsgHandled();
return (LRESULT)TRUE;
}
LRESULT OnCompareItem(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->SetMsgHandled(TRUE);
bHandled = pT->IsMsgHandled();
return (LRESULT)pT->CompareItem((LPCOMPAREITEMSTRUCT)lParam);
}
LRESULT OnDeleteItem(UINT , WPARAM , LPARAM lParam, BOOL& bHandled)
{
T* pT = static_cast<T*>(this);
pT->SetMsgHandled(TRUE);
pT->DeleteItem((LPDELETEITEMSTRUCT)lParam);
bHandled = pT->IsMsgHandled();
return (LRESULT)TRUE;
}
void DrawItem(LPDRAWITEMSTRUCT )
{
ATLASSERT(FALSE);
}
void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
if(lpMeasureItemStruct->CtlType != ODT_MENU)
{
T* pT = static_cast<T*>(this);
HWND hWnd = pT->GetDlgItem(lpMeasureItemStruct->CtlID);
CClientDC dc(hWnd);
TEXTMETRIC tm = { 0 };
dc.GetTextMetrics(&tm);
lpMeasureItemStruct->itemHeight = tm.tmHeight;
}
else
lpMeasureItemStruct->itemHeight = ::GetSystemMetrics(SM_CYMENU);
}
int CompareItem(LPCOMPAREITEMSTRUCT )
{
return 0;
}
void DeleteItem(LPDELETEITEMSTRUCT )
{
}
};
#define BEGIN_UPDATE_UI_MAP(thisClass) \
static const CUpdateUIBase::_AtlUpdateUIMap* GetUpdateUIMap() \
{ \
static const _AtlUpdateUIMap theMap[] = \
{
#define UPDATE_ELEMENT(nID, wType) \
{ nID, wType },
#define END_UPDATE_UI_MAP() \
{ (WORD)-1, 0 } \
}; \
return theMap; \
}
class CUpdateUIBase
{
public:
enum
{
UPDUI_MENUPOPUP = 0x0001,
UPDUI_MENUBAR = 0x0002,
UPDUI_CHILDWINDOW = 0x0004,
UPDUI_TOOLBAR = 0x0008,
UPDUI_STATUSBAR = 0x0010,
UPDUI_ENABLED = 0x0000,
UPDUI_DISABLED = 0x0100,
UPDUI_CHECKED = 0x0200,
UPDUI_CHECKED2 = 0x0400,
UPDUI_RADIO = 0x0800,
UPDUI_DEFAULT = 0x1000,
UPDUI_TEXT = 0x2000,
UPDUI_CLEARDEFAULT = 0x4000,
};
struct _AtlUpdateUIElement
{
HWND m_hWnd;
WORD m_wType;
bool operator ==(const _AtlUpdateUIElement& e) const
{ return (m_hWnd == e.m_hWnd && m_wType == e.m_wType); }
};
struct _AtlUpdateUIMap
{
WORD m_nID;
WORD m_wType;
bool operator ==(const _AtlUpdateUIMap& e) const
{ return (m_nID == e.m_nID && m_wType == e.m_wType); }
};
struct _AtlUpdateUIData
{
WORD m_wState;
union
{
void* m_lpData;
LPTSTR m_lpstrText;
};
bool operator ==(const _AtlUpdateUIData& e) const
{ return (m_wState == e.m_wState && m_lpData == e.m_lpData); }
};
ATL::CSimpleArray<_AtlUpdateUIElement> m_UIElements;
const _AtlUpdateUIMap* m_pUIMap;
_AtlUpdateUIData* m_pUIData;
WORD m_wDirtyType;
bool m_bBlockAccelerators;
CUpdateUIBase() : m_pUIMap(NULL), m_pUIData(NULL), m_wDirtyType(0), m_bBlockAccelerators(false)
{ }
~CUpdateUIBase()
{
if(m_pUIMap != NULL && m_pUIData != NULL)
{
const _AtlUpdateUIMap* pUIMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
while(pUIMap->m_nID != (WORD)-1)
{
if(pUIData->m_wState & UPDUI_TEXT)
delete [] pUIData->m_lpstrText;
pUIMap++;
pUIData++;
}
delete [] m_pUIData;
}
}
bool UIGetBlockAccelerators() const
{
return m_bBlockAccelerators;
}
bool UISetBlockAccelerators(bool bBlock)
{
bool bOld = m_bBlockAccelerators;
m_bBlockAccelerators = bBlock;
return bOld;
}
BOOL UIAddMenuBar(HWND hWnd)
{
if(hWnd == NULL)
return FALSE;
_AtlUpdateUIElement e;
e.m_hWnd = hWnd;
e.m_wType = UPDUI_MENUBAR;
return m_UIElements.Add(e);
}
BOOL UIAddToolBar(HWND hWnd)
{
if(hWnd == NULL)
return FALSE;
_AtlUpdateUIElement e;
e.m_hWnd = hWnd;
e.m_wType = UPDUI_TOOLBAR;
return m_UIElements.Add(e);
}
BOOL UIAddStatusBar(HWND hWnd)
{
if(hWnd == NULL)
return FALSE;
_AtlUpdateUIElement e;
e.m_hWnd = hWnd;
e.m_wType = UPDUI_STATUSBAR;
return m_UIElements.Add(e);
}
BOOL UIAddChildWindowContainer(HWND hWnd)
{
if(hWnd == NULL)
return FALSE;
_AtlUpdateUIElement e;
e.m_hWnd = hWnd;
e.m_wType = UPDUI_CHILDWINDOW;
return m_UIElements.Add(e);
}
BEGIN_MSG_MAP(CUpdateUIBase)
MESSAGE_HANDLER(WM_INITMENUPOPUP, OnInitMenuPopup)
MESSAGE_HANDLER(WM_COMMAND, OnCommand)
END_MSG_MAP()
LRESULT OnInitMenuPopup(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
{
bHandled = FALSE;
HMENU hMenu = (HMENU)wParam;
if(hMenu == NULL)
return 1;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return 1;
const _AtlUpdateUIMap* pMap = m_pUIMap;
while(pMap->m_nID != (WORD)-1)
{
if(pMap->m_wType & UPDUI_MENUPOPUP)
UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
pMap++;
pUIData++;
}
return 0;
}
LRESULT OnCommand(UINT , WPARAM wParam, LPARAM , BOOL& bHandled)
{
bHandled = FALSE;
if(m_bBlockAccelerators && HIWORD(wParam) == 1)
{
int nID = LOWORD(wParam);
if((UIGetState(nID) & UPDUI_DISABLED) == UPDUI_DISABLED)
{
ATLTRACE2(atlTraceUI, 0, _T("CUpdateUIBase::OnCommand - blocked disabled command 0x%4.4X\n"), nID);
bHandled = TRUE;
}
}
return 0;
}
BOOL UIEnable(int nID, BOOL bEnable, BOOL bForceUpdate = FALSE)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
{
if(bEnable)
{
if(pUIData->m_wState & UPDUI_DISABLED)
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState &= ~UPDUI_DISABLED;
}
}
else
{
if(!(pUIData->m_wState & UPDUI_DISABLED))
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState |= UPDUI_DISABLED;
}
}
if(bForceUpdate)
pUIData->m_wState |= pMap->m_wType;
if(pUIData->m_wState & pMap->m_wType)
m_wDirtyType |= pMap->m_wType;
break;
}
}
return TRUE;
}
BOOL UISetCheck(int nID, int nCheck, BOOL bForceUpdate = FALSE)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
{
switch(nCheck)
{
case 0:
if((pUIData->m_wState & UPDUI_CHECKED) || (pUIData->m_wState & UPDUI_CHECKED2))
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState &= ~(UPDUI_CHECKED | UPDUI_CHECKED2);
}
break;
case 1:
if(!(pUIData->m_wState & UPDUI_CHECKED))
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState &= ~UPDUI_CHECKED2;
pUIData->m_wState |= UPDUI_CHECKED;
}
break;
case 2:
if(!(pUIData->m_wState & UPDUI_CHECKED2))
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState &= ~UPDUI_CHECKED;
pUIData->m_wState |= UPDUI_CHECKED2;
}
break;
}
if(bForceUpdate)
pUIData->m_wState |= pMap->m_wType;
if(pUIData->m_wState & pMap->m_wType)
m_wDirtyType |= pMap->m_wType;
break;
}
}
return TRUE;
}
BOOL UISetCheck(int nID, bool bCheck, BOOL bForceUpdate = FALSE)
{
return UISetCheck(nID, bCheck ? 1 : 0, bForceUpdate);
}
BOOL UISetRadio(int nID, BOOL bRadio, BOOL bForceUpdate = FALSE)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
{
if(bRadio)
{
if(!(pUIData->m_wState & UPDUI_RADIO))
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState |= UPDUI_RADIO;
}
}
else
{
if(pUIData->m_wState & UPDUI_RADIO)
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState &= ~UPDUI_RADIO;
}
}
if(bForceUpdate)
pUIData->m_wState |= pMap->m_wType;
if(pUIData->m_wState & pMap->m_wType)
m_wDirtyType |= pMap->m_wType;
break;
}
}
return TRUE;
}
BOOL UISetText(int nID, LPCTSTR lpstrText, BOOL bForceUpdate = FALSE)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
if(lpstrText == NULL)
lpstrText = _T("");
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
{
if(pUIData->m_lpstrText == NULL || lstrcmp(pUIData->m_lpstrText, lpstrText))
{
delete [] pUIData->m_lpstrText;
pUIData->m_lpstrText = NULL;
int nStrLen = lstrlen(lpstrText);
ATLTRY(pUIData->m_lpstrText = new TCHAR[nStrLen + 1]);
if(pUIData->m_lpstrText == NULL)
{
ATLTRACE2(atlTraceUI, 0, _T("UISetText - memory allocation failed\n"));
break;
}
SecureHelper::strcpy_x(pUIData->m_lpstrText, nStrLen + 1, lpstrText);
pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
}
if(bForceUpdate)
pUIData->m_wState |= (UPDUI_TEXT | pMap->m_wType);
if(pUIData->m_wState & pMap->m_wType)
m_wDirtyType |= pMap->m_wType;
break;
}
}
return TRUE;
}
BOOL UISetDefault(int nID, BOOL bDefault, BOOL bForceUpdate = FALSE)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
{
if(bDefault)
{
if((pUIData->m_wState & UPDUI_DEFAULT) == 0)
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState |= UPDUI_DEFAULT;
}
}
else
{
if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
{
pUIData->m_wState |= pMap->m_wType;
pUIData->m_wState &= ~UPDUI_DEFAULT;
pUIData->m_wState |= UPDUI_CLEARDEFAULT;
}
}
if(bForceUpdate)
pUIData->m_wState |= pMap->m_wType;
if(pUIData->m_wState & pMap->m_wType)
m_wDirtyType |= pMap->m_wType;
break;
}
}
return TRUE;
}
BOOL UISetState(int nID, DWORD dwState)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
{
pUIData->m_wState = (WORD)(dwState | pMap->m_wType);
m_wDirtyType |= pMap->m_wType;
break;
}
}
return TRUE;
}
DWORD UIGetState(int nID)
{
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return 0;
for( ; pMap->m_nID != (WORD)-1; pMap++, pUIData++)
{
if(nID == (int)pMap->m_nID)
return pUIData->m_wState;
}
return 0;
}
#ifndef _WIN32_WCE
BOOL UIUpdateMenuBar(BOOL bForceUpdate = FALSE, BOOL bMainMenu = FALSE)
{
if(!(m_wDirtyType & UPDUI_MENUBAR) && !bForceUpdate)
return TRUE;
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
while(pMap->m_nID != (WORD)-1)
{
for(int i = 0; i < m_UIElements.GetSize(); i++)
{
if(m_UIElements[i].m_wType == UPDUI_MENUBAR)
{
HMENU hMenu = ::GetMenu(m_UIElements[i].m_hWnd);
if(hMenu != NULL && (pUIData->m_wState & UPDUI_MENUBAR) && (pMap->m_wType & UPDUI_MENUBAR))
UIUpdateMenuBarElement(pMap->m_nID, pUIData, hMenu);
}
if(bMainMenu)
::DrawMenuBar(m_UIElements[i].m_hWnd);
}
pMap++;
pUIData->m_wState &= ~UPDUI_MENUBAR;
if(pUIData->m_wState & UPDUI_TEXT)
{
delete [] pUIData->m_lpstrText;
pUIData->m_lpstrText = NULL;
pUIData->m_wState &= ~UPDUI_TEXT;
}
pUIData++;
}
m_wDirtyType &= ~UPDUI_MENUBAR;
return TRUE;
}
#endif
BOOL UIUpdateToolBar(BOOL bForceUpdate = FALSE)
{
if(!(m_wDirtyType & UPDUI_TOOLBAR) && !bForceUpdate)
return TRUE;
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
while(pMap->m_nID != (WORD)-1)
{
for(int i = 0; i < m_UIElements.GetSize(); i++)
{
if(m_UIElements[i].m_wType == UPDUI_TOOLBAR)
{
if((pUIData->m_wState & UPDUI_TOOLBAR) && (pMap->m_wType & UPDUI_TOOLBAR))
UIUpdateToolBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
}
}
pMap++;
pUIData->m_wState &= ~UPDUI_TOOLBAR;
pUIData++;
}
m_wDirtyType &= ~UPDUI_TOOLBAR;
return TRUE;
}
BOOL UIUpdateStatusBar(BOOL bForceUpdate = FALSE)
{
if(!(m_wDirtyType & UPDUI_STATUSBAR) && !bForceUpdate)
return TRUE;
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
while(pMap->m_nID != (WORD)-1)
{
for(int i = 0; i < m_UIElements.GetSize(); i++)
{
if(m_UIElements[i].m_wType == UPDUI_STATUSBAR)
{
if((pUIData->m_wState & UPDUI_STATUSBAR) && (pMap->m_wType & UPDUI_STATUSBAR))
UIUpdateStatusBarElement(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
}
}
pMap++;
pUIData->m_wState &= ~UPDUI_STATUSBAR;
if(pUIData->m_wState & UPDUI_TEXT)
{
delete [] pUIData->m_lpstrText;
pUIData->m_lpstrText = NULL;
pUIData->m_wState &= ~UPDUI_TEXT;
}
pUIData++;
}
m_wDirtyType &= ~UPDUI_STATUSBAR;
return TRUE;
}
BOOL UIUpdateChildWindows(BOOL bForceUpdate = FALSE)
{
if(!(m_wDirtyType & UPDUI_CHILDWINDOW) && !bForceUpdate)
return TRUE;
const _AtlUpdateUIMap* pMap = m_pUIMap;
_AtlUpdateUIData* pUIData = m_pUIData;
if(pUIData == NULL)
return FALSE;
while(pMap->m_nID != (WORD)-1)
{
for(int i = 0; i < m_UIElements.GetSize(); i++)
{
if(m_UIElements[i].m_wType == UPDUI_CHILDWINDOW)
{
if((pUIData->m_wState & UPDUI_CHILDWINDOW) && (pMap->m_wType & UPDUI_CHILDWINDOW))
UIUpdateChildWindow(pMap->m_nID, pUIData, m_UIElements[i].m_hWnd);
}
}
pMap++;
pUIData->m_wState &= ~UPDUI_CHILDWINDOW;
if(pUIData->m_wState & UPDUI_TEXT)
{
delete [] pUIData->m_lpstrText;
pUIData->m_lpstrText = NULL;
pUIData->m_wState &= ~UPDUI_TEXT;
}
pUIData++;
}
m_wDirtyType &= ~UPDUI_CHILDWINDOW;
return TRUE;
}
static void UIUpdateMenuBarElement(int nID, _AtlUpdateUIData* pUIData, HMENU hMenu)
{
#ifndef _WIN32_WCE
if((pUIData->m_wState & UPDUI_CLEARDEFAULT) != 0)
{
::SetMenuDefaultItem(hMenu, (UINT)-1, 0);
pUIData->m_wState &= ~UPDUI_CLEARDEFAULT;
}
#endif
CMenuItemInfo mii;
mii.fMask = MIIM_STATE;
mii.wID = nID;
#ifndef _WIN32_WCE
if((pUIData->m_wState & UPDUI_DISABLED) != 0)
mii.fState |= MFS_DISABLED | MFS_GRAYED;
else
mii.fState |= MFS_ENABLED;
if((pUIData->m_wState & UPDUI_CHECKED) != 0)
mii.fState |= MFS_CHECKED;
else
mii.fState |= MFS_UNCHECKED;
if((pUIData->m_wState & UPDUI_DEFAULT) != 0)
mii.fState |= MFS_DEFAULT;
#else
UINT uEnable = MF_BYCOMMAND;
if((pUIData->m_wState & UPDUI_DISABLED) != 0)
uEnable |= MF_GRAYED;
else
uEnable |= MF_ENABLED;
::EnableMenuItem(hMenu, nID, uEnable);
UINT uCheck = MF_BYCOMMAND;
if((pUIData->m_wState & UPDUI_CHECKED) != 0)
uCheck |= MF_CHECKED;
else
uCheck |= MF_UNCHECKED;
::CheckMenuItem(hMenu, nID, uCheck);
#endif
if((pUIData->m_wState & UPDUI_TEXT) != 0)
{
CMenuItemInfo miiNow;
miiNow.fMask = MIIM_TYPE;
miiNow.wID = nID;
if(::GetMenuItemInfo(hMenu, nID, FALSE, &miiNow))
{
mii.fMask |= MIIM_TYPE;
#ifndef _WIN32_WCE
mii.fType |= (miiNow.fType & ~(MFT_BITMAP | MFT_SEPARATOR)) | MFT_STRING;
#else
mii.fType |= (miiNow.fType & ~(MFT_SEPARATOR)) | MFT_STRING;
#endif
mii.dwTypeData = pUIData->m_lpstrText;
}
}
::SetMenuItemInfo(hMenu, nID, FALSE, &mii);
}
static void UIUpdateToolBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndToolBar)
{
::SendMessage(hWndToolBar, TB_ENABLEBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
::SendMessage(hWndToolBar, TB_CHECKBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED) ? TRUE : FALSE);
::SendMessage(hWndToolBar, TB_INDETERMINATE, nID, (LPARAM)(pUIData->m_wState & UPDUI_CHECKED2) ? TRUE : FALSE);
::SendMessage(hWndToolBar, TB_PRESSBUTTON, nID, (LPARAM)(pUIData->m_wState & UPDUI_RADIO) ? TRUE : FALSE);
}
static void UIUpdateStatusBarElement(int nID, _AtlUpdateUIData* pUIData, HWND hWndStatusBar)
{
if(pUIData->m_wState & UPDUI_TEXT)
::SendMessage(hWndStatusBar, SB_SETTEXT, nID, (LPARAM)pUIData->m_lpstrText);
}
static void UIUpdateChildWindow(int nID, _AtlUpdateUIData* pUIData, HWND hWnd)
{
HWND hChild = ::GetDlgItem(hWnd, nID);
::EnableWindow(hChild, (pUIData->m_wState & UPDUI_DISABLED) ? FALSE : TRUE);
int nCheck = BST_UNCHECKED;
if(pUIData->m_wState & UPDUI_CHECKED || pUIData->m_wState & UPDUI_RADIO)
nCheck = BST_CHECKED;
else if(pUIData->m_wState & UPDUI_CHECKED2)
nCheck = BST_INDETERMINATE;
::SendMessage(hChild, BM_SETCHECK, nCheck, 0L);
if(pUIData->m_wState & UPDUI_DEFAULT)
{
DWORD dwRet = (DWORD)::SendMessage(hWnd, DM_GETDEFID, 0, 0L);
if(HIWORD(dwRet) == DC_HASDEFID)
{
HWND hOldDef = ::GetDlgItem(hWnd, (int)(short)LOWORD(dwRet));
::SendMessage(hOldDef, BM_SETSTYLE, BS_PUSHBUTTON, MAKELPARAM(TRUE, 0));
}
::SendMessage(hWnd, DM_SETDEFID, nID, 0L);
}
if(pUIData->m_wState & UPDUI_TEXT)
::SetWindowText(hChild, pUIData->m_lpstrText);
}
};
template <class T>
class CUpdateUI : public CUpdateUIBase
{
public:
CUpdateUI()
{
T* pT = static_cast<T*>(this);
pT;
const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
m_pUIMap = pMap;
ATLASSERT(m_pUIMap != NULL);
int nCount;
for(nCount = 1; pMap->m_nID != (WORD)-1; nCount++)
pMap++;
#ifdef _DEBUG
for(int i = 0; i < nCount; i++)
{
for(int j = 0; j < nCount; j++)
{
if(i != j)
ATLASSERT(m_pUIMap[j].m_nID != m_pUIMap[i].m_nID);
}
}
#endif
ATLTRY(m_pUIData = new _AtlUpdateUIData[nCount]);
ATLASSERT(m_pUIData != NULL);
if(m_pUIData != NULL)
memset(m_pUIData, 0, sizeof(_AtlUpdateUIData) * nCount);
}
};
template <class T>
class CDynamicUpdateUI : public CUpdateUIBase
{
public:
ATL::CSimpleArray<_AtlUpdateUIMap> m_arrUIMap;
ATL::CSimpleArray<_AtlUpdateUIData> m_arrUIData;
CDynamicUpdateUI()
{
T* pT = static_cast<T*>(this);
pT;
const _AtlUpdateUIMap* pMap = pT->GetUpdateUIMap();
ATLASSERT(pMap != NULL);
for(;;)
{
BOOL bRet = m_arrUIMap.Add(*(_AtlUpdateUIMap*)pMap);
ATLASSERT(bRet);
if(bRet != FALSE)
{
_AtlUpdateUIData data = { 0, NULL };
bRet = m_arrUIData.Add(data);
ATLASSERT(bRet);
}
if(pMap->m_nID == (WORD)-1)
break;
pMap++;
}
ATLASSERT(m_arrUIMap.GetSize() == m_arrUIData.GetSize());
#ifdef _DEBUG
for(int i = 0; i < m_arrUIMap.GetSize(); i++)
{
for(int j = 0; j < m_arrUIMap.GetSize(); j++)
{
if(i != j)
ATLASSERT(m_arrUIMap[j].m_nID != m_arrUIMap[i].m_nID);
}
}
#endif
m_pUIMap = m_arrUIMap.m_aT;
m_pUIData = m_arrUIData.m_aT;
}
~CDynamicUpdateUI()
{
for(int i = 0; i < m_arrUIData.GetSize(); i++)
{
if((m_arrUIData[i].m_wState & UPDUI_TEXT) != 0)
delete [] m_arrUIData[i].m_lpstrText;
}
m_pUIMap = NULL;
m_pUIData = NULL;
}
bool UIAddUpdateElement(WORD nID, WORD wType)
{
for(int i = 0; i < m_arrUIMap.GetSize(); i++)
{
ATLASSERT(m_arrUIMap[i].m_nID != nID);
if(m_arrUIMap[i].m_nID == nID)
return false;
}
bool bRetVal = false;
_AtlUpdateUIMap uumEnd = { (WORD)-1, 0 };
BOOL bRet = m_arrUIMap.Add(uumEnd);
ATLASSERT(bRet);
if(bRet != FALSE)
{
_AtlUpdateUIData uud = { 0, NULL };
bRet = m_arrUIData.Add(uud);
ATLASSERT(bRet);
if(bRet != FALSE)
{
int nSize = m_arrUIMap.GetSize();
_AtlUpdateUIMap uum = { nID, wType };
m_arrUIMap.SetAtIndex(nSize - 2, uum);
m_arrUIData.SetAtIndex(nSize - 2, uud);
m_pUIMap = m_arrUIMap.m_aT;
m_pUIData = m_arrUIData.m_aT;
bRetVal = true;
}
}
return bRetVal;
}
bool UIRemoveUpdateElement(WORD nID)
{
bool bRetVal = false;
for(int i = 0; i < m_arrUIMap.GetSize(); i++)
{
if(m_arrUIMap[i].m_nID == nID)
{
BOOL bRet = m_arrUIMap.RemoveAt(i);
ATLASSERT(bRet);
bRet = m_arrUIData.RemoveAt(i);
ATLASSERT(bRet);
bRetVal = true;
break;
}
}
return bRetVal;
}
};
#define BEGIN_DLGRESIZE_MAP(thisClass) \
static const _AtlDlgResizeMap* GetDlgResizeMap() \
{ \
static const _AtlDlgResizeMap theMap[] = \
{
#define END_DLGRESIZE_MAP() \
{ -1, 0 }, \
}; \
return theMap; \
}
#define DLGRESIZE_CONTROL(id, flags) \
{ id, flags },
#define BEGIN_DLGRESIZE_GROUP() \
{ -1, _DLSZ_BEGIN_GROUP },
#define END_DLGRESIZE_GROUP() \
{ -1, _DLSZ_END_GROUP },
template <class T>
class CDialogResize
{
public:
enum
{
DLSZ_SIZE_X = 0x00000001,
DLSZ_SIZE_Y = 0x00000002,
DLSZ_MOVE_X = 0x00000004,
DLSZ_MOVE_Y = 0x00000008,
DLSZ_REPAINT = 0x00000010,
DLSZ_CENTER_X = 0x00000020,
DLSZ_CENTER_Y = 0x00000040,
_DLSZ_BEGIN_GROUP = 0x00001000,
_DLSZ_END_GROUP = 0x00002000,
_DLSZ_GRIPPER = 0x00004000
};
struct _AtlDlgResizeMap
{
int m_nCtlID;
DWORD m_dwResizeFlags;
};
struct _AtlDlgResizeData
{
int m_nCtlID;
DWORD m_dwResizeFlags;
RECT m_rect;
int GetGroupCount() const
{
return (int)LOBYTE(HIWORD(m_dwResizeFlags));
}
void SetGroupCount(int nCount)
{
ATLASSERT(nCount > 0 && nCount < 256);
DWORD dwCount = (DWORD)MAKELONG(0, MAKEWORD(nCount, 0));
m_dwResizeFlags &= 0xFF00FFFF;
m_dwResizeFlags |= dwCount;
}
bool operator ==(const _AtlDlgResizeData& r) const
{ return (m_nCtlID == r.m_nCtlID && m_dwResizeFlags == r.m_dwResizeFlags); }
};
ATL::CSimpleArray<_AtlDlgResizeData> m_arrData;
SIZE m_sizeDialog;
POINT m_ptMinTrackSize;
bool m_bGripper;
CDialogResize() : m_bGripper(false)
{
m_sizeDialog.cx = 0;
m_sizeDialog.cy = 0;
m_ptMinTrackSize.x = -1;
m_ptMinTrackSize.y = -1;
}
void DlgResize_Init(bool bAddGripper = true, bool bUseMinTrackSize = true, DWORD dwForceStyle = WS_CLIPCHILDREN)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
DWORD dwStyle = pT->GetStyle();
#ifdef _DEBUG
if(((dwStyle & WS_CHILD) == 0) && ((dwStyle & WS_THICKFRAME) == 0))
ATLTRACE2(atlTraceUI, 0, _T("DlgResize_Init - warning: top level dialog without the WS_THICKFRAME style - user cannot resize it\n"));
#endif
if((dwStyle & dwForceStyle) != dwForceStyle)
pT->ModifyStyle(0, dwForceStyle);
if((dwStyle & WS_CHILD) == 0)
{
pT->ModifyStyleEx(0, WS_EX_DLGMODALFRAME);
if(pT->GetIcon(FALSE) == NULL)
pT->SetIcon(NULL, FALSE);
}
{
ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
if(wndGripper.IsWindow() && m_arrData.GetSize() > 0 && (m_arrData[0].m_dwResizeFlags & _DLSZ_GRIPPER) != 0)
wndGripper.DestroyWindow();
}
m_arrData.RemoveAll();
m_sizeDialog.cx = 0;
m_sizeDialog.cy = 0;
m_ptMinTrackSize.x = -1;
m_ptMinTrackSize.y = -1;
RECT rectDlg = { 0 };
pT->GetClientRect(&rectDlg);
m_sizeDialog.cx = rectDlg.right;
m_sizeDialog.cy = rectDlg.bottom;
#ifndef _WIN32_WCE
m_bGripper = false;
if(bAddGripper)
{
ATLASSERT(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)));
if(!::IsWindow(pT->GetDlgItem(ATL_IDW_STATUS_BAR)))
{
ATL::CWindow wndGripper;
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);
ATLASSERT(wndGripper.IsWindow());
if(wndGripper.IsWindow())
{
m_bGripper = true;
RECT rectCtl = { 0 };
wndGripper.GetWindowRect(&rectCtl);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
_AtlDlgResizeData data = { ATL_IDW_STATUS_BAR, DLSZ_MOVE_X | DLSZ_MOVE_Y | DLSZ_REPAINT | _DLSZ_GRIPPER, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
m_arrData.Add(data);
}
}
}
#else
bAddGripper;
#endif
if(bUseMinTrackSize)
{
if((dwStyle & WS_CHILD) != 0)
{
RECT rect = { 0 };
pT->GetClientRect(&rect);
m_ptMinTrackSize.x = rect.right - rect.left;
m_ptMinTrackSize.y = rect.bottom - rect.top;
}
else
{
RECT rect = { 0 };
pT->GetWindowRect(&rect);
m_ptMinTrackSize.x = rect.right - rect.left;
m_ptMinTrackSize.y = rect.bottom - rect.top;
}
}
const _AtlDlgResizeMap* pMap = pT->GetDlgResizeMap();
ATLASSERT(pMap != NULL);
int nGroupStart = -1;
for(int nCount = 1; !(pMap->m_nCtlID == -1 && pMap->m_dwResizeFlags == 0); nCount++, pMap++)
{
if(pMap->m_nCtlID == -1)
{
switch(pMap->m_dwResizeFlags)
{
case _DLSZ_BEGIN_GROUP:
ATLASSERT(nGroupStart == -1);
nGroupStart = m_arrData.GetSize();
break;
case _DLSZ_END_GROUP:
{
ATLASSERT(nGroupStart != -1);
int nGroupCount = m_arrData.GetSize() - nGroupStart;
m_arrData[nGroupStart].SetGroupCount(nGroupCount);
nGroupStart = -1;
}
break;
default:
ATLASSERT(FALSE && _T("Invalid DLGRESIZE Map Entry"));
break;
}
}
else
{
ATLASSERT(m_bGripper ? (pMap->m_nCtlID != ATL_IDW_STATUS_BAR) : TRUE);
ATL::CWindow ctl = pT->GetDlgItem(pMap->m_nCtlID);
ATLASSERT(ctl.IsWindow());
RECT rectCtl = { 0 };
ctl.GetWindowRect(&rectCtl);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
DWORD dwGroupFlag = (nGroupStart != -1 && m_arrData.GetSize() == nGroupStart) ? _DLSZ_BEGIN_GROUP : 0;
_AtlDlgResizeData data = { pMap->m_nCtlID, pMap->m_dwResizeFlags | dwGroupFlag, { rectCtl.left, rectCtl.top, rectCtl.right, rectCtl.bottom } };
m_arrData.Add(data);
}
}
ATLASSERT((nGroupStart == -1) && _T("No End Group Entry in the DLGRESIZE Map"));
}
void DlgResize_UpdateLayout(int cxWidth, int cyHeight)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
if(((pT->GetStyle() & WS_CHILD) != 0) && m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
{
if(cxWidth < m_ptMinTrackSize.x)
cxWidth = m_ptMinTrackSize.x;
if(cyHeight < m_ptMinTrackSize.y)
cyHeight = m_ptMinTrackSize.y;
}
BOOL bVisible = pT->IsWindowVisible();
if(bVisible)
pT->SetRedraw(FALSE);
for(int i = 0; i < m_arrData.GetSize(); i++)
{
if((m_arrData[i].m_dwResizeFlags & _DLSZ_BEGIN_GROUP) != 0)
{
int nGroupCount = m_arrData[i].GetGroupCount();
ATLASSERT(nGroupCount > 0 && i + nGroupCount - 1 < m_arrData.GetSize());
RECT rectGroup = m_arrData[i].m_rect;
int j = 1;
for(j = 1; j < nGroupCount; j++)
{
rectGroup.left = __min(rectGroup.left, m_arrData[i + j].m_rect.left);
rectGroup.top = __min(rectGroup.top, m_arrData[i + j].m_rect.top);
rectGroup.right = __max(rectGroup.right, m_arrData[i + j].m_rect.right);
rectGroup.bottom = __max(rectGroup.bottom, m_arrData[i + j].m_rect.bottom);
}
for(j = 0; j < nGroupCount; j++)
{
_AtlDlgResizeData* pDataPrev = NULL;
if(j > 0)
pDataPrev = &(m_arrData[i + j - 1]);
pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i + j], true, pDataPrev);
}
i += nGroupCount - 1;
}
else
{
RECT rectGroup = { 0, 0, 0, 0 };
pT->DlgResize_PositionControl(cxWidth, cyHeight, rectGroup, m_arrData[i], false);
}
}
if(bVisible)
pT->SetRedraw(TRUE);
pT->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
}
BEGIN_MSG_MAP(CDialogResize)
MESSAGE_HANDLER(WM_SIZE, OnSize)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_GETMINMAXINFO, OnGetMinMaxInfo)
#endif
END_MSG_MAP()
LRESULT OnSize(UINT , WPARAM wParam, LPARAM lParam, BOOL& )
{
T* pT = static_cast<T*>(this);
#ifndef _WIN32_WCE
if(m_bGripper)
{
ATL::CWindow wndGripper = pT->GetDlgItem(ATL_IDW_STATUS_BAR);
if(wParam == SIZE_MAXIMIZED)
wndGripper.ShowWindow(SW_HIDE);
else if(wParam == SIZE_RESTORED)
wndGripper.ShowWindow(SW_SHOW);
}
#endif
if(wParam != SIZE_MINIMIZED)
{
ATLASSERT(::IsWindow(pT->m_hWnd));
pT->DlgResize_UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
}
return 0;
}
#ifndef _WIN32_WCE
LRESULT OnGetMinMaxInfo(UINT , WPARAM , LPARAM lParam, BOOL& )
{
if(m_ptMinTrackSize.x != -1 && m_ptMinTrackSize.y != -1)
{
LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
lpMMI->ptMinTrackSize = m_ptMinTrackSize;
}
return 0;
}
#endif
bool DlgResize_PositionControl(int cxWidth, int cyHeight, RECT& rectGroup, _AtlDlgResizeData& data, bool bGroup,
_AtlDlgResizeData* pDataPrev = NULL)
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
ATL::CWindow ctl;
RECT rectCtl = { 0 };
ctl = pT->GetDlgItem(data.m_nCtlID);
if(!ctl.GetWindowRect(&rectCtl))
return false;
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rectCtl, 2);
if(bGroup)
{
if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
{
int cxRight = rectGroup.right + cxWidth - m_sizeDialog.cx;
int cxCtl = data.m_rect.right - data.m_rect.left;
rectCtl.left = rectGroup.left + (cxRight - rectGroup.left - cxCtl) / 2;
rectCtl.right = rectCtl.left + cxCtl;
}
else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
{
rectCtl.left = rectGroup.left + ::MulDiv(data.m_rect.left - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
if((data.m_dwResizeFlags & DLSZ_SIZE_X) != 0)
{
rectCtl.right = rectGroup.left + ::MulDiv(data.m_rect.right - rectGroup.left, rectGroup.right - rectGroup.left + (cxWidth - m_sizeDialog.cx), rectGroup.right - rectGroup.left);
if(pDataPrev != NULL)
{
ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
RECT rcPrev = { 0 };
ctlPrev.GetWindowRect(&rcPrev);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
int dxAdjust = (rectCtl.left - rcPrev.right) - (data.m_rect.left - pDataPrev->m_rect.right);
rcPrev.right += dxAdjust;
ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
}
}
else
{
rectCtl.right = rectCtl.left + (data.m_rect.right - data.m_rect.left);
}
}
if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
{
int cyBottom = rectGroup.bottom + cyHeight - m_sizeDialog.cy;
int cyCtl = data.m_rect.bottom - data.m_rect.top;
rectCtl.top = rectGroup.top + (cyBottom - rectGroup.top - cyCtl) / 2;
rectCtl.bottom = rectCtl.top + cyCtl;
}
else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
{
rectCtl.top = rectGroup.top + ::MulDiv(data.m_rect.top - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
if((data.m_dwResizeFlags & DLSZ_SIZE_Y) != 0)
{
rectCtl.bottom = rectGroup.top + ::MulDiv(data.m_rect.bottom - rectGroup.top, rectGroup.bottom - rectGroup.top + (cyHeight - m_sizeDialog.cy), rectGroup.bottom - rectGroup.top);
if(pDataPrev != NULL)
{
ATL::CWindow ctlPrev = pT->GetDlgItem(pDataPrev->m_nCtlID);
RECT rcPrev = { 0 };
ctlPrev.GetWindowRect(&rcPrev);
::MapWindowPoints(NULL, pT->m_hWnd, (LPPOINT)&rcPrev, 2);
int dxAdjust = (rectCtl.top - rcPrev.bottom) - (data.m_rect.top - pDataPrev->m_rect.bottom);
rcPrev.bottom += dxAdjust;
ctlPrev.SetWindowPos(NULL, &rcPrev, SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
}
}
else
{
rectCtl.bottom = rectCtl.top + (data.m_rect.bottom - data.m_rect.top);
}
}
}
else
{
if((data.m_dwResizeFlags & DLSZ_CENTER_X) != 0)
{
int cxCtl = data.m_rect.right - data.m_rect.left;
rectCtl.left = (cxWidth - cxCtl) / 2;
rectCtl.right = rectCtl.left + cxCtl;
}
else if((data.m_dwResizeFlags & (DLSZ_SIZE_X | DLSZ_MOVE_X)) != 0)
{
rectCtl.right = data.m_rect.right + (cxWidth - m_sizeDialog.cx);
if((data.m_dwResizeFlags & DLSZ_MOVE_X) != 0)
rectCtl.left = rectCtl.right - (data.m_rect.right - data.m_rect.left);
}
if((data.m_dwResizeFlags & DLSZ_CENTER_Y) != 0)
{
int cyCtl = data.m_rect.bottom - data.m_rect.top;
rectCtl.top = (cyHeight - cyCtl) / 2;
rectCtl.bottom = rectCtl.top + cyCtl;
}
else if((data.m_dwResizeFlags & (DLSZ_SIZE_Y | DLSZ_MOVE_Y)) != 0)
{
rectCtl.bottom = data.m_rect.bottom + (cyHeight - m_sizeDialog.cy);
if((data.m_dwResizeFlags & DLSZ_MOVE_Y) != 0)
rectCtl.top = rectCtl.bottom - (data.m_rect.bottom - data.m_rect.top);
}
}
if((data.m_dwResizeFlags & DLSZ_REPAINT) != 0)
ctl.Invalidate();
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)
ctl.SetWindowPos(NULL, &rectCtl, SWP_NOZORDER | SWP_NOACTIVATE);
return true;
}
};
template <class T>
class CDoubleBufferImpl
{
public:
void DoPaint(CDCHandle )
{
ATLASSERT(FALSE);
}
BEGIN_MSG_MAP(CDoubleBufferImpl)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
#endif
END_MSG_MAP()
LRESULT OnEraseBackground(UINT , WPARAM , LPARAM , BOOL& )
{
return 1;
}
LRESULT OnPaint(UINT , WPARAM wParam, LPARAM , BOOL& )
{
T* pT = static_cast<T*>(this);
ATLASSERT(::IsWindow(pT->m_hWnd));
if(wParam != NULL)
{
RECT rect = { 0 };
pT->GetClientRect(&rect);
CMemoryDC dcMem((HDC)wParam, rect);
pT->DoPaint(dcMem.m_hDC);
}
else
{
CPaintDC dc(pT->m_hWnd);
CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint);
pT->DoPaint(dcMem.m_hDC);
}
return 0;
}
};
template <class T, class TBase = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
class ATL_NO_VTABLE CDoubleBufferWindowImpl : public ATL::CWindowImpl< T, TBase, TWinTraits >, public CDoubleBufferImpl< T >
{
public:
BEGIN_MSG_MAP(CDoubleBufferWindowImpl)
CHAIN_MSG_MAP(CDoubleBufferImpl< T >)
END_MSG_MAP()
};
#if !defined(__ATLCTRLW_H__) && !defined(_WIN32_WCE)
#undef CBRM_GETMENU
#undef CBRM_TRACKPOPUPMENU
#undef CBRM_GETCMDBAR
#undef CBRPOPUPMENU
#endif
};
#endif