WTL 界面设计篇(CSkinEdit)

2023-11-20

头文件声明(CSkinEdit.h):

#pragma once

#include "SkinManager.h"

// 不支持滚动条皮肤
// 图片背景支持不完整
// Edit控件必须是ES_MULTILINE风格,SetMarginsEx才能生效,ES_MULTILINE风格好像不能动态修改,只能在生成控件时指定

class CSkinEdit : public CWindowImpl<CSkinEdit, CEdit>
{
public:
	CSkinEdit(void);
	~CSkinEdit(void);

	BEGIN_MSG_MAP_EX(CSkinEdit)
		MSG_WM_CREATE(OnCreate)
		MSG_WM_NCCALCSIZE(OnNcCalcSize)
		MSG_WM_ERASEBKGND(OnEraseBkgnd)
		MSG_WM_NCPAINT(OnNcPaint)
		MSG_OCM_CTLCOLOREDIT(OnCtlColor)
		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_SIZE(OnSize)
		MSG_WM_DESTROY(OnDestroy)
		DEFAULT_REFLECTION_HANDLER()
	END_MSG_MAP()

public:
	BOOL SetBgNormalPic(LPCTSTR lpszFileName, RECT * lpNinePart = NULL);
	BOOL SetBgHotPic(LPCTSTR lpszFileName, RECT * lpNinePart = NULL);
	BOOL SetIconPic(LPCTSTR lpszFileName);
	void SetTransparent(BOOL bTransparent, HDC hBgDC);
	void SetDefaultText(LPCTSTR lpszText);
	BOOL IsDefaultText();
	void SetDefaultTextMode(BOOL bIsDefText);
	void SetMarginsEx(int nLeft, int nTop, int nRight, int nBottom);	// 设置上下左右边距函数
	void SetMultiLine(BOOL bMultiLine = TRUE);
	BOOL SubclassWindow(HWND hWnd);

private:
	int OnCreate(LPCREATESTRUCT lpCreateStruct);
	LRESULT OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam);
	BOOL OnEraseBkgnd(CDCHandle dc);
	void OnNcPaint(CRgnHandle rgn);
	HBRUSH OnCtlColor(CDCHandle dc, CEdit edit);
	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);
	void OnSize(UINT nType, CSize size);
	void OnDestroy();

	BOOL StartTrackMouseLeave();
	void CalcCenterRect(CRect& rcDest, int cx, int cy, CRect& rcCenter);
	void SetCenterInSingleLine();

	void DrawParentWndBg(HDC hDC);

private:
	CImageEx * m_lpBgImgN;
	CImageEx * m_lpBgImgH;
	CImageEx * m_lpIconImg;
	int m_nIconWidth;
	BOOL m_bFocus, m_bPress, m_bHover, m_bMouseTracking;
	BOOL m_bTransparent;
	HDC m_hBgDC;
	BOOL m_bIsDefText;
	CString m_strDefText;
	TCHAR m_cPwdChar;
	BOOL m_bMultiLine;
};

源码定义(CSkinEdit.cpp):

#include "StdAfx.h"
#include "SkinEdit.h"

CSkinEdit::CSkinEdit(void)
{
	m_lpBgImgN = NULL;
	m_lpBgImgH = NULL;
	m_lpIconImg = NULL;
	m_nIconWidth = 0;
	m_bFocus = m_bPress = m_bHover = m_bMouseTracking = FALSE;
	m_bTransparent = FALSE;
	m_hBgDC = NULL;
	m_bIsDefText = FALSE;
	m_cPwdChar = 0;
	m_bMultiLine = FALSE;
}

CSkinEdit::~CSkinEdit(void)
{
}

BOOL CSkinEdit::SetBgNormalPic(LPCTSTR lpszFileName, RECT * lpNinePart/* = NULL*/)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgN);
	m_lpBgImgN = CSkinManager::GetInstance()->GetImage(lpszFileName);
	if (m_lpBgImgN != NULL)
		m_lpBgImgN->SetNinePart(lpNinePart);
	return (m_lpBgImgN != NULL) ? TRUE : FALSE;
}

BOOL CSkinEdit::SetBgHotPic(LPCTSTR lpszFileName, RECT * lpNinePart/* = NULL*/)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgH);
	m_lpBgImgH = CSkinManager::GetInstance()->GetImage(lpszFileName);
	if (m_lpBgImgH != NULL)
		m_lpBgImgH->SetNinePart(lpNinePart);
	return (m_lpBgImgH != NULL) ? TRUE : FALSE;
}

BOOL CSkinEdit::SetIconPic(LPCTSTR lpszFileName)
{
	CSkinManager::GetInstance()->ReleaseImage(m_lpIconImg);
	m_lpIconImg = CSkinManager::GetInstance()->GetImage(lpszFileName);
	if (m_lpIconImg != NULL)
		m_nIconWidth = m_lpIconImg->GetWidth();
	return (m_lpIconImg != NULL) ? TRUE : FALSE;
}

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

void CSkinEdit::SetDefaultText(LPCTSTR lpszText)
{
	m_strDefText = lpszText;
}

BOOL CSkinEdit::IsDefaultText()
{
	return m_bIsDefText;
}

void CSkinEdit::SetDefaultTextMode(BOOL bIsDefText)
{
	if (bIsDefText == m_bIsDefText)
		return;

	m_bIsDefText = bIsDefText;
	if (m_bIsDefText)
	{
		m_cPwdChar = GetPasswordChar();
		SetPasswordChar(0);
		SetWindowText(m_strDefText);
	}
	else
	{
		SetPasswordChar(m_cPwdChar);
		SetWindowText(_T(""));
	}
}

// 设置上下左右边距函数
void CSkinEdit::SetMarginsEx(int nLeft, int nTop, int nRight, int nBottom)
{
	CRect rtClient;
	GetClientRect(rtClient);

	CRect rt(rtClient.left + nLeft, rtClient.top + nTop, 
		rtClient.right - nRight, rtClient.bottom - nBottom);
	SetRectNP(rt);
}

void CSkinEdit::SetMultiLine(BOOL bMultiLine/* = TRUE*/)
{
	m_bMultiLine = bMultiLine;
	if (!m_bMultiLine && IsWindow())		// 单行模式居中
		SetCenterInSingleLine();
}

BOOL CSkinEdit::SubclassWindow(HWND hWnd)
{
	__super::SubclassWindow(hWnd);

	SetDefaultText(m_strDefText);

	if (!m_bMultiLine)	// 单行模式居中
		SetCenterInSingleLine();

	return TRUE;
}

int CSkinEdit::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	SetMsgHandled(FALSE);
	return 0;
}

LRESULT CSkinEdit::OnNcCalcSize(BOOL bCalcValidRects, LPARAM lParam)
{
	SetMsgHandled(FALSE);

 	if (NULL == m_lpIconImg || m_lpIconImg->IsNull())
 		return 0;

	if (bCalcValidRects)
	{
		LPNCCALCSIZE_PARAMS pParam = (LPNCCALCSIZE_PARAMS)lParam;
		pParam->rgrc[0].right -= m_nIconWidth;
		pParam->rgrc[1] = pParam->rgrc[0];
	}   

	return 0;
}

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

void CSkinEdit::OnNcPaint(CRgnHandle rgn)
{
	CRect rcWindow;
	GetWindowRect(&rcWindow);

	CRect rcClient;
	GetClientRect(&rcClient);

	ClientToScreen(&rcClient);
	rcClient.OffsetRect(-rcWindow.left, -rcWindow.top);

	rcWindow.OffsetRect(-rcWindow.left, -rcWindow.top);

	HDC hDC = ::GetWindowDC(m_hWnd);

// 	RECT rcClip = {0};
// 	::GetClipBox(hDC, &rcClip);
// 	HRGN hOldRgn = ::CreateRectRgnIndirect(&rcClip);
// 	HRGN hRgn = ::CreateRectRgnIndirect(&rcClient);
// 	::ExtSelectClipRgn(hDC, hRgn, RGN_DIFF);

	CRect rcIcon;
	HRGN hRgn2 = NULL;
	if (m_lpIconImg != NULL && !m_lpIconImg->IsNull())
	{
		int cxIcon = m_lpIconImg->GetWidth();
		int cyIcon = m_lpIconImg->GetHeight();

		CalcCenterRect(rcWindow, cxIcon, cyIcon, rcIcon);
		rcIcon.right = rcWindow.right - 2;
		rcIcon.left = rcIcon.right - cxIcon;

		//hRgn2 = ::CreateRectRgnIndirect(&rcIcon);
		//::ExtSelectClipRgn(hDC, hRgn2, RGN_OR);
	}

	if (m_bTransparent)
		DrawParentWndBg(hDC);

	if (m_bHover)
	{
		if (m_lpBgImgH != NULL && !m_lpBgImgH->IsNull())
		{
			m_lpBgImgH->Draw2(hDC, rcWindow);
		}
		else
		{
			if (m_lpBgImgN != NULL && !m_lpBgImgN->IsNull())
				m_lpBgImgN->Draw2(hDC, rcWindow);
		}
	}
	else
	{
		if (m_lpBgImgN != NULL && !m_lpBgImgN->IsNull())
			m_lpBgImgN->Draw2(hDC, rcWindow);
	}

	if (m_lpIconImg != NULL && !m_lpIconImg->IsNull())
		m_lpIconImg->Draw2(hDC, rcIcon);

// 	::SelectClipRgn(hDC, hOldRgn);
// 	::DeleteObject(hOldRgn);
// 	::DeleteObject(hRgn);
// 	if (hRgn2 != NULL)
// 		::DeleteObject(hRgn2);

	::ReleaseDC(m_hWnd, hDC);




// 	HPEN hPen, hOldPen;
// 	HBRUSH hBrush, hOldBrush;
// 
// 	hPen = ::CreatePen(PS_INSIDEFRAME | PS_SOLID, 1, RGB(163, 194, 212));
// 	hBrush = ::CreateSolidBrush(RGB(255, 255, 255));
// 
// 	hOldPen = (HPEN)::SelectObject(hDC, hPen);
// 	hOldBrush = (HBRUSH)::SelectObject(hDC, hBrush);
// 	::Rectangle(hDC, rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
// 	::SelectObject(hDC, hOldPen);
// 	::SelectObject(hDC, hOldBrush);
// 
// 	::DeleteObject(hPen);
// 	::DeleteObject(hBrush);
}

// void CSkinEdit::OnPaint(CDCHandle dc)
// {
// 	CPaintDC PaintDC(m_hWnd);
// 
// 	CRect rcClient;
// 	GetClientRect(&rcClient);
// 
// 	PaintDC.FillSolidRect(&rcClient, RGB(255,0,0));
// 
// 	SetMsgHandled(FALSE);
// }

HBRUSH CSkinEdit::OnCtlColor(CDCHandle dc, CEdit edit)
{
	//::SetBkMode(dc, TRANSPARENT);
	if (m_bIsDefText)
		::SetTextColor(dc, RGB(128,128,128));
	else
		::SetTextColor(dc, RGB(0,0,0));

	return (HBRUSH)NULL_BRUSH;
}

void CSkinEdit::OnLButtonDown(UINT nFlags, CPoint point)
{
	m_bPress = TRUE;
	::InvalidateRect(m_hWnd, NULL, FALSE);
	SetMsgHandled(FALSE);
}

void CSkinEdit::OnLButtonUp(UINT nFlags, CPoint point)
{
	if (m_bPress)
	{
		m_bPress = FALSE;
		::InvalidateRect(m_hWnd, NULL, FALSE);
	}

	SetMsgHandled(FALSE);
}

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

	SetMsgHandled(FALSE);
}

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

void CSkinEdit::OnSetFocus(CWindow wndOld)
{
	if (m_bIsDefText)
	{
		m_bIsDefText = FALSE;
		SetPasswordChar(m_cPwdChar);
		SetWindowText(_T(""));
	}

	m_bFocus = TRUE;
	::InvalidateRect(m_hWnd, NULL, FALSE);
	SetMsgHandled(FALSE);
}

void CSkinEdit::OnKillFocus(CWindow wndFocus)
{
	if (GetWindowTextLength() <= 0 && !m_strDefText.IsEmpty())
	{
		m_bIsDefText = TRUE;
		m_cPwdChar = GetPasswordChar();
		SetPasswordChar(0);
		SetWindowText(m_strDefText);
	}

	m_bFocus = FALSE;
	::InvalidateRect(m_hWnd, NULL, FALSE);
	SetMsgHandled(FALSE);
}

void CSkinEdit::OnSize(UINT nType, CSize size)
{
	DefWindowProc();

	if (!m_bMultiLine)			// 单行模式居中
		SetCenterInSingleLine();
}

void CSkinEdit::OnDestroy()
{
	SetMsgHandled(FALSE);

	CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgN);
	CSkinManager::GetInstance()->ReleaseImage(m_lpBgImgH);
	CSkinManager::GetInstance()->ReleaseImage(m_lpIconImg);
}

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

