Advanced MFC Programming
Advanced MFC Programming Advanced MFC Programming
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
- Page 87 and 88: Chapter 4. Button Use string text a
- Page 89 and 90: Chapter 4. Button function, first t
- Page 91 and 92: Chapter 4. Button Now we can remove
- Page 93 and 94: Chapter 4. Button } ( m_bBmpCheck ?
- Page 95 and 96: Chapter 4. Button using bit-wise AN
- Page 97 and 98: Chapter 4. Button Overriding Functi
- Page 99 and 100: Chapter 4. Button …… First pBit
- Page 101 and 102: Chapter 4. Button Using Class MCBit
- Page 103 and 104: Chapter 4. Button The button’s ID
- Page 105 and 106: Chapter 4. Button However, since me
- Page 107 and 108: Chapter 4. Button Here, we use subc
- Page 109 and 110: Chapter 5. Common Controls command
- Page 111 and 112: Chapter 5. Common Controls ((CSpinB
- Page 113 and 114: Chapter 5. Common Controls } The in
- Page 115 and 116: Chapter 5. Common Controls …… B
- Page 117 and 118: Chapter 5. Common Controls The “S
- Page 119 and 120: Chapter 5. Common Controls button
- Page 121 and 122: Chapter 5. Common Controls In this
- Page 123 and 124: Chapter 5. Common Controls (CBN_CLO
- Page 125 and 126: Chapter 5. Common Controls compare
- Page 127 and 128: Chapter 5. Common Controls } ptrEdi
- Page 129 and 130: Chapter 5. Common Controls ……
- Page 131 and 132: Chapter 5. Common Controls void CWn
- Page 133 and 134: Chapter 5. Common Controls Five loc
- Page 135 and 136: Chapter 5. Common Controls This fun
- Page 137: Chapter 5. Common Controls After cr
- Page 141 and 142: Chapter 5. Common Controls Using th
- Page 143 and 144: Chapter 5. Common Controls Paramete
- Page 145 and 146: Chapter 5. Common Controls void MCT
- Page 147 and 148: Chapter 5. Common Controls modifica
- Page 149 and 150: Chapter 5. Common Controls In funct
- Page 151 and 152: Chapter 5. Common Controls Changing
- Page 153 and 154: Chapter 5. Common Controls m_tabCtr
- Page 155 and 156: Chapter 5. Common Controls Custom R
- Page 157 and 158: Chapter 6. Dialog Box Chapter 6 Dia
- Page 159 and 160: Chapter 6. Dialog Box void CMLDialo
- Page 161 and 162: Chapter 6. Dialog Box } Function CP
- Page 163 and 164: Chapter 6. Dialog Box Everything is
- Page 165 and 166: Chapter 6. Dialog Box } MINMAXINFO;
- Page 167 and 168: Chapter 6. Dialog Box Sample Sampel
- Page 169 and 170: Chapter 6. Dialog Box } brush=(HBRU
- Page 171 and 172: Chapter 6. Dialog Box wndA.GetWindo
- Page 173 and 174: Chapter 6. Dialog Box rectStaticGrp
- Page 175 and 176: Chapter 6. Dialog Box } TOOLTIPTEXT
- Page 177 and 178: Chapter 6. Dialog Box ) { } if ( )
- Page 179 and 180: Chapter 6. Dialog Box pWndCtrl=GetW
- Page 181 and 182: Chapter 6. Dialog Box Sample 6.8-2\
- Page 183 and 184: Chapter 6. Dialog Box } // handle t
- Page 185 and 186: Chapter 6. Dialog Box 1) Tracking s
- Page 187 and 188: Chapter 7. Common Dialog Boxes DWOR
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