MFC-ListCtrl 可编辑重写

来源:互联网 发布:贰捌佬新域名 编辑:程序博客网 时间:2024/05/16 16:16

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

但是有个不大不小的问题是,当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)

29public:
30virtual BOOL PreTranslateMessage(MSG*
pMsg);
31//
}}AFX_VIRTUAL
32

33// Implementation

34public:
35virtual ~
CMyListCtrl();
36

37// Generated message map functions

38protected:
39
CEdit m_EditItem;
40int
m_Row;
41int
m_Col;
42//{{AFX_MSG(CMyListCtrl)

43 afx_msgvoid OnLButtonDown(UINT nFlags, CPoint point);
44 afx_msgvoid
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
7if(SubItemHitTest(&hi)!= -1 )
8{
9 m_Row= hi.iItem;
10 m_Col= hi.iSubItem;
11if(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
4if(m_EditItem.m_hWnd!= NULL)
5{
6 m_EditItem.ShowWindow(0);
7if(m_Row != -1)
8{
9 CString ItemText;
10 m_EditItem.GetWindowText(ItemText);
11this->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
6if(pMsg->hwnd== m_EditItem.m_hWnd)
7{
8switch (pMsg->message)
9{
10case WM_KEYDOWN:
11{
12switch (pMsg->wParam)
13{
14case VK_RETURN://回车
15if(m_Row != -1)
16{
17 CString ItemText;
18 m_EditItem.GetWindowText(ItemText);
19this->SetItemText(m_Row, m_Col, ItemText);
20 ::PostMessage(GetParent()->m_hWnd, MLSM_ITEMCHANGED, (WPARAM)MAKELONG(m_Row, m_Col), (LPARAM)this->m_hWnd);
21 }

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

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

 

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

0 0
原创粉丝点击