CTreeCtrl 節點支援拖拽功能

2021-06-13 09:13:44 字數 4576 閱讀 8334

1、首先,從ctreectrl派生乙個類cxtreectrl。

2、此類需處理以下問題:

a、基本拖動實現;

b、處理無意拖動;

c、能處理拖動過程中滾動問題;

d、拖動過程中節點會智慧型展開。

具體實現辦法:

a、基本拖動實現

當我們要拖動乙個專案時,樹型檢視控制項會給它的父視窗傳送tvn_begindrag通知訊息。可以在此處建立表示專案處在拖動操作中的圖象,呼叫 createdragimage 函式產生一副預設的圖象,該函式建立的圖象由條目圖象和標籤文字組成。建立了拖**象後,呼叫begindrag 函式指定拖**象的熱點位置,然後呼叫 dragenter 函式顯示拖**象。接下來處理 wm_mousemove 訊息用於更新拖**象,我們想讓移動中的圖象經過某些專案時高亮度顯示,這可以呼叫 selectdroptarget 來實現。在呼叫 selectdroptarget 前,我們先呼叫dragshownolock ( false ) 來隱藏圖象列表,之後再呼叫 dragshownolock ( true ) 來恢復圖象列表的顯示,這樣就不會在拖動過程中留下難看的軌跡。最後我們處理wm_lbuttonup 訊息用於完成拖動操作,在給訊息中,我們需要完成結束拖**想的顯示、刪除拖**象、釋放滑鼠、節點的拷貝/刪除等操作。在節點的拷貝/刪除操作中,如果是父節點拖到子節點上,我們可以先將父節點拷到根結點下的臨時節點中,再從臨時結點處拷到子節點,然後將根結點下的臨時節點刪除,這樣做的目的是防止產生異常。

b、處理無意拖動

大家可能都有過這樣的經歷:在滑鼠按下時不小心移動了滑鼠,這時系統就認為產生了乙個移動操作。如果我們不針對這種情況加以解決的話,就很容易產生誤操作。下面我們就提出乙個解決方法:設定時間延遲。也就是說當使用者按下滑鼠後必須在原位置停留一段時間,才能啟用拖動操作。

c、處理拖動過程中滾動問題

當我們進行拖動時,如果目的節點不可見,則需要拖動滾動條或收攏其它一些節點以使得目的節點顯示出來,無疑,這會給我們帶來很大的不便。下面我們就來給樹型控制項新增自動滾動支援。設定乙個定時器,在 wm_timer 訊息中檢測滑鼠的位置,如果靠近樹型控制項的下邊緣,則使得控制項向下滾動,靠近上邊緣則向上滾動。滾動速度根據滑鼠的位置確定。

d、拖動過程中節點智慧型展開

這一步我們要實現的功能是在拖動過程中當滑鼠停留在某個節點上一段時間後,該節點會自動展開。    設定乙個定時器,當滑鼠在拖動過程中停止在某個節點上時,定時器被啟動,再設定一變數儲存當前的滑鼠位置。

下面部分是原始碼:

xtreectrl.h檔案

#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

// xtreectrl.h : header file///

// cxtreectrl window

class cxtreectrl : public ctreectrl

}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

declare_message_map()

private:

htreeitem copybranch(htreeitem htibranch,htreeitem htinewparent,htreeitem htiafter);

htreeitem copyitem(htreeitem hitem,htreeitem htinewparent,htreeitem htiafter);

};

xtreectrl.cpp檔案:#include "xtreectrl.h"

#ifdef _debug

#define new debug_new

#undef this_file

static char this_file = __file__;

#endif

#define drag_delay 60

/// cxtreectrl

cxtreectrl::cxtreectrl()

cxtreectrl::~cxtreectrl()

begin_message_map(cxtreectrl, ctreectrl)

//}afx_msg_map

end_message_map()

/// cxtreectrl message handlers

void cxtreectrl::onbegindrag(nmhdr* pnmhdr, lresult* presult)

void cxtreectrl::onmousemove(uint nflags, cpoint point)

m_nhovertimerid = settimer( 1,800,null ); //定時為 0.8 秒則自動展開

m_hoverpoint = point;

if( m_bdragging )

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)

expand( m_hitemdragd,tve_expand );

htreeitem htiparent = m_hitemdragd;

while( (htiparent = getparentitem(htiparent)) != null )

}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)

//拷貝分支

htreeitem cxtreectrl::copybranch(htreeitem htibranch, htreeitem htinewparent, htreeitem htiafter)

return hnewitem;

}void cxtreectrl::onlbuttondown(uint nflags, cpoint point)

void cxtreectrl::ontimer(uint nidevent)

} //處理拖曳過程中的滾動問題

else if( nidevent == m_nscrolltimerid )

}else if( pt.y > rect.bottom - 10 )

{ //向下滾動

int slowscroll = 6 - (pt.y - rect.bottom + 10)/20;

if( 0 == (m_timerticks % ((slowscroll > 0) ? slowscroll : 1)) )

{cimagelist::dragshownolock ( false );

sendmessage( wm_vscroll,sb_linedown );

int ncount = getvisiblecount();

for( int i=0 ; i

CTreeCtrl 節點擊擇問題

一 問題說明 樹形控制項,單擊某個節點彈出相應的對話方塊 二 問題處理 起先使用了ctreectrl的onselchangedoperate這個事件,實際操作中出現了問題 二次單擊時對話方塊不能顯示,上網查詢資料,才明白二次單擊並不能觸發onselchangedoperate事件 所以最後選擇了on...

CTreeCtrl 使某個節點被選中

一 建立樹形控制項 m operatelist.create ws visible ws tabstop ws child ws border tvs hasbuttons tvs linesatroot tvs haslines tvs disabledragdrop tvs trackselec...

CTreeCtrl 收起某個節點並判斷是否已收起

框架 mfc 需求 收起某個節點,然後判斷改節點是否已收起 問題 收起節點後判斷節點是否收起無效 m treedev.expand m htreeitemlowlevel,tve collapse uint nstate m treedev.getitemstate m htreeitemlowle...