listctrl

ListCtrlEx.h


/************************************************************************
作者:luxintian(mail:luxintian@sina.com,QQ:383467500)


本类是在
Lee Nowotny的gxListCtrl类
(详见例子http://www.codeproject.com/listctrl/listeditor.asp)

Author的CComboListCtrl类
(
的基础上经过改就而成主要修改如下:
1,重载了ClistCtrl::InsertColumn两个函数,在该函数中添加了两个参数用来决定
某一项是使用文本框还是组合框,如果是组合框,则用一个CStringArray类的指针作
为参数,用的时候只要在主程序添加一个CStringArray的变量,并为该变量添加字符
串,就可以在相应的的组合框中添加了CStringArray变量中的字符串数组
2,在列表控件中的内容改变后向主窗体发送了了WM_ITEM_CHANGED消息,消息中
WPARAM参数保存所改变的项,LPARAM参数保存所改变的子项


************************************************************************/
#if !defined(AFX_LISTCTRLEX_H__20F0FD03_A78E_484D_BBFC_BA357CC87C68__INCLUDED_)
#define AFX_LISTCTRLEX_H__20F0FD03_A78E_484D_BBFC_BA357CC87C68__INCLUDED_


#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// ListCtrlEx.h : header file
//
#include <afxtempl.h>


#define COLUMN_STYLE_GENERAL 0x00000000
#define COLUMN_STYLE_EDIT 0x00000001
#define COLUMN_STYLE_COMBOBOX 0x00000002


#define WM_ITEM_CHANGED WM_USER+8
//
typedef struct tagSUBITEMINFO
{
tagSUBITEMINFO(){m_dwColumnType=0;m_parComboString=NULL;}
DWORD m_dwColumnType;
CStringArray* m_parComboString;
} SUBITEMINFO,*LPSUBITEMINFO;


/
// CListCtrlEx window


class CListCtrlEx : public CListCtrl
{
// Construction
public:
CListCtrlEx();


// Attributes
public:


// Operations
public:
int InsertColumn( int nCol, const LVCOLUMN* pColumn, DWORD nStyle = COLUMN_STYLE_GENERAL,CStringArray * pStringArray = NULL );
int InsertColumn( int nCol, LPCTSTR lpszColumnHeading, int nFormat = LVCFMT_LEFT, int nWidth = -1, DWORD nStyle = COLUMN_STYLE_GENERAL ,CStringArray * pStringArray = NULL, int nSubItem = -1 );
BOOL DeleteColumn( int nCol );

void ShowSubCtrl(int nItem, int nSubItem,DWORD dwCtrlType = COLUMN_STYLE_EDIT);
int HitTestEx (CPoint& Point, int& nSubItem);

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CListCtrlEx)
//}}AFX_VIRTUAL


// Implementation
public:
virtual ~CListCtrlEx();


// Generated message map functions
protected:
CArray<LPSUBITEMINFO,LPSUBITEMINFO> m_arColumnInfo;

//{{AFX_MSG(CListCtrlEx)
afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
afx_msg void OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult);
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
afx_msg void OnDestroy();
//}}AFX_MSG


DECLARE_MESSAGE_MAP()
};
//


// CListCellEdit window


class CListCellEdit : public CEdit
{
// Construction
public:
CListCellEdit(int nItem, int nSubItem, CString strInitTex);
void SetListItemText();

// Attributes
public:

// Operations
public:

// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CListCellEdit)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~CListCellEdit();

protected:
int m_nItem;
    int m_nSubItem;
    CString m_strInitText;
    BOOL m_bEscape;

// Generated message map functions
//{{AFX_MSG(CListCellEdit)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg void OnNcDestroy();
afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
//}}AFX_MSG

DECLARE_MESSAGE_MAP()
};
/


/
// CListCellCombo window


