[WTL/ATL]_[初级]_[TreeView控件如何显示ToolTip]

场景

  1. 在开发界面程序时,CTreeViewCtrl(它实际内部封装的就是Win32TreeView控件)一般会用来作为选择某些类型的树形菜单,点击某项的时候,右边能显示某些对应的数据。当这个控件的宽度固定时,有时候每行的文本项可能由于过长从而穿透了整个控件的水平位置, 从而显示效果来看是不好的。这时候希望可以用省略号的样式来省略后边多出的文本,之后鼠标移动到这个文本项时能显示完整的文字,那么这个文本提示,或者说tooltip如何实现?

说明

  1. CTreeViewCtrlWTL的新版里可以使用它的子类CTreeViewCtrlExTCTreeViewCtrlExTHTREEITEM常用操作进行了封装,也可以对返回的CTreeItemT类进行操作,它提供了很多便利的方法对HTREEITEM的处理。
CTreeViewCtrlExT<CWindow> treeView_;
  1. 默认情况下,当创建一个CTreeViewCtrl时,默认就会创建一个tooltip,除非指定样式TVS_NOTOOLTIPS才不会创建这个子控件。可是就算是默认创建里,这个tooltip并不会自动显示,还需要进行一些编码。
treeView_.Create(m_hWnd,NULL,L"Tree",WS_VISIBLE | WS_CHILD | 
		TVS_SHOWSELALWAYS | 
		TVS_FULLROWSELECT |
		TVS_HASLINES |
		TVS_LINESATROOT |
		TVS_INFOTIP | WS_BORDER|
		TVS_HASBUTTONS,0,kMyTreeViewId);

auto tooltip = treeView_.GetToolTips();
assert(tooltip.m_hWnd);

  1. TreeView创建时如果提供了TVS_INFOTIP样式,当鼠标移动到文本项的上边时,就会触发一个TVN_GETINFOTIP通知。通过捕抓这个通知,就可以设置在tooltip显示的文本。没错,这个样式就是可让tooltip显示。注意,这个样式不能和TVS_NOTOOLTIPS使用,只有创建了tooltip才会有提示气泡。
BEGIN_MSG_MAP_EX(CView)
	NOTIFY_HANDLER_EX(kMyTreeViewId,TVN_GETINFOTIP,onInfoTip)
	REFLECT_NOTIFICATIONS()
END_MSG_MAP()


LRESULT CView::onInfoTip(LPNMHDR pnmh)
{
	LPNMTVGETINFOTIP pTip = (LPNMTVGETINFOTIP)pnmh;
	CTreeItem item(pTip->hItem,&treeView_);

	item.GetText(pTip->pszText, pTip->cchTextMax);
	return 0;
}

例子

  1. 通过onInfoTip方法,把HTREEITEM的文本内容复制到LPNMTVGETINFOTIP结构的文本字段里,它的长度最长有1024字节.

View.h

// View.h : interface of the CView class
//
/

#pragma once

#include <utility>
#include <string>


enum
{
	kMyStaticId = WM_USER+1,
	kMyTreeViewId,
	kMyButtonId
};

class CView : public CWindowImpl<CView>
{
public:
	DECLARE_WND_CLASS(NULL)

	BOOL PreTranslateMessage(MSG* pMsg);

	BEGIN_MSG_MAP_EX(CView)
		MSG_WM_CREATE(OnCreate)
		MESSAGE_HANDLER(WM_PAINT, OnPaint)
		NOTIFY_HANDLER_EX(kMyTreeViewId,TVN_GETINFOTIP,onInfoTip)
		REFLECT_NOTIFICATIONS()
	END_MSG_MAP()

// Handler prototypes (uncomment arguments if needed):
//	LRESULT MessageHandler(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
//	LRESULT CommandHandler(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
//	LRESULT NotifyHandler(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& /*bHandled*/)
	int OnCreate(LPCREATESTRUCT lpCreateStruct);
	LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
	void UpdateLayout();
	void AddMockData();
	void OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl);
	LRESULT onInfoTip(LPNMHDR pnmh);

private:
	std::wstring GetControlText(HWND hwnd,wchar_t* buf = NULL);
	HTREEITEM AppendItem(HTREEITEM hParentItem,LPWSTR pText,bool hasChildren = false);

	CTreeViewCtrlExT<CWindow> treeView_;

	CFont font_normal_;
	CFont font_bold_;

	CBrushHandle brush_white_;
	CBrushHandle brush_hollow_;
	CBrush brush_red_;
	CToolTipCtrl tooltip_;
	TCHAR strToolTipText_[MAX_PATH];

public:
};

View.cpp

// View.cpp : implementation of the CView class
//
/

#include "stdafx.h"
#include "resource.h"
#include <utility>
#include <sstream>
#include <assert.h>

#include "View.h"
#include <CommCtrl.h>
#include <string>
#include <regex>

using namespace std;

BOOL CView::PreTranslateMessage(MSG* pMsg)
{
	return FALSE;
}

