标签:des style class code ext strong color get int 文件 set
本课中,我们将学习如何使用树型视图控件。另外还要学习如何在树型视图中完成拖-拉动作,以及如何使用图象列表。
树型视图是一种特别的窗口,我们可以使用它一目了然地表示某种层次关系。譬如象在资源管理器中左边窗口中的就是树型视图。您可以调用CreateWindowEx来创建树型视图,传递一个类名“"SysTreeView32"”,或者您也可以把它放到一个对话框中去。不要忘了在您的代码中加入InitCommonControls函数。
树型视图有几种特有的风格。下面是几种经常使用的。
像其它的通用控件一样,树型视图用消息来完成通信。父窗口发送一系列的消息给树型视图,而树型视图发送"notification"消息给它的父窗口。在这方面,树型视图和其它的通用控制没什么两样。
当有事件发生时,树型视图发送一个WM_NOTIFY消息个父窗口,并在消息中附带传递一些附加信息。
下面我们来看NMHDR:
typedef struct
tagNMHDR
{
HWND
hwndFrom;
UINT idFrom;
UINT
code;
}NMHDR;hwndFrom是发送WM_NOTIFY消息的控件的窗口句柄。
idFrom是发送WM_NOTIFY消息的控件的ID。
code是控件发送给父窗口的数据。
树型视图发送给父窗口的通知消息以TVN_打头。
树型视图接收到的消息以TVM_打头,譬如:TVM_CREATEDRAGIMAGE。树型视图发送TVN_XXX消息时在code变量中放入NMHDR型变量。父窗口发送TVM_消息来控制树型视图。
在创建完树型视图后可以通过发送TVM_INSERTITEM消息往其中加入项目了。
TVM_INSERTITEM
wParam =
0;
lParam = 指向结构体TV_INSERTSTRUCT的指针;
您应当知道一些关于树型视图中的项目之间关系的一些术语。一个项目可能是一个父亲、儿子或两者都是。父项目下含有子项目,而该父项目又有可能是其它项目的子项目。一个没有父项目的项目叫根项目。在树型视图中可能有多个根项目。现在我们来看看TV_INSERTSTRUCT结构体:
typedef struct tagTVINSERTSTRUCT { HTREEITEM hParent; HTREEITEM hInsertAfter; #if (_WIN32_IE >= 0x0400) union { TVITEMEX itemex; TVITEM item; } DUMMYUNIONNAME; #else TVITEM item; #endif } TVINSERTSTRUCT, *LPTVINSERTSTRUCT;
hParent = 父项目的句柄。如果该值为TVI_ROOT
value或NULL,该项目插在树型视图的根部。
hInsertAfter =
应该插入在起后面的项目的句柄或下面的值:
union { TVITEMEX itemex; TVITEM item; } DUMMYUNIONNAME;
我们仅使用TVITEM。
typedef struct tagTVITEM
{
UINT mask;
HTREEITEM
hItem;
UINT state;
UINT
stateMask;
LPTSTR pszText;
int
cchTextMax;
int iImage;
int
iSelectedImage;
int
cChildren;
LPARAM lParam;
} TVITEM,
*LPTVITEM;
该结构体根据消息类型,用来发送或接收关于一个树型视图的项目的有关信息。譬如:对于消息TVM_INSERTITEM,它用来指定插入树型视图控件的项目的属性。而对于消息TVM_GETITEM,该结构体用来填充关于选定项目的信息。
imask 用来指定TV_ITEM的那些成员变量有效。譬如,如果指定了TVIF_TEXT,这意味着pszText成员变量是有效的。您可以同时指定几个标志位。
hItem 是树型视图项目的句柄。每一个项目都有它自己的句柄,就像窗口一样。如果您想要操作一个项目,就必须选择它的句柄。
pszText 是一个字符串指针。它是项目的标签名。
cchTextMax仅在查询项目的名称时使用。由于在pszText中指定了指针,WINDOWS还要知道该缓冲去的大小。所以您必须给出该值。
iImage 和 iSelectedImage用来指定图象列表以及一个索引号。这样就知道当项目被选中或没被选中时用哪个图象来表示该项目。像资源管理器中左边窗口中的文件夹等小图表就是有这两个参数来决定的。
为了在树型视图中插入一个项目,您必须至少设定hParent,
hInsertAfter,另外您还要设定imask和pszText值。
如果您想要在项目的名称左边显示图标的话,您必须创建一个图形列表,并且把它和树形视图相关联起来。您可以调用ImageList_Create来创建一个图形列表。
HIMAGELIST ImageList_Create( int cx, int cy, UINT flags, int cInitial, int cGrow );
如果创建成功的话,该函数返回一个空的图象列表的句柄。
cx ==
以像素为单位的图象的宽度。
cy ==
以像素为单位的图象的高度。图象列表中的每一幅的高度都必须相同。否则WINDOWS会对您的图象进行裁剪,如果过大的话就可能裁剪成几小块。所以您必须指定相同大小的图象。
flags ==
指定图象列表的图象的颜色深度。详细情况请参考WIN32 API 指南。
cInitial ==
指定包含的图象的数目。WINDWOS将依此来分配合适的内存。
cGrow ==
在增加新图象是一次增加的数目。
图象列表不是窗口。仅仅是保存在那给其它的窗口使用的一种资源。在图象列表产生后,您可以调用ImageList_Add来向其中加入图象。
int
ImageList_Add(
HIMAGELIST himl,
HBITMAP hbmImage,
HBITMAP hbmMask
);
如果该函数调用失败的话,返回-1。
himl ==
图象列表的句柄。它是调用ImageList_Create时返回的值。
hbmImage ==
加入图象列表的位图的句柄。您通常把位图保存在资源中,然后调用LoadBitmap来把它加载进来。注意您没有必要指定该位图中包含的图象的数目。WINDOWS会根据它的大小,自动计算。
hbmMask ==
掩码位图的句柄。如果没有使用掩码位图,可以忽略该值。通常我们加入两种图象到图象列表中。一种时被选中时显示的图象,另一种时没被选中时显示的。
当图象列表准备就绪后,您可以发送消息TVM_SETIMAGELIST给树型视图来让图象列表和树型视图联系起来。
您可以通过发送消息TVM_GETITEM来检索图形视图的信息。
TVM_GETITEM
wParam =
0
lParam =指向结构体TV_ITEM的指针。该结构体将用来得到相关的信息。
在发送该消息前必须设置成员变量imask的值,以便WINDOWS能告诉相关的信息。当然,最重要的是,您必须传递您想得到信息的项目的句柄。这就引起了一个问题,您如何得到项目的句柄?要保存所有项目的句柄吗?
答案是很简单的:没有必要。您可以发送消息TVM_GETNEXTITEM到树型视图以检索您想要得到其属性的项目的句柄。譬如:您可以查询第一个子项目的句柄、根目录的句柄、选中的项目的句柄等等。
wParam中的值非常重要, 我解释如下:
由此您可以通过发送该消息来得到项目的句柄,然后在发送消息TVM_GETITEM时在结构体变量TV_ITEM的成员变量hItem中放入该项目的句柄就可以得到关于该项目的有关信息了。
也就是因为这一部分我才决定写这课教程。当我按照InPrise公司的WIN32帮助来运行例子时,发现它的帮助中缺少真正重要的信息。我只有通过自己做实验,最后总算弄明白来个中来由。希望您不要和我一样再去走这些弯路,下面我把我所知的在树型视图中进行拖-拉操作的步骤描述如下:
#include "Windows.h"
#include "tchar.h"
#include
"commctrl.h"
#pragma comment(lib,"comctl32.lib")
#define
IDB_TREE 4006
TCHAR ClassName[] = _T("TreeViewWinClass");
TCHAR
AppName[] = _T("Tree View Demo");
TCHAR TreeViewClass[] =
_T("SysTreeView32");
TCHAR Parent[] = _T("Parent Item");
TCHAR Child1[] =
_T("Child1");
TCHAR Child2[] = _T("Child2");
BOOL DragMode =
FALSE;
HINSTANCE g_hInstance;
HWND hwndTreeView;
HTREEITEM
hParent;
HIMAGELIST hImageList;
HIMAGELIST hDragImageList;
INT_PTR
CALLBACK ProcWinMain( HWND hWnd,
UINT Msg,
WPARAM
wParam,
LPARAM lParam
)
{
TV_INSERTSTRUCT
tvinsert;
HBITMAP hBitmap;
TV_HITTESTINFO
tvhit;
switch(Msg)
{
case WM_CREATE:
hwndTreeView =
CreateWindowEx(NULL,TreeViewClass,NULL,WS_CHILD|WS_VISIBLE|TVS_HASLINES|TVS_HASBUTTONS|TVS_LINESATROOT,0,0,200,400,hWnd,NULL,
g_hInstance,NULL);
hImageList
= ImageList_Create(16,16,ILC_COLOR16,2,10);
hBitmap =
LoadBitmap(g_hInstance,MAKEINTRESOURCE(IDB_TREE));
ImageList_Add(hImageList,hBitmap,NULL);
DeleteObject(hBitmap);
SendMessage(hwndTreeView,TVM_SETIMAGELIST,0,(LPARAM)hImageList);
tvinsert.hParent
= NULL;
tvinsert.hInsertAfter = TVI_ROOT;
tvinsert.item.mask =
TVIF_TEXT|TCIF_IMAGE|TVIF_SELECTEDIMAGE;
tvinsert.item.pszText =
Parent;
tvinsert.item.iImage = 0;
tvinsert.item.iSelectedImage =
1;
hParent = (HTREEITEM)
SendMessage(hwndTreeView,TVM_INSERTITEM,0,(LPARAM)&tvinsert);
tvinsert.hParent
= hParent;
tvinsert.hInsertAfter = TVI_LAST;
tvinsert.item.pszText =
Child1;
SendMessage(hwndTreeView,TVM_INSERTITEM,0
,(LPARAM)&tvinsert);
tvinsert.item.pszText =
Child2;
SendMessage(hwndTreeView,TVM_INSERTITEM,0,(LPARAM)&tvinsert);
break;
case
WM_DESTROY:
PostQuitMessage(0);
break;
case
WM_MOUSEMOVE:
if(DragMode)
{
tvhit.pt.x = LOWORD(lParam);
tvhit.pt.y
=
HIWORD(lParam);
ImageList_DragMove(tvhit.pt.x,tvhit.pt.y);
ImageList_DragShowNolock(FALSE);
HTREEITEM
hTmp =
(HTREEITEM)SendMessage(hwndTreeView,TVM_HITTEST,NULL,(LPARAM)&tvhit);
if(hTmp
!=
NULL)
SendMessage(hwndTreeView,TVM_SELECTITEM,TVGN_DROPHILITE,(LPARAM)hTmp);
ImageList_DragShowNolock(TRUE);
}
break;
case
WM_LBUTTONDOWN:
if(DragMode)
{
ImageList_DragLeave(hwndTreeView);
ImageList_EndDrag();
ImageList_Destroy(hDragImageList);
HTREEITEM
hTmp =
(HTREEITEM)SendMessage(hwndTreeView,TVM_GETNEXTITEM,TVGN_DROPHILITE,0);
SendMessage(hwndTreeView,TVM_SELECTITEM,TVGN_CARET,(LPARAM)hTmp);
SendMessage(hwndTreeView,TVM_SELECTITEM,TVGN_DROPHILITE,0);
ReleaseCapture();
DragMode
= FALSE;
}
break;
case WM_NOTIFY:
{
NM_TREEVIEW *pTree =
(NM_TREEVIEW *)lParam;
if(pTree->hdr.code ==
TVN_BEGINDRAG)
{
hDragImageList = (HIMAGELIST )
SendMessage(hwndTreeView,TVM_CREATEDRAGIMAGE,0,(LPARAM)pTree->itemNew.hItem);
ImageList_BeginDrag(hDragImageList,0,0,0);
ImageList_DragEnter(hwndTreeView,pTree->ptDrag.x,pTree->ptDrag.y);
SetCapture(hWnd);
DragMode
= TRUE;
}
}
break;
default:
return
DefWindowProc(hWnd,Msg,wParam,lParam);
}
return 0;
}
int WINAPI
WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR
lpCmdLine,
int nCmdShow
)
{
WNDCLASSEX wc;
MSG msg;
HWND
hWnd;
g_hInstance = hInstance;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = ProcWinMain;
wc.cbClsExtra =
NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hbrBackground
= (HBRUSH)(COLOR_APPWORKSPACE);
wc.lpszMenuName = NULL;
wc.lpszClassName =
ClassName;
wc.hIcon = wc.hIconSm =
LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor =
LoadCursor(NULL,IDC_ARROW);
RegisterClassEx(&wc);
hWnd =
CreateWindowEx(WS_EX_CLIENTEDGE,ClassName,AppName,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,200,400,NULL,NULL,hInstance,NULL);
ShowWindow(hWnd,SW_SHOWNORMAL);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return
msg.wParam;
InitCommonControls();
}
win32 sdk树形控件的项拖拽实现,码迷,mamicode.com
标签:des style class code ext strong color get int 文件 set
原文地址:http://www.cnblogs.com/lidabo/p/3701584.html