📄 hyperlink.cpp
字号:
// HyperLink.cpp : implementation file
//
#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_iHyperLinkSort=HLS_MAIL;
m_hLinkCursor=NULL; //无光标
m_crLinkColour=RGB(0,0,255); //蓝色
m_crVisitedColour=RGB(0,255,0); //紫色
m_crHoverColour=RGB(255,0,0);
m_bOverControl=FALSE; // Cursor not yet over control
m_bVisited=FALSE; //未访问
m_bUnderline=1; //有下划线
m_bAdjustToFit=TRUE; // Resize the window to fit the text?
m_strURL.Empty();
}
CHyperLink::~CHyperLink()
{
m_Font.DeleteObject();
}
BEGIN_MESSAGE_MAP(CHyperLink, CStatic)
//{{AFX_MSG_MAP(CHyperLink)
ON_WM_CTLCOLOR_REFLECT()
ON_WM_SETCURSOR()
ON_WM_MOUSEMOVE()
ON_CONTROL_REFLECT(STN_CLICKED, OnClicked)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CHyperLink message handlers
BOOL CHyperLink::PreTranslateMessage(MSG* pMsg)
{
// TODO: Add your specialized code here and/or call the base class
m_ToolTip.RelayEvent(pMsg);
return CStatic::PreTranslateMessage(pMsg);
}
void CHyperLink::OnClicked()
{
if(m_iHyperLinkSort==HLS_MAIL)
{
GotoMail(m_strMail,SW_SHOW);
SetVisited();
return;
}
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
}
void CHyperLink::PreSubclassWindow()
{
// TODO: Add your specialized code here and/or call the base class
// 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);
}
//Create the font
LOGFONT lf;
GetFont()->GetLogFont(&lf);
lf.lfUnderline=m_bUnderline;
m_Font.CreateFontIndirect(&lf);
SetFont(&m_Font);
PositionWindow(); // Adjust size of window to fit URL if necessary
SetDefaultCursor(); // Try and load up a "hand" cursor
//Create the tooltip
CRect rect;
GetClientRect(rect);
m_ToolTip.Create(this);
m_ToolTip.AddTool(this,m_strURL,rect,TOOLTIP_ID);
CStatic::PreSubclassWindow();
}
HBRUSH CHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)
{
// TODO: Change any attributes of the DC here
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);
return (HBRUSH)GetStockObject(NULL_BRUSH);
}
BOOL CHyperLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
if (m_hLinkCursor)
{
::SetCursor(m_hLinkCursor);
return TRUE;
}
return FALSE;
}
void CHyperLink::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CStatic::OnMouseMove(nFlags, point);
if(m_bOverControl)// Cursor is currently over control
{
CRect rect;
GetClientRect(rect);
if(!rect.PtInRect(point))
{
m_bOverControl=FALSE;
ReleaseCapture();
RedrawWindow();
return;
}
}
else//Cursor has just moved over control
{
m_bOverControl=TRUE;
RedrawWindow();
SetCapture();
}
}
/////////////////////////////////////////////////////////
//CHyperLink operations
void CHyperLink::SetURL(CString strURL)
{
m_strURL=strURL;
m_iHyperLinkSort=HLS_URL;
if(::IsWindow(GetSafeHwnd()))
{
PositionWindow();
m_ToolTip.UpdateTipText(strURL,this,TOOLTIP_ID);
}
}
void CHyperLink::SetMail(CString strMail)
{
m_strMail=strMail;
m_iHyperLinkSort=HLS_MAIL;
if(::IsWindow(GetSafeHwnd()))
{
PositionWindow();
m_ToolTip.UpdateTipText(strMail,this,TOOLTIP_ID);
}
}
void CHyperLink::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 CHyperLink::SetVisited(BOOL bVisited /* = TRUE */)
{
m_bVisited = bVisited;
if (::IsWindow(GetSafeHwnd()))
Invalidate();
}
void CHyperLink::SetLinkCursor(HCURSOR hCursor)
{
m_hLinkCursor = hCursor;
if (m_hLinkCursor == NULL)
SetDefaultCursor();
}
void CHyperLink::SetUnderline(BOOL bUnderline /* = TRUE */)
{
m_bUnderline=bUnderline;
if(::IsWindow(GetSafeHwnd()))
{
LOGFONT lf;
GetFont()->GetLogFont(&lf);
lf.lfUnderline = m_bUnderline;
m_Font.DeleteObject();
m_Font.CreateFontIndirect(&lf);
SetFont(&m_Font);
Invalidate();
}
}
void CHyperLink::SetAutoSize(BOOL bAutoSize /* = TRUE */)
{
m_bAdjustToFit=bAutoSize;
if(::IsWindow(GetSafeHwnd()))
PositionWindow();
}
void CHyperLink::PositionWindow()
{
if (!::IsWindow(GetSafeHwnd()) || !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();
CFont* pOldFont=pDC->SelectObject(&m_Font);
CSize Extent=pDC->GetTextExtent(strWndText);
pDC->SelectObject(pOldFont);
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
// The following appeared in Paul DiLascia's Jan 1998 MSJ articles.
// It loads a "hand" cursor from the winhlp32.exe module
void CHyperLink::SetDefaultCursor()
{
if(m_hLinkCursor == NULL) // No cursor handle - load our own
{
// Get the windows directory
CString strWndDir;
GetWindowsDirectory(strWndDir.GetBuffer(MAX_PATH),MAX_PATH);
strWndDir.ReleaseBuffer();
strWndDir+=_T("\\winhlp32.exe");
// This retrieves cursor #106 from winhlp32.exe, which is a hand pointer
HMODULE hModule = LoadLibrary(strWndDir);
if(hModule)
{
HCURSOR hHandCursor=::LoadCursor(hModule, MAKEINTRESOURCE(106));
if (hHandCursor)
m_hLinkCursor=CopyCursor(hHandCursor);
}
FreeLibrary(hModule);
}
}
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("Unknown Error (%d) occurred.",nError);
break;
}
str="Unable to open hyperlink:\n\n"+str;
AfxMessageBox(str,MB_ICONEXCLAMATION | MB_OK);
}
HINSTANCE CHyperLink::GotoURL(LPCTSTR url, int showcmd)
{
TCHAR key[MAX_PATH + MAX_PATH];
// First try ShellExecute()
HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd);
// If it failed, get the .htm regkey and lookup the program
if((UINT)result <= HINSTANCE_ERROR)
{
if(GetRegKey(HKEY_CLASSES_ROOT,_T(".htm"), key)==ERROR_SUCCESS)
{
lstrcat(key, _T("\\shell\\open\\command"));
if(GetRegKey(HKEY_CLASSES_ROOT,key,key)==ERROR_SUCCESS)
{
TCHAR *pos;
pos=_tcsstr(key,_T("\"%1\""));
if(pos == NULL)//No quotes found
{
pos=strstr(key,_T("%1"));// Check for %1, without quotes
if(pos==NULL)// No parameter at all...
pos=key+lstrlen(key)-1;
else
*pos='\0';// Remove the parameter
}
else
*pos='\0';// Remove the parameter
lstrcat(pos,_T(" "));
lstrcat(pos,url);
result=(HINSTANCE)WinExec(key,showcmd);
}
}
}
return result;
}
void CHyperLink::GotoMail(CString strMail,int iShowCmd)
{
ShellExecute(NULL,"open","mailto:"+strMail,"","",iShowCmd);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -