⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mycombolistctrl.cpp

📁 一个非常好的WINCE界面
💻 CPP
字号:
//MyComboListCtrl.cpp
#include "stdafx.h"
#include "MyComboListCtrl.h"
#include "InPlaceCombo.h"
#include "InPlaceEdit.h"

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

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

/////////////////////////////////////////////////////////////////////////////
// CMyComboListCtrl

CMyComboListCtrl::CMyComboListCtrl()
{
    m_iColumnCounts = 0;
    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;
}

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


BEGIN_MESSAGE_MAP(CMyComboListCtrl, CListCtrl)
    //{{AFX_MSG_MAP(CMyComboListCtrl)
    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()

/////////////////////////////////////////////////////////////////////////////
// CMyComboListCtrl message handlers

CInPlaceCombo* CMyComboListCtrl::ShowInPlaceList(int iRowIndex, int iColumnIndex, 
                                                 CStringList& rComboItemsList, 
                                                 CString strCurSelecetion /*= ""*/, 
                                                 int iSel /*= -1*/)
{
    // The returned obPointer should not be saved

    // Make sure that the item is visible
    if (!EnsureVisible(iRowIndex, TRUE))
    {
        return NULL;
    }

    // Make sure that iColumnIndex is valid 
    CHeaderCtrl* pHeader = static_cast<CHeaderCtrl*> (GetDlgItem(FIRST_COLUMN));

    int iColumnCount = pHeader->GetItemCount();

    if (iColumnIndex >= iColumnCount || GetColumnWidth(iColumnIndex) < MIN_COLUMN_WIDTH) 
    {
        return NULL;
    }

    // Calculate the rectangle specifications for the combo box
    CRect obCellRect(0, 0, 0, 0);
    CalculateCellRect(iColumnIndex, iRowIndex, obCellRect);

    int iHeight = obCellRect.Height();  
    int iCount = (int )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; 

    // Create the in place combobox
    CInPlaceCombo* pInPlaceCombo = CInPlaceCombo::GetInstance();
    pInPlaceCombo->ShowComboCtrl(m_dwDropDownCtrlStyle, obCellRect, this, 0, iRowIndex, 
        iColumnIndex, &rComboItemsList, strCurSelecetion, iSel);

    return pInPlaceCombo;
}

CInPlaceEdit* CMyComboListCtrl::ShowInPlaceEdit(int iRowIndex, int iColumnIndex, 
                                                CString& rstrCurSelection)
{
    // Create an in-place edit control
    CInPlaceEdit* pInPlaceEdit = CInPlaceEdit::GetInstance();

    CRect obCellRect(0, 0, 0, 0);
    CalculateCellRect(iColumnIndex, iRowIndex, obCellRect);

    pInPlaceEdit->ShowEditCtrl(m_dwEditCtrlStyle, obCellRect, this, 0, 
        iRowIndex, iColumnIndex,
        m_strValidChars[iColumnIndex], rstrCurSelection);

    return pInPlaceEdit;
}

void CMyComboListCtrl::OnHScroll(UINT iSBCode, UINT iPos, CScrollBar* pScrollBar) 
{
    // TODO: Add your message handler code here and/or call default

    if (GetFocus() != this)
    {
        SetFocus();
    }

    CListCtrl::OnHScroll(iSBCode, iPos, pScrollBar);
}

void CMyComboListCtrl::OnVScroll(UINT iSBCode, UINT iPos, CScrollBar* pScrollBar) 
{
    // TODO: Add your message handler code here and/or call default

    if (GetFocus() != this)
    {
        SetFocus();
    }

    CListCtrl::OnVScroll(iSBCode, iPos, pScrollBar);
}

void CMyComboListCtrl::OnLButtonDown(UINT iFlags, CPoint obPoint) 
{
    // TODO: Add your message handler code here and/or call default

    int iColumnIndex = -1;
    int iRowIndex = -1;

    // Get the current column and row
    if (!HitTestEx(obPoint, &iRowIndex, &iColumnIndex))
    {
        return;
    }

    CListCtrl::OnLButtonDown(iFlags, obPoint);

    // If column is not read only then
    // If the SHIFT or CTRL key is down call the base class
    // Check the high bit of GetKeyState to determine whether SHIFT or CTRL key is down
    if ((GetKeyState(VK_SHIFT) & 0x80) || (GetKeyState(VK_CONTROL) & 0x80))
    {
        return;
    }

    // Get the current selection before creating the in place combo box
    CString strCurSelection = GetItemText(iRowIndex, iColumnIndex);

    if (-1 != iRowIndex)
    {
        UINT flag = LVIS_FOCUSED;

        if ((GetItemState(iRowIndex, flag ) & flag) == flag)
        {
            // Add check for LVS_EDITLABELS
            if (GetWindowLong(m_hWnd, GWL_EXSTYLE) & LVS_EDITLABELS)
            {
                // If combo box is supported
                // Create and show the in place combo box
                if (IsCombo(iColumnIndex))
                {
                    CStringList obComboItemsList;

                    GetParent()->SendMessage(WM_SET_ITEMS, (WPARAM)iColumnIndex, 
                        (LPARAM)&obComboItemsList);  

                    CInPlaceCombo* pInPlaceComboBox = ShowInPlaceList(iRowIndex, 
                        iColumnIndex, obComboItemsList, strCurSelection);
                    ASSERT(pInPlaceComboBox); 

                    // Set the selection to previous selection
                    pInPlaceComboBox->SelectString(-1, strCurSelection);
                }
                // If combo box is not read only
                // Create and show the in place edit control
                else if (!IsReadOnly(iColumnIndex))
                {
                    CInPlaceEdit* pInPlaceEdit = ShowInPlaceEdit(iRowIndex, 
                        iColumnIndex, strCurSelection);
                }
            }
        }
    }  
}

bool CMyComboListCtrl::HitTestEx(CPoint &obPoint, int* pRowIndex, int* pColumnIndex) const
{
    if (!pRowIndex || !pColumnIndex)
    {
        return false;
    }

    // Get the row index
    *pRowIndex = HitTest(obPoint, NULL);

    if (pColumnIndex)
    {
        *pColumnIndex = 0;
    }

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

    // Get the number of columns
    CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);

    int iColumnCount = pHeader->GetItemCount();

    // Get bounding rect of item and check whether obPoint falls in it.
    CRect obCellRect;
    GetItemRect(*pRowIndex, &obCellRect, LVIR_BOUNDS);

    if (obCellRect.PtInRect(obPoint))
    {
        // Now find the column
        for (*pColumnIndex = 0; *pColumnIndex < iColumnCount; (*pColumnIndex)++)
        {
            int iColWidth = GetColumnWidth(*pColumnIndex);

            if (obPoint.x >= obCellRect.left && obPoint.x <= (obCellRect.left + iColWidth))
            {
                return true;
            }
            obCellRect.left += iColWidth;
        }
    }
    return false;
}

void CMyComboListCtrl::SetComboColumns(int iColumnIndex, bool bSet /*= true*/)
{
    // If the Column Index is not present && Set flag is false
    // Then do nothing 
    // If the Column Index is present && Set flag is true
    // Then do nothing
    POSITION Pos = m_ComboSupportColumnsList.Find(iColumnIndex);

    // If the Column Index is not present && Set flag is true
    // Then Add to list
    if ((NULL == Pos) && bSet) 
    {
        m_ComboSupportColumnsList.AddTail(iColumnIndex); 
    }

    // If the Column Index is present && Set flag is false
    // Then Remove from list
    if ((NULL != Pos) && !bSet) 
    {
        m_ComboSupportColumnsList.RemoveAt(Pos); 
    }
}

void CMyComboListCtrl::SetReadOnlyColumns(int iColumnIndex, bool bSet /*= true*/)
{
    // If the Column Index is not present && Set flag is false
    // Then do nothing 
    // If the Column Index is present && Set flag is true
    // Then do nothing
    POSITION Pos = m_ReadOnlyColumnsList.Find(iColumnIndex);

    // If the Column Index is not present && Set flag is true
    // Then Add to list
    if ((NULL == Pos) && bSet) 
    {
        m_ReadOnlyColumnsList.AddTail(iColumnIndex); 
    }

    // If the Column Index is present && Set flag is false
    // Then Remove from list
    if ((NULL != Pos) && !bSet) 
    {
        m_ReadOnlyColumnsList.RemoveAt(Pos); 
    }
}

