📄 atlctrlx.h
字号:
// get label part rects
HFONT hFontOld = dc.SelectFont(m_hFontNormal);
RECT rcLeft = rcClient;
dc.DrawText(lpstrLeft, cchLeft, &rcLeft, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
dc.SelectFont(m_hFont);
RECT rcLink = { rcLeft.right, rcLeft.top, rcClient.right, rcClient.bottom };
dc.DrawText(lpstrLink, cchLink, &rcLink, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
dc.SelectFont(m_hFontNormal);
RECT rcRight = { rcLink.right, rcLink.top, rcClient.right, rcClient.bottom };
dc.DrawText(lpstrRight, cchRight, &rcRight, DT_LEFT | DT_WORDBREAK | DT_CALCRECT);
dc.SelectFont(hFontOld);
int cyMax = max(rcLeft.bottom, max(rcLink.bottom, rcRight.bottom));
::SetRect(&rcAll, rcLeft.left, rcLeft.top, rcRight.right, cyMax);
}
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, &rcAll, nDrawStyle | DT_WORDBREAK | DT_CALCRECT);
if(m_hFont != NULL)
dc.SelectFont(hOldFont);
if (dwStyle & SS_CENTER)
{
int dx = (rcClient.right - rcAll.right) / 2;
::OffsetRect(&rcAll, dx, 0);
}
else if (dwStyle & SS_RIGHT)
{
int dx = rcClient.right - rcAll.right;
::OffsetRect(&rcAll, dx, 0);
}
}
cx = rcAll.right - rcAll.left;
cy = rcAll.bottom - rcAll.top;
return true;
}
// for command buttons only
bool GetToolTipText(LPTSTR lpstrBuffer, int nLength) const
{
ATLASSERT(IsCommandButton());
return GetHyperLink(lpstrBuffer, nLength);
}
bool SetToolTipText(LPCTSTR lpstrToolTipText)
{
ATLASSERT(IsCommandButton());
return SetHyperLink(lpstrToolTipText);
}
// Operations
BOOL SubclassWindow(HWND hWnd)
{
ATLASSERT(m_hWnd == NULL);
ATLASSERT(::IsWindow(hWnd));
#if (_MSC_VER >= 1300)
BOOL bRet = ATL::CWindowImpl< T, TBase, TWinTraits>::SubclassWindow(hWnd);
#else // !(_MSC_VER >= 1300)
typedef ATL::CWindowImpl< T, TBase, TWinTraits> _baseClass;
BOOL bRet = _baseClass::SubclassWindow(hWnd);
#endif // !(_MSC_VER >= 1300)
if(bRet)
{
T* pT = static_cast<T*>(this);
pT->Init();
}
return bRet;
}
bool Navigate()
{
ATLASSERT(::IsWindow(m_hWnd));
bool bRet = true;
if(IsNotifyButton())
{
NMHDR nmhdr = { m_hWnd, GetDlgCtrlID(), NM_CLICK };
::SendMessage(GetParent(), WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&nmhdr);
}
else if(IsCommandButton())
{
::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
}
else
{
ATLASSERT(m_lpstrHyperLink != NULL);
#ifndef _WIN32_WCE
DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL);
#else // CE specific
SHELLEXECUTEINFO shExeInfo = { sizeof(SHELLEXECUTEINFO), 0, 0, L"open", m_lpstrHyperLink, 0, 0, SW_SHOWNORMAL, 0, 0, 0, 0, 0, 0, 0 };
::ShellExecuteEx(&shExeInfo);
DWORD_PTR dwRet = (DWORD_PTR)shExeInfo.hInstApp;
#endif // _WIN32_WCE
bRet = (dwRet > 32);
ATLASSERT(bRet);
if(bRet)
{
m_bVisited = true;
Invalidate();
}
}
return bRet;
}
// Message map and handlers
BEGIN_MSG_MAP(CHyperLinkImpl)
MESSAGE_HANDLER(WM_CREATE, OnCreate)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
MESSAGE_RANGE_HANDLER(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
#endif // !_WIN32_WCE
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
MESSAGE_HANDLER(WM_PAINT, OnPaint)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint)
#endif // !_WIN32_WCE
MESSAGE_HANDLER(WM_SETFOCUS, OnFocus)
MESSAGE_HANDLER(WM_KILLFOCUS, OnFocus)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
#ifndef _WIN32_WCE
MESSAGE_HANDLER(WM_MOUSELEAVE, OnMouseLeave)
#endif // !_WIN32_WCE
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLButtonDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLButtonUp)
MESSAGE_HANDLER(WM_CHAR, OnChar)
MESSAGE_HANDLER(WM_GETDLGCODE, OnGetDlgCode)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
MESSAGE_HANDLER(WM_ENABLE, OnEnable)
MESSAGE_HANDLER(WM_GETFONT, OnGetFont)
MESSAGE_HANDLER(WM_SETFONT, OnSetFont)
MESSAGE_HANDLER(WM_UPDATEUISTATE, OnUpdateUiState)
END_MSG_MAP()
LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
T* pT = static_cast<T*>(this);
pT->Init();
return 0;
}
#ifndef _WIN32_WCE
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_tip.IsWindow())
{
m_tip.DestroyWindow();
m_tip.m_hWnd = NULL;
}
bHandled = FALSE;
return 1;
}
LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
MSG msg = { m_hWnd, uMsg, wParam, lParam };
if(m_tip.IsWindow() && IsUsingToolTip())
m_tip.RelayEvent(&msg);
bHandled = FALSE;
return 1;
}
#endif // !_WIN32_WCE
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return 1; // no background painting needed (we do it all during WM_PAINT)
}
LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
{
if(!m_bPaintLabel)
{
bHandled = FALSE;
return 1;
}
T* pT = static_cast<T*>(this);
if(wParam != NULL)
{
pT->DoEraseBackground((HDC)wParam);
pT->DoPaint((HDC)wParam);
}
else
{
CPaintDC dc(m_hWnd);
pT->DoEraseBackground(dc.m_hDC);
pT->DoPaint(dc.m_hDC);
}
return 0;
}
LRESULT OnFocus(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
if(m_bPaintLabel)
Invalidate();
else
bHandled = FALSE;
return 0;
}
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& bHandled)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
{
::SetCursor(m_hCursor);
if(IsUnderlineHover())
{
if(!m_bHover)
{
m_bHover = true;
InvalidateRect(&m_rcLink);
UpdateWindow();
#ifndef _WIN32_WCE
StartTrackMouseLeave();
#endif // !_WIN32_WCE
}
}
}
else
{
if(IsUnderlineHover())
{
if(m_bHover)
{
m_bHover = false;
InvalidateRect(&m_rcLink);
UpdateWindow();
}
}
bHandled = FALSE;
}
return 0;
}
#ifndef _WIN32_WCE
LRESULT OnMouseLeave(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(IsUnderlineHover() && m_bHover)
{
m_bHover = false;
InvalidateRect(&m_rcLink);
UpdateWindow();
}
return 0;
}
#endif // !_WIN32_WCE
LRESULT OnLButtonDown(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if(::PtInRect(&m_rcLink, pt))
{
SetFocus();
SetCapture();
}
return 0;
}
LRESULT OnLButtonUp(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)
{
if(GetCapture() == m_hWnd)
{
ReleaseCapture();
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if(::PtInRect(&m_rcLink, pt))
{
T* pT = static_cast<T*>(this);
pT->Navigate();
}
}
return 0;
}
LRESULT OnChar(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(wParam == VK_RETURN || wParam == VK_SPACE)
{
T* pT = static_cast<T*>(this);
pT->Navigate();
}
return 0;
}
LRESULT OnGetDlgCode(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return DLGC_WANTCHARS;
}
LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
POINT pt = { 0, 0 };
GetCursorPos(&pt);
ScreenToClient(&pt);
if((m_lpstrHyperLink != NULL || IsCommandButton()) && ::PtInRect(&m_rcLink, pt))
{
return TRUE;
}
bHandled = FALSE;
return FALSE;
}
LRESULT OnEnable(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
Invalidate();
UpdateWindow();
return 0;
}
LRESULT OnGetFont(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
return (LRESULT)m_hFontNormal;
}
LRESULT OnSetFont(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
{
m_hFontNormal = (HFONT)wParam;
if((BOOL)lParam)
{
Invalidate();
UpdateWindow();
}
return 0;
}
LRESULT OnUpdateUiState(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
// If the control is subclassed or superclassed, this message can cause
// repainting without WM_PAINT. We don't use this state, so just do nothing.
return 0;
}
// Implementation
void Init()
{
ATLASSERT(::IsWindow(m_hWnd));
// Check if we should paint a label
const int cchBuff = 8;
TCHAR szBuffer[cchBuff] = { 0 };
if(::GetClassName(m_hWnd, szBuffer, cchBuff))
{
if(lstrcmpi(szBuffer, _T("static")) == 0)
{
ModifyStyle(0, SS_NOTIFY); // we need this
DWORD dwStyle = GetStyle() & 0x000000FF;
#ifndef _WIN32_WCE
if(dwStyle == SS_ICON || dwStyle == SS_BLACKRECT || dwStyle == SS_GRAYRECT ||
dwStyle == SS_WHITERECT || dwStyle == SS_BLACKFRAME || dwStyle == SS_GRAYFRAME ||
dwStyle == SS_WHITEFRAME || dwStyle == SS_OWNERDRAW ||
dwStyle == SS_BITMAP || dwStyle == SS_ENHMETAFILE)
#else // CE specific
if(dwStyle == SS_ICON || dwStyle == SS_BITMAP)
#endif // _WIN32_WCE
m_bPaintLabel = false;
}
}
// create or load a cursor
#if (WINVER >= 0x0500) || defined(_WIN32_WCE)
m_hCursor = ::LoadCursor(NULL, IDC_HAND);
#else
#if (_ATL_VER >= 0x0700)
m_hCursor = ::CreateCursor(ATL::_AtlBaseModule.GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane);
#else // !(_ATL_VER >= 0x0700)
m_hCursor = ::CreateCursor(_Module.GetModuleInstance(), _AtlHyperLink_CursorData.xHotSpot, _AtlHyperLink_CursorData.yHotSpot, _AtlHyperLink_CursorData.cxWidth, _AtlHyperLink_CursorData.cyHeight, _AtlHyperLink_CursorData.arrANDPlane, _AtlHyperLink_CursorData.arrXORPlane);
#endif // !(_ATL_VER >= 0x0700)
#endif
ATLASSERT(m_hCursor != NULL);
// set font
if(m_bPaintLabel)
{
ATL::CWindow wnd = GetParent();
m_hFontNormal = wnd.GetFont();
if(m_hFontNormal == NULL)
m_hFontNormal = (HFONT)::GetStockObject(SYSTEM_FONT);
if(m_hFontNormal != NULL && m_hFont == NULL)
{
LOGFONT lf = { 0 };
CFontHandle font = m_hFontNormal;
font.GetLogFont(&lf);
if(IsUsingTagsBold())
lf.lfWeight = FW_BOLD;
else if(!IsNotUnderlined())
lf.lfUnderline = TRUE;
m_hFont = ::CreateFontIndirect(&lf);
m_bInternalLinkFont = true;
ATLASSERT(m_hFont != NULL);
}
}
#ifndef _WIN32_WCE
// create a tool tip
m_tip.Create(m_hWnd);
ATLASSERT(m_tip.IsWindow());
#endif // !_WIN32_WCE
// set label (defaults to window text)
if(m_lpstrLabel == NULL)
{
int nLen = GetWindowTextLength();
if(nLen > 0)
{
LPTSTR lpszText = (LPTSTR)_alloca((nLen + 1) * sizeof(TCHAR));
if(GetWindowText(lpszText, nLen + 1))
SetLabel(lpszText);
}
}
T* pT = static_cast<T*>(this);
pT->CalcLabelRect();
// set hyperlink (defaults to label), or just activate tool tip if already set
if(m_lpstrHyperLink == NULL && !IsCommandButton())
{
if(m_lpstrLabel != NULL)
SetHyperLink(m_lpstrLabel);
}
#ifndef _WIN32_WCE
else
{
m_tip.Activate(TRUE);
m_tip.AddTool(m_hWnd, m_lpstrHyperLink, &m_rcLink, 1);
}
#endif // !_WIN32_WCE
// set link colors
if(m_bPaintLabel)
{
ATL::CRegKey rk;
LONG lRet = rk.Open(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Internet Explorer\\Settings"));
if(lRet == 0)
{
const int cchBuff = 12;
TCHAR szBuff[cchBuff] = { 0 };
#if (_ATL_VER >= 0x0700)
ULONG ulCount = cchBuff;
lRet = rk.QueryStringValue(_T("Anchor Color"), szBuff, &ulCount);
#else
DWORD dwCount = cchBuff * sizeof(TCHAR);
lRet = rk.QueryValue(szBuff, _T("Anchor Color"), &dwCount);
#endif
if(lRet == 0)
{
COLORREF clr = pT->_ParseColorString(szBuff);
ATLASSERT(clr != CLR_INVALID);
if(clr != CLR_INVALID)
m_clrLink = clr;
}
#if (_ATL_VER >= 0x0700)
ulCount = cchBuff;
lRet = rk.QueryStringValue(_T("Anchor Color Visited"), szBuff, &ulCount);
#else
dwCount = cchBuff * sizeof(TCHAR);
lRet = rk.QueryValue(szBuff, _T("Anchor Color Visited"), &dwCount);
#endif
if(lRet == 0)
{
COLORREF clr = pT->_ParseColorString(szBuff);
ATLASSERT(clr != CLR_INVALID);
if(clr != CLR_INVALID)
m_clrVisited = clr;
}
}
}
}
static COLORREF _ParseColorString(LPTSTR lpstr)
{
int c[3] = { -1, -1, -1 };
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -