日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

演练VC中的COMMON一族(转贴)之一

發(fā)布時(shí)間:2024/1/18 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 演练VC中的COMMON一族(转贴)之一 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

聲明:由于在CSDN論壇看到不少VC新手問及VC控件的使用。本人手頭正好有一份以前下載到的一份資料,講述的比較詳細(xì)。所以發(fā)出來和大家共享。但由于時(shí)間久遠(yuǎn),已不及得下載的地址了。所以只能以收藏方式發(fā)表。下面有原作者的單位和姓名。在此表示歉意!

演練VC中的COMMON一族
遼寧省鐵嶺市委辦公室(112000)宋立波
??? 1.表頭控制???????? Header Control?
??? 2.圖像列表控制???? Image List
??? 3.列表控制和視???? List Control&List View
??? 4.樹控制和視?????? Tree Control&Tree View
??? 5.標(biāo)簽控制和視???? Tab Control&Tab View
??? 6.工具條控制?????? Toolbar Control
??? 7.進(jìn)度條控制?????? Progress Control
??? 8.滑動(dòng)條控制????? Slider Control
??? 9.旋轉(zhuǎn)按鈕控制??? Spin Button Control
??? 10.狀態(tài)條控制????? Status Bar Control
其中,絕大部分通用控制在MFC類庫(kù)中都存在兩種封裝形式,即控制類和視類,控制類主要是供直接使用控制而提供的,而視類則是通過間接使用控制而提供的,視類可以更好地把控制類集成到MFC結(jié)構(gòu)中,并且使用視類可以利用引用直接對(duì)嵌套在其中的控制進(jìn)行各種操作。兩者在使用方法上沒有太大區(qū)別,就拿列表控制類和視類來說,當(dāng)創(chuàng)建列表視后可通過CListCtrl&? ctrlList =? GetListCtrl()成員函數(shù)取得視類引用ctrlList之后,就可以利用列表視的視函數(shù)對(duì)視進(jìn)行各項(xiàng)操作(ctrlList.Add等)。

第1章 演練CHeadCtrl
??? 表頭控制(CHeaderCtrl)通常應(yīng)用在窗口中的文本或數(shù)據(jù)的列表之上。一般為數(shù)據(jù)列的標(biāo)題,可以包括多個(gè)部分,用戶可以拖動(dòng)每個(gè)部分并可以控制每列的寬度。表頭控制類提供了普通表頭控制的基本方法,只有在WINDOWS95以后版本系統(tǒng)中才提供,其方法包含在afxcmn.h文件中,一般與標(biāo)簽控制(CTabCtrl)和列表控制(CListCtrl)組合使用。
1.1 表頭控制的對(duì)象結(jié)構(gòu)
1.1.1 表頭控制對(duì)象的建立方法
??? CHeaderCtrl &cheaderCtrl 建立表頭控制對(duì)象
??? Create???????????????????? 建立表頭并綁定對(duì)象
??? CHeaderCtrl::Create的格式如下:BOOL Create( DWORD dwStyle, const RECT&
??? rect, CWnd* pParentWnd, UINT nID );
??? 其返回值非零時(shí)初始化成功,否則失敗。
??? 參數(shù)dwStyle用來確定表頭控制類型;rect用來確定表頭控制的大小和位置;ParentWnd用來確定表頭控制的父窗口;nID用來表示表頭控制的標(biāo)志。
??? 表頭控制風(fēng)格包括:
HDS_BUTTONS???? 表示表頭控制外觀類似按鈕;
HDS_HORZ??????? 表示表頭控制為水平排列;
??? HDS_VERT??????? 表示表頭控制為垂直排列;
??? HDS_HIDDEN????? 表示表頭控制為隱藏模式。
它也可以使用普通類控制風(fēng)格,包括:
??? CCS_BOTTOM????? 設(shè)置控制位置在父窗口的底部并與父窗口同樣寬度;
??? CCS_NODIVIDER?? 在控制頂部形成兩個(gè)像素的高亮區(qū);
??? CCS_NOHILITE??? 在控制頂部形成一個(gè)像素的高亮區(qū);
??? CCS_NOMOVEY???? 在響應(yīng)WM_SIZE消息時(shí)重置大小并水平排列;
??? CCS_NOPARENTALIGN? 使控制自動(dòng)靠近父窗口的頂部或底部;
??? CCS_NORESIZE??? 設(shè)置初始大小或新值時(shí)使控制使用默認(rèn)寬度和高度;
??? CCS_TOP???????? 設(shè)置在父窗口客戶區(qū)域的頂部并與父窗口同樣寬度;
??? 同樣表頭控制也可以使用窗口控制風(fēng)格,包括:
??? WS_CHILD??????? 建立一個(gè)子窗口,不能用于WS_POPUP窗口類型;
??? WS_VISIBLE????? 建立一個(gè)初始時(shí)不可見的窗口;
??? WS_DISABLED???? 建立一個(gè)初始時(shí)無效的窗口;
??? WS_GROUP??????? 確定可用光標(biāo)移動(dòng)的控制群組;
??? WS_TABSTOP????? 確定可用TAB控制移動(dòng)站點(diǎn);
??? 表頭控制一般分為兩個(gè)步驟,首先確定表頭控制的數(shù)據(jù)結(jié)構(gòu),然后建立表頭控制并綁定對(duì)象。
1.1.2 表頭控制的屬性
??? 表頭控制的屬性包括取得表頭控制中項(xiàng)目的數(shù)量GetItemCount、取得表頭控制中某一項(xiàng)目的內(nèi)容GetItem和設(shè)置表頭控制中某一項(xiàng)目的內(nèi)容SetItem。
1.1.3 表頭控制的操作方法
??? 表頭控制的操作方法包括向表頭控制中插入一個(gè)新項(xiàng)目InsertItem、從表頭控制中刪除一個(gè)項(xiàng)目DeleteItem和繪制表頭中給定的項(xiàng)目DrawItem等。
1.2 表頭控制的數(shù)據(jù)結(jié)構(gòu)
??? 在使用表頭控制時(shí),首先必須建立一個(gè)數(shù)據(jù)結(jié)構(gòu)HD_ITEM,其結(jié)構(gòu)定義如下:
??? typedef struct _HD_ITEM
??? { UINT??? mask;??????? file://結(jié)構(gòu)成員有效控制位
????? int???? cxy;???????? file://表頭項(xiàng)目的寬度
????? LPSTR?? pszText;???? file://表頭項(xiàng)目?jī)?nèi)容
????? HBITMAP hbm;???????? file://表頭項(xiàng)目的位置句柄
????? int???? cchTextMax;? file://表頭內(nèi)容字符串長(zhǎng)度
????? int???? fmt;???????? file://表頭項(xiàng)目的格式
????? LPARAM? lParam;????? file://應(yīng)用程序定義的32位數(shù)據(jù)
??? } HD_ITEM;
??? 屏蔽控制位說明了數(shù)據(jù)結(jié)構(gòu)成員中包含的有效數(shù)據(jù),可以是下面標(biāo)志的組合:
??? HDI_BITMAP??????? hbm成員有效
??? HDI_FORMAT??????? fmt 成員有效
??? HDI_LPARAM??????? lParam成員有效
??? HDI_TEXT????????? pszText 和cchTextMax 成員有效
??? HDI_WIDTH???????? cxy 成員有效并確定項(xiàng)目寬度值
??? 格式標(biāo)志位fmt可以是以下標(biāo)志的組合:
??? HDF_CENTER??????? 表頭項(xiàng)目居中
??? HDF_LEFT????????? 表頭項(xiàng)目左對(duì)齊
??? HDF_RIGHT???????? 表頭項(xiàng)目右對(duì)齊
??? HDF_BITMAP??????? 表頭顯示一個(gè)位圖
??? HDF_OWNERDRAW???? 由主窗口自繪表頭項(xiàng)目
??? HDF_STRING??????? 表頭項(xiàng)目為一個(gè)字符串
1.3 表頭控制的應(yīng)用技巧
??? 由于表頭控制無法單獨(dú)使用,其主要是配合列表控制和標(biāo)簽控制,并多以文字表頭應(yīng)用多見,InsertItem、SetItem和GetItem是常用的方法,如在列表控制時(shí)利用InsertColumn屬性就可以增加一個(gè)表列的文本標(biāo)題,具體用法和技巧見列表控制和標(biāo)簽控制。下面以在列表控制中的增加表列的方法來具體說明:
??? lvcol.pszText="品? 名";//設(shè)置第一列表頭名
??? lvcol.iSubItem=i;????? file://表列序號(hào)
??? lvcol.cx=70;?????????? file://表列寬度
??? m_ListCtrl.InsertColumn(i++,&lvcol);//插入一個(gè)表列
??? lvcol.pszText="數(shù)? 量";//設(shè)置第二列表頭名
??? lvcol.iSubItem=i;
??? lvcol.cx=70;
??? m_ListCtrl.InsertColumn(i++,&lvcol);//插入一個(gè)表列
??? ......//其它代碼


第2章 演練CImageList
??? 圖像列表控制(CImageList)是相同大小圖像的一個(gè)集合,每個(gè)集合中均以0為圖像的索引序號(hào)基數(shù),圖像列表通常由大圖標(biāo)或位圖構(gòu)成,其中包含透明位圖模式。可以利用WINDOWS32位應(yīng)用程序接口函數(shù)API來繪制、建立和刪除圖像,并能實(shí)現(xiàn)增加、刪除、替換和拖動(dòng)圖像等操作。圖像列表控制提供了控制圖像列表的基本方法,這些方法在WINDOWS95及以后版本才能實(shí)現(xiàn)。
2.1 圖像控制的對(duì)象結(jié)構(gòu)
2.1.1 圖像控制的數(shù)據(jù)成員
??? m_hImageList???????? 連接圖像對(duì)象的控制句柄
2.1.2 圖像控制的建立方法
??? CimageList&imageList建立圖像控制對(duì)象結(jié)構(gòu)
??? Create?????????????? 初始化圖像列表并綁定對(duì)象
??? 圖像控制的建立方法如下:
??? BOOL Create( int cx, int cy, UINT nFlags, int nInitial, int nGrow );
??? BOOL Create( UINT nBitmapID, int cx, int nGrow, COLORREF crMask );
??? BOOL Create( LPCTSTR lpszBitmapID, int cx, int nGrow, COLORREF crMask );
BOOL Create( CImageList& imagelist1, int nImage1, CImageList& imagelist2
? ,int? nImage2,int dx, int dy );
??? 其中各項(xiàng)參數(shù)的含義為:cx定義圖像的寬度,單位為象素;cy定義圖象的高度,單位為象素;nFlags確定建立圖像列表的類型,可以是以下值的組合:ILC_COLOR、ILC_COLOR4、ILC_COLOR8、ILC_COLOR16、ILC_COLOR24、ILC_COLOR32、ILC_COLORDDB和ILC_MASK;nInitial用來確定圖像列表包含的圖像數(shù)量;nGrow用來確定圖像列表可控制的圖像數(shù)量。
??? NbitmapID??? 用來確定圖像列表聯(lián)系的位圖標(biāo)志值;crMask表示顏色屏蔽位;
??? LpszBitmapID 用來確定包含位圖資源的標(biāo)識(shí)串;
imagelist1??? 指向圖像列表控制對(duì)象的一個(gè)指針;nImage1圖像列表1中包含的圖像數(shù)??? 量;imagelist2指向圖像列表控制對(duì)象的一個(gè)指針;nImage2圖像列表2中包含的圖像數(shù)量;dx表示以象素為單位的圖像寬度;dy表示以象素為單位的圖像高度。
同樣,圖像控制的建立也包括兩個(gè)步驟,首先建立圖像列表結(jié)構(gòu),然后建立圖像列表控制。
2.1.3 圖像控制的屬性類
??? 圖像控制的屬性類包括返回m_hImageList.控制句柄GetSafeHandle、取得圖像列表中的圖像數(shù)量GetImageCount、設(shè)置圖像列表的背景顏色SetBkColor、取得圖像列表的背景顏色SetBkColor和取得圖像的有關(guān)信息SetBkColor。
2.1.4 圖像控制的操作方法
??? 圖像控制的操作方法包括將一個(gè)圖像列表綁定到一個(gè)對(duì)象上Attach、將對(duì)象上的圖像列表解除綁定并返回句柄Detach、刪除一個(gè)圖像列表DeleteImageList、將一個(gè)圖像增加到圖像列表中Add和將一個(gè)圖像從圖像列表中刪除Remove等。
2.2 圖像控制的應(yīng)用技巧
??? 對(duì)于圖像控制,同樣不能單獨(dú)使用,必須與列表控制、樹控制和標(biāo)簽控制相互結(jié)合應(yīng)用,下面分別介紹其具體應(yīng)用技巧。
2.2.1 圖像控制在列表控制中的應(yīng)用技巧
2.2.1.1 設(shè)置圖像控制CListCtrl::SetImageList的調(diào)用格式如下:
??? CImageList* SetImageList( CImageList* pImageList, int nImageList );
??? 其返回值是指向前一個(gè)圖像列表控制的一個(gè)指針,如果不存在前一個(gè)圖像列表則為NULL;其中參數(shù)pImageList是指向圖像列表的標(biāo)識(shí),nImageList是圖像列表的類型,可以是如下值:
??? LVSIL_NORMAL???? 用大圖標(biāo)方式進(jìn)行圖像列表;
??? LVSIL_SMALL???? 用小圖標(biāo)方式進(jìn)行圖像列表;
??? LVSIL_STATE???? 以圖像狀態(tài)進(jìn)行圖像列表;
2.2.1.2 取得圖像控制CListCtrl::GetImageList的調(diào)用格式如下:
??? CImageList* GetImageList( int nImageList ) const;
??? 其返回值為指向圖像列表控制的指針,其中nImageList用來確定取得返回值的圖像列表的??? 值,其取值與設(shè)置圖像列表函數(shù)相同。
??? ③圖像控制在列表控制中的應(yīng)用示例
??? CImageList Cil1,Cil2;??????????? file://定義大小圖標(biāo)像列表
??? CVCLISTApp *pApp=(CVCLISTApp *)AfxGetApp();//取得列表控制程序
??? Cil1.Create(32,32,TRUE,2,2);???? file://建立32位圖像控制
??? Cil1.Add(pApp->LoadIcon(IDI_GJ));//增加選中狀態(tài)圖像
??? Cil1.Add(pApp->LoadIcon(IDI_XS));//增加非選中狀態(tài)圖像
??? Cil2.Create(16,16,TRUE,2,2);???? file://建立16位圖像控制
??? Cil2.Add(pApp->LoadIcon(IDI_GJ));//增加選中狀態(tài)圖像
??? Cil2.Add(pApp->LoadIcon(IDI_XS));//增加非選中狀態(tài)圖像
??? m_ListCtrl.SetImageList(&Cil1,LVSIL_NORMAL);//設(shè)置大圖標(biāo)控制
??? m_ListCtrl.SetImageList(&Cil2,LVSIL_SMALL);//設(shè)置小圖標(biāo)控制
2.2.2 圖像控制在樹控制中的應(yīng)用技巧
2.2.2.1 設(shè)置圖像控制CTreeCtrl::SetImageList的調(diào)用格式如下:
??? CImageList* SetImageList( CImageList * pImageList, int nImageListType );
??? 其返回值為指向前前一個(gè)圖像列表的指針,否則為NULL;參數(shù)pImageList為指向圖像列表的標(biāo)識(shí),如果pImageList為NULL則所有的圖像都將從樹控制中被清除;nImageListType為圖像列表設(shè)置的類型,可以是如下值之一:
??? TVSIL_NORMAL?? 設(shè)置正常圖像列表,其中包括選中和非選中兩種圖標(biāo);
??? TVSIL_STATE?? 設(shè)置圖像列表狀態(tài),指用戶自定義狀態(tài);
2.2.2.2 取得圖像控制CTreeCtrl::GetImageList的調(diào)用格式如下:
??? CImageList* GetImageList( UINT nImage );
??? 如果調(diào)用成功則返回圖像列表控制指針,否則為NULL;nImage為取得返回值的圖像列表類型,其取值和取得圖像列表控制完全相同。
2.2.2.3 圖像控制在樹控制中的應(yīng)用示例
??? CImageList Cil1,Cil2;//定義大小圖標(biāo)像列表
??? CVCTREEApp *pApp=(CVCTREEApp *)AfxGetApp();//獲取應(yīng)用程序指針
??? Cil1.Create(16,16,ILC_COLOR,2,2);//建立圖像控制
??? Cil1.Add(pApp->LoadIcon(IDI_PM));//增加選中狀態(tài)圖像
??? Cil1.Add(pApp->LoadIcon(IDI_CJ));//增加非選中狀態(tài)圖像
??? m_TreeCtrl.SetImageList(&Cil1,TVSIL_NORMAL);//設(shè)置圖像控制列表
??? 然后在樹控制的結(jié)構(gòu)定義中進(jìn)行如下設(shè)置:
??? TCItem.item.iImage=0;??????? file://設(shè)置未選中圖像索引號(hào)
??? TCItem.item.iSelectedImage=1;//設(shè)置選中時(shí)圖像引號(hào)
2.2.3 圖像控制在標(biāo)2.2.4 簽控制中的應(yīng)用技巧
2.2.4.1 設(shè)置圖像控制CTabCtrl::SetImageList的調(diào)用格式
??? CImageList * SetImageList( CImageList * pImageList );
??? 其返回值為指向前一個(gè)圖像列表的指針,如果不存在前一個(gè)圖像列表則為NULL;pImageList為標(biāo)識(shí)TAB控制的圖像列表指針。
2.2.4.2 取得圖像控制CTabCtrl::GetImageList的調(diào)用格式
??? HIMAGELIST GetImageList() const;
??? 其返回值為指向TAB控制的圖像列表指針,如果調(diào)用不成功則為NULL。
??? 其應(yīng)用技巧較前兩種更加簡(jiǎn)單,這里不再贅述。


第3章 演練CList
3.1 列表控制的主要功能
??? 列表控制和視(List Control&View)主要用來以各種方式顯示一組數(shù)據(jù)記錄供用戶進(jìn)行各種操作,Windows98/95中資源管理器中的“查看”標(biāo)簽下的“大圖標(biāo)|小圖標(biāo)|列表|詳細(xì)資源”就是一個(gè)非常好的典型應(yīng)用。列表中的記錄可以包括多個(gè)數(shù)據(jù)項(xiàng),也可以包括表示數(shù)據(jù)內(nèi)容的大小圖標(biāo),用來表示數(shù)據(jù)記錄的各種屬性。
??? 列表控制提供了對(duì)Windows列表功能操作的基本方法,而使用列表視的視函數(shù)可以對(duì)列表視進(jìn)行各種操作,通過調(diào)用視成員GetListCtrl獲取嵌在列表視內(nèi)列表控制的引用(GetListCtrl&? ctrlList? =? GetListCtrl()),就可以和列表控制一樣進(jìn)行各種操作。操作一個(gè)列表控制和視的基本方法為:創(chuàng)建列表控制;創(chuàng)建列表控制所需要的圖像列表;向列表控制添加表列和表項(xiàng);對(duì)列表進(jìn)行各種控制,主要包括查找、排序、刪除、顯示方式、排列方式以及各種消息處理功能等;最后撤消列表控制。
??? 對(duì)于一個(gè)列表控制,其最典型最常用的顯示控制方式為:大圖標(biāo)方式(LVS_ICON)、小圖標(biāo)方式(LVS_SMALLICON)、列表顯示方式(LVS_LIST)和詳細(xì)資料(即報(bào)告LVS_REPORT)顯示方式。這可以通過設(shè)置其顯示方式屬性來實(shí)現(xiàn)。要控制列表所在窗口的風(fēng)格,可通過功能函數(shù)GetWindowLong和SetWindowLong來實(shí)現(xiàn),要控制列表圖標(biāo)的對(duì)齊方式,可通過設(shè)置列表窗口的風(fēng)格LVS_ALIGNTOP或LVS_ALIGNLEFT來實(shí)現(xiàn),
3.2 列表控制的對(duì)象結(jié)構(gòu)
3.2.1 列表控制的建立方法
??? CListCtrl&listCtrl? 定義列表對(duì)象的結(jié)構(gòu)
??? Create?????????????? 建立列表控制并綁定對(duì)象
列表控制CListCtrl::Create的調(diào)用格式如下:
??? BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
其中參數(shù)dwStyle用來確定列表控制的風(fēng)格;rect用來確定列表控制的大小和位置;pParentWnd用來確定列表控制的父窗口,通常是一個(gè)對(duì)話框;nID用來確定列表控制的標(biāo)識(shí)。其中列表控制的風(fēng)格可以是下列值的組合:
??? LVS_ALIGNLEFT????? 用來確定表項(xiàng)的大小圖標(biāo)以左對(duì)齊方式顯示;
??? LVS_ALIGNTOP?????? 用來確定表項(xiàng)的大小圖標(biāo)以頂對(duì)齊方式顯示;
??? LVS_AUTOARRANGE??? 用來確定表項(xiàng)的大小圖標(biāo)以自動(dòng)排列方式顯示;
??? LVS_EDITLABELS???? 設(shè)置表項(xiàng)文本可以編輯,父窗口必須設(shè)有LVN_ENDLABELEDIT風(fēng)格;
??? LVS_ICON?????????? 用來確定大圖標(biāo)的顯示方式;
LVS_LIST?????????? 用來確定列表方式顯示;
LVS_NOCOLUMNHEADER 用來確定在詳細(xì)資料方式時(shí)不顯示列表頭;
LVS_NOLABELWRAP??? 用來確定以單行方式顯示圖標(biāo)的文本項(xiàng);
LVS_NOSCROLL?????? 用來屏蔽滾動(dòng)條;
LVS_NOSORTHEADER?? 用來確定列表頭不能用作按鈕功能;
LVS_OWNERDRAWFIXED 在詳細(xì)列表方式時(shí)允許自繪窗口;
LVS_REPORT???????? 用來確定以詳細(xì)資料即報(bào)告方式顯示;
LVS_SHAREIMAGELISTS用來確定共享圖像列表方式;
LVS_SHOWSELALWAYS? 用來確定一直顯示被選中表項(xiàng)方式;
LVS_SINGLESEL????? 用來確定在某一時(shí)刻只能有一項(xiàng)被選中;
LVS_SMALLICON????? 用來確定小圖標(biāo)顯示方式;
LVS_SORTASCENDING? 用來確定表項(xiàng)排序時(shí)是基于表項(xiàng)文本的升序方式;
LVS_SORTDESCENDING 用來確定表項(xiàng)排序時(shí)是基于表項(xiàng)文本的降序方式;
3.2.2 列表控制的屬性類
列表控制的屬性類包括取得列表控制的背景色GetBkColor、設(shè)置列表控制的背景色SetBkColor、取得列表控制的圖像列表GetImageList、設(shè)置列表控制的圖像列表SetImageList、取得列表項(xiàng)數(shù)目GetItemCount、取得列表控制的屬性GetItem、取得與表項(xiàng)相關(guān)的數(shù)據(jù)GetItemData、設(shè)置表項(xiàng)的屬性SetItem、設(shè)置與表項(xiàng)相關(guān)的數(shù)值SetItemData、取得相關(guān)聯(lián)的下一個(gè)表項(xiàng)GetNextItem、設(shè)置列表控制的文本顏色SetTextColor、取得列表控制的文本背景顏色GetTextBkColor、設(shè)置表項(xiàng)的最大數(shù)目SetItemCount和取得被選中表項(xiàng)的數(shù)目GetSelectedCount等。
3.2.3 列表控制的操作方法
??? 列表控制的操作方法包括插入一個(gè)新的表項(xiàng)InsertItem、刪除一個(gè)表項(xiàng)DeleteItem、排序表項(xiàng)SortItems、測(cè)試列表的位置HitTest、重繪表項(xiàng)RedrawItems、插入一個(gè)表列InsertColumn、刪除一個(gè)表列DeleteColumn、編輯一個(gè)表項(xiàng)文本EditLabel和重繪一個(gè)表項(xiàng)DrawItem等。
3.3 列表控制的數(shù)據(jù)結(jié)構(gòu)
列表控制中包含兩個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu)LV_ITEM和LV_COLUMN。LV_ITEM用于定義列表控制的一個(gè)表項(xiàng),LV_COLUMN用于定義列表控制的一個(gè)表列,其定義格式分別為:
typedef struct _LV_ITEM {
?? UINT?? mask;?????? file://結(jié)構(gòu)成員屏蔽位
??? ?int??? iItem;????? file://表項(xiàng)索引號(hào)
int??? iSubItem;?? file://子表項(xiàng)索引號(hào)
UINT?? state;????? file://表項(xiàng)狀態(tài)
UINT?? stateMask;? file://狀態(tài)有效性屏蔽位
LPTSTR? pszText;?? file://表項(xiàng)名文本
int??? cchTextMax; file://表項(xiàng)名最大長(zhǎng)度
int??? iImage;???? // 表項(xiàng)圖標(biāo)的索引號(hào)
LPARAM lParam;???? // 與表項(xiàng)相關(guān)的32位數(shù)
} LV_ITEM;
??? typedef struct _LV_COLUMN {
??????? UINT mask;???????? file://結(jié)構(gòu)成員有效性屏蔽位
??????? int fmt;?????????? file://表列對(duì)齊方式
??????? int cx;??????????? file://表列的象素寬度
??????? LPTSTR pszText;??? file://表列的表頭名
??????? int cchTextMax;??? file://表列名的文本長(zhǎng)度
??????? int iSubItem;????? file://與表列關(guān)聯(lián)的子表項(xiàng)索引號(hào)
} LV_COLUMN;
其中fmt可以取如下值:
LVCFMT_CENTER??????? 表列居中對(duì)齊
LVCFMT_LEFT????????? 表列左對(duì)齊
3.4 列表控制的應(yīng)用技巧示例
??? 本文給出具體實(shí)例演示列表控制及前面的表頭控制和圖像列表的應(yīng)用技巧。步驟如下:
1、通過“FILE->NEW->PROJECTS->MFC AppWizard(EXE)”建立名為VCLIST的工程,在建立過程中選擇基于對(duì)話框(Dialog based)的應(yīng)用;將對(duì)話框中的默認(rèn)控件刪除,并將所有對(duì)話框?qū)傩灾械腖anguage域設(shè)置為Chinese(P.R.C.),以使應(yīng)用程序支持中文;
建立兩個(gè)圖標(biāo)IDI_GJ和IDI_XS,用來表示圖標(biāo)的選中和非選中狀態(tài),對(duì)于每個(gè)圖標(biāo)都應(yīng)建立32X32和16X16兩種大小,以保證程序的需要;
??? 3、在對(duì)話框窗口中設(shè)計(jì)組合框(Group Box),組合框中設(shè)置四個(gè)無線按鈕(Radio)“大圖標(biāo)|小圖標(biāo)|列表|資料”,同時(shí)設(shè)置排序、刪除和關(guān)閉三個(gè)控制按鈕(Button),并在對(duì)話框中設(shè)置大小合適的列表控制(List Ctrl),其對(duì)應(yīng)標(biāo)識(shí)分別如下:
??? 控制名稱??????? 標(biāo)題名稱??????????????? 標(biāo)識(shí)符號(hào)
??? 列表控制???????????????? ??????????? IDC_LISTCTRL
??? 組合框????????? 方式???? IDC_STATIC
??? 無線按鈕??????? 大圖標(biāo)??????????? IDC_STDICON
??????????????????? 小圖標(biāo)? ??????????? IDC_SMLICON
? ?????????????? 列? 表?????????????? IDC_LIST
??????????????????? 資? 料?????????????? IDC_REPORT
??? 按鈕??????????? 排? 序??????? IDC_SORT
??????????????????? 刪? 除???????????? ? IDC_DEL
??????????????????? 關(guān)? 閉?????????????? IDOK
??? 4、在設(shè)置無線按鈕時(shí),需要注意的是只有大圖標(biāo)的Group屬性為選中狀態(tài),而其它無線按鈕的狀態(tài)均為默認(rèn)值。
??? 5、選中列表控制控件,選擇“VIEW->ClassWizard->Memory Variables”,并利用IDC_? LISTCTRL引入成員變量,其變量類型為:
??? 變量名??????????? 種類??????????? 變量類型
??? m_ListCtrl??????? Control???????? ClistCtrl
??? 同時(shí)利用“MESSAGES MAP”為各無線按鈕和命令按鈕增加控制功能。
??? 6、然后在包含文件和代碼文件中分別加入如下代碼:
??? (1)在VCLISTDlg.h中增加數(shù)據(jù)結(jié)構(gòu)和定義
??? typedef struct tagSPS {?file://定義結(jié)構(gòu)
?? char szPm[10];?? ??file://品名
?? int? Lx;???????? ??file://0-GJ 1-XS
?? char szSl[10];?? ??file://數(shù)量
?? char szDj[10];?? ??file://單價(jià)
?? char szJe[10];?? ??file://金額
??? } SPS;
??? int CALLBACK CompareFunc(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort);
?? (2)在VCLISTDlg.CPP中的起始處增加初始化數(shù)據(jù)和程序定義
??? file://在文件開始處增加數(shù)據(jù)結(jié)構(gòu)初始化
??? SPS Sps[]={//信息
??????? {"紅梅",0,"1000","30","30000"},
??????? {"黃梅",0,"1000","29","29000"},
??????? {"綠梅",0,"1000","28","28000"},
??????? {"青梅",0,"1000","27","27000"},
??????? {"白梅",0,"1000","31","31000"},
??????? {"紅梅",1,"1000","30","30000"},
??????? {"黃梅",1,"1000","29","29000"},
??????? {"綠梅",1,"1000","28","28000"},
??????? {"青梅",1,"1000","27","27000"},
????? ?{"白梅",1,"1000","31","31000"}};
??? CImageList Cil1,Cil2;//大小圖像列表
??? (3)在程序初始化處增加表頭、圖像和列表控制建立代碼
??? BOOL CVCLISTDlg::OnInitDialog()
??? {CDialog::OnInitDialog();
??? file://......//其它代碼
??? // TODO: Add extra initialization here此處增加代碼
??? LV_ITEM lvitem;
??? LV_COLUMN lvcol;
??? int i,iPos,iItemNum;
??? CVCLISTApp *pApp=(CVCLISTApp *)AfxGetApp();//創(chuàng)建圖象列表
??? Cil1.Create(32,32,TRUE,2,2);
??? Cil1.Add(pApp->LoadIcon(IDI_GJ));
??? Cil1.Add(pApp->LoadIcon(IDI_XS));
??? Cil2.Create(16,16,TRUE,2,2);
??? Cil2.Add(pApp->LoadIcon(IDI_GJ));
??? Cil2.Add(pApp->LoadIcon(IDI_XS));//設(shè)置圖象列表
??? m_ListCtrl.SetImageList(&Cil1,LVSIL_NORMAL);
??? m_ListCtrl.SetImageList(&Cil2,LVSIL_SMALL);//向列表控制中添加表列
??? lvcol.mask=LVCF_FMT|LVCF_SUBITEM|LVCF_TEXT|LVCF_WIDTH;
??? lvcol.fmt=LVCFMT_CENTER;//居中
??? i=0;
??? lvcol.pszText="品? 名";
??? lvcol.iSubItem=i;
??? lvcol.cx=70;
??? m_ListCtrl.InsertColumn(i++,&lvcol);
??? lvcol.pszText="數(shù)? 量";
??? lvcol.iSubItem=i;
??? lvcol.cx=70;
??? m_ListCtrl.InsertColumn(i++,&lvcol);
??? lvcol.pszText="單? 價(jià)";
??? lvcol.iSubItem=i;
??? lvcol.cx=70;
??? m_ListCtrl.InsertColumn(i++,&lvcol);
??? lvcol.pszText="金? 額";
??? lvcol.iSubItem=i;
??? lvcol.cx=70;
??? m_ListCtrl.InsertColumn(i++,&lvcol);
??? file://向列表控制中添加表項(xiàng)
??? iItemNum=sizeof(Sps)/sizeof(SPS);
??? for(i=0;i<iItemNum;i++){
??lvitem.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_PARAM;
??lvitem.iItem=i;
??lvitem.iSubItem=0;
??lvitem.pszText=Sps[i].szPm;
??lvitem.iImage=Sps[i].Lx;
??lvitem.lParam=i;
??iPos=m_ListCtrl.InsertItem(&lvitem);//返回表項(xiàng)插入后的索引號(hào)
??lvitem.mask=LVIF_TEXT;
??lvitem.iItem=iPos;
??lvitem.iSubItem=1;
??lvitem.pszText=Sps[i].szSl;
??m_ListCtrl.SetItem(&lvitem);
??lvitem.iSubItem=2;
??lvitem.pszText=Sps[i].szDj;
??m_ListCtrl.SetItem(&lvitem);
??lvitem.iSubItem=3;
??lvitem.pszText=Sps[i].szJe;
??m_ListCtrl.SetItem(&lvitem);
??? }
??? CheckRadioButton(IDC_STDICON,IDC_REPORT,IDC_STDICON);
??? return TRUE;? // return TRUE? unless you set the focus to a control
??? }
??? (4)完善列表顯示方式代碼
??? 在利用Classwizard類向?qū)?chuàng)建各功能按鈕顯示功能函數(shù)之后,必須依次完善這些功能函數(shù)的代碼,這些功能函數(shù)如下:
void CVCLISTDlg::OnStdicon()//設(shè)置大圖標(biāo)顯示方式
{?// TODO: Add your control notification handler code here
?LONG lStyle;
?lStyle=GetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE);//獲取當(dāng)前窗口類型
?lStyle&=~LVS_TYPEMASK;?file://清除顯示方式位
?lStyle|=LVS_ICON;?????? file://設(shè)置顯示方式
?SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//設(shè)置窗口類型
}
void CVCLISTDlg::OnSmlicon() file://設(shè)置小圖標(biāo)顯示方式
{?// TODO: Add your control notification handler code here
?LONG lStyle;
?lStyle=GetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE);//獲取當(dāng)前窗口類型
?lStyle&=~LVS_TYPEMASK;?file://清除顯示方式位
?lStyle|=LVS_SMALLICON;? file://設(shè)置顯示方式
?SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//設(shè)置窗口類型
}
void CVCLISTDlg::OnList() file://設(shè)置列表顯示方式
{?// TODO: Add your control notification handler code here
?LONG lStyle;
?lStyle=GetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE);//獲取當(dāng)前窗口類型
?lStyle&=~LVS_TYPEMASK;?file://清除顯示方式位
?lStyle|=LVS_LIST;?????? file://設(shè)置顯示方式
?SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//設(shè)置窗口類型
}
void CVCLISTDlg::OnReport() file://詳細(xì)資料顯示方式
{?// TODO: Add your control notification handler code here
?LONG lStyle;
?lStyle=GetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE);//獲取當(dāng)前窗口類型
?lStyle&=~LVS_TYPEMASK;?file://清除顯示方式位
?lStyle|=LVS_REPORT;???? file://設(shè)置顯示方式
?SetWindowLong(m_ListCtrl.m_hWnd,GWL_STYLE,lStyle);//設(shè)置窗口類型
}
??? (5)刪除功能的實(shí)現(xiàn)
??? 要實(shí)現(xiàn)刪除功能,必須取得選中表項(xiàng)的數(shù)和表項(xiàng)總數(shù),并且需要從后向前進(jìn)行依次刪除,其原因是每個(gè)表項(xiàng)被刪除后,其后各表項(xiàng)的索引號(hào)均會(huì)發(fā)生遞減變化,如果采取從前向后刪除的方法,就會(huì)造成無法正常刪除選中的表項(xiàng),其功能代碼如下:
void CVCLISTDlg::OnDel() file://刪除按鈕功能
{?// TODO: Add your control notification handler code here
?int i,iState;
?int nItemSelected=m_ListCtrl.GetSelectedCount();//所選表項(xiàng)數(shù)
?int nItemCount=m_ListCtrl.GetItemCount();//表項(xiàng)總數(shù)
?if(nItemSelected<1) return;
?for(i=nItemCount-1;i>=0;i--){
??iState=m_ListCtrl.GetItemState(i,LVIS_SELECTED);
??if(iState!=0) m_ListCtrl.DeleteItem(i);
?}
}
??? (6)排序功能的實(shí)現(xiàn)
??? 列表控制有一個(gè)特殊的功能,當(dāng)以詳細(xì)資料方式顯示時(shí),列表頂部的表頭可以當(dāng)作按鈕來使用,這可以通過列表控制創(chuàng)建時(shí)的風(fēng)格來控制。當(dāng)鼠標(biāo)點(diǎn)擊列表頭名稱時(shí),列表控制就會(huì)向其父窗口發(fā)送一個(gè)LNV_COLUMNCLICK消息,利用類導(dǎo)向中列表控制IDC_LISTCTRL對(duì)應(yīng)的LNV_COLUMNCLICK消息加入相應(yīng)處理函數(shù),就可將表列按照特定順序進(jìn)行排列。其函數(shù)使用方法見程序,其中iSort為排序的表列索引號(hào),(PFNLVCOMPARE)CompareFunc為進(jìn)行具體排序的回調(diào)函數(shù),也就是說,通過鼠標(biāo)點(diǎn)擊表頭實(shí)現(xiàn)的排序過程是由第三方開發(fā)的專用排序函數(shù)來實(shí)現(xiàn)的,排序函數(shù)只是實(shí)現(xiàn)表項(xiàng)的具體比較操作,而整個(gè)排序過程是由SortItemS屬性通過不斷調(diào)用這個(gè)函數(shù)來實(shí)現(xiàn)的。正常的排序過程是升序方式,通過調(diào)換排序函數(shù)中的參數(shù)值,就可實(shí)現(xiàn)降序排列,即將PARAM1與PARAM2調(diào)換位置。這個(gè)回調(diào)函數(shù)的前兩個(gè)參數(shù)為表列中表項(xiàng)的索引號(hào),第三個(gè)參數(shù)為排序的表列索引號(hào)。
void CVCLISTDlg::OnColumnclickListctrl(NMHDR* pNMHDR, LRESULT* pResult)
{?? file://鼠標(biāo)左鍵單擊表頭處理函數(shù)
?NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
?// TODO: Add your control notification handler code here
?static int iSorted=-1;//排列序號(hào)
?if (pNMListView->iSubItem==iSorted) return;
?iSorted=pNMListView->iSubItem;
?m_ListCtrl.SortItems((PFNLVCOMPARE)CompareFunc,iSorted);
?*pResult = 0;
}
??? file://排序時(shí)比較表項(xiàng)的回調(diào)函數(shù)
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2,LPARAM lParamSort)
{?char *text1,*text2;
??? switch (lParamSort){
?case 0L:text1=Sps[lParam1].szPm;
??? text2=Sps[lParam2].szPm;break;
?case 1L:text1=Sps[lParam1].szSl;
??? text2=Sps[lParam2].szSl;break;
?case 2L:text1=Sps[lParam1].szDj;
??? text2=Sps[lParam2].szDj;break;
?case 3L:text1=Sps[lParam1].szJe;
??? text2=Sps[lParam2].szJe;break;
?}
?return (strcmp(text1,text2));//結(jié)果為>0 =0 <0
}
??? 同樣,也可以通過專用按鈕來實(shí)現(xiàn)排序功能,如本文的排序按鈕對(duì)應(yīng)的功能代碼如下:
void CVCLISTDlg::OnSort()
{?// TODO: Add your control notification handler code here
?m_ListCtrl.SortItems((PFNLVCOMPARE)CompareFunc,0);}
??? 7、列表視的演練技巧
在使用列表視時(shí),其方法與列表控制基本相同,只不過列表視是在窗口中來實(shí)現(xiàn)的而列表控制是在對(duì)話框中實(shí)現(xiàn),列表視的各種功能是通過菜單來實(shí)現(xiàn)的而列表控制是通過按鈕等方式來實(shí)現(xiàn)的,列表控制需要在對(duì)話框中創(chuàng)建列表控制控件而列表視直接占據(jù)整個(gè)窗口,在設(shè)計(jì)過程中只要將按鈕和列表控制設(shè)計(jì)過程變?yōu)椴藛卧O(shè)計(jì),并注意在功能增加是在類向?qū)е惺峭ㄟ^菜單命令來操作,同時(shí)在每個(gè)功能函數(shù)前面增加取得列表視引用的命令(?CListCtrl& ListCtrl = GetListCtrl()),而其余數(shù)據(jù)結(jié)構(gòu)和代碼均不需要修改,實(shí)現(xiàn)起來比較容易。
筆者實(shí)現(xiàn)的列表控制和視程序的運(yùn)行結(jié)果如下:
??????????????????? 列表控制演練示例結(jié)果

