www.pudn.com > mu_explorer.rar > BBHyperLink.cpp


// BBHyperLink.cpp : implementation file 
// 
 
#include "stdafx.h" 
#include "BBHyperLink.h" 
 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#undef THIS_FILE 
static char THIS_FILE[] = __FILE__; 
#endif 
 
///////////////////////////////////////////////////////////////////////////// 
// CBBHyperLink 
 
#define TOOLTIP_ID 1 
 
//设置风格位操作 
#define SETBITS(dw, bits)	(dw |= bits) 
//去掉风格位操作 
#define CLEARBITS(dw, bits)	(dw &= ~(bits)) 
//判断风格位操作 
#define BITSET(dw, bit)		(((dw) & (bit)) != 0L) 
 
///////////////////////////////////////////////////////////////////////////// 
// CBBHyperLink 
 
const DWORD CBBHyperLink::STYLEUNDERLINE		 = 0x00000001;		// 下划线 
const DWORD CBBHyperLink::STYLEUSEHOVER		 = 0x00000002;		// 鼠标的掠过颜色风格 
const DWORD CBBHyperLink::STYLEAUTOSIZE	  	 = 0x00000004;		// 自动调整大小 
const DWORD CBBHyperLink::STYLEDOWNCLICK		 = 0x00000008;		// 鼠标按下代表单击风格 
const DWORD CBBHyperLink::STYLEGETFOCUSONCLICK = 0x00000010;		// 单击时候得到光标 
const DWORD CBBHyperLink::STYLENOHANDCURSOR	 = 0x00000020;		// 没有设置光标 
const DWORD CBBHyperLink::STYLENOACTIVECOLOR	 = 0x00000040;		// 没有活动时设置颜色 
 
//默认的颜色 
COLORREF CBBHyperLink::m_crLinkColor		= RGB(0, 0, 255);	 
COLORREF CBBHyperLink::m_crActiveColor	= RGB(0, 128, 128);	 
COLORREF CBBHyperLink::m_crVisitedColor	= RGB(128, 0, 128);	 
COLORREF CBBHyperLink::m_crHoverColor		= RGB(255, 0, 0	);	 
 
HCURSOR	 CBBHyperLink::m_hLinkCursor		= NULL;				 
 
CBBHyperLink::CBBHyperLink() 
{ 
	m_bOverControl		= FALSE;	// 光标不在控件上 
	m_bVisited			= FALSE;	// 可见 
	m_bLinkActive		= FALSE;	// 活动 
	m_strURL.Empty();				// URL 
	// 设置默认的风格 
	m_dwStyle = STYLEUNDERLINE|STYLEAUTOSIZE|STYLEGETFOCUSONCLICK; 
} 
 
CBBHyperLink::~CBBHyperLink() 
{ 
    m_Font.DeleteObject(); 
} 
 
IMPLEMENT_DYNAMIC(CBBHyperLink, CStatic) 
 
BEGIN_MESSAGE_MAP(CBBHyperLink, CStatic) 
    //{{AFX_MSm_MAP(CBBHyperLink) 
    ON_WM_CTLCOLOR_REFLECT() 
    ON_WM_SETCURSOR() 
    ON_WM_MOUSEMOVE() 
	ON_WM_LBUTTONUP() 
	ON_WM_SETFOCUS() 
	ON_WM_KILLFOCUS() 
	ON_WM_KEYDOWN() 
	ON_WM_NCHITTEST() 
	ON_WM_LBUTTONDOWN()	 
	//}}AFX_MSm_MAP 
END_MESSAGE_MAP() 
 
///////////////////////////////////////////////////////////////////////////// 
// CBBHyperLink message handlers 
 
BOOL CBBHyperLink::PreTranslateMessage(MSG* pMsg)  
{ 
    m_ToolTip.RelayEvent(pMsg); 
    return CStatic::PreTranslateMessage(pMsg); 
} 
 
void CBBHyperLink::PreSubclassWindow()  
{		     
	// 如果URL为空,以显示文本为连接对象 
    if (m_strURL.IsEmpty()) 
        GetWindowText(m_strURL); 
 
    //检查是否为空 
    CString strWndText; 
    GetWindowText(strWndText); 
    if (strWndText.IsEmpty())  
	{	 
        //ASSERT(!m_strURL.IsEmpty());     
		CStatic::SetWindowText(m_strURL); 
    } 
 
    //得到字体 
    CFont* pFont = GetFont();	 
	 
	if (pFont != NULL)  
	{ 
		LOGFONT lf; 
		pFont->GetLogFont(&lf); 
		lf.lfUnderline = BITSET(m_dwStyle, STYLEUNDERLINE); 
		if (m_Font.CreateFontIndirect(&lf)) 
			CStatic::SetFont(&m_Font);     
		//调整窗口的大小,以适应字体的全部可见 
		AdjustWindow(); 
	} 
	else  
	{				 
		//如果没有得到字体,说明本控件不是一个Text类型的, 
		//把其设置成自动伸缩 
		CLEARBITS(m_dwStyle,STYLEAUTOSIZE); 
	} 
	 
	if (!BITSET(m_dwStyle,STYLENOHANDCURSOR)) 
		SetDefaultCursor();      
 
    //提示 
    CRect rect;  
    GetClientRect(rect); 
    m_ToolTip.Create(this);	 
    m_ToolTip.AddTool(this, m_strURL, rect, TOOLTIP_ID); 
 
    CStatic::PreSubclassWindow(); 
} 
 
//设置字体和颜色 
HBRUSH CBBHyperLink::CtlColor(CDC* pDC, UINT nCtlColor)  
{		 
	ASSERT(nCtlColor == CTLCOLOR_STATIC); 
 
	if (m_bOverControl && BITSET(m_dwStyle,STYLEUSEHOVER)) 
	{ 
		pDC->SetTextColor(m_crHoverColor); 
	} 
	else if (!BITSET(m_dwStyle,STYLENOACTIVECOLOR) && m_bLinkActive) 
	{ 
		pDC->SetTextColor(m_crActiveColor); 
	} 
	else if (m_bVisited) 
	{ 
		pDC->SetTextColor(m_crVisitedColor); 
	} 
	else 
	{ 
		pDC->SetTextColor(m_crLinkColor); 
	} 
	 
	pDC->SetBkMode(TRANSPARENT); 
	return (HBRUSH)GetStockObject(NULL_BRUSH); 
} 
 
void CBBHyperLink::OnMouseMove(UINT nFlags, CPoint point)  
{ 
	if (m_bOverControl)        // 当前在 
	{ 
		CRect rect; 
		GetClientRect(rect); 
 
		if (!rect.PtInRect(point)) 
		{ 
			m_bOverControl = FALSE; 
			ReleaseCapture(); 
			Invalidate();						 
			return; 
		}			 
	} 
	else                      // 光标已经离开 
	{ 
		m_bOverControl = TRUE; 
		Invalidate();		 
		SetCapture();		 
	} 
} 
 
//通常,如果没有SS_NOTIFY,Static控件得不到到鼠标事件, 
//本函数完成了与SS_NOTIFY 
//的效果,但在调用OnCtlColor时打开SS_NOTIFY更可靠,因为在Bitamap风格的Static中没有 
//发送WM_CTLCOLOR的消息 
 
UINT CBBHyperLink::OnNcHitTest(CPoint point)  
{ 
	return HTCLIENT;	 
} 
 
void CBBHyperLink::OnLButtonDown(UINT nFlags, CPoint point)  
{ 
	if (BITSET(m_dwStyle,STYLEGETFOCUSONCLICK)) 
	{ 
		SetFocus();				 
	} 
	if (BITSET(m_dwStyle,STYLEDOWNCLICK)) 
	{ 
		FollowLink(); 
	} 
	m_bLinkActive = TRUE; 
} 
 
void CBBHyperLink::OnLButtonUp(UINT nFlags, CPoint point)  
{ 
	if (m_bLinkActive && !BITSET(m_dwStyle,STYLEDOWNCLICK)) 
		FollowLink(); 
} 
 
BOOL CBBHyperLink::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)  
{	 
	if (m_hLinkCursor) 
	{ 
		::SetCursor(m_hLinkCursor); 
		return TRUE; 
	} 
	return FALSE; 
} 
 
void CBBHyperLink::OnSetFocus(CWnd* pOldWnd)  
{ 
	m_bLinkActive = TRUE; 
	Invalidate();							// Repaint to set the focus 
} 
 
void CBBHyperLink::OnKillFocus(CWnd* pNewWnd)  
{	 
	// Assume that control lost focus = mouse out 
	// this avoid troubles with the Hover color 
	m_bOverControl = FALSE; 
	m_bLinkActive = FALSE; 
	Invalidate();							// Repaint to unset the focus 
} 
 
void CBBHyperLink::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)  
{	 
	//空格 
	if (nChar == VK_SPACE) 
	{ 
		FollowLink(); 
	} 
	else 
	{ 
		CStatic::OnKeyDown(nChar, nRepCnt, nFlags); 
	} 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CBBHyperLink operations 
 
void CBBHyperLink::SetColors(	COLORREF crLinkColor, 
							COLORREF crActiveColor, 
							COLORREF crVisitedColor, 
                            COLORREF crHoverColor /* = -1 */)  
{ 
	m_crLinkColor    = crLinkColor; 
	m_crActiveColor	 = crActiveColor; 
	m_crVisitedColor = crVisitedColor;	 
 
	if (crHoverColor == -1) 
		m_crHoverColor = ::GetSysColor(COLOR_HIGHLIGHT); 
	else 
		m_crHoverColor = crHoverColor;	 
} 
 
 
void CBBHyperLink::GetColors(COLORREF	&crLink,COLORREF &crActive,COLORREF	&crVisited,COLORREF	&crHover) 
{	 
	crLink=m_crLinkColor; 
	crActive = m_crActiveColor; 
	crVisited = m_crVisitedColor; 
	crHover = m_crHoverColor; 
} 
 
void CBBHyperLink::SetLinkCursor(HCURSOR hCursor) { 
	ASSERT(hCursor != NULL); 
 
	m_hLinkCursor = hCursor; 
	if (m_hLinkCursor == NULL) 
		SetDefaultCursor(); 
} 
 
HCURSOR CBBHyperLink::GetLinkCursor() { 
	return m_hLinkCursor; 
} 
 
BOOL CBBHyperLink:: ModifyLinkStyle(DWORD dwRemove, DWORD dwAdd, 
								  BOOL bApply /* =TRUE */) 
{ 
	 
	if ((dwRemove & dwAdd) != 0L) 
		return FALSE; 
	 
	CLEARBITS(m_dwStyle, dwRemove); 
	SETBITS(m_dwStyle, dwAdd);		 
	if (bApply && ::IsWindow(GetSafeHwnd())) 	 
	{ 
	 
		if (BITSET(dwAdd,STYLEUNDERLINE) || BITSET(dwRemove,STYLEUNDERLINE)) 
			SwitchUnderline();		 
		if (BITSET(dwAdd,STYLEAUTOSIZE)) 
			AdjustWindow();		 
		if (BITSET(dwRemove,STYLEUSEHOVER)) 
			Invalidate(); 
	} 
	return TRUE; 
} 
 
DWORD CBBHyperLink::GetLinkStyle() const { 
	return m_dwStyle; 
} 
 
void CBBHyperLink::SetURL(CString strURL) 
{ 
	m_strURL = strURL; 
 
	if (::IsWindow(GetSafeHwnd()))  
	{ 
		ShowWindow(SW_HIDE); 
		AdjustWindow(); 
		m_ToolTip.UpdateTipText(strURL, this, TOOLTIP_ID); 
		ShowWindow(SW_SHOW); 
	} 
} 
 
CString CBBHyperLink::GetURL() const  
{  
	return m_strURL;    
} 
 
void CBBHyperLink::SetWindowText(LPCTSTR lpszText) 
{ 
	ASSERT(lpszText != NULL); 
 
	if (::IsWindow(GetSafeHwnd()))  
	{		 
		ShowWindow(SW_HIDE);					 
		CStatic::SetWindowText(lpszText);		 
		AdjustWindow(); 
		ShowWindow(SW_SHOW);			 
	} 
} 
 
void CBBHyperLink::SetFont(CFont* pFont) 
{ 
	ASSERT(::IsWindow(GetSafeHwnd())); 
	ASSERT(pFont != NULL);	 
	ShowWindow(SW_HIDE);				 
	LOGFONT lf;	 
	pFont->GetLogFont(&lf); 
	m_Font.DeleteObject(); 
	m_Font.CreateFontIndirect(&lf);	 
	CStatic::SetFont(&m_Font);	 
	AdjustWindow(); 
	ShowWindow(SW_SHOW);				 
} 
 
 
void CBBHyperLink::SwitchUnderline() 
{	 
	LOGFONT lf; 
	CFont* pFont = GetFont(); 
	if (pFont != NULL)  
	{ 
		pFont->GetLogFont(&lf);		 
		lf.lfUnderline = BITSET(m_dwStyle,STYLEUNDERLINE); 
		m_Font.DeleteObject(); 
		m_Font.CreateFontIndirect(&lf); 
		SetFont(&m_Font);					 
	}	 
} 
 
//调整窗口的大小,以适应文字的大小 
void CBBHyperLink::AdjustWindow() 
{	 
	ASSERT(::IsWindow(GetSafeHwnd())); 
     
	if (!BITSET(m_dwStyle,STYLEAUTOSIZE))  
		return; 
 
     
    CRect rcWnd; 
    GetWindowRect(rcWnd); 
 
	//父窗口先转换 
    CWnd* pParent = GetParent(); 
    if (pParent) 
        pParent->ScreenToClient(rcWnd); 
	 
 
	CRect rcClient; 
	GetClientRect(rcClient); 
 
	// 计算边框 
	int borderWidth = rcWnd.Width() - rcClient.Width(); 
	int borderHeight = rcWnd.Height() - rcClient.Height(); 
 
    // 得到字体的尺寸 
    CString strWndText; 
    GetWindowText(strWndText);	 
    CDC* pDC = GetDC();	 
    CFont* pOldFont = pDC->SelectObject(&m_Font); 
    CSize Extent = pDC->GetTextExtent(strWndText); 
    pDC->SelectObject(pOldFont); 
    ReleaseDC(pDC); 
 
     
	//得到字体的对方式 
    DWORD dwStyle = GetStyle();     
    if (BITSET(dwStyle, SS_CENTERIMAGE)) 
	{ 
		rcWnd.DeflateRect(0, (rcWnd.Height() - Extent.cy) / 2); 
	} 
    else 
	{ 
		rcWnd.bottom = rcWnd.top + Extent.cy; 
	} 
 
    if (BITSET(dwStyle, SS_CENTER)) 
	{ 
		rcWnd.DeflateRect((rcWnd.Width() - Extent.cx) / 2, 0); 
	} 
    else if (BITSET(dwStyle,SS_RIGHT)) 
	{ 
		rcWnd.left  = rcWnd.right - Extent.cx; 
	} 
	else // SS_LEFT 
	{ 
		rcWnd.right = rcWnd.left + Extent.cx; 
	} 
	 
	MoveWindow(rcWnd.left, rcWnd.top, rcWnd.Width() + borderWidth, 
		rcWnd.Height() + borderHeight); 
} 
 
void CBBHyperLink::SetVisited(BOOL bVisited /* = TRUE */) { 
	m_bVisited = bVisited; 
} 
 
BOOL CBBHyperLink::IsVisited() const { 
	return m_bVisited; 
} 
 
///////////////////////////////////////////////////////////////////////////// 
// CBBHyperLink implementation 
 
// 从WIn32hlp中得到默认的手形光标 
void CBBHyperLink::SetDefaultCursor() 
{ 
	//如果仅在Win2000中可以用 
	//HCURSOR hHandCursor=::LoadCursor(NULL,IDC_HAND); 
	//m_hLinkCursor = CopyCursor(hHandCursor); 
	//return; 
	//否则用 
	if (m_hLinkCursor == NULL)		 
	{ 
         
		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); 
	} 
} 
 
HINSTANCE CBBHyperLink::GotoURL(LPCTSTR url, int showcmd) 
{ 
    HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd); 
    return result; 
} 
 
// 激活连接控件 
void CBBHyperLink::FollowLink()  
{	 
	int result = (int) GotoURL(m_strURL, SW_SHOW); 
    if (result <= HINSTANCE_ERROR) 
	{ 
        MessageBeep(MB_ICONEXCLAMATION);	         
    }  
	else  
	{ 
		m_bVisited = TRUE; 
		Invalidate(); 
	} 
}