class CListCellCombo : public CComboBox
{
// Construction
public:
CListCellCombo();
CListCellCombo(int nItem,int nSubItem,CString strWindowText);
// Attributes
public:


// Operations
public:


// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CListCellCombo)
public:
virtual BOOL PreTranslateMessage(MSG* pMsg);
//}}AFX_VIRTUAL


// Implementation
public:
virtual ~CListCellCombo();


// Generated message map functions
protected:
int m_iRowIndex;// Index of the item in the list control
int m_iColumnIndex;// Index of the subitem in the list control
CString m_strWindowText;// Previous selected string value in the combo control

//{{AFX_MSG(CListCellCombo)
afx_msg void OnKillFocus(CWnd* pNewWnd);
afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
afx_msg void OnNcDestroy();
//}}AFX_MSG


DECLARE_MESSAGE_MAP()
};


/
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.


#endif // !defined(AFX_LISTCTRLEX_H__20F0FD03_A78E_484D_BBFC_BA357CC87C68__INCLUDED_)



ListCtrlEx.cpp

// ListCtrlEx.cpp : implementation file
//


#include "stdafx.h"
#include "CListTest.h"
#include "ListCtrlEx.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/
// CListCtrlEx


CListCtrlEx::CListCtrlEx()
{
}


CListCtrlEx::~CListCtrlEx()
{
}




BEGIN_MESSAGE_MAP(CListCtrlEx, CListCtrl)
//{{AFX_MSG_MAP(CListCtrlEx)
ON_WM_HSCROLL()
ON_WM_VSCROLL()
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
ON_WM_LBUTTONDOWN()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/
// CListCtrlEx message handlers


void CListCtrlEx::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default
if (GetFocus() != this) SetFocus();

CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}


void CListCtrlEx::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
// TODO: Add your message handler code here and/or call default
if (GetFocus() != this) SetFocus();

CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}


void CListCtrlEx::ShowSubCtrl(int nItem, int nSubItem,DWORD dwCtrlType/* = COLUMN_STYLE_EDIT*/)
{
    // The returned pointer should not be saved

    // Make sure that the item is visible
    if (!EnsureVisible (nItem, TRUE)) return;

    // Make sure that nCol is valid
    CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0);
    int nColumnCount = pHeader->GetItemCount();
    if (nSubItem >= nColumnCount || GetColumnWidth (nSubItem) < 5)
{
return;
}

    // Get the column offset
    int Offset = 0;
    for (int iColumn = 0; iColumn < nSubItem; iColumn++)
Offset += GetColumnWidth (iColumn);

    CRect Rect;
    GetItemRect (nItem, &Rect, LVIR_BOUNDS);

    // Now scroll if we need to expose the column
    CRect ClientRect;
    GetClientRect (&ClientRect);
    if (Offset + Rect.left < 0 || Offset + Rect.left > ClientRect.right)
    {
CSize Size;
if (Offset + Rect.left > 0)
Size.cx = -(Offset - Rect.left);
else
Size.cx = Offset - Rect.left;
Size.cy = 0;
Scroll (Size);
Rect.left -= Size.cx;
    }

    // Get nSubItem alignment
    LV_COLUMN lvCol;
    lvCol.mask = LVCF_FMT;
    GetColumn (nSubItem, &lvCol);
    DWORD dwStyle;
    if ((lvCol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT)
dwStyle = ES_LEFT;
    else if ((lvCol.fmt & LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT)
dwStyle = ES_RIGHT;
    else dwStyle = ES_CENTER;

    Rect.left += Offset+4;
    Rect.right = Rect.left + GetColumnWidth (nSubItem) - 3;
    if (Rect.right > ClientRect.right)
Rect.right = ClientRect.right;

    dwStyle |= WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;


CString strCulText=GetItemText (nItem, nSubItem);
if(dwCtrlType==COLUMN_STYLE_EDIT)
{
CEdit *pEdit = new CListCellEdit (nItem, nSubItem, strCulText);
pEdit->Create (dwStyle, Rect, this, 101);
}
if(dwCtrlType==COLUMN_STYLE_COMBOBOX)
{
//显示组合框
CRect rc(Rect.left-2,Rect.top-2,Rect.right,Rect.bottom+100);
CComboBox * pCombo = new CListCellCombo(nItem,nSubItem,strCulText);
pCombo->Create(WS_CHILD|WS_VISIBLE|WS_VSCROLL|CBS_DROPDOWNLIST, rc,this, 1);
if(m_arColumnInfo[nSubItem]->m_parComboString)
{
for(int i=0;i<m_arColumnInfo[nSubItem]->m_parComboString->GetSize();i++)
{
pCombo->AddString((*(m_arColumnInfo[nSubItem]->m_parComboString)).GetAt(i));
}
}
  int nIndex=pCombo->FindString(0,strCulText);
if(nIndex!=CB_ERR)
{
pCombo->SetCurSel(nIndex);
}
else
{
pCombo->SetCurSel(-1);
}
}
}


void CListCtrlEx::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) 
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
// TODO: Add your control notification handler code here
LV_ITEM *plvItem = &pDispInfo->item;

    if (plvItem->pszText != NULL)
    {
SetItemText (plvItem->iItem, plvItem->iSubItem, plvItem->pszText);
    }