????????????????? 列表視演練示例結(jié)果


第4章 演練CTree
4.1 樹控制的主要功能
??? 樹控制和視(Tree Control&View)主要用來顯示具有一定層次結(jié)構(gòu)的數(shù)據(jù)項(xiàng),如資源管理器中的磁盤目錄等,以供用戶在其中進(jìn)行各種選擇。樹控制中的每個(gè)數(shù)據(jù)項(xiàng)包括數(shù)據(jù)項(xiàng)名稱的文本字符串和用于表示該數(shù)據(jù)項(xiàng)的圖像,每個(gè)數(shù)據(jù)項(xiàng)下面均可包含各種子項(xiàng),整個(gè)結(jié)構(gòu)就象目錄樹一樣。對(duì)于包含各種子項(xiàng)的數(shù)據(jù)項(xiàng),可通過鼠標(biāo)雙擊來展開或合攏,這可以通過控制樹的不同風(fēng)格來實(shí)現(xiàn)樹控制的不同顯示形態(tài)。這些風(fēng)格主要包括:
??? TVS_HASLINES表示用連線來連接父項(xiàng)和它下面的各個(gè)子項(xiàng),這可以使樹的顯示層次結(jié)構(gòu)更加清晰,但在無父項(xiàng)的各子項(xiàng)之間并沒有連線;
??? TVS_LINESATROOT表示在無父項(xiàng)的各子項(xiàng)即根下面的各子項(xiàng)之間存在連線;
??? TVS_HASBUTTONS表示在帶有子項(xiàng)的父項(xiàng)前面增加一個(gè)帶“+”或“-”的按鈕,這使得用戶也可以通過單擊這個(gè)小按鈕來實(shí)現(xiàn)子項(xiàng)的展開和合攏,當(dāng)存在子項(xiàng)時(shí),按鈕的初始狀態(tài)為“+”,當(dāng)子項(xiàng)被展開時(shí),按小按鈕由“+”變?yōu)椤?#xff0d;”號(hào),當(dāng)子項(xiàng)合攏時(shí),小按鈕由“-”變?yōu)椤?#xff0b;”號(hào),這一風(fēng)格同樣對(duì)于根項(xiàng)無效,如果需要可通過組合TVS_LINESATROOT風(fēng)格來實(shí)現(xiàn);
??? TVS_EDITLABELS表示允許讓用戶單擊具有輸入焦點(diǎn)的數(shù)據(jù)項(xiàng)來修改其名稱。
對(duì)于樹控制,MFC中也以兩種形式來封裝,即樹控制(CTREECTRL)和樹視(CTREEVIEW),來滿足用戶的不同需求,對(duì)于一般要求的用戶如在對(duì)話框中應(yīng)用,使用樹控制比較方便,而對(duì)于具有較高要求的用戶,在使用樹視時(shí)還具有視窗口的各種方便特性,可以更好地滿足文檔/視結(jié)構(gòu)的要求。當(dāng)在窗口中使用樹視時(shí),樹視會(huì)占滿兩個(gè)窗口的客戶區(qū)域并自動(dòng)隨窗口的框架結(jié)構(gòu)的調(diào)整而調(diào)整,并能夠很好地處理諸如菜單、加速鍵和工具條中的各種命令消息。在使用樹視時(shí)只要利用其成員函數(shù)CtreeView取得其一個(gè)引用,就可以象樹控制一樣方便地應(yīng)用:CtreeCtrl &treeCtrl = GetTreeCtrl()。
4.2 樹控制的對(duì)象結(jié)構(gòu)
4.2.1 樹控制的建立方法
??? CtreeCtrl&treeCtrl? 建立樹控制對(duì)象結(jié)構(gòu)
??? Create?????????????? 建立樹控制并綁定對(duì)象
??? 樹控制CTreeCtrl::Create的調(diào)用格式如下:
??? BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
??? 其中參數(shù)dwStyle用來確定樹控制的類型;rect用來確定樹控制的大小和位置;pParentWnd用來確定樹控制的父窗口,通用是一個(gè)對(duì)話框并且不能為NULL;nID用來確定樹控制的標(biāo)識(shí)。樹控制的風(fēng)格可以是下列值的組合:
??? TVS_HASLINES?????? 表示樹控制在各子項(xiàng)之間存在連線;
??? TVS_LINESATROOT??? 表示樹控制在根項(xiàng)之間存在連線;
??? TVS_HASBUTTONS???? 表示樹控制視在父項(xiàng)左側(cè)存在展開合攏控制按鈕;
??? TVS_EDITLABELS???? 表示可以控制鼠標(biāo)單擊修改樹項(xiàng)的名稱;
??? TVS_SHOWSELALWAYS? 表示選中項(xiàng)即使在窗口失去輸入焦點(diǎn)時(shí)仍然保持選中狀態(tài);
??? TVS_DISABLEDRAGDROP表示禁止樹控制發(fā)送TVN_BEGINDRAG消息
4.2.2 樹控制的屬性類
??? 樹控制屬性類包括取得樹控制中項(xiàng)數(shù)GetCount、取得樹控制中項(xiàng)相對(duì)于父項(xiàng)的偏移值GetIndent、取得樹控制圖像列表控制句柄GetImageList、設(shè)置樹控制圖像列表控制句柄SetImageList、取得匹配下一個(gè)樹項(xiàng)GetNextItem、判斷給定樹項(xiàng)是否包含子項(xiàng)ItemHasChildren、取得樹項(xiàng)子項(xiàng)GetChildItem、取得下一個(gè)同屬樹項(xiàng)GetNextSiblingItem、取得前一個(gè)同屬樹項(xiàng)GetPrevSiblingItem、取得父樹項(xiàng)GetParentItem、取得第一個(gè)可視樹項(xiàng)GetFirstVisibleItem、取得下一個(gè)可視樹項(xiàng)GetNextVisible? Item、取得前一個(gè)可視的樹項(xiàng)GetPrevVisibleItem、取得被選中的樹項(xiàng)GetSelectedItem、取得根樹項(xiàng)GetRootItem、取得樹項(xiàng)的屬性GetItem、設(shè)置樹項(xiàng)的屬性SetItem、取得樹項(xiàng)的狀態(tài)GetItemState、設(shè)置樹項(xiàng)的狀態(tài)SetItemState、取得與樹項(xiàng)關(guān)聯(lián)圖像GetItemImage、設(shè)置與樹項(xiàng)關(guān)聯(lián)圖像SetItemImage、取得樹項(xiàng)文本GetItemText、設(shè)置樹項(xiàng)文本SetItemText和取得樹項(xiàng)編輯控制句柄GetEditControl等。
4.2.3 樹控制的操作方法
??? 樹控制的操作方法包括插入一個(gè)樹項(xiàng)InsertItem、刪除一個(gè)樹項(xiàng)DeleteItem、刪除所有樹項(xiàng)DeleteAllItems、展開或合攏樹項(xiàng)的子項(xiàng)Expand、選中特定樹項(xiàng)SelectItem、選擇一個(gè)樹項(xiàng)作為第一個(gè)可視樹項(xiàng)SelectSetFirstVisible、編輯一個(gè)可視的樹項(xiàng)EditLabel和排序給定父樹項(xiàng)的子樹項(xiàng)SortChildren等。
4.3 樹控制的數(shù)據(jù)結(jié)構(gòu)
??? 在使用樹控制時(shí)需要了解兩個(gè)個(gè)非常重要的數(shù)據(jù)結(jié)構(gòu)TV_ITEM和TV_INSERTSTRUCT,前一個(gè)數(shù)據(jù)結(jié)構(gòu)是用來表示樹控制的樹項(xiàng)信息,后一個(gè)數(shù)據(jù)結(jié)構(gòu)是用來定義將樹項(xiàng)增加到數(shù)據(jù)控制中所需要的數(shù)據(jù)內(nèi)容。另外,還需要NM_TREEVIEW、TV_DISPINFO和TV_HITTESTINFO三個(gè)數(shù)據(jù)結(jié)構(gòu),這幾個(gè)數(shù)據(jù)結(jié)構(gòu)的定義方法如下:
4.3.1 基本數(shù)據(jù)項(xiàng)結(jié)構(gòu)
typedef struct _TV_ITEM {
??? UINT?????? mask;?????? file://結(jié)構(gòu)成員有效性屏蔽位
??? HTREEITEM? hItem;????? file://數(shù)據(jù)項(xiàng)控制句柄
??? UINT?????? state;????? file://數(shù)據(jù)項(xiàng)狀態(tài)
??? UINT?????? stateMask;? file://狀態(tài)有效性屏蔽位
??? LPSTR????? pszText;??? file://數(shù)據(jù)項(xiàng)名稱字符串
??? int??????? cchTextMax; file://數(shù)據(jù)項(xiàng)名稱的最大長(zhǎng)度
??? int??????? iImage;???? file://數(shù)據(jù)項(xiàng)圖標(biāo)索引號(hào)
??? int??????? iSelectedImage;//選中數(shù)據(jù)項(xiàng)圖標(biāo)索引號(hào)
??? int??????? cChildren;? file://子項(xiàng)標(biāo)識(shí)
??? LPARAM???? lParam;???? file://程序定義的32位數(shù)據(jù)
} TV_ITEM, FAR *LPTV_ITEM;
4.3.2 插入樹項(xiàng)結(jié)構(gòu)
??? typedef struct _TV_INSER?TSTRUCT {
??? HTREEITEM hParent;????? file://父項(xiàng)控制句柄
??? HTREEITEM hInsertAfter; file://插入樹項(xiàng)的位置
??? TV_ITEM?? item;???????? file://數(shù)據(jù)項(xiàng)的結(jié)構(gòu)
??? } TV_INSERTSTRUCT, FAR *LPTV_INSERTSTRUCT;
??? 其中插入的位置如果是TVI_FIRST 或TVI_LAST ,則分別插入到樹控制的最前面或最后面,如果是TVI_SORT ,則插入的樹項(xiàng)自動(dòng)插入到合適的位置。
4.3.3 樹控制通知消息結(jié)構(gòu)
??? typedef struct _NM_TREEVIEW {
??? NMHDR??? hdr;???? file://通知消息句柄
??? UINT???? action;? file://通知消息標(biāo)志
??? TV_ITEM? itemOld; file://原來的數(shù)據(jù)結(jié)構(gòu)
??? TV_ITEM? itemNew; file://新的數(shù)據(jù)結(jié)構(gòu)
??? POINT??? ptDrag;? file://拖動(dòng)指針
??? } NM_TREEVIEW;
4.3.4 取得或設(shè)置數(shù)據(jù)結(jié)構(gòu)
??? typedef struct _TV_DISPINFO {? tvdi
??? NMHDR?? hdr;????? file://通知消息控制句柄
??? TV_ITEM item;???? file://數(shù)據(jù)項(xiàng)結(jié)構(gòu)
??? } TV_DISPINFO;
4.3.5 指4.3.6 針測(cè)試數(shù)據(jù)結(jié)構(gòu)
??? typedef struct _TVHITTESTINFO {? tvhtst
??? POINT???? pt;???? file://客戶區(qū)域屏幕坐標(biāo)指針
??? UINT????? flags;? file://存放測(cè)試結(jié)果的變量
??? HTREEITEM hItem;? file://測(cè)試的數(shù)據(jù)項(xiàng)結(jié)構(gòu)
??? } TV_HITTESTINFO, FAR *LPTV_HITTESTINFO;
??? 其中flags測(cè)試結(jié)果可以是如下值:
??? TVHT_ABOVE??????? 在客戶區(qū)域上面
??? TVHT_BELOW??????? 在客戶區(qū)域下面
??? TVHT_NOWHERE????? 在客戶區(qū)域中并在最后一項(xiàng)下面
??? TVHT_ONITEM?????? 在與樹項(xiàng)關(guān)聯(lián)的位圖或標(biāo)簽內(nèi)
??? TVHT_ONITEMBUTTON 在與樹項(xiàng)關(guān)聯(lián)的按鈕上
??? TVHT_ONITEMICON?? 在與樹項(xiàng)關(guān)聯(lián)的位圖上
??? TVHT_ONITEMINDENT 在與樹項(xiàng)關(guān)聯(lián)的聯(lián)線上
??? TVHT_ONITEMLABEL? 在與樹項(xiàng)關(guān)聯(lián)的標(biāo)簽上
??? TVHT_ONITEMRIGHT? 在樹項(xiàng)的右側(cè)區(qū)域中
??? TVHT_ONITEMSTATEICON 在用戶定義的狀態(tài)圖標(biāo)上
??? TVHT_TOLEFT?????? 在客戶區(qū)域的左側(cè)
??? TVHT_TORIGHT????? 在客戶區(qū)域的右側(cè)
4.4 樹控制的應(yīng)用技巧示例
??? 這里仍以基于對(duì)話框演示實(shí)例來具體介紹樹控制及其和圖像列表相結(jié)構(gòu)的應(yīng)用技巧:
??? 通過“FILE->NEW->PROJECTS->MFC AppWizard(EXE)”建立名為VCTREE的工程,在建立過程中選擇基于對(duì)話框(Dialog based)的應(yīng)用;將對(duì)話框中的默認(rèn)控件刪除,并將所有對(duì)話框?qū)傩灾械腖anguage域設(shè)置為Chinese(P.R.C.),以使應(yīng)用程序支持中文;建立兩個(gè)圖標(biāo)IDI_PM和IDI_CJ,用來表示圖標(biāo)的選中和非選中狀態(tài),對(duì)于每個(gè)圖標(biāo)都應(yīng)建立32X32和16X16兩種大小,以保證程序的需要;在對(duì)話框窗口中添加樹控制對(duì)象(TREE? CONTROL),并設(shè)置五個(gè)按鈕“增加|刪除|查看|排序|關(guān)閉”,其對(duì)應(yīng)標(biāo)識(shí)分別如下:
?? 控制名稱??????? 標(biāo)題名稱??????????????? 標(biāo)識(shí)符號(hào)
??? 樹控制????????????????????????????????? IDC_TREECTRL
??? 按鈕??????????? 增? 加????????????????? IDC_ADD
??????????????????? 刪? 除????????????????? IDC_DEL
??????????????????? 查? 看????????????????? IDC_VIEW
??????????????????? 排? 序????????????????? IDC_SORT
??????????????????? 關(guān)? 閉????????????????? IDOK
??? 5、選中樹控制控件,選擇“VIEW->ClassWizard->Memory Variables。骺刂艻DC_TREECTRL???????? 引入成員變量,其變量類型為:
????? 變量名??????????? 種類??????????? 變量類型
??? m_TreeCtrl??????? Control???????? CTreeCtrl
??? 同時(shí)利用“MESSAGES MAP”為各命令按鈕增加控制功能函數(shù)。
??? 6、然后在代碼文件VCTREEDlg.CPP中分別加入如下控制代碼:
??? (1)在文件開始處增加圖像列表定義
??? CImageList Cil1,Cil2;//大小圖標(biāo)像列表
??? (2)在初始化文件開始處增加代碼
??? BOOL CVCTREEDlg::OnInitDialog()
??? {?CDialog::OnInitDialog();
??? ......//原來其它代碼
??? // TODO: Add extra initialization here
??? // 此處開始增加代碼
??? CVCTREEApp *pApp=(CVCTREEApp *)AfxGetApp();//創(chuàng)建圖象列表
??? Cil1.Create(16,16,ILC_COLOR,2,2);
??? Cil1.Add(pApp->LoadIcon(IDI_PM));
??? Cil1.Add(pApp->LoadIcon(IDI_CJ));
??? m_TreeCtrl.SetImageList(&Cil1,TVSIL_NORMAL); file://設(shè)置圖象列表
??? DWORD dwStyles=GetWindowLong(m_TreeCtrl.m_hWnd,GWL_STYLE);//獲取樹控制原風(fēng)格
??? dwStyles|=TVS_EDITLABELS|TVS_HASBUTTONS|TVS_HASLINES|TVS_LINESATROOT;
??? SetWindowLong(m_TreeCtrl.m_hWnd,GWL_STYLE,dwStyles);//設(shè)置風(fēng)格
??? char * CJ[4]={"玉溪卷煙廠","云南卷煙廠","沈陽卷煙廠","成都卷煙廠"};//根數(shù)據(jù)名稱
??? char * PM[4][5]={
??{"紅梅一","紅梅二","紅梅三","紅梅四","紅梅五"},//產(chǎn)品數(shù)據(jù)項(xiàng)
??{"白梅一","白梅二","白梅三","白梅四","白梅五"},
??{"綠梅一","綠梅二","綠梅三","綠梅四","綠梅五"},
??{"青梅一","青梅二","青梅三","青梅四","青梅五"}};
??? int i,j;
??? HTREEITEM hRoot,hCur;//樹控制項(xiàng)目句柄
??? TV_INSERTSTRUCT TCItem;//插入數(shù)據(jù)項(xiàng)數(shù)據(jù)結(jié)構(gòu)
??? TCItem.hParent=TVI_ROOT;//增加根項(xiàng)
??? TCItem.hInsertAfter=TVI_LAST;//在最后項(xiàng)之后
??? TCItem.item.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;//設(shè)屏蔽
??? TCItem.item.pszText="數(shù)據(jù)選擇";
??? TCItem.item.lParam=0;//序號(hào)
??? TCItem.item.iImage=0;//正常圖標(biāo)
??? TCItem.item.iSelectedImage=1;//選中時(shí)圖標(biāo)
??? hRoot=m_TreeCtrl.InsertItem(&TCItem);//返回根項(xiàng)句柄
??? for(i=0;i<4;i++){//增加各廠家
??TCItem.hParent=hRoot;
??TCItem.item.pszText=CJ[i];
??TCItem.item.lParam=(i+1)*10;//子項(xiàng)序號(hào)
??hCur=m_TreeCtrl.InsertItem(&TCItem);
??for(j=0;j<5;j++){//增加各產(chǎn)品
???TCItem.hParent=hCur;
???TCItem.item.pszText=PM[i][j];
???TCItem.item.lParam=(i+1)*10+(j+1);//子項(xiàng)序號(hào)
???m_TreeCtrl.InsertItem(&TCItem);
??}
???? m_TreeCtrl.Expand(hCur,TVE_EXPAND);//展開樹
??? }
??? m_TreeCtrl.Expand(hRoot,TVE_EXPAND);//展開上一級(jí)樹
??? return TRUE;? // return TRUE? unless you set the focus to a control
??? }
??? (3)增加樹項(xiàng)功能的實(shí)現(xiàn)
??? 在增加樹項(xiàng)功能時(shí),除了需要定義和設(shè)置插入樹項(xiàng)的數(shù)據(jù)結(jié)構(gòu)之外,還需要注意的是新增樹項(xiàng)的名稱初始時(shí)均為“新增數(shù)據(jù)”,增加后允許用戶給數(shù)據(jù)項(xiàng)設(shè)置自定義名稱。在編程時(shí)應(yīng)特別注意m_TreeCtrl.EditLabel(hInsert);后面不能跟任何其它程序命令,否則這條編輯指令無效。
??? void CVCTREEDlg::OnAdd()
??? {?file://增加子項(xiàng)功能函數(shù)
??? HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選擇項(xiàng)句柄
??? if(hSel==NULL) return;//無任何選項(xiàng)則返回
??? static int nAddNo=100;//編號(hào)大于100為新增數(shù)據(jù)
??? TV_INSERTSTRUCT TCItem;//定義插入項(xiàng)數(shù)據(jù)結(jié)構(gòu)
??? TCItem.hParent=hSel;?? file://設(shè)置父項(xiàng)句柄
??? TCItem.hInsertAfter=TVI_LAST;//在最后增加
??? TCItem.item.mask=TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;//設(shè)屏蔽
??? TCItem.item.pszText="新增數(shù)據(jù)";
??? TCItem.item.lParam=nAddNo++;//索引號(hào)增加
??? TCItem.item.iImage=0;//正常圖標(biāo)
??? TCItem.item.iSelectedImage=1;//選中時(shí)圖標(biāo)
??? HTREEITEM hInsert=m_TreeCtrl.InsertItem(&TCItem);//增加
??? m_TreeCtrl.Expand(hSel,TVE_EXPAND);
??? m_TreeCtrl.EditLabel(hInsert);//修改增加的數(shù)據(jù)
??? }
??? (4)刪除樹項(xiàng)功能的實(shí)現(xiàn)
??? 在實(shí)現(xiàn)刪除功能時(shí),應(yīng)對(duì)存在子項(xiàng)的樹項(xiàng)進(jìn)行提示,以警告用戶是否連同其子項(xiàng)一起刪除。
??? void CVCTREEDlg::OnDel()
??? {?file://刪除子項(xiàng)功能函數(shù)
????? HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選項(xiàng)句柄;
??? ?if(hSel==NULL) return;//無任何選項(xiàng)則返回
??? ?if(m_TreeCtrl.ItemHasChildren(hSel))//判斷是否有子項(xiàng)
????? ?if(MessageBox("廠家下存在品名,一同刪除?","警告",MB_YESNO)==IDNO) return;
? ?m_TreeCtrl.DeleteItem(hSel);
??? }
??? (5)排序功能的實(shí)現(xiàn)
??? 排序功能是對(duì)所選中的樹項(xiàng)的所有子項(xiàng)按字符中順序進(jìn)行排序,如果想要按照其它規(guī)則進(jìn)行排序,應(yīng)利用SortChildrenItemBC()函數(shù)進(jìn)行自行開發(fā)排序程序,這個(gè)自行開發(fā)的函數(shù)與列表控制中實(shí)現(xiàn)的函數(shù)基本相同,可興趣的讀可以試驗(yàn)。
??? void CVCTREEDlg::OnSort()
??? {?file://排序子項(xiàng)功能函數(shù)
??? HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選項(xiàng)句柄;
??? if(hSel==NULL) return;//無任何選項(xiàng)則返回
??? m_TreeCtrl.SortChildren(hSel);
??? }
??? (6)查看功能的實(shí)現(xiàn)
??? 查看功能用來查看選中樹項(xiàng)的有關(guān)信息,函數(shù)中中顯示了樹項(xiàng)的文本名稱和標(biāo)識(shí)號(hào),可以將這兩個(gè)信息作為查找關(guān)鍵字,來查看其它更詳細(xì)的信息。
??? void CVCTREEDlg::OnView()
??? {?file://查看選中項(xiàng)功能函數(shù)
??? HTREEITEM hSel=m_TreeCtrl.GetSelectedItem();//取得選項(xiàng)句柄;
??? if(hSel==NULL) return;//無任何選項(xiàng)則返回
??? CString cText=m_TreeCtrl.GetItemText(hSel);//取得數(shù)據(jù)項(xiàng)名
??? LONG IDs=m_TreeCtrl.GetItemData(hSel);//取得數(shù)據(jù)項(xiàng)序號(hào)
??? char temp[100];
??? wsprintf(temp,"廠家:%s 編號(hào):%05d",cText,IDs);
??? MessageBox(temp,"選擇信息");
??? }
??? (7)修改功能的實(shí)現(xiàn)
??? 如果不進(jìn)行其它處理,當(dāng)修改樹項(xiàng)的文本名稱后,就會(huì)發(fā)現(xiàn)其未被修改,這是因?yàn)槌绦蛑袥]有對(duì)修改結(jié)果進(jìn)行保存處理,這就要利用TV_DISPINFO結(jié)構(gòu)和SetItemText函數(shù)對(duì)TVN_ENDLABELEDIT進(jìn)行處理,這樣就可以正確地實(shí)現(xiàn)修改功能。
??? void CVCTREEDlg::OnEndlabeleditTree(NMHDR* pNMHDR, LRESULT* pResult)
??? {?TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
??// TODO: Add your control notification handler code here
????? if(pTVDispInfo->item.pszText==0)?return;//用戶取消修改操作
??? ?m_TreeCtrl.SetItemText(pTVDispInfo->item.hItem,
??pTVDispInfo->item.pszText);//設(shè)置新數(shù)據(jù)
??*pResult = 0;
??? }
7、樹視的演練技巧
樹視的應(yīng)用技巧在使用樹視時(shí),其方法與樹控制基本相同,只不過樹視是在窗口中來實(shí)現(xiàn)的而樹控制是在對(duì)話框中實(shí)現(xiàn),樹視的各種功能是通過菜單來實(shí)現(xiàn)的而樹控制是通過按鈕等方式來實(shí)現(xiàn)的,樹控制需要在對(duì)話框中創(chuàng)建樹控制控件而樹視直接占據(jù)整個(gè)窗口,在設(shè)計(jì)過程中只要將按鈕和樹控制設(shè)計(jì)過程變?yōu)椴藛卧O(shè)計(jì),并注意在功能函數(shù)是在類向?qū)е惺峭ㄟ^菜單命令來操作,同時(shí)在每個(gè)功能函數(shù)前面增加取得列表視引用的命令(CTreeCtrl& TreeCtrl = GetTreeCtrl()),而其余數(shù)據(jù)結(jié)構(gòu)和代碼均不需要修改,實(shí)現(xiàn)起來比較容易。筆者實(shí)現(xiàn)的樹控制和視程序的運(yùn)行結(jié)果如下:
??????????????????? 樹控制的演練示例結(jié)果
????????????? 樹視演練結(jié)果示例
第5章 演練CTab
5.1 標(biāo)5.2 簽控制的主要功能
??? 標(biāo)簽控制(Tab Control)是用來在一個(gè)窗口如對(duì)話框等中的同一用戶區(qū)域控制多組顯示信息或控制信息,由頂部的一組標(biāo)簽來控制不同的信息提示,標(biāo)簽即可以是文本說明也可以是一個(gè)代表文本含義的圖標(biāo),或是兩者的組合。針對(duì)不同的選擇標(biāo)簽,都會(huì)有一組提示信息或控制信息與之相對(duì)應(yīng),供用戶進(jìn)行交互操作,這在WINDOWS98的屬性表中最常見。另外還存在一種特殊風(fēng)格的標(biāo)簽,即TBS_BUTTONS風(fēng)格的標(biāo)簽,這種標(biāo)簽外觀類似按鈕,通過鼠標(biāo)點(diǎn)擊改變狀態(tài),一般用來執(zhí)行一些功能而不是用來顯示或控制信息。
??? 提到標(biāo)簽,最快想到的應(yīng)該是屬性表對(duì)話(Property Sheet),這兩者的配合應(yīng)用更是隨處可見。屬性表對(duì)話框有時(shí)也稱為多頁對(duì)話框(Multiple-Page Dialog)或是標(biāo)簽對(duì)話框(Table Dialog),最多可設(shè)置24個(gè)屬性頁(Property Page),通過頂部的標(biāo)簽來選擇不同的屬性頁。另外還有一種特殊的屬性表對(duì)話框,就象VC++5.0中的類向?qū)ppWizard一樣,其不存在供用戶選擇的標(biāo)簽,而是按照順序依次控制屬性頁的顯示,并且還有一般屬性頁中不存在的“確認(rèn)”、“上一步”、“下一步”、“完成”和“幫助”等按鈕。
??? 標(biāo)簽控制在MFC中只存在一種封裝形式,即控制類CtabCtrl。在使用標(biāo)簽時(shí)即可以在對(duì)話框中直接添加,也可以在窗口中作為子窗口來使用,只不過這樣應(yīng)用時(shí)需要選創(chuàng)建標(biāo)簽。
5.3 標(biāo)5.4 簽控制的對(duì)象結(jié)構(gòu)
5.4.1 標(biāo)5.4.2 簽控制的建立方法
??? CTabCtrl&tabCtrl???? 建立標(biāo)簽控制對(duì)象結(jié)構(gòu)
??? Create??????????????? 建立標(biāo)簽控制并綁定對(duì)象
??? 標(biāo)簽控制CTabCtrl::Create的調(diào)用格式如下:
??? BOOL Create( DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID );
??? 其中參數(shù)dwStyle用來確定標(biāo)簽控制的風(fēng)格;rect用來控制標(biāo)簽的大小和位置;pParentWnd用來確定標(biāo)簽控制的父窗口句柄;nID用來確定標(biāo)簽控制的標(biāo)識(shí)符。
標(biāo)簽控制的風(fēng)格可以是如下值的組合:
??? TCS_BUTTONS??????????? 表示將標(biāo)簽外觀定義成類似按鈕
??? TCS_FIXEDWIDTH???????? 使所有標(biāo)簽具有相同的寬度
??? TCS_FOCUSNEVER???????? 使特定標(biāo)簽永遠(yuǎn)不接收輸入焦點(diǎn)
??? TCS_FOCUSONBUTTONDOWN? 當(dāng)標(biāo)簽被鼠標(biāo)點(diǎn)擊時(shí)接收輸入焦點(diǎn),其僅與TCS_BUTTONS合用
??? TCS_FORCEICONLEFT????? 強(qiáng)制圖標(biāo)在左面,剩余部分使標(biāo)簽居中
??? TCS_FORCELABELLEFT???? 使圖標(biāo)和標(biāo)簽均左對(duì)齊
??? TCS_MULTILINE????????? 允許標(biāo)簽控制顯示多行標(biāo)簽
??? TCS_OWNERDRAWFIXED???? 允許父窗口自繪標(biāo)簽
??? TCS_RIGHTJUSTIFY?????? 使標(biāo)簽右對(duì)齊
??? TCS_SHAREIMAGELISTS??? 當(dāng)控制被撤消時(shí)標(biāo)簽控制的圖像不被撤消
??? TCS_TOOLTIPS?????????? 允許標(biāo)簽控制存在工具提示控制
??? TCS_TABS?????????????? 標(biāo)簽正常顯示,為默認(rèn)狀態(tài)
??? TCS_SINGLELINE???????? 將標(biāo)簽只顯示在一行上,默認(rèn)狀態(tài)
??? TCS_RAGGEDRIGHT??????? 不使標(biāo)簽自動(dòng)填滿控制區(qū)域,默認(rèn)狀態(tài)
??? 同樣,標(biāo)簽控制還可以使用窗口的一些控制風(fēng)格:
??? WS_CHILD?????????????? 為標(biāo)簽控制創(chuàng)建子窗口,只能與WS_POPUP風(fēng)格一起使用
??? WS_VISIBLE???????????? 建立一個(gè)初始可視的標(biāo)簽控制
??? WS_DISABLED??????????? 建立一個(gè)初始不可視的標(biāo)簽控制
??? WS_GROUP?????????????? 建立標(biāo)簽控制群組的第一個(gè)控制
??? WS_TABSTOP???????????? 建立可用TAB鍵移動(dòng)的標(biāo)簽控制
5.4.3 標(biāo)5.4.4 簽控制的屬性類
??? 標(biāo)簽控制的屬性類包括取得與標(biāo)簽控制相關(guān)聯(lián)的圖像列表GetImageList、設(shè)置標(biāo)簽控制的圖像列表SetImageList、取得標(biāo)簽控制中標(biāo)簽的總數(shù)GetItemCount、取得標(biāo)簽控制中特定標(biāo)答的相關(guān)信息GetItem、設(shè)置標(biāo)簽的部分或全部屬性SetItem、檢測(cè)當(dāng)前被選中的標(biāo)簽GetCurSel、將一個(gè)標(biāo)簽設(shè)置為選中狀態(tài)SetCurSel和取得具有當(dāng)前輸入焦點(diǎn)的標(biāo)簽SetCurSel等。
5.4.5 標(biāo)5.4.6 簽控制的操作方法
??? 標(biāo)簽控制的操作方法包括在標(biāo)簽控制中插入一個(gè)標(biāo)簽InsertItem、刪除一個(gè)標(biāo)簽????? DeleteItem、從標(biāo)簽控制中刪除所有項(xiàng)目DeleteAllItems、從標(biāo)簽控制中刪除一個(gè)圖像列表RemoveImage和繪制標(biāo)簽控制中的特定一項(xiàng)DrawItem等。
5.5 標(biāo)5.6 簽控制的數(shù)據(jù)結(jié)構(gòu)
??? 在使用標(biāo)簽控制時(shí),必須使用的函數(shù)就是在標(biāo)簽控制中插入標(biāo)簽。函數(shù)InsertItem的原形如下:
??? BOOL? InsertItem(int nItem,TC_ITEM * pTabCtrlItem);
??? 該函數(shù)中的TC_ITEM為添加標(biāo)簽時(shí)所使用信息的數(shù)據(jù)結(jié)構(gòu),其數(shù)據(jù)成員的定義方法及含義如下:
??? typedef struct _TC_ITEM {
??? UINT mask;???????? // 確定結(jié)構(gòu)成員的屏蔽或設(shè)置位
??? UINT lpReserved1;? // 保留未用
??? UINT lpReserved2;? // 保留未用
??? LPSTR pszText;???? // 標(biāo)簽名稱字符串
??? int cchTextMax;??? // 標(biāo)簽名稱字符串緩沖區(qū)大小
??? int iImage;??????? // 標(biāo)簽控制的圖像索引號(hào)
??? LPARAM lParam;???? // 應(yīng)用程序定義的相關(guān)32位數(shù)據(jù)
??? } TC_ITEM;
??? 當(dāng)鼠標(biāo)點(diǎn)擊標(biāo)簽控制中的標(biāo)簽時(shí),標(biāo)簽控制就會(huì)向其父窗口發(fā)送相關(guān)的通知消息,通過處理這些通知消息,程序可以實(shí)現(xiàn)各種功能。
5.7 屬性表和屬性頁的基本用法
??? 在標(biāo)簽控制過程中,屬性表對(duì)話框和屬性頁是必不可少的。在MFC類庫(kù)中,屬性表對(duì)話框類CpropertySheet是由CWnd類派生而來的,而屬性頁類CpropertyPage是由Cdialog類派生而來的,它們的用法基本相同:
??? 1、創(chuàng)建所有的屬性頁。創(chuàng)建屬性頁的方法與創(chuàng)建一般對(duì)話框資源的方法一樣,利用對(duì)話框編輯器可以為每個(gè)屬性頁創(chuàng)建一個(gè)對(duì)話框模板,其區(qū)別在于,當(dāng)利用類向?qū)lassWizard為屬性頁生成類時(shí)應(yīng)選擇屬性頁類CpropertyPage作為基類,而不是將一般的對(duì)話框類Cdialog作為基類;
??? 2、創(chuàng)建屬性表對(duì)話框,并將事先創(chuàng)建好的各屬性頁添加進(jìn)去,兩者的創(chuàng)建順序可以互換,但在創(chuàng)建完之后將屬性頁添加到屬性表對(duì)話框中去這一步是必須要做的;
??? 3、顯示屬性表對(duì)話框。雖然屬性表對(duì)話框類CpropertySheet不是由對(duì)話框類Cdialog派生而來的,但兩者的操作非常類似,調(diào)用DoModal()函數(shù)就會(huì)顯示一個(gè)模態(tài)屬性表對(duì)話框,而調(diào)用Create()操作就會(huì)顯示一個(gè)非模態(tài)的屬性表對(duì)話框;
??? 4、對(duì)數(shù)據(jù)交換的處理。和對(duì)話框類似,屬性表對(duì)話框與對(duì)象之間的數(shù)據(jù)交換也是通過數(shù)據(jù)成員2來實(shí)現(xiàn)的,只是屬性表本身不帶數(shù)據(jù)成員,而實(shí)際進(jìn)行數(shù)據(jù)交換的是屬性頁中的數(shù)據(jù)成員;
??? 5、對(duì)向?qū)?duì)話框的處理。如果要顯示一個(gè)向?qū)?duì)話框,在顯示之前應(yīng)首先調(diào)用SetWizardMode()函數(shù)對(duì)向?qū)?duì)話框進(jìn)行特殊處理,對(duì)于存在按鈕的向?qū)?duì)話框,還應(yīng)調(diào)用SetWizardButtons()來對(duì)向?qū)?duì)話框的按鈕功能進(jìn)行定制,在用戶操作結(jié)束時(shí)還應(yīng)調(diào)用SetFinishText()函數(shù)將“完成”按鈕設(shè)置為有效狀態(tài)。
5.8 標(biāo)5.9 簽控制的應(yīng)用技巧示例程序
  本文給出一個(gè)基于文檔的標(biāo)簽應(yīng)用實(shí)例。實(shí)例程序中通過簡(jiǎn)單設(shè)置菜單、標(biāo)簽和屬性表來演示標(biāo)簽控制的實(shí)際應(yīng)用技巧,程序通過選擇菜單選項(xiàng)彈出設(shè)置正文顏色、字體和修飾等屬性表對(duì)話框來和用戶進(jìn)行簡(jiǎn)單交互。其實(shí)現(xiàn)步驟如下:
??? 1、利用應(yīng)用程序向?qū)ppWizard創(chuàng)建一個(gè)基于文檔的工程TAB,在選擇工程類型時(shí)應(yīng)選擇單文檔;
??? 2、利用資源中的菜單生成器,刪除無用菜單,并增加如下菜單結(jié)構(gòu)
??? 菜單名??????????????? 標(biāo)識(shí)符
??? 設(shè)置(S)?????????????? (彈出菜單名)
??? 背景設(shè)置(B)?????????? IDM_BKGRND
??? 前景設(shè)置(F)?????????? IDM_FRGRND
??? 3、利用對(duì)話框設(shè)計(jì)器設(shè)置屬性表對(duì)話框所需要的四個(gè)屬性頁,注意在選擇基類時(shí)應(yīng)將屬性? 頁類CpropertyPage作為基類,并將對(duì)話框及菜單等控件的所有屬均改為中文。四個(gè)屬性頁及其包括的控件內(nèi)容分別為:(1)文字屬性對(duì)話框包括一個(gè)輸入文字的文本輸入框,用于輸入和修改在窗口上顯示的文字;(2)字體屬性對(duì)話框包括三個(gè)選中框,用來確定顯示的字體修飾;(3)字間距屬性對(duì)話框包括一個(gè)用于顯示提示信息的標(biāo)簽和用于輸入字間距大小的文本輸入框;(4)顏色屬性對(duì)話框包括一個(gè)成組框和三個(gè)單選圓鈕;(5)窗口中設(shè)置一個(gè)用于顯示輸入文字的標(biāo)簽。
??? 以上控制的設(shè)置參數(shù)如下:
??? ?控制名稱??????????? 標(biāo)題名稱????????????? 標(biāo)識(shí)符串
??? ?標(biāo)簽控制????????????????????????????????? IDC_TABCTRL
????? 表態(tài)文本??????????? 字間距(10-100)??????? IDC_STATIC1
????? 編輯框??????????????????????????????????? IDC_LIST
????? 成組框????????????? 顏色????????????????? IDC_STATIC2
????? 單選按鈕??????????? 黑色????????????????? IDC_BLACK
????????????????????????? 紅色????????????????? IDC_RED
????????????????????????? 藍(lán)色????????????????? IDC_BLUE
????? 文本框(編輯框)????????????????????????? IDC_TEXT
????? 設(shè)置字體(復(fù)選按鈕)粗體????????????????? IDC_BOLD
????????????????????????? 斜體????????????????? IDC_ITALIC
????????????????????????? 下劃線??????????????? IDC_UNDERLINE
????? 按? 鈕????????????? 確認(rèn)????????????????? IDOK
????????????????????????? 取消????????????????? IDCANCEL
??? 利用類向?qū)lassWizard在屬性表對(duì)話框CtabDlg、屬性頁對(duì)話框CtextPage和CstylePage中分別加入如下數(shù)據(jù)成員:
? ?標(biāo)識(shí)符串????????????? 類型??????????????? 數(shù)據(jù)成員
??? IDC_TABCTRL?????????? CtabCtrl??????????? m_tabCtrl
??? IDC_DIST????????????? int???????????????? m_nDist
??? IDC_BLACK???????????? int???????????????? m_nColor
??? IDC_TEXT????????????? Cstring???????????? m_cText
??? IDC_BOLD????????????? BOOL??????????????? m_bBold
??? IDC_ITALIC??????????? BOOL??????????????? m_bItalic
??? IDC_UNDERLINE???????? BOOL??????????????? m_bUnderline
??? 以上數(shù)據(jù)成員也可以在TABDlg.h、StylePage.h和TextPage.h中利用手工方法增加。
??? 4、將要顯示的數(shù)據(jù)成員加入到視類中去,來和對(duì)話框之間進(jìn)行數(shù)據(jù)交換,并且將其在初始化函數(shù)中進(jìn)行數(shù)據(jù)初始化。
??? (1)在TabView.h中增加如下代碼:
#include "TabDlg.h"
#include "TextPage.h"
#include "StylePage.h"
class CTabView : public CView
{public:
?int nDist;//數(shù)值
?int nColor;//顏色
?CString cText;//中文字符串
?BOOL bBold,bItalic,bUnderline;//字體屬性
}
(2)在TabView.cpp中對(duì)數(shù)據(jù)成員進(jìn)行如下初始化。
CTabView::CTabView()
{?nDist=20;
?nColor=1;
?cText=CString("標(biāo)簽控制演示實(shí)例");
?bBold=bItalic=bUnderline=FALSE;
}
(3)在TabDlg.cpp中向控制中增加標(biāo)簽,來實(shí)現(xiàn)背景設(shè)置功能。
BOOL CTabDlg::OnInitDialog()
{?CDialog::OnInitDialog();
?TC_ITEM tcItem;//添加標(biāo)簽
?tcItem.mask=TCIF_TEXT;
?tcItem.pszText="字 間 距";
?m_tabCtrl.InsertItem(0,&tcItem);
?tcItem.pszText="顏色設(shè)置";
?m_tabCtrl.InsertItem(1,&tcItem);
?m_tabCtrl.SetCurSel(1);
return TRUE;
}
??? 當(dāng)標(biāo)簽切換時(shí),標(biāo)簽控制會(huì)自動(dòng)向?qū)υ捒虼翱诎l(fā)送TCN_SELCHANGE通知消息,這時(shí)需要根據(jù)所選擇的標(biāo)簽索引號(hào)對(duì)屬性頁的顯示和隱藏進(jìn)行切換控制,應(yīng)完善OnSelchangeTabctrl()函數(shù):
void CTabDlg::OnSelchangeTabctrl(NMHDR* pNMHDR, LRESULT* pResult)
{?int iPage=m_tabCtrl.GetCurSel();//所選標(biāo)簽號(hào)
?switch(iPage){
?? case 0://字間距
?? GetDlgItem(IDC_STATIC2)->ShowWindow(SW_HIDE);//隱藏選擇按鈕
?? GetDlgItem(IDC_BLACK)->ShowWindow(SW_HIDE);//隱藏選擇按鈕
?? GetDlgItem(IDC_RED)->ShowWindow(SW_HIDE);//隱藏選擇按鈕
?? GetDlgItem(IDC_BLUE)->ShowWindow(SW_HIDE);//隱藏選擇按鈕
?? GetDlgItem(IDC_STATIC1)->ShowWindow(SW_SHOW);//顯示輸入項(xiàng)數(shù)
?? GetDlgItem(IDC_DIST)->ShowWindow(SW_SHOW);//顯示輸入項(xiàng)數(shù)
?? break;
??? case 1://顏色設(shè)置
?? GetDlgItem(IDC_STATIC1)->ShowWindow(SW_HIDE);//隱藏項(xiàng)數(shù)輸入
?? GetDlgItem(IDC_DIST)->ShowWindow(SW_HIDE);//隱藏項(xiàng)數(shù)輸入
?? GetDlgItem(IDC_STATIC2)->ShowWindow(SW_SHOW);//顯示選項(xiàng)選擇
?? GetDlgItem(IDC_BLACK)->ShowWindow(SW_SHOW);//顯示選項(xiàng)選擇
?? GetDlgItem(IDC_RED)->ShowWindow(SW_SHOW);//顯示選項(xiàng)選擇
?? GetDlgItem(IDC_BLUE)->ShowWindow(SW_SHOW);//顯示選項(xiàng)選擇
?? break;
? }
? *pResult = 0;
}
??? (4)菜單功能的完善。在執(zhí)行相應(yīng)的菜單功能時(shí),必須對(duì)類向?qū)г黾拥南鄳?yīng)功能函數(shù)進(jìn)行代碼完善,這就要處理TabView.cpp文件,背景設(shè)置功能函數(shù)如下:
void CTabView::OnBkgrnd()
{?CTabDlg ctd;
ctd.m_nDist=nDist;
ctd.m_nColor=nColor;
if(ctd.DoModal()==IDCANCEL) return;
nDist=ctd.m_nDist;
nColor=ctd.m_nColor;
Invalidate();//重新繪制窗口
}
??? 同樣,也要對(duì)前景設(shè)置功能函數(shù)進(jìn)行完善:
void CTabView::OnFrgrnd()
{?CPropertySheet cps("前景設(shè)置");//創(chuàng)建屬性表對(duì)象
CTextPage ctp; file://顯示文字屬性頁
CStylePage csp;//顯示字體屬性頁
ctp.m_cText=cText;
csp.m_bBold=bBold;
csp.m_bItalic=bItalic;
csp.m_bUnderline=bUnderline;
cps.AddPage(&ctp);//添加屬性頁
cps.AddPage(&csp);
if(cps.DoModal()==IDCANCEL) return;
cText=ctp.m_cText;
bBold=csp.m_bBold;
bItalic=csp.m_bItalic;
bUnderline=csp.m_bUnderline;
Invalidate();//重新繪制窗口
}
??? (5)為了充分演示標(biāo)簽控制與各屬性頁之間的數(shù)據(jù)交換功能,應(yīng)該實(shí)現(xiàn)標(biāo)簽控制各屬性頁與用戶之間數(shù)據(jù)交換結(jié)束后的窗口顯示功能,筆者實(shí)現(xiàn)的功能函數(shù)顯示了由屬性頁中輸入的字體及背景網(wǎng)格功能,TabView.cpp中的對(duì)應(yīng)函數(shù)代碼如下:
void CTabView::OnDraw(CDC* pDC)
{?CTabDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
RECT rc;
GetClientRect(&rc);
int i,j,k;
CPen pen,*pOldPen;
COLORREF color;
switch (nColor){
case 0:color=RGB(0,0,0);?? file://設(shè)置黑色
?break;
case 1:color=RGB(0xff,0,0);//設(shè)置紅色
?break;
case 2:color=RGB(0,0,0xff);//設(shè)置藍(lán)色
?break;
}
pen.CreatePen(PS_SOLID,1,color);
pOldPen=pDC->SelectObject(&pen);//繪制背景網(wǎng)格
j=rc.right/nDist+1;
k=rc.bottom/nDist+1;
for(i=0;i<j+k;i++){
? pDC->MoveTo(i*nDist,0);
? pDC->LineTo(0,i*nDist);
? if(i<j){
??? pDC->MoveTo(i*nDist,0);
??? pDC->LineTo(rc.right,(j-i)*nDist);
? } else {
???? pDC->MoveTo(0,(i-j)*nDist);
???? pDC->LineTo(rc.right,i*nDist);
? }
}
pDC->SelectObject(&pOldPen);
CFont font,*pOldFont;
font.CreateFont(50,0,0,0,bBold?1000:200,
bItalic,bUnderline,0,ANSI_CHARSET,
?OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
?DEFAULT_QUALITY,DEFAULT_PITCH,NULL);
pOldFont=pDC->SelectObject(&font);
pDC->TextOut(20,20,cText);
pDC->SelectObject(pOldFont);
}
標(biāo)簽控制的整個(gè)實(shí)現(xiàn)過程雖然比較繁鎖,但只要掌握其實(shí)現(xiàn)的本質(zhì),設(shè)計(jì)一個(gè)優(yōu)秀的標(biāo)簽控制界面也并非很困難的事情。
筆者實(shí)現(xiàn)的標(biāo)簽控制的演練示例結(jié)果如下:
????????????????? 標(biāo)簽控制演練示例結(jié)果


