CListCtrl -> Felder Editieren und Übernhmen
-
Hi
ich hab lange gesucht jedoch nicht darüber gefunden wie ich die einzelnen Felder einer CListCtrl editieren kann.
Ich hab eine List welche in einer CListCtrl angezeigt wird. Jedoch hätte ich gerne das ich die einzelnen Felder editieren kann und das alle die geändert wurden auch übernehme und speicher kann.
Weiss das zufällig jemand wie das geht ??
Danke,
Indian
-
Mal ein kurzer Beitrag dazu:
1. Mach dir ne Basisklasse für das ListCtrl, welche von CListCtrl erbt,
damit ersparst du dir, es bei jeder anderen ListCtrl immer wieder vollständig
implementieren zu müssen...Header:
class LBasisListCtrl : public CListCtrl { // Konstruktion public: LBasisListCtrl(); public: CEdit* EditSubLabel(int nItem, int nCol); virtual ~LBasisListCtrl(); virtual void SetSubItemText(int item, int subitem, CString text) =0; // Generierte Nachrichtenzuordnungsfunktionen protected: //{{AFX_MSG(LBasisListCtrl) afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); //}}AFX_MSG DECLARE_MESSAGE_MAP() };
cpp:
CEdit* LBasisListCtrl::EditSubLabel(int nItem, int nCol) { // The returned pointer should not be saved // Make sure that the item is visible if( !EnsureVisible( nItem, TRUE ) ) return NULL; // Make sure that nCol is valid CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0); int nColumnCount = pHeader->GetItemCount(); if( nCol >= nColumnCount || GetColumnWidth(nCol) < 5 ) return NULL; // Get the column offset int offset = 0; for( int i = 0; i < nCol; i++ ) offset += GetColumnWidth( i ); CRect rect; GetItemRect( nItem, &rect, LVIR_BOUNDS ); // Now scroll if we need to expose the column CRect rcClient; GetClientRect( &rcClient ); if( offset + rect.left < 0 || offset + rect.left > rcClient.right ) { CSize size; size.cx = offset + rect.left; size.cy = 0; Scroll( size ); rect.left -= size.cx; } // Get Column alignment LV_COLUMN lvcol; lvcol.mask = LVCF_FMT; GetColumn( nCol, &lvcol ); DWORD dwStyle ; if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_LEFT) dwStyle = ES_LEFT; else if((lvcol.fmt&LVCFMT_JUSTIFYMASK) == LVCFMT_RIGHT) dwStyle = ES_RIGHT; else dwStyle = ES_CENTER; rect.left += offset+4; rect.right = rect.left + GetColumnWidth( nCol ) - 3 ; if( rect.right > rcClient.right) rect.right = rcClient.right; dwStyle |= WS_BORDER|WS_CHILD|WS_VISIBLE|ES_AUTOHSCROLL; CEdit *pEdit = new CInPlaceEdit(nItem, nCol, GetItemText( nItem, nCol )); pEdit->Create( dwStyle, rect, this, IDC_EDIT ); return pEdit; } void LBasisListCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if( GetFocus() != this ) SetFocus(); CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar); } void LBasisListCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { if( GetFocus() != this ) SetFocus(); CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar); }
Hier dann die konkrete Implementierung, die SetSubItemText wird hier ausformuliert:
Header:
class LInc : public LBasisListCtrl { // Konstruktion public: LInc(); virtual void SetSubItemText(int item, int subitem, CString text); // Attribute public: // Operationen public: // Überschreibungen // Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen //{{AFX_VIRTUAL(LInc) //}}AFX_VIRTUAL // Implementierung public: void Init(); virtual ~LInc(); // Generierte Nachrichtenzuordnungsfunktionen protected: //{{AFX_MSG(LInc) afx_msg void OnClick(NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult); //}}AFX_MSG DECLARE_MESSAGE_MAP() };
cpp:
void LInc::OnClick(NMHDR* pNMHDR, LRESULT* pResult) { LPNMITEMACTIVATE lpItem = (LPNMITEMACTIVATE) pNMHDR; if(lpItem->iItem > -1 && lpItem->iSubItem >-1) { EditSubLabel( lpItem->iItem, lpItem->iSubItem ); } *pResult = 0; } void LInc::SetSubItemText(int item, int subitem, CString text) { */Text speichern*/ SetItemText(item,subitem,text); } void LInc::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO *plvDispInfo = (LV_DISPINFO *)pNMHDR; LV_ITEM *plvItem = &plvDispInfo->item; if (plvItem->pszText != NULL) { SetSubItemText(plvItem->iItem, plvItem->iSubItem, plvItem->pszText); } *pResult = FALSE; }
Jetzt brauchen wir noch eine Klasse von CEdit abzuleiten, die weiss wo sie gerade
editiert etc.Header:
class CInPlaceEdit : public CEdit { // Konstruktion public: CInPlaceEdit(int iItem, int iSubItem, CString sInitText); // Attributes public: // Operations public: // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CInPlaceEdit) public: virtual BOOL PreTranslateMessage(MSG* pMsg); //}}AFX_VIRTUAL // Implementation public: virtual ~CInPlaceEdit(); // Generated message map functions protected: //{{AFX_MSG(CInPlaceEdit) afx_msg void OnKillFocus(CWnd* pNewWnd); afx_msg void OnNcDestroy(); afx_msg void OnChar(UINT nChar, UINT nRepCnt, UINT nFlags); afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); //}}AFX_MSG DECLARE_MESSAGE_MAP() private: int m_iItem; int m_iSubItem; CString m_sInitText; BOOL m_bESC; // To indicate whether ESC key was pressed };
cpp:
CInPlaceEdit::CInPlaceEdit(int iItem, int iSubItem, CString sInitText) :m_sInitText( sInitText ) { m_iItem = iItem; m_iSubItem = iSubItem; m_bESC = FALSE; } CInPlaceEdit::~CInPlaceEdit() { } BEGIN_MESSAGE_MAP(CInPlaceEdit, CEdit) //{{AFX_MSG_MAP(CInPlaceEdit) ON_WM_KILLFOCUS() ON_WM_NCDESTROY() ON_WM_CHAR() ON_WM_CREATE() //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CInPlaceEdit message handlers BOOL CInPlaceEdit::PreTranslateMessage(MSG* pMsg) { if( pMsg->message == WM_KEYDOWN ) { if(pMsg->wParam == VK_RETURN || pMsg->wParam == VK_DELETE || pMsg->wParam == VK_ESCAPE || GetKeyState( VK_CONTROL) ) { ::TranslateMessage(pMsg); ::DispatchMessage(pMsg); return TRUE; // DO NOT process further } } return CEdit::PreTranslateMessage(pMsg); } void CInPlaceEdit::OnKillFocus(CWnd* pNewWnd) { CEdit::OnKillFocus(pNewWnd); CString str; GetWindowText(str); // Send Notification to parent of ListView ctrl LV_DISPINFO dispinfo; dispinfo.hdr.hwndFrom = GetParent()->m_hWnd; dispinfo.hdr.idFrom = GetDlgCtrlID(); dispinfo.hdr.code = LVN_ENDLABELEDIT; dispinfo.item.mask = LVIF_TEXT; dispinfo.item.iItem = m_iItem; dispinfo.item.iSubItem = m_iSubItem; dispinfo.item.pszText = m_bESC ? NULL : LPTSTR((LPCTSTR)str); dispinfo.item.cchTextMax = str.GetLength(); GetParent()->GetParent()->SendMessage( WM_NOTIFY, GetParent()->GetDlgCtrlID(), (LPARAM)&dispinfo ); DestroyWindow(); } void CInPlaceEdit::OnNcDestroy() { CEdit::OnNcDestroy(); delete this; } void CInPlaceEdit::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { if( nChar == VK_ESCAPE || nChar == VK_RETURN) { if( nChar == VK_ESCAPE ) m_bESC = TRUE; GetParent()->SetFocus(); return; } CEdit::OnChar(nChar, nRepCnt, nFlags); // Resize edit control if needed // Get text extent CString str; GetWindowText( str ); CWindowDC dc(this); CFont *pFont = GetParent()->GetFont(); CFont *pFontDC = dc.SelectObject( pFont ); CSize size = dc.GetTextExtent( str ); dc.SelectObject( pFontDC ); size.cx += 5; // add some extra buffer // Get client rect CRect rect, parentrect; GetClientRect( &rect ); GetParent()->GetClientRect( &parentrect ); // Transform rect to parent coordinates ClientToScreen( &rect ); GetParent()->ScreenToClient( &rect ); // Check whether control needs to be resized // and whether there is space to grow if( size.cx > rect.Width() ) { if( size.cx + rect.left < parentrect.right ) rect.right = rect.left + size.cx; else rect.right = parentrect.right; MoveWindow( &rect ); } } int CInPlaceEdit::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CEdit::OnCreate(lpCreateStruct) == -1) return -1; // Set the proper font CFont* font = GetParent()->GetFont(); SetFont(font); SetWindowText( m_sInitText ); SetFocus(); SetSel( 0, -1 ); return 0; }
Fertig
Devil
-
ich bekommne Fehlermeldung das
IDC_EDIT nicht deklariert ist
c:\Dokumente und Einstellungen\Mother\Eigene Dateien\Visual Studio-Projekte\Kasse\Kasse\SortListCtrl.cpp(467): error C2065: 'IDC_EDIT' : nichtdeklarierter Bezeichner
-
Hi,
ich weis zwar nicht viel, aber IDC_EDIT ist ein Steuerelement
Auch als Eingabefeld getarnt. Baue ein Eingabefeld mit dem Namen IDC_EDIT
ein, und schaue was passiert.asmodia
-
asmodia schrieb:
Hi,
ich weis zwar nicht viel, aber IDC_EDIT ist ein Steuerelement
Auch als Eingabefeld getarnt. Baue ein Eingabefeld mit dem Namen IDC_EDIT
ein, und schaue was passiert.asmodia
Stimmt, habe vergessen, das man in den Dialog auch ein Editfeld einbauen
muss, welches dann auf randlos gestellt wird, und der Haken bei Sichtbar sollte raus.Devil
-
hi
also mir ist war das mit ner eigenen klasse für clistctrl zu arg.
ich habe mir nen schönen dialog gebaut - dort alle items/subitems rein
dann kann man dort schön ändern und bei ok werden alle member des dlgs wieder
in die liste geschrieben.sentinel
-
Ich hab ein neues EditFeld (Steuerelement) erzeugt mit dem Namen IDC_EDIT. Wird leider trotzdem nicht erkannt. Das Kompilieren hat funktioniert als ich die Klasse vom Dialog eingebundenn habe jedoch funktioniert das editieren immer noch nicht. Nur die erste Spalte wie sonst auch immer.
Kann mir jemand erklären wie ich Funktionen nutze. Ist bischen schwer für mich hier einzuarbeiten
-
an devil81
fehlt bei der Implementierung nicht eine Implementierung welches die notwendige Funktion aufruft, damit man die Felder editieren kann ?? Eine MessageMap Einbindung ?
ich kann immer nur noch die erste spalte default mässig editieren, alle anderen sind immer noch nicht editierbar. Ausserdem kann ich denn wert in der ersten Spalten nach dem editieren ja nicht übernehmen. Nachdem ich editierthabe und "ENTER" drücke müsste doch der neue wert übernommen werden oder ?
-
hi
leider wird das editierte Feld mit dem editiertem Wert nicht übernommen. Handler fehlten noch
ON_WM_LBUTTONDBLCLK()
ON_NOTIFY_REFLECT(LVN_ENDLABELEDIT, OnEndLabelEdit)
-
hi devil81
noch ne frage. wie kann ich festlegen welche spalte editiert werden kann und welche nicht ???