void CSkinEdit::CalcCenterRect(CRect& rcDest, int cx, int cy, CRect& rcCenter)
{
	int x = (rcDest.Width() - cx + 1) / 2;
	int y = (rcDest.Height() - cy + 1) / 2;

	rcCenter = CRect(rcDest.left+x, rcDest.top+y, rcDest.left+x+cx, rcDest.top+y+cy);
}

void CSkinEdit::SetCenterInSingleLine()
{
	CRect rcClient;
	GetClientRect(&rcClient);

	CDCHandle dc = ::GetDC(m_hWnd);
	TEXTMETRIC tm = {0};
	dc.GetTextMetrics(&tm);
	int nFontHeight = tm.tmHeight + tm.tmExternalLeading;
	int nMargin = (rcClient.Height() - nFontHeight) / 2;
	::ReleaseDC(m_hWnd, dc);

	rcClient.DeflateRect(0, nMargin);
	SetRectNP(&rcClient);
}

void CSkinEdit::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);
}

 

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

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

  • 一些论文审稿方面的体会

    本人小硕在读 老师也让帮忙审了论文 多是与自己领域相关的 老师让多学习学习 每次审论文都感觉诚惶诚恐 要是提的问题太多吧 感觉万一给拒了作者该多伤心啊 这挑的问题少吧 这明显对不起更多的人嘛 大体总结一下自己遇到的问题吧 一 现在论文提交量
  • Win10+CUDA8.0+Visual Studio2013安装、环境配置教程

    最近刚开始接触opencv的GPL编程 所以自己搜了下网上有关配置CUDA的过程 经过摸索整理 配置成功 现将教程整理如下 1 下载CUDA安装包 下载地址https developer nvidia com cuda downloads
  • 使用CUDA和CUFFT进行快速1D卷积的示例

    使用CUDA和CUFFT进行快速1D卷积的示例 在计算机视觉 数字信号处理和机器学习中 卷积是一种常见的操作 然而 卷积操作通常需要大量计算 因此需要一种高效的方法来完成 CUDA和CUFFT可以用于对使用FFT的快速1D卷积进行加速 在本
  • [Unity XLua]热更新XLua入门(一)-基础篇

    Aladdin XLua 前言 前段时间腾讯开源了一个内部热更框架XLua在Unity开发群里引起一阵热议 也受到广大开发者的热捧 然后我当然也抱着好奇的心去学习学习 后面也会将扩展之后的工程放在git上 大家一起学习交流 在此感谢XLua
  • c3p0数据库连接池死锁问题和mysql重连,连接丢失

    c3p0参数解释 最常用配置 initialPoolSize 连接池初始化时创建的连接数 default 3 取值应在minPoolSize与maxPoolSize之间 c3p0 initialPoolSize 10 minPoolSize
  • 敏捷项目管理ACP解析会笔记

    互联网时代企业环境现状 产品生命周期急剧缩短 市场环境变化太快 客户不满意 客户 团队 产品 产品需求界定不清 什么是敏捷项目管理 低成本 快速度 高质量 交付更高质量 敏捷宣言 个体和交互 重于过程和工具 可工作的软件 重于面面俱到的文档