LRESULT CView::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
	CPaintDC dc(m_hWnd);
	CMemoryDC mdc(dc,dc.m_ps.rcPaint);

	CRect rect_client;
	GetClientRect(&rect_client);
	mdc.FillSolidRect(rect_client,RGB(255,255,255));
	//TODO: Add your drawing code here

	return 0;
}

static HFONT GetFont(int pixel,bool bold,const wchar_t* font_name)
{
	LOGFONT lf; 
	memset(&lf, 0, sizeof(LOGFONT)); // zero out structure 
	lf.lfHeight = pixel; // request a 8-pixel-height font
	if(bold)
	{
		lf.lfWeight = FW_BOLD;  
	}
	lstrcpy(lf.lfFaceName, font_name); // request a face name "Arial"
	
	HFONT font = ::CreateFontIndirect(&lf);
	return font;
}


std::wstring CView::GetControlText(HWND hwnd,wchar_t* buf)
{
	auto length = ::GetWindowTextLength(hwnd);
	bool bufNull = false;
	if(!buf){
		buf = new wchar_t[length+1]();
		bufNull = true;
	}
	
	::GetWindowText(hwnd,buf,length+1);
	std::wstring str(buf);

	if(bufNull)
		delete []buf;

	return str;
}

static std::wstring GetProductBinDir()
{
	static wchar_t szbuf[MAX_PATH];  
	GetModuleFileName(NULL,szbuf,MAX_PATH);  
    PathRemoveFileSpec(szbuf);
	int length = lstrlen(szbuf);
	szbuf[length] = L'\\';
	szbuf[length+1] = 0;
	return std::wstring(szbuf);
}

HTREEITEM CView::AppendItem(HTREEITEM hParentItem,LPWSTR pText,bool hasChildren)
{
	TVINSERTSTRUCT tvis;
	tvis.hParent=hParentItem;
	tvis.hInsertAfter=TVI_LAST;

	tvis.itemex.mask=TVIF_TEXT|TVIF_PARAM;
	if(hasChildren)
		tvis.itemex.mask |= TVIF_CHILDREN;
	
	tvis.itemex.pszText=pText;

	return treeView_.InsertItem(&tvis);
}

void CView::AddMockData()
{
	AppendItem(NULL,L"Tobey");
	AppendItem(NULL,L"Level",true);
	auto nameItem = AppendItem(NULL,L"Website");
	AppendItem(nameItem,L"https://blog.csdn.net/infoworld");
}

int CView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	font_normal_ = ::GetFont(16,false,L"Arial");
	font_bold_ = ::GetFont(16,true,L"Arial");


	// `TVS_INFOTIP`样式是必须的,不然无法触发`TVN_GETINFOTIP`消息.
	// `TVS_NOTOOLTIPS`样式不能设置,如果设置了,不会创建`tooltip`控件; 
	// 默认`treeView`控件会创建一个`tooltip`控件.
	treeView_.Create(m_hWnd,NULL,L"Tree",WS_VISIBLE | WS_CHILD | 
		TVS_SHOWSELALWAYS | 
		TVS_FULLROWSELECT |
		TVS_HASLINES |
		TVS_LINESATROOT |
		TVS_INFOTIP | WS_BORDER|
		TVS_HASBUTTONS,0,kMyTreeViewId);

	// 会自动创建一个`tooltip`,这里只是一个例子
	auto tooltip = treeView_.GetToolTips();
	assert(tooltip.m_hWnd);
	AddMockData();

	brush_hollow_ = AtlGetStockBrush(HOLLOW_BRUSH);
	brush_white_ = AtlGetStockBrush(WHITE_BRUSH);
	brush_red_.CreateSolidBrush(RGB(255,0,0));
	UpdateLayout();

	return 0;
}

LRESULT CView::onInfoTip(LPNMHDR pnmh)
{
	LPNMTVGETINFOTIP pTip = (LPNMTVGETINFOTIP)pnmh;
	CTreeItem item(pTip->hItem,&treeView_);

	item.GetText(pTip->pszText, pTip->cchTextMax);
	return 0;
}

void CView::OnCommandIDHandlerEX(UINT uNotifyCode, int nID, CWindow wndCtl)
{
		
}

void CView::UpdateLayout()
{
	CRect rect;
	GetClientRect(&rect);

	CClientDC dc(m_hWnd);
	dc.SelectFont(font_normal_);

	CSize size_control(700,300);
	CRect rect_control = CRect(CPoint(20,20),size_control);
	treeView_.MoveWindow(rect_control);

}

图1:

在这里插入图片描述

下载

https://download.csdn.net/download/infoworld/87448039

参考

  1. TVM_SETTOOLTIPS message (Commctrl.h)

  2. How to Use Tree-View Infotips

  3. Tree View

  4. Using Tree-View Controls

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Peter(阿斯拉达)

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

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

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

打赏作者

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

抵扣说明:

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

余额充值