CListCtrl - Fehler beim Zeichen
-
Hallo,
ich würde gerne einen Button in einem List Controls Zeichen hab auch folgenden Code erstellt, leider klappt das nicht wie gewollt, kompaliert wird alles
Fehler kommen dann beim Aufruf folgender Zeile:
m_pButton->Create("", dwStyle, rcSubItem, this, nItem);
Während des Programm Starts kommt folgende Meldung:
First-chance exception at 0x0040219a in ProgressLVDemo.exe: 0xC0000005: Access violation reading location 0x00000000.
Unhandled exception at 0x0040219a in ProgressLVDemo.exe: 0xC0000005: Access violation reading location 0x00000000.Ich hab hierzu mal den Source Code, vielleicht kann jemand einen Fehler erkennen:
// ProListCtrl.cpp : implementation file // #include "stdafx.h" #include "ProgressLVDemo.h" #include "ProListCtrl.h" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CProListCtrl CProListCtrl::CProListCtrl() { } CProListCtrl::~CProListCtrl() { } BEGIN_MESSAGE_MAP(CProListCtrl, CListCtrl) //{{AFX_MSG_MAP(CProListCtrl) ON_WM_HSCROLL() ON_WM_VSCROLL() ON_NOTIFY_REFLECT(NM_CUSTOMDRAW, OnCustomDraw) ON_WM_DESTROY() // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CProListCtrl message handlers void CProListCtrl::OnCustomDraw(NMHDR* pNMHDR, LRESULT* pResult) { NMLVCUSTOMDRAW* pLVCD = (NMLVCUSTOMDRAW*)pNMHDR; BOOL bCheck = false; *pResult = CDRF_DODEFAULT; if (CDDS_PREPAINT == pLVCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYITEMDRAW; return; }else if (CDDS_ITEMPREPAINT == pLVCD->nmcd.dwDrawStage) { *pResult = CDRF_NOTIFYSUBITEMDRAW; return; }else if ( (CDDS_SUBITEM | CDDS_ITEMPREPAINT) == pLVCD->nmcd.dwDrawStage ) { *pResult = CDRF_NOTIFYPOSTPAINT; return; }else if ( (CDDS_SUBITEM | CDDS_ITEMPOSTPAINT) == pLVCD->nmcd.dwDrawStage ) { int nItem = pLVCD->nmcd.dwItemSpec; int nSubItem = pLVCD->iSubItem; if (1 != nSubItem) return; CRect rcSubItem; //--------------------------------------------------------------- // Gets the Information from SetObject(); //--------------------------------------------------------------- this->GetSubItemRect(m_nRow, m_nCol, LVIR_BOUNDS, rcSubItem); //Style DWORD dwStyle = WS_BORDER | WS_CHILD | WS_TABSTOP; //this->GetSubItemRect(3, 1, LVIR_BOUNDS, rcSubItem); //CButton* pCtrl = (CButton*) this->GetItemData(nItem); //CProgressCtrl* pCtrl = (CProgressCtrl*)this->GetItemData(nItem); //CEdit* pCtrl = (CEdit*) this->GetItemData(nItem); //if (NULL == pCtrl) //{ if (m_nControlType == 1) { //CEdit* pEdit = (CEdit *); //this ->GetItemData (nItem); //pEdit = new CEdit(); //pEdit ->Create (dwStyle, rcSubItem, this, nItem); m_pEdit->Create(dwStyle, rcSubItem, this, nItem); ASSERT(m_pEdit->GetSafeHwnd()); this->SetItemData(nItem, (DWORD)m_pEdit); m_pEdit->MoveWindow(rcSubItem); m_pEdit->ShowWindow(SW_SHOW); } if (m_nControlType == 2) { //CButton* pButton; //= (CButton *) this->GetItemData (nItem); CButton* m_pButton = (CButton *) this->GetItemData (nItem); /* pButton = new CButton(); pButton ->Create ("", dwStyle, rcSubItem, this, nItem); */ m_pButton->Create("", dwStyle, rcSubItem, this, nItem); ASSERT(m_pButton->GetSafeHwnd()); this->SetItemData(nItem, (DWORD) m_pButton); m_pButton->MoveWindow(rcSubItem); m_pButton->ShowWindow(SW_SHOW); } if (m_nControlType == 3) { //CListBox* pListBox = (CListBox *) this->GetItemData (nItem); //pListBox = new CListBox(); //pListBox ->Create (dwStyle | WS_VSCROLL, rcSubItem, this, nItem); m_pList->Create(dwStyle | WS_VSCROLL, rcSubItem, this, nItem); ASSERT(m_pList->GetSafeHwnd()); this->SetItemData(nItem, (DWORD)m_pList); m_pList->MoveWindow(rcSubItem); m_pList->ShowWindow(SW_SHOW); } //pCtrl = new CProgressCtrl; //pCtrl = new CButton; //pCtrl = new CEdit; if (rcSubItem.Width() > 100) rcSubItem.right = rcSubItem.left + 100; //DWORD dwStyle = WS_BORDER | WS_CHILD | WS_TABSTOP; //pCtrl->Create(WS_CHILD|WS_VISIBLE|PBS_SMOOTH, rcSubItem, this, 0x1000 + nItem); //pCtrl->Create(_T("buttion"), dwStyle, rcSubItem, this, 0x1000 + nItem); //pCtrl->Create(dwStyle, rcSubItem, this, nItem); //ASSERT(pCtrl->GetSafeHwnd()); //pCtrl->SetPos( nItem*2 % 100 ); //this->SetItemData(nItem, (DWORD)pCtrl); //} if (rcSubItem.Width() > 100) rcSubItem.right = rcSubItem.left + 100; /* pCtrl->MoveWindow(rcSubItem); pCtrl->ShowWindow(SW_SHOW); */ *pResult = CDRF_SKIPDEFAULT; return; } } void CProListCtrl::OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { CListCtrl::OnHScroll(nSBCode, nPos, pScrollBar); InvalidateProgressCtrls(); } void CProListCtrl::OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) { CListCtrl::OnVScroll(nSBCode, nPos, pScrollBar); InvalidateProgressCtrls(); } void CProListCtrl::InvalidateProgressCtrls() { int nFirst = GetTopIndex(); int nLast = nFirst + GetCountPerPage(); //Hide the other items. int nCount = this->GetItemCount(); CProgressCtrl* pCtrl; for(int i = 0; i < nFirst; i++) { pCtrl = (CProgressCtrl*)this->GetItemData(i); if (NULL != pCtrl) pCtrl->ShowWindow(SW_HIDE); } for(i = nLast; i < nCount; i++) { pCtrl = (CProgressCtrl*)this->GetItemData(i); if (NULL != pCtrl) pCtrl->ShowWindow(SW_HIDE); } //Invalidate CRect rc(0,0,0,0); CRect rcSubItem; for(; nFirst < nLast; nFirst++) { GetSubItemRect(nFirst, 1, LVIR_BOUNDS, rcSubItem); VERIFY( rc.UnionRect(rc, rcSubItem) ); } InvalidateRect(rc); // Using this method, the flicker seems better that above. But I am not sure why, and think it's non-effective. //for(; nFirst < nLast; nFirst++) //{ // GetSubItemRect(nFirst, 1, LVIR_BOUNDS, rcSubItem); // InvalidateRect(rcSubItem); //} } void CProListCtrl::OnDestroy() { int nCount = this->GetItemCount(); CProgressCtrl* pCtrl; for(int i = 0; i < nCount; i++) { pCtrl = (CProgressCtrl*)this->GetItemData(i); if (NULL != pCtrl) delete pCtrl; this->SetItemData(i, 0); } } /**************************************************************** * FUNCTION : SetObject() * DESCRIPTION : Set the Properties for Drawing Function * PARAMETERS : (int) iRow - Number of the Row * (int) iCol - Number of the Colum * (int) iControlType - Type of the Control * RETURNS : - ****************************************************************/ void CProListCtrl::SetObject(int iRow, int iCol, int iControlType) { //Überprüfe ob ungültige Werte if (iRow < 0) return; if (iCol < 0) return; if (iControlType < 0) return; //Werte zuweißen m_nRow = iRow; m_nCol = iCol; m_nControlType = iControlType; } /**************************************************************** * FUNCTION : LoadControls(); * DESCRIPTION : Loads the Controls to Paint * PARAMETERS : - * RETURNS : - ****************************************************************/ void CProListCtrl::LoadControls() { m_pButton = new CButton(); m_pList = new CListBox(); m_pEdit = new CEdit(); }
und dazu noch die Header File:
#if !defined(AFX_PROLISTCTRL_H__81C51345_D304_48FE_AE90_1A71500AB2E9__INCLUDED_) #define AFX_PROLISTCTRL_H__81C51345_D304_48FE_AE90_1A71500AB2E9__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // ProListCtrl.h : header file // ///////////////////////////////////////////////////////////////////////////// // CProListCtrl window class CProListCtrl : public CListCtrl { // Construction public: CProListCtrl(); // Attributes public: // Operations public: void InvalidateProgressCtrls(); void SetObject(int iRow, int iCol, int iControlType); //void LoadControls(); //Global Table int m_nRow; int m_nCol; int m_nControlType; //Global Controls CButton* m_pButton; CEdit* m_pEdit; CListBox* m_pList; // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CProListCtrl) //}}AFX_VIRTUAL // Implementation public: virtual ~CProListCtrl(); // Generated message map functions protected: //{{AFX_MSG(CProListCtrl) afx_msg void OnCustomDraw( NMHDR* pNMHDR, LRESULT* pResult); afx_msg void OnHScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnVScroll( UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); afx_msg void OnDestroy(); afx_msg void LoadControls(); // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; ///////////////////////////////////////////////////////////////////////////// //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif // !defined(AFX_PROLISTCTRL_H__81C51345_D304_48FE_AE90_1A71500AB2E9__INCLUDED_)
Vielen Dank!
-
Wurde denn der CButton überhaupt erzeugt, bevor du ihn anzeigen wolltest? (sprich: hast du vor dem Anzeigen die LoadControls() Methode aufgerufen?)
Edit: Oder wahrscheinlicher ist, daß die Zeile "CButton* m_pButton = (CButton
this->GetItemData (nItem);" Humbug ist - in den anderen if()-Blöcken hast du die entsprechenden Zeilen ja auch auskommentiert.
-
Du hast Recht, ich hab die Funktion LoadControls(); eingebaut und der Button wurde angezeigt.
Die von dir angemerkte Zeile habe ich auskommentiert, mein nächstes Problem ist allerdings, das der Button bei jedem aufruf neu gezeichnet wird (z.B. scrollbalken wird bewegt) und das ich nur einen anstatt meiner einbauten zwei Buttons sehen kann...
-
So kannst Du das auch vergessen. Es wäre Irrsinn für jede Zeile einen eigenen Button zu erzeugen.
Einfacher ist es komplett auf Ownerdraw zu setzen und nur den Schalter entsprechend anzuzeigen, z.B. mit DrawFrameControl. Die entsprechende Funktionalität bekommst Du indem Du einen eigenen Handler für LButtonDown schreibst.
Du zeichnest also nur den Button, anstatt dort ein Fenster zu erzeugen.In dieser Form Buttons auf dem ListCtrl zu erzeugen ist kein guter Weg. Alleine schon die Position synchron zu halten beim Rollen ist schwierig.
Oder besser Du verwendest ein Grid, das entsprechende Funktionen bietet.
Weiterhin gibt es unter www.codeproject.com einige Listctrls die aufgebohrt wurden und solche netten Dinge wie Checkboxen und Schalter bereits unterstützen.
-
Okay Dankeschön,
werde dann ein bisschen Probieren