求分享一个mfc的超链接类CStaticEx

huhu0013 2014-08-27 04:42:27
希望有一个static控件,能实现类似超链接的外观和行为:

(1)鼠标移到控件时,鼠标指针变成手的形状,控件字体颜色变化,出现下划线
(2)鼠标离开控件时,鼠标指针恢复原状,控件字体复原
(3)能够自由定义点击控件后的程序行为


百度了很久都没有找到功能完美的
求各位分享一个
...全文
191 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Eleven 2014-10-10
  • 打赏
  • 举报
回复
codeproject上去搜索一下,应该有不少的~
向立天 2014-10-09
  • 打赏
  • 举报
回复
您好 我是本版版主 此帖已多日无人关注 请您及时结帖 如您认为问题没有解决可按无满意结帖处理 另外本版设置了疑难问题汇总帖 并已在版面置顶 相关规定其帖子中有说明 您可以根据规定提交您帖子的链接 如您目前不想结帖只需回帖说明 我们会删除此结帖通知 见此回复三日内无回应 我们将强制结帖 相关规定详见界面界面版关于版主结帖工作的具体办法
zhllxt 2014-10-09
  • 打赏
  • 举报
回复

#pragma once


// CStaticButton

class CStaticButton : public CButton
{
	DECLARE_DYNAMIC(CStaticButton)

public:
	CStaticButton();
	virtual ~CStaticButton();

	COLORREF SetTextColor( COLORREF crText ) { COLORREF crTextOld = m_crText; m_crText = crText; return crTextOld; };
protected:
	//按钮的状态
	bool m_bIsPressed, m_bIsFocus, m_bIsMouseOver;
	HCURSOR	m_hHandCursor;
	COLORREF m_crText;

protected:
	DECLARE_MESSAGE_MAP()
	virtual void PreSubclassWindow();
public:
	virtual void DrawItem(LPDRAWITEMSTRUCT /*lpDrawItemStruct*/);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg LRESULT OnMouseLeave(WPARAM wParam, LPARAM lParam);
protected:
	virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);
public:
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
};



// StaticButton.cpp : 实现文件
//

#include "stdafx.h"
#include "StaticButton.h"


// CStaticButton

IMPLEMENT_DYNAMIC(CStaticButton, CButton)

CStaticButton::CStaticButton() : m_crText( RGB(0,0,255) )
{
	m_bIsPressed = m_bIsFocus = m_bIsMouseOver = false;
	m_hHandCursor = ::LoadCursor(0, MAKEINTRESOURCE(32649/*IDC_HAND*/));
}

CStaticButton::~CStaticButton()
{
}

BEGIN_MESSAGE_MAP(CStaticButton, CButton)
	ON_WM_MOUSEMOVE()
	ON_MESSAGE(WM_MOUSELEAVE, OnMouseLeave)
	ON_WM_SETCURSOR()
	ON_WM_ERASEBKGND()
END_MESSAGE_MAP()


// CStaticButton 消息处理程序

void CStaticButton::PreSubclassWindow()
{
	// TODO: 在此添加专用代码和/或调用基类
	ModifyStyle(0,BS_OWNERDRAW);
	//SetClassLong(m_hWnd,GCL_HCURSOR,(LONG)m_hHandCursor);
	CButton::PreSubclassWindow();
}

void CStaticButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
	// TODO:  添加您的代码以绘制指定项
	CDC * pDC = CDC::FromHandle( lpDrawItemStruct->hDC );
	int nSavedDC = pDC->SaveDC();

	CString strText;
	GetWindowText( strText );
	CSize szExtent = pDC->GetTextExtent( strText,strText.GetLength() );

	CRect rc = lpDrawItemStruct->rcItem;

	//COLORREF crReturn=CLR_INVALID;
	//HWND hParentWnd=::GetParent(m_hWnd);
	//if(hParentWnd)
	//{
	//	HDC hParentDC=::GetDC(hParentWnd);
	//	if(hParentDC)
	//	{
	//		HBRUSH brParentBk =(HBRUSH)::SendMessage(hParentWnd,WM_CTLCOLORDLG,(WPARAM)hParentDC,(LPARAM)hParentWnd);
	//		if(brParentBk)
	//		{
	//			LOGBRUSH lb;
	//			if(GetObject(brParentBk,sizeof(LOGBRUSH),&lb))
	//			{
	//				crReturn = lb.lbColor;
	//			}
	//		}
	//		::ReleaseDC(hParentWnd,hParentDC);
	//	}
	//}
	//pDC->FillSolidRect( rc,crReturn );
	//pDC->FillRect( rc,CBrush::FromHandle( (HBRUSH)GetClassLong( this->GetSafeHwnd(),GCL_HBRBACKGROUND ) ) );

	pDC->SetBkMode( TRANSPARENT );
	pDC->SetTextColor( IsWindowEnabled() ? m_crText : GetSysColor(COLOR_GRAYTEXT) );

	CFont font;
	CFont * pFont = GetFont();
	if ( pFont )
	{
		LOGFONT lf;
		pFont->GetObject( sizeof(lf), &lf );
		lf.lfUnderline = m_bIsMouseOver;
		font.CreateFontIndirect( &lf );
	}

	pDC->SelectObject( &font );

	LONG lStyle = GetWindowLong(m_hWnd,GWL_STYLE);
	if( lStyle & BS_LEFT )
	{
		rc.left = 0;
	}
	else if( lStyle & BS_RIGHT)
	{
		rc.left=rc.right-szExtent.cx;
	}
	else
	{
		rc.left += ( rc.Width() - szExtent.cx ) / 2;
	}

	if( m_bIsPressed )
		pDC->TextOut(rc.left+1,(rc.bottom-szExtent.cy)/2+1,strText);
	else
		pDC->TextOut(rc.left,(rc.bottom-szExtent.cy)/2,strText);

	pDC->RestoreDC( nSavedDC );
}

void CStaticButton::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	if( !m_bIsMouseOver )
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE;
		m_bIsMouseOver = ( _TrackMouseEvent(&tme) == TRUE );

		Invalidate();

		CWnd * pParent = GetParent();
		if( pParent )
		{
			CRect rc;
			GetWindowRect( rc );
			pParent->ScreenToClient( rc );
			pParent->InvalidateRect( rc );
		}
	}

	CButton::OnMouseMove(nFlags, point);
}

LRESULT CStaticButton::OnMouseLeave(WPARAM wParam, LPARAM lParam)
{
	m_bIsMouseOver = false;
	Invalidate();
	CWnd * pParent = GetParent();
	if( pParent )
	{
		CRect rc;
		GetWindowRect( rc );
		pParent->ScreenToClient( rc );
		pParent->InvalidateRect( rc );
	}
	return 0;
}

LRESULT CStaticButton::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	// TODO: 在此添加专用代码和/或调用基类
	switch( message )
	{
	case BM_SETSTATE:
		if( (UINT)m_bIsPressed != wParam )
		{
			m_bIsPressed = ( wParam == TRUE );
			CWnd * pParent = GetParent();
			if( pParent )
			{
				CRect rc;
				GetWindowRect( rc );
				pParent->ScreenToClient( rc );
				pParent->InvalidateRect( rc );
			}
		}
		break;
	default:
		break;
	}

	return CButton::WindowProc(message, wParam, lParam);
}

BOOL CStaticButton::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	::SetCursor( m_hHandCursor );
	return TRUE;
	//return CButton::OnSetCursor(pWnd, nHitTest, message);
}

BOOL CStaticButton::OnEraseBkgnd(CDC* pDC)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	return TRUE;
	//return CButton::OnEraseBkgnd(pDC);
}
为什么从CButton派生而不从CStatic派生:当从CStatic派生时,鼠标左键只要在超连接上按下了就会马上打开链接地址,而不是等鼠标按下并弹起之后再打开链接,从CButton派生即可避免该问题。
树叶上的蜗牛 2014-09-01
  • 打赏
  • 举报
回复
自己写吧,一天时间搞定
Jackxan 2014-09-01
  • 打赏
  • 举报
回复
没有现成的,自己动手写吧

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