CListCtrl, wie hoch ist die maximale Aufnahmekapazität von Daten



  • Andy007 schrieb:

    Hallo,

    kannst du mir den genaueren Link direkt zu dem Grid posten? Danke.

    Kann ich:
    http://codeproject.com/miscctrl/gridctrl.asp

    Eventuell ein paar mal probieren, die Site hat notorische Zugangsprobleme.



  • gerade kein login schrieb:

    Hi,

    die Klasse CListCtrl kann diesen 'virtual mode' auch. Der Style nennt sich LVS_OWNERDATA, Du kannst auch einfach 'Benutzerdaten' in den Eigenschaften des Controls anhaken.

    Wenn Du jetzt die Nachricht LVN_GETDISPINFO abfängst, kannst Du darin immer genau den Inhalt reinschreiben, der zur Zeit gerade angezeigt werden soll.

    Wir haben hier ein Projekt, wo ca. 500.000 Listen-Einträge mit einer CListCtrl Tabelle dargestellt werden + läuft mit OWNERDATA superschnell 😉

    Gruß T. 🙂

    Super! Hab nicht gewußt, daß es auch mit dem Standard-CListCtrl geht. Danke!!! Hast du eventuell einen Schnipsel, wie man LVN_GETDISPINFO umsetzt?



  • AndRo67 schrieb:

    Kann ich:
    http://codeproject.com/miscctrl/gridctrl.asp

    Eventuell ein paar mal probieren, die Site hat notorische Zugangsprobleme.

    Danke dir!



  • Hab mal die Stelle aus dem Projekt kopiert, wie gesagt wir schreiben an der Stelle Daten aus einer DB. Je nach dem wo Deine Daten herkommen, musst Du sie halt hier dynamisch bereitstellen.

    /*
    ===================================================================================
    	Nachricht des ListControls abfangen, die geforderten Infos aus der Datenbank
    	lesen und in die Liste schreiben
    ===================================================================================
    */
    
    void CMyDlg::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) 
    {
    	LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
    	// Initialisierungen:
    	CString str = _T("");
    	CString stemp = _T("");
    	CString strArtikelPlusTitel;
    	COleVariant varValue;
    	long index = pDispInfo->item.iItem;
    	long subItem = 	pDispInfo->item.iSubItem;
    	long lDataColumn = 1;
    
    	if(pDispInfo->item.mask & LVIF_TEXT)								//gültiger Textpuffer?
    	{
    		try
    		{
    			if ( m_RecordList.m_lCrntRecord == -1 )						// wenn Variable wegen Requery oder bei Prog-Start auf -1 gesetzt wurde
    			{
    				MyRecords->SetAbsolutePosition(index);					// Den Index der DB mit Fenster syncronisieren
    				m_RecordList.m_lCrntRecord = index;
    			}
    			else 
    			{
    				if ( m_RecordList.m_lCrntRecord != index )				// Die Listenposition gegen glob, Hilfs-Variable checken
    				{
    					if ( !(MyRecords->IsEOF() || MyRecords->IsEOF()) ) 
    					{
    						// relative Position
    						if ( index <= (int)MyRecords->GetRecordCount() )//Check ob Listen-Pos kleiner als Anzahl der Records
    						{
    							const long lOffset = index - m_RecordList.m_lCrntRecord;  //Offset errechnen (Differenz)
    							if ( lOffset != 0 )							// Nochmal check ob Offset != 0
    							{
    								MyRecords->Move(lOffset);				//Record aktualisieren
    								m_RecordList.m_lCrntRecord += lOffset;	//glob, Hilfs-Variable um Offset korregieren
    							}
    						}
    					}
    				}
    			}
    		}
    		catch(CDaoException* e)
    		{
    			MyRecords->DisplayDaoException(e);
    			e->Delete();
    			return;
    		}
    		try
    		{																//Daten aus dem Datensatz ziehen:
    			if(subItem)
    			{
    				lDataColumn = TranslateColumns(subItem);
    				MyRecords->GetFieldValue(lDataColumn, varValue);
    			}
    			else
    			{
    				MyRecords->GetFieldValue(0, varValue);
    			}
    		}
    		catch(CDaoException* e)
    		{
    			MyRecords->DisplayDaoException(e);
    			e->Delete();
    			return;
    		}
    		const VARIANT* variant = LPCVARIANT(varValue);
    
    		if(variant->vt & VT_BYREF)
    			return;
    
    		str = Variant2String(variant);
    		if (lDataColumn == 5)
    		{
    			if (MyRecords->m_ARTIKEL != _T(""))
    			{
    				strArtikelPlusTitel = MyRecords->m_ARTIKEL + _T(" ");
    				strArtikelPlusTitel += str;
    				str = strArtikelPlusTitel;
    			}
    		}
    		lstrcpyn(pDispInfo->item.pszText, str, pDispInfo->item.cchTextMax);//Text kopieren
    	}
    	if(pDispInfo->item.mask & LVIF_IMAGE)
    	{
    		pDispInfo->item.iImage = 0;										//gültiges Bild?
    	}
    	*pResult = 0;
    }
    

    Mit 'ner DB als Datenquelle ist der Aufwand zur Synkronisierung von DB-Zeilen und Listenzeilen etwas fummelig, aber man wird mit sehr angenehmer Performance belohnt... 😉

    Gruß T.



  • gerade kein login schrieb:

    ............ Mit 'ner DB als Datenquelle ist der Aufwand zur Synkronisierung von DB-Zeilen und Listenzeilen etwas fummelig, aber man wird mit sehr angenehmer Performance belohnt... 😉

    Gruß T.

    Super! Ich werde versuchen, das umzusetzen. Danke!!!



  • gerade kein login schrieb:

    Mit 'ner DB als Datenquelle ist der Aufwand zur Synkronisierung von DB-Zeilen und Listenzeilen etwas fummelig, aber man wird mit sehr angenehmer Performance belohnt... 😉

    Gruß T.

    Hallo,

    ich habe versucht, diesen "Virtual Mode" für das CListCtrl einzusetzen. Irgendwie habe ich noch nicht verstanden, was da abgeht 😮

    Unser Projekt "ID3Sort", in dem die Liste benutzt wird http://www.informatik-gruppe.de/projekte/id3sort/id3sort.htm

    Vielleicht kannst du mir hier weiterhelfen 😋

    Ich habe bereits die Methode OnGetDispInfo geschrieben. Weiss aber nicht, ob sie so ungefähr richtig ist. Jedenfalls erfolgt kein Aufruf dieser Funktion! Wann wird sie denn überhaupt aufgerufen? Und von wem wird sie aufgerufen 🙄

    void CID3Sort_Win_MFCDlg::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) 
    {
          LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
          // TODO: Code für die Behandlungsroutine der Steuerelement-Benachrichtigung hier einfügen
    
          LV_ITEM &lvItem = pDispInfo->item;
          if( lvItem.mask & LVIF_TEXT )
          {
                CID3 tag;
                vector<CID3> tagListe = m_liste.getAllTag();
                vector<CID3>::iterator current;
                current = tagListe.begin();
    
                int nItem = lvItem.iItem;
                for( int i = 0; ( i < nItem && current != tagListe.end()); i++)
                {
                      current++;
                }
                tag = *current;
                switch( lvItem.iSubItem )
                {
                case 0:
                      lvItem.pszText = (LPSTR) tag.getFileName().c_str();
                      break;
                case 1:
                      lvItem.pszText = (LPSTR) tag.getSongTitle().c_str();
                      break;
                case 2:
                      lvItem.pszText = (LPSTR) tag.getArtist().c_str();
                      break;
                case 3:
                      lvItem.pszText = (LPSTR) tag.getAlbum().c_str();
                      break;
                case 4:
                      lvItem.pszText = (LPSTR) tag.getComment().c_str();
                      break;
                case 5:
                      lvItem.pszText = (LPSTR) tag.getYear().c_str();
                      break;
                case 6:
                      lvItem.pszText = (LPSTR) tag.getGenre().c_str();
                      break;
                case 7:
                      char str[10];
                      LongToString(tag.getFileSize(), 8, str);
                      lvItem.pszText = (LPSTR) str;
                      break;
                }
          }
    
          *pResult = 0;
    }
    

    www.cteam2005.de
    www.informatik-gruppe.de



  • Ich schau's mir heute abend mal genauer an, bin gerade auf'er Arbeit...

    Gruß T. 🙂



  • Ist noch nicht ganz korrekt, was Du machst.

    Zum Verständinis: Die virtuelle Liste wird nur mit den Daten befüllt, die gerade angezeigt werden sollen.

    Wenn Du diesen Ownerdata Style einsetzt, dann fordert die LVN_GETDISPINFO Nachricht Dich auf, eine Zelle der Tabelle mit Daten zu füllen.

    Vorgehensweise:
    - CListCtrl Membervariable erstellen.
    - Eigenschaft 'Besitzerdaten' oder 'Ownerdata' im Eigenschaften Dialog aktivieren.
    - Im Klassen-Assi Deine Liste auswählen (hier IDC_LIST1) und die Behandlungsroutine für LVN_GETDISPINFO erstellen lassen.
    - Jetzt bekommst Du in OnGetdispinfo über pDispInfo->item.iItem bzw. pDispInfo->item.iSubItem immer genau die Zelle beschrieben, die jetzt gefüllt werden soll.
    - Wichtig: Sobald Deine Applikation ermittelt hat, wieviele Einträge (Zeilen) in Deine Liste insgesamt kommen sollen, sollte das der Liste über m_ctrl_List1.SetItemCount() mitgeteilt werden. Wenn sich die Anzahl ändern sollte, musst Du auch das mitteilen.

    Du kannst also die For-Schleife weglassen und musst stattdessen die Daten mit Hilfe der Koordinaten die Dir LV_DISPINFO liefert, aus dem Vector holen und in die Zelle schreiben die gerade dran ist. Für die nächste Zelle kommt eine neue Nachricht.

    Gruß T. 🙂



  • Super, danke dir! Ich konnte wegen Probleme mit VC++ nicht testen. Werde nun sofort testen. Vielen Dank! 👍



  • Vielen Dank,

    dieser Thread hat mir sehr geholfen.
    Eine "Kleinigkeit" hab ich aber noch. Ich kann ja normalerweise mit
    SetItemData dem LVITEM einen Parameter mitgeben.
    Geht das auch irgendwie in der LVN_GETDISPINFO? Ich braeuchte den Parameter naemlich dringen.
    Ich habe ein abgeleitetes ListCtrl das mir anhand von GetItemData() die Hintergrundfarbe setzt.
    Diese Klasse moechte ich ungern nochmal grossartig veraendern.

    Ich dachte mir jetzt, dass ich mit

    if(pItem->mask & LVIF_TEXT)
    	{
    		ConfP* pEl;
    		csConf.Lock();
    		pEl=conf.getItem(pItem->iItem);
    		csConf.Unlock();
    		if (pE!=NULL)
    		{
    			pDispInfo->item.lParam=43;
    			pItem->mask=pItem->mask | LVIF_PARAM;
    

    eben diesen LVITEM Parameter auf 43 😉 setzen kann. Ich bekomme aber beim auslesen mit GetItemData(iRow) immer 0.

    Gibts da irgendwelche Vorschlaege?
    Oder muss ich wirklich nochmal alle mit SetItemData "ausserhalb" von GETDISPINFO setzen was ziemlich bloed waere.
    vielen Dank
    t2x


Anmelden zum Antworten