分享

VC++6.0CListCtrl控件中添加编辑框和下拉列表框

 牛人的尾巴 2014-11-19

VC++6.0CListCtrl控件中添加编辑框和下拉列表框  

2007-12-29 15:38:53|  分类: 默认分类 |举报 |字号 订阅

      前段时间一个VC++6的开发任务中,打算在CListCtrl控件中添加编辑框和下拉列表框,以便扩展下拉列表框的功能.因为VC++6的CListCtrl控件默认行为只能浏览,不能编辑每一项,而且每一下也没有下拉列表框的样式,要改变这种样式,只能自己编码,因自己水平有限,只能上网求助.上网搜索一翻,终于找到!是一个外国人写的,真得很佩服他的水平,通过代码可以看出他对VC的熟悉程度.

      解决方法就是从CListCtrl派生自己的新类,在自己得派生类里添加这些功能,并添加相应的事件响应函数,这里不多说了,列出源文件中的代码,请大家自己琢磨吧.

头文件:

#if !defined(AFX_MYLISTCTRL_H__D5DCAA3F_54C1_4B6B_85FD_C36648DDA223__INCLUDED_)
#define AFX_MYLISTCTRL_H__D5DCAA3F_54C1_4B6B_85FD_C36648DDA223__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// MyListCtrl.h : header file
//
//#define MAX_LISTCTRL_COLUMNS 33
#include <afxtempl.h>

class CInPlaceCombo;
class CInPlaceEdit;
#define WM_VALIDATE WM_USER+0X7FFD
#define WM_SET_ITEMS WM_USER+0X7FFC
/////////////////////////////////////////////////////////////////////////////
// CMyListCtrl window

class CMyListCtrl : public CListCtrl
{
// Construction
public:
 //typedef enum {MODE_READONLY,MODE_DIGITAL_EDIT,MODE_TEXT_EDIT,MODE_COMBO} COMBOLISTCTRL_COLUMN_MODE;
 CMyListCtrl();
public:

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

// Implementation
public:
 void EnableHScroll(bool bEnable=TRUE);
 void EnableVScroll(bool bEnable=TRUE);
 void SetValidEditCtrlCharacters(CString& rstrValidCharacters);
 void SetReadOnlyColumns(int iColumnIndex,bool bSet=TRUE);
 void SetComboColumns(int iColumnIndex,bool bSet=TRUE);
 virtual ~CMyListCtrl();

 // Generated message map functions
protected:
 //{{AFX_MSG(CMyListCtrl)
 afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
 afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
 afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
 afx_msg void OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult);
 afx_msg void OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult);
 //}}AFX_MSG

 DECLARE_MESSAGE_MAP()
private:
 void ScrollToView(int iColumnIndex,CRect& obCellRect);
 bool IsReadOnly(int iColumnIndex);
 bool IsCombo(int iColumnIndex);
 void CalculateCellRect(int iColumnIndex,int iRowIndex,CRect& robCellRect);
 CInPlaceEdit* ShowInPlaceEdit(int iRowIndex,int iColumnIndex,CString& rstrCurSelection);
 CInPlaceCombo* ShowInPlaceList(int iRowIndex,int iColumnIndex,CStringList& rComboItemsList,
           CString strCurSelection="",int iSel=-1);
 bool HitTestEx(CPoint & rHitPoint,int * pRowIndex,int * pColumnIndex) const;

 CList<int,int> m_ComboSupportColumnsList;
 CList<int,int> m_ReadOnlyColumnsList;
 CString m_strValidEditCtrlChars;
 DWORD m_dwEditCtrlStyle;
 DWORD m_dwDropDownCtrlStyle;
 //COMBOLISTCTRL_COLUMN_MODE m_modeColumn[MAX_LISTCTRL_COLUMNS];
 //CString m_strValidChars[MAX_LISTCTRL_COLUMNS];
};

/////////////////////////////////////////////////////////////////////////////

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

#endif // !defined(AFX_MYLISTCTRL_H__D5DCAA3F_54C1_4B6B_85FD_C36648DDA223__INCLUDED_)

实现文件:

// MyListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "J2CPS.h"
#include "MyListCtrl.h"
#include "InPlaceCombo.h"
#include "InPlaceEdit.h"

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

#define FIRST_COLUMN             0
#define MIN_COLUMN_WIDTH         10
#define MAX_DROP_DOWN_ITEM_COUNT 10
/////////////////////////////////////////////////////////////////////////////
// CMyListCtrl

CMyListCtrl::CMyListCtrl()
{
 m_ComboSupportColumnsList.RemoveAll();
 m_ReadOnlyColumnsList.RemoveAll();
 m_strValidEditCtrlChars.Empty();
 m_dwEditCtrlStyle=ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_LEFT | ES_NOHIDESEL;
 m_dwDropDownCtrlStyle=WS_BORDER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_AUTOVSCROLL |
        CBS_DROPDOWNLIST | CBS_DISABLENOSCROLL;
}

