• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            積木

            No sub title

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              140 Posts :: 1 Stories :: 11 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(1)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            原諒轉載自http://tech.ddvip.com/2008-11/122662837992492.html

            Visual C++中提供的MFC類CtreeCtrl(樹型控件)用來顯示具有一定層次結構的數據項時方便、直觀,所以它已經被廣泛地應用在各種軟件中,如資源管理器中的磁盤目錄就用的是樹型控件,我們在編程中也會經常用到這個控件,但是這個控件也有缺陷,那就是它并不直接支持拖動節點等高級特性,這使得程序員在編程時使用它受到了很大限制,同時又給軟件用戶帶來了一些不便。為此,本實例通過從 CTreeCtrl 中派生了一個類 CXTreeCtrl ,實現樹型控件中節點的拖動。這個類具有如下的功能:⑴ 基本項目條拖動的實現;⑵ 處理項目條的無意拖動;⑶ 能處理項目條拖動過程中的滾動問題;⑷ 拖動過程中節點會智能展開。程序編譯運行后的效果如圖所示:

            570)?'570px':'auto'; }" src="http://img.ddvip.com/2008_11_14/1226628379_ddvip_9835.png">

              圖一:樹型控件節點拖動示例

              一、實現方法

              我們針對上述自定義類的實現功能,介紹實現思路和方法。

              (1)基本項目條拖動的實現

              當我們要拖動樹型控件的一個項目條時,樹型控件會給它的父窗口發送一個TVN_BEGINDRAG通知消息,所以可以在此消息的響應函數中,調用 CTreeCtrl ::CreateDragImage ()函數創建表示當前項目條正處在拖動操作中的圖象,該函數創建的圖象由項目條的圖象和標簽文本組成。創建了拖動圖象后,調用CImageList::BeginDrag()函數指定拖動圖象的熱點位置,然后調用CImageList::DragEnter()函數顯示拖動圖象。接下來處理 WM_MOUSEMOVE 消息用于更新拖動圖象,我們想讓移動中的圖象經過某些項目時高亮度顯示,這可以調用 CTreeCtrl ::SelectDropTarget() 來實現。在調用 SelectDropTarget()函數之前,需要先調用CImageList::DragShowNolock ( false )函數來隱藏圖象列表,然后再調用CImageList::DragShowNolock ( true ) 函數來恢復圖象列表的顯示,這樣就不會在拖動過程中留下難看的軌跡。最后我們處理 WM_LBUTTONUP 消息用于完成拖動操作,在該消息響應函數中,我們需要完成結束拖動圖象的顯示、刪除拖動圖象、釋放鼠標、節點的拷貝/刪除等操作。在節點的拷貝/刪除操作中,如果是父節點拖到子節點上,我們可以先將父節點拷到根結點下的臨時節點中,再從臨時結點處拷到子節點,然后將根結點下的臨時節點刪除,這樣做的目的是防止產生異常。

              (2)處理項目條的無意拖動

              牐犎綣在鼠標按下時不小心移動了鼠標,這時系統就認為產生了一個移動操作,這就產生了誤操作。解決這個問題的方法是設置時間延遲,也就是說當用戶按下鼠標后必須在原位置停留一段時間,才能激活拖動操作。

              (3)處理拖動過程中的滾動問題

              當我們拖動樹型控件的項目條時,如果目的節點不可見,則需要拖動滾動條或收攏其它一些節點以使得目的節點顯示出來,無疑,這會給我們帶來很大的不便。為此就要給樹型控件添加自動滾動支持。首先設置一個定時器,在 WM_TIMER 消息中檢測鼠標的位置,如果靠近樹型控件的下邊緣,則使得控件向下滾動。靠近上邊緣則向上滾動。滾動速度根據鼠標的位置確定。

              (4)拖動過程中節點的智能展開

              為了實現在拖動過程中鼠標停留在某個節點上一段時間后,該節點會自動展開的功能。設置一個定時器,當鼠標在拖動過程中停止在某個節點上時,定時器被啟動,再設置一變量保存當前的鼠標位置。

              二、編程步驟

              1、 新建一對話框工程DragTree,編輯資源,在對話框中加入一樹型控件IDC_TREE ,屬性設置為:Has Buttons、Has Lines、Lines at root、Edit Labels、Border;

              2、 使用Class Wizard給該控件添加一個成員變量 m_wndTree ,在代碼部分將該控件的類型修改為CXTreeCtrl。

              3、 在對話框的OnInitDialog()函數中添加代碼,初始化樹型控件的項目條;

              4、 制作一個圖像資源(ID為IDB_TREEIMAGE),其中包含兩個小圖標,用來作為樹型控件項目條的顯示圖標;

              5、 添加代碼,編譯運行程序。

              三、程序代碼

            // XTreeCtrl.h : header file 
            #if !defined(AFX_XTREECTRL_H__3EF12526_EF66_4FD9_A572_59476441D79A__INCLUDED_) 
            #define AFX_XTREECTRL_H__3EF12526_EF66_4FD9_A572_59476441D79A__INCLUDED_ 
            #if _MSC_VER > 1000 
            #pragma once 
            #endif // _MSC_VER > 1000 
            class CXTreeCtrl : public CTreeCtrl 

             
            // Construction 
             public
              CXTreeCtrl(); 
              
            // Attributes 
             public
              
            // Operations 
             public
              
            // Overrides 
              
            // ClassWizard generated virtual function overrides 
              
            //{{AFX_VIRTUAL(CXTreeCtrl) 
              
            //}}AFX_VIRTUAL 
              
            // Implementation 
             public
              
            virtual ~CXTreeCtrl(); 
              
            // Generated message map functions 
             protected
              UINT m_TimerTicks; 
            //處理滾動的定時器所經過的時間 
              UINT m_nScrollTimerID; //處理滾動的定時器 
              CPoint m_HoverPoint; //鼠標位置 
              UINT m_nHoverTimerID; //鼠標敏感定時器 
              DWORD m_dwDragStart; //按下鼠標左鍵那一刻的時間 
              BOOL m_bDragging; //標識是否正在拖動過程中 
              CImageList* m_pDragImage; //拖動時顯示的圖象列表 
              HTREEITEM m_hItemDragS; //被拖動的標簽 
              HTREEITEM m_hItemDragD; //接受拖動的標簽 
              
            //{{AFX_MSG(CXTreeCtrl) 
               afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult); 
               afx_msg 
            void OnMouseMove(UINT nFlags, CPoint point); 
               afx_msg 
            void OnLButtonUp(UINT nFlags, CPoint point); 
               afx_msg 
            void OnLButtonDown(UINT nFlags, CPoint point); 
               afx_msg 
            void OnTimer(UINT nIDEvent); 
              
            //}}AFX_MSG 
              DECLARE_MESSAGE_MAP() 
             
            private
              HTREEITEM CopyBranch(HTREEITEM htiBranch,HTREEITEM htiNewParent,HTREEITEM htiAfter); 
              HTREEITEM CopyItem(HTREEITEM hItem,HTREEITEM htiNewParent,HTREEITEM htiAfter); 
            }; 
            #endif 
            //////////////////////////////////////////////////////////// CXTreeCtrl 
            #include "stdafx.h" 
            #include 
            "DragTree.h" 
            #include 
            "XTreeCtrl.h" 
            #ifdef _DEBUG 
            #define new DEBUG_NEW 
            #undef THIS_FILE 
            static char THIS_FILE[] = __FILE__; 
            #endif 
            #define DRAG_DELAY 60 
            CXTreeCtrl::CXTreeCtrl() 

             m_bDragging 
            = false

            CXTreeCtrl::
            ~CXTreeCtrl() 
            {} 
            BEGIN_MESSAGE_MAP(CXTreeCtrl, CTreeCtrl) 
            //{{AFX_MSG_MAP(CXTreeCtrl) 
             ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag) 
             ON_WM_MOUSEMOVE() 
             ON_WM_LBUTTONUP() 
             ON_WM_LBUTTONDOWN() 
             ON_WM_TIMER() 
            //}}AFX_MSG_MAP 
            END_MESSAGE_MAP() 
            void CXTreeCtrl::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) 

             NM_TREEVIEW
            * pNMTreeView = (NM_TREEVIEW*)pNMHDR; 
             
            *pResult = 0
             
            //如果是無意拖曳,則放棄操作 
             if( (GetTickCount() - m_dwDragStart) < DRAG_DELAY ) 
              
            return
             m_hItemDragS 
            = pNMTreeView->itemNew.hItem; 
             m_hItemDragD 
            = NULL; 
             
            //得到用于拖動時顯示的圖象列表 
             m_pDragImage = CreateDragImage( m_hItemDragS ); 
             
            if!m_pDragImage ) 
              
            return
             m_bDragging 
            = true
             m_pDragImage
            ->BeginDrag ( 0,CPoint(8,8) ); 
             CPoint pt 
            = pNMTreeView->ptDrag; 
             ClientToScreen( 
            &pt ); 
             m_pDragImage
            ->DragEnter ( this,pt ); //"this"將拖曳動作限制在該窗口 
             SetCapture(); 
             m_nScrollTimerID 
            = SetTimer( 2,40,NULL ); 

            void CXTreeCtrl::OnMouseMove(UINT nFlags, CPoint point) 

             HTREEITEM hItem; 
             UINT flags; 
             
            //檢測鼠標敏感定時器是否存在,如果存在則刪除,刪除后再定時 
             if( m_nHoverTimerID ) 
             { 
              KillTimer( m_nHoverTimerID ); 
              m_nHoverTimerID 
            = 0
             } 
             m_nHoverTimerID 
            = SetTimer( 1,800,NULL ); //定時為 0.8 秒則自動展開 
             m_HoverPoint = point; 
             
            if( m_bDragging ) 
             { 
              CPoint pt 
            = point; 
              CImageList::DragMove( pt ); 
              
            //鼠標經過時高亮顯示 
              CImageList::DragShowNolock( false ); //避免鼠標經過時留下難看的痕跡 
              if( (hItem = HitTest(point,&flags)) != NULL ) 
              { 
               SelectDropTarget( hItem ); 
               m_hItemDragD 
            = hItem; 
              } 
              CImageList::DragShowNolock( 
            true ); 
              
            //當條目被拖曳到左邊緣時,將條目放在根下 
              CRect rect; 
              GetClientRect( 
            &rect ); 
              
            if( point.x < rect.left + 20 ) 
               m_hItemDragD 
            = NULL; 
             } 
             CTreeCtrl::OnMouseMove(nFlags, point); 

            void CXTreeCtrl::OnLButtonUp(UINT nFlags, CPoint point) 

             CTreeCtrl::OnLButtonUp(nFlags, point); 
             
            if( m_bDragging ) 
             { 
              m_bDragging 
            = FALSE; 
              CImageList::DragLeave( 
            this ); 
              CImageList::EndDrag(); 
              ReleaseCapture(); 
              delete m_pDragImage; 
              SelectDropTarget( NULL ); 
              
            if( m_hItemDragS == m_hItemDragD ) 
              { 
               KillTimer( m_nScrollTimerID ); 
               
            return
              } 
              Expand( m_hItemDragD,TVE_EXPAND ); 
              HTREEITEM htiParent 
            = m_hItemDragD; 
              
            while( (htiParent = GetParentItem(htiParent)) != NULL ) 
              { 
               
            if( htiParent == m_hItemDragS ) 
               { 
                HTREEITEM htiNewTemp 
            = CopyBranch( m_hItemDragS,NULL,TVI_LAST ); 
                HTREEITEM htiNew 
            = CopyBranch( htiNewTemp,m_hItemDragD,TVI_LAST ); 
                DeleteItem( htiNewTemp ); 
                SelectItem( htiNew ); 
                KillTimer( m_nScrollTimerID ); 
                
            return
               } 
              } 
              HTREEITEM htiNew 
            = CopyBranch( m_hItemDragS,m_hItemDragD,TVI_LAST ); 
              DeleteItem( m_hItemDragS ); 
              SelectItem( htiNew ); 
              KillTimer( m_nScrollTimerID ); 
             } 

            HTREEITEM CXTreeCtrl::CopyItem(HTREEITEM hItem, HTREEITEM htiNewParent, HTREEITEM htiAfter) 
            //拷貝條目 

             TV_INSERTSTRUCT tvstruct; 
             HTREEITEM hNewItem; 
             CString sText; 
             
            //得到源條目的信息 
             tvstruct.item.hItem = hItem; 
             tvstruct.item.mask
            =TVIF_CHILDREN|TVIF_HANDLE|TVIF_IMAGE|TVIF_SELECTEDIMAGE; 
             GetItem( 
            &tvstruct.item ); 
             sText 
            = GetItemText( hItem ); 
             tvstruct.item.cchTextMax 
            = sText.GetLength (); 
             tvstruct.item.pszText 
            = sText.LockBuffer (); 
             
            //將條目插入到合適的位置 
             tvstruct.hParent = htiNewParent; 
             tvstruct.hInsertAfter 
            = htiAfter; 
             tvstruct.item.mask 
            = TVIF_IMAGE|TVIF_SELECTEDIMAGE|TVIF_TEXT; 
             hNewItem 
            = InsertItem( &tvstruct ); 
             sText.ReleaseBuffer (); 
             
            //限制拷貝條目數據和條目狀態 
             SetItemData( hNewItem,GetItemData(hItem) ); 
             SetItemState( hNewItem,GetItemState(hItem,TVIS_STATEIMAGEMASK),TVIS_STATEIMAGEMASK); 
             
            return hNewItem; 

            HTREEITEM CXTreeCtrl::CopyBranch(HTREEITEM htiBranch, HTREEITEM htiNewParent, HTREEITEM htiAfter) 
            //拷貝分支 

             HTREEITEM hChild; 
             HTREEITEM hNewItem 
            = CopyItem( htiBranch,htiNewParent,htiAfter ); 
             hChild 
            = GetChildItem( htiBranch ); 
             
            while( hChild != NULL ) 
             { 
              CopyBranch( hChild,hNewItem,htiAfter ); 
              hChild 
            = GetNextSiblingItem( hChild ); 
             } 
             
            return hNewItem; 

            void CXTreeCtrl::OnLButtonDown(UINT nFlags, CPoint point) //處理無意拖曳 

             m_dwDragStart 
            = GetTickCount(); 
             CTreeCtrl::OnLButtonDown(nFlags, point); 

            void CXTreeCtrl::OnTimer(UINT nIDEvent) 

             
            //鼠標敏感節點 
             if( nIDEvent == m_nHoverTimerID ) 
             { 
              KillTimer( m_nHoverTimerID ); 
              m_nHoverTimerID 
            = 0
              HTREEITEM trItem 
            = 0
              UINT uFlag 
            = 0
              trItem 
            = HitTest( m_HoverPoint,&uFlag ); 
              
            if( trItem && m_bDragging ) 
              { 
               SelectItem( trItem ); 
               Expand( trItem,TVE_EXPAND ); 
              } 
             } 
             
            //處理拖曳過程中的滾動問題 
             else if( nIDEvent == m_nScrollTimerID ) 
             { 
              m_TimerTicks
            ++
              CPoint pt; 
              GetCursorPos( 
            &pt ); 
              CRect rect; 
              GetClientRect( 
            &rect ); 
              ClientToScreen( 
            &rect ); 
              HTREEITEM hItem 
            = GetFirstVisibleItem(); 
              
            if( pt.y < rect.top +10 ) 
              { 
               
            //向上滾動 
               int slowscroll = 6 - (rect.top + 10 - pt.y )/20
               
            if0 == (m_TimerTicks % ((slowscroll > 0? slowscroll : 1)) ) 
               { 
                CImageList::DragShowNolock ( 
            false ); 
                SendMessage( WM_VSCROLL,SB_LINEUP ); 
                SelectDropTarget( hItem ); 
                m_hItemDragD 
            = hItem; 
                CImageList::DragShowNolock ( 
            true ); 
               } 
              } 
              
            else if( pt.y > rect.bottom - 10 ) 
              { 
               
            //向下滾動 
               int slowscroll = 6 - (pt.y - rect.bottom + 10)/20
               
            if0 == (m_TimerTicks % ((slowscroll > 0? slowscroll : 1)) ) 
               { 
                CImageList::DragShowNolock ( 
            false ); 
                SendMessage( WM_VSCROLL,SB_LINEDOWN ); 
                
            int nCount = GetVisibleCount(); 
                
            forint i=0 ; i<nCount-1 ; i++ ) 
                 hItem 
            = GetNextVisibleItem( hItem ); 
                 
            if( hItem ) 
                  SelectDropTarget( hItem ); 
                 m_hItemDragD 
            = hItem; 
                 CImageList::DragShowNolock ( 
            true ); 
               } 
              } 
             } 
             
            else
              CTreeCtrl::OnTimer(nIDEvent); 

            //////////////////////////////////////////////////////////// 
            BOOL CDragTreeDlg::OnInitDialog() 

             CDialog::OnInitDialog(); 
             …………………….
            //此處代碼省略 
             
            // TODO: Add extra initialization here 
             m_image.Create ( IDB_TREEIMAGE,16,1,RGB(255,255,255) ); 
             m_wndTree.SetImageList ( 
            &m_image,TVSIL_NORMAL ); 
             HTREEITEM hti1 
            = m_wndTree.InsertItem ( _T("唐詩"),0,1 ); 
             HTREEITEM hti2 
            = m_wndTree.InsertItem ( _T("宋詞"),0,1 ); 
             HTREEITEM hti3 
            = m_wndTree.InsertItem ( _T("元曲"),0,1 ); 
             HTREEITEM hti4 
            = m_wndTree.InsertItem ( _T("李白"),0,1,hti1 ); 
             m_wndTree.InsertItem ( _T(
            "靜夜思(床前明月光)"),0,1,hti4 ); 
             m_wndTree.InsertItem ( _T(
            "將進酒(君不見黃河之水天上來)"),0,1,hti4 ); 
             m_wndTree.InsertItem ( _T(
            "望廬山瀑布(日照香爐生紫煙)"),0,1,hti4 ); 
             m_wndTree.InsertItem ( _T(
            "蜀道難(噫吁戲,危乎高哉)"),0,1,hti4 ); 
             HTREEITEM hti5 
            = m_wndTree.InsertItem ( _T("杜甫"),0,1,hti1 ); 
             m_wndTree.InsertItem ( _T(
            "蜀相(丞相祠堂何處尋)"),0,1,hti5 ); 
             m_wndTree.InsertItem ( _T(
            "春望(國破山河在)"),0,1,hti5 ); 
             m_wndTree.InsertItem ( _T(
            "茅屋為秋風所破歌(八月秋高風怒號)"),0,1,hti5 ); 
             HTREEITEM hti6 
            = m_wndTree.InsertItem ( _T("白居易"),0,1,hti1 ); 
             m_wndTree.InsertItem ( _T(
            "長恨歌(漢皇重色思傾國)"),0,1,hti6 ); 
             m_wndTree.InsertItem ( _T(
            "琵琶行並序(潯陽江頭夜送客)"),0,1,hti6 ); 
             m_wndTree.InsertItem ( _T(
            "李清照"),0,1,hti2 ); 
             m_wndTree.InsertItem ( _T(
            "柳永"),0,1,hti2 ); 
             
            return TRUE; // return TRUE unless you set the focus to a control 
            }

             

            posted on 2011-11-04 11:23 Jacc.Kim 閱讀(710) 評論(0)  編輯 收藏 引用 所屬分類: VC / C++
            久久免费看黄a级毛片| 日韩av无码久久精品免费| 2022年国产精品久久久久| 成人资源影音先锋久久资源网| 国产日产久久高清欧美一区| 精品99久久aaa一级毛片| 久久亚洲AV成人无码软件| 亚洲午夜久久久久妓女影院| 99久久国产综合精品五月天喷水| 亚洲国产成人久久精品99| 日产精品久久久久久久| 久久精品国产99国产精偷| 思思久久99热只有频精品66| 国产激情久久久久久熟女老人| 久久久久亚洲AV无码永不| 久久久WWW成人免费精品| 国产精品无码久久久久久| 久久人人爽人爽人人爽av| 国产精品久久影院| 精品久久久久久中文字幕大豆网| 99精品久久久久久久婷婷| 色欲综合久久中文字幕网| 久久午夜综合久久| 精品久久久久久综合日本| 性做久久久久久久| 国产精品成人久久久| 国产午夜精品久久久久九九电影| 亚洲AV日韩精品久久久久久久| 中文字幕精品无码久久久久久3D日动漫 | 欧美精品丝袜久久久中文字幕 | 久久综合久久综合九色| 久久久久99这里有精品10| 久久播电影网| 久久精品国产99久久丝袜| 香蕉久久一区二区不卡无毒影院| 久久综合给合久久狠狠狠97色69 | 国产亚洲精品久久久久秋霞| 亚洲国产日韩欧美综合久久| 久久午夜无码鲁丝片午夜精品| 久久噜噜久久久精品66| 久久99精品久久久久久9蜜桃|