1

MFC では、リスト コントロール内の項目のテキストを編集できますが、Edit Labels を true に設定することで最初の列に対してのみ編集できます。最初の列アイテムをクリックしてテキストを変更すると、そのテキストを変更できますが、Enter キーを押してもテキストが更新されません。他の列のテキストを編集するには、なぜ、どのようにすればよいですか?

4

3 に答える 3

3

List コントロールのセルの位置 (List コントロールをダブルクリックしたとき) に CEdit コントロールを作成し、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();
    }
}

お役に立てば幸いです。ありがとう

于 2013-04-25T18:22:41.973 に答える
1

残念ながら、最初の列以外の列を利用LVS_EDITLABELSして編集することはできません。LVN_ENDLABELEDIT

回避策については、CodeProject のXListCtrlの記事を参照してください。必要に応じて編集コントロールが動的に作成されます。

于 2009-11-27T08:06:32.573 に答える
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 も同じように動作すると想定しています。

于 2009-11-06T17:41:33.223 に答える