CMyListCtrl::~CMyListCtrl()
{
 CInPlaceCombo::DeleteInstance();
 CInPlaceEdit::DeleteInstance();
}


BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
 //{{AFX_MSG_MAP(CMyListCtrl)
 ON_WM_HSCROLL()
 ON_WM_VSCROLL()
 ON_WM_LBUTTONDOWN()
 ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndlabeledit)
 ON_NOTIFY_REFLECT(LVN_BEGINLABELEDIT, OnBeginlabeledit)
 //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMyListCtrl message handlers

bool CMyListCtrl::HitTestEx(CPoint &rHitPoint, int *pRowIndex, int *pColumnIndex) const
{
 if(!pRowIndex || !pColumnIndex)
  return FALSE;
 *pRowIndex=HitTest(rHitPoint,NULL);
 if(pColumnIndex)
  *pColumnIndex=0;
 if((GetWindowLong(m_hWnd,GWL_STYLE) & LVS_TYPEMASK)!=LVS_REPORT)
  return FALSE;
 CHeaderCtrl * pHeader=(CHeaderCtrl *)GetDlgItem(0);
 int iColumnCount=pHeader->GetItemCount();
 CRect obCellRect;
 GetItemRect(*pRowIndex,&obCellRect,LVIR_BOUNDS);
 if(obCellRect.PtInRect(rHitPoint))
 {
  for(*pColumnIndex=0;*pColumnIndex<iColumnCount;(*pColumnIndex)++)
  {
   int iColWidth=GetColumnWidth(*pColumnIndex);
   if(rHitPoint.x>=obCellRect.left && rHitPoint.x<=(obCellRect.left+iColWidth))
    return TRUE;
   obCellRect.left+=iColWidth;
  }
 }
 return FALSE;
}

void CMyListCtrl::SetComboColumns(int iColumnIndex, bool bSet)
{
 POSITION Pos=m_ComboSupportColumnsList.Find(iColumnIndex);
 if((Pos==NULL) && bSet)
 {
  m_ComboSupportColumnsList.AddTail(iColumnIndex);
 }
 if((Pos!=NULL) && !bSet)
 {
  m_ComboSupportColumnsList.RemoveAt(Pos);
 }
}

void CMyListCtrl::SetReadOnlyColumns(int iColumnIndex, bool bSet)
{
 POSITION Pos=m_ReadOnlyColumnsList.Find(iColumnIndex);
 if((Pos==NULL) && bSet)
 {
  m_ReadOnlyColumnsList.AddTail(iColumnIndex);
 }
 if((Pos!=NULL) && !bSet)
 {
  m_ReadOnlyColumnsList.RemoveAt(Pos);
 }
}

void CMyListCtrl::SetValidEditCtrlCharacters(CString &rstrValidCharacters)
{
 m_strValidEditCtrlChars=rstrValidCharacters;
}

void CMyListCtrl::EnableVScroll(bool bEnable)
{
 if(bEnable)
 {
  m_dwDropDownCtrlStyle|=WS_VSCROLL;
 }
 else
 {
  m_dwDropDownCtrlStyle&=~WS_VSCROLL;
 }
}

void CMyListCtrl::EnableHScroll(bool bEnable)
{
 if(bEnable)
 {
  m_dwDropDownCtrlStyle|=WS_HSCROLL;
 }
 else
 {
  m_dwDropDownCtrlStyle&=~WS_HSCROLL;
 }
}

CInPlaceCombo* CMyListCtrl::ShowInPlaceList(int iRowIndex, int iColumnIndex, CStringList &rComboItemsList,
           CString strCurSelection, int iSel)
{
 if(!EnsureVisible(iRowIndex,TRUE))
 {
  return NULL;
 }
 CHeaderCtrl* pHeader=static_cast<CHeaderCtrl*>(GetDlgItem(FIRST_COLUMN));
 int iColumnCount=pHeader->GetItemCount();
 if(iColumnIndex>=iColumnCount || GetColumnWidth(iColumnIndex)<MIN_COLUMN_WIDTH)
 {
  return NULL;
 }
 CRect obCellRect(0,0,0,0);
 CalculateCellRect(iColumnIndex,iRowIndex,obCellRect);
 int iHeight=obCellRect.Height();
 int iCount=rComboItemsList.GetCount();
 iCount=(iCount<MAX_DROP_DOWN_ITEM_COUNT)?iCount+MAX_DROP_DOWN_ITEM_COUNT:(MAX_DROP_DOWN_ITEM_COUNT+1);
 obCellRect.bottom+=iHeight*iCount;
 CInPlaceCombo* pInPlaceCombo=CInPlaceCombo::GetInstance();
 pInPlaceCombo->ShowComboCtrl(m_dwDropDownCtrlStyle,obCellRect,this,0,iRowIndex,iColumnIndex,&rComboItemsList,
        strCurSelection,iSel);
 return pInPlaceCombo;
}