*pResult = 0;
}


int CListCtrlEx::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, int nWidth, DWORD nStyle,CStringArray * pStringArray, int nSubItem)
{
int nIndex=CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat ,nWidth ,nSubItem );
if(nIndex!=-1)
{
LPSUBITEMINFO pSII=new SUBITEMINFO;
pSII->m_dwColumnType=nStyle;
pSII->m_parComboString=pStringArray;
m_arColumnInfo.InsertAt(nIndex,pSII);
}
return nIndex;
}


int CListCtrlEx::InsertColumn( int nCol, const LVCOLUMN* pColumn, DWORD nStyle,CStringArray * pStringArray)
{
int nIndex=CListCtrl::InsertColumn(nCol,pColumn);
if(nIndex!=-1)
{
LPSUBITEMINFO pSII=new SUBITEMINFO;
pSII->m_dwColumnType=nStyle;
pSII->m_parComboString=pStringArray;
m_arColumnInfo.InsertAt(nIndex,pSII);
}
return nIndex;
}


BOOL CListCtrlEx::DeleteColumn(int nCol )
{
BOOL bResult=CListCtrl::DeleteColumn(nCol);
if(bResult)
{
delete m_arColumnInfo.GetAt(nCol);
m_arColumnInfo.RemoveAt(nCol);
}
return bResult;
}


void CListCtrlEx::OnLButtonDown(UINT nFlags, CPoint point) 
{
CListCtrl::OnLButtonDown(nFlags, point);
// TODO: Add your message handler code here and/or call default
    int nItem;
    int nSubItem;
    if ((nItem = HitTestEx (point, nSubItem)) ==-1)
    {
return;
}

switch(m_arColumnInfo[nSubItem]->m_dwColumnType)
{
case COLUMN_STYLE_GENERAL:
return;
break;
case COLUMN_STYLE_EDIT:
ShowSubCtrl(nItem,nSubItem,COLUMN_STYLE_EDIT);
break;
case COLUMN_STYLE_COMBOBOX:
ShowSubCtrl(nItem,nSubItem,COLUMN_STYLE_COMBOBOX);
break;
default:
break;
}
}


int CListCtrlEx::HitTestEx (CPoint& Point, int& nSubItem)
{
nSubItem = 0;
int ColumnNum = 0;
    int Row = HitTest (Point, NULL);

    // Make sure that the ListView is in LVS_REPORT
    if ((GetWindowLong (m_hWnd, GWL_STYLE) & LVS_TYPEMASK) != LVS_REPORT)
return Row;

    // Get the top and bottom row visible
    Row = GetTopIndex();
    int Bottom = Row + GetCountPerPage();
    if (Bottom > GetItemCount())
Bottom = GetItemCount();
    
    // Get the number of columns
    CHeaderCtrl* pHeader = (CHeaderCtrl*) GetDlgItem(0);
    int nColumnCount = pHeader->GetItemCount();

    // Loop through the visible rows
    for(; Row <= Bottom; Row++)
    {
// Get bounding rect of item and check whether point falls in it.
CRect Rect;
GetItemRect (Row, &Rect, LVIR_BOUNDS);
if (Rect.PtInRect (Point))
{
// Now find the column
for (ColumnNum = 0; ColumnNum < nColumnCount; ColumnNum++)
{
int ColWidth = GetColumnWidth (ColumnNum);
if (Point.x >= Rect.left && Point.x <= (Rect.left + ColWidth))
{
nSubItem = ColumnNum;
return Row;
}
Rect.left += ColWidth;
}
}
    }

    return -1;
}


