📄 atlctrlx.h
字号:
return -1; // not found
}
};
class CMultiPaneStatusBarCtrl : public CMultiPaneStatusBarCtrlImpl<CMultiPaneStatusBarCtrl>
{
public:
DECLARE_WND_SUPERCLASS(_T("WTL_MultiPaneStatusBar"), GetWndClassName())
};
/////////////////////////////////////////////////////////////////////////////
// CPaneContainer - provides header with title and close button for panes
// pane container extended styles
#define PANECNT_NOCLOSEBUTTON 0x00000001
#define PANECNT_VERTICAL 0x00000002
template <class T, class TBase = CWindow, class TWinTraits = CControlWinTraits>
class ATL_NO_VTABLE CPaneContainerImpl : public CWindowImpl< T, TBase, TWinTraits >, public CCustomDraw< T >
{
public:
DECLARE_WND_CLASS_EX(NULL, 0, -1)
// Constants
enum
{
m_cxyBorder = 2,
m_cxyTextOffset = 4,
m_cxyBtnOffset = 1,
m_cchTitle = 80,
m_cxImageTB = 13,
m_cyImageTB = 11,
m_cxyBtnAddTB = 7,
m_cxToolBar = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder + m_cxyBtnOffset,
m_xBtnImageLeft = 6,
m_yBtnImageTop = 5,
m_xBtnImageRight = 12,
m_yBtnImageBottom = 11,
m_nCloseBtnID = ID_PANE_CLOSE
};
// Data members
CToolBarCtrl m_tb;
CWindow m_wndClient;
int m_cxyHeader;
TCHAR m_szTitle[m_cchTitle];
DWORD m_dwExtendedStyle; // Pane container specific extended styles
// Constructor
CPaneContainerImpl() : m_cxyHeader(0), m_dwExtendedStyle(0)
{
m_szTitle[0] = 0;
}
// Attributes
DWORD GetPaneContainerExtendedStyle() const
{
return m_dwExtendedStyle;
}
DWORD SetPaneContainerExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)
{
DWORD dwPrevStyle = m_dwExtendedStyle;
if(dwMask == 0)
m_dwExtendedStyle = dwExtendedStyle;
else
m_dwExtendedStyle = (m_dwExtendedStyle & ~dwMask) | (dwExtendedStyle & dwMask);
if(m_hWnd != NULL)
{
T* pT = static_cast<T*>(this);
bool bUpdate = false;
if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) != 0) && ((dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)) // add close button
{
pT->CreateCloseButton();
bUpdate = true;
}
else if(((dwPrevStyle & PANECNT_NOCLOSEBUTTON) == 0) && ((dwExtendedStyle & PANECNT_NOCLOSEBUTTON) != 0)) // remove close button
{
pT->DestroyCloseButton();
bUpdate = true;
}
if((dwPrevStyle & PANECNT_VERTICAL) != (dwExtendedStyle & PANECNT_VERTICAL)) // change orientation
{
CalcSize();
bUpdate = true;
}
if(bUpdate)
pT->UpdateLayout();
}
return dwPrevStyle;
}
HWND GetClient() const
{
return m_wndClient;
}
HWND SetClient(HWND hWndClient)
{
HWND hWndOldClient = m_wndClient;
m_wndClient = hWndClient;
if(m_hWnd != NULL)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
return hWndOldClient;
}
BOOL GetTitle(LPTSTR lpstrTitle, int cchLength) const
{
ATLASSERT(lpstrTitle != NULL);
return (lstrcpyn(lpstrTitle, m_szTitle, cchLength) != NULL);
}
BOOL SetTitle(LPCTSTR lpstrTitle)
{
ATLASSERT(lpstrTitle != NULL);
BOOL bRet = (lstrcpyn(m_szTitle, lpstrTitle, m_cchTitle) != NULL);
if(bRet && m_hWnd != NULL)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout();
}
return bRet;
}
int GetTitleLength() const
{
return lstrlen(m_szTitle);
}
// Methods
HWND Create(HWND hWndParent, LPCTSTR lpstrTitle = NULL, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
{
if(lpstrTitle != NULL)
lstrcpyn(m_szTitle, lpstrTitle, m_cchTitle);
return CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
}
HWND Create(HWND hWndParent, UINT uTitleID, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
DWORD dwExStyle = 0, UINT nID = 0, LPVOID lpCreateParam = NULL)
{
if(uTitleID != 0U)
::LoadString(_Module.GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle);
return CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
}
BOOL EnableCloseButton(BOOL bEnable)
{
ATLASSERT(::IsWindow(m_hWnd));
T* pT = static_cast<T*>(this);
pT; // avoid level 4 warning
return (m_tb.m_hWnd != NULL) ? m_tb.EnableButton(pT->m_nCloseBtnID, bEnable) : FALSE;
}
void UpdateLayout()
{
RECT rcClient;
GetClientRect(&rcClient);
T* pT = static_cast<T*>(this);
pT->UpdateLayout(rcClient.right, rcClient.bottom);
}
// Message map and handlers
BEGIN_MSG_MAP(CPaneContainerImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
MESSAGE_HANDLER(WM_COMMAND, OnCommand)
FORWARD_NOTIFICATIONS()
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
pT->CalcSize();
if((m_dwExtendedStyle & PANECNT_NOCLOSEBUTTON) == 0)
pT->CreateCloseButton();
return 0;
}
LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
pT->UpdateLayout(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return 0;
}
LRESULT OnSetFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(m_wndClient.m_hWnd != NULL)
m_wndClient.SetFocus();
return 0;
}
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return 1; // no background needed
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CPaintDC dc(m_hWnd);
T* pT = static_cast<T*>(this);
pT->DrawPaneTitle(dc.m_hDC);
if(m_wndClient.m_hWnd == NULL) // no client window
pT->DrawPane(dc.m_hDC);
return 0;
}
LRESULT OnNotify(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
if(m_tb.m_hWnd == NULL)
{
bHandled = FALSE;
return 1;
}
T* pT = static_cast<T*>(this);
LPNMHDR lpnmh = (LPNMHDR)lParam;
LRESULT lRet = 0;
// pass toolbar custom draw notifications to the base class
if(lpnmh->code == NM_CUSTOMDRAW && lpnmh->hwndFrom == m_tb.m_hWnd)
lRet = CCustomDraw< T >::OnCustomDraw(0, lpnmh, bHandled);
// tooltip notifications come with the tooltip window handle and button ID,
// pass them to the parent if we don't handle them
else if(lpnmh->code == TTN_GETDISPINFO && lpnmh->idFrom == pT->m_nCloseBtnID)
bHandled = pT->GetToolTipText(lpnmh);
// only let notifications not from the toolbar go to the parent
else if(lpnmh->hwndFrom != m_tb.m_hWnd && lpnmh->idFrom != pT->m_nCloseBtnID)
bHandled = FALSE;
return lRet;
}
LRESULT OnCommand(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
// if command comes from the close button, substitute HWND of the pane container instead
if(m_tb.m_hWnd != NULL && (HWND)lParam == m_tb.m_hWnd)
return ::SendMessage(GetParent(), WM_COMMAND, wParam, (LPARAM)m_hWnd);
bHandled = FALSE;
return 1;
}
// Custom draw overrides
DWORD OnPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW /*lpNMCustomDraw*/)
{
return CDRF_NOTIFYITEMDRAW; // we need per-item notifications
}
DWORD OnItemPrePaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc = lpNMCustomDraw->hdc;
#if (_WIN32_IE >= 0x0400)
RECT& rc = lpNMCustomDraw->rc;
#else //!(_WIN32_IE >= 0x0400)
RECT rc;
m_tb.GetItemRect(0, &rc);
#endif //!(_WIN32_IE >= 0x0400)
dc.FillRect(&rc, COLOR_3DFACE);
return CDRF_NOTIFYPOSTPAINT;
}
DWORD OnItemPostPaint(int /*idCtrl*/, LPNMCUSTOMDRAW lpNMCustomDraw)
{
CDCHandle dc = lpNMCustomDraw->hdc;
#if (_WIN32_IE >= 0x0400)
RECT& rc = lpNMCustomDraw->rc;
#else //!(_WIN32_IE >= 0x0400)
RECT rc;
m_tb.GetItemRect(0, &rc);
#endif //!(_WIN32_IE >= 0x0400)
RECT rcImage = { m_xBtnImageLeft, m_yBtnImageTop, m_xBtnImageRight + 1, m_yBtnImageBottom + 1 };
::OffsetRect(&rcImage, rc.left, rc.top);
T* pT = static_cast<T*>(this);
if((lpNMCustomDraw->uItemState & CDIS_DISABLED) != 0)
{
RECT rcShadow = rcImage;
::OffsetRect(&rcShadow, 1, 1);
CPen pen1;
pen1.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DHILIGHT));
pT->DrawButtonImage(dc, rcShadow, pen1);
CPen pen2;
pen2.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_3DSHADOW));
pT->DrawButtonImage(dc, rcImage, pen2);
}
else
{
if((lpNMCustomDraw->uItemState & CDIS_SELECTED) != 0)
::OffsetRect(&rcImage, 1, 1);
CPen pen;
pen.CreatePen(PS_SOLID, 0, ::GetSysColor(COLOR_BTNTEXT));
pT->DrawButtonImage(dc, rcImage, pen);
}
return CDRF_DODEFAULT; // continue with the default item painting
}
// Implementation - overrideable methods
void UpdateLayout(int cxWidth, int cyHeight)
{
ATLASSERT(::IsWindow(m_hWnd));
RECT rect;
if(IsVertical())
{
::SetRect(&rect, 0, 0, m_cxyHeader, cyHeight);
if(m_tb.m_hWnd != NULL)
m_tb.SetWindowPos(NULL, m_cxyBorder, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
if(m_wndClient.m_hWnd != NULL)
m_wndClient.SetWindowPos(NULL, m_cxyHeader, 0, cxWidth - m_cxyHeader, cyHeight, SWP_NOZORDER);
else
rect.right = cxWidth;
}
else
{
::SetRect(&rect, 0, 0, cxWidth, m_cxyHeader);
if(m_tb.m_hWnd != NULL)
m_tb.SetWindowPos(NULL, rect.right - m_cxToolBar, m_cxyBorder + m_cxyBtnOffset, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
if(m_wndClient.m_hWnd != NULL)
m_wndClient.SetWindowPos(NULL, 0, m_cxyHeader, cxWidth, cyHeight - m_cxyHeader, SWP_NOZORDER);
else
rect.bottom = cyHeight;
}
InvalidateRect(&rect);
}
void CreateCloseButton()
{
ATLASSERT(m_tb.m_hWnd == NULL);
// create toolbar for the "x" button
m_tb.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN | CCS_NOMOVEY | TBSTYLE_TOOLTIPS | TBSTYLE_FLAT, 0);
ATLASSERT(m_tb.IsWindow());
if(m_tb.m_hWnd != NULL)
{
T* pT = static_cast<T*>(this);
pT; // avoid level 4 warning
m_tb.SetButtonStructSize();
TBBUTTON tbbtn;
memset(&tbbtn, 0, sizeof(tbbtn));
tbbtn.idCommand = pT->m_nCloseBtnID;
tbbtn.fsState = TBSTATE_ENABLED;
tbbtn.fsStyle = TBSTYLE_BUTTON;
m_tb.AddButtons(1, &tbbtn);
m_tb.SetBitmapSize(m_cxImageTB, m_cyImageTB);
m_tb.SetButtonSize(m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB);
if(IsVertical())
m_tb.SetWindowPos(NULL, m_cxyBorder + m_cxyBtnOffset, m_cxyBorder + m_cxyBtnOffset, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOACTIVATE);
else
m_tb.SetWindowPos(NULL, 0, 0, m_cxImageTB + m_cxyBtnAddTB, m_cyImageTB + m_cxyBtnAddTB, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
}
void DestroyCloseButton()
{
if(m_tb.m_hWnd != NULL)
m_tb.DestroyWindow();
}
void CalcSize()
{
T* pT = static_cast<T*>(this);
CFontHandle font = pT->GetTitleFont();
LOGFONT lf;
font.GetLogFont(lf);
if(IsVertical())
{
m_cxyHeader = m_cxImageTB + m_cxyBtnAddTB + m_cxyBorder;
}
else
{
int cyFont = abs(lf.lfHeight) + m_cxyBorder + 2 * m_cxyTextOffset;
int cyBtn = m_cyImageTB + m_cxyBtnAddTB + m_cxyBorder + 2 * m_cxyBtnOffset;
m_cxyHeader = max(cyFont, cyBtn);
}
}
HFONT GetTitleFont() const
{
return AtlGetDefaultGuiFont();
}
BOOL GetToolTipText(LPNMHDR /*lpnmh*/)
{
return FALSE;
}
void DrawPaneTitle(CDCHandle dc)
{
RECT rect;
GetClientRect(&rect);
if(IsVertical())
{
rect.right = rect.left + m_cxyHeader;
dc.DrawEdge(&rect, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_BOTTOM | BF_ADJUST);
dc.FillRect(&rect, COLOR_3DFACE);
}
else
{
rect.bottom = rect.top + m_cxyHeader;
dc.DrawEdge(&rect, EDGE_ETCHED, BF_LEFT | BF_TOP | BF_RIGHT | BF_ADJUST);
dc.FillRect(&rect, COLOR_3DFACE);
// draw title only for horizontal pane container
dc.SetTextColor(::GetSysColor(COLOR_WINDOWTEXT));
dc.SetBkMode(TRANSPARENT);
T* pT = static_cast<T*>(this);
HFONT hFontOld = dc.SelectFont(pT->GetTitleFont());
rect.left += m_cxyTextOffset;
rect.right -= m_cxyTextOffset;
if(m_tb.m_hWnd != NULL)
rect.right -= m_cxToolBar;;
dc.DrawText(m_szTitle, -1, &rect, DT_LEFT | DT_SINGLELINE | DT_VCENTER | DT_END_ELLIPSIS);
dc.SelectFont(hFontOld);
}
}
// called only if pane is empty
void DrawPane(CDCHandle dc)
{
RECT rect;
GetClientRect(&rect);
if(IsVertical())
rect.left += m_cxyHeader;
else
rect.top += m_cxyHeader;
if((GetExStyle() & WS_EX_CLIENTEDGE) == 0)
dc.DrawEdge(&rect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
dc.FillRect(&rect, COLOR_APPWORKSPACE);
}
// drawing helper - draws "x" button image
void DrawButtonImage(CDCHandle dc, RECT& rcImage, HPEN hPen)
{
HPEN hPenOld = dc.SelectPen(hPen);
dc.MoveTo(rcImage.left, rcImage.top);
dc.LineTo(rcImage.right, rcImage.bottom);
dc.MoveTo(rcImage.left + 1, rcImage.top);
dc.LineTo(rcImage.right + 1, rcImage.bottom);
dc.MoveTo(rcImage.left, rcImage.bottom - 1);
dc.LineTo(rcImage.right, rcImage.top - 1);
dc.MoveTo(rcImage.left + 1, rcImage.bottom - 1);
dc.LineTo(rcImage.right + 1, rcImage.top - 1);
dc.SelectPen(hPenOld);
}
bool IsVertical() const
{
return ((m_dwExtendedStyle & PANECNT_VERTICAL) != 0);
}
};
class CPaneContainer : public CPaneContainerImpl<CPaneContainer>
{
public:
DECLARE_WND_CLASS_EX(_T("WTL_PaneContainer"), 0, -1)
};
}; //namespace WTL
#endif // __ATLCTRLX_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -