【材料整理】VC 树形控件 例子及相关知识

转自:http://www.vckbase.com/index.php/wv/1352

首先,我们要创建一个基本对话框的MFC工程MFC_TreeCRTL(名字随便给一个)。然后在资源视图中插入两个Dialog,ID分别为IDD_DIALOG11和IDD_DIALOG211,都更改Style属性为Child,Border属性为None,为它们建立两个类,分别命名为Cdialog11和Cdialog211,并在MFC_TreeCRTLDlg.CPP文件中包含dialog11.h和dialog211.h两个头文件。再导入几个资源图标作为树形控件节点的图标及装饰面板。最后在主面板上添加一个CTreeCtrl控件,ID为默认,并在ClassWizard中添加它的一个变量,命名为m_mytree。

接着,我们进行具体代码编写。

我们必须在CMFC_TreeCRTLDlg类中加入这些变量和函数

CDialog * m_treePages[2];
CString node_name;
BOOL InitMytree();

我们还要在CMFC_TreeCRTLDlg类的构造函数中为m_treePages[2]分配空间,

m_treePages[0]=new Cdialog11;
m_treePages[1]=new Cdialog211;
InitMytree()函数为m_mytree的初始化过程。(原文遗漏,若没有这句,不显示)在OnInitDialog里面加上 InitMytree();  //关键

BOOL CMFC_TreeCRTLDlg::InitMytree()
{
	//节点的图标	 
	int i=0;
	int i_count=2;
	//载入图标
	HICON icon[4];
	icon[0]=AfxGetApp()->LoadIcon (IDI_ICON6); 
	icon[1]=AfxGetApp()->LoadIcon (IDI_ICON7);

	//创建图像列表控件
	CImageList* m_imagelist=new CImageList; 
	m_imagelist->Create(16,16,0,7,7); 
	m_imagelist->SetBkColor (RGB(255,255,255));
	for(int n=0; n < i_count; n++)
		m_imagelist->Add(icon[n]);//把图标载入图像列表控件
	m_mytree.SetImageList(m_imagelist,TVSIL_NORMAL);  //为m_mytree设置一个图像列表,使CtreeCtrl的节点显示不同的图标 
	m_mytree.SetBkColor(RGB(0,250,255));//设置m_mytree的背景色

	//创建节点
	//父节点
	HTREEITEM root0=m_mytree.InsertItem(L"Dialog1",0,1,TVI_ROOT,TVI_LAST);
	HTREEITEM root1=m_mytree.InsertItem(L"Dialog2",0,1,TVI_ROOT,TVI_LAST);
	//一层子节点
	HTREEITEM sub_son0=m_mytree.InsertItem(L"Dialog 1-1",0,1,root0,TVI_LAST);
	HTREEITEM sub_son1=m_mytree.InsertItem(L"Dialog 2-1",0,1,root1,TVI_LAST);
	//二层孙子节点
	HTREEITEM sub_m_son0=m_mytree.InsertItem(L"Dialog 2-1-1",0,1,sub_son1,TVI_LAST);

	//建立节点对应的Dialog
	m_treePages[0]->Create(IDD_DIALOG11,this);
	m_treePages[1]->Create(IDD_DIALOG211,this);
	m_treePages[0]->ShowWindow(SW_SHOW);
	m_treePages[1]->ShowWindow(SW_HIDE);

	//把Dialog移到合适位置
	CRect m_rect;
	GetClientRect(m_rect);
	m_rect.left=200;
	m_treePages[0]->MoveWindow(m_rect);
	m_treePages[1]->MoveWindow(m_rect);

	return true;
}

始初化完成后,我们要添加CTreeCtrl的消息响应事件,这样才能让它按我们的要求起作用。我们打开Class Wizard点选IDC_TREE1添加TVN_SELCHANGED消息,并在消息响应函数中写入代码。

void CMFC_TreeCRTLDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult)
{
	//LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
	UpdateData(true);
	CString node_name=m_mytree.GetItemText(pNMTreeView->itemNew.hItem);
	//在标题栏显示节点信息
	SetWindowText(node_name);
	//切换面板
	if(node_name=="Dialog 1-1"){
		m_treePages[0]->ShowWindow(SW_SHOW);
		m_treePages[1]->ShowWindow(SW_HIDE);
	}
	else if(node_name=="Dialog 2-1-1"){
		m_treePages[0]->ShowWindow(SW_HIDE);
		m_treePages[1]->ShowWindow(SW_SHOW);
	}
	UpdateData(false);

	*pResult = 0;
}


以下转自: http://blog.sina.com.cn/s/blog_6a817a6c0100v2sx.html

树形控件TreeCtrl和下节要讲的列表控件 ListCtrl在系统中大量被使用,例如Windows资源管理器就是一个典型的例子。

关于创建及风格:

树形控件可以用于树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点。MFC中使用CTreeCtrl类来封装树形控件的各种操作。通过调用Create创建一个窗口:

BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );

dwStyle中可以使用以下一些树形控件的专用风格:

TVS_CHECKBOXES 

    4.70版:在每个item前面显示出复选框。必须为item关联了Image之后,复选框才能显示出来。设置这种风格的时候,要用DrawFrameControl创建并且设置两种状态的图片,一种是选中状态的图片,另一种是未选中时的图片。更多信息请查看Working with state image indexes.

在5.80版中,即使没有图片,也会显示复选框。

这种风格一旦创建,将不能移除。只能destroy后再create一个新的。

   在创建treeview control之后,用SetWindowLong函数设置TVS_CHECKBOXES 即可。

TVS_DISABLEDRAGDROP  
     防止tree-view control发送TVN_BEGINDRAG消息。

TVS_EDITLABELS  
     允许用户修改item标签

TVS_FULLROWSELECT  
     允许选定整行。已选定的整行将高亮显示,点击这个item所在行的任意地方都将导致它被选中。这种风格不能与TVS_HASLINES并存。

TVS_HASBUTTONS  
    在父节点处显示(+)或(-)。用户可以点击这些按钮展开或者合并它的子节点。为了在tree-view的root处显示出按钮来,必须要用TVS_LINESATROOT.

TVS_HASLINES  
    用直线显示item之间的层次关系。

TVS_INFOTIP  
     通过发送TVN_GETINFOTIP得到功能提示信息。

TVS_LINESATROOT  
     用直线连接root处的item.如果没有TVS_HASLINES风格,这种风格将被忽略。

TVS_NOHSCROLL  
     不显示垂直滚动条。

TVS_NONEVENHEIGHT  
     让items之间的距离是不等的,否则就是等间距的.可用TVM_SETITEMHEIGHT设置高度。

TVS_NOSCROLL  
      无滚动条。.

TVS_NOTOOLTIPS  
      无提示

TVS_RTLREADING  
      按照从右到左的顺序显示文本。

TVS_SHOWSELALWAYS
      当tree-view control失去焦点时,被选中的item仍然保留被选中状态。 

TVS_SINGLEEXPAND  
     4.71版任何时刻只有一个item的child item被展开。如果用单击选中item并且这个item还没有展开的话,那么单击后它将被展开。如果选择item的时候用户按下了CTRL键,未被选中的item将不会自动收起。
     5.80版将使被选中的item展开,未被选中的收起。如果按下了CTRL,未被选中的不会收起。

TVS_TRACKSELECT 

    允许跟踪

 

 

关于增加/删除

   在树形控件中每一个结点都有一个句柄(HTREEITEM),同时添加结点时必须提供的参数是该结点的父结点句柄,(其中根Root结点只有一个,既不可以添加也不可以删除)利用InsertItem可以添加一个结点:

HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST );

pszItem为显示的字符

hParent代表父结点的句柄,当前添加的结点会排在hInsertAfter表示的结点的后面,返回值为当前创建的结点的句柄。

下面的代码会建立一个如下形式的树形结构: 
+--- Parent1
+--- Child1_1
+--- Child1_2
+--- Child1_3
+--- Parent2
+--- Parent3

HTREEITEM hItem,hSubItem;

//在根结点上添加Parent1
hItem = m_tree.InsertItem( "Parent1 ",TVI_ROOT);

//在Parent1上添加一个子结点
hSubItem = m_tree.InsertItem( "Child1_1 ",hItem);

//在Parent1上添加一个子结点,排在Child1_1后面

hSubItem = m_tree.InsertItem( "Child1_2 ",hItem,hSubItem);
hSubItem = m_tree.InsertItem( "Child1_3 ",hItem,hSubItem);
hItem = m_tree.InsertItem( "Parent2 ",TVI_ROOT,hItem); 
hItem = m_tree.InsertItem( "Parent3 ",TVI_ROOT,hItem);
 

 

 

关于添加图标
如果你希望在每个结点前添加一个小图标,就必需先调用

CImageList* SetImageList( CImageList * pImageList, int nImageListType );

指明当前所使用的ImageList,nImageListType为TVSIL_NORMAL。在调用完成后控件中使用图片以设置的ImageList中图片为准。然后调用InsertItem添加结点:

HTREEITEM InsertItem( LPCTSTR lpszItem, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST);

nImage为结点没被选中时所使用图片序号,nSelectedImage为结点被选中时所使用图片序号。下面的代码演示了ImageList的设置。 

m_list.Create(IDB_TREE,16,4,RGB(0,0,0));
m_tree.SetImageList(&m_list,TVSIL_NORMAL);
m_tree.InsertItem( "Parent1 ",0,1);//添加,选中时显示图标1,未选中时显示图标0

 

 

关于插入标记

这是拖曳时经常用到的函数。

BOOL SetInsertMark( HTREEITEM hItem, BOOL fAfter = TRUE );

TRUE表示在hItem下面显示横杠,而FALSE则表示在上面。

同类函数还有:

SetInsertMarkColor,GetInsertMarkColor

 

 

关于得到/修改控件状态
此外CTreeCtrl还提供了一些函数用于得到/修改控件的状态。 
HTREEITEM GetSelectedItem( );将返回当前选中的结点的句柄。

BOOL SelectItem( HTREEITEM hItem );将选中指明结点。 
BOOL GetItemImage( HTREEITEM hItem, int& nImage, int& nSelectedImage )用于得到某结点所使用图标索引。

BOOL SetItemImage( HTREEITEM hItem, int nImage, int nSelectedImage )用于修改某结点所使用图标索引。 
CString GetItemText( HTREEITEM hItem )用于得到某一结点的显示字符。

BOOL SetItemText( HTREEITEM hItem, LPCTSTR lpszItem );用于修改某一结点的显示字符。 
BOOL DeleteItem( HTREEITEM hItem );用于删除某一结点

BOOL DeleteAllItems( );将删除所有结点。

 

如何展开/收缩一个父节点?

CTreeCtrl::Expand
BOOL Expand( HTREEETEM hItem, UINT nColor );
返回值:如果成功则返回非零值;否则返回0。
参数:
hItem 要被扩展的tree项的句柄。
nCode 用来指示要被进行的动作的标志。这个标志可以是下列值之一:
· TVE_COLLAPSE 收缩列表。
· TVE_COLLAPSERESET 收缩列表并删除子项。
· TVE_EXPAND 展开列表。
· TVE_TOGGLE 如果列表当前是展开的则收缩列表;反之则展开列表。
说明:
此成员函数用来展开或收缩给定父项的子项列表(如果有)。

 

关于遍历:

此外如果想遍历树可以使用下面的函数: 
HTREEITEM GetRootItem( );得到根结点。 
HTREEITEM GetChildItem( HTREEITEM hItem );得到子结点。 
HTREEITEM GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem );得到指明结点的上/下一个兄弟结点。 
HTREEITEM GetParentItem( HTREEITEM hItem );得到父结点。

<后面有两个遍历例程>

 

 

关于消息映射:
树形控件的消息映射使用ON_NOTIFY宏,形式如同:

ON_NOTIFY( wNotifyCode, id, memberFxn )

wNotifyCode为通知代码,id为产生该消息的窗口ID

memberFxn为处理函数,函数的原型如同void OnXXXTree(NMHDR* pNMHDR, LRESULT* pResult),其中pNMHDR为一数据结构,在具体使用时需要转换成其他类型的结构。对于树形控件可能取值和对应的数据结构为: 
TVN_SELCHANGED 在所选中的结点发生改变后发送,所用结构:NMTREEVIEW 
TVN_ITEMEXPANDED 在某结点被展开后发送,所用结构:NMTREEVIEW 
TVN_BEGINLABELEDIT 在开始编辑结点字符时发送,所用结构:NMTVDISPINFO 
TVN_ENDLABELEDIT 在结束编辑结点字符时发送,所用结构:NMTVDISPINFO 
TVN_GETDISPINFO 在需要得到某结点信息时发送,(如得到结点的显示字符)所用结构:NMTVDISPINFO
 
关于ON_NOTIFY有很多内容,将在以后的内容中进行详细讲解。

 

消息处理例程

如何获得右击项句柄?

 

响应NM_RCLICK消息

void CLayerDialog::OnRclick(NMHDR* pNMHDR, LRESULT* pResult)

{

       // TODO: Add your control notification handler code here

       NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

       //右击获取所选项

       CPoint   point,p;  

       TVHITTESTINFO   HitTestInfo;  

       GetCursorPos(&point);

       m_treectrl.ScreenToClient(&point);  

       HitTestInfo.pt   =   point;  

       HTREEITEM h   =   m_treectrl.HitTest(&HitTestInfo);

       if(h!=NULL)

       {

              。。。。。//需要代码 

       }

}

 

如何响应checkbox被单击? 

响应NM_CLICK消息(checkbox就是分支前面的复选框,可从资源中修改属性添加)

void CLayerDialog::OnLclick(NMHDR *pNMHDR,LRESULT *pResult)

{

    NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

    // TODO: Add your control notification handler code here

    CPoint p;

    GetCursorPos(&p);

    m_treectrl.ScreenToClient(&p);

    UINT nFlag;

    HTREEITEM h=m_treectrl.HitTest(p,&nFlag);

   if((h !=  NULL)&&(TVHT_ONITEMSTATEICON & nFlag))  

   {   

           。。。。。//需要代码

    }

}

 

设置和获取checkbox的状态函数

GetCheck( ) 

SetCheck( )

 

 

 


如何知道某个点在CTreeCtrl上的位置

CTreeCtrl::HitTest

HTREEITEM HitTest( CPoint pt, UINT* pFlags );
  HTREEITEM HitTest( TVHITTESTINFO* pHitTestInfo );

返回值:

  返回位于指定点的tree view项的句柄,如果没有项位于该点,则返回NULL。
参数:

 

pt in  要测试的点的客户坐标。
pFlags

out  指向一个用来接收有关点击测试的信息的整数的指针。它可以是说明部分中列出的flags成员值中的一个或多个。

其中flags测试结果可以是如下值:

      TVHT_ABOVE 在客户区域上面

  TVHT_BELOW 在客户区域下面

  TVHT_NOWHERE 在客户区域中并在最后一项下面

  TVHT_ONITEM 在与树项关联的位图或标签内

  TVHT_ONITEMBUTTON 在与树项关联的按钮上

  TVHT_ONITEMICON 在与树项关联的位图上

  TVHT_ONITEMINDENT 在与树项关联的联线上

  TVHT_ONITEMLABEL 在与树项关联的标签上

  TVHT_ONITEMRIGHT 在树项的右侧区域中

  TVHT_ONITEMSTATEICON 在用户定义的状态图标上

  TVHT_TOLEFT 在客户区域的左侧

  TVHT_TORIGHT 在客户区域的右侧

pHitTestInfo

in/out 一个包含点击测试的位置并接收测试结果的信息的TVHITTESTINFO结构的地址。

typedef struct _TVHITTESTINFO {
  POINT pt;
  UINT flags;
  HTREEITEM hItem;
} TVHITTESTINFO, FAR* LPTVHITTESTINFO;

 


说明:
此成员函数用来确定相对于一个tree view控件的客户区的指定点的定位。
当调用这个函数时,pt参数指定要测试的点的坐标。此函数返回位于指定点的项的句柄,或者如果没有项位于该点则返回NULL。另外,pFlags参数包含了指明指定点的定位的值。

 

 

 

