Probleme listbox LBS_OWNERDRAWFIXED

Signaler
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008
-
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008
-
Bonjour,
Je galere depuis plusieurs jours pour essayer de mettre des couleurs de fond a certaines lignes de ma listbox...
J'ai trouvé quelques exemples, utilisant notamment LB_INSERTSTRING, LB_SETITEMDATA et WM_DRAWITEM pour le faire
Mais d'apres les codes, ma listbox doit aovir l'attribut LBS_OWNERDRAWFIXED pour que WS_DRAWITEM soit bien executé (sinon je crois qu'il ne va jamais dedans)
Cependant, LBS_OWNERDRAWFIXED n'est pas reconnu sous mon evc++!!!!
Quelqu'un a une idée pourquoi?
Je fais du C en Win32 pour ceux qui n'avait pas compris ^^
hTab[i] = CreateWindowEx(  WS_EX_CLIENTEDGE,  TEXT("LISTBOX"),   NULL,
  WS_VISIBLE|WS_CHILD|LBS_NOTIFY|WS_VSCROLL|WS_TABSTOP|WS_BORDER|LBS_OWNERDRAWFIXED |LBS_USETABSTOPS,...);

error C2065: 'LBS_OWNERDRAWFIXED' : undeclared identifier

Help il faut que j'arrive a mettre ces foutues couleurs!

38 réponses

Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Salut,
Cette constante est définie dans winuser.h. Tu peux essayer de l'ajouter en haut de ton code avec un #define:
#define LBS_OWNERDRAWFIXED    0x0010
J'espère que ça marchera pour toi.
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

J'ai bien rajouté ce que tu m'a di, mais toujours rien a l'horizon!! Help!!
Voici les bouts de code concerné :
#define LBS_OWNERDRAWFIXED    0x0010
  // en haut de mon code comme tu me l'a di
--------------
typedef struct _LBITEM                                         // structure définissant l'item
{
   LPTSTR text;         // texte de l'item
   COLORREF textcolor;  // couleur du texte
   HBRUSH bgbrush;      // brush pour dessiner le fond de l'item
} LBITEM, *PLBITEM;

----------------
  case WM_DRAWITEM:                                          //Dessin des lignes de la listbox  { 
   LPDRAWITEMSTRUCT info = (LPDRAWITEMSTRUCT) lParam;
   PLBITEM item = (PLBITEM) info->itemData;



   SetTextColor(info->hDC, item->textcolor);
   SetBkMode(info->hDC, TRANSPARENT);
 
   FillRect(info->hDC, &info->rcItem, item->bgbrush);
   DrawText(info->hDC, item->text, -1, &info->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER);
  }
-------------------------
Et a la creation de mon tableau :
hTab[i] = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT("LISTBOX"),  NULL, WS_VISIBLE|WS_CHILD|
LBS_NOTIFY|WS_VSCROLL||WS_BORDER| LBS_OWNERDRAWFIXED |LBS_USETABSTOPS,
"Remplissage" de mon tableau :
LBITEM lbitem = {maLigne , rouge , fondBleu } ;
 int test=SendMessage(hTab[i], LB_INSERTSTRING, (WPARAM)0, (LPARAM)maLigne);     
 SendMessage(hTab[i], LB_SETITEMDATA, (WPARAM)test, (LPARAM)&lbitem);
J'insere sinon avec un LB_ADDSTRING qui affiche bien le texte aussi :
//SendDlgItemMessage(hWnd, i, LB_ADDSTRING, 0, (LPARAM)maLigne); 

Voila, je dois faire quelque chose, ou ne pas faire quelque chose, qui fait que WM_DRAWITEM ne semble jamais appelé??? Car les item sont bien "rempli" avec le texte, mais pas de couleur!!
ou alors c'est que le #define LBS_OWNERDRAWFIXED m'enleve juste l'erreur mais ne fonctionne pas??
SNIF SNIF!!!!
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

A signaler que j'ai egalement essayé
#define LBS_OWNERDRAWFIXED    0x0010L

Sans succes...
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
13
Il est possible que ton Windows CE ne prend en charge que les listbox standard. A vérifier.
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Oh moi qui me faisait une joie de voir une reponse, ca commence a me faire peur tout ca!!
Comment je peux verifier ca?
Et si ce que tu suppose se vérifie, comment je peux remedier a cela pour tout de meme mettre des couleurs a mes items de listbox? C'est le dernier truc qui me reste a géré sur ces listbox : mes focus sur les lignes voulues fonctionnent, et j'ai également créer des "colonnes" à l'aide de LBS_USETABSTOPS...
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

"Windows CE .NET provides the ability to change the user-interface skin of the operating system. This is similar to the concept of owner-draw controls, by which a Win32 program can change the appearance of various controls like push buttons, status bars, header controls, ListView controls, and the Tab control. (The desktop supports other owner-drawn items, like the Listbox, that are not supported in Windows CE.) "