CInPlaceEdit* CMyListCtrl::ShowInPlaceEdit(int iRowIndex, int iColumnIndex, CString &rstrCurSelection)
{
 CInPlaceEdit* pInPlaceEdit=CInPlaceEdit::GetInstance();
 CRect obCellRect(0,0,0,0);
 CalculateCellRect(iColumnIndex,iRowIndex,obCellRect);
 pInPlaceEdit->ShowEditCtrl(m_dwEditCtrlStyle,obCellRect,this,0,iRowIndex,iColumnIndex,
          m_strValidEditCtrlChars,rstrCurSelection);
 return pInPlaceEdit;
}

void CMyListCtrl::CalculateCellRect(int iColumnIndex, int iRowIndex, CRect &robCellRect)
{
 GetItemRect(iRowIndex,&robCellRect,LVIR_BOUNDS);
 CRect rcClient;
 GetClientRect(&rcClient);
 if(robCellRect.right>rcClient.right)
 {
  robCellRect.right=rcClient.right;
 }
 ScrollToView(iColumnIndex,robCellRect);
}

bool CMyListCtrl::IsCombo(int iColumnIndex)
{
 if(m_ComboSupportColumnsList.Find(iColumnIndex))
 {
  return TRUE;
 }
 return FALSE;
}

bool CMyListCtrl::IsReadOnly(int iColumnIndex)
{
 if(m_ReadOnlyColumnsList.Find(iColumnIndex))
 {
  return TRUE;
 }
 return FALSE;
}

void CMyListCtrl::ScrollToView(int iColumnIndex, CRect &obCellRect)
{
 CRect rcClient;
 GetClientRect(&rcClient);
 int iColumnWidth=GetColumnWidth(iColumnIndex);
 int iOffSet=0;
 for(int iIndex_=0;iIndex_<iColumnIndex;iIndex_++)
 {
  iOffSet+=GetColumnWidth(iIndex_);
 }
 CSize obScrollSize(0,0);
 if(((iOffSet+obCellRect.left)<rcClient.left) || ((iOffSet+obCellRect.left)>rcClient.right))
 {
  obScrollSize.cx=iOffSet+obCellRect.left;
 }
 else
  if((iOffSet+obCellRect.left+iColumnWidth)>rcClient.right)
  {
   obScrollSize.cx=iOffSet+obCellRect.left+iColumnWidth-rcClient.right;
  }
 Scroll(obScrollSize);
 obCellRect.left-=obScrollSize.cx;
 obCellRect.left+=iOffSet;
 obCellRect.right=obCellRect.left+iColumnWidth;
}

void CMyListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
 if(GetFocus()!=this)
 {
  SetFocus();
 }
 CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar);
}

void CMyListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
 if(GetFocus()!=this)
 {
  SetFocus();
 }
 CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}

void CMyListCtrl::OnLButtonDown(UINT nFlags, CPoint point)
{
 int iColumnIndex=-1;
 int iRowIndex=-1;
 if(!HitTestEx(point,&iRowIndex,&iColumnIndex))
 {
  return;
 }
 CListCtrl::OnLButtonDown(nFlags, point);
 if((GetKeyState(VK_SHIFT) & 0X80) || (GetKeyState(VK_CONTROL) & 0X80))
 {
  return;
 }
 CString strCurSelection=GetItemText(iRowIndex,iColumnIndex);
 if(iRowIndex!=-1)
 {
  UINT flag=LVIS_FOCUSED;
  if((GetItemState(iRowIndex,flag) & flag)==flag)
  {
   if(GetWindowLong(m_hWnd,GWL_STYLE) & LVS_EDITLABELS)
   {
    if(IsCombo(iColumnIndex))
    {
     CStringList obComboItemsList;
     GetParent()->SendMessage(WM_SET_ITEMS,(WPARAM)iColumnIndex,(LPARAM)&obComboItemsList);
     CInPlaceCombo* pInPlaceComboBox=ShowInPlaceList(iRowIndex,iColumnIndex,obComboItemsList,strCurSelection);
     ASSERT(pInPlaceComboBox);
     pInPlaceComboBox->SelectString(-1,strCurSelection);
    }
    else
     if(!IsReadOnly(iColumnIndex))
     {
      CInPlaceEdit* pInPlaceEdit=ShowInPlaceEdit(iRowIndex,iColumnIndex,strCurSelection);
     }
   }
  }
 }
}

void CMyListCtrl::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
 LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
 SetItemText(pDispInfo->item.iItem,pDispInfo->item.iSubItem,pDispInfo->item.pszText);
 GetParent()->SendMessage(WM_VALIDATE,GetDlgCtrlID(),(LPARAM)pDispInfo);
 *pResult = 0;
}

void CMyListCtrl::OnBeginlabeledit(NMHDR* pNMHDR, LRESULT* pResult)
{
 LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
 if(IsReadOnly(pDispInfo->item.iSubItem))
 {
  *pResult=1;
  return;
 }
 *pResult = 0;
}

       最后,VC真的很不错,功能很强,虽然上手不快,但仔细研究,大家会有收获的.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多