关于动态提供结点所显示的字符

   首先你在添加结点时需要指明lpszItem参数为:LPSTR_TEXTCALLBACK。在控件显示该结点时会通过发送TVN_GETDISPINFO来取得所需要的字符,在处理该消息时先将参数pNMHDR转换为LPNMTVDISPINFO,然后填充其中item.pszText。但是我们通过什么来知道该结点所对应的信息呢,我的做法是在添加结点后设置其lParam参数,然后在提供信息时利用该参数来查找所对应的信息。下面的代码说明了这种方法: 
char szOut[8][3]={ "No.1 ", "No.2 ", "No.3 "};
//添加结点
HTREEITEM hItem = m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 0 );
hItem = m_tree.InsertItem(LPSTR_TEXTCALLBACK,...)
m_tree.SetItemData(hItem, 1 );
//处理消息
void CParentWnd::OnGetDispInfoTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
pTVDI-> item.pszText=szOut[pTVDI-> item.lParam];//通过lParam得到需要显示的字符在数组中的位置
*pResult = 0;
}


关于编辑结点的显示字符

首先需要设置树形控件的TVS_EDITLABELS风格,在开始编辑时该控件将会发送TVN_BEGINLABELEDIT,你可以通过在处理函数中返回TRUE来取消接下来的编辑,在编辑完成后会发送TVN_ENDLABELEDIT,在处理该消息时需要将参数pNMHDR转换为LPNMTVDISPINFO,然后通过其中的item.pszText得到编辑后的字符,并重置显示字符。如果编辑在中途中取消该变量为NULL。下面的代码说明如何处理这些消息: 

//处理消息 TVN_BEGINLABELEDIT
void CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
if(pTVDI-> item.lParam==0);//判断是否取消该操作
*pResult = 1;
else
*pResult = 0;
}
//处理消息 TVN_BEGINLABELEDIT
void CParentWnd::OnBeginEditTree(NMHDR* pNMHDR, LRESULT* pResult)
{
TV_DISPINFO* pTVDI = (TV_DISPINFO*)pNMHDR;
if(pTVDI-> item.pszText==NULL);//判断是否已经取消取消编辑
m_tree.SetItemText(pTVDI-> item.hItem,pTVDI-> pszText);//重置显示字符
*pResult = 0;
}

上面讲述的方法所进行的消息映射必须在父窗口中进行(同样WM_NOTIFY的所有消息都需要在父窗口中处理)。

 

 

关于修改树控件的背景位图

【材料整理】VC 树形控件 例子及相关知识_第1张图片

     对于Visual C++ MFC提供的标准树型控件CTreeCtrl来说,并不支持背景位图,所以如果需要实现背景位图就需要先让其在内存CDC对象上对TREEVIEW缺省绘图,然后在选择背景位图,与缺省位图合成,即采用贴图的方式,把标准的TREEVIEW窗口贴在底图上。这个操作在内存中完成。同时为了避免闪烁,必须重载OnItemexpanding()和OnItemexpanded()这两个函数。SetRedraw函数主要保证其不要在子节点弹出时重画,而是在子节点已经扩展后重画。为此,例程中定义了一个CTreeCtrl类的子类CmyTreeCtrl,并重载了以下几个成员函数:

BOOL CMyTreeCtrl::SetBKImage(LPCTSTR LpszResource)
void CMyTreeCtrl::OnPaint()
void CMyTreeCtrl::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
void CMyTreeCtrl::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
BOOL CMyTreeCtrl::OnEraseBkgnd(CDC* pDC)

 

 

 

 

 

我的实践代码:

MFC:

关于变量

在资源文件的主对话框上添加一个CTreeCtrl控件,选中此控件点击右键->CalassWizard->Member Variables 在这项中双击CTreeCtrl控件的ID,关联这个控件与一个CTreeCtrl变量(eg m_TreeCtrl)

关于属性设置:

增加 TreeCtrl 的 TVS_HASBUTTONS,TVS_HASLINES、TVS_LINESATROOT Style,代码如下:

    DWORD dwStyle = GetWindowLong(m_TreeCtrl.m_hWnd,GWL_STYLE);
    dwStyle |= TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT;
    SetWindowLong(m_TreeCtrl.m_hWnd,GWL_STYLE,dwStyle);

如何插入一个节点

HTREEITEM hRoot,hItem,hItem1,hItem2,hSubItem,hSubItem1;
hRoot = m_TreeCtrl.InsertItem("我的电脑");//并不是不是真正意义上的根节点,只是在视觉效果上看起来是
hItem = m_TreeCtrl.InsertItem( "Parent1 ",hRoot);
hSubItem = m_TreeCtrl.InsertItem("child1",hItem);
hSubItem1 = m_TreeCtrl.InsertItem("child2",hItem,hSubItem);

hItem1 = m_TreeCtrl.InsertItem( "Parent2 ",hRoot,hItem);
hItem2 = m_TreeCtrl.InsertItem( "Parent3 ",hRoot,hItem1);

效果图:

【材料整理】VC 树形控件 例子及相关知识_第2张图片

现在我想往child1和child2前加上图标:

首先,构造出来ImageList :

CImageList* imageList=new CImageList();
imageList->Create(19, 19, ILC_COLOR24|ILC_MASK, 20, 1);

//参数意义:参看:http://blog.sina.com.cn/s/blog_4b3c1f950100b0eh.html
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,"D:\Project\TEMP\1.bmp",IMAGE_BITMAP,

19,19,LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE);
CBitmap* m_bitmap = new CBitmap();
m_bitmap->Attach(hBitmap);
imageList->Add(m_bitmap,RGB(0, 0, 0));//参数意义,下面有解释

然后,把ImageList和TreeCtrl关联起来:

m_TreeCtrl.SetImageList(imageList,TVSIL_NORMAL);

注:这个关联必须在m_TreeCtrl插入节点之前。

然后,在插入子节点时这样:

hSubItem = m_TreeCtrl.InsertItem("child1",0,1,hItem);

//添加节点 "child1",未选中时图标为imageList的第0个,选中后图标为imageList的第1个.

效果图:

【材料整理】VC 树形控件 例子及相关知识_第3张图片

?????怎么会是这样????怎么全部都加上了图标??

待解答.....

?????有什么方法能在子节点的位置上不是只是一个字符串,而是插入一个其他的控件呢????

待解答.....

 

 

GetWindowLong

 
函数功能:该函数获得有关指定窗口的信息,函数也获得在额外窗口内存中指定偏移位地址的32位度整型值。 
函数原型:LONG GetWindowLong(HWND hWnd,int nlndex);   
参数:  
    hWnd: 窗口句柄及间接给出的窗口所属的窗口类。  
    nlndex:指定要检索的基于0的偏移量。有效值的范围从0到窗口额外内存空间的字节数,减去4。例如,若指定了12位或多于12位的窗体类的额外存储空间,则应设为第三个32位整数的索引位8(12- 4=8)。要获得任意其他值,
    指定下列值之一:  
    GWL_EXSTYLE= (-20) 扩展窗口样式   GWL_STYLE=(-16) 窗口样式   
    GWL_WNDPROC= (-4) 该窗口的窗口函数的地址   GWL_HINSTANCE= (-6) 拥有窗口的实例的句柄  
    GWL_HWNDPARENT= (-8) 该窗口之父的句柄。不要用SetWindowWord来改变这个值   
    GWL_ID= (-12) 对话框中一个子窗口的标识符  GWL_USERDATA = (-21) 含义由应用程序规定    DWL_DLGPROC = 4 这个窗口的对话框函数地址  
    DWL_MSGRESULT = 0 在对话框函数中处理的一条消息返回的值   DWL_USER = 8 含义由应用程序规定 
返回值:
    如果函数成功,返回值是所需的32位值;如果函数失败,返回值是0。若想获得更多错误信息请调用 GetLastError函数。

 

SetWindowLong

 
函数功能:SetWindowLong该函数改变指定窗口的属性.函数也将指定的一个32位值设置在窗口的额外存储空间的指定偏移位置。
函数原型:LONG SetWindowLong(HWND hWnd,int nlndex,LONG dwNewLong);
参数:
   hWnd: 窗口句柄及间接给出的窗口所属的类。   
   nlndex:指定将设定的大于等于0的偏移值。 有效值的 范围从0到额外类的存储空间的字节数-4:例如若指定了12位或多于12位的额外类存储空间,则应设为第三个32位整数的索引位8。
   要设置其他任何值,可以指定下面值之一:  
     GWL_EXSTYLE:设定一个新的扩展 风格。GWL_STYLE:设定一个新的窗口风格。  
     GWL_WNDPROC:为窗口过程设定一个新的 地址。GWL_ID:设置一个新的窗口标识符。   
     GWL_HINSTANCE:设置一个新的 应用程序实例句柄。   
     GWL_USERDATA:设置与 窗口有关的32位值。每一个窗口均有一个由创建该窗口的应用程序使用的32位值。  当hWnd参数标识了一个 对话框时,也可使用下列值:   
     DWL_DLGPROC: 设置对话框过程的新地址。   
     DWL_MSGRESULT:设置在对话框过程中处理的消息的返回值。 
     DWL_USER:设置的应用程序私有的新的额外信息,例如一个句柄或指针。   
   dwNewLong:指定的替换值。  
返回值:
  如果函数成功,返回值是指定的32位整数的原来的值。如果函数失败,返回值为0。若想获得更多错误信息,请调用GetLastError函数。
备注: 如果由hWnd参数指定的窗口与调用线程不属于同一进程,将导致SetWindowLong函数失败。
 
 
CImageList::Add
int Add( CBitmap* pbmImage, CBitmap* pbmMask );
int Add( CBitmap* pbmImage, COLORREF crMask );
int Add( HICON hIcon );

返回值:
如果成功,则为第一个新图象的基于零的索引,否则为-1。

参数:
pbmImage 指向包含一个或多个图象的位图的指针。图象数由位图宽推断。
pbmMask 指向包含掩码的位图的指针。如果无掩码与图象列表一起使用,则此参数被忽略。
crMask 生成掩码的颜色。指定位图中的此颜色的每个像素被改为黑色,掩码中的相应位数被设置为1。
hIcon 包含新图象的位图和掩码的图标的句柄。

说明:
调用此函数来添加一个或多个图象或图标到图象列表中。
 
什么是掩码图??
在ImageList.Create时如果选择ILC_MASK(既使用掩膜)。如果包含这个值,那么当前ImageList使用2个位图,指定一个单色位图,将其做为掩膜,掩膜是用来实现透明的,就是在显示的时候,会将这个单色位图与图片与PDC做一系列的“位或”“位与”等操作,最终实现透明。从单色位图的设置角度来看的话,如果单色位图“按位异或”图片得到的像素点颜色值为黑色,那么这个像素点就按透明处理。
掩码图就是是指的这一幅单色位图。

 

 

遍历例程:

以下是采用递归完成的遍历树的函数: 
遍历树  
//hitem:待遍历树的根节点

void TreeVisit(HTREEITEM hItem) 
{   
  AfxMessageBox(GetItemText(hItem));  
  if(ItemHasChildren(hItem))  
  { 
   HTREEITEM hChildItem = GetChildItem(hItem);  
   while(hChildItem!=NULL)  
   {  
       TreeVisit(hChildItem); //递归遍历孩子节点  
     hChildItem = GetNextItem(hChildItem, TVGN_NEXT);  
   }  
  }  
}  

 
如何根据名称查找树中的某个节点(必须是节点名称是唯一的)
//item:待遍历树的根节点,strtext:待查找节点名称
HTREEITEM finditem(HTREEITEM item, CString strtext)  

{   
     HTREEITEM hfind;   
     //空树,直接返回NULL
     if(item == NULL)   
          return NULL;   
     //遍历查找
    while(item!=NULL)   
    {   
         //当前节点即所需查找节点
         if(GetItemText(item) == strtext)   
            return item;   

         //查找当前节点的子节点
         if(ItemHasChildren(item))   
        {   
             item = GetChildItem(item);  
             //递归调用查找子节点下节点
             hfind = finditem(item,strtext);   
             if(hfind)   
            {   
                  return hfind;   
            }else //子节点中未发现所需节点,继续查找兄弟节点
                 item = GetNextSiblingItem(GetParentItem(item));   
       }   
       else{ //若无子节点,继续查找兄弟节点
       

你可能感兴趣的:(windows编程)