📄 atlframe.h
字号:
// Windows Template Library - WTL version 7.0
// Copyright (C) 1997-2002 Microsoft Corporation
// All rights reserved.
//
// This file is a part of the Windows Template Library.
// The code and information is provided "as-is" without
// warranty of any kind, either expressed or implied.
#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
/////////////////////////////////////////////////////////////////////////////
// Classes in this file
//
// CFrameWindowImpl<T, TBase, TWinTraits>
// CMDIWindow
// CMDIFrameWindowImpl<T, TBase, TWinTraits>
// CMDIChildWindowImpl<T, TBase, TWinTraits>
// COwnerDraw<T>
// CUpdateUIBase
// CUpdateUI<T>
// CDialogResize<T>
namespace WTL
{
/////////////////////////////////////////////////////////////////////////////
// CFrameWndClassInfo - Manages frame window Windows class information
class CFrameWndClassInfo
{
public:
WNDCLASSEX m_wc;
LPCTSTR m_lpszOrigName;
WNDPROC pWndProc;
LPCTSTR m_lpszCursorID;
BOOL m_bSystemCursor;
ATOM m_atom;
TCHAR m_szAutoName[5 + sizeof(void*) * 2]; // sizeof(void*) * 2 is the number of digits %p outputs
UINT m_uCommonResourceID;
ATOM Register(WNDPROC* pProc)
{
if (m_atom == 0)
{
::EnterCriticalSection(&_Module.m_csWindowCreate);
if(m_atom == 0)
{
HINSTANCE hInst = _Module.GetModuleInstance();
if (m_lpszOrigName != NULL)
{
ATLASSERT(pProc != NULL);
LPCTSTR lpsz = m_wc.lpszClassName;
WNDPROC proc = m_wc.lpfnWndProc;
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
// try process local class first
if(!::GetClassInfoEx(_Module.GetModuleInstance(), m_lpszOrigName, &wc))
{
// try global class
if(!::GetClassInfoEx(NULL, m_lpszOrigName, &wc))
{
::LeaveCriticalSection(&_Module.m_csWindowCreate);
return 0;
}
}
memcpy(&m_wc, &wc, sizeof(WNDCLASSEX));
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; // we don't register global classes
if (m_wc.lpszClassName == NULL)
{
wsprintf(m_szAutoName, _T("ATL:%p"), &m_wc);
m_wc.lpszClassName = m_szAutoName;
}
WNDCLASSEX wcTemp;
memcpy(&wcTemp, &m_wc, sizeof(WNDCLASSEX));
m_atom = (ATOM)::GetClassInfoEx(m_wc.hInstance, m_wc.lpszClassName, &wcTemp);
if (m_atom == 0)
{
if(m_uCommonResourceID != 0) // use it if not zero
{
m_wc.hIcon = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 32, 32, LR_DEFAULTCOLOR);
m_wc.hIconSm = (HICON)::LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(m_uCommonResourceID), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
}
m_atom = ::RegisterClassEx(&m_wc);
}
}
::LeaveCriticalSection(&_Module.m_csWindowCreate);
}
if (m_lpszOrigName != NULL)
{
ATLASSERT(pProc != NULL);
ATLASSERT(pWndProc != NULL);
*pProc = pWndProc;
}
return m_atom;
}
};
#define DECLARE_FRAME_WND_CLASS(WndClassName, uCommonResourceID) \
static CFrameWndClassInfo& GetWndClassInfo() \
{ \
static 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 CFrameWndClassInfo& GetWndClassInfo() \
{ \
static 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 CFrameWndClassInfo& GetWndClassInfo() \
{ \
static CFrameWndClassInfo wc = \
{ \
{ sizeof(WNDCLASSEX), 0, StartWindowProc, \
0, 0, NULL, NULL, NULL, NULL, NULL, WndClassName, NULL }, \
OrigWndClassName, NULL, NULL, TRUE, 0, _T(""), uCommonResourceID \
}; \
return wc; \
}
// Command Chaining Macros
#define CHAIN_COMMANDS(theChainClass) \
{ \
if(uMsg == WM_COMMAND && theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
return TRUE; \
}
#define CHAIN_COMMANDS_MEMBER(theChainMember) \
{ \
if(uMsg == WM_COMMAND && theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \
return TRUE; \
}
#define CHAIN_COMMANDS_ALT(theChainClass, msgMapID) \
{ \
if(uMsg == WM_COMMAND && theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
return TRUE; \
}
#define CHAIN_COMMANDS_ALT_MEMBER(theChainMember, msgMapID) \
{ \
if(uMsg == WM_COMMAND && theChainMember.ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, msgMapID)) \
return TRUE; \
}
// Client window command chaining macro
#define CHAIN_CLIENT_COMMANDS() \
if(uMsg == WM_COMMAND && m_hWndClient != NULL) \
::SendMessage(m_hWndClient, uMsg, wParam, lParam);
/////////////////////////////////////////////////////////////////////////////
// CFrameWindowImpl
// standard toolbar styles
#define ATL_SIMPLE_TOOLBAR_STYLE \
(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS)
// toolbar in a rebar pane
#define ATL_SIMPLE_TOOLBAR_PANE_STYLE \
(WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT)
// standard rebar styles
#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 //!(_WIN32_IE >= 0x0400)
// rebar without borders
#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 //!(_WIN32_IE >= 0x0400)
// command bar support
#ifndef __ATLCTRLW_H__
#define CBRM_GETCMDBAR (WM_USER + 301) // return command bar HWND
#define CBRM_GETMENU (WM_USER + 302) // returns loaded or attached menu
#define CBRM_TRACKPOPUPMENU (WM_USER + 303) // displays a popup menu
struct _AtlFrameWnd_CmdBarPopupMenu
{
int cbSize;
HMENU hMenu;
UINT uFlags;
int x;
int y;
LPTPMPARAMS lptpm;
};
#define CBRPOPUPMENU _AtlFrameWnd_CmdBarPopupMenu
#endif //!__ATLCTRLW_H__
template <class TBase = CWindow, class TWinTraits = CFrameWinTraits>
class ATL_NO_VTABLE CFrameWindowImplBase : public CWindowImplBaseT< TBase, TWinTraits >
{
public:
DECLARE_FRAME_WND_CLASS(NULL, 0)
// Data members
HWND m_hWndToolBar;
HWND m_hWndStatusBar;
HWND m_hWndClient;
HACCEL m_hAccel;
struct _AtlToolBarData
{
WORD wVersion;
WORD wWidth;
WORD wHeight;
WORD wItemCount;
//WORD aItems[wItemCount]
WORD* items()
{ return (WORD*)(this+1); }
};
#if (_WIN32_IE >= 0x0500)
struct _ChevronMenuInfo
{
HMENU hMenu;
LPNMREBARCHEVRON lpnm;
bool bCmdBar;
};
#endif //(_WIN32_IE >= 0x0500)
// Constructor
CFrameWindowImplBase() : m_hWndToolBar(NULL), m_hWndStatusBar(NULL), m_hWndClient(NULL), m_hAccel(NULL)
{ }
// Methods
#if (_ATL_VER < 0x0700)
HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam)
{
ATLASSERT(m_hWnd == NULL);
if(atom == 0)
return NULL;
_Module.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, (LPCTSTR)(LONG_PTR)MAKELONG(atom, 0), 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,
_Module.GetModuleInstance(), lpCreateParam);
ATLASSERT(m_hWnd == hWnd);
return hWnd;
}
#endif //(_ATL_VER < 0x0700)
static HWND CreateSimpleToolBarCtrl(HWND hWndParent, UINT nResourceID, BOOL bInitialSeparator = FALSE,
DWORD dwStyle = ATL_SIMPLE_TOOLBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
HINSTANCE hInst = _Module.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);
TBBUTTON* pTBBtn = (TBBUTTON*)_alloca(nItems * sizeof(TBBUTTON));
// set initial separator (half width)
if(bInitialSeparator)
{
pTBBtn[0].iBitmap = 4;
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 = 8;
pTBBtn[j].idCommand = 0;
pTBBtn[j].fsState = 0;
pTBBtn[j].fsStyle = TBSTYLE_SEP;
pTBBtn[j].dwData = 0;
pTBBtn[j].iString = 0;
}
}
HWND hWnd = ::CreateWindowEx(0, TOOLBARCLASSNAME, NULL, dwStyle, 0,0,100,100,
hWndParent, (HMENU)LongToHandle(nID), _Module.GetModuleInstance(), NULL);
::SendMessage(hWnd, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0L);
// check if font is taller than our bitmaps
CFontHandle font = (HFONT)::SendMessage(hWnd, WM_GETFONT, 0, 0L);
if(font.IsNull())
font = AtlGetDefaultGuiFont();
LOGFONT lf;
font.GetLogFont(lf);
WORD cyFontHeight = (WORD)abs(lf.lfHeight);
if(AtlIsAlphaBitmapResource(nResourceID)) // alpha channel bitmap (valid for Windows XP only)
{
HIMAGELIST hImageList = ImageList_LoadImage(_Module.GetResourceInstance(), MAKEINTRESOURCE(nResourceID), pData->wWidth, 1, CLR_NONE, IMAGE_BITMAP, LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
ATLASSERT(hImageList != NULL);
::SendMessage(hWnd, TB_SETIMAGELIST, 0, (LPARAM)hImageList);
}
else
{
TBADDBITMAP tbab;
tbab.hInst = hInst;
tbab.nID = nResourceID;
::SendMessage(hWnd, TB_ADDBITMAP, nBmp, (LPARAM)&tbab);
}
TBADDBITMAP tbab;
tbab.hInst = hInst;
tbab.nID = nResourceID;
::SendMessage(hWnd, TB_ADDBUTTONS, nItems, (LPARAM)pTBBtn);
::SendMessage(hWnd, TB_SETBITMAPSIZE, 0, MAKELONG(pData->wWidth, max(pData->wHeight, cyFontHeight)));
::SendMessage(hWnd, TB_SETBUTTONSIZE, 0, MAKELONG(pData->wWidth + 7, max(pData->wHeight, cyFontHeight) + 7));
return hWnd;
}
static HWND CreateSimpleReBarCtrl(HWND hWndParent, DWORD dwStyle = ATL_SIMPLE_REBAR_STYLE, UINT nID = ATL_IDW_TOOLBAR)
{
// Ensure style combinations for proper rebar painting
if(dwStyle & CCS_NODIVIDER && dwStyle & WS_BORDER)
dwStyle &= ~WS_BORDER;
else if(!(dwStyle & WS_BORDER) && !(dwStyle & CCS_NODIVIDER))
dwStyle |= CCS_NODIVIDER;
// Create rebar window
HWND hWndReBar = ::CreateWindowEx(0, REBARCLASSNAME, NULL, dwStyle, 0, 0, 100, 100, hWndParent, (HMENU)LongToHandle(nID), _Module.GetModuleInstance(), NULL);
if(hWndReBar == NULL)
{
ATLTRACE2(atlTraceUI, 0, _T("Failed to create rebar.\n"));
return NULL;
}
// Initialize and send the REBARINFO structure
REBARINFO rbi;
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, LPTSTR lpstrTitle = NULL, BOOL bNewRow = FALSE, int cxWidth = 0, BOOL bFullWidthAlways = FALSE)
{
ATLASSERT(::IsWindow(hWndReBar)); // must be already created
#ifdef _DEBUG
// block - check if this is really a rebar
{
TCHAR lpszClassName[sizeof(REBARCLASSNAME)];
::GetClassName(hWndReBar, lpszClassName, sizeof(REBARCLASSNAME));
ATLASSERT(lstrcmp(lpszClassName, REBARCLASSNAME) == 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -