📄 atlctrlx.h
字号:
LPTSTR p = NULL;
for(int i = 0; i < 2; i++)
{
for(p = lpstr; *p != _T('\0'); p = ::CharNext(p))
{
if(*p == _T(','))
{
*p = _T('\0');
c[i] = T::_xttoi(lpstr);
lpstr = &p[1];
break;
}
}
if(c[i] == -1)
return CLR_INVALID;
}
if(*lpstr == _T('\0'))
return CLR_INVALID;
c[2] = T::_xttoi(lpstr);
return RGB(c[0], c[1], c[2]);
}
bool CalcLabelRect()
{
if(!::IsWindow(m_hWnd))
return false;
if(m_lpstrLabel == NULL && m_lpstrHyperLink == NULL)
return false;
CClientDC dc(m_hWnd);
RECT rcClient = { 0 };
GetClientRect(&rcClient);
m_rcLink = rcClient;
if(!m_bPaintLabel)
return true;
if(IsUsingTags())
{
// find tags and label parts
LPTSTR lpstrLeft = NULL;
int cchLeft = 0;
LPTSTR lpstrLink = NULL;
int cchLink = 0;
LPTSTR lpstrRight = NULL;
int cchRight = 0;
T* pT = static_cast<T*>(this);
pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
ATLASSERT(lpstrLink != NULL);
ATLASSERT(cchLink > 0);
// get label part rects
HFONT hFontOld = dc.SelectFont(m_hFontNormal);
RECT rcLeft = rcClient;
if(lpstrLeft != NULL)
dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
dc.SelectFont(m_hFont);
RECT rcLink = rcClient;
if(lpstrLeft != NULL)
rcLink.left = rcLeft.right;
dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
dc.SelectFont(hFontOld);
m_rcLink = rcLink;
}
else
{
HFONT hOldFont = NULL;
if(m_hFont != NULL)
hOldFont = dc.SelectFont(m_hFont);
LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
DWORD dwStyle = GetStyle();
int nDrawStyle = DT_LEFT;
if (dwStyle & SS_CENTER)
nDrawStyle = DT_CENTER;
else if (dwStyle & SS_RIGHT)
nDrawStyle = DT_RIGHT;
dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK | DT_CALCRECT);
if(m_hFont != NULL)
dc.SelectFont(hOldFont);
if (dwStyle & SS_CENTER)
{
int dx = (rcClient.right - m_rcLink.right) / 2;
::OffsetRect(&m_rcLink, dx, 0);
}
else if (dwStyle & SS_RIGHT)
{
int dx = rcClient.right - m_rcLink.right;
::OffsetRect(&m_rcLink, dx, 0);
}
}
return true;
}
void CalcLabelParts(LPTSTR& lpstrLeft, int& cchLeft, LPTSTR& lpstrLink, int& cchLink, LPTSTR& lpstrRight, int& cchRight) const
{
lpstrLeft = NULL;
cchLeft = 0;
lpstrLink = NULL;
cchLink = 0;
lpstrRight = NULL;
cchRight = 0;
LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
int cchText = lstrlen(lpstrText);
bool bOutsideLink = true;
for(int i = 0; i < cchText; i++)
{
if(lpstrText[i] != _T('<'))
continue;
if(bOutsideLink)
{
if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 3, _T("<A>"), 3) == CSTR_EQUAL)
{
if(i > 0)
{
lpstrLeft = lpstrText;
cchLeft = i;
}
lpstrLink = &lpstrText[i + 3];
bOutsideLink = false;
}
}
else
{
if(::CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, &lpstrText[i], 4, _T("</A>"), 4) == CSTR_EQUAL)
{
cchLink = i - 3 - cchLeft;
if(lpstrText[i + 4] != 0)
{
lpstrRight = &lpstrText[i + 4];
cchRight = cchText - (i + 4);
break;
}
}
}
}
}
void DoEraseBackground(CDCHandle dc)
{
HBRUSH hBrush = (HBRUSH)::SendMessage(GetParent(), WM_CTLCOLORSTATIC, (WPARAM)dc.m_hDC, (LPARAM)m_hWnd);
if(hBrush != NULL)
{
RECT rect = { 0 };
GetClientRect(&rect);
dc.FillRect(&rect, hBrush);
}
}
void DoPaint(CDCHandle dc)
{
if(IsUsingTags())
{
// find tags and label parts
LPTSTR lpstrLeft = NULL;
int cchLeft = 0;
LPTSTR lpstrLink = NULL;
int cchLink = 0;
LPTSTR lpstrRight = NULL;
int cchRight = 0;
T* pT = static_cast<T*>(this);
pT->CalcLabelParts(lpstrLeft, cchLeft, lpstrLink, cchLink, lpstrRight, cchRight);
// get label part rects
RECT rcClient = { 0 };
GetClientRect(&rcClient);
dc.SetBkMode(TRANSPARENT);
HFONT hFontOld = dc.SelectFont(m_hFontNormal);
if(lpstrLeft != NULL)
dc.DrawText(lpstrLeft, cchLeft, &rcClient, DT_LEFT | DT_WORDBREAK);
COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
dc.SelectFont(m_hFont);
else
dc.SelectFont(m_hFontNormal);
dc.DrawText(lpstrLink, cchLink, &m_rcLink, DT_LEFT | DT_WORDBREAK);
dc.SetTextColor(clrOld);
dc.SelectFont(m_hFontNormal);
if(lpstrRight != NULL)
{
RECT rcRight = { m_rcLink.right, m_rcLink.top, rcClient.right, rcClient.bottom };
dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK);
}
if(GetFocus() == m_hWnd)
dc.DrawFocusRect(&m_rcLink);
dc.SelectFont(hFontOld);
}
else
{
dc.SetBkMode(TRANSPARENT);
COLORREF clrOld = dc.SetTextColor(IsWindowEnabled() ? (m_bVisited ? m_clrVisited : m_clrLink) : (::GetSysColor(COLOR_GRAYTEXT)));
HFONT hFontOld = NULL;
if(m_hFont != NULL && (!IsUnderlineHover() || (IsUnderlineHover() && m_bHover)))
hFontOld = dc.SelectFont(m_hFont);
else
hFontOld = dc.SelectFont(m_hFontNormal);
LPTSTR lpstrText = (m_lpstrLabel != NULL) ? m_lpstrLabel : m_lpstrHyperLink;
DWORD dwStyle = GetStyle();
int nDrawStyle = DT_LEFT;
if (dwStyle & SS_CENTER)
nDrawStyle = DT_CENTER;
else if (dwStyle & SS_RIGHT)
nDrawStyle = DT_RIGHT;
dc.DrawText(lpstrText, -1, &m_rcLink, nDrawStyle | DT_WORDBREAK);
if(GetFocus() == m_hWnd)
dc.DrawFocusRect(&m_rcLink);
dc.SetTextColor(clrOld);
dc.SelectFont(hFontOld);
}
}
#ifndef _WIN32_WCE
BOOL StartTrackMouseLeave()
{
TRACKMOUSEEVENT tme = { 0 };
tme.cbSize = sizeof(tme);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = m_hWnd;
return _TrackMouseEvent(&tme);
}
#endif // !_WIN32_WCE
// Implementation helpers
bool IsUnderlined() const
{
return ((m_dwExtendedStyle & (HLINK_NOTUNDERLINED | HLINK_UNDERLINEHOVER)) == 0);
}
bool IsNotUnderlined() const
{
return ((m_dwExtendedStyle & HLINK_NOTUNDERLINED) != 0);
}
bool IsUnderlineHover() const
{
return ((m_dwExtendedStyle & HLINK_UNDERLINEHOVER) != 0);
}
bool IsCommandButton() const
{
return ((m_dwExtendedStyle & HLINK_COMMANDBUTTON) != 0);
}
bool IsNotifyButton() const
{
return ((m_dwExtendedStyle & HLINK_NOTIFYBUTTON) == HLINK_NOTIFYBUTTON);
}
bool IsUsingTags() const
{
return ((m_dwExtendedStyle & HLINK_USETAGS) != 0);
}
bool IsUsingTagsBold() const
{
return ((m_dwExtendedStyle & HLINK_USETAGSBOLD) == HLINK_USETAGSBOLD);
}
bool IsUsingToolTip() const
{
return ((m_dwExtendedStyle & HLINK_NOTOOLTIP) == 0);
}
static int _xttoi(const TCHAR* nptr)
{
#ifndef _ATL_MIN_CRT
return _ttoi(nptr);
#else // _ATL_MIN_CRT
while(*nptr == _T(' ')) // skip spaces
++nptr;
int c = (int)(_TUCHAR)*nptr++;
int sign = c; // save sign indication
if (c == _T('-') || c == _T('+'))
c = (int)(_TUCHAR)*nptr++; // skip sign
int total = 0;
while((TCHAR)c >= _T('0') && (TCHAR)c <= _T('9'))
{
total = 10 * total + ((TCHAR)c - _T('0')); // accumulate digit
c = (int)(_TUCHAR)*nptr++; // get next char
}
// return result, negated if necessary
return ((TCHAR)sign != _T('-')) ? total : -total;
#endif // _ATL_MIN_CRT
}
};
class CHyperLink : public CHyperLinkImpl<CHyperLink>
{
public:
DECLARE_WND_CLASS(_T("WTL_HyperLink"))
};
///////////////////////////////////////////////////////////////////////////////
// CWaitCursor - displays a wait cursor
class CWaitCursor
{
public:
// Data
HCURSOR m_hWaitCursor;
HCURSOR m_hOldCursor;
bool m_bInUse;
// Constructor/destructor
CWaitCursor(bool bSet = true, LPCTSTR lpstrCursor = IDC_WAIT, bool bSys = true) : m_hOldCursor(NULL), m_bInUse(false)
{
#if (_ATL_VER >= 0x0700)
HINSTANCE hInstance = bSys ? NULL : ATL::_AtlBaseModule.GetResourceInstance();
#else // !(_ATL_VER >= 0x0700)
HINSTANCE hInstance = bSys ? NULL : _Module.GetResourceInstance();
#endif // !(_ATL_VER >= 0x0700)
m_hWaitCursor = ::LoadCursor(hInstance, lpstrCursor);
ATLASSERT(m_hWaitCursor != NULL);
if(bSet)
Set();
}
~CWaitCursor()
{
Restore();
}
// Methods
bool Set()
{
if(m_bInUse)
return false;
m_hOldCursor = ::SetCursor(m_hWaitCursor);
m_bInUse = true;
return true;
}
bool Restore()
{
if(!m_bInUse)
return false;
::SetCursor(m_hOldCursor);
m_bInUse = false;
return true;
}
};
///////////////////////////////////////////////////////////////////////////////
// CCustomWaitCursor - for custom and animated cursors
class CCustomWaitCursor : public CWaitCursor
{
public:
// Constructor/destructor
CCustomWaitCursor(ATL::_U_STRINGorID cursor, bool bSet = true, HINSTANCE hInstance = NULL) :
CWaitCursor(false, IDC_WAIT, true)
{
if(hInstance == NULL)
{
#if (_ATL_VER >= 0x0700)
hInstance = ATL::_AtlBaseModule.GetResourceInstance();
#else // !(_ATL_VER >= 0x0700)
hInstance = _Module.GetResourceInstance();
#endif // !(_ATL_VER >= 0x0700)
}
m_hWaitCursor = (HCURSOR)::LoadImage(hInstance, cursor.m_lpstr, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
if(bSet)
Set();
}
~CCustomWaitCursor()
{
Restore();
#if !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
::DestroyCursor(m_hWaitCursor);
#endif // !defined(_WIN32_WCE) || ((_WIN32_WCE >= 0x400) && !(defined(WIN32_PLATFORM_PSPC) || defined(WIN32_PLATFORM_WFSP)))
}
};
///////////////////////////////////////////////////////////////////////////////
// CMultiPaneStatusBarCtrl - Status Bar with multiple panes
template <class T, class TBase = CStatusBarCtrl>
class ATL_NO_VTABLE CMultiPaneStatusBarCtrlImpl : public ATL::CWindowImpl< T, TBase >
{
public:
DECLARE_WND_SUPERCLASS(NULL, TBase::GetWndClassName())
// Data
enum { m_cxPaneMargin = 3 };
int m_nPanes;
int* m_pPane;
// Constructor/destructor
CMultiPaneStatusBarCtrlImpl() : m_nPanes(0), m_pPane(NULL)
{ }
~CMultiPaneStatusBarCtrlImpl()
{
delete [] m_pPane;
}
// Methods
HWND Create(HWND hWndParent, LPCTSTR lpstrText, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
{
#if (_MSC_VER >= 1300)
return ATL::CWindowImpl< T, TBase >::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
#else // !(_MSC_VER >= 1300)
typedef ATL::CWindowImpl< T, TBase > _baseClass;
return _baseClass::Create(hWndParent, rcDefault, lpstrText, dwStyle, 0, nID);
#endif // !(_MSC_VER >= 1300)
}
HWND Create(HWND hWndParent, UINT nTextID = ATL_IDS_IDLEMESSAGE, DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | SBARS_SIZEGRIP, UINT nID = ATL_IDW_STATUS_BAR)
{
const int cchMax = 128; // max text length is 127 for status bars (+1 for null)
TCHAR szText[cchMax];
szText[0] = 0;
#if (_ATL_VER >= 0x0700)
::LoadString(ATL::_AtlBaseModule.GetResourceInstance(), nTextID, szText, cchMax);
#else // !(_ATL_VER >= 0x0700)
::LoadString(_Module.GetResourceInstance(), nTextID, szText, cchMax);
#endif // !(_ATL_VER >= 0x0700)
return Create(hWndParent, szText, dwStyle, nID);
}
BOOL SetPanes(int* pPanes, int nPanes, bool bSetText = true)
{
ATLASSERT(::IsWindow(m_hWnd));
ATLASSERT(nPanes > 0);
m_nPanes = nPanes;
delete [] m_pPane;
m_pPane = NULL;
ATLTRY(m_pPane = new int[nPanes]);
ATLASSERT(m_pPane != NULL);
if(m_pPane == NULL)
return FALSE;
memcpy(m_pPane, pPanes, nPanes * sizeof(int));
int* pPanesPos = (int*)_alloca(nPanes * sizeof(int));
// get status bar DC and set font
CClientDC dc(m_hWnd);
HFONT hOldFont = dc.SelectFont(GetFont());
// get status bar borders
int arrBorders[3] = { 0 };
GetBorders(arrBorders);
const int cchBuff = 128;
TCHAR szBuff[cchBuff] = { 0 };
SIZE size = { 0, 0 };
int cxLeft = arrBorders[0];
// calculate right edge of each part
for(int i = 0; i < nPanes; i++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -