1.Win32控件-ToolTip的使用

最近在MFC中使用ToolTip时有诸多疑惑,查阅了不少资料,仔细研究了MSDN文档,在此记录使用方法和注意事项,与大家共勉。

1.理论

首先,思考一下,如果是我们自己来实现ToolTip(工具提示)的功能,要如何做呢?最自然的想法是:当我们把鼠标移动到希望提示的窗口时弹出一个提示窗口,我们把鼠标移出希望提示的窗口时关闭提示窗口。OK,微软也不会比我们聪明多少,它的实现基本思想就是这样的。

需要注意的是微软为了保证使用的方便,使用了设计模式中的观察者模式,这样使用方便,但是却造成了理解上的不易。

简单来说,观察者模式就是设计有观察者和被观察对象,当被观察对象触发某些特定的动作时,会通知指定的观察者采取相关动作。这里观察者和被观察者要事先绑定并指定被观察对象如何向观察者发出通知,一般采用回调函数或消息通知的形式,这是Windows系统,当然是后一种了。

结合这里ToolTip的实现,观察者就是ToolTip(工具提示)窗口,被观察者就是希望提示的窗口(Tool窗口),当鼠标移动到希望提示的窗口(Tool窗口)上这一事件触发后就会通知ToolTip(工具提示)窗口弹出,或者当鼠标移出希望提示的窗口(Tool窗口)上这一事件触发后就会通知ToolTip(工具提示)窗口隐藏。

那么理论上,一般ToolTip的使用步骤如下:

1.创建Tooltip窗口,一般一个ToolTip窗口可用于多个Tool窗口的提示。

2.添加Tooltip窗口所观察Tool窗口

3.所观察Tool窗口产生鼠标移入和移出事件时通知Tooltip窗口显示和隐藏

2.实际使用

基本上微软的实现和我们理论上描述的差不多,我们要实际使用ToolTip主要是搞懂消息传递时的参数意义。

实际使用步骤如下:

1.使用CreateWindowEx创建ToolTip窗口

2.向新创建ToolTip窗口发送TTM_ADDTOOL消息,为创建的ToolTip窗口添加所观察Tool窗口

这个过程传递TOOLINFO类型参数来区别不同的Tool窗口和对应的提示文字

TOOLINFO的定义如下

typedef struct tagTOOLINFO{
    UINT      cbSize;
    UINT      uFlags;
    HWND      hwnd;
    UINT_PTR  uId;
    RECT      rect;
    HINSTANCE hinst;
    LPTSTR    lpszText;
#if (_WIN32_IE >= 0x0300)
    LPARAM lParam;
#endif
#if (_WIN32_WINNT >= 0x0501)
    void *lpReserved;
#endif
} TOOLINFO, NEAR *PTOOLINFO, *LPTOOLINFO;

部分参数定义如下

[1].cbSize

指的是TOOLINFO的大小,这里一定要注意,许多有问题的地方就源于这里。主要问题是下面这一句的定义

#if (_WIN32_WINNT >= 0x0501)
    void *lpReserved;
#endif

在一些低版本的系统中使用高版本的编译器,如在Windows 2000中使用VS 2005,这时候编译器默认的版本大于0x0501,这个时候会有void *lpReserved定义,但是实际的Windows 2000中的comctl32.dll版本偏低,并没有定义相关字段,当实际调用时传递给dll中的TOOLINFO参数中cbSize偏大,dll检测到这一条件后添加Tool窗口就失败了。

解决方法很简单,加载对应的dll或者减少cbSize。

在高版本的编译器中,定义对应低版本操作系统的版本号_WIN32_WINNT 就可以减少cbSize了

提供高版本的dll并在高版本的编译器中使用清单文件即可加载对应的DLL版本

当然,如果你不是在低版本的系统中使用高版本的编译器中使用的话就不需要考虑这个问题了。最常见的问题就是在XP中使用VS2005、2008系列编译器引起的问题,这种情况下最简单的就是链接正确的6.0版本 DLL如下:

#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif

[2].uFlags

指明一些配置参数,见具体使用说明

以下两个参数指明希望显示工具提示的窗口或控件,只需要选择一种情况

[3].rect

如果希望鼠标移动到某一个窗口的一个指定区域时显示提示,这个rect就是指定区域,这个时候hwnd就是这个窗口句柄。这个时候uID只是一个自定义标识,用来区别不同的区域。

[4].uId

