Advanced MFC Programming

Advanced MFC Programming Advanced MFC Programming

math.hcmuns.edu.vn
from math.hcmuns.edu.vn More from this publisher
11.04.2014 Views

Chapter 5. Common Controls implement dragging. We can also create our own customized image list for dragging operation, the procedure of creating this type of image list is the same with creating a normal image list. 1) We can call function CImageList::SetDragCursorImage(…) to combine an image contained in the image list with the cursor to begin dragging. 1) We must lock the tree control window when a node is being dragged around to avoid any change happening to the tree structure (When a node is being dragged, the tree should not change). When we want to do a temporary update (For example, when the dragging image enters a node and we want to highlight that node to indicate that the source can be dropped there), we must first unlock the window, then implement the update. If we want the dragging to be continued, we must lock the window again. 1) Function CImageList::EnterDrag(…) can be called to enter dragging mode and lock the tree control window. Before we make any change to the tree control window (For example, before we highlight a node), we need to call function CImageList::LeaveDrag(…) to unlock the tree control window. After the updates, we need to call CImageList::EnterDrag(…) again to lock the window. This will prevent the tree control from being updated when a node is being dragged around. 1) We can show or hide the dragging image by calling function CImageList::DragShowNolock(…) without locking the tree control window. This function is usually called before CImageList::SetDragCursorImage(…) is called. 1) To begin dragging, we need to call CImageList::BeginDrag(…); to move the dragging image to a specified position, we can call CImageList::DragMove(…); to end dragging, we need to call CImageList::EndDrag(). 1) We can highlight a node by calling function CTreeCtrl::SelectDropTarget(…). The following is a list of prototypes of the above-mentioned functions: BOOL CImageList::DragShowNolock(BOOL bShow); Parameter bShow Meaning TRUE to show the dragging image, FALSE to hide it. This function does not lock the tree control window. BOOL CImageList::SetDragCursorImage(int nDrag, CPoint ptHotSpot); Parameter nDrag PtHotSpot Meaning Index of the image in the list that will be used as the dragging image. Position of the hot spot in the image, this position will be used to do hit test when the image is being dragged around. BOOL CImageList::BeginDrag(int nImage, CPoint ptHotSpot); Parameter nImage ptHotSpot Meaning Index of the image in the list that will be used as the dragging image. Initial position to start dragging. BOOL CImageList::DragMove(CPoint pt); Parameter pt Meaning New position where the dragging image can be put. BOOL CImageList::DragEnter(CWnd *pWndLock, CPoint point); Parameter pWndLock point Meaning Pointer to the window that should be locked during the dragging. Position where the dragging image can be displayed. BOOL CImageList::DragLeave(CWnd *pWndLock); 126

