MFC-ListCtrl 可编辑重写

MFC下,提供了List Control控件,当选择Report模式时,可以方便的做数据报表之类的应用。类似下图:

MFC-ListCtrl 可编辑重写 - ″x.闷、 - 半边天

 

但是有个不大不小的问题是,当List Control选择可编辑模式时,只有每一行的第一列的单元格才能编辑,而且在默认情况下,当选中的时候,也只有被选中的这一行的第一个单元格才会反色显示~~这未免太BT了~

在网上找了一些相关的帖子,解决整行选中的问题可以采用为List Control控件增加LVS_EX_FULLROWSELECT样式的方法来实现:

 m_Result.SetExtendedStyle(m_Result.GetExtendedStyle() | LVS_EX_GRIDLINES | LVS_EX_FULLROWSELECT | LVS_EX_HEADERDRAGDROP | LVS_EX_TWOCLICKACTIVATE);

 

上面的代码中,LVS_EX_GRIDLINES是希望显示网格;LVS_EX_FULLROWSELECT是希望被选中时整行反色显 示;LVS_EX_HEADERDRAGDROP是让其支持点击表头排序;LVS_EX_TWOCLICKACTIVATE是希望有鼠标在未被选中的行上 移动的时候有一些效果~

 

整行选中的效果算是搞定了,接下来做任意单元格的编辑~

MFC的List Control控件本身是没有办法达到这个目的了,那怎么办呢?一个比较简单的方法是:虚拟出来一个编辑框,覆盖到被编辑的单元格上 :-)

所以,接下来的工作就是,基于CListCtrl类创建一个自己的ListCtrl类,并重载它的鼠标点击事件处理函数,以便判断用户需要修改的单元格,并动态显示或隐藏一个文本框,用来表示需要编译的单元格~

首先创建自己的类:

 

 


 1 #if !defined(AFX_MYLISTCTRL_H__7FDA9396_E298_4F10_B778_EB8ADFD82F9A__INCLUDED_)
 2#define AFX_MYLISTCTRL_H__7FDA9396_E298_4F10_B778_EB8ADFD82F9A__INCLUDED_
 3
 4#if _MSC_VER > 1000
 5#pragma once
 6#endif // _MSC_VER > 1000
 7// MyListCtrl.h : header file
 8//
 9#define IDC_MY_LIST_EDITBOX 0xffff
10
11#define MLSM_ITEMCHANGED (WM_USER + 200)
12/////
13// CMyListCtrl window
14
15class CMyListCtrl : public CListCtrl
16{
17// Construction
18public:
19 CMyListCtrl();
20
21// Attributes
22public:
23// Operations
24public:
25
26// Overrides
27 // ClassWizard generated virtual function overrides
28 //{{AFX_VIRTUAL(CMyListCtrl)
29 public:
30 virtual BOOL PreTranslateMessage(MSG* pMsg);
31 //}}AFX_VIRTUAL
32
33// Implementation
34public:
35 virtual ~CMyListCtrl();
36
37 // Generated message map functions
38protected:
39 CEdit m_EditItem;
40 int m_Row;
41 int m_Col;
42 //{{AFX_MSG(CMyListCtrl)
43 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
44 afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
45 //}}AFX_MSG
46
47 DECLARE_MESSAGE_MAP()
48}
;
49
50/////
51
52//{{AFX_INSERT_LOCATION}}
53// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
54
55#endif // !defined(AFX_MYLISTCTRL_H__7FDA9396_E298_4F10_B778_EB8ADFD82F9A__INCLUDED_)

 其中需要重载或定义的关键的几个成员:

 CEdit m_EditItem;
 int m_Row;
 int m_Col;
 //{{AFX_MSG(CMyListCtrl)
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);

virtual BOOL PreTranslateMessage(MSG* pMsg);

m_EditItem是用来做编辑动作的文本框;

m_Row和m_Col用来标识需要编辑的单元格,以便在不同的成员函数之间传递;

OnLButtonDown用来处理鼠标左键单击事件;

OnLButtonDblClk用来处理鼠标左键双击事件;

PreTrahslateMessage函数用来截获按键事件,主要用来截获回车和ESC键,表示在编辑过程中确认修改或者取消修改

 

在鼠标左键双击事件中,主要的任务是需要判断被双击的单元格,如果单元格有效,则需要进入编辑模式,并显示文本框用来响应用户的输入,代码如下:

 


 1void CMyListCtrl::OnLButtonDblClk(UINT nFlags, CPoint point)
 2{
 3 // TODO: Add your message handler code here and/or call default
 4 LVHITTESTINFO hi;
 5 hi.pt = point;
 6
 7 if(SubItemHitTest(&hi) != -1 )
 8 {
 9  m_Row = hi.iItem;
10  m_Col = hi.iSubItem;
11  if(m_EditItem.m_hWnd == NULL)
12  {
13   RECT rect;
14   rect.left = rect.top = 0;
15   rect.bottom = 20;
16   rect.right = 100;
17   m_EditItem.Create(WS_CHILD | ES_LEFT | WS_BORDER | ES_AUTOHSCROLL | ES_WANTRETURN | ES_MULTILINE, rect, this, IDC_MY_LIST_EDITBOX);
18   m_EditItem.SetFont(this->GetFont(), FALSE);
19  }

20  CRect rect;
21  GetSubItemRect(hi.iItem, hi.iSubItem, LVIR_BOUNDS, rect);
22  m_EditItem.SetWindowText(this->GetItemText(hi.iItem, hi.iSubItem));
23  m_EditItem.MoveWindow(&rect, TRUE);
24  m_EditItem.ShowWindow(1);
25    }

26 CListCtrl::OnLButtonDblClk(nFlags, point);
27}

 

在鼠标单击事件中,我们需要判断用户单击的是不是其他的单元格,如果是,表示用户希望退出编辑模式了,此时,需要保存编辑之后的文本:


 1void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
 2{
 3 // TODO: Add your message handler code here and/or call default
 4 if(m_EditItem.m_hWnd != NULL)
 5 {
 6  m_EditItem.ShowWindow(0);
 7  if(m_Row != -1)
 8  {
 9   CString ItemText;
10   m_EditItem.GetWindowText(ItemText);
11   this->SetItemText(m_Row, m_Col, ItemText);
12   ::PostMessage(GetParent()->m_hWnd, MLSM_ITEMCHANGED, (WPARAM)MAKELONG(m_Row, m_Col), (LPARAM)this->m_hWnd);
13  }

14 }

15 m_Col = m_Row = -1;
16 CListCtrl::OnLButtonDown(nFlags, point);
17}

在PreTranslateMessage函数中,需要截获按键时间中的回车键和ESC键,并保存或取消编辑:


 1BOOL CMyListCtrl::PreTranslateMessage(MSG* pMsg)
 2{
 3 // TODO: Add your specialized code here and/or call the base class
 4 BOOL bHandledMsg = FALSE;
 5
 6 if(pMsg->hwnd == m_EditItem.m_hWnd)
 7 {
 8  switch (pMsg->message)
 9  {
10   case WM_KEYDOWN:
11   {
12    switch (pMsg->wParam)
13    {
14     case VK_RETURN://回车
15      if(m_Row != -1)
16      {
17       CString ItemText;
18       m_EditItem.GetWindowText(ItemText);
19       this->SetItemText(m_Row, m_Col, ItemText);
20       ::PostMessage(GetParent()->m_hWnd, MLSM_ITEMCHANGED, (WPARAM)MAKELONG(m_Row, m_Col), (LPARAM)this->m_hWnd);
21      }

22     case VK_ESCAPE://ESC键
23      m_EditItem.ShowWindow(0);
24      m_Col = m_Row = -1;
25      bHandledMsg = TRUE;
26      break;
27     default:
28      break;
29    }

30   }
// case WM_KEYDOWN
31   break;
32   default:
33    break;
34  }
// switch(pMsg->message)
35 }
// if(pMsg->hwnd
36 return (bHandledMsg ? TRUE : CListCtrl::PreTranslateMessage(pMsg));          
37}

OK,一个可以支持编辑的List Control控件就制作完成了,试试吧 :-)

MFC是Microsoft Foundation Classes的缩写,是微软为了简化Windows编程而开发的一套C++类库。ListCtrlMFC中的一个控件,用于显示和编辑数据的列表。 要在MFC中实现可编辑ListCtrl控件,可以按照以下步骤进行操作: 1. 在对话框资源中添加一个ListCtrl控件,并设置其属性,如样式、列数等。可以使用控件向导来简化这一过程。 2. 在对话框类的头文件中声明一个ListCtrl对象,用于对控件进行操作。例如,在CDialog派生类中添加如下成员变量: ```cpp CListCtrl m_listCtrl; ``` 3. 在OnInitDialog函数中获取ListCtrl控件的指针,并进行初始化操作。例如: ```cpp m_listCtrl.SubclassDlgItem(IDC_LISTCTRL, this); //将控件与IDC_LISTCTRL关联起来 m_listCtrl.InsertColumn(0, _T("列1"), LVCFMT_LEFT, 100); //插入列 ``` 4. 通过ListCtrl对象的成员函数,可以实现对控件中的数据进行操作。例如,添加一行数据的代码如下: ```cpp m_listCtrl.InsertItem(0, _T("数据1")); //在第0行插入一行数据 m_listCtrl.SetItemText(0, 1, _T("数据2")); //设置第0行、第1列的数据 ``` 5. 若要实现可编辑功能,可以通过响应鼠标双击、单击或其他事件,在合适的位置进行编辑操作。例如,在双击某一项时弹出对话框进行编辑: ```cpp int index = m_listCtrl.GetSelectionMark(); //获取当前选中的项 CString data = m_listCtrl.GetItemText(index, 1); //获取选中项的数据 CEditDialog editDlg; //自定义的对话框类 editDlg.m_editCtrl.SetWindowText(data); //将数据显示在对话框的编辑框中 if (editDlg.DoModal() == IDOK) { CString newData; editDlg.m_editCtrl.GetWindowText(newData); //获取对话框中编辑框的数据 m_listCtrl.SetItemText(index, 1, newData); //更新ListCtrl控件中的数据 } ``` 通过以上步骤,就可以实现在MFC中可编辑ListCtrl控件。需要注意的是,在实际应用过程中可能还需要处理其他事件、进行数据校验等操作,具体实现可根据需求进行扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值