可编辑子项的ListCtrl<二>

说明

在上一篇文章:可编辑子项的ListCtrl
我们实现了一个简易版本的可编辑子项的ListCtrl。
本文我们继续增加一个功能,即在ListCtrl中,实现可以直接输入内容的ComboBox。
所以,ListCtrl会存在以下三种可编辑项。
1、可编辑的文本框。
这里写图片描述
2、ComboBox
这里写图片描述
3、可直接输入内容的ComboBox。
这里写图片描述

下载

源码下载
示例程序下载
源码共包含8个文件:

  1. ListCtrlXE.h
  2. ListCtrlXE.cpp
  3. EditLCXE.h
  4. EditLCXE.cpp
  5. ComboLCXE.h
  6. ComboLCXE.cpp
  7. EditInComboLCXE.h
  8. EditInComboLCXE.cpp

使用时,直接#include “ListCtrlXE.h”即可。

部分源码

[ListCtrlXE.h]

#pragma once

#include ".\LCXE\EditLCXE.h"
#include ".\LCXE\ComboLCXE.h"
#include <string>
#include <list>
#include <map>

using std::string;
using std::list;
using std::map;

// 双击客制化消息,在双击控件时会向父窗口发送该消息
// 该消息的WPARAM与LPARAM均为LCXE_LBDC_Data的指针
#define MSG_LCXE_LBTN_DBLCLICK_CUSTOM WM_USER + 0x111

// ComboBox结束消息
// 该消息的WPARAM与LPARAM均为LCXE_ComboEndData的指针
#define MSG_LCXE_COMBO_END WM_USER + 0x112

// EditBox结束消息
// 该消息的WPARAM与LPARAM均为LCXE_EditEndData的指针
#define MSG_LCXE_EDIT_END  WM_USER + 0x113

class CListCtrlXE;

// ListCtrlXE Left Button Double Click Data
struct LCXE_LBDC_Data
{
    int nItem;
    int nSubItem;
    CListCtrlXE* pLCXE;
};

// ListCtrlXE ComboBox End Msg Data
struct LCXE_ComboEndData
{
    int nItem;
    int nSubItem;
    CComboBox* pCombo;
    CListCtrlXE* pLCXE;
};

// ListCtrlXE Edit End Msg Data
struct LCXE_EditEndData
{
    int nItem;
    int nSubItem;
    CEdit* pEdit;
    CListCtrlXE* pLCXE;
};

class CListCtrlXE : public CListCtrl
{
    DECLARE_DYNAMIC(CListCtrlXE)

public:
    CListCtrlXE();
    virtual ~CListCtrlXE();

protected:
    DECLARE_MESSAGE_MAP()

protected:
    afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point);
    afx_msg void OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult);
    afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
    afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);

    afx_msg LRESULT OnEditEnd(WPARAM wParam,LPARAM lParam);
    afx_msg LRESULT OnComboEnd(WPARAM wParam,LPARAM lParam);

    // 显示EditBox
    int ShowEditBox(CEditLCXE* pEdit, bool bShow);

    // 显示ComboBox
    int ShowCombo(CComboLCXE* pCombo, bool bShow);

public:
    // 创建EditBox
    // 注意:请勿对返回的CEdit*执行delete操作
    CEdit* CreateEdit(DWORD dwStyle = ES_AUTOHSCROLL | ES_LEFT | ES_WANTRETURN | WS_BORDER);

    // 创建ComboBox
    // 注意:请勿对返回的CComboBox*执行delete操作
    CComboBox* CreateCombo(DWORD dwStyle = ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_LEFT | CBS_DROPDOWNLIST);

    // 显示EditBox
    int ShowEditBox(CEdit* pEdit);

    // 显示ComboBox
    int ShowCombo(CComboBox* pCombo);

private:
    // 子控件列表
    list<CEditLCXE*>  m_lstEdit;
    list<CComboLCXE*> m_lstCombo;

    // 当前点击项
    int nItem;
    // 当前点击子项
    int nSubItem;

    // 子控件ID
    int m_nCtrlId;
};

[ListCtrlXE.cpp]

// EditableListCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "ListCtrlXE.h"

// CListCtrlXE

IMPLEMENT_DYNAMIC(CListCtrlXE, CListCtrl)

CListCtrlXE::CListCtrlXE()
{
    m_nCtrlId = 1001;
}

