Newsgroup: it.comp.programmare.win32
Titolo: Disegni in CListCtrl

Ciao 
qualcuno sa come si fa a disegnare dentro una riga del listcontrol?
Non voglio mettere le icone, ma fare dei disegni con line, rect etc..
Ciao
F

> qualcuno sa come si fa a disegnare dentro una riga del listcontrol?
Qualcosa del genere:
- crei una tua classe CMyListControl derivata da CListCtrl
- implementi le funzioni virtuali DrawItem, e MeasureItem (se vuoi anche la 
CompareItem per mantenere la lista ordinata a tuo piacere)
N.B. Nella DrawItem ricevi un hDC che puoi usare per disegnare tutto quello 
che vuoi.
- nella dialog inserisci un normale controllo CListCtrl e poi con il 
ClassWizard gli assegni una Member Variable di tipo Control che sarà la tua 
CMyListControl e nelle proprietà Styles gli metti Owner draw su Fixed o 
Variable
Eventualmente su 
codeguru.com
 puoi trovare degli esempi 



gRazie Mille Ci provo!
F

 wrote:
Cioa Guglielmo
ce l'ho fatta a fare la funzione virtuale, perň non riesco piů a
scrivere tutte le colonne (di testo) del listcontrol.
Cioč scrivo solo il numero della colonna.
Come posso fare?
ti appendo un pezzo di quelo che ho fatto :
CString pp;
	pp.Format("%i",lpdrawitemstruct->itemData);
 if (nIndex != (UINT) -1)
	{
		 //lpDrawItemStruct->itemData
		dc.DrawText(pp,rcItem,DT_LEFT);
    }
Grazie
Ciao
F

 ha scritto nel messaggio 
news:0d0ti11rdblt51nu8...@4ax.com...

Potresti fare cosě:
- con la GetColumnWidth recuperi la larghezza di ogni colonna (ti serve per 
calcolarti rcItem per ogni colonna che devi tracciare)
- con la GetItemText recpure il testo della colonna (utilizza itemID come 
primo parametro della GetItemText)
- richiami quindi la DrawText N volte per ogni colonna che devi tracciare, 
recuperando il testo opportuno e calcolandoti la posizione esatta.
Per fare una cosa piů generica dovresti usare perň la GetColumn che ti 
restituisce una struttura LVCOLUMN con tutte le informazioni specifiche 
della colonna (allineamento, se ha un'immagine, etc.) 

della colonna (allineamento, se ha un'immagine, etc.) 
Ok Ho fatto tutto però mi spatascia su un casino di caratteri uno
sopra l'altro oppure con distanze "non convenzionali" e poi se muovo
la barra di scorrimento a destra ...peggio che peggio.
Se ti incollo qui sotto la funzione che ho scritto gli dai
un'occhiata?
Grazie grazie
P.s. ci saranno delle cose orribili e sbagliate...me ne vergogno!
void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpdrawitemstruct)
{
LVCOLUMN* Colonna=(LVCOLUMN*)this->m_hWnd; //Questa è una mia
						    //invenzione!!
			//come si fa a inizializzare un puntatore??
	CString Content;
	CDC dc;
    dc.Attach (lpdrawitemstruct->hDC);
	UINT nIndex = lpdrawitemstruct->itemID;
	CRect rcItem(lpdrawitemstruct->rcItem);
	DWORD Dati;
    Dati = lpdrawitemstruct->itemData;
	CString Dati2;
	Dati2.Format("%d",Dati);
	CBrush iBrush;
	iBrush.CreateSolidBrush(RGB(250,210,55));
	CBrush iBrush2;
	iBrush2.CreateSolidBrush(RGB(270,228,21));
	int Spazio=0;
 
	if (lpdrawitemstruct->itemID==5)
	{
		dc.FillRect (rcItem, &iBrush);
	}
	else
		dc.FillRect (rcItem, &iBrush2);
	//delete iBrush;
    if (lpdrawitemstruct->itemState & ODS_FOCUS)
        dc.DrawFocusRect (rcItem);
////////SCRIVO IL TESTO 
		for (int x=0;x<=29;x++)//29 colonne
		{
 Content=this->GetItemText(lpdrawitemstruct->itemID,x);
			dc.DrawText(Content,rcItem,DT_LEFT);
			this->GetColumn(x,Colonna);
			Spazio=Spazio+(Colonna->cx);
			rcItem.left=Spazio;
		}
    dc.Detach ();
}

> MEGACUT
Hem... ci sono un po' di cosette da sistemare.
Ti mando l'esempio stupido stupido per tracciare il testo di N colonne, da 
li puoi prendere spunto per fare tutto ciň che ti serve:
void MyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpdrawitemstruct)
{
 //Preparo il DC
 CDC dc;
 dc.Attach (lpdrawitemstruct->hDC);
 //Conto le colonne
 CHeaderCtrl* pHeader = (CHeaderCtrl*)GetDlgItem(0);
 int nColumnCount = pHeader->GetItemCount();
 //Dimensioni dell'output
 CRect Rect = lpdrawitemstruct->rcItem;
 //Coloro lo sfondo se la linea č selezionata
 if (lpdrawitemstruct->itemState & ODS_SELECTED)
 {
  dc.FillSolidRect (Rect, GetSysColor (COLOR_HIGHLIGHT));
  dc.SetTextColor (GetSysColor (COLOR_HIGHLIGHTTEXT));
 }
 else
 {
  dc.FillSolidRect (Rect, GetSysColor (COLOR_BTNFACE));
  dc.SetTextColor (GetSysColor (COLOR_WINDOWTEXT));
 }
 //Traccio il testo di tutte le colonne
 for (int i = 0; i < nColumnCount; i++)
 {
  //Recupero dalla colonna informazioni sull'allineamento
  LVCOLUMN Column;
  Column.mask = LVCF_FMT;
  GetColumn (i, &Column);
  //Recupero il testo
  CString Text = GetItemText (lpdrawitemstruct->itemID, i);
  //Preparo l'area per tracciare il testo
  Rect.right = Rect.left + GetColumnWidth (i);
  //Traccio il testo seguendo l'allineamento della colonna
  switch (Column.fmt & LVCFMT_JUSTIFYMASK)
  {
  case LVCFMT_CENTER:
   dc.DrawText (Text, Rect, DT_CENTER);
   break;
  case LVCFMT_RIGHT:
   dc.DrawText (Text, Rect, DT_RIGHT);
   break;
  default:
   dc.DrawText (Text, Rect, DT_LEFT);
   break;
  }
  //Preparo il rettangolo per la colonna successiva
  Rect.left = Rect.right;
 }
 //Rilasico il DC
 dc.Detach ();
}