void CListCtrlEx::OnDestroy() 
{

// TODO: Add your message handler code here
int nCount=m_arColumnInfo.GetSize();
for(int i=0;i<nCount;i++)
{
delete m_arColumnInfo.GetAt(i);
}
m_arColumnInfo.RemoveAll();

CListCtrl::OnDestroy();

}


/
// CListCellEdit


CListCellEdit:: CListCellEdit(int nItem, int nSubItem, CString strInitText)
{
    m_nItem = nItem;
    m_nSubItem = nSubItem;
    m_strInitText = strInitText;
m_bEscape=FALSE;
}


CListCellEdit::~CListCellEdit()
{
}




BEGIN_MESSAGE_MAP(CListCellEdit, CEdit)
//{{AFX_MSG_MAP(CListCellEdit)
ON_WM_KILLFOCUS()
ON_WM_NCDESTROY()
ON_WM_CHAR()
ON_WM_CREATE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/
// CListCellEdit message handlers


void CListCellEdit::OnKillFocus(CWnd* pNewWnd) 
{
CEdit::OnKillFocus(pNewWnd);

// TODO: Add your message handler code here
SetListItemText();


    DestroyWindow();
}


void CListCellEdit::OnNcDestroy() 
{
CEdit::OnNcDestroy();

// TODO: Add your message handler code here
    delete this;
}


BOOL CListCellEdit::PreTranslateMessage(MSG* pMsg) 
{
// TODO: Add your specialized code here and/or call the base class
if( pMsg->message == WM_KEYDOWN )
{
if(pMsg->wParam == VK_RETURN
|| pMsg->wParam == VK_DELETE
|| pMsg->wParam == VK_ESCAPE
|| GetKeyState( VK_CONTROL)
)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
return TRUE;      // DO NOT process further
}
}

return CEdit::PreTranslateMessage(pMsg);
}


void CListCellEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
// TODO: Add your message handler code here and/or call default
if( nChar == VK_ESCAPE || nChar == VK_RETURN)
{
if( nChar == VK_ESCAPE )
m_bEscape = TRUE;
GetParent()->SetFocus();


return;
}


// Resize edit control if needed
// Get text extent
CString str;


GetWindowText( str );
CWindowDC dc(this);
CFont *pFont = GetParent()->GetFont();
CFont *pFontDC = dc.SelectObject( pFont );
CSize size = dc.GetTextExtent( str );
dc.SelectObject( pFontDC );
size.cx += 5;     // add some extra buffer


// Get client rect
CRect rect, parentrect;
GetClientRect( &rect );
GetParent()->GetClientRect( &parentrect );


// Transform rect to parent coordinates
ClientToScreen( &rect );
GetParent()->ScreenToClient( &rect );


// Check whether control needs to be resized
// and whether there is space to grow
if( size.cx > rect.Width() )
{
if( size.cx + rect.left < parentrect.right )
rect.right = rect.left + size.cx;
else
rect.right = parentrect.right;
MoveWindow( &rect );
}

CEdit::OnChar(nChar, nRepCnt, nFlags);
}


int CListCellEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CEdit::OnCreate(lpCreateStruct) == -1)
return -1;

// Set the proper font
CFont* font = GetParent()->GetFont();
SetFont(font);


SetWindowText( m_strInitText );
SetFocus();
SetSel( 0, -1 );

return 0;
}


void CListCellEdit::SetListItemText()
{
    CString Text;
    GetWindowText (Text);


    // Send Notification to parent of ListView ctrl
    LV_DISPINFO dispinfo;
    dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
    dispinfo.hdr.idFrom = GetDlgCtrlID();
    dispinfo.hdr.code = LVN_ENDLABELEDIT;


    dispinfo.item.mask = LVIF_TEXT;
    dispinfo.item.iItem = m_nItem;
    dispinfo.item.iSubItem = m_nSubItem;
    dispinfo.item.pszText = m_bEscape ? NULL : LPTSTR ((LPCTSTR) Text);
    dispinfo.item.cchTextMax = Text.GetLength();
    GetParent()->GetParent()->SendMessage (WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM) &dispinfo);
