Rafraichissement (repaint) de listbox transparente [WIN32-nonMFC]

Signaler
Messages postés
7
Date d'inscription
vendredi 14 mars 2008
Statut
Membre
Dernière intervention
3 novembre 2008
-
Messages postés
571
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
5 décembre 2013
-
Bonjour,

J'ai une listbox sur une application skinée avec un bmp.
Cette dernière est transparente mais lorsque je clique sur un élément de la liste, la barre de selection ne s'efface pas. J'ai remarqué que lorsque je fais invalidateRect() + UpdateWindow(), ca réglait le problème, sauf que je vois le bmp se redessiner.
En fait, ça fait suite à mon précédent post concernant une static transparente. Donc j'ai éssayé d'appliquer la même méthode que m'avait donnée racpp, sauf que là, j'ai le bmp qui passe devant les items de la listbox :-)
 (ce qui pourrait être génant pour l'utilisateur )

Quelle est alors la bonne méthodeà utiliser ?

Voici un bout de code :

Lors d'un click dans la liste, je récupère juste le texte de l'item, c'est là que je faisait le InvalidateRect et UpdateWindow:
_filenameplay est une variable membre.

                case IDL_CLIPLIST:
                    if(HIWORD (wParam) == LBN_SELCHANGE)
                    {
                        //InvalidateRect(m_hWnd, 0, 0);
                        //UpdateWindow(m_hWnd);
                        if(_filenameplay != NULL) delete[] _filenameplay;
                        int iIndex  = SendMessage (m_hClipListbox, LB_GETCURSEL, 0, 0);
                         int iLength = SendMessage (m_hClipListbox, LB_GETTEXTLEN, iIndex, 0) + 1 ;
                        _filenameplay = new char[iLength];
                        SendMessage (m_hClipListbox, LB_GETTEXT, iIndex, (LPARAM) _filenameplay);
                    }

C'est là que je précise que je veux une listbox transparente :

        case WM_CTLCOLORLISTBOX:
            if ((HWND)lParam==m_hClipListbox)
            {
                SetTextColor((HDC)wParam,RGB(255,255,255));
                SetBkColor((HDC)wParam,TRANSPARENT);
                return (INT_PTR)GetStockObject(NULL_BRUSH);
            }
            break;

Quand je lance l'appli, l'affichage initial est impécable, mais si je click sur un item, les surlignages de sélection ne s'éffacent pas.
Plus fun encore, si j'ai suffisament d'éléments dans ma liste pour avoir une scroll bar dedans, dès que je scroll, le fond des items de la liste passent en noir sur toute la ligne au lieu d'uniquement sous leur textes.

J'espere avoir été un minimum clair,
Merci par avance pour vos réponses.

6 réponses

Messages postés
571
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
5 décembre 2013

J'ai deja eu ce probleme pour un edit (notamment quand on sélectionne une partie du texte, impossible de modifier la couleur de la selection) et le seul moyen que j'ai trouvé c'est de mettre des invalidateRect() partout. Du style

        case WM_KEYDOWN:
        {
            long style = GetWindowLong(hwnd, GWL_STYLE);
            if (style & ES_MULTILINE) {
                InvalidateRect(hwnd, 0, 1);
            }
          }
        break;
        case WM_VSCROLL:
        {
            long style = GetWindowLong(hwnd, GWL_STYLE);
            if (style & ES_MULTILINE) {
                InvalidateRect(hwnd, 0, 1);
            }
          }
        break;

        case WM_HSCROLL:
        {
            long style = GetWindowLong(hwnd, GWL_STYLE);
            if (style & ES_MULTILINE) {
                InvalidateRect(hwnd, 0, 1);
            }
          }
        break;

etc ....
et de memoire je redessine ma listBox au niveau du message WM_CTLCOLORLISTBOX ( a verifier) en fait j'ai uttilisé le programme fournis avec visual studio spy++ pour voir dans quel ordre sont envoyé les commandes pour reperer laquelle est la derniere, pour etre sur que rien ne sera redessiné par dessus.
Apres j'ai pas compris "voir le bmp se redessiner" ?
Messages postés
7
Date d'inscription
vendredi 14 mars 2008
Statut
Membre
Dernière intervention
3 novembre 2008

Bonsoir,
En fait, quand je dis que je vois le bmp se redéssiner, c'est juste que j'ai des traits horizontaux très brefs, mais pas beaux.
Je vais tester la solution de mettre des InvalidateRect() et te dirais le résultat.
Merci,
Dan.
Messages postés
7
Date d'inscription
vendredi 14 mars 2008
Statut
Membre
Dernière intervention
3 novembre 2008

En fait je pense qu'on ne s'est pas compris, ce que je souhaite, c'est redéssiner ma listbox proprement.
Elle n'est absolument pas multiligne. Mais vu qu'elle ne se redéssine pas, elle garde le surlignage de la sélection précédente.
Merci,
Dan.
Messages postés
571
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
5 décembre 2013

Si tu voit le bmp se redessiner, c'est que tu ne doit pas utliser de "double buffer". Le code que je j'ai donné n'est qu'un exemple, regarde mes sources sur une je customise une listbox complete avec les scroolbar mais uniquement la bordure (en fait sur cette source je rempli le fond en uni, mais si tu utilises une couleur transparente pour recrire les items, ca devrait marcher avec une image). Et je viens de verifier su r une vielle souce c'est bien le message WM_CTLCOLORLISTBOX que je traite pour mettre une image en fond de la listbox.
Messages postés
7
Date d'inscription
vendredi 14 mars 2008
Statut
Membre
Dernière intervention
3 novembre 2008

Je ne souhaite pas faire de customisation quelle qu'elle soit hormis la transparence de la listbox. Comme je l'ai précisé, j'intercepte le message suivant :

        case WM_CTLCOLORLISTBOX:
            if ((HWND)lParam==m_hClipListbox)
            {
                SetTextColor((HDC)wParam,RGB(255,255,255));
                SetBkColor((HDC)wParam,TRANSPARENT);
                return (INT_PTR)GetStockObject(NULL_BRUSH);
            }
            break;

Mon but est d'éviter de faire des InvalidateRect() à tout bout de champ.
Il doit bien y avoir un moyen propre de repaindre une listbox.

Merci,
Dan.
Messages postés
571
Date d'inscription
samedi 3 avril 2004
Statut
Membre
Dernière intervention
5 décembre 2013

A ma connaissance ce que tu veux faire est impossible car en retournant NULL, tu as un fond tranparent, mais qui ne s'efface plus (surlignage de sélection, ou probleme de persistance quand tu fait defiler la liste).
Je ne voit que trois methodes :
1 - Refaire une listbox complete en ownerdraw (je peux te filer un code en mfc a convertir) mais y a du taff, traiter
WM_ERASEBKGND pour reafficher le fond
.
2- Ttricher en reaffichant un fond a coup de invalidateRect() a chaque modif de la listbox (truc de barbare).
3- Au lieu de retourner NULL tu retourne un handle vers une brush contenant l'image du fond mais vide, c'est ce que je fait pour mon edit mais pareil c'est du bricolage.

Mais la "transparence" consiste a redessiner le fond vide et reecrire par dessus avec une couleur ayant un fond transparent, soit tu le memorises avant de dessiner ta listbox, soit via un fichier externe.