STP dis moi que j'ai une solution de rechange! help
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

Et en utilisant un item listview sa doit être possible !

tu as déja essayé ?

+
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Tu veux dire que j'utiliserais une listbox mais que j'insererai des item listview??
Je vois pa trop comment c'est possible
Sinon si tu sous entend utiliser directement une listview au lieu d'une listbox : windows Ce ne prend pa les listview

As tu un exemple d'insertion d'item listview dans une listbox?
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

Non pas du tout utiliser une litview plutot que listbox ^^
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Ok donc utiliser une listbox avec des items a la liste view si je comprends bien...
Je vais essayer, mais d'apres le code que j'ai posté dans mes premiers messages, comment verrai tu ca Omnia?
Je laisse tout tel quel, je dois seulement modifier mes SendMessage? mais faire des listbox.pszText... ne devrait pas trop lui plaire non?
Tu as l'air d'etre assez calé la dessus, donc je suis pres a ecouter tes conseils? ^^
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

mais non en fait je m'explique mal.

Alors c'est assez simple:

au lieu d'utiliser des listbox qui sont assez limités

tu peux utiliser des listview, pour info avec une listview tu pourra faire autant de choses qu'avec les listbox et même plus voila

en gros il suffit de changer le composant et donc toutes les procédure d'ajout d'items, etc ..

voila c tout :)

bonn prog
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

mm désolé j'ai répondu a coté c'est vrais Windows CE ne prend pas en compte les listview.

bon dans ce cas la pour les listbox:

Il faut créer un sousclassment avec l'api SetWindowLong, puis tu crée ta boucle windows et tu traite les message de dessin.

normalement le sous classement va régélé ton problème.

Il y a quelques exemples sur le site sa devrais marché :)

voila bonne prog
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Oki je vais regarder ton API, j'epsere m'en sortir ;)
Le souci c'est que j'ai peur que ma listbox, a partir du moment ou elle ne peut pas accepter le LBS_OWNERDRAWFIXED, elle ne passe jamais dans les messages de dessin justement.
Je vais regarder ta solution, peut etre que c'est tout simplement pas jouable sinon sous Windows CE...
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Peux-tu m'expliquer rapidmeent en quoi consiste SetWindowLong en fait? car les exemple que j'ai vu consistent plutot en du redimensionnement de controle, ou des recuperations de champs texte...
De plus comme je le crains je pense que ma listbox doit avoir le champ LBS_OWNERDRAWFIXED, chose impossible sous Windows CE...
Et sinon , tu dis "puis tu crée ta boucle Windows", je ne saisis pas trop là non plus. Je suis désolé tu dois me prendre pour un nul
Si j'ai bien compris, le SetWindowLong doit se faire apres le création de la listbox, et le deuxieme parametre concerne ce qu'on veut justement modifier...?
Désolé je ne suis pas très clair mais la je ne maitrise pas du tout
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

Non t'inquiète s'est assez simple,

lorsque l'on dev et que l'on utilise les api.

tu as une déclaration avec ton winmain et tu associes à ta forme principale une fonction qui va gérer les messages.

et bien le fait de sous classer un composant , on attribut au composant une fonction qui va gérer les messages de même manière.

maintenant pour ton cas une fois que tu as sous classé ta listbox il ne te reste plus qu'a géré le message WM_DRAWITEM

pour ton composant il suffit de lui ajouter la propriété BS_OWNERDRAW

voila :)

pour un exemple j'utilise un sous classement sur une listview dans une source que je viens d'ajouter

http://www.cppfrance.com/codes/WIN32-DEV-CPLUSPLUS-SNIFF-RAW-SOCKET-AVEC-ANNALYSE_43049.aspx

bon prog
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Merci beaucoup je regarde ca dès que possible et te tiens au courant! ;)
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

ReSalut omnia, j'ai fais les modification ssur tes conseils, et l'exemple que tu m'a fourni,
cependant j'ai l'impression qu'il ne passe pas dans ma fonction ( j'ai mis des messageBox basiques pour vérifier qui ne se déclenchent pas). De plus, mes items reste désespérement blancs, tandis que maintenant le focus a disparu sur ceux pour lesquels je l'avait mis, et on peut maintenant en selectionner plusieurs :s
C'est sans doute une mauvaise manip' du SetWindowLong, c'est pourquoi je te montre les bouts de code sans doute responsable :

