RSS

Customizing CListCtrl

19 Dec

Hi Friends,

Today I was trying to build an application for the customer in which I needed to give them a list. So I chose “CListCtrl“.
But when they changed their requirement and wanted to edit the list, It became a painful job to perform such task because List-control only allowes to edit the first item of the list.

So as a solution I designed my own class by extending CListCtrl. Frankly Its very easy to customize List-Control.
Following are the steps you would have to take.

1.) Derive the ClistCtrl Class.

2.) Override three functions

  • MyListCtrl::OnBeginLabelEdit()

  • MyListCtrl::OnEndLabelEdit()

  • MyListCtrl::onLButtonDown()


3.) Derive the class CEdit .

4.) Override one function.

  • cMyEdit::OnWindowPosChanging()




Following is the code that I used to do it..

Header File(MyListCtrl.h)
//Inheriting CEdit class.
class cMyEdit: public CEdit
{
public:
int m_x;
int m_y;
public:
DECLARE_MESSAGE_MAP()
afx_msg void OnWindowPosChanged(WINDOWPOS* lpwndpos);
afx_msg void OnWindowPosChanging(WINDOWPOS* lpwndpos);
};
// Inheriting CListCtrl Class.
class MyListCtrl:public CListCtrl{
public:
//This CEdit is placed on the top of the subItem whenever editing is        required.
cMyEdit m_editWnd;
//It contains the current Item of which subItem is being edited.
int m_item;
//This is the subItem that is being edited.
int m_subitem;
MyListCtrl();
DECLARE_MESSAGE_MAP()
//Total Events that has to be overridden.
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnLvnBeginlabeledit(NMHDR *pNMHDR, LRESULT    *pResult);
afx_msg void OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnPaint();
};
End Header
Source File( MyListCtrl.cpp)

#pragma once
#include "stdafx.h"
#include "MyListCtrl.h"
#include ".\mylistctrl.h"
MyListCtrl::MyListCtrl()
{
m_item = 0;
m_subitem = 0;
}
BEGIN_MESSAGE_MAP(MyListCtrl, CListCtrl)
ON_WM_LBUTTONDOWN()
ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnLvnBeginlabeledit)
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnLvnEndlabeledit)
ON_WM_PAINT()
END_MESSAGE_MAP()
void MyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
LVHITTESTINFO lvhit;
lvhit.pt = point;
int item = SubItemHitTest(&lvhit);
//if (over a subitem)
if (item != -1 && lvhit.iSubItem && (lvhit.flags &
LVHT_ONITEM ))
{
//mouse click outside the editbox in an already
//editing cell cancels editing
if (m_subitem == lvhit.iSubItem && item == m_item)
{
CListCtrl::OnLButtonDown(nFlags, point);
}
else
{
CListCtrl::OnLButtonDown(nFlags, point);
m_subitem = lvhit.iSubItem;
m_item = item;
EditLabel(item);
}
}
else
CListCtrl::OnLButtonDown(nFlags, point);
}
void MyListCtrl::OnLvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
// TODO: Add your control notification handler code here
//if (subitem selected for editing)
if (m_subitem)
{
ASSERT(m_item == pDispInfo->item.iItem);
CRect subrect;
GetSubItemRect( pDispInfo->item.iItem, m_subitem, LVIR_BOUNDS , subrect );
//get edit control and subclass
HWND hWnd=(HWND)SendMessage(LVM_GETEDITCONTROL);
ASSERT(hWnd!=NULL);
VERIFY(m_editWnd.SubclassWindow(hWnd));
//move edit control text 1 pixel to the right of org label,
//as Windows does it...
m_editWnd.m_x=subrect.left + 6;
m_editWnd.SetWindowText(GetItemText
(pDispInfo->item.iItem,m_subitem));
//hide subitem text so it don't show if we delete some
//text in the edit control
//OnPaint handles other issues also regarding this
CRect rect;
GetSubItemRect(pDispInfo->item.iItem,m_subitem,
LVIR_LABEL ,rect);
CDC* hDc = GetDC();
hDc->FillRect(rect,&CBrush(::GetSysColor(COLOR_WINDOW)));
ReleaseDC(hDc);
}
*pResult = 0;
}
//Saving the Changes
void MyListCtrl::OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
// TODO: Add your control notification handler code here
LV_ITEM *plvItem = &pDispInfo->item;
//if (end of sub-editing) do cleanup
if (m_subitem)
{
//plvItem->pszText is NULL if editing canceled
if (plvItem->pszText != NULL )
SetItemText(plvItem->iItem,m_subitem,
plvItem->pszText);
VERIFY(m_editWnd.UnsubclassWindow()!=NULL);
m_subitem = 0;
//always revert to org label (Windows thinks we are editing
//the leftmost item)
*pResult = 0;
}
else
//return: update label on leftmost item
*pResult = 1;
}
// Make sure that first Item is not getting invisible.
void MyListCtrl::OnPaint()
{
//CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
if (m_subitem)
{
CRect rect;
CRect editrect;
GetSubItemRect(m_item,m_subitem,LVIR_LABEL,
rect);
m_editWnd.GetWindowRect(editrect);
ScreenToClient(editrect);
//block text redraw of the subitems text (underneath the
//editcontrol)
//if we didn't do this and deleted some text in the edit
//control, the subitems original label would show
if (editrect.right < rect.right)
{
rect.left = editrect.right ;
ValidateRect(rect);
}
//block filling redraw of leftmost item (caused by FillRect)
GetItemRect(m_item, rect,LVIR_LABEL );
ValidateRect(rect);
}
// Do not call CListCtrl::OnPaint() for painting messages
CListCtrl::OnPaint();
}
//*****************************************
BEGIN_MESSAGE_MAP(cMyEdit, CEdit)
ON_WM_WINDOWPOSCHANGING()
END_MESSAGE_MAP()
'
void cMyEdit::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
CEdit::OnWindowPosChanging(lpwndpos);
lpwndpos->x = m_x;
// TODO: Add your message handler code here
}
End Source

Now You can use this Customized List-control in your application, with the subitem editing enabled.

For any clarification Just feel free to ask.
And one last thing, Don’t forget to leave a comment if it helped you or for any suggestion.

Blogged with the Flock Browser</div

Advertisements
 
9 Comments

Posted by on December 19, 2008 in TechIssues

 

Tags: , , ,

9 responses to “Customizing CListCtrl

  1. Jean Filion

    February 2, 2009 at 12:57 pm

    Sir,

    I want to thank you for your article on the MyListCtrl subitem editing.

    You have saved me days of agony.

    I plugged in your code, and it worked.

    Thank you !!!

    Jean

     
  2. Bob Duffy

    March 28, 2009 at 3:03 am

    Ditto!! It just works. Saved me _hours_ of frying my brain…

    –Bob

     
    • ybhuppi

      November 23, 2009 at 5:28 am

      my pleasure

       
  3. tina

    November 19, 2009 at 12:30 pm

    Thank you soooooooo much.

     
    • ybhuppi

      November 23, 2009 at 5:28 am

      Welcome 🙂

       
  4. cedrix

    July 23, 2012 at 1:18 pm

    Thank you for this post! I just have a question: is it normal that while editing a cell, the cell content of the first column disappear?

     
    • ybhuppi

      July 29, 2012 at 12:17 pm

      No. It should not hide the first column’s content. There might be anything going wrong with your code.

       
  5. willynt

    April 3, 2013 at 7:56 am

    Same as cedrix, fist col content disappear while editing other columns… on win7 and win8. Any suggestions?

     
  6. Tatti

    December 1, 2014 at 9:25 pm

    Thank you so much for this article. You help me. You are my hero))))

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s