📄 ch10.htm
字号:
</UL>
<P>The four handlers will each call SetWindowLong(), which sets a window's attribute.
Its arguments are the window's handle, a flag that specifies the value to be changed,
and the new value. For example, passing GWL_STYLE as the second value means that
the window's style should be changed to the style given in the third argument. Changing
the list view control's style (for example, to LVS_SMALLICON) changes the type of
view that it displays. With that in mind, add the four handler functions to the bottom
of CommonView.cpp:</P>
<P>
<PRE>void CCommonView::OnSmall()
{
SetWindowLong(m_listView.m_hWnd, GWL_STYLE,
WS_VISIBLE | WS_CHILD | WS_BORDER |
LVS_SMALLICON | LVS_EDITLABELS);
}
void CCommonView::OnLarge()
{
SetWindowLong(m_listView.m_hWnd, GWL_STYLE,
WS_VISIBLE | WS_CHILD | WS_BORDER |
LVS_ICON | LVS_EDITLABELS);
}
void CCommonView::OnList()
{
SetWindowLong(m_listView.m_hWnd, GWL_STYLE,
WS_VISIBLE | WS_CHILD | WS_BORDER |
LVS_LIST | LVS_EDITLABELS);
}
void CCommonView::OnReport()
{
SetWindowLong(m_listView.m_hWnd, GWL_STYLE,
WS_VISIBLE | WS_CHILD | WS_BORDER |
LVS_REPORT | LVS_EDITLABELS);
}
</PRE>
<P>In addition to changing the view, you can program a number of other features for
your list view controls. When the user does something with the control, Windows sends
a WM_NOTIFY message to the parent window. The most common notifications sent by a
list view control are the following:</P>
<P>
<UL>
<LI>LVN_COLUMNCLICK  Indicates that the user clicked a column header
<P>
<LI>LVN_BEGINLABELEDIT  Indicates that the user is about to edit an item's
label
<P>
<LI>LVN_ENDLABELEDIT  Indicates that the user is ending the label-editing
process
</UL>
<P>Why not have Common allow editing of the first column in this list view? You start
by overriding the virtual function OnNotify() that was inherited by CCommonView from
CScrollView. Right-click CCommonView in ClassView and choose Add Virtual Function.
Select OnNotify() from the list on the left and click Add and Edit; then add these
lines of code at the beginning of the function, replacing the TODO comment:</P>
<P>
<PRE>LV_DISPINFO* lv_dispInfo = (LV_DISPINFO*) lParam;
if (lv_dispInfo->hdr.code == LVN_BEGINLABELEDIT)
{
CEdit* pEdit = m_listView.GetEditControl();
// Manipulate edit control here.
}
else if (lv_dispInfo->hdr.code == LVN_ENDLABELEDIT)
{
if ((lv_dispInfo->item.pszText != NULL) &&
(lv_dispInfo->item.iItem != -1))
{
m_listView.SetItemText(lv_dispInfo->item.iItem,
0, lv_dispInfo->item.pszText);
}
}
</PRE>
<P>The three parameters received by OnNotify() are the message's WPARAM and LPARAM
values and a pointer to a result code. In the case of a WM_NOTIFY message coming
from a list view control, the WPARAM is the list view control's ID. If the WM_NOTIFY
message is the LVN_BEGINLABELEDIT or LVN_ENDLABELEDIT notification, the LPARAM is
a pointer to an LV_DISPINFO structure, which itself contains NMHDR and LV_ITEM structures.
You use the information in these structures to manipulate the item that the user
is trying to edit.</P>
<P>If the notification is LVN_BEGINLABELEDIT, your program can do whatever pre-editing
initialization it needs to do, usually by calling GetEditControl() and then working
with the pointer returned to you. This sample application shows you only how to get
that pointer.</P>
<P>When handling label editing, the other notification to watch out for is LVN_ENDLABELEDIT,
which means that the user has finished editing the label, by either typing the new
label or canceling the editing process. If the user has canceled the process, the
LV_DISPINFO structure's item.pszText member will be NULL, or the item.iItem member
will be -1. In this case, you need do nothing more than ignore the notification.
If, however, the user completed the editing process, the program must copy the new
label to the item's text, which OnNotify() does with a call to SetItemText(). The
CListCtrl object's SetItemText() member function requires three arguments: the item
index, the sub-item index, and the new text.</P>
<P>At this point you can build Common again and test it. Click each of the four buttons
to change the view style. Also, try editing one of the labels in the first column
of the list view.</P>
<P>Figure 10.1 already showed you the report view for this list view. Figure 10.6
shows the application's list view control displaying small icons, and Figure 10.7
shows the large icons. (Some controls in these figures have yet to be covered in
this chapter.)</P>
<P>You can do a lot of other things with a list view control. A little time invested
in exploring and experimenting can save you a lot of time writing your user interface.</P>
<P><A HREF="javascript:popUp('10uvc06.gif')"><B>FIG. 10.6</B></A><B> </B><I>Here's
the sample application's list view control set to small icons.</I></P>
<P><A HREF="javascript:popUp('10uvc07.gif')"><B>FIG. 10.7</B></A><B> </B><I>Here's
the sample application's list view control set to large icons.</I></P>
<H2><B></B></H2>
<H2><A NAME="Heading19"></A>The Tree View Control</H2>
<P>In the preceding section, you learned how to use the list view control to organize
the display of many items in a window. The list view control enables you to display
items both as objects in a window and objects in a report organized into columns.
Often, however, the data you'd like to organize for your application's user is best
placed in a hierarchical view. That is, elements of the data are shown as they relate
to one other. A good example of a hierarchical display is the directory tree used
by Windows to display directories and the files that they contain.</P>
<P>MFC provides this functionality in the CTreeCtrl class. This versatile control
displays data in various ways, all the while retaining the hierarchical relationship
between the data objects in the view.</P>
<P>If you'd like to see an example of a tree view control, revisit Windows Explorer
(see Figure 10.8). The left side of the window shows how the tree view control organizes
objects in a window. (The right side of the window contains a list view control,
which you learned about in the preceding section). In the figure, the tree view displays
not only the storage devices on the computer but also the directories and files stored
on those devices. The tree clearly shows the hierarchical relationship between the
devices, directories, and files, and it enables the user to open and close branches
on the tree to explore different levels.</P>
<P><A HREF="javascript:popUp('10uvc08.gif')"><B>FIG. 10.8</B></A><B> </B><I>A tree
view control displays a hierarchical relationship between items.</I></P>
<P><I></I>
<H3><A NAME="Heading20"></A>Creating the Tree View</H3>
<P>Tree views are a little simpler than list views. You will write the rest of CreateTreeView(),
which performs the following tasks:</P>
<P>
<DL>
<DT></DT>
<DD><B>1. </B>Creates an image list
<P>
<DT></DT>
<DD><B>2. </B>Creates the tree view itself
<P>
<DT></DT>
<DD><B>3. </B>Associates the image list with the list view
<P>
<DT></DT>
<DD><B>4. </B>Creates the root item
<P>
<DT></DT>
<DD><B>5. </B>Creates child items
<P>
</DL>
<P>Creating the image list, creating the tree control, and associating the control
with the image list are very similar to the steps completed for the image list. You've
already written the code to create the image list, so add these lines to CreateTreeView():</P>
<P>
<PRE>// Create the Tree View control.
m_treeView.Create(WS_VISIBLE | WS_CHILD | WS_BORDER |
TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS |
TVS_EDITLABELS, CRect(20, 260, 160, 360), this,
IDC_TREEVIEW);
m_treeView.SetImageList(&m_treeImageList, TVSIL_NORMAL);
</PRE>
<P>(Remember to add a resource ID for IDC_TREEVIEW.) The CTreeCtrl class, of which
m_treeView is an object, defines special styles to be used with tree view controls.
Table 10.4 lists these special styles.</P>
<P>
<H4>Table 10.4  Tree View Control Styles</H4>
<P>
<TABLE BORDER="1">
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT"><B>Style</B></TD>
<TD ALIGN="LEFT"><B>Description</B></TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_DISABLEDRAGDROP </TD>
<TD ALIGN="LEFT">Disables drag-and-drop operations </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_EDITLABELS </TD>
<TD ALIGN="LEFT">Enables the user to edit labels </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_HASBUTTONS </TD>
<TD ALIGN="LEFT">Gives each parent item a button </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_HASLINES </TD>
<TD ALIGN="LEFT">Adds lines between items in the tree </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_LINESATROOT </TD>
<TD ALIGN="LEFT">Adds a line between the root and child items </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_SHOWSELALWAYS </TD>
<TD ALIGN="LEFT">Forces a selected item to stay selected when losing focus </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_NOTOOLTIPS </TD>
<TD ALIGN="LEFT">Suppresses ToolTips for the tree items </TD>
</TR>
<TR ALIGN="LEFT" VALIGN="TOP">
<TD ALIGN="LEFT">TVS_SINGLEEXPAND </TD>
<TD ALIGN="LEFT">Expands or collapses tree items with a single click rather than a double click </TD>
</TR>
</TABLE>
<H3><A NAME="Heading21"></A>Creating the Tree View's Items</H3>
<P>Creating items for a tree view control is much like creating items for a list
view control. As with the list view, Visual C++ defines a structure that you must
initialize and pass to the function that creates the items. This structure is called
TVITEM and is defined in Listing 10.8.</P>
<P>
<H4>Listing 10.8  The TVITEM Structure, Defined by MFC</H4>
<PRE>typedef struct _TVITEM
{
UINT mask;
HTREEITEM hItem;
UINT state;
UINT stateMask;
LPSTR pszText;
int cchTextMax;
int iImage;
int iSelectedImage;
int cChildren;
LPARAM lParam;
</PRE>
<PRE>} TV_ITEM;
</PRE>
<P>In the TVITEM structure, the mask member specifies the other structure members
that are valid. The flags you can use are as follows:</P>
<P>
<UL>
<LI>TVIF_CHILDREN  cChildren is valid.
<P>
<LI>TVIF_HANDLE  hItem is valid.
<P>
<LI>TVIF_IMAGE  iImage is valid.
<P>
<LI>TVIF_PARAM  lParam is valid.
<P>
<LI>TVIF_SELECTEDIMAGE  iSelectedImage is valid.
<P>
<LI>TVIF_STATE  state and stateMask are valid.
<P>
<LI>TVIF_TEXT  pszText and cchTextMax are valid.
</UL>
<P>The hItem member is the handle of the item, whereas the state and stateMask members
hold the item's current state and its valid states, which can be one or more of TVIS_BOLD,
TVIS_CUT, TVIS_DROPHILITED, TVIS_EXPANDED, TVIS_EXPANDEDONCE, TVIS_FOCUSED, TVIS_OVERLAYMASK,
TVIS_SELECTED, TVIS_STATEIMAGEMASK, and TVIS_USERMASK.</P>
<P>The pszText member is the address of a string buffer. When using the TVITEM structure
to create an item, the string buffer contains the item's text. When obtaining information
about the item, pszText is the buffer where the information will be stored, and cchTextMax
is the size of the buffer. If pszText is set to LPSTR_TEXTCALLBACK, the item uses
the callback mechanism. Finally, the iImage member is the index of the item's icon
in the image list. If set to I_IMAGECALLBACK, the iImage member indicates that the
item uses the callback mechanism.</P>
<P>The iSelectedImage member is the index of the icon in the image list that represents
the item when the item is selected. As with iImage, if this member is set to I_IMAGECALLBACK,
the iSelectedImage member indicates that the item uses the callback mechanism. Finally,
cChildren specifies whether there are child items associated with the item.</P>
<P>In addition to the TVITEM structure, you must initialize a TVINSERTSTRUCT structure
that holds information about how to insert the new structure into the tree view control.
That structure is declared in Listing 10.9.</P>
<P>
<H4>Listing 10.9  The TVINSERTSTRUCT Structure, Defined by MFC</H4>
<PRE>typedef struct tagTVINSERTSTRUCT {
HTREEITEM hParent;
HTREEITEM hInsertAfter;
#if (_WIN32_IE >= 0x0400)
union
{
TVITEMEX itemex;
TVITEM item;
} DUMMYUNIONNAME;
#else
TVITEM item;
#endif
</PRE>
<PRE>} TVINSERTSTRUCT, FAR *LPTVINSERTSTRUCT;
</PRE>
<P>In this structure, hParent is the handle to the parent tree-view item. A value
of NULL or TVI_ROOT specifies that the item should
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -