现在的位置: 首页 > 综合 > 正文

MFC中CImageList类的封装与原理

2019年03月10日 ⁄ 综合 ⁄ 共 1774字 ⁄ 字号 评论关闭

MFC写程序还是比SDK方便多了,虽然和C#等其他语言还是要麻烦不少。MFC给控件添加图标就很容易实现,使用CImageList类就可以了。

首先创建一个CImageList变量,然后添加一系列图标或者位图,最后将控件与CImageList关联就行了。

例如,给CTreeCtrl节点添加图标:

m_ImgList.Create(16, 16, ILC_COLOR16, 4, 2) ;
	m_treeCtrl.SetImageList(&m_ImgList, TVSIL_NORMAL) ;
	m_ImgList.Add(AfxGetApp()->LoadIcon(IDI_ICON0)) ;
	m_ImgList.Add(AfxGetApp()->LoadIcon(IDI_ICON1)) ;
	m_ImgList.Add(AfxGetApp()->LoadIcon(IDI_ICON2)) ;
	m_ImgList.Add(AfxGetApp()->LoadIcon(IDI_ICON3)) ;
	HTREEITEM hRoot = m_treeCtrl.InsertItem(_T("Root"), 0, 0) ;
	m_treeCtrl.InsertItem(_T("11"), 1, 1, hRoot) ;
	m_treeCtrl.InsertItem(_T("12"), 2, 2, hRoot, TVI_FIRST) ;
	m_treeCtrl.InsertItem(_T("13"), 3, 0, hRoot, TVI_SORT) ;   //参数的含义分别是 节点显示名,节点显示时的图标,节点选择时的图标,要在哪个节点下插入节点,插入的顺序(如最后一个,第一个,或者排列)

效果如下:

现在要讨论的是,为什么感觉如此简单易行?是不是MFC做了很高端的封装?抱着打破砂锅问到底的态度看了看MFC代码,发现竟然只是封装了SDK函数,根本没有涉及其他的高深技术,也就是说利用SDK完全可以做到,只不过麻烦一点。

以m_treeCtrl.InsertItem(_T("13"), 3, 0, hRoot, TVI_SORT) 举例,

HTREEITEM CTreeCtrl::InsertItem(UINT nMask, LPCTSTR lpszItem, int nImage,
	int nSelectedImage, UINT nState, UINT nStateMask, LPARAM lParam,
	HTREEITEM hParent, HTREEITEM hInsertAfter)
{
	ASSERT(::IsWindow(m_hWnd));
	TVINSERTSTRUCT tvis;
	tvis.hParent = hParent;
	tvis.hInsertAfter = hInsertAfter;
	tvis.item.mask = nMask;
	tvis.item.pszText = (LPTSTR) lpszItem;
	tvis.item.iImage = nImage;
	tvis.item.iSelectedImage = nSelectedImage;
	tvis.item.state = nState;
	tvis.item.stateMask = nStateMask;
	tvis.item.lParam = lParam;
	return (HTREEITEM)::SendMessage(m_hWnd, TVM_INSERTITEM, 0, (LPARAM)&tvis);
}

人家仍然是发送的SDK消息,一目了然。那么MFC又是怎么封装CImageList和关联控件的呢?

查看代码发现,CImageList维护的是一个HIMAGELIST句柄。API函数ImageList_Create, ImageList_Add就可以对HIMAGELIST句柄创建和添加元素,CImageList对象的创建和添加实际上也是对HIMAGELIST的操作,即封装了SDK代码。与控件关联也是发送SDK消息:SendMessage(m_hWnd, TVM_SETIMAGELIST, (WPARAM)nImageList,
(LPARAM)pImageList->GetSafeHandle()))。也就是说,SDK提供了相关的接口,MFC只是封装了代码而已。

所以,MFC并不是创造性的达到某种技术效果,他很大程度上只是封装SDK代码。知道了这些MFC也就不再神秘了。

抱歉!评论已关闭.