如果希望标移动到某一个控件时显示提示:uId就是这个控件的ID号,这时候需要指明包含这个控件的窗口句柄hwnd;如果指定uFlags参数包含TTF_IDISHWND,这时候uId就是这个控件的句柄,这时候不需要指明hwnd。

以下参数指明希望显示的工具提示文字

[5].lpszText

指明工具提示的显示文字:当定义了hInstance时,lpszText是对应的字符串资源ID号;如果没有定义hInstance,lpszText指向自定义的字符串buffer。如果指明lpszText参数为LPSTR_TEXTCALLBACK,创建ToolTip控件时会发送给hwnd指定的窗口一个TTN_GETDISPINFO的通知消息让用户响应这个消息以获得显示的工具提示字符串。

3.当鼠标移入或移出希望显示工具提示的窗口或控件时,通知ToolTip提示窗口显示或隐藏

这里我们自然想到的是在希望显示工具提示的窗口或控件中响应鼠标消息。

1.但是这样做不仅麻烦,而且有些对话框和全部控件无法响应WM_MOUSE消息。这里,微软使用子类化希望显示工具提示的窗口或控件的方法截取指定的鼠标消息来通知ToolTip窗口显示或隐藏。在uFlags参数中指明TTF_SUBCLASS,这样在发送TTM_ADDTOOL时就子类化了对应的窗口或控件,一般指明了这个参数就不需要用户再做其他工作,这也是满足绝大多数应用的使用方法。

2.当然,你也可以自己子类化对应窗口或控件,给ToolTip提示窗口发送TTM_RELAYEVENT通知消息。

3.但是对于一些单纯使用子类化无法截取消息的窗口如系统对话框,可能必须使用DLL钩子来完成这样的消息重导向。

3.代码实现

首先确认加载对应版本控件

然后在WM_CREATE或WM_INITDIALOG消息中创建ToolTip工具提示窗口

//创建提示窗口
hwndTip = CreateWindowEx(	WS_EX_TOPMOST,
							TOOLTIPS_CLASS,
							NULL,
							WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							CW_USEDEFAULT,
							hDlg,
							NULL,
							hInstance,
							NULL
							);

接下来为各个窗口和控件添加提示文字,在这个过程中做了窗口子类化的工作,注意随鼠标移动(Track类)的工具提示还是要自己处理WM_MOUSEMOVE消息,并且他不能和其他的窗口或控件共用ToolTip提示窗口。下面是各种常用情况的添加工具提示,完整的实现见附件源代码。

/**
 *功能:	为hwnd指定窗口区域rect添加工具提示文字szTipText
 *参数:	hwndTip -- 用于显示提示文字的ToolTip窗口
 *		hwnd、rect、uId --要显示提示文字的窗口、区域和自定义的ID
 *		szTipText --待显示的工具提示文字
 *返回:	无
 *其他:	2014/05/30 By Jim Wen Ver1.0
**/
void AddRectTool(HWND hwndTip,
				 HWND hwnd, RECT rect, UINT uid,
				 LPCTSTR szTipText)
{
	TOOLINFO	tti;

	//设置提示窗口的信息
	memset(&tti, 0, sizeof(TOOLINFO));
	tti.cbSize		= sizeof(TOOLINFO);
	tti.uFlags		= TTF_SUBCLASS;
	tti.hwnd		= hwnd;
	tti.rect		= rect;
	tti.uId			= uid;
	tti.lpszText	= szTipText; 

	//新增一个提示
	SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &tti);
} 

/**
 *功能:	为指定控件添加工具提示文字
 *参数:	hwndTip -- 用于显示提示文字的ToolTip窗口
 *		hwnd、uId --控件的父窗口、控件ID
 *		hInstance、szStringRes --应用程序句柄和工具提示文字字符串资源ID
 *返回:	无
 *其他:	2014/05/30 By Jim Wen Ver1.0
**/
void AddWindowTool1 (HWND hwndTip,
					 HWND hwnd, UINT uid,
					 HINSTANCE hInstance, LPCTSTR szStringRes)
{
	TOOLINFO	tti;

	//设置提示窗口的信息
	memset(&tti, 0, sizeof(TOOLINFO));
	tti.cbSize		= sizeof(TOOLINFO);
	tti.uFlags		= TTF_IDISHWND | TTF_SUBCLASS ;
	tti.uId			= (UINT_PTR)GetDlgItem(hwnd, uid);
	tti.hinst		= hInstance;
	tti.lpszText	= szStringRes;

	//新增一个提示
	SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &tti);
} 

