Von CListBox abgeleitete Klasse will manche Daten nicht anzeigen



  • Ich habe die Klasse CMyListBox von CListBox abgeleitet um gewisse Daten farbig herforzuheben.

    Ich habe dies nach dem Beispiel vom MSDN für owner drawn Listbox gemacht.
    Doch leider wird bei manchen Daten nur ein Zeichensalat angezeigt.
    m_lbAnzeigeDaten und m_lbZeilenNummer sind die Variabeln der Klasse CMyListBox.

    Füllen der beiden Elementen mit Daten:

    void CTestDlg::OnBnClickedButtonOpen()
    {
    	m_lbAnzeigeDaten.ResetContent();
    	m_lbZeilenNummer.ResetContent();
    
    	cWorkClass.LoadFile();
    
    	CStringArray straDaten;
    	cWorkClass.GetDataArray(straDaten);
    
    	CString strZahl;
    
    	for(int i = 0; i<straDaten.GetSize();i++)
    	{
    		m_lbAnzeigeDaten.AddString(straDaten[i]);// Das funktioniert
    
    		strZahl.Format(_T("%d"),i);
    		m_lbZeilenNummer.AddString(strZahl); // Hier wird nur Datensalat angezeigt
    		//m_lbZeilenNummer.AddString(_T(„Test“)); //Das funktioniert
    		//m_lbAnzeigeDaten.AddString(strZahl);// Hier wird nur Datensalat angezeigt
    	}
    }
    

    Zeichnen der Daten in der abgeleiteten Klasse:

    // Funktion aus: http://msdn.microsoft.com/en-us/library/kc9hahtd(v=vs.80).aspx
    void CMyListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    	ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX);
    	LPCTSTR lpszText = (LPCTSTR) lpDrawItemStruct->itemData; // Hier bekomme ich in manchen Fällen nur Datensalat 
    	ASSERT(lpszText != NULL);
    	CDC dc;
    
    	dc.Attach(lpDrawItemStruct->hDC);
    
    	// Save these value to restore them when done drawing.
    	COLORREF crOldTextColor = dc.GetTextColor();
    	COLORREF crOldBkColor = dc.GetBkColor();
    
    	// If this item is selected, set the background color 
    	// and the text color to appropriate values. Also, erase
    	// rect by filling it with the background color.
    	if(	(lpDrawItemStruct->itemAction | ODA_SELECT) &&
    		(lpDrawItemStruct->itemState & ODS_SELECTED))
    	{
    		dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
    		dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
    		dc.FillSolidRect(	&lpDrawItemStruct->rcItem, 
    				::GetSysColor(COLOR_HIGHLIGHT));
    	}
    	else
    	{
    		dc.FillSolidRect(&lpDrawItemStruct->rcItem, crOldBkColor);
    	}
    	// If this item has the focus, draw a red frame around the
    	// item's rect.
    	if(	(lpDrawItemStruct->itemAction | ODA_FOCUS) &&
    		(lpDrawItemStruct->itemState & ODS_FOCUS))
    	{
    		CBrush br(RGB(255, 0, 0));
    		dc.FrameRect(&lpDrawItemStruct->rcItem, &br);
    		}
    
    	// Draw the text.
    	dc.DrawText(
    		lpszText,
    		strlen(lpszText),
    		&lpDrawItemStruct->rcItem,
    		DT_CENTER|DT_SINGLELINE|DT_VCENTER);
    
    	// Reset the background color and the text color back to their
    	// original values.
    	dc.SetTextColor(crOldTextColor);
    	dc.SetBkColor(crOldBkColor);
    
    	dc.Detach();
    }
    

    Weis zufälligerweise jemand was ich da wieder falsch gemacht habe?


  • Mod

    Hast Du auch den Stil Ownerdrawvariable verwendet?



  • Ich habe in den Einstellungen Ownerdrawn auf "Fest" geändert.
    Damit müsste der richtige Stil gesetzt sein.

    Das Merkwürdige ist ja, dass wenn die Daten aus dem CStringArray kommen oder hardcoded sind richtig angezeift werden und alles so gezeichnet wird wie es soll.

    Doch sobald ich die Zeilennumer als anzuzeigende Daten verwende, wird nur ein Datensalad angezeigt.
    Auch die Verwendung von itoa und einem char-Array hat nichts gebracht.
    Dass ist ganz so, als ob es dann einen ungültigen Zeiger gibt.

    Ich kann mir aber beim bessten Willen nicht vorstellen wo da der Fehler in meinem Code liegen könnte.
    Vor allem da ja hardcoded Text richtig verarbeitet wird.



  • hast du auch LBS_HASSTRINGS als stil gesetzt?



  • Der Stil ist gesetzt.

    Spy++ bestätigt es.


  • Mod

    Was stellst Du Dir denn vor was in ItemData drin steht. Was hast Du denn rein getan mit SetData oder SetDataPtr?



  • Was stellst Du Dir denn vor was in ItemData drin steht.

    So wie es die Beschreibung sagt, stehen da die Daten drinnen, die auf LPCTSTR gekastet werden.

    Was hast Du denn rein getan mit SetData oder SetDataPtr?

    Bis jetzt habe ich keine der beiden Funktionen verwendet.
    Bis jetzt habe ich die Daten nur mit AddString in der Funktion OnBnClickedButtonOpen an die Klasse übergeben.
    Wenn ich mit AddString die Zeilennummer als String übergebe, kebomme ich nur Datenmüll in itemData.

    Bis jetzt bin ich noch garnicht dazu gekommen, erweiterte Anzeigefunktionen und Funktionen zum Übergeben weiterer Daten einzubinden.
    Erst sollen die grundliegenden Dinge funktionieren.
    Ich stehe da jetzt aber komplett auf dem Schlauch und habe absolut keine Ahnung was ich falsch gemacht haben könnte.



  • na ja die Beschreibung von MS ist in demfall würde ich sagen ein klein wenig zu unvollständig, was eher zu verwirrung führt als zur Lösung. MS setzt den Textstring bzw. den Zeiger auf diesen mit SetItemData/SetItemDataPtr, wonach sie dann auch in der OnDraw() unter lpDrawItemStruct->itemData den Zeiger auf den String haben. Wenn du dagegen mit AddString los gehst, dann bekommst du den String mit GetText() geliefert denb du dann anzeigen kannst.

    Also so hab ich das immer genutzt, wenn da noch jemand ne bessere Idee vielleicht hat, sollte er das sagen

    CString strItem;
        if (lpDrawItemStruct->itemID != -1)
        {
            GetText(lpDrawItemStruct->itemID, strItem);
        }
    

  • Mod

    So wie CTecS es schreibt ist es.

    itemData enthält, den Zeiger, die Daten, die Du setzt. Wenn Du LBS_HASSTRINGS verwendest musst Du Dir auch selbst die Daten holen.



  • Danke für eure Hilfe.
    Ohne euch hätte ich ewig nach diesem Fehler gesucht.

    mfg Bernd


Log in to reply