11.04.2014 Views

Advanced MFC Programming

Advanced MFC Programming

Advanced MFC Programming

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Chapter 14. Views<br />

how the default styles of the tree control are customized in the sample (within function CDirView::<br />

OnInitialUpdate()):<br />

……<br />

……<br />

lStyleOld=::GetWindowLong(GetTreeCtrl().GetSafeHwnd(), GWL_STYLE);<br />

lStyleOld|=TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS;<br />

::SetWindowLong(GetTreeCtrl().GetSafeHwnd(), GWL_STYLE, lStyleOld);<br />

Style TVS_HASLINES will let the nodes be connected by dotted lines, TVS_LINESATROOT will add a line<br />

at the root node, and TVS_HASBUTTONS will add a rectangle button (displays either “+” or “-”) for each<br />

expandable node. If we do not specify these styles, the tree control will look slightly different.<br />

These styles can also be customized in function CView::PreCreateWindw(…). In order to do so, we<br />

need to set the corresponding style flags for member dwExStyle of structure CREATESTRUCT. The difference<br />

between two methods is that using ::SetWindowLong(…) can let us change the styles of a window<br />

dynamically.<br />

Adding Root Node<br />

The next step is to add nodes to the tree. We need to call function CTreeCtrl::InsertItem(…) to add a<br />

node to the tree. To call this function, we need to prepare a TV_INSERTSTRUCT type object, and specify the<br />

properties of node. For example, we can specify the node’s parent, associated image, label and states. This<br />

procedure has been discussed in chapter 5. One thing we need to pay attention to is that since<br />

InsertItem(…) is not a member function of CTreeView, we must first call function<br />

CTreeView::GetTreeCtrl() to obtain the tree control before adding any node. The following portion of<br />

function CDirView::OnInitialUpdate() shows how the root node is added:<br />

……<br />

memset(&tvInsertStruct, 0, sizeof(TV_INSERTSTRUCT));<br />

tvInsertStruct.hParent=NULL;<br />

tvInsertStruct.hInsertAfter=TVI_LAST;<br />

tvInsertStruct.item.iImage=0;<br />

tvInsertStruct.item.iSelectedImage=0;<br />

tvInsertStruct.item.pszText="Desktop";<br />

tvInsertStruct.item.mask=TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_TEXT | TVIF_STATE;<br />

tvInsertStruct.item.stateMask|=TVIS_EXPANDED;<br />

tvInsertStruct.item.state|=TVIS_EXPANDED;<br />

……<br />

hTreeItem=GetTreeCtrl().InsertItem(&tvInsertStruct);<br />

ASSERT(hTreeItem);<br />

Finding out Available Drives in the System<br />

By stuffing TV_INSERTSTRUCT type object and calling function CTreeCtrl::InsertItem(…) repeatedly,<br />

the tree can be created. However, before proceeding to create other nodes, we need to find out all the<br />

available drives in the system.<br />

Currently there can be at most 26 drives contained in one system, which are labeled from “A:” to “Z:”.<br />

We can call runtime function _chdrive(…) to change the current working drive (Calling this function has<br />

the same effect with typing command “a:” in a DOS prompt window). Function _chdrive(…) has one<br />

parameter:<br />

int _chdrive(int drive);<br />

Parameter drive specifies target drive. It can be any number from 1 to 26, which represents drive A:,<br />

B:, C:… and so on. The function will return 0 if the working drive is changed successfully, otherwise it<br />

returns -1.<br />

So we can call this function repeatedly by passing 1, 2, 3…26 to it and examining the returned value. If<br />

the function returns 0, this means the drive is available, and we need to add it to the tree control. If the<br />

function returns -1, we can just go on to check the next drive.<br />

438

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

Saved successfully!

Ooh no, something went wrong!