?

總結(jié)

以上是生活随笔為你收集整理的演练VC中的COMMON一族(转贴)之一的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美黑大粗 | 久操欧美 | 手机av电影在线 | 久色91 | 生活片毛片| 欧美xxxxbbb| 亚洲性视频 | 国产精品黄视频 | 国产一级黄色大片 | 欧美一区二区日韩一区二区 | 2019年中文字幕 | 尼姑福利影院 | 国产伦理在线 | 亚洲v国产v| 欧美成人精品一区二区 | 国产精品日韩一区二区三区 | 99国产精品无码 | 日韩高清免费av | 国产小视频免费在线观看 | 99久久99久久久精品棕色圆 | 国产精品久久久久久免费 | 在线毛片网| 欧美mv日韩mv国产网站 | 青草久久久久 | 九月色婷婷 | 精品无码久久久久久国产 | av资源天堂| 国产又粗又猛又黄又爽视频 | 亚洲一区91 | 亚洲一级电影 | jizz91 | 99自拍偷拍 | 精品国产成人av | 性xxxx狂欢老少配o | 国产性生活片 | av免费国产 | 久久天天躁狠狠躁夜夜躁2014 | 午夜精品久久久久久久四虎美女版 | 奇米影视亚洲春色 | 日本黄色性视频 | 三级少妇 | 国产亚洲精品美女 | 西比尔在线观看完整视频高清 | 超碰在线观看免费版 | av资源站 | 国产麻豆一区二区 | 都市激情 亚洲 | 国产中文字幕三区 | 成人午夜影片 | 内射一区二区 | 亚洲国产日韩在线观看 | 中文字幕一区二区三区精华液 | 国产一区二区三区精品视频 | 日美韩一区二区三区 | 中文字幕女同女同女同 | 亚洲超碰在线 | 爱搞逼综合网 | 国产精品13p | 午夜影视网 | 亚洲专区在线播放 | 亚洲欧美国产高清va在线播放 | 成人av动漫在线 | 久久99久久99精品免视看婷婷 | 亚洲大片 | 欧美成人xxxx| 午夜痒痒网 | 欧美老熟妇喷水 | av中文资源 | 夜夜爽影院 | 日本一本一道 | 日本美女黄色一级片 | 日本一区二区三区视频在线播放 | 伊人一级| 色一情一乱一伦一区二区三区 | 久久国产精品-国产精品 | 狠狠干网址 | 中文字幕女优 | 色吟av| 日韩在线播放一区 | 国产黄色免费在线观看 | av不卡在线免费观看 | 亚洲AV无码阿娇国产精品 | 四虎免费在线观看 | 国产aaa视频 | 国产成人免费网站 | 欧美伦理影院 | 成人福利一区 | 日韩一区二区三区在线看 | 免费a级大片 | 啪啪网页 | 久久综合久久88 | 性大片潘金莲裸体 | 丁香婷婷亚洲 | 国产主播在线播放 | 成人免费看视频 | 黄页在线播放 | 啪啪网站视频 | 黑丝一区二区三区 | 黄色网址哪里有 |