前言:我之所以将这两个部分放在一起写,当然是因为他们是有关系的啦,我们的窗口是不会响应WM_MOUSELEAVE和WM_MOUSEHOVER消息的,我们可以通过_TrackMouseEvent来激活这两个消息,让我们的窗口接收这两个消息,接收到消息后,我们能干嘛呢????注意WM_MOUSEHOVER消息,当我们在一个控件上停一段时间后,就会激发这个消息,这个消息应该叫“悬停”,所以,在鼠标悬停时,我们应该创建toolTip!!!!这就是两者的关系。我们先看_TrackMouseEvent是如何激活这两个消息的,然后再看怎样添加ToolTip。
先看个最终界面图,吸引下大家
默认情况下,窗口是不响应 WM_MOUSELEAVE 和 WM_MOUSEHOVER 消息的,所以要使用_TrackMouseEvent函数来激活这两个消息。调用这个函数后,当鼠标在指定窗口上停留超过一定时间或离开窗口后,该函数会 Post 这两个消息到指定窗口。
在stdafx.h中,添加所需要的头文件和库文件,代码如下:
#include <CommCtrl.h> #pragma comment(lib, "comctl32.lib")
(1)在对话框类中定义一个变量来标识是否追踪当前鼠标状态,之所以要这样定义是要避免鼠标已经在窗体之上时,一移动鼠标就不断重复产生 WM_MOUSEHOVER 。并初始化为false,意思是尚未开始追踪!
bool m_bMouseTracking;//追踪WM_MOUSELEAVE 和 WM_MOUSEHOVER 消息(2)在WM_MOUSEMOVE中开启追踪
case WM_MOUSEMOVE: { // Start tracking this entire window again... if( !m_bMouseTracking ) {//如果没有跟踪消息,则开启跟踪WM_MOUSEHOVER和WM_MOUSELEAVE消息 TRACKMOUSEEVENT tme = { 0 }; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_HOVER | TME_LEAVE; tme.hwndTrack = m_hWnd;// 指定要 追踪 的窗口 tme.dwHoverTime = 10;// 鼠标在按钮上停留超过 10ms ,才认为状态为 HOVER _TrackMouseEvent(&tme);// 开启 Windows 的 WM_MOUSELEAVE , WM_MOUSEHOVER 事件支持 m_bMouseTracking = true;//为true表示已经开启追踪,false表示现在未跟踪 } }(3)WM_MOUSEHOVE、WM_MOUSELEAVE中的处理
case WM_MOUSEHOVER: { m_bMouseTracking=false; } return true; case WM_MOUSELEAVE: { if( m_bMouseTracking ) ::SendMessage(m_hWnd, WM_MOUSEMOVE, 0, (LPARAM) -1); m_bMouseTracking = false; } break;
HWND m_hwndTooltip;//TOOLTIP的句柄 TOOLINFO m_ToolTip;讲解:
在需要创建显示TOOLTIP的地方,按照下面的代码,创建就会直接显示出来;
// Create tooltip information CStdString sToolTip = L"HAHA HERE XXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXXXXXXX"; if( sToolTip.IsEmpty() ) return true; ::ZeroMemory(&m_ToolTip, sizeof(TOOLINFO)); //m_ToolTip.cbSize = sizeof(TOOLINFO); m_ToolTip.cbSize=TTTOOLINFOA_V2_SIZE; m_ToolTip.uFlags = TTF_IDISHWND | TTF_SUBCLASS; m_ToolTip.hwnd = m_hWnd; m_ToolTip.uId = (UINT_PTR) m_hWnd; m_ToolTip.hinst = m_hInstance; m_ToolTip.lpszText = const_cast<LPTSTR>( (LPCTSTR) sToolTip ); m_ToolTip.rect =pHover->GetPos();//不用指定显示位置,系统会自动判断位置 if( m_hwndTooltip == NULL ) { m_hwndTooltip = ::CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd, NULL, m_hInstance, NULL); ::SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip); ::SendMessage(m_hwndTooltip, TTM_SETMAXTIPWIDTH, 0, 20); //要多行显示,要先加上这个,然后在要分段的地方加上\n } ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &m_ToolTip);讲解:
2、m_ToolTip.cbSize的填充必须注意!!!!----直接影响到会不会显示出来,这部分会引用另一篇文章在下面讲解(参见:四、参考 ---2);
有些同鞋,根据上面的创建步骤死活就是显示不出来,为什么呢!!!!!m_ToolTip.cbSize赋值时出错了!!!!
如果#define _WIN32_WINNT 0x0500,赋值方式必须是:
m_ToolTip.cbSize = sizeof(TOOLINFO)而如果_WIN32_WINNT >= 0x0501,对应的赋值方式必须是:
m_ToolTip.cbSize=TTTOOLINFOA_V2_SIZE;3、多行显示
::SendMessage(m_hwndTooltip, TTM_SETMAXTIPWIDTH, 0, 20); //要多行显示,要先加上这个,然后在要分段的地方加上\n
if( m_hwndTooltip != NULL ) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip);
我们在《WIN32界面开发之四:CPaintManagerUI类构建》的基础上进行修改,利用这些教程逐步逼近DUILIB,争取把DUILIB一步步实现,如果对上篇还不了解的同学,还是先看看DUIRudiment是怎么构架的吧。突然到一节来估计是看不懂的。按照上面的内容,大家也应该知道,我们这里要添加的功能就是添加_TrackMouseEvent和TOOLTIP
1、为CPaintManagerUI添加m_hInstance变量;
大家从TOOLTIP的创建也可以知道,创建ToolTip是要当前应用程序的hInstance的,所以我们要先保存起来,与DUILIB一致,添加静态变量:
static HINSTANCE m_hInstance;//注意在类外初始化和一个设置函数:
static void SetInstance(HINSTANCE hInst);设置函数的实现:
void CPaintManagerUI::SetInstance(HINSTANCE hInst) { m_hInstance = hInst; }2、初始化m_hInstance
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nShowCmd){ Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); CPaintManagerUI::SetInstance(hInstance); CStartPage *startPage=new CStartPage(); startPage->SetInstance(hInstance); startPage->Create(); startPage->ShowWindow(true); Message(); delete startPage; Gdiplus::GdiplusShutdown(gdiplusToken); return 0; }
在WM_MOUSEHOVER中创建TOOLTIP,先看代码:
case WM_MOUSEHOVER: { m_bMouseTracking = false; POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; CControlUI* pHover =m_pRoot->FindCtrlFromPT(pt); if( pHover == NULL ) break; // Generate mouse hover event if( m_pEventHover != NULL ) { TEventUI event = { 0 }; event.ptMouse = pt; event.Type = UIEVENT_MOUSEHOVER; event.pSender = m_pEventHover; event.dwTimestamp = ::GetTickCount(); m_pEventHover->Event(event); }//这段与创建TOOLTIP无关,这里是给控件发送HOVER事件 // Create tooltip information CStdString sToolTip = L"HAHA HERE XXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXX\nXXXXXXXXXXXXXXXXXXXXXXX"; if( sToolTip.IsEmpty() ) return true; ::ZeroMemory(&m_ToolTip, sizeof(TOOLINFO)); //m_ToolTip.cbSize = sizeof(TOOLINFO); m_ToolTip.cbSize=TTTOOLINFOA_V2_SIZE; m_ToolTip.uFlags = TTF_IDISHWND | TTF_SUBCLASS; m_ToolTip.hwnd = m_hWnd; m_ToolTip.uId = (UINT_PTR) m_hWnd; m_ToolTip.hinst =m_hInstance; m_ToolTip.lpszText = const_cast<LPTSTR>( (LPCTSTR) sToolTip ); m_ToolTip.rect =pHover->GetPos();//不用指定显示位置,系统会自动判断位置 if( m_hwndTooltip == NULL ) { m_hwndTooltip = ::CreateWindowEx(0, TOOLTIPS_CLASS, NULL, WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_BALLOON, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hWnd, NULL,m_hInstance, NULL); ::SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip); ::SendMessage(m_hwndTooltip, TTM_SETMAXTIPWIDTH, 0, 20); //要多行显示,要先加上这个,然后在要分段的地方加上\n } ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &m_ToolTip); } return true;讲解:
#ifndef _WIN32_WINNT // 指定要求的最低平台是 Windows Vista。 #define _WIN32_WINNT 0x0600 // 将此值更改为相应的值,以适用于 Windows 的其他版本。 #endif
这里有两个地方要撤销显示,首先当鼠标移出控件时,要撤销显示,再者,在移出当前窗体时,也要撤销显示;
1、鼠标移出控件时的代码:
在WM_MOUSEMOVE中,在移出控件时,添加SendMessage---TTM_TRACKACTIVATE , FALSE
if( pNewHover != m_pEventHover && m_pEventHover != NULL ) { event.Type = UIEVENT_MOUSELEAVE; event.pSender = m_pEventHover; m_pEventHover->Event(event); //在鼠标离开控件时,要取消激活TOOLTIP,也就是让其不显示! if( m_hwndTooltip != NULL ) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip); m_pEventHover = NULL; }2、鼠标移出窗体时
由于我们用_TrackMouseEvent监听的HWND是窗体的HWND,所以鼠标在移出窗体时,会触发WM_MOUSELEAVE消息;所以在WM_MOUSELEAVE同样添加撤销代码:
case WM_MOUSELEAVE: { if( m_hwndTooltip != NULL ) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip); if( m_bMouseTracking ) ::SendMessage(m_hWnd, WM_MOUSEMOVE, 0, (LPARAM) -1); m_bMouseTracking = false; }
1、MSDN关于TOOLLIP的各项参数及用法讲解:http://msdn.microsoft.com/en-us/library/windows/desktop/bb760246%28v=vs.85%29.aspx
本文由HARVIC完成,如若转载,请标明出处,请大家尊重初创者的版权,谢谢!!
源文地址:http://blog.csdn.net/harvic880925/article/details/9796229
源码地址:http://download.csdn.net/detail/harvic880925/5881347
声明:感谢金山影音漂亮的界面图片,该图片来自网络。