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 Variable tvInsertStruct is declared at the beginning of function CCCtlDlg::OnInitDialog(), it is a TV_INSERTSTRUCT type object. To create a specific node, we must stuff this object with node information and call function CTreeCtrl::InsertItem(…). This function returns a handle to the newly created node, which is stored in variable hTreeItem and will be used to create its child node. The following portion of function CCCtlDlg::OnInitDialog() shows how the child node is created: …… …… tvInsertStruct.hParent=hTreeItem; tvInsertStruct.hInsertAfter=TVI_LAST; tvInsertStruct.item.mask=TVIF_IMAGE | TVIF_SELECTEDIMAGE| TVIF_TEXT; tvInsertStruct.item.iImage=1; tvInsertStruct.item.iSelectedImage=1; tvInsertStruct.item.pszText="Doc"; hTreeItem=m_treeCtrl.InsertItem(&tvInsertStruct); ASSERT(hTreeItem); This procedure is exactly the same for other nodes. For different nodes, the only difference of this procedure is that each node has different parent node, uses different image index and text string. For all nodes, their normal states and selected states are represented by the same image (member iImage and iSelectedImage are assigned the same image index), so the image will not change if we select a node. With the above implementations, the tree control can work. By compiling and executing the application at this point, we will see a tree with seven nodes, which are represented by different labels and images. A node can be expanded or collapsed with mouse clicking if it has child node(s). 5.13 Handling Tree Control Messages There are many messages associated with the tree control. We need to write message handlers for the tree control in order to customize its default behavior. In sample 5.13\CCtl we will demonstrates two methods of customizing a tree control: 1) How to change a node’s associated image dynamically. 2) How to enable label editing. Sample 5.13\CCtl is based on sample 5.12\CCtl. In this sample the image associated with node “Folder” will be changed automatically according to its current state (expanded or collapsed). If it is expanded, image IDB_BITMAP_OPENFOLDER will be associated with this node; if it is collapsed, image IDB_BITMAP_CLOSED_FOLDER will be used. Also, the application supports dynamic label editing: if the user clicks mouse’s left button on the label of a node, that node will enter editing mode, and we can edit the text string as if we were using an edit box. The messages associated with node expanding and collapsing are TVN_ITEMEXPANDING and TVN_ITEMEXPANDED. The former message is sent when a node is about to be expanded or collapsed, and the latter message is sent after such action is completed. In our case, we need to handle the former message to change a node’s image before its state changes. Handling TVN_ITEMEXPANDING to Change a Node’s Associated Image In MFC, message TVN_ITEMEXPANDING can be mapped to a member function as follows: void CTreeCtrl::OnItemexpanding(NMHDR *pNMHDR, LRESULT *pResult) { NM_TREEVIEW *pNMTreeView = (NM_TREEVIEW*)pNMHDR; } *pResult = 0; Variable pNMTreeView is a pointer to NM_TREEVIEW type object obtained from the message parameters, it contains the information about the node being clicked: 122

Chapter 5. Common Controls typedef struct _NM_TREEVIEW{ NMHDR hdr; UINT action; TV_ITEM itemOld; TV_ITEM itemNew; POINT ptDrag; } NM_TREEVIEW; The most important member of this structure is action, it could be either TVE_EXPAND (indicating the node is about to expand) or TVE_COLLAPSE (indicating the node is about to collapse). Two other useful members are itemOld and itemNew, both of them are TV_ITEM type objects and contain old and new states of the node respectively. We can check iImage member of itemNew to see if the associated image is 2 or 3 (Indices 2 and 3 correspond to image IDB_BITMAP_CLOSED_FOLDER and IDB_BITMAP_OPENFOLDER respectively, which indicate that the node represents a folder. In the sample, we will not change other node’s image when they are being expanded or collapsed), if so, we need to call function CTreeCtrl::SetItemImage(…) to change the image of the node if necessary. We can handle this message either within class CTreeCtrl or CDialog. Handling the message in CTreeCtrl has the advantage that once the feature is implemented, we can reuse this class in other applications without adding additional code. In the sample, a new class MCTreeCtrl is designed for this purpose. It is added to the application through using Class Wizard. Also, message handlers MCTreeCtrl::OnItemexpanding(…) and MCTreeCtrl::OnEndlabeledit(…) are added to dynamically change node’s associated images and enable label editing (Label editing will be discussed later). The following is the implementation of function MCTreeCtrl::OnItemexpanding(…): void MCTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT *pResult) { NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; } if ( ) { } if ( ) { pNMTreeView->action == TVE_EXPAND && pNMTreeView->itemNew.iImage == 2 SetItemImage(pNMTreeView->itemNew.hItem, 3, 3); pNMTreeView->action == TVE_COLLAPSE && pNMTreeView->itemNew.iImage == 3 SetItemImage(pNMTreeView->itemNew.hItem, 2, 2); } *pResult = 0; If the node is about to expand and its associated image is 2, we associate image 3 with this node. This is implemented through calling function CTreeCtrl::SetItemImage(…), which has the following format: BOOL CTreeCtrl::SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage); The first parameter of this function is the handle of tree control, which can be obtained from pNMTreeView->itemNew.hItem. Similarly, if the node is about to collapse and its associated image is 3, we call this function to associate image 2 with this node. Handling TVN_ENDLABELEDIT to Enable Label Editing The next feature we want to add is label editing. If we are familiar with “Explorer” application in Windows95, we know that the file or directory names (which are node labels) can be edited dynamically by single clicking on it. 123

