MFC:超链接文本(重绘CStatic)

来源:互联网 发布:文件档案管理系统软件 编辑:程序博客网 时间:2024/06/05 20:26

头文件 XHyperLink.h:

#ifndef XHYPERLINK_H#define XHYPERLINK_Hextern UINT WM_XHYPERLINK_CLICKED;class CXHyperLink : public CStatic{public:    CXHyperLink();    virtual ~CXHyperLink();public:    enum UnderLineOptions { ulHover = -1, ulNone = 0, ulAlways = 1};public:    void SetURL(CString strURL);    CString GetURL() const    {        return m_strURL;    }    void EnableURL(BOOL bFlag) { m_bIsURLEnabled = bFlag; }    BOOL IsURLEnabled() const { return m_bIsURLEnabled; }    void SetColours(COLORREF crLinkColour, COLORREF crVisitedColour, COLORREF crHoverColour = -1);    COLORREF GetLinkColour() const    {        return m_crLinkColour;    }    COLORREF GetVisitedColour() const    {        return m_crVisitedColour;    }    COLORREF GetHoverColour() const    {        return m_crHoverColour;    }    void SetBackgroundColour(COLORREF crBackground);    COLORREF GetBackgroundColour() const    {        return m_crBackground;    }    void SetVisited(BOOL bVisited = TRUE);    BOOL GetVisited() const    {        return m_bVisited;    }    void SetLinkCursor(HCURSOR hCursor);    HCURSOR CXHyperLink::GetLinkCursor() const    {        return m_hLinkCursor;    }    void SetUnderline(int nUnderline = ulHover);    int GetUnderline() const    {        return m_nUnderline;    }    void SetAutoSize(BOOL bAutoSize = TRUE);    BOOL GetAutoSize() const    {        return m_bAdjustToFit;    }    void SetNotifyParent(BOOL bFlag) { m_bNotifyParent = bFlag; }    BOOL GetNotifyParent() const { return m_bNotifyParent; }    void EnableTooltip(BOOL bFlag)    {        m_bToolTip = bFlag;        m_ToolTip.Activate(m_bToolTip);    }    BOOL IsTooltipEmabled() const    {        return m_bToolTip;    }    void SetAlwaysOpenNew(BOOL bFlag)    {        m_bAlwaysOpenNew = bFlag;    }    BOOL GetAlwaysOpenNew() const    {        return m_bAlwaysOpenNew;    }    void SetWindowText(LPCTSTR lpszString);public:    static HINSTANCE GotoURL(LPCTSTR url, int showcmd,  BOOL bAlwaysOpenNew = FALSE);public:    virtual BOOL PreTranslateMessage(MSG* pMsg);    virtual BOOL DestroyWindow();protected:    virtual void PreSubclassWindow();    static LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata);    void NotifyParent();    void PositionWindow();    void ReportError(int nError);    void SetDefaultCursor();protected:    COLORREF        m_crLinkColour;        // Hyperlink colours    COLORREF        m_crVisitedColour;    COLORREF        m_crHoverColour;    // Hover colour    COLORREF        m_crBackground;        // background color    CBrush            m_Brush;            // background brush    BOOL            m_bOverControl;        // cursor over control?    BOOL            m_bVisited;            // Has it been visited?    int                m_nUnderline;        // underline hyperlink?    BOOL            m_bAdjustToFit;        // Adjust window size to fit text?    CString            m_strURL;            // hyperlink URL    CFont            m_UnderlineFont;    // Font for underline display    CFont            m_StdFont;            // Standard font    HCURSOR            m_hLinkCursor;        // Cursor for hyperlink    CToolTipCtrl    m_ToolTip;            // The tooltip    UINT            m_nTimerID;    BOOL            m_bIsURLEnabled;    // TRUE = navigate to url    BOOL            m_bNotifyParent;    // TRUE = notify parent    BOOL            m_bToolTip;            // TRUE = display tooltip    BOOL            m_bAlwaysOpenNew;    // TRUE = always open new browser windowprotected:    afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);    afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);    afx_msg void OnMouseMove(UINT nFlags, CPoint point);    afx_msg BOOL OnEraseBkgnd(CDC* pDC);    afx_msg void OnTimer(UINT nIDEvent);    afx_msg void OnClicked();    DECLARE_MESSAGE_MAP()};#endif //XHYPERLINK_H

源文件 XHyperLink.cpp:

#include "stdafx.h"#include "XHyperLink.h"#include "atlconv.h"        // for Unicode conversion#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif#define TOOLTIP_ID 1#ifndef IDC_HAND#define IDC_HAND MAKEINTRESOURCE(32649)   // From WINUSER.H#endifUINT WM_XHYPERLINK_CLICKED = ::RegisterWindowMessage(_T("WM_XHYPERLINK_CLICKED"));BEGIN_MESSAGE_MAP(CXHyperLink, CStatic)    ON_WM_CTLCOLOR_REFLECT()    ON_WM_SETCURSOR()    ON_WM_MOUSEMOVE()    ON_WM_TIMER()    ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)    ON_WM_ERASEBKGND()END_MESSAGE_MAP()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}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();}BOOL CXHyperLink::DestroyWindow(){    KillTimer(m_nTimerID);    return CStatic::DestroyWindow();}BOOL CXHyperLink::PreTranslateMessage(MSG* pMsg){    m_ToolTip.RelayEvent(pMsg);    return CStatic::PreTranslateMessage(pMsg);}void CXHyperLink::PreSubclassWindow(){    DWORD dwStyle = GetStyle();    ::SetWindowLong(GetSafeHwnd(), GWL_STYLE, dwStyle | SS_NOTIFY);    if (m_strURL.IsEmpty())        GetWindowText(m_strURL);    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();}void CXHyperLink::OnClicked(){    m_bOverControl = FALSE;    int result = HINSTANCE_ERROR + 1;    if (m_bIsURLEnabled)    {        result = (int)GotoURL(m_strURL, SW_SHOW, m_bAlwaysOpenNew);    }    m_bVisited = (result > HINSTANCE_ERROR);    if (!m_bVisited)    {        MessageBeep(MB_ICONEXCLAMATION);     // Unable to follow link        ReportError(result);    }    else    {        SetVisited();                        // Repaint to show visited colour    }    NotifyParent();}#ifdef _DEBUGHBRUSH CXHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)#elseHBRUSH 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);    }}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);}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);}BOOL CXHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/){    if (m_hLinkCursor)    {        ::SetCursor(m_hLinkCursor);        return TRUE;    }    return FALSE;}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;}void CXHyperLink::SetURL(CString strURL){    m_strURL = strURL;    if (::IsWindow(GetSafeHwnd()))    {        PositionWindow();        m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);    }}void CXHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour, COLORREF crHoverColour /* = -1 */){    m_crLinkColour    = crLinkColour;    m_crVisitedColour = crVisitedColour;    if (crHoverColour == -1)        m_crHoverColour = ::GetSysColor(COLOR_HIGHLIGHT);    else        m_crHoverColour = crHoverColour;    if (::IsWindow(m_hWnd))    {        Invalidate();    }}void CXHyperLink::SetBackgroundColour(COLORREF crBackground){    m_crBackground = crBackground;    if (m_Brush.GetSafeHandle())        m_Brush.DeleteObject();    m_Brush.CreateSolidBrush(m_crBackground);}void CXHyperLink::SetVisited(BOOL bVisited /* = TRUE */){    m_bVisited = bVisited;    if (::IsWindow(GetSafeHwnd()))        Invalidate();}void CXHyperLink::SetLinkCursor(HCURSOR hCursor){    m_hLinkCursor = hCursor;    if (m_hLinkCursor == NULL)        SetDefaultCursor();}void CXHyperLink::SetUnderline(int nUnderline /*=ulHover*/){    if (m_nUnderline == nUnderline)        return;    if (::IsWindow(GetSafeHwnd()))    {        if (nUnderline == ulAlways)            SetFont(&m_UnderlineFont);        else            SetFont(&m_StdFont);        Invalidate();    }    m_nUnderline = nUnderline;}void CXHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */){    m_bAdjustToFit = bAutoSize;    if (::IsWindow(GetSafeHwnd()))        PositionWindow();}void CXHyperLink::SetWindowText(LPCTSTR lpszString){    ASSERT(lpszString);    if (!lpszString)        return;    CStatic::SetWindowText(_T(""));    RedrawWindow();    CStatic::SetWindowText(lpszString);    PositionWindow();}void CXHyperLink::PositionWindow(){    if (!::IsWindow(GetSafeHwnd()) || !m_bAdjustToFit)        return;    CRect WndRect, ClientRect;    GetWindowRect(WndRect);    GetClientRect(ClientRect);    ClientToScreen(ClientRect);    CWnd* pParent = GetParent();    if (pParent)    {        pParent->ScreenToClient(WndRect);        pParent->ScreenToClient(ClientRect);    }    CString strWndText;    GetWindowText(strWndText);    CDC* pDC = GetDC();    CFont* pOldFont = pDC->SelectObject(&m_UnderlineFont);    CSize Extent = pDC->GetTextExtent(strWndText);    pDC->SelectObject(pOldFont);    ReleaseDC(pDC);    Extent.cx += WndRect.Width() - ClientRect.Width();    Extent.cy += WndRect.Height() - ClientRect.Height();    DWORD dwStyle = GetStyle();    if (dwStyle & SS_CENTERIMAGE)        WndRect.DeflateRect(0, (WndRect.Height() - Extent.cy)/2);    else        WndRect.bottom = WndRect.top + Extent.cy;    if (dwStyle & SS_CENTER)        WndRect.DeflateRect((WndRect.Width() - Extent.cx)/2, 0);    else if (dwStyle & SS_RIGHT)        WndRect.left = WndRect.right - Extent.cx;    else        WndRect.right = WndRect.left + Extent.cx;    SetWindowPos(NULL, WndRect.left, WndRect.top, WndRect.Width(), WndRect.Height(), SWP_NOZORDER);}void CXHyperLink::SetDefaultCursor(){    if (m_hLinkCursor == NULL)    {        TRACE(_T("loading from IDC_HAND\n"));        m_hLinkCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);        if (m_hLinkCursor == NULL)        {            TRACE(_T("loading from winhlp32\n"));            // Get the windows directory            CString strWndDir;            GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH), MAX_PATH);            strWndDir.ReleaseBuffer();            strWndDir += _T("\\winhlp32.exe");            HMODULE hModule = LoadLibrary(strWndDir);            if (hModule)            {                HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106));                if (hHandCursor)                {                    m_hLinkCursor = CopyCursor(hHandCursor);                }                FreeLibrary(hModule);            }        }    }}LONG CXHyperLink::GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata){    HKEY hkey;    LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey);    if (retval == ERROR_SUCCESS)    {        long datasize = MAX_PATH;        TCHAR data[MAX_PATH];        RegQueryValue(hkey, NULL, data, &datasize);        _tcscpy_s(retdata, MAX_PATH + 1, data);        RegCloseKey(hkey);    }    return retval;}void CXHyperLink::ReportError(int nError){#ifdef XHYPERLINK_REPORT_ERROR    CString str;    switch (nError)    {    case 0:                            str = "The operating system is out\nof memory or resources."; break;    case SE_ERR_PNF:                str = "The specified path was not found."; break;    case SE_ERR_FNF:                str = "The specified file was not found."; break;    case ERROR_BAD_FORMAT:            str = "The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image)."; break;    case SE_ERR_ACCESSDENIED:        str = "The operating system denied\naccess to the specified file."; break;    case SE_ERR_ASSOCINCOMPLETE:    str = "The filename association is\nincomplete or invalid."; break;    case SE_ERR_DDEBUSY:            str = "The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed."; break;    case SE_ERR_DDEFAIL:            str = "The DDE transaction failed."; break;    case SE_ERR_DDETIMEOUT:            str = "The DDE transaction could not\nbe completed because the request timed out."; break;    case SE_ERR_DLLNOTFOUND:        str = "The specified dynamic-link library was not found."; break;    case SE_ERR_NOASSOC:            str = "There is no application associated\nwith the given filename extension."; break;    case SE_ERR_OOM:                str = "There was not enough memory to complete the operation."; break;    case SE_ERR_SHARE:                str = "A sharing violation occurred. ";    default:                        str.Format(_T("Unknown Error (%d) occurred."), nError); break;    }    str = "Unable to open hyperlink:\n\n" + str;    AfxMessageBox(str, MB_ICONEXCLAMATION | MB_OK);#else    UNUSED_ALWAYS(nError);#endif    // XHYPERLINK_REPORT_ERROR}void CXHyperLink::NotifyParent(){    if (m_bNotifyParent)    {        CWnd *pParent = GetParent();        if (pParent && ::IsWindow(pParent->m_hWnd))        {            pParent->SendMessage(WM_XHYPERLINK_CLICKED, GetDlgCtrlID());        }    }}HINSTANCE CXHyperLink::GotoURL(LPCTSTR url, int showcmd, BOOL bAlwaysOpenNew /*= FALSE*/){    if (!url || url[0] == _T('\0'))        return (HINSTANCE) HINSTANCE_ERROR + 1;    TCHAR key[MAX_PATH*2];    TCHAR *verb = _T("open");    if (bAlwaysOpenNew)        verb = _T("new");    HINSTANCE result = ShellExecute(NULL, verb, url, NULL,NULL, showcmd);    if ((UINT)result <= HINSTANCE_ERROR)    {        if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS)        {            _tcscat_s(key, _T("\\shell\\open\\command"));            if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS)            {                TCHAR *pos;                pos = _tcsstr(key, _T("\"%1\""));                if (pos == NULL)                {                    pos = _tcsstr(key, _T("%1"));        // Check for %1, without quotes                    if (pos == NULL)                    // No parameter at all...                        pos = key + _tcslen(key)-1;                    else                        *pos = _T('\0');                // Remove the parameter                }                else                {                    *pos = _T('\0');                    // Remove the parameter                }                _tcscat(pos, _T(" "));                _tcscat(pos, url);                USES_CONVERSION;                result = (HINSTANCE) WinExec(T2A(key),showcmd);            }        }    }    return result;}


用法:

在对话框头文件中添加一个继承CXHyperLink的变量:    CXHyperLink m_ctrlWebStatic;

m_ctrlWebStatic.SetWindowText(_T("百度"));
m_ctrlWebStatic.SetURL(_T("www.baidu.com"));

1 0