/**
 *功能:	为指定控件添加工具提示文字,这里的文字通过给hwnd发送消息来获得
 *参数:	hwndTip -- 用于显示提示文字的ToolTip窗口
 *		hwnd、uId --控件的父窗口、控件ID
 *返回:	无
 *其他:	2014/05/30 By Jim Wen Ver1.0
**/
void AddWindowTool2 (HWND hwndTip,
					 HWND hwnd, UINT uid)
{
	TOOLINFO		tti;

	//设置提示窗口的信息
	memset(&tti, 0, sizeof(TOOLINFO));
	tti.cbSize		= sizeof(TOOLINFO);
	tti.uFlags		= TTF_IDISHWND | TTF_SUBCLASS ;
	tti.hwnd		= hwnd;
	tti.uId			= (UINT_PTR)GetDlgItem(hwnd, uid);
	tti.lpszText	= LPSTR_TEXTCALLBACK;

	//新增一个提示
	SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &tti);
} 

/**
 *功能:	为指定控件添加工具提示文字,这个工具提示是随鼠标移动的,这个不能定义TTF_SUBCLASS,必须自己传递鼠标消息
 *		在WM_MOUSE中通过TTM_TRACKPOSITION来确认工具提示文字位置
 *		可以通过TTM_TRACKACTIVATE来确认显示和隐藏
 *		不能和其他的提示共用一个ToolTip提示窗口
 *参数:	hwndTip -- 用于显示提示文字的ToolTip窗口
 *		hwnd、uId --控件的父窗口、控件ID
 *		szTipText --待显示的工具提示文字
 *返回:	无
 *其他:	2014/05/30 By Jim Wen Ver1.0
**/
BOOL g_bIsVisible=FALSE;
void AddWindowTool3 ( HWND hwndTip,
					  HWND hwnd, UINT uid,
					  LPCTSTR szTipText)
{
	TOOLINFO	tti;

	//设置提示窗口的信息
	memset(&tti, 0, sizeof(TOOLINFO));
	tti.cbSize		= sizeof(TOOLINFO);
	tti.uFlags		= TTF_IDISHWND | TTF_TRACK ;
	tti.uId			= (UINT_PTR)GetDlgItem(hwnd, uid);
	tti.lpszText	= szTipText;

	//新增一个提示
	SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &tti);

	//显示工具提示
	SendMessage(hwndTip, TTM_TRACKACTIVATE,(WPARAM)TRUE,(LPARAM)&tti);
	g_bIsVisible = TRUE;
} 

/**
 *功能:	为指定控件添加多行工具提示文字,这里的文字必须通过给hwnd发送消息来获得
 *参数:	hwndTip -- 用于显示提示文字的ToolTip窗口
 *		hwnd、uId --控件的父窗口、控件ID
 *返回:	无
 *其他:	2014/05/30 By Jim Wen Ver1.0
**/
void AddWindowTool4 (HWND hwndTip,
					 HWND hwnd, UINT uid,
					 LPCTSTR szTipText)
{
	TOOLINFO		tti;

	//设置提示窗口的信息
	memset(&tti, 0, sizeof(TOOLINFO));
	tti.cbSize		= sizeof(TOOLINFO);
	tti.uFlags		= TTF_CENTERTIP | TTF_IDISHWND | TTF_SUBCLASS ;
	tti.hwnd		= hwnd;
	tti.uId			= (UINT_PTR)GetDlgItem(hwnd, uid);
	tti.lpszText	= LPSTR_TEXTCALLBACK;

	//新增一个提示
	SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &tti);
} 

完整演示源代码下载链接

原创,转载请注明来自http://blog.csdn.net/wenzhou1219

1.Win32控件-ToolTip的使用,布布扣,bubuko.com

时间: 2024-12-27 08:50:20

1.Win32控件-ToolTip的使用的相关文章

win32 控件的创建和消息响应

1. 控件的创建 控件的创建和窗口创建是一样的,例如: //-------- 创建窗口或控件 ----hwnd = CreateWindow("button","myButton01", WS_VISIBLE|WS_CHILD, 80,60,35,25, hWnd,(HMENU)IDB_BUTTON01,hInst,NULL); 是一个按钮的创建,其中hWnd是窗口句柄,hInst是应用程序句柄. 其他控件类似的可以把第一个参数"button"改

onmouseover 执行 ToolTip 控件

Tooltip控件是一个简单,但非常有用的控件.它能够为我们的软件提供非常漂亮的提示信息,提高软件的可用性,给用户比较好的体验.假设现在有两个按钮,一个用来预览吊线世系图,一个用来预览行转.为了保持按钮文本的简洁,以及为按钮尺寸所限.我们不能可能把这个按钮的主要功能通过text属性表述清楚,这个时候我们就可以用到tooltip控件了. 首先我们在按钮所在窗体添加一个tooltip控件,将id该为ttMsg.这个时候你几乎可以在当前窗体的所有控件的属性框中添加了一个叫ttMsg上的tooltip属

ToolTip控件的应用

Tooltip控件是一个简单,但非常有用的控件.它能够为我们的软件提供非常漂亮的提示信息,提高软件的可用性,给用户比较好的体验.假设现在有两个按钮,一个用来预览吊线世系图,一个用来预览行转.为了保持按钮文本的简洁,以及为按钮尺寸所限.我们不能可能把这个按钮的主要功能通过text属性表述清楚,这个时候我们就可以用到tooltip控件了. 首先我们在按钮所在窗体添加一个tooltip控件,将id该为ttMsg.这个时候你几乎可以在当前窗体的所有控件的属性框中添加了一个叫ttMsg上的tooltip属

silverlight中常用的控件

一.布局控件 Canvas面板是一种很基础的布局面板,它支持对其中的控件采用绝对坐标定位.Canvas.Top和Canvas.Left.Canvas.ZIndex附加属性:如果指定了两个控件相对于父容器Canvas同样的边距,则后面声明的控件父覆盖前面声明的控件.这时我们可以使用Canvas.ZIndex属性来改变它们的显示顺序. StackPanel是一种简单的布局面板,它支持用行或列的方式来定位其中包含的控件.StackPanel 常用于安排页面上的一个很小的 UI 部分.默认情况下,Ori

WPF控件中可以用来记录数据用的属性总结

今天遇到一个问题需要为每个控件tooltip根据不同情况显示多组数据,于是需要用到控件的某个属性暂存这个数据.好吧,现在我找到了3个属性可用,给自己做个备忘. 1.Tag 这个属性是object类型 比较灵活(不过这个我们项目其他地方用到了) 2.Uid  这个属性是string类型 可以用来存储一段数据(我就用这个做的) 3.ToolTip 这个属性是object类型 不过设置这个要注意,而且比较麻烦,想要不让其他人看到还要在事件里处理. 以上就是我找到的几个可用属性,如有其它属性欢迎补充.

进度条控件CProgressCtrl实现进度滚动效果

关于CProgressCtrl 控件的基本操作网上有很多资料,可我想实现进度条中进度滚动效果,即很多时候程序出现的等待或启动画面,如下图: 实现这个效果的函数为SetMarquee(_In_ BOOL fMarqueeMode, _In_ int nInterval),第一个参数为开关,第二个参数指定滚动时间.且控件应该包含 PBS_MARQUEE风格,eg:m_ProgressCtl.Create(WS_CHILD|WS_VISIBLE|PBS_MARQUEE,CRect(100,200,25

MFC 访问控件的几种方法

访问控件的方法 控件是一种交互的工具,应用程序需要通过某种方法来访问控件以对其进行查询和设置.访问控件有四种方法: 利用对话框的数据交换功能访问控件.这种方法适用于自动创建的控件.先用ClassWizard为对话框类加入与控件对应的数据成员变量,然后在适当的时侯调用UpdateData,就可以实现对话框和控件的数据交换.这种方法只能交换数据,不能对控件进行全面的查询和设置,而且该方法不是针对某个控件,而是针对所有参与数据交换的控件.另外,对于新型的Win32控件,不能用ClassWizard创建

Win32 SDK程序创建一些控件(简单调用InitCommonControlsEx,并指定ICC_LISTVIEW_CLASSES控件就可以了)

在Win32 SDK中创建一些控件的时候需要注意一下(具体是哪些控件请参看MSDN文档中列出来的) [cpp] view plain copy /* MSDN:Carries information used to load common control classes from the * dynamic-link library (DLL).This structure is used with the InitCommonControlsEx function. * 需要使用的结构体和函数

win32 sdk树形控件的项拖拽实现

本课中,我们将学习如何使用树型视图控件.另外还要学习如何在树型视图中完成拖-拉动作,以及如何使用图象列表. 理论: 树型视图是一种特别的窗口,我们可以使用它一目了然地表示某种层次关系.譬如象在资源管理器中左边窗口中的就是树型视图.您可以调用CreateWindowEx来创建树型视图,传递一个类名""SysTreeView32"",或者您也可以把它放到一个对话框中去.不要忘了在您的代码中加入InitCommonControls函数. 树型视图有几种特有的风格.下面是几