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

Posted infoworld

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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

以上是关于[WTL/ATL]_[初级]_[TreeView控件如何显示ToolTip]的主要内容,如果未能解决你的问题,请参考以下文章

[WTL/ATL]_[初级]_[关于窗口子类析构时崩溃的原因]

[WTL/ATL]_[初级]_[使用虚拟列表视图来解决新增大量数据卡顿问题]

[WTL/ATL]_[初级]_[使用虚拟列表视图来解决新增大量数据卡顿问题]

[WTL/ATL]_[初级]_[关于窗口子类析构时崩溃的原因]

[WTL/ATL]_[初级]_[如何设置CEdit的文本框背景色和文字颜色]

[WTL/ATL]_[初级]_[如何设置CEdit的文本框背景色和文字颜色]