MFC CListCtrl在单元格上显示文本框以供用户编辑

时间:2016-01-22 08:14:31

标签: c++ user-interface mfc clistctrl

我有一个CListCtrl,我在单元格上显示一个文本框,允许用户编辑单元格的文本。

这样可行,但根据用户窗口设置,我认为文本框不会保留在不同UI样式的正确位置。

有没有人知道将文本框窗口置于用户点击的单元格中心的可靠方法?这是我现在使用的代码。我并不关心文本框右侧添加值16.我只想要一个可靠的方法来放置文本框左侧和顶部的位置。

void FilesDialog::OnNMClickFiles(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE temp = (LPNMITEMACTIVATE)pNMHDR;
    //get the row number
    nItem = temp->iItem;
    //get the column number
    nSubItem = temp->iSubItem;
    if (nSubItem == 0 || nSubItem == -1 || nItem == -1)
    {
        *pResult = 0;
        return;
    }
    //Retrieve the text of the selected subItem from the list
    CString str = GetItemText(filesList.m_hWnd, nItem, nSubItem);
    CRect rectList, rectDlg, rectCl;
    CRect rectItem;
    // Get the rectangle of the selected sub-item.
    ListView_GetSubItemRect(filesList.m_hWnd, temp->iItem, temp->iSubItem, LVIR_BOUNDS, &rectItem);
    //Get the Rectange of the listControl
    ::GetWindowRect(temp->hdr.hwndFrom, &rectList);
    //Get the Rectange of the Dialog
    ::GetWindowRect(this->m_hWnd, &rectDlg);
    GetClientRect(&rectCl);
    //this->ScreenToClient(&rectCl);
    int subY = rectDlg.Height() - rectCl.Height() - 5;
    int lft = rectItem.left + rectList.left - rectDlg.left + 1;
    int tp = rectItem.top + rectList.top - rectDlg.top - subY;
    // When an item is cut off by the window on the right
    // side, resize the text box so that the right side
    // is at the edge of the list control.
    int rtEdge = rectDlg.right - (rectDlg.right - rectCl.right);
    int subWdth = 0;
    if (lft + rectItem.Width() - 2 > rtEdge)
    {
        // 16 is just an arbitrary value that seems to work.
        subWdth = 16 + (lft + rectItem.Width() - 2) - rtEdge;
    }
    // Move the edit box window over the cell.
    editText.MoveWindow(lft, tp, rectItem.Width() - 2 - subWdth, rectItem.Height() - 1, true);
    //Set the list Item text in the edit box.
    ::SetWindowText(editText.m_hWnd, str);
    // Show the edit box and set focus to it.
    ::ShowWindow(editText.m_hWnd, SW_SHOW);
    ::SetFocus(editText.m_hWnd);

    *pResult = 0;

}

感谢。

1 个答案:

答案 0 :(得分:1)

这取决于editText的创建方式。如果editText的父级是ListView控件,例如:

editText.Create(WS_CHILD, CRect(0, 0, 1, 1), &filesList, 1);

然后无需调整任何内容,只需按原样使用rectItem

void FilesDialog::OnNMClickFiles(NMHDR *pNMHDR, LRESULT *pResult)
{
    LPNMITEMACTIVATE temp = (LPNMITEMACTIVATE)pNMHDR;
    if (temp->iSubItem == 0 || temp->iSubItem == -1 || temp->iItem == -1)
    {
        *pResult = 0;
        return;
    }

    CString str = filesList.GetItemText(temp->iItem, temp->iSubItem);

    CRect rectItem;
    filesList.GetSubItemRect(temp->iItem, temp->iSubItem, LVIR_BOUNDS, rectItem);

    editText.SetWindowText(str);
    editText.MoveWindow(rectItem, 1);
    editText.ShowWindow(SW_SHOW);

    *pResult = 0;
}

如果另一方面editText的父级不是ListView控件,则编辑框不会相对于ListView定位,因此必须调整其位置。

例如,如果在editText中初始化DoDataExchange,则按如下方式偏移rectItem

POINT p = { 0 };
filesList.MapWindowPoints(this, &p, 1);
rectItem.OffsetRect(p.x, p.y);
...
editText.MoveWindow(rectItem, 1);