透明信息提示框CFyToolTip设计及源码 适用于各类绘图的实时信息展示

在图形绘制领域,经常需要用到透明的信息提示窗口,比如当鼠标移动到一个图元上,显示该图元对象的实时数据(如设备名称、状态、实测数据等),当鼠标移开,及时隐藏该提示框;比如在曲线控件绘图时,随着鼠标移动,实时展示曲线对应的横纵坐标值等。

各种通用开发库里,也有类似的控件,如C# WinForm的ToolTip,1>风格比较厚实,透明度不好,遮挡住了底部的图形;2>Tip窗口显示和隐藏不灵敏,感觉顿挫。浮云绘图将在本文详细设计和实现透明信息提示框CFyToolTip类。

一、透明提示框的需求描述

1. 需支持显示和隐藏功能;

2. 需支持设定指定显示位置功能;

3. 需支持设置或动态计算提示框的窗口大小尺寸;

4. 需支持提示框背景色和边框颜色;

5. 需支持提示框文本字体类型和字号设置;

6. 需支持多行信息提示;

7. 需支持每行设置不同的文本内容和字体颜色。

二、透明提示框的定义(C++)

根据上文的开发需求和上图的展示效果,相应属性定义如下代码。

显示Tip框方法有4个:

void ShowTips(CPoint& point, CRect& parentRect, CString* vals, int* colors, int count)用于实现上图实时测量多行文本多颜色字体的信息提示,当然也可以用于所有情形信息提示。

void ShowXTips(int xCenter, int yTop, CString strTipsContent)用于实现上图X轴上的居中显示的信息提示框。
void ShowY1Tips(int xRight, int yCenter, CString strTipsContent)用于显示左侧Y轴的信息提示。
void ShowY2Tips(int xLeft, int yCenter, CString strTipsContent)用于显示右侧Y轴的信息提示。

// 作者:浮云绘图,专业付费定制图形编辑器、工控曲线、报表等各类绘图软件
// QQ:316868127

class CFyToolTip : public CWnd
{
private:
	CPoint  m_ptOrg;            //左上角坐标
	CSize   m_TipSize;          
	CString m_strTips;
	COLORREF m_clrBack = 0xE0E0E0;
	COLORREF m_clrText = 0x000000;
	COLORREF m_clrFrameColor;

	bool m_bMultLineTip = false;		//多行不同颜色文字Tip模式标记
	CString* m_values = NULL;           //多行文本
	int* m_colors = NULL;               //多行字体颜色
	int m_lineCount = 0;

	CString m_fontName = "微软雅黑";
	int m_fontSize = 8;

	// Construction
public:
	CFyToolTip();
	virtual ~CFyToolTip();

public:
	BOOL Create(CWnd* pWnd, BYTE bAlpha, DWORD dwStyle= WS_POPUP);	

	void SetToolTipSize(CSize szSize);

	void ShowTips(int nX, int nY, CString strTipsContent);

	void HideTips();

	void SetBkColor(COLORREF clrBack);

	void SetTipTextColor(COLORREF clrText);

	void SetFrameColor(COLORREF clrFrame);

	void ShowTips(CPoint& point, CRect& parentRect, CString* vals, int* colors, int count);

	void ShowXTips(int xCenter, int yTop, CString strTipsContent);
	void ShowY1Tips(int xRight, int yCenter, CString strTipsContent);
	void ShowY2Tips(int xLeft, int yCenter, CString strTipsContent);

	int GetTipsTextHeight();

	void DrawTransparentRect(CDC* dc, CRect* rect);

protected:
	//{{AFX_MSG(CFyToolTip)
	afx_msg void OnPaint();
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

三、透明提示框的实现

请看OnPaint函数,先重绘客户区背景和边框 --> 再画各行文本(文字、字体和颜色)。

每当调用ShowTips函数时,根据传入的显示起点和显示内容,重新计算Tip窗口的大小位置,再调用OnPaint完成重绘。

// 作者:浮云绘图,专业付费定制图形编辑器、工控曲线、报表等各类绘图软件
// QQ:316868127

BOOL CFyToolTip::Create(CWnd* pWnd, BYTE bAlpha, DWORD dwStyle)
{
	LPCTSTR lpszClassName = AfxRegisterWndClass(NULL);
	BOOL bRet = CreateEx(WS_EX_TOOLWINDOW | WS_EX_TOPMOST, lpszClassName, _T(""),		//WS_EX_TOOLWINDOW  WS_EX_TOPMOST
		dwStyle, 0, 0, 1, 1, pWnd->GetSafeHwnd(), NULL);								// WS_POPUP WS_CHILD
	if (bRet)
	{
		CSize sz(30,20);
		MoveWindow(CRect(m_ptOrg, sz));
		m_TipSize = sz;
	}

	LONG para = GetWindowLong(this->GetSafeHwnd(), GWL_EXSTYLE);
	para |= WS_EX_LAYERED;
	SetWindowLong(this->GetSafeHwnd(), GWL_EXSTYLE, para);
	SetLayeredWindowAttributes(RGB(0, 0, 0), bAlpha, LWA_ALPHA);	//LWA_ALPHA 

	m_parent = pWnd;
	return bRet;
}

void CFyToolTip::OnPaint()
{
	CPaintDC dc(this); // device context for painting

	// TODO: Add your message handler code here
	CRect rtWin;
	GetClientRect(rtWin);
	dc.FillSolidRect(rtWin, m_clrBack);
	dc.SetBkMode(TRANSPARENT);
	dc.Draw3dRect(rtWin, m_clrFrameColor, m_clrFrameColor);
	
	CFont font;
	font.CreatePointFont(m_fontSize * 10, m_fontName, NULL);
	CFont* pOldFont = dc.SelectObject(&font);

	CRect curLineRect;
	if (!m_bMultLineTip)
	{
		CSize txtSize = dc.GetTextExtent(m_strTips);      // 字串的长度像素
		curLineRect.SetRect(rtWin.left + 0, 1, rtWin.right, txtSize.cy);
		dc.SetTextColor(m_clrText);
		dc.DrawText(m_strTips, rtWin, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
	}
	else
	{
		int offsetY = 1;
		for (int i = 0; i < m_lineCount; i++)
		{
			CSize txtSize = dc.GetTextExtent(m_values[i]);      // 字串的长度像素

			dc.SetTextColor(m_colors[i]);
			curLineRect.SetRect(rtWin.left + 4, offsetY, rtWin.right, offsetY + txtSize.cy);
			dc.DrawText(m_values[i], curLineRect, DT_LEFT | DT_VCENTER | DT_SINGLELINE);

			offsetY += txtSize.cy + 1;
		}
	}
	dc.SelectObject(pOldFont);
}



void CFyToolTip::ShowTips(int nX, int nY, CString strTipsContent)
{
	m_bMultLineTip = false;

	
	m_strTips = strTipsContent;

	//计算字符串长宽
	HDC hDC = ::GetDC(this->m_hWnd);
	CDC dc;
	dc.Attach(hDC);

	CFont font;
	font.CreatePointFont(m_fontSize * 10, m_fontName, NULL);
	CFont* pOldFont = dc.SelectObject(&font);
	CSize txtSize = dc.GetTextExtent(m_strTips);      // 字串的长度像素
	dc.SelectObject(pOldFont);

	//设置窗口位置大小
	m_ptOrg = CPoint(nX, nY);
	m_TipSize= txtSize;
	MoveWindow(nX, nY, m_TipSize.cx, m_TipSize.cy, TRUE);
	if (!IsWindowVisible())
	{
		ShowWindow(SW_SHOW);
	}
	Invalidate(TRUE);
}

void CFyToolTip::ShowXTips(int xCenter, int yTop, CString strTipsContent)
{
	m_bMultLineTip = false;

	m_strTips = strTipsContent;

	//计算字符串长宽
	HDC hDC = ::GetDC(this->m_hWnd);
	CDC dc;
	dc.Attach(hDC);

	CFont font;
	font.CreatePointFont(m_fontSize * 10, m_fontName, NULL);
	CFont* pOldFont = dc.SelectObject(&font);
	CSize txtSize = dc.GetTextExtent(m_strTips);      // 字串的长度像素
	dc.SelectObject(pOldFont);

	//设置窗口位置大小
	int nX = xCenter - txtSize.cx / 2;
	m_ptOrg = CPoint(nX, yTop);
	m_TipSize = txtSize;
	MoveWindow(nX, yTop, m_TipSize.cx + 2, m_TipSize.cy, TRUE);
	if (!IsWindowVisible())
	{
		ShowWindow(SW_SHOW);
	}
	Invalidate(TRUE);
}

void CFyToolTip::ShowY1Tips(int xRight, int yCenter, CString strTipsContent)
{
    ......
}

void CFyToolTip::ShowY2Tips(int xLeft, int yCenter, CString strTipsContent)
{
    ......
}

void CFyToolTip::ShowTips(CPoint& point, CRect& parentRect, CString* vals, int* colors, int count)
{
    ......
}

void CFyToolTip::HideTips()
{
	if (IsWindow(m_hWnd))
	{
		ShowWindow(SW_HIDE);
	}
}


void CFyToolTip::SetBkColor(COLORREF clrBack)
{
	m_clrBack = clrBack;
}

void CFyToolTip::SetFrameColor(COLORREF clrFrame)
{
	m_clrFrameColor = clrFrame;
}

void CFyToolTip::SetTipTextColor(COLORREF clrText)
{
	m_clrText = clrText;
}
.....

本文完整了实现了上图展示的3中透明信息提示框,可以满足绝大多数对透明窗口信息提示框的功能要求。如果在某些特性场景下,还需要支持FyTipTool提示框支持鼠标 点击、移动等事件,可以继续扩展。需增加以下事件支持:

	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMouseLeave();

四、CFyToolTip使用示例

//1声明变量,Y轴上左Tip
CFyToolTip* m_y1ToolTip;        


//2构造变量,透明度200/255
m_y1ToolTip = new CFyToolTip();
m_y1ToolTip->Create(this, 200);


//3显示、隐藏提示框
if (GetPointInArea(point))
{
    CString syTip = GetYToolTip(point);
    int y1Right;
    GetYAxesTipXPos(virpoint, y1Right, y2Left);
    if (y1Right > 0)
    {
        CPoint tmpPt(y1Right, point.y);
        ClientToScreen(&tmpPt);
        m_y1ToolTip->ShowY1Tips(tmpPt.x, tmpPt.y, syTip);
    }
}
else
{
    m_y1ToolTip->HideTips();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浮云绘图

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值