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...


  • Mod

    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


Anmelden zum Antworten