Chapter 5. Common Controls Parameter pWndLock Meaning The window that has been locked during the dragging. BOOL CTreeCtrl::SelectDropTarget(HTREEITEM hItem); Parameter hItem Meaning Handle of the node that is to be highlighted. When the mouse button is released, we need to check if the source node can be copied to the target node. In the sample, we disable copying under the following three conditions: 1) The source node is the same with the target node. 2) The target node is a descendent node of the source node. 3) The target node does not have any child node. By setting these restrictions, a node can only be copied to become the child of its parent node (direct or indirect). We can use function CTreeCtrl::GetParentItem(…) to decide if one node is the descendent of another node: HTREEITEM CTreeCtrl::GetParentItem(HTREEITEM hItem); This function will return an HTREEITEM handle, which specifies the parent of node hItem. By repeatedly calling this function we will finally get a NULL return value (This indicates that the root node was encountered). Using this method, we can easily find out a list of all nodes that are parents of a specific node. New Member Variables and Functions To implement drag-n-drop, several new variables and functions are declared in class MCTreeCtrl: …… …… class MCTreeCtrl : public CTreeCtrl { public: void CopyItemTo(HTREEITEM, HTREEITEM); BOOL IsDescendent(HTREEITEM, HTREEITEM); //{{AFX_VIRTUAL(MCTreeCtrl) //}}AFX_VIRTUAL protected: BOOL m_bIsDragging; CImageList *m_pilDrag; HTREEITEM m_hTreeDragSrc; HTREEITEM m_hTreeDragTgt; }; Here, Boolean type variable m_bIsDragging is used to indicate if the drag-n-drop activity is undergoing. Pointer m_pilDrag will be used to store the dragging image. Variables m_hTreeDragSrc and m_hTreeDragTgt are used to store the handles of source and target nodes respectively. We can use them to implement copying right after the source node is dropped. Function MCTreeCtrl::IsDescendent(…) is used to judge if one node is the descendent node of another, and MCTreeCtrl::CopyItemTo(…) will copy one node (and all its descendent nodes) to another place. Node Copy When copying a node, we want to copy not only the node itself, but also all its descendent nodes. Since we do not know how many descendents a node have beforehand, we need to call function MCTreeCtrl::CopyItemTo(…) recursively until all the descendent nodes are copied. The following is the implementation of this function: void MCTreeCtrl::CopyItemTo(HTREEITEM hTreeDragTgt, HTREEITEM hTreeDragSrc) { 127

Chapter 5. Common Controls<br />

Parameter<br />

pWndLock<br />

Meaning<br />

The window that has been locked during the dragging.<br />

BOOL CTreeCtrl::SelectDropTarget(HTREEITEM hItem);<br />

Parameter<br />

hItem<br />

Meaning<br />

Handle of the node that is to be highlighted.<br />

When the mouse button is released, we need to check if the source node can be copied to the target<br />

node. In the sample, we disable copying under the following three conditions: 1) The source node is the<br />

same with the target node. 2) The target node is a descendent node of the source node. 3) The target node<br />

does not have any child node. By setting these restrictions, a node can only be copied to become the child<br />

of its parent node (direct or indirect).<br />

We can use function CTreeCtrl::GetParentItem(…) to decide if one node is the descendent of<br />

another node:<br />

HTREEITEM CTreeCtrl::GetParentItem(HTREEITEM hItem);<br />

This function will return an HTREEITEM handle, which specifies the parent of node hItem. By<br />

repeatedly calling this function we will finally get a NULL return value (This indicates that the root node<br />

was encountered). Using this method, we can easily find out a list of all nodes that are parents of a specific<br />

node.<br />

New Member Variables and Functions<br />

To implement drag-n-drop, several new variables and functions are declared in class MCTreeCtrl:<br />

……<br />

……<br />

class MCTreeCtrl : public CTreeCtrl<br />

{<br />

public:<br />

void CopyItemTo(HTREEITEM, HTREEITEM);<br />

BOOL IsDescendent(HTREEITEM, HTREEITEM);<br />

//{{AFX_VIRTUAL(MCTreeCtrl)<br />

//}}AFX_VIRTUAL<br />

protected:<br />

BOOL m_bIsDragging;<br />

CImageList *m_pilDrag;<br />

HTREEITEM m_hTreeDragSrc;<br />

HTREEITEM m_hTreeDragTgt;<br />

};<br />

Here, Boolean type variable m_bIsDragging is used to indicate if the drag-n-drop activity is<br />

undergoing. Pointer m_pilDrag will be used to store the dragging image. Variables m_hTreeDragSrc and<br />

m_hTreeDragTgt are used to store the handles of source and target nodes respectively. We can use them to<br />

implement copying right after the source node is dropped. Function MCTreeCtrl::IsDescendent(…) is<br />

used to judge if one node is the descendent node of another, and MCTreeCtrl::CopyItemTo(…) will copy<br />

one node (and all its descendent nodes) to another place.<br />

Node Copy<br />

When copying a node, we want to copy not only the node itself, but also all its descendent nodes. Since<br />

we do not know how many descendents a node have beforehand, we need to call function<br />

MCTreeCtrl::CopyItemTo(…) recursively until all the descendent nodes are copied. The following is the<br />

implementation of this function:<br />

void MCTreeCtrl::CopyItemTo(HTREEITEM hTreeDragTgt, HTREEITEM hTreeDragSrc)<br />

{<br />

127

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!