📄 atlctrlx.h
字号:
return true;
}
BOOL GetPaneText(int nPaneID, LPTSTR lpstrText, int* pcchLength = NULL, int* pnType = NULL) const
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
int nLength = GetText(nIndex, lpstrText, pnType);
if(pcchLength != NULL)
*pcchLength = nLength;
return TRUE;
}
BOOL SetPaneText(int nPaneID, LPCTSTR lpstrText, int nType = 0)
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
return SetText(nIndex, lpstrText, nType);
}
BOOL GetPaneRect(int nPaneID, LPRECT lpRect) const
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
return GetRect(nIndex, lpRect);
}
BOOL SetPaneWidth(int nPaneID, int cxWidth)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(nPaneID != ID_DEFAULT_PANE); // Can't resize this one
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
// get pane positions
int* pPanesPos = NULL;
ATLTRY(pPanesPos = (int*)_alloca(m_nPanes * sizeof(int)));
GetParts(m_nPanes, pPanesPos);
// calculate offset
int cxPaneWidth = pPanesPos[nIndex] - ((nIndex == 0) ? 0 : pPanesPos[nIndex - 1]);
int cxOff = cxWidth - cxPaneWidth;
// find variable width pane
int nDef = m_nPanes;
for(int i = 0; i < m_nPanes; i++)
{
if(m_pPane[i] == ID_DEFAULT_PANE)
{
nDef = i;
break;
}
}
// resize
if(nIndex < nDef) // before default pane
{
for(int i = nIndex; i < nDef; i++)
pPanesPos[i] += cxOff;
}
else // after default one
{
for(int i = nDef; i < nIndex; i++)
pPanesPos[i] -= cxOff;
}
// set pane postions
return SetParts(m_nPanes, pPanesPos);
}
#if (_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
BOOL GetPaneTipText(int nPaneID, LPTSTR lpstrText, int nSize) const
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
GetTipText(nIndex, lpstrText, nSize);
return TRUE;
}
BOOL SetPaneTipText(int nPaneID, LPCTSTR lpstrText)
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
SetTipText(nIndex, lpstrText);
return TRUE;
}
BOOL GetPaneIcon(int nPaneID, HICON& hIcon) const
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
hIcon = GetIcon(nIndex);
return TRUE;
}
BOOL SetPaneIcon(int nPaneID, HICON hIcon)
{
ATLASSERT(::IsWindow(m_hWnd));
int nIndex = GetPaneIndexFromID(nPaneID);
if(nIndex == -1)
return FALSE;
return SetIcon(nIndex, hIcon);
}
#endif //(_WIN32_IE >= 0x0400) && !defined(_WIN32_WCE)
// Message map and handlers
BEGIN_MSG_MAP(CMultiPaneStatusBarCtrlImpl< T >)
MESSAGE_HANDLER(WM_SIZE, OnSize)
END_MSG_MAP()
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
LRESULT lRet = DefWindowProc(uMsg, wParam, lParam);
if(wParam != SIZE_MINIMIZED && m_nPanes > 0)
{
T* pT = static_cast<T*>(this);
pT->UpdatePanesLayout();
}
return lRet;
}
// Implementation
BOOL UpdatePanesLayout()
{
// get pane positions
int* pPanesPos = NULL;
ATLTRY(pPanesPos = (int*)_alloca(m_nPanes * sizeof(int)));
ATLASSERT(pPanesPos != NULL);
if(pPanesPos == NULL)
return FALSE;
int nRet = GetParts(m_nPanes, pPanesPos);
ATLASSERT(nRet == m_nPanes);
if(nRet != m_nPanes)
return FALSE;
// calculate offset
RECT rcClient = { 0 };
GetClientRect(&rcClient);
int cxOff = rcClient.right - pPanesPos[m_nPanes - 1];
#ifndef _WIN32_WCE
// Move panes left if size grip box is present
if((GetStyle() & SBARS_SIZEGRIP) != 0)
cxOff -= ::GetSystemMetrics(SM_CXVSCROLL) + ::GetSystemMetrics(SM_CXEDGE);
#endif //!_WIN32_WCE
// find variable width pane
int i;
for(i = 0; i < m_nPanes; i++)
{
if(m_pPane[i] == ID_DEFAULT_PANE)
break;
}
// resize all panes from the variable one to the right
if((i < m_nPanes) && (pPanesPos[i] + cxOff) > ((i == 0) ? 0 : pPanesPos[i - 1]))
{
for(; i < m_nPanes; i++)
pPanesPos[i] += cxOff;
}
// set pane postions
return SetParts(m_nPanes, pPanesPos);
}
int GetPaneIndexFromID(int nPaneID) const
{
for(int i = 0; i < m_nPanes; i++)
{
if(m_pPane[i] == nPaneID)
return i;
}
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 = ATL::CWindow, class TWinTraits = ATL::CControlWinTraits>
class ATL_NO_VTABLE CPaneContainerImpl : public ATL::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;
ATL::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);
#if (_MSC_VER >= 1300)
return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
#else //!(_MSC_VER >= 1300)
typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
#endif //!(_MSC_VER >= 1300)
}
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)
#if (_ATL_VER >= 0x0700)
::LoadString(ATL::_AtlBaseModule.GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle);
#else //!(_ATL_VER >= 0x0700)
::LoadString(_Module.GetResourceInstance(), uTitleID, m_szTitle, m_cchTitle);
#endif //!(_ATL_VER >= 0x0700)
#if (_MSC_VER >= 1300)
return ATL::CWindowImpl< T, TBase, TWinTraits >::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
#else //!(_MSC_VER >= 1300)
typedef ATL::CWindowImpl< T, TBase, TWinTraits > _baseClass;
return _baseClass::Create(hWndParent, rcDefault, NULL, dwStyle, dwExStyle, nID, lpCreateParam);
#endif //!(_MSC_VER >= 1300)
}
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 = { 0 };
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);
pT;
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);
#ifndef _WIN32_WCE
// 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);
#endif //!_WIN32_WCE
// 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -