對於對話框中的TreeView控件,如果想在初始化(OnInitDialog)中SetCheck,必須:
m_tree.ModifyStyle( TVS_CHECKBOXES, 0 );
m_tree.ModifyStyle( 0, TVS_CHECKBOXES );
m_tree.SetCheck(hItem, TRUE);
即即使在對話框編輯器中爲TreeView增加了Check Boxes屬性,也必須重新設一次TVS_CHECKBOXES,SetCheck才能起作用
而對於非初始化中的SetCheck,則不受影響
出處:http://shuiyu.100steps.net/blog_old/index.php?job=art&articleid=a_20050303_225747
感覺此文作者盡心盡責,有關CTreeView的一些問題說的很詳細,也許我以後能用的着,所以先把他這篇文章放於下面,以便來日方便查看:
(1)SetCheck
對於對話框中的TreeView控件,如果想在初始化(OnInitDialog)中SetCheck,必須:
m_tree.ModifyStyle( TVS_CHECKBOXES, 0 );
m_tree.ModifyStyle( 0, TVS_CHECKBOXES );
m_tree.SetCheck(hItem, TRUE);
即即使在對話框編輯器中爲TreeView增加了Check Boxes屬性,也必須重新設一次TVS_CHECKBOXES,SetCheck才能起作用
而對於非初始化中的SetCheck,則不受影響
(2)OnCheckChange
對於TreeView中的checkbox,沒有對應的notify,必須自己處理
參考msdn.microsoft.com,Q261289
我的做法稍有不同:
我的做法稍有不同:
第一步:繼承CTreeCtrl
class CMyTreeCtrl : public CTreeCtrl
二:
增加WM_LBUTTONDOWN處理函數。包括:
代碼 |
.h:
// 定義自定義消息,用於通知父窗口
#define UM_CHECKSTATECHANGE (WM_USER + xxx)
afx_msg void OnLButtonDown(UINT nFlags, CPoint point) ;
.cpp:
ON_WM_LBUTTONDOWN()
void CMyTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
TVHITTESTINFO tvHitInfo = { point.x, point.y } ;
HitTest(&tvHitInfo) ; // 測試擊鍵位置
if (tvHitInfo.flags & TVHT_ONITEMSTATEICON)
GetParent()->SendMessage(UM_CHECKSTATECHANGE,
WPARAM(GetDlgCtrlID()), LPARAM(tvHitInfo.hItem)) ;
// 通知父窗口
CTreeCtrl::OnLButtonDown(nFlags, point) ;
}
發現不能捕獲WM_LBUTTONUP?!原因不知,請各位指教
發送消息不能用PostMessage。原因請看第三步
由於只能捕獲WM_LBUTTONDOWN,將導致一個問題,即如果用戶在checkbox中按下,卻拖動鼠標在checkbox外放手,就會出現不一致情況,因爲checkbox是收到WM_LBUTTONUP才作出反應的
目前我還沒有很好的解決這個問題,只有一個弱智辦法,通過timer來“糾正”錯誤。同樣請各位指教
三:
在dialog中,處理UM_CHECKSTATECHANGE
代碼 |
.h: afx_msg void OnCheckChange(UINT nID, HTREEITEM hItem) ; .cpp: ON_MESSAGE(UM_CHECKSTATECHANGE, OnCheckChange) void CxxxDlg::OnCheckChange(UINT nID, HTREEITEM hItem) { switch (nID) { case IDC_TREEVIEW: // IDC_TREEVIEW:TreeView控件的ID if (m_tree.GetCheck(hItem)) { // original checked, now unchecked // TODO: 增加Unchecked代碼 } else { // original unchecked, now checked // TODO: 增加Checked代碼 } break ; } } |
這裏要注意,(GetCheck(hItem) == TRUE)表示Unchecked,(GetCheck(hItem) == FALSE)表示Checked,原因在於在CMyTreeCtrl中捕獲的是WM_LBUTTONDOWN,OnCheckChange發生時,checkbox還未變化。基於同樣原因,第二步中不能使用PostMessage,而必須SendMessage,以免出錯
不能在最後增加m_tree.SetCheck()來解決第二步中提到的問題。
根本辦法在於設法捕獲WM_LBUTTONUP
與microsoft的做法相比:減少了獲取鼠標點擊位置和座標映射的代碼;CMyTreeCtrl可以獨立出來重用
(3)TreeView的子窗口
在特殊的情況下,需要在TreeView中添加子窗口
主要問題:當TreeView中內容發生變化時,將重繪客戶區,將子窗口也抹去(?!至於原因,又要請各位指教了),即使子窗口設爲TOPMOST
我的方法:
第一步:
繼承CTreeCtrl:class CMyTreeCtrl : public CTreeCtrl
處理WM_PAINT,同時通知父窗口:
代碼 |
.h: #define UM_TREEREDRAW (WM_USER + xxx) afx_msg void OnPaint(); .cpp: ON_WM_PAINT() void CMyTreeCtrl::OnPaint() { CTreeCtrl::OnPaint() ; GetParent()->SendMessage(UM_TREEREDRAW, WPARAM(GetDlgCtrlID()), LPARAM(0)) ; } |
二:
處理UM_TREEREDRAW:
代碼 |
void CxxxDlg::OnTreeRedraw(UINT nID, LPARAM lParam) { switch (nID) { case IDC_TREEVIEW: // IDC_TREEVIEW:TreeView控件的ID wndChild.RedrawWindow(NULL, NULL, RDW_INVALIDATE) ; // 強制重繪子窗口 break ; } } |