Chapter 5. Common Controls<br />

typedef struct _NM_TREEVIEW{<br />

NMHDR hdr;<br />

UINT action;<br />

TV_ITEM itemOld;<br />

TV_ITEM itemNew;<br />

POINT ptDrag;<br />

} NM_TREEVIEW;<br />

The most important member of this structure is action, it could be either TVE_EXPAND (indicating the<br />

node is about to expand) or TVE_COLLAPSE (indicating the node is about to collapse). Two other useful<br />

members are itemOld and itemNew, both of them are TV_ITEM type objects and contain old and new states<br />

of the node respectively. We can check iImage member of itemNew to see if the associated image is 2 or 3<br />

(Indices 2 and 3 correspond to image IDB_BITMAP_CLOSED_FOLDER and IDB_BITMAP_OPENFOLDER<br />

respectively, which indicate that the node represents a folder. In the sample, we will not change other<br />

node’s image when they are being expanded or collapsed), if so, we need to call function<br />

CTreeCtrl::SetItemImage(…) to change the image of the node if necessary.<br />

We can handle this message either within class CTreeCtrl or CDialog. Handling the message in<br />

CTreeCtrl has the advantage that once the feature is implemented, we can reuse this class in other<br />

applications without adding additional code.<br />

In the sample, a new class MCTreeCtrl is designed for this purpose. It is added to the application<br />

through using Class Wizard. Also, message handlers MCTreeCtrl::OnItemexpanding(…) and<br />

MCTreeCtrl::OnEndlabeledit(…) are added to dynamically change node’s associated images and enable<br />

label editing (Label editing will be discussed later).<br />

The following is the implementation of function MCTreeCtrl::OnItemexpanding(…):<br />

void MCTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT *pResult)<br />

{<br />

NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;<br />

}<br />

if<br />

(<br />

)<br />

{<br />

}<br />

if<br />

(<br />

)<br />

{<br />

pNMTreeView->action == TVE_EXPAND &&<br />

pNMTreeView->itemNew.iImage == 2<br />

SetItemImage(pNMTreeView->itemNew.hItem, 3, 3);<br />

pNMTreeView->action == TVE_COLLAPSE &&<br />

pNMTreeView->itemNew.iImage == 3<br />

SetItemImage(pNMTreeView->itemNew.hItem, 2, 2);<br />

}<br />

*pResult = 0;<br />

If the node is about to expand and its associated image is 2, we associate image 3 with this node. This<br />

is implemented through calling function CTreeCtrl::SetItemImage(…), which has the following format:<br />

BOOL CTreeCtrl::SetItemImage(HTREEITEM hItem, int nImage, int nSelectedImage);<br />

The first parameter of this function is the handle of tree control, which can be obtained from<br />

pNMTreeView->itemNew.hItem. Similarly, if the node is about to collapse and its associated image is 3, we<br />

call this function to associate image 2 with this node.<br />

Handling TVN_ENDLABELEDIT to Enable Label Editing<br />

The next feature we want to add is label editing. If we are familiar with “Explorer” application in<br />

Windows95, we know that the file or directory names (which are node labels) can be edited dynamically<br />

by single clicking on it.<br />

123

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

Saved successfully!

Ooh no, something went wrong!