悬浮提示是一种常见的提示,那么界面中的简单悬浮提示(只有文本的)是如何实现的?
下面简单的以CEGUI中的实现加以分析,下面的代码主要截取与设置悬浮提示相关的部分。悬浮提示其实也是一种特殊的界面,因此也派生自CEGUI各种窗口的基类Window类。
CEGUI中的window类继承自属性集和事件集:
class CEGUIEXPORT Window : public PropertySet, public EventSet
{
//!< 事件相关
///< 鼠标进入事件
virtual void onMouseEnters(MouseEventArgs& e);
///< 鼠标离开事件
virtual void onMouseLeaves(MouseEventArgs& e);
///< 鼠标移动事件
virtual void onMouseMove(MouseEventArgs& e);
//!< 成员变量相关
///< 窗口设置的文本
String d_text;
///< 窗口悬浮提示的文本
String d_tooltipText;
///< 窗口保存的指向悬浮提示的指针
Tooltip* d_customTip;
}
Tooltip继承自Window类,这样看起来Tooltip也类似成为了Window的一种属性,而通过Window::d_customTip及Tooltip::d_target可以进行方便地修改,Tooltip内部主要实现了设置关联目标窗口及控制显示的接口。
class CEGUIEXPORT Tooltip : public Window
{
///< 设置/获取目标窗口
void setTargetWindow(Window* wnd);
const Window* getTargetWindow();
///< 重置显示时间
void resetTimer(void);
///< 关联的目标窗口
const Window* d_target;
}
当鼠标进入窗口的有效范围时,会触发Tooltip类中重新定义的onMouseEnters()接口。
void Tooltip::onMouseEnters(MouseEventArgs& e)
{
///< 计算位置
positionSelf();
Window::onMouseEnters(e);
}
可以看出Tooltip只是计算了自身的位置,然后便调用Window类的接口。
void Window::onMouseEnters(MouseEventArgs& e)
{
///< 设置鼠标图标
getGUIContext().getMouseCursor().setImage(getMouseCursor());
///< 获取Window关联的Tooltip
Tooltip* const tip = getTooltip();
///< 判断tip是否为空,且tip不是父窗口
if (tip && !isAncestor(tip))
tip->setTargetWindow(this);
///< 触发事件
fireEvent(EventMouseEntersSurface, e, EventNamespace);
}
这其中调用了Tooltip的接口setTargetWindow():
void Tooltip::setTargetWindow(Window* wnd)
{
//...
///< 保存关联的目标窗口
d_target = wnd;
///< 设置Tooltip的窗口文本
setText(wnd->getTooltipText());
///< 重置显示时间
resetTimer();
//...
}
这里要注意一下,setText(wnd->getTooltipText())设置的是Tooltip的成员d_text,而非wnd的成员d_text。在Tooltip的渲染层,悬浮提示文字的尺寸及内容都是通过Tooltip的d_text来获取的。
Tooltip中并没有重新定义onMouseMove()这个接口,所以当鼠标在窗口上移动时,触发的是Window::onMouseMove
void Window::onMouseMove(MouseEventArgs& e)
{
///< 重新设置显示时间
Tooltip* const tip = getTooltip();
if (tip)
tip->resetTimer();
}
当鼠标离开窗口区域时,会触发OnMouseLeaves()
void Window::onMouseLeaves(MouseEventArgs& e)
{
const Window* const mw = getGUIContext().getWindowContainingMouse();
Tooltip* const tip = getTooltip();
///< 悬浮提示窗口存在且不为包含鼠标的wnd且不是当前窗口的父窗口时,将关联窗口指针置为空
if (tip && mw != tip && !(mw && mw->isAncestor(tip)))
tip->setTargetWindow(0);
///< 触发事件
fireEvent(EventMouseLeavesSurface, e, EventNamespace);
}