VC中給樹形控制元件的圖示加上工具提示 (轉)
VC中給樹形控制元件的圖示加上工具提示 (轉)[@more@]VC中給樹形的圖示加上工具提示
我從沒有在任何一個應用中看到過圖示的工具提示。有時候查遍了整個幫助
文件也沒有明白某個圖示是什麼意思。如果能在自己的程式中為圖示加上工具提
示,一定會使介面的友好性大大增加。本文中以樹形控制元件為例,詳細介紹了在VC
中使用MFC提供的機制來實現圖示工具提示的方法。
---- 第一步:使控制元件可以顯示工具提示
---- EnableTool(TRUE)使一個視窗可以顯示工具提示。在什麼地方插入
這條程式碼最好呢?在類的PreSubclassWindow()中。因為不管一個控制元件如何被建立
,MFC都會呼叫此。而其他的函式則不一定會被呼叫。以OnCreate()為例,如
果呼叫Create()或CreateEx()建立一個控制元件,OnCreate()會被呼叫,而如果一個
控制元件是從對話方塊資源建立,OnCreate()就不會被呼叫。
實現程式碼如下:
void CTreeCtrlX::PreSubclassWindow()
{
CTreeCtrl::PreSubclassWindow();
EnableToolTips(TRUE);
}
---- 第二步:過載虛擬函式OnToolHitTest()
---- MFC呼叫函式來確定在某個點是否應該顯示工具提示。MSDN建議如果滑鼠落
在應該顯示工具提示的點上,返回值1。這並不完全正確。這個函式應該返回不同
的值來區分視窗中不同的應該顯示提示的區域。
---- 在這個函式中,本文只處理滑鼠落在節點圖示或節點狀態圖示上的情況。讀
者可以按照自己的情況向樹的其他元素上新增工具提示。在兩種情況下,都要計
算圖示的區域,並且把TOOLINFO的uID設為滑鼠所在點的樹節點的控制程式碼。注意,盡
管對於節點圖示和節點狀態圖示,使用了相同的id,但返回值並不相同。不同的
返回值迫使MFC工具提示。
---- 雖然我們可以在此函式中給出工具提示,但因為滑鼠的每次移動都會呼叫此
函式,太多的處理並不是一個好注意,所以我們在其他的函式中處理應該顯示什
麼提示的問題。
類宣告中的程式碼如下所示:
// Overrs
// ClassWizard generated
virtual function overrides
//{{AFX_VIRTUAL(CTreeCtrlX)
protected:
…
virtual int OnToolHitTest
( CPoint point, TOOLINFO* pTI ) const;
//}}AFX_VIRTUAL
實現程式碼如下所示:
int CTreeCtrlX::OnToolHitTest
(CPoint point, TOOLINFO * pTI) const
{
RECT rect;
UINT nFlags;
HTREEITEM hitem = HitTest( point, &nFlags );
if( nFlags & TVHT_ONITEMICON )
{
CImageList *pImg = GetImageList( TVSIL_NORMAL );
IMAGEINFO imageinfo;
pImg- >GetImageInfo( 0, &imageinfo );
GetItemRect( hitem, &rect, TRUE );
rect.right = rect.left - 2;
rect.left -= (imageinfo.rcImage.right + 2);
pTI- >hwnd = m_hWnd;
pTI- >uId = (UINT)hitem;
pTI- >lpszText = LPSTR_TEXTCALLBACK;
pTI- >rect = rect;
return pTI- >uId;
}
else if( nFlags & TVHT_ONITEMSTATEICON )
{
CImageList *pImg = GetImageList( TVSIL_NORMAL );
IMAGEINFO imageinfo;
pImg- >GetImageInfo( 0, &imageinfo );
GetItemRect( hitem, &rect, TRUE );
rect.right = rect.left -
(imageinfo.rcImage.right + 2);
pImg = GetImageList( TVSIL_STATE );
rect.left = rect.right - imageinfo.rcImage.right ;
pTI- >hwnd = m_hWnd;
pTI- >uId = (UINT)hitem;
pTI- >lpszText = LPSTR_TEXTCALLBACK;
pTI- >rect = rect;
// 返回與節點圖示不同的值
return pTI- >uId*2;
}
return -1;
}
---- 第三步:處理TTN_NEEDTEXT訊息;
---- 加入一個函式處理TTN_NEEDTEXT訊息通知。當工具處理控制需要知道應該顯
示什麼資訊時,這條訊息被髮出。由於上一步中我們給TOOLINFO的lpszText賦值
為LPSTR_TEXTCALLBACK,所以我們要處理這個訊息VC的ClassWizard並不支援這條
訊息被對映,所以只有我們自己加入這條訊息的對映機制加入到MESSAGE_MAP中去
。我們不得不處理這個訊息的兩個版本,TTN_NEEDTEXTA和TTN_NEEDTEXTA。訊息
對映的程式碼如下所示:
BEGIN_MESSAGE_MAP(CTreeCtrlX, CTreeCtrl)
//{{AFX_MSG_MAP(CTreeCtrlX)
…
//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE
(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE
(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
下面的程式碼是加到類宣告中:
protected:
//{{AFX_MSG(CTreeCtrlX)
…
//}}AFX_MSG
afx_msg BOOL OnToolTipText
( UINT id, NMHDR * pNMHDR, LRESULT * pResult );
DECLARE_MESSAGE_MAP()
---- 現在討論這個函式本身的實現。為了適應不同的語言字符集,ANSI字符集和
UNICODE字符集都必須被處理,處理過程會有些不同。此處對樹形控制元件的本身產生
的ToolTip訊息不予處理,過濾掉上述訊息的原則是樹形控制元件本身產生的訊息的ID
是樹形控制元件視窗的控制程式碼,並且有TTF_IDISHWND標誌。根據滑鼠位置可以確定應該
給出節點圖示還是狀態圖示的工具提示。本文根據筆者畫的圖顯示了一些無關緊
要的提示,讀者做這一步時應該加入一些有意義的提示。當然,本文假定控制元件包
含節點圖示和狀態圖示。如不包含,計算滑鼠位置時要注意 不要計算錯誤。
BOOL CTreeCtrlX::OnToolTipText
( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
// 需要處理ANSI和UNICODE兩種格式
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
CString strTipText;
UINT nID = pNMHDR- >idFrom;
// 不必處理樹自己發出的ToolTip訊息
if( nID == (UINT)m_hWnd &&
(( pNMHDR- >code == TTN_NEEDTEXTA &&
pTTTA- >uFlags & TTF_IDISHWND ) ||
( pNMHDR- >code == TTN_NEEDTEXTW &&
pTTTW- >uFlags & TTF_IDISHWND ) ) )
return FALSE;
// 得到滑鼠位置
const MSG* pMessage;
CPoint pt;
pMessage = GetCurrentMessage();
ASSERT ( pMessage );
pt = pMessage- >pt;
ScreenToClient( &pt );
UINT nFlags;
HTREEITEM hitem = HitTest( pt, &nFlags );
if( nFlags & TVHT_ONITEMICON )
{
int nImage, nSelImage;
GetItemImage( (HTREEITEM ) nID, nImage, nSelImage );
switch(nImage)
{
case 0:
strTipText = "叉";
break;
case 1:
strTipText = "加號";
break;
case 2:
strTipText = "菱形";
break;
}
}
else
{
if( (GetItemState( (HTREEITEM ) nID,
TVIS_STATEIMAGEMASK ) > >12 ) == 2 )
strTipText.Format( "此節點被選中" );
else
strTipText.Format( "此節點未被選中" );
}
#ifndef _UNICODE
if (pNMHDR- >code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA- >szText, strTipText, 80);
else
_mbstowcsz(pTTTW- >szText, strTipText, 80);
#else
if (pNMHDR- >code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA- >szText, strTipText, 80);
else
lstrcpyn(pTTTW- >szText, strTipText, 80);
#endif
*pResult = 0;
return TRUE; // 訊息處理完畢
}
---- 本文程式在,VC6.0下透過。
我從沒有在任何一個應用中看到過圖示的工具提示。有時候查遍了整個幫助
文件也沒有明白某個圖示是什麼意思。如果能在自己的程式中為圖示加上工具提
示,一定會使介面的友好性大大增加。本文中以樹形控制元件為例,詳細介紹了在VC
中使用MFC提供的機制來實現圖示工具提示的方法。
---- 第一步:使控制元件可以顯示工具提示
---- EnableTool(TRUE)使一個視窗可以顯示工具提示。在什麼地方插入
這條程式碼最好呢?在類的PreSubclassWindow()中。因為不管一個控制元件如何被建立
,MFC都會呼叫此。而其他的函式則不一定會被呼叫。以OnCreate()為例,如
果呼叫Create()或CreateEx()建立一個控制元件,OnCreate()會被呼叫,而如果一個
控制元件是從對話方塊資源建立,OnCreate()就不會被呼叫。
實現程式碼如下:
void CTreeCtrlX::PreSubclassWindow()
{
CTreeCtrl::PreSubclassWindow();
EnableToolTips(TRUE);
}
---- 第二步:過載虛擬函式OnToolHitTest()
---- MFC呼叫函式來確定在某個點是否應該顯示工具提示。MSDN建議如果滑鼠落
在應該顯示工具提示的點上,返回值1。這並不完全正確。這個函式應該返回不同
的值來區分視窗中不同的應該顯示提示的區域。
---- 在這個函式中,本文只處理滑鼠落在節點圖示或節點狀態圖示上的情況。讀
者可以按照自己的情況向樹的其他元素上新增工具提示。在兩種情況下,都要計
算圖示的區域,並且把TOOLINFO的uID設為滑鼠所在點的樹節點的控制程式碼。注意,盡
管對於節點圖示和節點狀態圖示,使用了相同的id,但返回值並不相同。不同的
返回值迫使MFC工具提示。
---- 雖然我們可以在此函式中給出工具提示,但因為滑鼠的每次移動都會呼叫此
函式,太多的處理並不是一個好注意,所以我們在其他的函式中處理應該顯示什
麼提示的問題。
類宣告中的程式碼如下所示:
// Overrs
// ClassWizard generated
virtual function overrides
//{{AFX_VIRTUAL(CTreeCtrlX)
protected:
…
virtual int OnToolHitTest
( CPoint point, TOOLINFO* pTI ) const;
//}}AFX_VIRTUAL
實現程式碼如下所示:
int CTreeCtrlX::OnToolHitTest
(CPoint point, TOOLINFO * pTI) const
{
RECT rect;
UINT nFlags;
HTREEITEM hitem = HitTest( point, &nFlags );
if( nFlags & TVHT_ONITEMICON )
{
CImageList *pImg = GetImageList( TVSIL_NORMAL );
IMAGEINFO imageinfo;
pImg- >GetImageInfo( 0, &imageinfo );
GetItemRect( hitem, &rect, TRUE );
rect.right = rect.left - 2;
rect.left -= (imageinfo.rcImage.right + 2);
pTI- >hwnd = m_hWnd;
pTI- >uId = (UINT)hitem;
pTI- >lpszText = LPSTR_TEXTCALLBACK;
pTI- >rect = rect;
return pTI- >uId;
}
else if( nFlags & TVHT_ONITEMSTATEICON )
{
CImageList *pImg = GetImageList( TVSIL_NORMAL );
IMAGEINFO imageinfo;
pImg- >GetImageInfo( 0, &imageinfo );
GetItemRect( hitem, &rect, TRUE );
rect.right = rect.left -
(imageinfo.rcImage.right + 2);
pImg = GetImageList( TVSIL_STATE );
rect.left = rect.right - imageinfo.rcImage.right ;
pTI- >hwnd = m_hWnd;
pTI- >uId = (UINT)hitem;
pTI- >lpszText = LPSTR_TEXTCALLBACK;
pTI- >rect = rect;
// 返回與節點圖示不同的值
return pTI- >uId*2;
}
return -1;
}
---- 第三步:處理TTN_NEEDTEXT訊息;
---- 加入一個函式處理TTN_NEEDTEXT訊息通知。當工具處理控制需要知道應該顯
示什麼資訊時,這條訊息被髮出。由於上一步中我們給TOOLINFO的lpszText賦值
為LPSTR_TEXTCALLBACK,所以我們要處理這個訊息VC的ClassWizard並不支援這條
訊息被對映,所以只有我們自己加入這條訊息的對映機制加入到MESSAGE_MAP中去
。我們不得不處理這個訊息的兩個版本,TTN_NEEDTEXTA和TTN_NEEDTEXTA。訊息
對映的程式碼如下所示:
BEGIN_MESSAGE_MAP(CTreeCtrlX, CTreeCtrl)
//{{AFX_MSG_MAP(CTreeCtrlX)
…
//}}AFX_MSG_MAP
ON_NOTIFY_EX_RANGE
(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
ON_NOTIFY_EX_RANGE
(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
END_MESSAGE_MAP()
下面的程式碼是加到類宣告中:
protected:
//{{AFX_MSG(CTreeCtrlX)
…
//}}AFX_MSG
afx_msg BOOL OnToolTipText
( UINT id, NMHDR * pNMHDR, LRESULT * pResult );
DECLARE_MESSAGE_MAP()
---- 現在討論這個函式本身的實現。為了適應不同的語言字符集,ANSI字符集和
UNICODE字符集都必須被處理,處理過程會有些不同。此處對樹形控制元件的本身產生
的ToolTip訊息不予處理,過濾掉上述訊息的原則是樹形控制元件本身產生的訊息的ID
是樹形控制元件視窗的控制程式碼,並且有TTF_IDISHWND標誌。根據滑鼠位置可以確定應該
給出節點圖示還是狀態圖示的工具提示。本文根據筆者畫的圖顯示了一些無關緊
要的提示,讀者做這一步時應該加入一些有意義的提示。當然,本文假定控制元件包
含節點圖示和狀態圖示。如不包含,計算滑鼠位置時要注意 不要計算錯誤。
BOOL CTreeCtrlX::OnToolTipText
( UINT id, NMHDR * pNMHDR, LRESULT * pResult )
{
// 需要處理ANSI和UNICODE兩種格式
TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
CString strTipText;
UINT nID = pNMHDR- >idFrom;
// 不必處理樹自己發出的ToolTip訊息
if( nID == (UINT)m_hWnd &&
(( pNMHDR- >code == TTN_NEEDTEXTA &&
pTTTA- >uFlags & TTF_IDISHWND ) ||
( pNMHDR- >code == TTN_NEEDTEXTW &&
pTTTW- >uFlags & TTF_IDISHWND ) ) )
return FALSE;
// 得到滑鼠位置
const MSG* pMessage;
CPoint pt;
pMessage = GetCurrentMessage();
ASSERT ( pMessage );
pt = pMessage- >pt;
ScreenToClient( &pt );
UINT nFlags;
HTREEITEM hitem = HitTest( pt, &nFlags );
if( nFlags & TVHT_ONITEMICON )
{
int nImage, nSelImage;
GetItemImage( (HTREEITEM ) nID, nImage, nSelImage );
switch(nImage)
{
case 0:
strTipText = "叉";
break;
case 1:
strTipText = "加號";
break;
case 2:
strTipText = "菱形";
break;
}
}
else
{
if( (GetItemState( (HTREEITEM ) nID,
TVIS_STATEIMAGEMASK ) > >12 ) == 2 )
strTipText.Format( "此節點被選中" );
else
strTipText.Format( "此節點未被選中" );
}
#ifndef _UNICODE
if (pNMHDR- >code == TTN_NEEDTEXTA)
lstrcpyn(pTTTA- >szText, strTipText, 80);
else
_mbstowcsz(pTTTW- >szText, strTipText, 80);
#else
if (pNMHDR- >code == TTN_NEEDTEXTA)
_wcstombsz(pTTTA- >szText, strTipText, 80);
else
lstrcpyn(pTTTW- >szText, strTipText, 80);
#endif
*pResult = 0;
return TRUE; // 訊息處理完畢
}
---- 本文程式在,VC6.0下透過。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-963072/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- vue的樹形控制元件Vue控制元件
- 舉個例子!Tableau技巧(37):如何在工具提示裡顯示條形圖
- Antd:Tree樹形控制元件資料解析(JSON轉換)控制元件JSON
- VC++儲存繪製的圖形-1C++
- vis.js工具提示3d圖形JS3D
- 給你的Flutter頁面跳轉加上動畫Flutter動畫
- 【Android】自定義樹形控制元件Android控制元件
- Vue+element中Tree樹形控制元件資料失效~Vue控制元件
- 給自己的網站加上HTTPS網站HTTP
- 踩坑日記-element ui樹形控制元件UI控制元件
- CAD繪圖工具中的正多邊形命令繪圖
- markdown樹形結構生成工具
- Zeit – Linux圖形化中定時任務的工具Linux
- 第歸方法建立樹形圖
- 影像和圖示轉換工具:Snap Converter for macMac
- 兩款 Linux 桌面中的圖形化操作 PDF 的工具Linux
- 如何給普通圖片加上水波紋【shader 奇技淫巧】
- iview樹加圖示View
- Android 多級樹形結構顯示Android
- Flutter | ShaderMask - 給你的Widget加上色彩Flutter
- CoordConv:給你的卷積加上座標卷積
- Iview元件庫之樹形控制元件增刪改功能View控制元件
- element-ui裡Form 表單內給label內容新增圖示提示UIORM
- .NET 控制元件轉圖片控制元件
- Linux基礎命令---顯示樹形程式pstreeLinux
- 字串陣列轉為樹形結構字串陣列
- DrawPad 圖形繪畫工具
- Illustrator 2022向量圖形工具
- DrawPad圖形繪畫工具
- 圖形使用者介面2:常用控制元件控制元件
- 鴻蒙跳轉到相簿或者檔案選擇圖片並顯示到Image控制元件中鴻蒙控制元件
- 樹:基本樹形
- 最小樹形圖(朱劉演算法)演算法
- XManager:xshell顯示圖形化介面
- 將List物件列表轉為樹形結構物件
- 給你的Vim加上自動程式設計功能程式設計
- mac圖形繪畫工具:DrawPadMac
- DrawPad for mac 圖形繪畫工具Mac
- DrawPad for mac圖形繪畫工具Mac