WTL 界面设计篇(CSkinHyperLink)

2023-10-27

头文件声明(CSkinHyperLink.h):

#pragma once

#include "SkinManager.h"

class CSkinHyperLink : public CWindowImpl<CSkinHyperLink, CStatic>
{
public:
	CSkinHyperLink(void);
	~CSkinHyperLink(void);

	BEGIN_MSG_MAP_EX(CSkinHyperLink)
		MSG_WM_CREATE(OnCreate)
		MSG_WM_ERASEBKGND(OnEraseBkgnd)
		MSG_WM_PAINT(OnPaint)
		MSG_WM_LBUTTONDOWN(OnLButtonDown)
		MSG_WM_LBUTTONUP(OnLButtonUp)
		MSG_WM_MOUSEMOVE(OnMouseMove)
		MSG_WM_MOUSELEAVE(OnMouseLeave)
		MSG_WM_SETFOCUS(OnSetFocus)
		MSG_WM_KILLFOCUS(OnKillFocus)
		MSG_WM_SETCURSOR(OnSetCursor)
		MSG_WM_SETTEXT(OnSetText)
		MESSAGE_RANGE_HANDLER_EX(WM_MOUSEFIRST, WM_MOUSELAST, OnMouseMessage)
		MSG_WM_DESTROY(OnDestroy)
	END_MSG_MAP()

public:
	void SetLinkColor(COLORREF clr);
	void SetHoverLinkColor(COLORREF clr);
	void SetVisitedLinkColor(COLORREF clr);
	void SetLabel(LPCTSTR lpszLabel);
	void SetHyperLink(LPCTSTR lpszLink);
	void SetToolTipText(LPCTSTR lpszText);
	void SetNormalFont(HFONT hFont);
	void SetHoverFont(HFONT hFont);
	void SetVisitedFont(HFONT hFont);
	void SetTransparent(BOOL bTransparent, HDC hBgDC);

	BOOL SubclassWindow(HWND hWnd);

private:
	int OnCreate(LPCREATESTRUCT lpCreateStruct);
	BOOL OnEraseBkgnd(CDCHandle dc);
	void OnPaint(CDCHandle dc);
	void OnLButtonDown(UINT nFlags, CPoint point);
	void OnLButtonUp(UINT nFlags, CPoint point);
	void OnMouseMove(UINT nFlags, CPoint point);
	void OnMouseLeave();
	void OnSetFocus(CWindow wndOld);
	void OnKillFocus(CWindow wndFocus);
	BOOL OnSetCursor(CWindow wnd, UINT nHitTest, UINT message);
	int OnSetText(LPCTSTR lpstrText);
	LRESULT OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
	void OnDestroy();

	BOOL StartTrackMouseLeave();
	BOOL Navigate();
	void DrawParentWndBg(HDC hDC);
	void Draw(HDC hDC);

private:
	COLORREF m_clrLink;
	COLORREF m_clrHover;
	COLORREF m_clrVisited;

	CString m_strHyperLink;

	HCURSOR m_hCursor;

	CToolTipCtrl m_ToolTipCtrl;

	BOOL m_bFocus, m_bHover, m_bMouseTracking;
	BOOL m_bVisited;

	HFONT m_hNormalFont;
	HFONT m_hHoverFont;
	HFONT m_hVisitedFont;
	BOOL m_bTransparent;
	HDC m_hBgDC;
};

源码定义(CSkinHyperLink.cpp):

#include "StdAfx.h"
#include "SkinHyperLink.h"

CSkinHyperLink::CSkinHyperLink(void)
{
	m_clrLink = RGB(0, 0, 255);
	m_clrHover = RGB(255, 0, 0);
	m_clrVisited = RGB(128, 0, 128);
	
	m_hCursor = NULL;

	m_bFocus = m_bHover = m_bMouseTracking = FALSE;
	m_bVisited = FALSE;

	m_hNormalFont = m_hHoverFont = m_hVisitedFont = NULL;
	m_bTransparent = FALSE;
	m_hBgDC = NULL;
}

CSkinHyperLink::~CSkinHyperLink(void)
{
}