li puoi prendere spunto per fare tutto ciň che ti serve:
Perfetto!
Grazie!
p.s.
ma tu di dove sei? 
Casomai ti capito a casa per una lezione privata?
 :)))

 wrote:
Vorrei chiederti anche un0altra cosa.
IO vorrei cambiare colore della riga del listcontrol in funzione di
una scelta che faccio nella maschera principale.
Cioè, nella maschera c'è una combobox e a seconda di quello che
seleziono la riga dovrebbe essere di colore diverso.
Quello che non  riesco a fare è a prendere il valore selezionato nel
combo perchè mi dà errore.
Ho fatto così:
void CMyListCtrl::DrawItem(LPDRAWITEMSTRUCT lpdrawitemstruct)
{
	CJustInTimeDlg Jdlg;
	 switch(Jdlg.m_Combo_Ordini.GetCurSel())
	 {
	 case 0:
		dc.FillSolidRect (Rect, RGB(250,210,55));
		dc.SetTextColor (GetSysColor (COLOR_WINDOWTEXT));
		break;
	 case 2:
		dc.FillSolidRect (Rect, RGB(250,100,55));
		dc.SetTextColor (GetSysColor (COLOR_WINDOWTEXT));
		break;
	}
Quando prova a fare lo switch mi dà errore di runtime.
Grazie
Ciao

 Ciao
Ops! Quello che hai scritto è sbagliato perchè non puoi accedere a 
m_Combo_Ordini che appartiene ad una Jdlg che hai dichiarato come variabile 
locale della DrawItem ;-)
Se vuoi accedere ad un altro controllo (la ComboBox) contenuta nella stessa 
dialog della MyListCtrl la strada è un po' più lunga e tortuosa.
Ma la mia domanda è: intendi cambiare il colore di sfondo di *TUTTI* gli 
elementi o di personalizzare il colore di ogni singola riga? 

