Προς το περιεχόμενο

Listview στη C++


georginos1989

Προτεινόμενες αναρτήσεις

  • Απαντ. 62
  • Δημ.
  • Τελ. απάντηση

Αλλάζοντας το Width property κάθε ListView Column μέσο του "Object Inspector" (μπορείς και μέσο κώδικα αλλά καθώς δεν έχεις εξοικείωση με την VCL άφησε το για αργότερα). Αν θες το Column να προσαρμόζει το πλάτος του αυτόματα στο περιεχόμενο του Item που παρουσιάζει ορίζεις το Width σε -1, αν θες να προσαρμόζει το περιεχόμενο του με βάση τον τίτλο του (Caption) τότε ορίζεις το Width σε -2, διαφορετικά ορίζεις κατευθείαν το Width στο επιθυμητό πλάτος (πχ. 100). Προσωπικά σε συμβουλεύω να επιλέξεις είτε το -2 ή να ορίσεις με το χέρι ένα ικανό πλάτος και να αποφύγεις την αυτόματη προσαρμογή του (-1) καθώς μπορεί να καταστήσει το πρόγραμμα δύσχρηστο.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Εβαλα και τισ 3 στηλες στο -2 το width... Τώρα ομως αν βαλω μια λεξη με 7 γραμματα βγαζει σφαλμα....

 

" List index out of bounds(1) "

 

Αν αντι να βαλω το -2 κανω το autosize=true σε καθε column δεν θα γίνει?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

" List index out of bounds(1) "

Αυτό πρόκειται για σοβαρό σφάλμα το οποίο υποδεικνύει ότι σε κάποια φάση εκτέλεσης του προγράμματος (πιθανότατα) κάποιο TListItem του TListView σου δεν περιέχει τον αναμενόμενο αριθμό SubItems οπότε ακολούθως γίνεται κάποια αναφορά στο ανύπαρκτο αυτό SubItem είτε από τον κώδικα σου (πχ. από τον κώδικα σχεδίασης) είτε από την VCL και φυσικά παρουσιάζεται το συγκεκριμένο exception. Συγκεκριμένα το "(1)" σημαίνει ότι κάποιο κομμάτι κώδικα δοκίμασε να διαβάσει το δεύτερο SubItem ενός TListItem που όμως δεν υπάρχει καταχωρημένο στην λίστα SubItem του TListItem. Τέτοιου είδους σφάλματα θέλουν μεγάλη προσοχή διότι καμία φορά περνάνε απαρατήρητα μέχρι να "σκάσουν", οπότε φρόντιζε πάντα να γεμίζεις όλα τα SubItems του TListItem σου, έστω με κενά (""). Διαφορετικά όπου γράφεις κώδικα που διαχειρίζεται SubItems θα πρέπει να συμβουλεύεσαι το TListItem->SubItems->Count ώστε να είσαι σίγουρος ότι το SubItem που θέλεις να διαβάσεις έχει δηλωθεί.

 

Αν αντι να βαλω το -2 κανω το autosize=true σε καθε column δεν θα γίνει?

Ναι, πρόκειται για το ίδιο πράμα.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Τωρα που το εκανα με το autosize οσο μεγαλη λεξη και να βαλω δεν βγαζει αυτο σο σφαλμα

Όπως σου είπα, το σφάλμα αυτό δεν έπρεπε σε καμία περίπτωση να παρουσιάζεται με Width = -2. Το ότι δεν παρουσιάζεται με AutoSize αλλά μόνο με Width = -2 σημαίνει είτε ότι πέτυχες κάποιο ιδιόρρυθμο bug της VCL (δύσκολο..) στο Width = -2 είτε στο AutoSize. Εξαρτάται από ποία πλευρά βλέπεις το πρόβλημα. Για να είσαι σίγουρος πάντως ότι ο κώδικα σου είναι σωστός πρέπει να πιστοποιήσεις ότι σε κάθε περίπτωση κάθε TListItem σου έχει δηλωμένα όλα τα απαραίτητα SubItems καθώς το σφάλμα αυτό υποδεικνύει ότι υπό συνθήκες κάποιο TListItem έχει λιγότερα SubItems. Από την άλλη πλευρά βέβαια, αφού κάνεις την δουλειά σου έτσι, ok συνεχίζεις και αν προκύψει κάποιο πρόβλημα στο υπόλοιπο πρόγραμμα, το εξετάζεις τότε περισσότερο επισταμένα (έχεις ήδη ενημερωθεί από την VCL ότι κάτι πάει κάπου στραβά).

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Να σε ρωτησω και κατι αλλο στο listview... Πως θα κάνω τα γράμματα σε εκεινα τα subitem poυ βαζω χρωμα να μην φαίνονται? Να υπάρχει δλδ μόνο το χρώμα...

Εκανα για αρχη να δω πως φαίνεται τα γραμματα ασπρα αλλά καλυτερα θα είναι να μην εχει γραμματα

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για να γίνει αυτό θα πρέπει να προβείς σε ορισμένες αλλαγές όσον αφορά τον κώδικα του OnAdvanceCustomDrawSubItem event.

 

Καταρχήν θα πρέπει να ζητήσουμε από την VCL να βάφει το κείμενο του SubItem που επιθυμούμε να κρύψουμε με το ίδιο χρώμα που βάφει το φόντο του (background).

 

Αυτό επιτυγχάνεται εύκολα με αυτή την εντολή:

 

>
ListView1->Canvas->Font->Color = ListView1->Canvas->Brush->Color;

 

Αυτός ο κώδικας μας δίδει το παρακάτω οπτικό αποτέλεσμα:

 

itemdrawa.png

 

Όπως βλέπεις υπάρχει πρόβλημα, διότι όταν επιλέξουμε το TListItem τότε το TListView αλλάζει τα χρώματα των SubItems ώστε το TListItem να ξεχωρίζει όντας επιλεγμένο και έτσι το περιεχόμενο του SubItem φαίνεται.

 

Για να αντιμετωπίσουμε αυτό το πρόβλημα θα πρέπει να γράψουμε λίγο ακόμα κώδικα στο OnAdvanceCustomDrawSubItem event.

Συγκεκριμένα ελέγχουμε το State set του event αν είναι σε κατάσταση cdsSelected (State.Contains(cdsSelected)) και αν ναι, τότε με την βοήθεια της Windows API ρουτίνας ListView_GetSubItemRect βρίσκουμε τις διαστάσεις (TRect) του SubItem που θέλουμε να αποκρύψουμε και ύστερα με την βοήθεια της VCL ρουτίνας TCanvas->FillRect διαγράφουμε το SubItem σχεδιάζοντας πάνω του ένα ορθογώνιο με το χρώμα επιλογής που χρησιμοποιεί το TListView μας (Canvas->Brush->Color = clHighlight). Τέλος ενημερώνουμε την VCL με το DefaultDraw = false; ότι αναλαμβάνουμε την πλήρη ευθύνη σχεδιάσεις στο TListItem SubItem.

 

Ολόκληρος ο κώδικας:

>
	if(Stage == cdPrePaint)
		if(SubItem == 1)
		{
			if(Item->SubItems->Strings[subItem - 1] == "1")
				ListView1->Canvas->Brush->Color = clRed;
			if(Item->SubItems->Strings[subItem - 1] == "2")
				ListView1->Canvas->Brush->Color = clGreen;
			if(Item->SubItems->Strings[subItem - 1] == "3")
				ListView1->Canvas->Brush->Color = clBlue;

			// Hide SubItem Text by making Brush & Font color the same!
			ListView1->Canvas->Font->Color =
               	ListView1->Canvas->Brush->Color;

			// Is item selected?
			if(State.Contains(cdsSelected))
			{
				TRect SubItemRC;

				// Get SubItem rectangle dimensions (WinAPI)
				if(ListView_GetSubItemRect(ListView1->Handle,
					Item->Index, SubItem, LVIR_BOUNDS, &SubItemRC))
				{
					// Set Canvas brush color to Windows Highlight color
					ListView1->Canvas->Brush->Color = clHighlight;
					// Erase (forcefully) the original SubItem contents!
					ListView1->Canvas->FillRect(SubItemRC);
					// Override "Selected Item" drawing!!
					DefaultDraw = false;
				}
			}
		}
		else
			ListView1->Canvas->Brush->Color = clWhite;

 

Τελικό οπτικό αποτέλεσμα:

 

itemdrawb.png

---

Η συμβουλή μου πάντως είναι να κρατάς τα SubItem κενά όταν δεν χρειάζονται κάποιο στοιχείο μεταφέροντας τις πληροφορίες αυτές στο TListItem->Tag member που μπορεί να δείχνει σε κάποιο pointer με πλούσια δεδομένα κλπ. Ξέρω ότι μπορεί να φαίνεται τώρα περιττή πολυτέλεια αλλά σε μεγάλα προγράμματα η αποσύνδεση των δεδομένων από την οπτική αναπαράσταση τους στο TListView αρκετές φορές «λύνει τα χέρια».

 

Καλή συνέχεια!

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Έχω βάλει τον παρακάτω κωδικα στο ondouble click tou listview και θέλω όταν θα κανει διπλό κλικ να ανοιγει αλλη φορμα.. Ειδα αυτο που με ειχες δειξει αλλά επειδη μαλλον δεν με βολευει μηπως γινεται καπως αλλιως.. Εγω δοκιμαζω να ανοιξω την φορμα που θελω με showmodal αλλα χτυπαει Linker error ...

Επίσης θέλω να στελνω τα στοιχεια του ιτεμ που επιλεγει σε editbox στην φορμα που ανοιγει.. Αυτό ενταξυ γινετε... Αλλά μου βγαζει το σφάλμα οταν παω να ανοιξω την φορμα

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 2 εβδομάδες αργότερα...

Μηπως ξερεις κανενα καλο βιβλιο για αντικειμενοστραφη προγραμματισμο?

Πως να σχεδιαζεις δλδ αντικειμενοστραφη προγραμματα.

Κανουμε στο τει ενα μαθημα τεχολογια λογισμικου και εχει αντικειμενοστραφη προγραμματισμο με κλασσεις και τετοια και uml design patterns (πχ factory, proxy singleton....)

Επειδη εχουμε να κανουμε και ενα προτζεκτ προσπαθω να τα κατανοησω ολα αυτα ώστε να κανω καλυτερο το προτζεκτ

 

Αν ξερεις καποιο βιβλιο....

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • 3 εβδομάδες αργότερα...

Μπορείς να διαβάσεις την τρέχουσα ώρα & ημερομηνία του υπολογιστή με την βοήθεια της ρουτίνας Now() η οποία επιστρέφει ένα αντικείμενο TDateTime. Μετά μπορείς να αφαιρέσεις από αυτό -n ημέρες με την βοήθεια της ρουτίνας IncDay, ομοίως με την IncMonth μπορείς να αφαιρέσεις -n μήνες λαμβάνοντας το ανάλογα ενημερωμένο TDateTime.

 

Η IncDay και η IncMonth είναι δηλωμένες στο "DateUtils.hpp" το οποίο πρέπει να συμπεριλάβεις (#include) στον κώδικα σου.

 

Ακολουθεί ένα παράδειγμα VCL σε ρυθμό κονσόλας που επιδεικνύει τα παραπάνω:

 

>
//-IncDay & IncMonth demo, Dx------------------------------------------------

#include <vcl.h>
#include <DateUtils.hpp>
#include <iostream>
#pragma hdrstop

#include <tchar.h>
//---------------------------------------------------------------------------

using namespace std;

#pragma argsused
int _tmain(int argc, _TCHAR* argv[])
{
wcout << "Today   = " << Now().DateString().w_str()<<endl;
wcout << "-7 days = " << IncDay(Now(), -7).DateString().w_str()<<endl;
wcout << "-1 month= " << IncMonth(Now(), -1).DateString().w_str()<<endl<<endl;

wcout << "Press Enter to exit";
cin.get();
return 0;
}
//---------------------------------------------------------------------------

ΕΞΟΔΟΣ:

 

>Today   = 14/1/2011
-7 days = 7/1/2011
-1 month= 14/12/2010

Press Enter to exit

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Αρχειοθετημένο

Αυτό το θέμα έχει αρχειοθετηθεί και είναι κλειστό για περαιτέρω απαντήσεις.


  • Δημιουργία νέου...