void CSkinHyperLink::SetLinkColor(COLORREF clr)
{
	m_clrLink = clr;
}

void CSkinHyperLink::SetHoverLinkColor(COLORREF clr)
{
	m_clrHover = clr;
}

void CSkinHyperLink::SetVisitedLinkColor(COLORREF clr)
{
	m_clrVisited = clr;
}

void CSkinHyperLink::SetLabel(LPCTSTR lpszLabel)
{
	CRect rcNew(0,0,0,0);
	HDC hDC = ::GetDC(m_hWnd);
	HFONT hFont = m_hNormalFont;
	if (NULL == hFont)
		hFont = (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0L);
	HFONT hOldFont = (HFONT)::SelectObject(hDC, hFont);
	::DrawText(hDC, lpszLabel, -1, &rcNew, DT_CALCRECT);
	::SelectObject(hDC, hOldFont);
	::ReleaseDC(m_hWnd, hDC);
	SetWindowPos(NULL, 0, 0, rcNew.Width(), rcNew.Height(), SWP_NOMOVE);

	SetWindowText(lpszLabel);
}

void CSkinHyperLink::SetHyperLink(LPCTSTR lpszLink)
{
	m_strHyperLink = lpszLink;
}

void CSkinHyperLink::SetToolTipText(LPCTSTR lpszText)
{
	if (!IsWindow())		// SetToolTipText函数必须在创建按钮窗口后才能调用
		return;

	if (!m_ToolTipCtrl.IsWindow())
		m_ToolTipCtrl.Create(m_hWnd);

	if (m_ToolTipCtrl.IsWindow())
	{
		if (m_ToolTipCtrl.GetToolCount() <= 0)
		{
			CRect rcClient;
			GetClientRect(&rcClient);

			m_ToolTipCtrl.Activate(TRUE);
			m_ToolTipCtrl.AddTool(m_hWnd, lpszText, &rcClient, 1);
		}
		else
		{
			m_ToolTipCtrl.Activate(TRUE);
			m_ToolTipCtrl.UpdateTipText(lpszText, m_hWnd, 1);
		}
	}
}

void CSkinHyperLink::SetNormalFont(HFONT hFont)
{
	m_hNormalFont = hFont;
}

void CSkinHyperLink::SetHoverFont(HFONT hFont)
{
	m_hHoverFont = hFont;
}

void CSkinHyperLink::SetVisitedFont(HFONT hFont)
{
	m_hVisitedFont = hFont;
}

void CSkinHyperLink::SetTransparent(BOOL bTransparent, HDC hBgDC)
{
	m_bTransparent = bTransparent;
	m_hBgDC = hBgDC;
}

BOOL CSkinHyperLink::SubclassWindow(HWND hWnd)
{
	BOOL bRet = __super::SubclassWindow(hWnd);
	if (bRet)
	{
		DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
		dwStyle |= SS_NOTIFY | WS_TABSTOP;
		::SetWindowLong(m_hWnd, GWL_STYLE, dwStyle);

		m_hCursor = ::LoadCursor(NULL, IDC_HAND);
	}

	return bRet;
}

int CSkinHyperLink::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	return 0;
}

BOOL CSkinHyperLink::OnEraseBkgnd(CDCHandle dc)
{
	return TRUE;
}

void CSkinHyperLink::OnPaint(CDCHandle dc)
{
	CPaintDC PaintDC(m_hWnd);
	Draw(PaintDC.m_hDC);
}

void CSkinHyperLink::OnLButtonDown(UINT nFlags, CPoint point)
{
	SetFocus();
	SetCapture();
	::InvalidateRect(m_hWnd, NULL, TRUE);
}

void CSkinHyperLink::OnLButtonUp(UINT nFlags, CPoint point)
{
	if(GetCapture() == m_hWnd)
	{
		ReleaseCapture();

		CRect rcClient;
		GetClientRect(&rcClient);

		if (::PtInRect(&rcClient, point))
		{
			BOOL bRet = Navigate();
			if (bRet)
				m_bVisited = TRUE;

			::InvalidateRect(m_hWnd, NULL, TRUE);
		}
	}
}

