Duilib 源码分析之 ToolTip 篇
2017-12-15 16:41
661 查看
首先关于 ToolTip 的相关资料,建议先看一下百度百科的介绍:TOOLINFO
Duilib 中对 Tooltip 的用法还算是比较简单易懂的,而且实现方法也很简单,只需要为控件添加属性
以上代码段是创建、显示、隐藏 Tooltip 窗口的代码。从代码可以看出,一个窗口只创建了一个 Tooltip 的窗口,不论鼠标移动到哪个子控件上显示 Tooltip,其实都是显示的同一个 Windows 窗口,只不过会修改其中的文字而已
CreateWindowEx 创建一个 ToolTip 窗口
SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip) 将 Tooltip 的数据设置到当前 ToolTip 窗口中
::SendMessage(m_hwndTooltip,TTM_SETMAXTIPWIDTH,0, pHover->GetToolTipWidth()) 设置 ToolTip 窗口的宽度,我看了下 Duilib 中目前
::SendMessage(m_hwndTooltip, TTM_SETTOOLINFO, 0, (LPARAM)&m_ToolTip) 这行代码的作用其实是想改变 Tooltip 窗口中的文字,而且是在 Tooltip 隐藏的情况下,因为此时我们有可能是从前一个控件移动到下一个控件,此时需要重新显示 Tooltip 窗口并修改文字。控制 Tooltip 窗口的隐藏显示需要用到下面的 2 行代码
::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&m_ToolTip) 显示 Tooltip 窗口
::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip) 隐藏 Tooltip 窗口
接下来,如果我们在 Duilib 中搜索一下
这里用到 了一个 API :
cbSize -> 直接设置为
dwFlags ->代表
hwndTrack -> 寄送消息的目的窗口
dwHoverTime -> 发送
每次
Duilib 中对 Tooltip 的用法还算是比较简单易懂的,而且实现方法也很简单,只需要为控件添加属性
tooltip, 值是希望提示的字符串就可以了,当鼠标移动到控件上停留时,会发送 WM_MOUSEHOVER 消息,Duilib 此时就会开始显示 tooltip 窗口了。 接下来看一下实现 tooltip 的代码:
bool CPaintManagerUI::MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT& lRes) { ...... case WM_MOUSEHOVER: ...... // Create tooltip information CDuiString sToolTip = pHover->GetToolTip(); if( sToolTip.IsEmpty() ) return true; ::ZeroMemory(&m_ToolTip, sizeof(TOOLINFO)); m_ToolTip.cbSize = sizeof(TOOLINFO); m_ToolTip.uFlags = TTF_IDISHWND; m_ToolTip.hwnd = m_hWndPaint; m_ToolTip.uId = (UINT_PTR) m_hWndPaint; 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, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, m_hWndPaint, NULL, m_hInstance, NULL); ::SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip); ::SendMessage(m_hwndTooltip,TTM_SETMAXTIPWIDTH,0, pHover->GetToolTipWidth()); } if(!::IsWindowVisible(m_hwndTooltip)) { ::SendMessage(m_hwndTooltip, TTM_SETTOOLINFO, 0, (LPARAM)&m_ToolTip); ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&m_ToolTip); } ...... case WM_MOUSELEAVE: { if( m_hwndTooltip != NULL ) ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip); ..... } }
以上代码段是创建、显示、隐藏 Tooltip 窗口的代码。从代码可以看出,一个窗口只创建了一个 Tooltip 的窗口,不论鼠标移动到哪个子控件上显示 Tooltip,其实都是显示的同一个 Windows 窗口,只不过会修改其中的文字而已
CreateWindowEx 创建一个 ToolTip 窗口
SendMessage(m_hwndTooltip, TTM_ADDTOOL, 0, (LPARAM) &m_ToolTip) 将 Tooltip 的数据设置到当前 ToolTip 窗口中
::SendMessage(m_hwndTooltip,TTM_SETMAXTIPWIDTH,0, pHover->GetToolTipWidth()) 设置 ToolTip 窗口的宽度,我看了下 Duilib 中目前
m_nTooltipWidth默认为 300,而且没有对应的属性可以修改。我建议可以添加一个
tooltipwidth的属性,解析到此属性后调用已存在的方法:
void SetToolTipWidth(int nWidth)
::SendMessage(m_hwndTooltip, TTM_SETTOOLINFO, 0, (LPARAM)&m_ToolTip) 这行代码的作用其实是想改变 Tooltip 窗口中的文字,而且是在 Tooltip 隐藏的情况下,因为此时我们有可能是从前一个控件移动到下一个控件,此时需要重新显示 Tooltip 窗口并修改文字。控制 Tooltip 窗口的隐藏显示需要用到下面的 2 行代码
::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&m_ToolTip) 显示 Tooltip 窗口
::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &m_ToolTip) 隐藏 Tooltip 窗口
接下来,如果我们在 Duilib 中搜索一下
m_hwndTooltip的出现场景,除了上面提到的场景和窗口关闭时销毁窗口外,还有一个地方用到了
m_hwndTooltip:
case WM_MOUSEMOVE: { if( m_pRoot == NULL ) break; // Start tracking this entire window again... if( !m_bMouseTracking ) { TRACKMOUSEEVENT tme = { 0 }; tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_HOVER | TME_LEAVE; tme.hwndTrack = m_hWndPaint; tme.dwHoverTime = m_hwndTooltip == NULL ? m_iHoverTime : (DWORD) ::SendMessage(m_hwndTooltip, TTM_GETDELAYTIME, TTDT_INITIAL, 0L); _TrackMouseEvent(&tme); m_bMouseTracking = true; } }
这里用到 了一个 API :
BOOL TrackMouseEvent(LPTRACKMOUSEEVENT lpEventTrack), 这个函数可以寄送
WM_MOUSEHOVER
WM_MOUSELEAVE两个消息, 默认情况下 Windows 是不会向窗口发送这两个消息的,需要调用
TrackMouseEvent来实现。
RACKMOUSEEVENT的定义如下:
typedef struct tagTRACKMOUSEEVENT { DWORD cbSize; DWORD dwFlags; HWND hwndTrack; DWORD dwHoverTime; } TRACKMOUSEEVENT, *LPTRACKMOUSEEVENT;
cbSize -> 直接设置为
sizeof(TRACKMOUSEEVENT)即可
dwFlags ->代表
TrackMouseEvent寄送的消息类型,
TME_HOVER
TME_LEAVE分别对应 WM_MOUSEHOVER
WM_MOUSELEAVE,也可以两个都写上:
TME_HOVER | TME_LEAVE
hwndTrack -> 寄送消息的目的窗口
dwHoverTime -> 发送
WM_MOUSEHOVER消息前鼠标所需保持停止不动的时间
每次
TrackMouseEvent调用并发送消息后即失效,若想再次接收
WM_MOUSEHOVER
WM_MOUSELEAVE需要再次调用
TrackMouseEvent。这部分实现可以看一下
CPaintManagerUI::m_bMouseTracking的赋值情况,每次
WM_MOUSEHOVER
WM_MOUSELEAVE处理后即设置为
false, 且在
WM_MOUSEMOVE时发现为
false,会重新调用
TrackMouseEvent
相关文章推荐
- duilib之源码分析
- Duilib 源码分析之 COptionUI 篇
- DUiLib 源码分析——第二篇UIBase
- DUiLib 源码分析——第二篇UIBase
- Duilib 源码分析之 CResourceManager 篇
- BOOtstrap源码分析之 tooltip、popover
- Duilib 源码分析之消息流程篇
- DuiLib的源码分析
- Duilib 源码分析之 CTextUI 篇
- Duilib源码分析(六)整体流程
- DUiLib 源码分析——第一篇UIManager
- duilib之源码分析
- Duilib 源码分析之 Shortcut 篇
- Duilib 源码分析之 CButtonUI 篇
- DUiLib 源码分析——第一篇UIManager
- DUiLib 源码分析——第一篇UIManager
- DUiLib 源码分析——第二篇UIBase
- Duilib之源码分析
- duilib之源码分析
- DUiLib 源码分析——第二篇UIBase