随机推荐

  • Java高并发处理方案

    java高并发 如何解决 什么方式解决 一 什么是高并发 二 高并发解决思路 三 高并发解决方案 一 什么是高并发 1 1 高并发 High Concurrency 是互联网分布式系统架构设计中必须考虑的因素之一 它通常是指 通过设计保证系
  • 实现一个函数,判断一个数是不是素数

    include
  • Stream实现List和Map互转总结

    本文来说下Stream实现List和Map互转总结 文章目录 实体类 Map转List代码 List转Map代码 实体类 本篇介绍Stream流List和Map互转 同时在转换过程中遇到的问题分析 package cn wideth col
  • 找到专业的软件外包开发公司

    今天给大家分享怎么样找软件开发公司开发 而且找到的是既负责又专业的 那怎么去找呢 看哪些方面 北京木奇移动技术有限公司 专业的软件外包开发公司 欢迎交流合作 1 案例看实力 在选择软件定制开发公司时 必须要留意对方的案例如何 有否做过大型的
  • 理解HTTP headers之Expires、Cache-Control、IF-Modified-Since

    一 什么是Http headers 当你在浏览器地址栏里键入一个url 你的浏览器将会类似如下的http请求 GET tutorials other top 20 mysql best practices HTTP 1 1 Host net
  • Hive函数row_number实现

    需求 查询一批用户最后三次登陆时间 ip数据 理解需求是实现分组取前n个值 实现方式是先按照uid字段升序或倒序 时间字段倒序排序数据集合 然后遍历数据集合 用row number函数遍历uid字段 相同则row number值 1 取ro
  • el-table添加border边框线不显示

    el table添加border属性 使用作用域插槽 会不现实左边的边框线 或者右边的边框线 总结问题 1 固定了表格的高度 height 250 把高度去掉
  • JavaScript(函数,作用域和闭包)

    目录 一 什么是函数 1 1 常用系统函数 1 2 函数声明 1 3 函数表达式 二 预解析 2 1 函数自调用 2 2 回调函数 三 变量的作用域 3 1 隐式全局变量 四 作用域与块级作用域 五 作用域链 六 闭包 一 什么是函数 类似
  • 微信小程序:图片高度设置无效问题

    控制台查看元素 显示其style中多了一个没有设置的高度值 找了很久发现是因为image标签设置了mode widthFix 此时高度会自适应 样式中设置高度无效
  • 对接百度api的工具类:Base64Util,FileUtil,HttpUtil

    对接百度api的工具类 Base64Util FileUtil HttpUtil package com baidu ai aip utils Base64 工具类 public class Base64Util private stati
  • Windows中安装GCC教程

    GCC的安装教程 GCC简介 GCC编译器通常在Linux系统下使用 一般来说大部分发行的系统会默认安装 GCC编译器使用gcc指令在终端进行shell操作 对于新接触Linux的朋友来说 简单的在Windows中练习过渡一下应该就足够了
  • Python数据库接口以及API

    非常详细的解释 包含数据库分类以及各种数据库的特点 https wiki python org moin DatabaseInterfaces
  • flex布局详解

    声明 本人的所有博客皆为个人笔记 作为个人知识索引使用 因此在叙述上存在逻辑不通顺 跨度大等问题 希望理解 分享出来仅供大家学习翻阅 若有错误希望指出 感谢 flex基本概念 任何一个容器都可以指定为Flex布局 例如 box displa
  • 3min利用Python实现9种经典排序算法可视化!(附源代码)

    来源 恋习Python 本文附视频 建议收藏 本文为你分享实现9种经典排序算法可视化的方法 3分钟即可实现 导 读 近在某网站上看到一个视频 是关于排序算法的可视化的 看着挺有意思的 也特别喜感 不知道作者是怎么做的 但是突然很想自己实现一
  • Qt中使用QFrame,并使得边框周围添加阴影的效果

    参考大神博客 https blog csdn net wzz953200463 article details 100533435 1 使用Qframe实现阴影的效果 首先我们需要放置一个frame控件在界面上 2 需要加上头文件 incl
  • 代码文档生成工具:Doxygen

    1 什么是 Doxygen Doxygen是一个程序的文档生成工具 可以将程序中的注释转换成说明文档或者说是API参考手册 同时也支持Markdown等文本工具 从而减少程序员整理文档的时间 程序中的注释需要遵循一定的规则书写 才能让Dox
  • SQL触发器编写与查看

    1 已有数据查看 2 编写触发器 以更新表一为条件 go create trigger TG Insert 创建触发器 on DB TABLE 20210528 定位某张表 for UPDATE 表 DB TABLE 20210528 更新
  • 微信小程序常见面试题

    1 小程序有几个文件 WXML 是框架设计的一套标签语言 结合基础组件 事件系统 可以构建出页面的结构 WXSS 用于描述 WXML 的组件样式 js 逻辑处理 json 小程序页面配置 2 微信小程序与 H5 的区别 运行环境 小程序的运
  • 【ChatGPT进阶】如何使用ChatGPT写小说?

    ChatGPT文本处理能力是毋庸置疑的 可以使用上下文相关的文本来进行自动推理和生成 它可以用来帮助写以更快的速度完成文章 它可以参考上下文 以提供有用的洞察力和见解 它可以大大提高写文章的效率 它可以从上下文中提取关键信息 然后使用这些信
  • WTL 界面设计篇(CSkinEdit)

    头文件声明 CSkinEdit h pragma once include SkinManager h 不支持滚动条皮肤 图片背景支持不完整 Edit控件必须是ES MULTILINE风格 SetMarginsEx才能生效 ES MULTI