void CSkinHyperLink::OnMouseMove(UINT nFlags, CPoint point)
{
	if (!m_bMouseTracking)
	{
		StartTrackMouseLeave();
		m_bMouseTracking = TRUE;
		m_bHover = TRUE;
		::InvalidateRect(m_hWnd, NULL, TRUE);
	}

	SetMsgHandled(FALSE);
}

void CSkinHyperLink::OnMouseLeave()
{
	m_bMouseTracking = FALSE;
	m_bHover = FALSE;
	::InvalidateRect(m_hWnd, NULL, TRUE);
	SetMsgHandled(FALSE);
}

void CSkinHyperLink::OnSetFocus(CWindow wndOld)
{
	m_bFocus = TRUE;
	::InvalidateRect(m_hWnd, NULL, TRUE);
	SetMsgHandled(FALSE);
}

void CSkinHyperLink::OnKillFocus(CWindow wndFocus)
{
	m_bFocus = FALSE;
	::InvalidateRect(m_hWnd, NULL, TRUE);
	SetMsgHandled(FALSE);
}

BOOL CSkinHyperLink::OnSetCursor(CWindow wnd, UINT nHitTest, UINT message)
{
	if (m_hCursor)
	{
		::SetCursor(m_hCursor);
		return TRUE;
	}
	SetMsgHandled(FALSE);
	return FALSE;
}

int CSkinHyperLink::OnSetText(LPCTSTR lpstrText)
{
	int nRet = DefWindowProc();
	HDC hDC = ::GetDC(m_hWnd);
	Draw(hDC);
	::ReleaseDC(m_hWnd, hDC);
	return nRet;
}

LRESULT CSkinHyperLink::OnMouseMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	MSG msg = { m_hWnd, uMsg, wParam, lParam };
	if (m_ToolTipCtrl.IsWindow())
		m_ToolTipCtrl.RelayEvent(&msg);
	SetMsgHandled(FALSE);
	return 1;
}

void CSkinHyperLink::OnDestroy()
{
	if (m_ToolTipCtrl.IsWindow())	// ToolTipCtrl早在之前的不知道什么地方已销毁,这里显式置空m_hWnd
		m_ToolTipCtrl.DestroyWindow();
	m_ToolTipCtrl.m_hWnd = NULL;

	m_hNormalFont = m_hHoverFont = m_hVisitedFont = NULL;

	SetMsgHandled(FALSE);
}

BOOL CSkinHyperLink::StartTrackMouseLeave()
{
	TRACKMOUSEEVENT tme = { 0 };
	tme.cbSize = sizeof(tme);
	tme.dwFlags = TME_LEAVE;
	tme.hwndTrack = m_hWnd;
	return _TrackMouseEvent(&tme);
}

BOOL CSkinHyperLink::Navigate()
{
	if (!m_strHyperLink.IsEmpty())
	{
		DWORD_PTR dwRet = (DWORD_PTR)::ShellExecute(0, _T("open"), m_strHyperLink, 0, 0, SW_SHOWNORMAL);
		return (dwRet > 32) ? TRUE : FALSE;
	}
	else
	{
		::SendMessage(GetParent(), WM_COMMAND, MAKEWPARAM(GetDlgCtrlID(), BN_CLICKED), (LPARAM)m_hWnd);
		return TRUE;
	}
}

void CSkinHyperLink::DrawParentWndBg(HDC hDC)
{
	HWND hParentWnd = ::GetParent(m_hWnd);

	CRect rcWindow;
	GetWindowRect(&rcWindow);
	::ScreenToClient(hParentWnd, (LPPOINT)&rcWindow); 
	::ScreenToClient(hParentWnd, ((LPPOINT)&rcWindow)+1);

	::BitBlt(hDC, 0, 0, rcWindow.Width(), rcWindow.Height(), m_hBgDC, rcWindow.left, rcWindow.top, SRCCOPY);
}

void CSkinHyperLink::Draw(HDC hDC)
{
	if (m_bTransparent)
		DrawParentWndBg(hDC);

	CRect rtClient;
	GetClientRect(&rtClient);

	int nTextLen = GetWindowTextLength();
	if (nTextLen > 0)
	{
		CString strText;
		GetWindowText(strText);

		HFONT hNormalFont = NULL, hHoverFont = NULL, hVisitedFont = NULL;
		HFONT hFont, hOldFont;
		COLORREF clrText;

		hNormalFont = m_hNormalFont;
		if (NULL == hNormalFont)
			hNormalFont = (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0L);

		if (m_bHover)	// 鼠标悬停状态
		{
			hHoverFont = m_hHoverFont;
			if (NULL == hHoverFont)
			{
				CFontHandle font = hNormalFont;
				LOGFONT lf = {0};
				font.GetLogFont(&lf);

				lf.lfUnderline = TRUE;

				hHoverFont = ::CreateFontIndirect(&lf);
			}
			hFont = hHoverFont;

			clrText = m_clrHover;
		}
		else if (m_bVisited)
		{
			hVisitedFont = m_hVisitedFont;
			if (NULL == hVisitedFont)
				hVisitedFont = hNormalFont;
			hFont = hVisitedFont;
			clrText = m_clrVisited;
		}
		else	// 普通状态
		{
			hFont = hNormalFont;
			clrText = m_clrLink;
		}

		int nMode = ::SetBkMode(hDC, TRANSPARENT);

		::SetTextColor(hDC, clrText);

		hOldFont = (HFONT)::SelectObject(hDC, hFont);
		::DrawText(hDC, strText, nTextLen, &rtClient, DT_SINGLELINE | DT_LEFT | DT_VCENTER);
		::SelectObject(hDC, hOldFont);

		::SetBkMode(hDC, nMode);

		if (hHoverFont != NULL && hHoverFont != m_hHoverFont)
		{
			::DeleteObject(hHoverFont);
			hHoverFont = NULL;
		}
	}
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WTL 界面设计篇(CSkinHyperLink) 的相关文章

随机推荐

  • FTP上传和下载文件

    使用FTP之前最好先在服务器上安装一个serv u软件 用它设置ftp服务表叫方便 实现ftp文件下载 package cn java store test import java io File import java io FileIn
  • Android studio 分析内存泄漏

    http www cnblogs com kelina2mark p 6140658 html
  • Bat脚本自动卸载软件-静默执行

    通过Bat脚本卸载软件 原理是得到某软件的ProductCode 然后通过MsiExec exe命令卸载软件 下面是卸载一个产品的基本代码示例 set ML4 0HF4Name Product4 0HF4 set ML4 0HF4Produ
  • 冒泡排序法

    Hello 大家好 今天我要介绍的是冒泡排序法 冒泡排序法是一种C语言中的数字大小排序的一种方法 这种排序方法是C语言中最简单的一种方法 Now 首先让我们先看一 下冒泡排序法的基本思想 冒泡排序法的思想 两两比较 如果前一个数比后一个数大
  • 程序员的职业成长之路?从初级到高级的技能提升之路

    程序员是一个非常有挑战性和创造性的职业 但也是一个需要不断学习和进步的职业 如果你想在这个行业里有所作为 你需要掌握一些必备的技能和方法 从初级到中级 再到高级 最后达到资深的水平 那么 程序员的成长路线是什么呢 维哥将为你介绍一些实用的建
  • 学计算机电脑屏幕多大,买电脑显示器的技巧 电脑显示屏多大尺寸好

    购买电脑是时 大多数的商家都会把电脑显示器作为电脑配置中的一个主要卖点 但其实很多时候 商家给与我们的信息都是错误的 所以买电脑显示器前 需要自己掌握一些技巧 而一些用户也会在购买多大尺寸的显示屏上纠结着 接下来小编为大家带来买电脑显示器的
  • pytorch之torch.randn()

    torch randn sizes out None dtype None layout torch strided device None requires grad False gt Tensor Args sizes int a se
  • 进入传奇荣耀显示服务器不存在,传奇荣耀复古版

    传奇荣耀复古版 1区服务器爆满排队15分钟 传奇荣耀复古版是一款复古系列的传奇游戏 玩家能够在游戏中24小时匹配到队友进行副本攻略 更有完善的社交系统 让玩家轻松结识更多的兄弟姐妹 实时语音系统方便玩家更好的进行沟通 让玩家们的作战更加轻松
  • 通过Android Timer来实现3S自动页面跳转

    实现开始页面的跳转 就是打开一个Android手机APP的欢迎界面后跳转到指定界面 启动页面的作用能够打广告 发公告 做缓存处理 更新数据等等 Timer是一种定时器工具 用来在一个后台线程计划执行指定任务 它可以计划执行一个任务一次或反复
  • 基于MATLAB的特征值与特征向量(附完整代码)

    目录 一 一般矩阵的特征值与特征向量 例题1 二 广义特征向量问题 例题2 三 稀疏矩阵的最大特征值 例题3 一 一般矩阵的特征值与特征向量 A为n阶矩阵 若数和向量x满足 那么数称为A的特征值 x称为A对应于特征值的特征向量 如果把式子改
  • 文本聚类(二)—— KMeans 聚类

    目录 二 KMeans 聚类 2 1 加载数据集 2 2 数据清洗 2 3 文本向量化 2 4 文本聚类 2 5 关键词展示 2 6 判定最佳聚类数 参考文档 在第一篇内容中 我们介绍了 LDA 主题模型 这一篇 我们将介绍经典的 KMea
  • 大数据分析利器——clickhouse的简介与应用

    大数据分析利器 clickhouse的简介与应用 背景介绍 公司原有的数仓技术架构是基于传统的Hadoop的数仓体系 使用任务调度 通过不同的hive的任 务调度解决不同的业务主题 传统的数仓架构胜在稳定 依托于Hadoop体系 使用的用户
  • Linux多线程:读写锁

    当有一个线程已经持有互斥锁时 互斥锁将所有试图进入临界区的线程都阻塞住 但是考 虑一种情形 当前持有互斥锁的线程只是要读访问共享资源 而同时有其它几个线程也想 读取这个共享资源 但是由于互斥锁的排它性 所有其它线程都无法获取锁 也就无法读
  • Asp.Net Mvc AutoFac 的简单使用

    http www kungge com kungge 2699 html 转载于 https www cnblogs com zhihang p 11059740 html
  • Windows MongoDB安装

    目录 一 下载 社区版7 0 0 二 安装 三 安装后的问题 四 测试 一 下载 社区版7 0 0 官网 Install MongoDB Community Kubernetes Operator MongoDB 二 安装 下载后双击打开安
  • idea自动生成类注释和方法注释

    一 自动生成类注释 打开Setting 选在Editor 然后是File and Code Templates 最后是Files 中的Class 点击class后 编辑右边的红色边框 里边是模板 将模板设置好 点击ok即可 下边是模板中的示
  • 【SpringBoot高级篇】SpringBoot集成Elasticsearch搜索引擎

    SpringBoot高级篇 SpringBoot集成Elasticsearch搜索引擎 1 什么是Elasticsearch 2 安装并运行Elasticsearch 2 1 拉取镜像 2 2 启动镜像 3 安装kibana 3 1 拉取k
  • BAT数据洞察报告 附下载地址

    BAT B指百度 A指阿里巴巴 T指腾讯 是三大互联网公司百度公司 Baidu 阿里巴巴集团 Alibaba 腾讯公司 Tencent 首字母的缩写 百度总部在北京 阿里巴巴总部在浙江省杭州市 腾讯总部在广东省深圳市 关注公众号 互联互通社
  • iOS App的打包和上架流程

    转载 iOS App的打包和上架流程 掘金 1 创建账号 苹果开发者账号几种开发者账号类型 个人开发者账号 费用 99 美元 年 688 00元 协作人数 仅限开发者自己 不需要填写公司的邓百氏编码 D U N S Number 支持账号下
  • WTL 界面设计篇(CSkinHyperLink)

    头文件声明 CSkinHyperLink h pragma once include SkinManager h class CSkinHyperLink public CWindowImpl