📄 xhyperlink.cpp
字号:
// XHyperLink.cpp Version 1.0
//
// XHyperLink static control. Will open the default browser with the
// given URL when the user clicks on the link.
//
// Copyright (C) 1997 - 1999 Chris Maunder
// All rights reserved. May not be sold for profit.
//
// Thanks to P錶 K. T鴑der for auto-size and window caption changes.
//
// "GotoURL" function by Stuart Patterson
// As seen in the August, 1997 Windows Developer's Journal.
// Copyright 1997 by Miller Freeman, Inc. All rights reserved.
// Modified by Chris Maunder to use TCHARs instead of chars.
//
// "Default hand cursor" from Paul DiLascia's Jan 1998 MSJ article.
//
// 2/29/00 -- P. Shaffer standard font mod.
//
///////////////////////////////////////////////////////////////////////////////
//
// Modified by: Hans Dietrich
// hdietrich@gmail.com
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "XHyperLink.h"
#include "atlconv.h" // for Unicode conversion
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma warning(disable : 4996) // disable bogus deprecation warning
#define TOOLTIP_ID 1
// Uncomment following line to enable error message box for URL navigation
//#define XHYPERLINK_REPORT_ERROR
#ifndef IDC_HAND
#define IDC_HAND MAKEINTRESOURCE(32649) // From WINUSER.H
#endif
// sends message to parent when hyperlink is clicked (see SetNotifyParent())
UINT WM_XHYPERLINK_CLICKED = ::RegisterWindowMessage(_T("WM_XHYPERLINK_CLICKED"));
///////////////////////////////////////////////////////////////////////////////
// CXHyperLink
BEGIN_MESSAGE_MAP(CXHyperLink, CStatic)
//{{AFX_MSG_MAP(CXHyperLink)
ON_WM_CTLCOLOR_REFLECT()
ON_WM_SETCURSOR()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
ON_WM_ERASEBKGND()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
///////////////////////////////////////////////////////////////////////////////
// ctor
CXHyperLink::CXHyperLink()
{
m_hLinkCursor = NULL; // No cursor as yet
m_crLinkColour = RGB(0,0,238); // Blue
m_crVisitedColour = RGB(85,26,139); // Purple
m_crHoverColour = RGB(255,0,0); // Red
m_bOverControl = FALSE; // Cursor not yet over control
m_bVisited = FALSE; // Hasn't been visited yet.
m_nUnderline = ulHover; // Underline the link?
m_bAdjustToFit = TRUE; // Resize the window to fit the text?
m_strURL = _T("");
m_nTimerID = 100;
m_bNotifyParent = FALSE; // TRUE = notify parent
m_bIsURLEnabled = TRUE; // TRUE = navigate to url
m_bToolTip = TRUE; // TRUE = display tooltip
m_crBackground = (UINT) -1; // set to default (no bg color)
m_bAlwaysOpenNew = FALSE; // TRUE = always open new browser window
}
///////////////////////////////////////////////////////////////////////////////
// dtor
CXHyperLink::~CXHyperLink()
{
TRACE(_T("in CXHyperLink::~CXHyperLink\n"));
if (m_hLinkCursor)
DestroyCursor(m_hLinkCursor);
m_hLinkCursor = NULL;
m_UnderlineFont.DeleteObject();
if (m_Brush.GetSafeHandle())
m_Brush.DeleteObject();
}
/////////////////////////////////////////////////////////////////////////////
// CXHyperLink overrides
///////////////////////////////////////////////////////////////////////////////
// DestroyWindow
BOOL CXHyperLink::DestroyWindow()
{
KillTimer(m_nTimerID);
return CStatic::DestroyWindow();
}
///////////////////////////////////////////////////////////////////////////////
// PreTranslateMessage
BOOL CXHyperLink::PreTranslateMessage(MSG* pMsg)
{
m_ToolTip.RelayEvent(pMsg);
return CStatic::PreTranslateMessage(pMsg);
}
///////////////////////////////////////////////////////////////////////////////
// PreSubclassWindow
void CXHyperLink::PreSubclassWindow()
{
// We want to get mouse clicks via STN_CLICKED
DWORD dwStyle = GetStyle();
::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);
// Set the URL as the window text
if (m_strURL.IsEmpty())
GetWindowText(m_strURL);
// Check that the window text isn't empty. If it is, set it as the URL.
CString strWndText;
GetWindowText(strWndText);
if (strWndText.IsEmpty())
{
ASSERT(!m_strURL.IsEmpty()); // Window and URL both NULL. DUH!
SetWindowText(m_strURL);
}
CFont* pFont = GetFont();
if (!pFont)
{
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
if (hFont == NULL)
hFont = (HFONT) GetStockObject(ANSI_VAR_FONT);
if (hFont)
pFont = CFont::FromHandle(hFont);
}
ASSERT(pFont->GetSafeHandle());
// Create the underline font
LOGFONT lf;
pFont->GetLogFont(&lf);
m_StdFont.CreateFontIndirect(&lf);
lf.lfUnderline = (BYTE) TRUE;
m_UnderlineFont.CreateFontIndirect(&lf);
PositionWindow(); // Adjust size of window to fit URL if necessary
SetDefaultCursor(); // Try and load up a "hand" cursor
SetUnderline();
// Create the tooltip
if (m_bToolTip)
{
CRect rect;
GetClientRect(rect);
m_ToolTip.Create(this);
m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);
}
CStatic::PreSubclassWindow();
}
/////////////////////////////////////////////////////////////////////////////
// CXHyperLink message handlers
///////////////////////////////////////////////////////////////////////////////
// OnClicked
void CXHyperLink::OnClicked()
{
m_bOverControl = FALSE;
HINSTANCE result = (HINSTANCE)HINSTANCE_ERROR + 1;
if (m_bIsURLEnabled)
result = GotoURL(m_strURL, SW_SHOW, m_bAlwaysOpenNew);
m_bVisited = (result > (HINSTANCE)HINSTANCE_ERROR);
if (!m_bVisited)
{
MessageBeep(MB_ICONEXCLAMATION); // Unable to follow link
ReportError((int)result);
}
else
SetVisited(); // Repaint to show visited colour
NotifyParent();
}
///////////////////////////////////////////////////////////////////////////////
// CtlColor
#ifdef _DEBUG
HBRUSH CXHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)
#else
HBRUSH CXHyperLink::CtlColor(CDC* pDC, UINT /*nCtlColor*/)
#endif
{
ASSERT(nCtlColor == CTLCOLOR_STATIC);
if (m_bOverControl)
pDC->SetTextColor(m_crHoverColour);
else if (m_bVisited)
pDC->SetTextColor(m_crVisitedColour);
else
pDC->SetTextColor(m_crLinkColour);
// transparent text.
pDC->SetBkMode(TRANSPARENT);
if (m_Brush.GetSafeHandle())
{
pDC->SetBkColor(m_crBackground);
return (HBRUSH) m_Brush;
}
else
{
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
}
///////////////////////////////////////////////////////////////////////////////
// OnMouseMove
void CXHyperLink::OnMouseMove(UINT nFlags, CPoint point)
{
if (!m_bOverControl) // Cursor has just moved over control
{
m_bOverControl = TRUE;
if (m_nUnderline == ulHover)
SetFont(&m_UnderlineFont);
Invalidate();
SetTimer(m_nTimerID, 100, NULL);
}
CStatic::OnMouseMove(nFlags, point);
}
///////////////////////////////////////////////////////////////////////////////
// OnTimer
void CXHyperLink::OnTimer(UINT nIDEvent)
{
CPoint p(GetMessagePos());
ScreenToClient(&p);
CRect rect;
GetClientRect(rect);
if (!rect.PtInRect(p))
{
m_bOverControl = FALSE;
KillTimer(m_nTimerID);
if (m_nUnderline != ulAlways)
SetFont(&m_StdFont);
rect.bottom+=10;
InvalidateRect(rect);
}
CStatic::OnTimer(nIDEvent);
}
///////////////////////////////////////////////////////////////////////////////
// OnSetCursor
BOOL CXHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/)
{
if (m_hLinkCursor)
{
::SetCursor(m_hLinkCursor);
return TRUE;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////
// OnEraseBkgnd
BOOL CXHyperLink::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(rect);
if (m_crBackground != (UINT)-1)
pDC->FillSolidRect(rect, m_crBackground);
else
pDC->FillSolidRect(rect, ::GetSysColor(COLOR_3DFACE));
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CXHyperLink operations
///////////////////////////////////////////////////////////////////////////////
// SetURL
void CXHyperLink::SetURL(CString strURL)
{
m_strURL = strURL;
if (::IsWindow(GetSafeHwnd()))
{
PositionWindow();
m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
}
}
///////////////////////////////////////////////////////////////////////////////
// SetColours
void CXHyperLink::SetColours(COLORREF crLinkColour,
COLORREF crVisitedColour,
COLORREF crHoverColour /* = -1 */)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -