Problem bei Customdraw von ComboBox


  • Mod

    Wenn Du "Has strings" auf nein gesetzt hast, dann übernimmst Du doch die Datenhaltung...

    Ichverstehe nicht ganz was Du willst/erwartest?



  • Mein Problem ist folgendes:

    ich haben eine Ownderdraw ComboBox, die mit "Fest" eingestellt ist und unter Daten einen Wert "-;" als start hat. Der Aufruf klappt soweit jetzt.
    Leider erscheinen, wenn ich mit .AddString() einen String hinzufüge anstelle meines Strings irgendweilche Chinesischen Zeichen und ich weiß nicht, wie ich das weg bekomme.

    Ich bekomme über eine Funktion ein WCHAR s[9] und den versuch ich da einzutragen.
    Dafür nehm ich mir einen CString und mittels Format(_T("%s"),s) und das klappt nicht. Meine Frag ist, was ich da falsch mache. Wenn ich das mit der normalen ComboBox mache, dann steht auch der inhalt von s[] drin.


  • Mod

    Ich verstehe momentan gar nichts von dem was Du schreibst. Wenn Du CBS_HASSTRINGS nicht gesetzt hast, dann kannst Du nichts in der Datenbox eintragen...

    Hast Du denn verstanden was es mit CBS_HASSTRINGS auf sich hat?

    Zeige mir Code wie Du formatierst und die Daten einfügst... und vor allem wie CBS_HASSTRINGS gesetzt ist!



  • Also wenn ich in meinem Eigenschaftsfenster (VS2010) Owerdraw auf "Fest" stelle kann ich unter "Daten" etwas eingeben. Egal ob ich bei Has Strings True oder False eingebe.

    Wenn ich CB_HASSTINGS angebe wird im Speicher der Combobox für jeden Eintrag eine String-Variable angelegt, die ich dann mit CB_GETLBTEXT auslesen muss/kann.

    Wobei ich eigentlich nur die Nummer des Eintrages brauche.

    Ich will zur Laufzeit Werte in meine Combobox einfügen und löschen. Das mache ich halt mit AddString() oder DeletString().
    Ich habe Ownderdraw auf Fest und Hasstings auf False gesetzt.

    Wenn ich

    .AddString(_T("test"));
    

    einfüge, dann steht der Wert in meiner Liste.

    Wenn ich

    CString s;
    s.SetString(_T("test"));
    .AddString(s);
    

    dagegen nutze, dann ist zwar eine Zeile in der Liste der Combobox und ich kann sie auswählen aber es steht nichts drin oder im schlimmsten Fall irgendwelche Zeichen.


  • Mod

    Du hast es nicht verstanden:
    HASSTRINGS==FALSE bedeutet, dass die ComboBox keine Strings verwaltet sondern Zeiger speichert! Wenn du also einen Zeiger auf einen CString übergibst ist der nach verlassen des Blocks ungültig und verweist irgendwo auf den Stack...
    Die Combobox zeigt dann auch Schrott an!
    Dito werden die "Daten" auch nicht korrekt angezeigt...

    Jetzt verstanden?

    Wenn Du also Strings in der CB speichern willst" und "keine Zeiger", dann msus CBS_HASSTRINGS gesetzt sein ⚠

    Das Ganze ist unabhängig ob Du nun die Nummer des Eintrages brauchst oder nicht!
    Das letzter Fall funktioniert ist reiner Suff, denn ver,utlich ist der Speicher einfach noch nicht wieder überschrieben...



  • Ah Ok jetzt bin ich ein wenig schlauer als Vorher (jedenfalls glaube ich das)

    Nun ist das Problem, dass ich keine Einträge einfügen kann, bzw. das ich einen Ausnahmefehler bekomme.

    Eine Ausnahme (erste Chance) bei 0x006d392f in Messe_Dongle.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0xffffffff.

    und er mir in die Funktion size_t __cdecl wcslen() zeigt.

    size_t __cdecl wcslen (
            const wchar_t * wcs
            )
    {
            const wchar_t *eos = wcs;
    
            while( *eos++ ) ;
    
            return( (size_t)(eos - wcs - 1) );
    }
    

    Das Ganze wird ausgelöst, wenn ich in meiner DrawItem() funktion DrawText aufrufe.

    void CMyComboBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
       ASSERT(lpDrawItemStruct->CtlType == ODT_COMBOBOX);
       LPCTSTR lpszText = (LPCTSTR) lpDrawItemStruct->itemData;
       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();
    
       COLORREF crNewText = RGB(0,220,220);
       COLORREF crNewBk = RGB(40,40,40);
    
       // If this item is selected, set the background color 
       // and the text color to appropriate values. Erase
       // the rect by filling it with the background color.
       if ((lpDrawItemStruct->itemAction & ODA_SELECT) &&
          (lpDrawItemStruct->itemState  & ODS_SELECTED))
       {
          dc.SetTextColor(crNewText);
          dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
          dc.FillSolidRect(&lpDrawItemStruct->rcItem, ::GetSysColor(COLOR_HIGHLIGHT));
       }
       else
       {
    	  dc.SetTextColor(crNewText);
          dc.FillSolidRect(&lpDrawItemStruct->rcItem, crNewBk);
       }
    
    	dc.DrawText( lpszText, (int)wcslen(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();
    
    }
    

    Leider kann ich mit dem Fehler überhaupt nichts anfangen 😞


  • Mod

    Drehen wir uns im Kreis oder wie? Jetzt sind wir wieder da wo wir angefangen haben und ich weiß immer noch nicht ob Du nun CBS_HASSTRINGS setzt oder nicht.

    1. Ist CBS_HASSTRINGS nicht gesetzt musst Du die Elemente verwalten und übergibst Zeigt und bekommst den Zeiger in DrawItem in itemData!
    2. Ist CBS_HASSTRINGS gesetzt ist itemData (siehe Doku, siehe Notiz von mir oben), und Du musst Dir den Eintrag selber holen (siehe ID in DRAWITEMSTRUCT).

    Hatte ich das nicht schon alles geschrieben? ... 😕



  • Sorry Martin, aber ich steh gerade auch voll auf der Leitung.
    Ich hab CBS_HASSTRINGS nicht gesetzt (FALSE) und so wie ich das sehe muss ich das setzen damit DrawItem funktioniert.

    Die Combobox wird jetzt auch angezeigt und wenn ich AddItem(_T("test")) sezte steht das auch drin (also test). Hoffe soweit ist das jetzt richtig.


  • Mod

    Uruk-h4j schrieb:

    Sorry Martin, aber ich steh gerade auch voll auf der Leitung.
    Ich hab CBS_HASSTRINGS nicht gesetzt (FALSE) und so wie ich das sehe muss ich das setzen damit DrawItem funktioniert.

    Nö! Warum? Wer sagt das?

    Die Combobox wird jetzt auch angezeigt und wenn ich AddItem(_T("test")) sezte steht das auch drin (also test). Hoffe soweit ist das jetzt richtig.

    Klar in diesem Fall ist der Zeiger "Konstant" logisch!

    Nochmal: Wenn Du CBS_HASTSTRINGS nicht gesetzt hast, musst Du selber die Strings speichern und die Combobox bekommt nur noch von Die "immer gültige Zeiger" geliefert!



  • Mal was ganz anderes:

    du musst den String anders auslesen.
    Der cast von der ->itemData funktioniert in deinem Fall nicht.

    besser:

    CString str;
    GetLBText( lpDrawItemStruct->itemID, str );
    

    und dann später

    dc.DrawText( str, &lpDrawItemStruct->rcItem, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
    

    Gruß Flo



  • WUHU !!!!

    Jetzt klappts. Dank dem hinweiß mit der Konstaten Pointer. Ich hab zwar immer eine Liste erstellt aber die war nur in der Funktion gültig. Hab jetzt eine globale Variable draus gemacht und jetzt klappts mit CB_HASSTRINGS -> False !

    Jetzt hab ich meine Farbige Combobox mit Einträgen !!!!

    Großes Danke Martin das du immer so viel Gedult hast. 😃 😃


  • Mod

    Uruk-h4j schrieb:

    Martin das du immer so viel Gedult hast. 😃 😃

    <Spock mässiges Augenbrauen heben>Faszinierend!</Spock mässiges Augenbrauen heben>
    Im Allgemeinen wird mir hier in dem Forum meistens genau das Gegenteil nachgesagt. 😉


Anmelden zum Antworten