现在的位置: 首页 > 综合 > 正文

从静态框派生的超链接控件

2013年10月05日 ⁄ 综合 ⁄ 共 7699字 ⁄ 字号 评论关闭
// HyperLink.h : header file
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.

#pragma once

/////////////////////////////////////////////////////////////////////////////
// CHyperLink window

class CHyperLink : public CStatic
{
  // Construction/destruction
public:
  CHyperLink();
  virtual ~CHyperLink();

  // Attributes
public:

  // Operations
public:

  void SetURL(CString strURL);
  CString GetURL()			{ return m_strURL;   }

  void SetColours(COLORREF crLinkColour, COLORREF crVisitedColour);
  COLORREF GetLinkColour()	{ return m_crLinkColour; }
  COLORREF GetVisitedColour()	{ return m_crVisitedColour; }

  void SetVisited(BOOL bVisited = TRUE);
  BOOL GetVisited()			{ return m_bVisited; }

  void SetLinkCursor(HCURSOR hCursor) { m_hLinkCursor = hCursor; }

  void SetUnderline(BOOL bUnderline = TRUE);
  BOOL GetUnderline()			{ return m_bUnderline; }

  void SetAutoSize(BOOL bAutoSize = TRUE);
  BOOL GetAutoSize()			{ return m_bAdjustToFit; }

  // Overrides
  // ClassWizard generated virtual function overrides
  //{{AFX_VIRTUAL(CHyperLink)
public:
  virtual BOOL PreTranslateMessage(MSG* pMsg);
protected:
  virtual void PreSubclassWindow();
  //}}AFX_VIRTUAL

  // Implementation
protected:
  HINSTANCE GotoURL(LPCTSTR url, int showcmd);
  void ReportError(int nError);
  LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata);
  void PositionWindow();

  // Protected attributes
protected:
  COLORREF m_crLinkColour, m_crVisitedColour;		// Hyperlink colours
  BOOL     m_bVisited;							// Has it been visited?
  BOOL	 m_bUnderline;							// underline hyperlink?
  BOOL	 m_bAdjustToFit;						// Adjust window size to fit text?
  CString  m_strURL;								// hyperlink URL
  CFont	 m_Font;								// Underline font if necessary
  HCURSOR  m_hLinkCursor;							// Cursor for hyperlink
  CToolTipCtrl m_ToolTip;							// The tooltip

  // Generated message map functions
protected:
  //{{AFX_MSG(CHyperLink)
  afx_msg HBRUSH CtlColor(CDC* pDC, UINT nCtlColor);
  afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
  afx_msg void OnClicked();
  //}}AFX_MSG
  DECLARE_MESSAGE_MAP()
};

 

// HyperLink.cpp : implementation file
//
// HyperLink static control. Will open the default browser with the given URL
// when the user clicks on the link.

#include "stdafx.h"
#include "HyperLink.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define TOOLTIP_ID 1

/////////////////////////////////////////////////////////////////////////////
// CHyperLink

CHyperLink::CHyperLink()
{
  m_crLinkColour      = RGB(0, 0, 238);     // Blue
  m_crVisitedColour   = RGB(85, 26, 139);   // Purple
  m_bVisited          = FALSE;              // Hasn't been visited yet.
  m_bUnderline        = TRUE;               // Underline the link?
  m_bAdjustToFit      = TRUE;               // Resize the window to fit the text?
  m_strURL.Empty();  
}

CHyperLink::~CHyperLink()
{
  if ((HFONT)m_Font)
    m_Font.DeleteObject();
}


BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
  //{{AFX_MSG_MAP(CHyperLink)
  ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
  ON_WM_CTLCOLOR_REFLECT()
  ON_WM_SETCURSOR()
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CHyperLink message handlers

BOOL CHyperLink::PreTranslateMessage(MSG* pMsg) 
{
  m_ToolTip.RelayEvent(pMsg);
  return CStatic::PreTranslateMessage(pMsg);
}

HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor) 
{
  ASSERT(nCtlColor == CTLCOLOR_STATIC);

  // Set the approriate colour
  if (m_bVisited)
    pDC->SetTextColor(m_crVisitedColour);
  else
    pDC->SetTextColor(m_crLinkColour);

  // Set underline font if required
  if (m_bUnderline) 
  {
    if (!(HFONT)m_Font) 
    {			// Create font only once.
      LOGFONT lf;
      GetFont()->GetLogFont(&lf);
      lf.lfUnderline = TRUE;
      m_Font.CreateFontIndirect(&lf);
    }

    pDC->SelectObject(&m_Font);
  }

  // transparent text.
  pDC->SetBkMode(TRANSPARENT);
  return (HBRUSH)GetStockObject(NULL_BRUSH);
}

BOOL CHyperLink::OnSetCursor(CWnd* /*pWnd*/, UINT /*nHitTest*/, UINT /*message*/) 
{
  ::SetCursor(m_hLinkCursor);
  return TRUE;
}

void CHyperLink::PreSubclassWindow() 
{
  // We want to get mouse clicks via STN_CLICKED
  DWORD dwStyle = GetStyle();
  ::SetWindowLong(m_hWnd, 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 empty. DUH!
    SetWindowText(m_strURL);
  }

  // Adjust size of window to fit URL if necessary
  PositionWindow();		

  // Load up the (standard) hyperlink cursor
  m_hLinkCursor = AfxGetApp()->LoadStandardCursor(IDC_HAND);

  // Create the tooltip
  CRect rect; 
  GetClientRect(rect);
  m_ToolTip.Create(this);
  m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID);

  CStatic::PreSubclassWindow();
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink operations

void CHyperLink::SetURL(CString strURL)
{
  m_strURL = strURL;
  PositionWindow();
  m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID);
}

void CHyperLink::SetColours(COLORREF crLinkColour, COLORREF crVisitedColour) 
{ 
  m_crLinkColour    = crLinkColour; 
  m_crVisitedColour = crVisitedColour; 
  Invalidate(); 
}

void CHyperLink::SetVisited(BOOL bVisited /* = TRUE */) 
{ 
  m_bVisited = bVisited; 
  Invalidate(); 
}

void CHyperLink::SetUnderline(BOOL bUnderline /* = TRUE */)
{
  m_bUnderline = bUnderline; 
  Invalidate(); 
}

void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
{
  m_bAdjustToFit = bAutoSize;
  PositionWindow();
}

void CHyperLink::PositionWindow()
{
  if (!m_bAdjustToFit) 
    return;

  // Get the current window position
  CRect rect;
  GetWindowRect(rect);

  CWnd* pParent = GetParent();
  if (pParent)
    pParent->ScreenToClient(rect);

  // Get the size of the window text
  CString strWndText;
  GetWindowText(strWndText);

  CDC* pDC = GetDC();
  CSize Extent = pDC->GetTextExtent(strWndText);
  ReleaseDC(pDC);

  // Get the text justification via the window style
  DWORD dwStyle = GetStyle();

  // Recalc the window size and position based on the text justification
  if (dwStyle & SS_CENTERIMAGE)
    rect.DeflateRect(0, (rect.Height() - Extent.cy)/2);
  else
    rect.bottom = rect.top + Extent.cy;

  if (dwStyle & SS_CENTER)   
    rect.DeflateRect((rect.Width() - Extent.cx)/2, 0);
  else if (dwStyle & SS_RIGHT) 
    rect.left  = rect.right - Extent.cx;
  else // SS_LEFT = 0, so we can't test for it explicitly 
    rect.right = rect.left + Extent.cx;

  // Move the window
  SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(), SWP_NOZORDER);
}

/////////////////////////////////////////////////////////////////////////////
// CHyperLink implementation

void CHyperLink::OnClicked()
{
  int result = (int)GotoURL(m_strURL, SW_SHOW);
  m_bVisited = (result > HINSTANCE_ERROR);
  if (!m_bVisited) 
  {
    MessageBeep(MB_ICONEXCLAMATION);	// Unable to follow link
    ReportError(result);
  } else 
    SetVisited();						// Repaint to show visited colour
}

LONG CHyperLink::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);
    lstrcpy(retdata,data);
    RegCloseKey(hkey);
  }

  return retval;
}

void CHyperLink::ReportError(int nError)
{
  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 = _T("Unable to open hyperlink:\n\n") + str;
  AfxMessageBox(str, MB_ICONEXCLAMATION | MB_OK);
}

HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
  // First try ShellExecute()
  HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);

  return result;
}

 

【上篇】
【下篇】

抱歉!评论已关闭.