elementi o di personalizzare il colore di ogni singola riga? 
Beh diciamo che voglio fare entrambe le cose.
Prima voglio cambiare il colore di tutte le righe in funzione dei quel
combo.
Poi in funzione di cosa c'č scritto nelle righe, vorrei cambiare il
colore della singola riga per evidenziare certe cose.
Che ne dici?
Grazie 
Ciao

 colore della singola riga per evidenziare certe cose.
Questo è semplice, controlli il contenuto del testo e in funzione di quello 
utilizzi un diverso colore.
Ti ricordo che per ogni elemento della riga puoi assegnare un valore DWORD 
(SetItemData) che puoi utilizzare per i tuoi scopi. 

SetBkColor con parametri diversi.
Aspč...se faccio una variabile privata non riesco a mettrerci un
valore dentro che proviene da OnSelendOkCComboOrd che č il combo del
dialog.
Cioč quando vado a vedere quanto č x in CMyListCtrl mi dice che č
-87456....cioč non ha preso il valore del controllo.
Cioč non riesco a vedere cosa ho scelto nel combo.

 wrote:
Aspč ancora....
senti come ho risolto.
Mi sono informato come fare a passare dei valori variabili tra una
classe e un'altra, cosa che non spaevo fare.
Ho creato una varibile Extern che posso vedere all'interno di tutto il
porgramma (che figata questa cosa!)
e ora mi passo il valore tra una classe e l'altra usando questo ponte.
Cosi prendo il valore con GetCursel lo metto nella variabile globale
e poi la "switccho" all''interno del DRAWITEM

 e poi la "switccho" all''interno del DRAWITEM
Anche se funziona sarebbe stato meglio:
1) Hai una CDialog dove ci sono due controlli: una CMyListCtrl e una 
CComboBox, ok?
2) Nella CDialog intercetti l'evento CBN_SELENDOK della CComboBox e richiami 
il metodo SetBkColor per cambiare il colore
Facile, pulito ed elegante ... e senza variabili globali!

Facile, pulito ed elegante ... e senza variabili globali!
Facile : Per chi lo sa fare :) 
Pulito ed elegante : senza dubbio.
Perň non ho capito una cosa.
l'evento CBN_SelendOK l'ho intercettato e funziona.
Non ho capito come richiamare l'evento SetBkColor del CListcontrol, 
perchč i colori devono cambiare nel ClistCtrl (e non nel combobox,
forse su questo non ero stato chiaro)
Grazie
Ciao.
F

 perchè i colori devono cambiare nel ClistCtrl
Ricapitolando:
- Nella CDialog hai due controlli CMyListCtrl e CComboBox
- Al controllo CMyListCtrl hai assegnato (con il ClassWizard) una Member 
Variable del tipo Control sulla tua CMyListControl (diciamo che l'hai 
chiamata m_MyListCtrl ok?)
- Nella CDialog hai intercettato l'evento OnSelendOk della ComboBox
- Quindi basta che in questo evento richiami m_MyListCtrl.SetBkColor 
(RGB(...))
Se vuoi ti mando un progettino di esempio.

Se vuoi ti mando un progettino di esempio.
No, ho capito....!
Scusami sono un po' stordito...
ok l'ho fatto!
Cambio il colore di tutte le righe, semplicissimo.
Mi ero perso nei meandri di DrawItem senza pensare che quella funzione
č piů che accessibile anche senza usare l'overload...
Quella che invece devo fare esclusivamente da DrawItem č la
colorazione di ogni riga diversamente e ho fatto anche quella.
Per cui dovrei essere un uomo felice ora
 :)
Grazie.


Avrei un'altra domandina!
Se io avessi adesso un'altro CListCtrl, che ho inserito in un altro
Dialog, in cui vorrei implementare un DrawItem diverso da quello
precedente, come faccio?
Cioč, se gli metto OWnerDrawFixed, lui va a prendere la classe
CMyListCtrl che ho generato per l'altro, quando cerca di disegnarlo?
Gazie
Ciao
F

F
Scusami ho fatto una domanda del cacchio!
E' logico che creo un'altra classe derivata da CListCtrl con un'altro
nome e poi la assegno al ListCtrl che mi interessa nel file .h che
definisce quella classe!
Scusa 
ciao
F