bool CMyComboListCtrl::IsReadOnly(int iColumnIndex)
{
    if (m_ReadOnlyColumnsList.Find(iColumnIndex))
    {
        return true;
    }

    return false;
}

bool CMyComboListCtrl::IsCombo(int iColumnIndex)
{
    if (m_ComboSupportColumnsList.Find(iColumnIndex))
    {
        return true;
    }

    return false;
}

void CMyComboListCtrl::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); 
}

void CMyComboListCtrl::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult) 
{
    LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    // TODO: Add your control notification handler code here

    // Update the item text with the new text
    SetItemText(pDispInfo->item.iItem, pDispInfo->item.iSubItem, pDispInfo->item.pszText);

    GetParent()->SendMessage(WM_VALIDATE, GetDlgCtrlID(), (LPARAM)pDispInfo); 

    *pResult = 0;
}

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

void CMyComboListCtrl::SetColumnValidEditCtrlCharacters(CString &rstrValidCharacters,int column)
{
    if(column>MAX_LISTCTRL_COLUMNS-1)
        return;
    if(column == -1)
    {
        for(int i=0;i<MAX_LISTCTRL_COLUMNS;i++)
        {
            m_strValidChars[i] = rstrValidCharacters;
        }
    }
    else
        m_strValidChars[column] = rstrValidCharacters;
}

void CMyComboListCtrl::EnableHScroll(bool bEnable /*= true*/)
{
    if (bEnable)
    {
        m_dwDropDownCtrlStyle |= WS_HSCROLL;
    }
    else
    {
        m_dwDropDownCtrlStyle &= ~WS_HSCROLL;
    } 
}

void CMyComboListCtrl::EnableVScroll(bool bEnable /*= true*/)
{
    if (bEnable)
    {
        m_dwDropDownCtrlStyle |= WS_VSCROLL;
    }
    else
    {
        m_dwDropDownCtrlStyle &= ~WS_VSCROLL;
    }
}

void CMyComboListCtrl::ScrollToView(int iColumnIndex, /*int iOffSet, */CRect& robCellRect)
{
    // Now scroll if we need to expose the column
    CRect rcClient;
    GetClientRect(&rcClient);

    int iColumnWidth = GetColumnWidth(iColumnIndex);

    // Get the column iOffset
    int iOffSet = 0;
    for (int iIndex_ = 0; iIndex_ < iColumnIndex; iIndex_++)
    {
        iOffSet += GetColumnWidth(iIndex_);
    }

    // If x1 of cell rect is < x1 of ctrl rect or
    // If x1 of cell rect is > x1 of ctrl rect or **Should not ideally happen**
    // If the width of the cell extends beyond x2 of ctrl rect then
    // Scroll

    CSize obScrollSize(0, 0);

    if (((iOffSet + robCellRect.left) < rcClient.left) || 
        ((iOffSet + robCellRect.left) > rcClient.right))
    {
        obScrollSize.cx = iOffSet + robCellRect.left;
    }
    else if ((iOffSet + robCellRect.left + iColumnWidth) > rcClient.right)
    {
        obScrollSize.cx = iOffSet + robCellRect.left + iColumnWidth - rcClient.right;
    }

    Scroll(obScrollSize);
    robCellRect.left -= obScrollSize.cx;

    // Set the width to the column width
    robCellRect.left += iOffSet;
    robCellRect.right = robCellRect.left + iColumnWidth;
}

void CMyComboListCtrl::OnBeginLabelEdit(NMHDR* pNMHDR, LRESULT* pResult) 
{
    LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    // TODO: Add your control notification handler code here
    if (IsReadOnly(pDispInfo->item.iSubItem))
    {
        *pResult = 1;
        return;
    }

    *pResult = 0;
}

int CMyComboListCtrl::InsertColumn(int nCol, LPCTSTR lpszColumnHeading, int nFormat, 
                                   int nWidth, int nSubItem)
{
    m_iColumnCounts++;
    return CListCtrl::InsertColumn(nCol, lpszColumnHeading, nFormat, nWidth, nSubItem);
}

int CMyComboListCtrl::GetColumnCounts()
{
    return m_iColumnCounts;
}

void CMyComboListCtrl::DeleteAllColumn()
{
    for (int i = 0; i < m_iColumnCounts; i++)
    {
        DeleteColumn(0);
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -