ClistCtrl回车换行至下一行单元格继续编辑

现在我的CListCtrl单元格是可以编辑的,我如何才能实现,比如现在编辑的是第一行第一列的单元格,按下回车后自动定位到第二行第一列继续编辑?
以下代码是我实现单元格可编辑的代码

void CListctrledit::OnNMClick(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    //进行单击检测,这个结构已经被扩展为能够适应子项的单击检测。
    LVHITTESTINFO cHitTest;
    cHitTest.pt = pNMItemActivate->ptAction;
    if (-1 != SubItemHitTest(&cHitTest))    //检测位于哪个单元格上
    {
        if (cHitTest.flags & LVHT_ONITEMLABEL)
        {
            m_iCurRow = cHitTest.iItem;
            m_iCurColunm = cHitTest.iSubItem;
            if (pNMItemActivate->iSubItem != 0)
            {
                //获取单元格信息
                CRect rect;    //单元格的尺寸
                GetSubItemRect(m_iCurRow, m_iCurColunm, LVIR_LABEL, rect);    //这个坐标是相对于ListCtrl左上角的
                CString sValue = GetItemText(m_iCurRow, m_iCurColunm);    //获取当前单元格的内容
                                                                        //创建编辑框
                if (!m_wndEdt.m_hWnd)
                {
                    m_wndEdt.Create(WS_CHILD | ES_CENTER | ES_AUTOHSCROLL | ES_WANTRETURN | ES_MULTILINE, rect, this, 1);
                    m_wndEdt.SetFont(this->GetFont(), FALSE);    //设置编辑框的字体
                }
                //使编辑框文本水平居中
                CRect rcEdit;
                GetDlgItem(1)->GetClientRect(&rcEdit);
                ::OffsetRect(&rcEdit, 0, 2);     //后两个参数代表横向,纵向偏移
                ::SendMessageA(((CComboBox*)GetDlgItem(1))->m_hWnd, EM_SETRECT, 0, (LPARAM)&rcEdit);
                rect.left = 100;
                m_wndEdt.SetWindowText(sValue);
                m_wndEdt.MoveWindow(rect);
                m_wndEdt.ShowWindow(SW_SHOW);
                m_wndEdt.CreateSolidCaret(1, rect.Height() - 5);//创建一个光标
                //m_wndEdt.ShowCaret();//显示光标
                //m_wndEdt.SetSel(-1);//使光标移到最后面
                int iLength = sValue.GetLength();
                m_wndEdt.SetSel(0, iLength, FALSE);//设置光标选中所有文字
                m_wndEdt.SetFocus();
            }
        }
        *pResult = 0;
    }
}
//获取修改后的值
void CListctrledit::OnEnEdtKillFocus()
{
    m_wndEdt.ShowWindow(SW_HIDE);
    if (m_iCurColunm < 0 || m_iCurRow < 0)
        return;
    CString sEdt;
    m_wndEdt.GetWindowText(sEdt);
    SetItemText(m_iCurRow, m_iCurColunm, sEdt);    //更新List Control的单元格显示
    m_wndEdt.ShowWindow(SW_HIDE);//隐藏编辑框
}

// 声明消息映射
BEGIN_MESSAGE_MAP(CMyListCtrl, CListCtrl)
    ON_NOTIFY(LVN_ENDLABELEDIT, IDC_LIST_CTRL, OnEndLabelEdit)
END_MESSAGE_MAP()

// 处理LVN_ENDLABELEDIT消息
void CMyListCtrl::OnEndLabelEdit(NMHDR* pNMHDR, LRESULT* pResult)
{
    LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    LV_ITEM* pItem = &(pDispInfo)->item;

    // 获取当前编辑的单元格的行和列索引
    int row = pItem->iItem;
    int col = pItem->iSubItem;

    // 设置焦点到下一个单元格
    SetItemState(row + 1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
    EnsureVisible(row + 1, FALSE);
    EditLabel(row + 1);

    *pResult = 0;
}

要实现这个功能,您可以在 CListCtrl 的 OnKeyDown() 函数中处理按键事件,并使用 SetItemState() 函数将焦点转移到下一个单元格。例如:

void MyListCtrl::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
    if (nChar == VK_RETURN)  // 如果用户按下回车键
    {
        int row = GetNextItem(-1, LVNI_FOCUSED);  // 获取当前选中行
        int col = GetNextItem(-1, LVNI_FOCUSED | LVNI_COLUMN);  // 获取当前选中列

        SetItemState(row, col, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);

        // 将焦点移到下一个单元格
        col++;
        if (col >= GetHeaderCtrl()->GetItemCount())  // 如果已到达最后一列,则跳到下一行
        {
            col = 0;
            row++;
        }

        if (row >= GetItemCount())  // 如果已到达最后一行,则回到第一行
        {
            row = 0;
        }

        EnsureVisible(row, TRUE);
        EditLabel(row, col);
    }
    else
    {
        CListCtrl::OnKeyDown(nChar, nRepCnt, nFlags);
    }
}

在这个示例中,我们首先获取当前选中的单元格的行和列。然后我们使用 SetItemState() 函数将选中状态设置为当前单元格。接下来,我们将焦点移到下一个单元格,如果已经到达最后一列,则移到下一行。最后,我们调用 EditLabel() 函数打开当前单元格的编辑框。

这个修改的多处代码,你的代码也没上全,所以不能发完整代码出来。需要处理的是编辑框的回车事件,在其中首先结束编辑,然后移到下一行编辑。这是部分实现可以参考一下:

BOOL CListctrledit::PreTranslateMessage(MSG* pMsg)
{
    // TODO: 在此添加专用代码和/或调用基类
    if (WM_KEYDOWN == pMsg->message && VK_RETURN == pMsg->wParam)

    {
        if (GetFocus() == GetDlgItem(1)) //根据不同控件焦点判断是那个在执行 
        {
            //MessageBox(_T("Enter Catched!"));
            OnEnEdtKillFocus();

            m_iCurRow++;
            EditContent();//这个需要重写
        }
        return true;
    }
    return CListCtrl::PreTranslateMessage(pMsg);
}