WNDPROC ListBoxProcSousClassement; 
// déclaré en global
la fonction ListBoxProc :
LRESULT CALLBACK ListBoxProc(HWND hwnd, UINT Msg, WPARAM Wparam, LPARAM lParam)
{
// MessageBox(NULL,TEXT("listboxproc"),TEXT(""),MB_OK);
  //traitement pour pour DrawItem
  if (Msg = = WM_DRAWITEM)
  {
//   MessageBox(NULL,TEXT("drawitem"),TEXT(""),MB_OK);
  SetTextColor((HDC)Wparam,rouge);
  SetBkColor((HDC)Wparam,rouge);
    return (BOOL) fondRouge;
  }  
  //retour la fonction de gestion de la listbox
  return CallWindowProc(ListBoxProcSousClassement, hwnd, Msg, Wparam, lParam);   
}

et dans mon WM_CREATE :
hTab[i] = CreateWindowEx( WS_EX_CLIENTEDGE, TEXT("LISTBOX"),   NULL,
      WS_VISIBLE|WS_CHILD|LBS_NOTIFY|WS_VSCROLL|WS_BORDER|BS_OWNERDRAW|LBS_USETABSTOPS|WS_TABSTOP,
      atoi(GetAbscisse(i)),atoi(GetOrdonnee(i))+15, atoi(GetLargeur(i,"T")), atoi(GetHauteur(i,"T"))-5,
  hWnd, HMENU(i), hinst, NULL);
le BS_OWNERDRAW n'apporta pes d'erreur,c'es deja un bon point ;)
puis pour ajouter mes items apres quelques calculs :
 SendDlgItemMessage(hWnd, i, LB_ADDSTRING, 0, (LPARAM)affichageLigne); 
 SendMessage(hTab[i], LB_SETTABSTOPS, indiceColonne+1, (LPARAM)stops); 
 ListBoxProcSousClassement = (WNDPROC)SetWindowLong(GetWindow(hTab[i],i), GWL_WNDPROC,(LONG)ListBoxProc); 
Le premier Send permet d'ajouter la ligne, le second gère mes tabstop pour les colonnes et enfin le fameux SEtWindowLong 

Cela vient peut etre du premier parametre du SetWindowLong? J'ai essayé un GetWindow, GetDlgItem, sans succès... Et pourtant j'ai l'impression que ta solution pourrait marcher!
Où me serais-je trompé a ton avis?

          
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

En fait c'est bien ce que tu as fait maintenant que sa fonctionne il faut que tu dessines l'interieur des lignes:

- gestion du focus
- écriture des caractères
...

une autre très bonne source sous cpp a regarder : (je pense que tu y trouvera ton bonheur)
http://www.cppfrance.com/codes/PROGRESSBAR-DANS-LISTVIEW-WIN32_24229.aspx

il manque seulement une chose pour toi

pour la réécriture du texte il faudra récupérer le texte précédement écrit puis le redessiné

voici un bout de code que j'utilise actuellement sur une listview a réadapter pour ta listbox:

case WM_DRAWITEM:
             //traitement par ligne
             lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
       
            //gestion de la sélection
            if(ListView_GetItemState(HListView, lpDrawItem->itemID, LVIS_SELECTED) & LVIS_SELECTED)
            {
              // L'élément est séléctionné
              FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, GetSysColorBrush(COLOR_HIGHLIGHT));
              SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
            }
            else
            {
              FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, GetSysColorBrush(COLOR_WINDOW));
              SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_MENUTEXT));
            }           
              
            ListView_GetItemRect(HListView, lpDrawItem->itemID, &rect, LVIR_BOUNDS);
            x = rect.left; // x dépend de la position de la scroll bar horizontalle
            // en tous cas on a toujours x <= 0
            rect.top = lpDrawItem->rcItem.top;
            rect.bottom = lpDrawItem->rcItem.bottom;         
           
            //les 5 première colonnes
            for (i=0;i<5;i++)
            {
                // nb colonne
                y = ListView_GetColumnWidth(HListView, i);
                rect.left = x + 2;
                rect.right = x + y - 2;
                //récupération du texte de l'item
                ListView_GetItemText(HListView,lpDrawItem->itemID,i,tmp,TMP_DEFAULT);
                DrawText(lpDrawItem->hDC,tmp, strlen(tmp), &rect, DT_VCENTER);
                x += y;  
            }
           
            //la 6 ème colonne  (progress bar + texte)
            y = ListView_GetColumnWidth(HListView, 5);
            rect.left = x;
            rect.right = x + y;
            rect.top = lpDrawItem->rcItem.top + 1;
            rect.bottom = lpDrawItem->rcItem.bottom - 1;
            FillRect(lpDrawItem->hDC, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
           
            // Dessine de 0 au %
            rect.left = x + 1;
            i = Progress[lpDrawItem->itemID] * (y - 1) / 100;
            rect.right = x + i + 1;
            rect.top = lpDrawItem->rcItem.top + 2;
            rect.bottom = lpDrawItem->rcItem.bottom - 2;
            if(Progress[lpDrawItem->itemID])
              FillRect(lpDrawItem->hDC, &rect, Hb1);
       
            // Dessin du % à 100
            rect.left = x + i + 1;
            rect.right = x + y - 1;
            if(Progress[lpDrawItem->itemID] != 100)
              FillRect(lpDrawItem->hDC, &rect, Hb2);
             
            //ajout d'un test pour éviter que le texte ne disparaisse si l'item est sélectionné
            if((ListView_GetItemState(HListView, lpDrawItem->itemID, LVIS_SELECTED) & LVIS_SELECTED) &&(Progress[lpDrawItem->itemID]<60))
            {
              // L'élément est séléctionné
              SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_MENUTEXT));
            }
           
            //texte dans la barre de progression : 0%
            rect.left = x+ y/2;
            rect.right = x + y;
            rect.bottom +=2;
            rect.top-=2;
            sprintf(tmp,"%d%%",Progress[lpDrawItem->itemID]);
            DrawText(lpDrawItem->hDC,tmp, strlen(tmp), &rect, DT_VCENTER); 
        break;
Messages postés
198
Date d'inscription
lundi 24 avril 2006
Statut
Membre
Dernière intervention
3 avril 2008

Au bord de la crise de nerfs... meme si je peux m'estimer heureux que tu repondes encore (peut etre plus longtps! :D)
Bon alors, j'ai essayer tout basiquement sans gérer le focus, de mettre une meme couleur pour chaque item, tout simplement.
Et donc toujours rien, pourtant mon WM_DRAWITEM semble bien formé. comment je pourrais vérifier que mon prog asse bien dans ma fonction sous-classée? car j'ai vraimeent des doutes sur le fait qu'elle y passe bien (avec un débuggage, lorsque j'arrive sur la ligne l'appelant, le Ctrl+F11 passe directement a la ligne suivante, ne rentre pas dans la fonction...)
Mais cela est peut etre normale, meme si j'ai des doutes... Snif snif
J'ai remis ma strucure pour créer mes items, et changer mon WM_DRAWITEM, ainsi : 
   
typedef struct _LBITEM
{
   LPTSTR text;         // texte de l'item
   COLORREF textcolor;  // couleur du texte
   HBRUSH bgbrush;      // brush pour dessiner le fond de l'item
} LBITEM, *PLBITEM;       
............................................................................................................................
LRESULT CALLBACK ListBoxProc(HWND hwnd, UINT Msg, WPARAM Wparam, LPARAM lParam)
{
  if (Msg = = WM_DRAWITEM)
  {
        LPDRAWITEMSTRUCT info = (LPDRAWITEMSTRUCT)lParam;
        PLBITEM item = (PLBITEM) info->itemData;



        SetTextColor(info->hDC, item->textcolor);
        SetBkMode(info->hDC, TRANSPARENT);




        FillRect(info->hDC, &info->rcItem, item->bgbrush);
        DrawText(info->hDC, item->text, -1, &info->rcItem, DT_SINGLELINE | DT_VCENTER | DT_CENTER); 
        return 0; 
  }
  return CallWindowProc(ListBoxProcSousClassement, hwnd, Msg, Wparam, lParam);   
}
............................................................................................................................
LBITEM lbitem = {ConvertAnsiToUnicode(affichageLigne) , rouge , fondBleu } ;
SendMessage(hTab[i], LB_INSERTSTRING, (WPARAM)0, (LPARAM)ConvertAnsiToUnicode(affichageLigne));  
SendMessage(hTab[i], LB_SETITEMDATA, (WPARAM)0, (LPARAM)&lbitem);
SendMessage(hTab[i], LB_SETTABSTOPS, indiceColonne+1, (LPARAM)stops); 
jusqu'ici je pense qu'il crée bien tout, et ensuite il ne rentre pas dans la ligne suivant a mon avis...
 ListBoxProcSousClassement = (WNDPROC)SetWindowLong(GetDlgItem(hTab[i],i), GWL_WNDPROC,(LONG)ListBoxProc);
 
j'ai de gros doutes sur mon GetDlgItem : hTab[i] represente ma listbox, le i es peut etre faux, dois-je mettre une constante, ou rien ne te choque?

ne devrait-il pas y avoir ma structure de transmise également?
    
Messages postés
240
Date d'inscription
jeudi 9 janvier 2003
Statut
Membre
Dernière intervention
22 mars 2009

mm et une question dans ta fenêtre principal tu as des appels sur WM_DRAWITEM ???

normalement sa devrais, si c'est le cas s'est la que tu dois mettre ton code

PS : désolé je suis au taff je te répondrais ce soir , si tu t'en sort pas je ferait un projet et je le publierais .

++