CListCtrlXE::~CListCtrlXE()
{
    list<CEditLCXE*>::iterator iterEdit =  m_lstEdit.begin();
    for (; iterEdit != m_lstEdit.end(); ++iterEdit)
    {
        CEditLCXE* pEdit = *iterEdit;
        delete pEdit;
    }

    list<CComboLCXE*>::iterator iterCombo = m_lstCombo.begin();
    for (; iterCombo != m_lstCombo.end(); ++iterCombo)
    {
        CComboLCXE* pCombo = *iterCombo;
        delete pCombo;
    }
}

//-----------------------------------------------------------------------------
// 函数: CreateEdit
// 功能: 创建Edit
// 参数:
//     dwStyle  ------  Edit的风格,默认的风格为ES_AUTOHSCROLL | ES_LEFT | ES_WANTRETURN | WS_BORDER
// 返回值:
//     CEdit*  ------  创建的Edit的指针,创建失败则返回NULL
// 注意:
//     创建的Edit由程序内部进行资源管理,请勿对返回的指针执行delete,DestroyWindow等操作
//-----------------------------------------------------------------------------
CEdit* CListCtrlXE::CreateEdit(DWORD dwStyle)
{
    CEditLCXE* pEdit = new CEditLCXE();
    if (0 == pEdit->Create(dwStyle | WS_CHILD, CRect(0, 0, 0, 0), this, m_nCtrlId++))
    {
        return NULL;
    }
    pEdit->ShowWindow(SW_HIDE);
    pEdit->SetFont(this->GetFont());

    m_lstEdit.push_back(pEdit);

    return pEdit;
}

//-----------------------------------------------------------------------------
// 函数: CreateCombo
// 功能: 创建ComboBox
// 参数:
//     dwStyle  ------  ComboBox的风格,默认的风格为ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_LEFT | CBS_DROPDOWNLIST
// 返回值:
//     CComboBox*  ------  创建的ComboBox的指针,创建失败则返回NULL
// 注意:
//     1.创建的ComboBox由程序内部进行资源管理,请勿对返回的指针执行delete,DestroyWindow等操作
//     2.可创建CBS_DROPDOWN风格的ComboBox
//-----------------------------------------------------------------------------
CComboBox* CListCtrlXE::CreateCombo(DWORD dwStyle)
{
    CComboLCXE *pCombo = new CComboLCXE();
    if (0 == pCombo->Create(dwStyle | WS_CHILD, CRect(0,0,0,0), this, m_nCtrlId++))
    {
        return NULL;
    }
    pCombo->ShowWindow(SW_HIDE);
    pCombo->SetFont(this->GetFont());

    m_lstCombo.push_back(pCombo);

    return pCombo;
}

// 显示EditBox
int CListCtrlXE::ShowEditBox(CEditLCXE* pEdit, bool bShow)
{
    if (NULL == pEdit)
    {
        return -1;
    }

    if (true == bShow)
    {
        if (nItem == -1 || nSubItem == -1)
        {
            return -1;
        }

        CString cstrText = this->GetItemText(nItem, nSubItem);
        CRect rcCtrl(0, 0, 0, 0);
        this->GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rcCtrl);

        pEdit->MoveWindow(&rcCtrl);
        pEdit->ShowWindow(SW_SHOW);
        pEdit->SetWindowText(cstrText);
        pEdit->SetFocus();
        pEdit->SetSel(-1); 
    }
    else
    {
        pEdit->ShowWindow(SW_HIDE);
    }

    return 0;
}

//---------------------------------------------------------
// 函数: ShowEditBox
// 功能: 显示EditBox
// 参数:
//     pEdit  ------  待显示的EditBox的指针,该EditBox必须为调用CListCtrlXE::CreateEdit创建,
//                    否则将不会显示,并且函数返回-1
// 返回值:
//     0   ------  成功
//     -1  ------  失败
//---------------------------------------------------------
int CListCtrlXE::ShowEditBox(CEdit* pEdit)
{
    if (NULL == pEdit)
    {
        return -1;
    }

    // 校验pEdit是否由调用CreateEdit创建的
    bool bFind = false;
    list<CEditLCXE*>::iterator iterEdit =  m_lstEdit.begin();
    for (; iterEdit != m_lstEdit.end(); ++iterEdit)
    {
        if (*iterEdit == (CEditLCXE*)pEdit)
        {
            bFind = true;
            break;
        }
    }
    if (false == bFind)
    {
        return -1;
    }

    // 显示
    return this->ShowEditBox((CEditLCXE*)pEdit, true);
}

// 显示ComboBox
int CListCtrlXE::ShowCombo(CComboLCXE* pCombo, bool bShow)
{
    if (NULL == pCombo)
    {
        return -1;
    }

    if (true == bShow)
    {
        if (nItem == -1 || nSubItem == -1)
        {
            return -1;
        }

        CString cstrText = this->GetItemText(nItem, nSubItem);
        CRect rcCtrl(0, 0, 0, 0);
        this->GetSubItemRect(nItem, nSubItem, LVIR_LABEL, rcCtrl);
        rcCtrl.bottom += 200;

        pCombo->MoveWindow(&rcCtrl);
        pCombo->ShowWindow(SW_SHOW);
        pCombo->SetCurSel(-1);
        pCombo->SetWindowText(cstrText);
        pCombo->SetFocus();

        int nItems = pCombo->GetCount();
        CString cstrComboItemText;
        for (int i = 0; i < nItems; ++i)
        {
            pCombo->GetLBText(i, cstrComboItemText);
            if (cstrText == cstrComboItemText)
            {
                pCombo->SetCurSel(i);
                break;
            }
        }
    }
    else
    {
        pCombo->ShowWindow(SW_HIDE);
    }

    return 0;
}

//-----------------------------------------------------------------------------
// 函数: ShowCombo
// 功能: 显示ComboBox
// 参数:
//     pCombo  ------ 待显示的ComboBox的指针,该ComboBox必须为调用CListCtrlXE::CreateCombo创建,
//                    否则将不会显示,并且函数返回-1
// 返回值:
//     0   ------  成功
//     -1  ------  失败
//-----------------------------------------------------------------------------
int CListCtrlXE::ShowCombo(CComboBox* pCombo)
{
    if (NULL == pCombo)
    {
        return -1;
    }

    // 校验pCombo是否由调用CreateCombo创建
    bool bFind = false;
    list<CComboLCXE*>::iterator iterCombo = m_lstCombo.begin();
    for (; iterCombo != m_lstCombo.end(); ++iterCombo)
    {
        if (*iterCombo == (CComboLCXE*)pCombo)
        {
            bFind = true;
            break;
        }
    }
    if (false == bFind)
    {
        return -1;
    }

    // 显示
    return this->ShowCombo((CComboLCXE*)pCombo, true);
}

BEGIN_MESSAGE_MAP(CListCtrlXE, CListCtrl)
    ON_WM_LBUTTONDBLCLK()
    ON_NOTIFY(HDN_BEGINTRACKA, 0, &CListCtrlXE::OnHdnBegintrack)
    ON_NOTIFY(HDN_BEGINTRACKW, 0, &CListCtrlXE::OnHdnBegintrack)
    ON_WM_HSCROLL()
    ON_WM_VSCROLL()
    ON_MESSAGE(WM_USER_EDIT_END, OnEditEnd)
    ON_MESSAGE(WM_USER_COMBO_END, OnComboEnd)
END_MESSAGE_MAP()

// CListCtrlXE message handlers

LRESULT CListCtrlXE::OnEditEnd(WPARAM wParam, LPARAM lParam)
{
    CEditLCXE* pEdit = (CEditLCXE*)wParam;
    if (NULL == pEdit)
    {
        return 0;
    }

    CString strText;
    pEdit->GetWindowText(strText);
    this->SetItemText(nItem, nSubItem, strText);

    this->ShowEditBox(pEdit, false);

    LCXE_EditEndData data;
    data.nItem = nItem;
    data.nSubItem = nSubItem;
    data.pEdit = pEdit;
    data.pLCXE = this;
    ::SendMessage(this->GetParent()->GetSafeHwnd(), MSG_LCXE_EDIT_END, (WPARAM)&data, (LPARAM)&data);

    return 0;
}

LRESULT CListCtrlXE::OnComboEnd(WPARAM wParam, LPARAM lParam)
{
    CComboLCXE* pCombo = (CComboLCXE*)wParam;
    if (NULL == pCombo)
    {
        return 0;
    }

    DWORD dwStyle = pCombo->GetStyle();
    if ((DWORD)(dwStyle & CBS_DROPDOWNLIST) == (DWORD)CBS_DROPDOWNLIST)
    {
        int nSel = pCombo->GetCurSel();
        CString cstrText;
        if (nSel != -1)
        {
            pCombo->GetLBText(nSel, cstrText);
        }
        this->SetItemText(nItem, nSubItem, cstrText);
    }
    else
    {
        CString cstrText;
        pCombo->GetWindowText(cstrText);
        this->SetItemText(nItem, nSubItem, cstrText);
    }

    this->ShowCombo(pCombo, false);

    LCXE_ComboEndData data;
    data.nItem = nItem;
    data.nSubItem = nSubItem;
    data.pCombo = pCombo;
    data.pLCXE = this;
    ::SendMessage(this->GetParent()->GetSafeHwnd(), MSG_LCXE_COMBO_END, (WPARAM)&data, (LPARAM)&data);

    return 0;
}

