这个项目中需要用MFC实现一个界面功能:listctrl中水平添加按钮。
MFC本身的listctrl控件只能显示简单的文本,简单的添加按钮也不是一两句代码能解决的问题,从这方面讲,MFC开发界面真是不得已而为之。
因为需要的按钮数目是不确定的,所以只能是动态创建,然后再根据listctrl控件的位置计算出按钮应该放置的位置,然后将按钮移动到指定坐标。
对MFC里面的类和关系,我并不熟悉,所以花了很长时间搜索,最终在下载的好几个版本的代码中找了一个基本可用的,修改开发。
一、 针对我们需要管理自己动态创建的按钮,所以我们自定义了一个CButton的子类。
按钮点击的响应逻辑在OnBnClicked函数中。之所以加入m_pData成员变量,是便于存放用户自定义数据,这样就可以在OnBnClicked函数中根据自定义变量做出相应的处理。 二、自定义listctrl子类
CListCtrlEx实现如下:
然后是创建按钮的逻辑,注意我这里是在ListCtrl控件中水平添加按钮(同一行的每一列),而不是垂直(同一列的每一行):
1
void CListCtrlEx::createItemButton(
int nItem,
int nSubItem, HWND hMain,LPCTSTR lpszCaption ,
void * pData)
2
{
3 CRect rect;
4 /*if( !EnsureVisible(nItem, TRUE))
5 return ;*/
6
7 GetSubItemRect(nItem, nSubItem, LVIR_BOUNDS, rect);
8 rect.bottom = rect.top + 150;
9 //rect.right = rect.left + 150;
10
11 DWORD dwStyle = WS_CHILD | WS_VISIBLE | BS_MULTILINE;
12 CButtonEx *pButton = new CButtonEx(nItem,nSubItem,rect,hMain,pData);
13 m_uID++;
14
15 pButton->Create(lpszCaption,dwStyle, rect, this, m_uID);
16 //CDC* pDC = pButton->GetDC();
17 //pDC->SetTextColor(RGB(255,0,0));
18 pButton->SetFont(&font);
19
20 // m_mButton.insert( make_pair( nItem, pButton ) ); //纵向添加用
21 m_mButton.insert( make_pair( nSubItem, pButton ) ); //单行横向添加用
22
23 return;
24}
25
上面的代码中,我将按钮的高都设为了150,而不是listctrl默认的一点点高。
当完成以上代码以后,就可以在对话框中添加listctrl控件的成员变量了:CListCtrlEx m_lsPath; 然后在OnInitDialog函数中给listctrl控件添加按钮:
1
int i = 0;
2
m_lsPath.InsertColumn(i,_T(""),LVCFMT_LEFT,150);
3
4
nRow = m_lsPath.InsertItem(0, "tim");
5
6
TCHAR caption[1000] =
{0};
//
标题
7
ImageCfg * pImageCfg =
new ImageCfg;
//
自定义数据
8
m_lsPath.createItemButton(nRow,i++,m_lsPath,caption,pImageCfg);
这样看起来一切很好,但是运行时发现,当按钮较多需要水平滚动条时,拖动水平滚动条并不能正确的显示按钮! 所以我们还需要处理CListCtrlEx的水平滚动命令:
这里操作的过程是:取得控件水平滚动条的位置,然后将所有按钮的水平坐标左移响应的值。其实这里可以优化一下:判断只有那些按钮会被显示才处理,其他的并不需要处理,例如:
这样,按钮就能正确刷新了。 不过,还有一个小问题:在拖动滚动条时,我们发现界面有些闪烁。