2009-11-06 4 views
1

В MFC я могу редактировать текст элементов в элементе управления списком, но только для первого столбца, установив Edit Labels в значение true. Теперь, когда я нажимаю на элемент первого столбца, чтобы изменить его текст, я могу изменить его текст, но когда я нажимаю Enter, его текст не обновляется, почему и как мне редактировать текст для других столбцов?Управление списком MFC

ответ

0

Для первой колонки:

  • создать список со стилем LVS_EDITLABELS
  • установить диалоговое управление в вашем списке, если он его не имеет, например, SetDlgCtrlID (ID_EDITLABEL);
  • Возможно, вам понадобится код для отслеживания текущего выбора
  • добавить обработчик для конца редактирования в родительском классе

    ON_NOTIFY(LVN_ENDLABELEDIT, ID_EDITLABEL, OnEndEdit) 
    
    void MyParentClass::OnEndEdit(NMHDR* pNMHDR, LRESULT* pResult) 
    { 
        NMLVDISPINFO* pLVDI = reinterpret_cast< NMLVDISPINFO* >(pNMHDR); 
        if(pLVDI->item.pszText) 
        m_List.SetItemText(m_iCurrentSelection, 0, pLVDI->item.pszText); 
        *pResult = 0; 
    } 
    

Для других столбцов: Я не пробовал еще, но это не должно быть слишком сложно, как вы можете поиска в исходный код MFC, как они это делают. Обратите внимание, что приведенный выше код проверен с помощью CMFCListCtrl из последнего пакета функций, хотя я предполагаю, что обычный CListCtrl ведет себя одинаково.

1

К сожалению, невозможно использовать LVS_EDITLABELS и LVN_ENDLABELEDIT для редактирования других столбцов, кроме первого.

Для получения дополнительной информации см. Статью XListCtrl о CodeProject для получения дополнительной информации, она динамически создает элемент управления редактированием, когда это необходимо.

2

Мы создаем элемент управления CEdit в позиции ячейки управления List (при двойном щелчке по элементу управления списком) , и когда мы нажимаем enter, он обновляет значение. В этом примере мы модифицируем только 1 подэлемент (2-й), когда мы dbclick на элементе управления списком , вы можете создать множество элементов управления CEdit и сделать это со всеми подэлементами. Контроль SingleSelection = True

//.h 
// Global variables in dialog 
private: 
    //.. 
    const static int  ID_TXTCTRL_TOMODIFY = 1001; 
    bool     m_IsEnterPressed; 
    CEdit *     m_pTxtCtrlToModify; 

    //.. 
protected: 
    //.. 
    BOOL PreTranslateMessage(MSG* pMsg); 
    virtual BOOL OnInitDialog(); 
    //.. 

public: 
    //.. 
    afx_msg void OnNMDblclkList(NMHDR *pNMHDR, LRESULT *pResult); 
    afx_msg void OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult); 
    afx_msg void OnEnKillFocusCtrlToModify(); 
    //.. 

//------------------------------------------------------------------ 
// .cpp 


BEGIN_MESSAGE_MAP(DlgMFC, CDialogEx) 
    //.. 
    ON_NOTIFY(NM_DBLCLK, IDC_LIST, &DlgMFC::OnNMDblclkList) 
    ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST, &DlgMFC::OnLvnItemchangedList) 
    ON_EN_KILLFOCUS(ID_TXTCTRL_TOMODIFY, &DlgMFC::OnEnKillFocusCtrlToModify) 
    //.. 
END_MESSAGE_MAP() 

BOOL DlgMFC::OnInitDialog() 
{ 
    CDialogEx::OnInitDialog(); 

    // Set the icon for this dialog. The framework does this automatically 
    // when the application's main window is not a dialog 
    SetIcon(m_hIcon, TRUE);   // Set big icon 
    SetIcon(m_hIcon, FALSE);  // Set small icon 

    // TODO: Add extra initialization here 

    m_pTxtCtrlToModify = NULL; 
    m_IsEnterPressed = false; 

    // 
    return TRUE; // return TRUE unless you set the focus to a control 
} 

// in this function we let to modify only 1 subitem (the 2nd), 
// you can create many CEdit controls an do it with all the subitems 



    // We create CEdit Control 
void DlgMFC::OnNMDblclkList(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
    //LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR); 
    //*pResult = 0; 


    POSITION p = m_CtrlList.GetFirstSelectedItemPosition(); 
    int index, id; 
    if(p) 
    { 
      index = m_CtrlList .GetNextSelectedItem(p);  

      CRect rect, rect_ListControl; // rect wiil be cell position in m_CtrlList, rect_ListControl will be m_CtrlList's position in dialog 
      if(m_CtrlList.GetSubItemRect(index, 2, LVIR_BOUNDS, rect)) // 2 is subitem number 
      { 
       if(m_pTxtCtrlToModify != NULL) 
        delete m_pTxtCtrlToModify; 
       m_pTxtCtrlToModify = new CEdit(); // Do not forget to delete it at the end of your program (you can use OnClose()) 


       m_CtrlList.GetWindowRect(&rect_ListControl); 
       this->ScreenToClient(&rect); 

       rect.left += rect_ListControl.left + 2; // 2 is just a correction 
       rect.right += rect_ListControl.left + 2; 
       rect.top += rect_ListControl.top + 2; 
       rect.bottom += rect_ListControl.top + 2; 

       m_pTxtCtrlToModify->Create(ES_CENTER | WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, rect, this, ID_TXTCTRL_TOMODIFY); 
       m_pTxtCtrlToModify->SetFocus(); 
       m_pTxtCtrlToModify->SetWindowTextW(m_CtrlList.GetItemText(index, 2)); // 2 is subitem number 

      } 

    } 
} 


// If Selection changes, we delete that CEdit 
void DlgMFC::OnLvnItemchangedList(NMHDR *pNMHDR, LRESULT *pResult) 
{ 
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR); 
    *pResult = 0; 

    if(m_pTxtCtrlToModify != NULL) 
    { 
     delete m_pTxtCtrlToModify; 
     m_pTxtCtrlToModify = NULL; 
    } 
} 


// Do not let the dialog to be closed when we press enter 
BOOL DlgMFC::PreTranslateMessage(MSG* pMsg) 
{ 
    if (pMsg->message == WM_KEYDOWN) 
    { 
     if ((pMsg->wParam == VK_RETURN) || (pMsg->wParam == VK_ESCAPE)) 
     { 
      pMsg->wParam = VK_TAB; 
      m_IsEnterPressed = true; 
     } 
    } 
    return CDialog::PreTranslateMessage(pMsg); 
} 


//If we pressed enter, we update it and delete CEdit control 
void DlgMFC::OnEnKillFocusCtrlToModify() 
{ 
    // we will update only when we press enter 
    if(m_IsEnterPressed == true) 
    {  
     m_IsEnterPressed = false; 

     // UPDATE here your Database or just ListControl or both ... 
     // Example: We update the same m_CtrlList's cell 
     POSITION p = m_CtrlList.GetFirstSelectedItemPosition(); 
     int index; 
     if(p) 
     { 
      CString str; 
      m_pTxtCtrlToModify->GetWindowTextW(str); 
      index = m_CtrlList .GetNextSelectedItem(p); 
      m_CtrlList.SetItemText(index,2,str); // 2 is subitem number 
     } 


     // Delete CEdit control 
     if(m_pTxtCtrlToModify != NULL) 
     { 
      delete m_pTxtCtrlToModify; 
      m_pTxtCtrlToModify = NULL; 
     } 

     m_CtrlList.SetFocus(); 
    } 
} 

Я надеюсь, что это поможет. Thanks