//如果已经修改则向主窗体发送消息
if(Text.Compare(m_strInitText) !=0 )
{
GetParent()->GetParent()->SendMessage(WM_ITEM_CHANGED,(WPARAM)m_nItem,(LPARAM)m_nSubItem);
}


}
/
// CListCellCombo


CListCellCombo::CListCellCombo()
{
}


CListCellCombo::CListCellCombo(int nItem,int nSubItem,CString strWindowText)
{
m_iRowIndex=nItem;
m_iColumnIndex=nSubItem;
m_strWindowText=strWindowText;
}


CListCellCombo::~CListCellCombo()
{
}




BEGIN_MESSAGE_MAP(CListCellCombo, CComboBox)
//{{AFX_MSG_MAP(CListCellCombo)
ON_WM_KILLFOCUS()
ON_WM_CREATE()
ON_WM_NCDESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/
// CListCellCombo message handlers


BOOL CListCellCombo::PreTranslateMessage(MSG* pMsg) 
{
// TODO: Add your specialized code here and/or call the base class
// If the message if for "Enter" or "Esc"
// Do not process
if (pMsg->message == WM_KEYDOWN)
{
if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_ESCAPE)
{
::TranslateMessage(pMsg);
::DispatchMessage(pMsg);
// DO NOT process further
return TRUE;
}
}

return CComboBox::PreTranslateMessage(pMsg);
}


void CListCellCombo::OnKillFocus(CWnd* pNewWnd) 
{
CComboBox::OnKillFocus(pNewWnd);

// TODO: Add your message handler code here
CString str;
GetWindowText(str);

// Send Notification to parent of ListView ctrl
LV_DISPINFO dispinfo;
dispinfo.hdr.hwndFrom = GetParent()->m_hWnd;
dispinfo.hdr.idFrom = GetDlgCtrlID();
dispinfo.hdr.code = LVN_ENDLABELEDIT;

dispinfo.item.mask = LVIF_TEXT;
dispinfo.item.iItem = m_iRowIndex;
dispinfo.item.iSubItem = m_iColumnIndex;
dispinfo.item.pszText = LPTSTR((LPCTSTR)str);
dispinfo.item.cchTextMax = str.GetLength();

GetParent()->SendMessage(WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo);
//如果已经修改则向主窗体发送消息
if(str.Compare(m_strWindowText) !=0 )
{
GetParent()->GetParent()->SendMessage(WM_ITEM_CHANGED,(WPARAM)m_iRowIndex,(LPARAM)m_iColumnIndex);
}
// Close the control
PostMessage(WM_CLOSE);

}


int CListCellCombo::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
if (CComboBox::OnCreate(lpCreateStruct) == -1)
return -1;

// TODO: Add your specialized creation code here
CFont* pFont = GetParent()->GetFont();
SetFont(pFont);
SetFocus();

return 0;
}


void CListCellCombo::OnNcDestroy() 
{
CComboBox::OnNcDestroy();

// TODO: Add your message handler code here
delete this;
}



DLG.H

CStringArray m_template;
CStringArray m_IsM;

DLG.CPP



void CCListTestDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
m_template.Add("COM1");
m_template.Add("COM2");
m_template.Add("COM3");
m_template.Add("COM4");
m_IsM.Add("Y");
m_IsM.Add("N");
m_list.InsertColumn(0,"ID",LVCFMT_CENTER,60);
m_list.InsertColumn(1,"任务",LVCFMT_CENTER,60);
m_list.InsertColumn(2,"模板",LVCFMT_CENTER,60,COLUMN_STYLE_COMBOBOX,&m_template);
m_list.InsertColumn(3,"是否多用",LVCFMT_CENTER,60,COLUMN_STYLE_COMBOBOX,&m_IsM);
// m_list.InsertColumn(3,"87iuhgghj",LVCFMT_CENTER,60,COLUMN_STYLE_COMBOBOX,&m_arString);
CString id("");
for(int i = 0; i < 10; i++)
{
id.Format("%d",i);
m_list.InsertItem(i,id);
m_list.SetItemText(i,0,id);
m_list.SetItemText(i,1,id);
}

}




void CCListTestDlg::OnBnClickedCancel()
{
MessageBox(m_list.GetItemText(0,2));
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值