void CListCtrlXE::OnLButtonDblClk(UINT nFlags, CPoint point)
{
    // TODO: Add your message handler code here and/or call default
    // 获取双击项
    LVHITTESTINFO lvhti;
    lvhti.pt = point;
    nItem = SubItemHitTest(&lvhti);
    if (nItem == -1)
    {
        return CListCtrl::OnLButtonDblClk(nFlags, point);
    }
    nSubItem = lvhti.iSubItem;
    if (nSubItem == -1)
    {
        return CListCtrl::OnLButtonDblClk(nFlags, point);
    }

    // 向父窗口发送MSG_LCXE_LBTN_DBLCLICK_CUSTOM消息
    LCXE_LBDC_Data data;
    data.nItem = nItem;
    data.nSubItem = nSubItem;
    data.pLCXE = this;
    ::SendMessage(this->GetParent()->GetSafeHwnd(), MSG_LCXE_LBTN_DBLCLICK_CUSTOM, (WPARAM)&data, (LPARAM)&data);

    return CListCtrl::OnLButtonDblClk(nFlags, point);
}

void CListCtrlXE::OnHdnBegintrack(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMHEADER phdr = reinterpret_cast<LPNMHEADER>(pNMHDR);

    list<CEditLCXE*>::iterator iterEdit = m_lstEdit.begin();
    for (; iterEdit != m_lstEdit.end(); ++iterEdit)
    {
        CEditLCXE* pEdit = *iterEdit;
        if (pEdit->GetSafeHwnd() != NULL
            && pEdit->IsWindowVisible())
        {
            OnEditEnd((WPARAM)pEdit, (LPARAM)pEdit);
        }
    }

    list<CComboLCXE*>::iterator iterCombo = m_lstCombo.begin();
    for (; iterCombo != m_lstCombo.end(); ++iterCombo)
    {
        CComboLCXE* pCombo = *iterCombo;
        if (pCombo->GetSafeHwnd() != NULL
            && pCombo->IsWindowVisible())
        {
            OnComboEnd((WPARAM)pCombo, (LPARAM)pCombo);
        }
    }

    *pResult = 0;
}

void CListCtrlXE::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    list<CEditLCXE*>::iterator iterEdit = m_lstEdit.begin();
    for (; iterEdit != m_lstEdit.end(); ++iterEdit)
    {
        CEditLCXE* pEdit = *iterEdit;
        if (pEdit->GetSafeHwnd() != NULL
            && pEdit->IsWindowVisible())
        {
            OnEditEnd((WPARAM)pEdit, (LPARAM)pEdit);
        }
    }

    list<CComboLCXE*>::iterator iterCombo = m_lstCombo.begin();
    for (; iterCombo != m_lstCombo.end(); ++iterCombo)
    {
        CComboLCXE* pCombo = *iterCombo;
        if (pCombo->GetSafeHwnd() != NULL
            && pCombo->IsWindowVisible())
        {
            OnComboEnd((WPARAM)pCombo, (LPARAM)pCombo);
        }
    }

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

void CListCtrlXE::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // TODO: Add your message handler code here and/or call default
    list<CEditLCXE*>::iterator iterEdit = m_lstEdit.begin();
    for (; iterEdit != m_lstEdit.end(); ++iterEdit)
    {
        CEditLCXE* pEdit = *iterEdit;
        if (pEdit->GetSafeHwnd() != NULL
            && pEdit->IsWindowVisible())
        {
            OnEditEnd((WPARAM)pEdit, (LPARAM)pEdit);
        }
    }

    list<CComboLCXE*>::iterator iterCombo = m_lstCombo.begin();
    for (; iterCombo != m_lstCombo.end(); ++iterCombo)
    {
        CComboLCXE* pCombo = *iterCombo;
        if (pCombo->GetSafeHwnd() != NULL
            && pCombo->IsWindowVisible())
        {
            OnComboEnd((WPARAM)pCombo, (LPARAM)pCombo);
        }
    }

    CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值