原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/2019/0905/629.html
这个项目中需求常州微信小程序开发用MFC完成一个界面功用:listctrl中程度添加按钮。
MFC自身的listctrl控件只能显现简单的文本,简单的添加按钮也不是一两句代码能处理的问题,从这方面讲,MFC开发界面真是不得已而为之。
由于需求的按钮数目是不肯定的,所以只能是动态创立,然后再依据listctrl控件的位置计算出按钮应该放置的位置,然后将按钮挪动到指定坐标。
对MFC里面的类和关系,我并不熟习,所以花了很长时间搜索,最终在下载的好几个版本的代码中找了一个根本可用的,修正开发。
一、 针对我们需求管理本人动态创立的按钮,所以我们自定义了一个CButton的子类。
1
2class CButtonEx : public CButton
3{
4 DECLARE_DYNAMIC(CButtonEx)
5
6public:
7 CButtonEx();
8 CButtonEx( int nItem, int nSubItem, CRect rect, HWND hParent,void * pData );
9 virtual ~CButtonEx();
10
11protected:
12 DECLARE_MESSAGE_MAP()
13public:
14 afx_msg void OnBnClicked(); //点击响应函数
15 int m_inItem; //所属listctrl的行
16 int m_inSubItem; //所属listctrl的列
17 CRect m_rect; //按钮所在的位置
18 HWND m_hParent; //按钮的父窗口
19 BOOL bEnable;
20 void * m_pData; //按钮带的用户自定义数据
21};
1CButtonEx::CButtonEx( int nItem, int nSubItem, CRect rect, HWND hParent,void * pData )
2{
3 m_inItem = nItem;
4 m_inSubItem = nSubItem;
5 m_rect = rect;
6 m_hParent = hParent;
7 bEnable = TRUE;
8 m_pData = pData;
9}
按钮点击的响应逻辑在OnBnClicked函数中。之所以参加m_pData成员变量,是常州网站开发建设便于寄存用户自定义数据,这样就能够在OnBnClicked函数中依据自定义变量做出相应的处置。
二、自定义listctrl子类
1#pragma once
2
3#include "ButtonEx.h"
4#include
5using namespace std;
6
7typedef map<int,CButtonEx*> button_map;
8// CListCtrlEx
9
10class CListCtrlEx : public CListCtrl
11{
12 DECLARE_DYNAMIC(CListCtrlEx)
13
14public:
15 CListCtrlEx();
16 virtual ~CListCtrlEx();
17
18protected:
19 DECLARE_MESSAGE_MAP()
20
21public:
22 //动态创立Button
23 void createItemButton( int nItem, int nSubItem, HWND hMain,LPCTSTR lpszCaption ,void * pData);
24 //释放创立的Button
25 void release();
26 void deleteItemEx( int nItem );
27 button_map m_mButton;
28
29public:
30 UINT m_uID;
31 CFont font ; //按钮上面的字体
32 void updateListCtrlButtonPos(); //更新按钮的位置
33 //void enableButton( BOOL bFlag, int iItem );
34 //重载程度滚动条滚动函数
35 afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
36};
CListCtrlEx完成如下:
1CListCtrlEx::CListCtrlEx()
2{
3 m_uID = 0;
4
5 font.CreatePointFont(100,"宋体");
6}
7
8CListCtrlEx::~CListCtrlEx()
9{
10 release();
11}
然后是创立按钮的逻辑,留意我游戏开发运营这里是在ListCtrl控件中程度添加按钮(同一行的每一列),而不是垂直(同一列的每一行):
1void 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默许的一点点高。
1void CListCtrlEx::release()
2{
3 button_map::iterator iter = m_mButton.begin();
4 while ( iter != m_mButton.end() )
5 {
6 delete iter->second;
7 iter->second = NULL;
8 iter++;
9 }
10 m_mButton.clear();
11}
当完成以上代码以后,就能够在对话框中添加listctrl控件的成员变量了:CListCtrlEx m_lsPath;
然后在OnInitDialog函数中给listctrl控件添加按钮:
1int 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的程度滚动命令:
1void CListCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
2{
3 // TODO: 在此添加音讯处置程序代码和/或调用默许值
4 CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
5 updateListCtrlButtonPos();
6 //Invalidate(FALSE);
7}
1void CListCtrlEx::updateListCtrlButtonPos()
2{
3 button_map::iterator iter = m_mButton.begin();
4 button_map::iterator itrEnd = m_mButton.end();
5 //调整横向的
6 int posx = GetScrollPos(SB_HORZ);//获得程度滚动条的位置
7 for (;iter != itrEnd;++iter)
8 {
9 CRect rect;
10 rect = iter->second->m_rect;
11 rect.left -= posx;
12 rect.right -= posx;
13 iter->second->ShowWindow( SW_HIDE );
14
15 iter->second->MoveWindow( &rect );
16 iter->second->ShowWindow( SW_SHOW );
17 /*if( iLine < iTopIndex )
18 {
19 iterUp->second->ShowWindow( SW_HIDE );
20 }*/
21 }
22 return;
23}
这里操作的过程是:获得控件程度滚动条的位置,然后将一切按钮的程度坐标左移响应的值。其实这里能够优化一下:判别只要那些按钮会被显现才处置,其他的并不需求处置,例如:
1void CListCtrlEx::updateListCtrlButtonPos()
2{
3 button_map::iterator iter = m_mButton.begin();
4 button_map::iterator itrEnd = m_mButton.end();
5
6 CRect rect;
7 GetClientRect(rect);
8 LONG width = rect.right;
9 //调整横向的
10 int posx = GetScrollPos(SB_HORZ);//获得程度滚动条的位置
11 for (;iter != itrEnd;++iter)
12 {
13 iter->second->ShowWindow( SW_HIDE );
14
15 rect = iter->second->m_rect;
16 rect.left -= posx;
17 rect.right -= posx;
18 if (rect.right > 0)
19 {
20 if (rect.left > width)
21 {
22 //其他的都超出了显现范围
23 break;
24 }
25 iter->second->MoveWindow( &rect );
26 iter->second->ShowWindow( SW_SHOW );
27 }
28
29 /*if( iLine < iTopIndex )
30 {
31 iterUp->second->ShowWindow( SW_HIDE );
32 }*/
33 }
34 return;
35}
这样,按钮就能正确刷新了。
不过,还有一个小问题:在拖动滚动条时,我们发现界面有些闪烁。
上篇:上一篇:为列表框控件List Control设置行高
下篇:下一篇:MFC ListControl完成复选框全选、反选