Duilib支持自绘tooltip

来源:互联网 发布:js select 选中值 编辑:程序博客网 时间:2024/05/20 09:22

由于Duilib的tooltip使用的是系统默认的实现,这里希望他能像普通窗口一样使用xml定制界面,所以决定尝试修改Duilib源码实现这个效果,最终还是做出一个版本。效果图:


1.为CControlUI增加下面4个函数:

virtual void SetUserToolTipXml(LPCTSTR pstrXml);virtual CDuiString GetUserToolTipXml() const;virtual void SetToolTipCallBack(IToolTipCallBack* pCallBack);virtual IToolTipCallBack* GetToolTipCallback() const;void CControlUI::SetUserToolTipXml(LPCTSTR pstrXml){    m_sToolTipXml = pstrXml;}CDuiString CControlUI::GetUserToolTipXml() const{    return m_sToolTipXml;}void CControlUI::SetToolTipCallBack(IToolTipCallBack* pCallBack){    m_pCallBack = pCallBack;}IToolTipCallBack* CControlUI::GetToolTipCallback() const{    return m_pCallBack;}


CControlUI::SetAttribute:

else if( _tcscmp(pstrName, _T("usertooltip")) == 0 ) SetUserToolTipXml(pstrValue);

可以对每个控件单独定制tooltip界面,并且使用IToolTipCallBack回调接口实现界面上的文本

2.自绘tooltip类

CustomToolTipWnd.h

#pragma oncenamespace DuiLib {class IToolTipCallBack {public:virtual LPCTSTR GetToolTip(CControlUI* pTipOwner, LPCTSTR pstrTipCtrl) = 0;};class CCustomToolTipWnd : public CWindowWnd{public:CCustomToolTipWnd(CControlUI* pOwner);~CCustomToolTipWnd(void);void Init(LPCTSTR pstrXml, IToolTipCallBack* callback);protected:LPCTSTR GetWindowClassName() const;UINT GetClassStyle() const;void OnFinalMessage(HWND hWnd);LRESULT HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);void Walk(CControlUI* pCtrl);private:CPaintManagerUI m_pm;CDuiString m_sXml;IToolTipCallBack* m_pCallBack;CControlUI* m_pOwner;};}// namespace Duilib

CustomToolTipWnd.cpp

#include "stdafx.h"#include "CustomToolTipWnd.h"namespace DuiLib {CCustomToolTipWnd::CCustomToolTipWnd(CControlUI* pOwner) : m_pOwner(pOwner), m_pCallBack(NULL){}CCustomToolTipWnd::~CCustomToolTipWnd(void){}LPCTSTR CCustomToolTipWnd::GetWindowClassName() const{return TOOLTIPS_CLASS;}UINT CCustomToolTipWnd::GetClassStyle() const{return 0;}void CCustomToolTipWnd::OnFinalMessage(HWND hWnd){//delete this;}void CCustomToolTipWnd::Init(LPCTSTR pstrXml, IToolTipCallBack* callback){ASSERT(pstrXml);m_pCallBack = callback;m_pm.Init(m_hWnd);CDialogBuilder builder;CControlUI* pRoot = builder.Create(pstrXml, (UINT)0, NULL, &m_pm);ASSERT(pRoot && "Failed to parse XML");m_pm.AttachDialog(pRoot);if (m_pCallBack){Walk(pRoot);}}LRESULT CCustomToolTipWnd::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam){LRESULT lRes = 0;if( uMsg == WM_DESTROY ) {}else if ( uMsg == WM_WINDOWPOSCHANGING || uMsg == WM_WINDOWPOSCHANGED) {WINDOWPOS* pos = (WINDOWPOS*)lParam;pos->cx = m_pm.GetInitSize().cx;pos->cy = m_pm.GetInitSize().cy;}else if ( uMsg == WM_PAINT || uMsg == WM_ERASEBKGND ) {return m_pm.MessageHandler(uMsg, wParam, lParam, lRes);}return CWindowWnd::HandleMessage(uMsg, wParam, lParam);}void CCustomToolTipWnd::Walk(CControlUI* pCtrl){if (pCtrl == NULL){return;}IContainerUI* pContainer = static_cast<IContainerUI*>(pCtrl->GetInterface(L"IContainer"));if (pContainer != NULL){for (int i = 0; i < pContainer->GetCount(); ++i){CControlUI* pItem = pContainer->GetItemAt(i);Walk(pItem);}}else{pCtrl->SetText(m_pCallBack->GetToolTip(m_pOwner, pCtrl->GetName()));}}}//namespace Duilib

3.修改CPaintManagerUI加入CCustomToolTipWnd
添加成员变量CCustomToolTipWnd* m_pCustomToolTipWnd;在MessageHandler的WM_MOUSEHOVER事件中增加下面的蓝色代码:  
            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);            }if (m_pCustomToolTipWnd) {m_pCustomToolTipWnd->Unsubclass();}if ( pHover->GetUserToolTipXml() != L"" ) {delete m_pCustomToolTipWnd;m_pCustomToolTipWnd = new CCustomToolTipWnd(pHover);if( m_pCustomToolTipWnd == NULL ) return 0;m_pCustomToolTipWnd->Subclass(m_hwndTooltip);  m_pCustomToolTipWnd->Init(pHover->GetUserToolTipXml(), pHover->GetToolTipCallback());}::SendMessage( m_hwndTooltip,TTM_SETMAXTIPWIDTH,0, pHover->GetToolTipWidth());            ::SendMessage(m_hwndTooltip, TTM_SETTOOLINFO, 0, (LPARAM) &m_ToolTip);            ::SendMessage(m_hwndTooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &m_ToolTip);        }



实例代码及XML:

为列表的每一项添加tooltip,设置回调

typedef struct _Info{CString tooltips[3];}Info;map<CControlUI*, Info> m_arrToolTips;


CDialogBuilder builder;CListUI* jokelist = static_cast<CListUI*>(m_PaintManager.FindControl(L"jocklist"));CListContainerElementUI* pItem = static_cast<CListContainerElementUI*>(builder.Create(L"item.xml", 0, NULL, &m_PaintManager));CString s;s.Format(L"%d", jokelist->GetCount());pItem->SetFixedHeight(30);pItem->SetText(s);pItem->SetToolTip(s);pItem->SetToolTipCallBack(this);//if (jokelist->GetCount() % 2 == 0){pItem->SetUserToolTipXml(L"tooltip1.xml");}//else{//pItem->SetUserToolTipXml(L"tooltip2.xml");}Info sa;sa.tooltips[0] = s;sa.tooltips[1] =  CTime::GetCurrentTime().Format(L"%Y/%m/%d %H:%M:%S ");sa.tooltips[2] +=  L"你好,我是" + s + L"。";m_arrToolTips[pItem] = sa;jokelist->Add(pItem);

 回调函数实现   

LPCTSTR CMainFrame::GetToolTip( CControlUI* pTipOwner, LPCTSTR pstrTipCtrl ){if ( _tcscmp(pstrTipCtrl, L"IDC_CURRENT_BUDDY_ID") ==0 ){return m_arrToolTips[pTipOwner].tooltips[0];}else if ( _tcscmp(pstrTipCtrl, L"IDC_CURRENT_BUDDY_NAME") ==0 ){return m_arrToolTips[pTipOwner].tooltips[1];}else if ( _tcscmp(pstrTipCtrl, L"IDC_CURRENT_BUDDY_MESSAGE") ==0 ){return m_arrToolTips[pTipOwner].tooltips[2];}return L"";}

item.xml

<?xml version="1.0" encoding="utf-8"?><Window size="200,80" mininfo="200,54" caption="0,0,0,0" sizebox="4,4,4,4" bktrans="false">  <Font id="0" name="微软雅黑" size="14" bold="false" default="true" />  <Font id="1" name="微软雅黑" size="12" bold="false"/>  <Default name="VScrollBar" value="width="9" button1normalimage="file='public_scrollbar.png' source='0,0,9,9'" button1hotimage="file='public_scrollbar.png' source='9,0,18,9'" button1pushedimage="file='public_scrollbar.png' source='18,0,27,9'" button2normalimage="file='public_scrollbar.png' source='0,15,9,24'" button2hotimage="file='public_scrollbar.png' source='9,15,18,24'" button2pushedimage="file='public_scrollbar.png' source='18,15,27,24'" thumbnormalimage="file='public_scrollbar.png' source='0,24,9,30' corner='0,2,0,2'" thumbhotimage="file='public_scrollbar.png' source='9,24,18,30' corner='0,2,0,2'" thumbpushedimage="file='public_scrollbar.png' source='18,24,27,30' corner='0,2,0,2'" bknormalimage="file='public_scrollbar.png' source='0,9,9,15'"" />  <VerticalLayout bkcolor="#FF9CCF7A">    <HorizontalLayout inset="3,3,3,3">      <Button name="IDC_CURRENT_BUDDY_FACE" width="48" height="48" xborderround="48,48" xbkcolor="#FFDCE7D7" foreimage="pikachu.png" normalimage="tabbtn_highlight.png" hotimage="indicator\indicator_window_btn_hot.png" pushedimage="indicator\indicator_window_btn_hot.png" />      <VerticalLayout>        <Label name="IDC_CURRENT_BUDDY_ID" autocalcwidth="false" textpadding="8,0,0,0" textcolor="#FF210029" font="0"/>        <Label name="IDC_CURRENT_BUDDY_NAME" autocalcwidth="false" textpadding="8,0,0,0" textcolor="#FF210029" font="0"/>        <Label name="IDC_CURRENT_BUDDY_MESSAGE" autocalcwidth="false" textpadding="8,0,0,0" textcolor="#FF210029" font="0"/>      </VerticalLayout>    </HorizontalLayout>  </VerticalLayout></Window>


原创粉丝点击