IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

CListCtrl, hauteur d'un item, CImageList et fusion de bitmaps


Sujet :

MFC

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 114
    Points : 56
    Points
    56
    Par défaut CListCtrl, hauteur d'un item, CImageList et fusion de bitmaps
    Bonjour,

    je souhaiterais developper un CListCtrl avec la possibilité de spécifier la hauteur d'un item en mode Report.
    A ma connaissance il existe plusieurs facons de le faire dont les principales sont
    decrite sur ce site
    http://www.codeproject.com/listctrl/changerowheight.asp.

    J'ai implementé les solutions données et cela fonctionne bien sauf dans un cas lorsque le control est redimensionné et qu'une scrollbar apparait.Dans ce cas
    j'ai essayé de gérer la scroll avec des Scrollinfo mais sans succès.
    Comme au depart les méthodes décrites relèvent un peu de la bidouille, cela ne m'etonne pas que j'ai un souci avec le scrolling.

    Par conséquent j'aimerais essayer une idée qui consiste a modifier (ou créer) une image list qui a la bonne taille en hauteur.
    Prenons le cas ou j'ai deja une imagelist associée a mon CListCtrl, j'ai ajouté une méthode SetItemHeight pour spécifier la taille d'un item et j'aimerais fusionner l'image liste existante dans une plus grande.

    Donc ma question est :

    1)comment récuperer la couleur transparente asscociée a une ImageList

    2)comment créer une CBitmap de taille et de couleur donnée.
    Pour le moment j'ai codé le code ci-dessous mais je ne suis pas sur de moi.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    BOOL CListCtrlCommands::CreateBitmap(CBitmap& bmp, int nWidth, int nHeight, COLORREF crfColor)
    {
    	BOOL bRet = FALSE;
     
    	CDC memDC; 
    	bRet = memDC.CreateCompatibleDC(NULL);
    	bmp.CreateCompatibleBitmap(&memDC, nWidth, nHeight);
    	memDC.SelectObject(&bmp);
    	CBrush brushBk;
    	brushBk.CreateSolidBrush( crfColor );
    	RECT rcBkGnd = {0, 0, nWidth, nHeight};
    	memDC.SelectObject( &brushBk );
    	memDC.FillRect(&rcBkGnd, &brushBk);
     
    	return bRet;
    }
    3)Comment fusionner les deux bitmaps, celle venant de CreateBitmap avec celle de l'imagelist ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // Merge two bitmaps by vertically centered the small inside the big one
    // bmpSmall comes from ImageList, bmpBig is the bitmap created by CreateBitmap
    BOOL CListCtrlCommands::MergeBitmaps(CBitmap& bmpBigOut, CBitmap& bmpSmall, CBitmap& bmpBig )
    {
    //????
    }
    4) est ce que mon approche a une chance de marcher un jour ?

  2. #2
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Salut,

    Si j'ai bien tout compris, tu veux créer une nouvelle ImageList avec une hauteur plus importante à partir de l'ImageList original ?

    L'ImageList de départ a deux bitmap normalement, l'image elle-même et son masque pour la gestion de la transparence.

    Tu récupères ces deux bitmaps par la fonction ImageList_GetImageInfo

    Je peux t'en dire plus, si tu me confirmes que c'est bien ça que tu veux faire

    @+

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 114
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par stephdim Voir le message
    Salut,

    Si j'ai bien tout compris, tu veux créer une nouvelle ImageList avec une hauteur plus importante à partir de l'ImageList original ?

    L'ImageList de départ a deux bitmap normalement, l'image elle-même et son masque pour la gestion de la transparence.

    Tu récupères ces deux bitmaps par la fonction ImageList_GetImageInfo

    Je peux t'en dire plus, si tu me confirmes que c'est bien ça que tu veux faire

    @+
    Oui c'est bien ca.
    Pour le GetImageInfo je m'en sers deja et je n'avais pas vu qu'il y avait un handle associé au masque.
    Donc la chose suivante doit fonctionner non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    CBitmap bmp;
    IMAGEINFO imgInfo;
    pImgList->GetImageInfo(0, &imgInfo);
    VERIFY(bmp.Attach(imgInfo.hbmMask));
    HDC hMemDC = ::CreateCompatibleDC( NULL );
    HBITMAP hOldBmp = (HBITMAP) ::SelectObject(hMemDC, bmp);
    COLORREF clrMask = ::GetPixel(hMemDC, 1, 1);
    VERIFY(::SelectObject(hMemDC, hOldBmp));
    VERIFY(::DeleteDC(hMemDC));

    Mais ensuite c'est le reste qui me semble plus difficile car je dois recreer une image liste en changeant la hauteur et peut etre meme la largeur car je ne sais pas si on peut associer des images rectangulaires a un CListCtrl

  4. #4
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Oui tu peux associer une image de la taille que tu veux,donc pas la peine de toucher à la largeur, sinon tu auras des blancs entre l'icone et le texte ...

    Pas la peine de recuperer clrMask, puisque tu manipules un masque.

    L'idée est de redimensionner ton Bitmap de l'image et aussi celui du masque, et de recreer une ImageList à partir de ces deux bitmaps et non à partir d'une couleur clrMask.

    Un masque est un bitmap monochrome.

    Donc tu créées un nouveau bitmap avec la meme largeur que ton ImageList mais à la nouvelle hauteur. Pas la peine d'initialiser la couleur du fond, puisqu'il y a un masque.
    Tu fais un BitBlt de ton bitmap original vers ton nouveau bitmap a la bonne position (au milieu) --> cette solution necessite 2 Memory Device Context
    Tu peux aussi utiliser ImageList_Draw --> ça sera moins long à programmer

    Idem pour le masque.

    Des conseils pour la prog:

    N'utilises pas CBitmap::Attach() avec le handle trouvé dans IMAGEINFO car le destructeur de CBitmap va détruire le Bitmap s'il n'y a pas un Detach() entre temps. Utilises plutot CBitmap::FromHandle() qui te donne un pointeur temporaire sur l'objet et là pas de soucis

    Je peux te fournir un bout de code, dès que j'aurai 5 min si tu le souhaites.

    @+

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 114
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par stephdim Voir le message
    Oui tu peux associer une image de la taille que tu veux,donc pas la peine de toucher à la largeur, sinon tu auras des blancs entre l'icone et le texte ...
    Normalement ce n'est pas trop genant car je fais du CustomDraw et je choisis donc ou j'affiche le text, l'icone ... Mais ceci dit tu as raison.
    Par contre je ne sais pas si c'est bien d'avoir des images dans une imagelist qui ne soient pas carrées


    Ok je suis preneur de bout de code.

  6. #6
    Membre confirmé Avatar de stephdim
    Profil pro
    Inscrit en
    Août 2007
    Messages
    462
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 462
    Points : 521
    Points
    521
    Par défaut
    Bon voila ce que je peux te proposer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    BOOL ChangeImageListHeight(CImageList *pDestImgList,CImageList *pSrcImgList,LONG extraheight)
    {
      ASSERT(extraheight>0);
     
      IMAGEINFO imginfo;
      VERIFY(pSrcImgList->GetImageInfo(0,&imginfo));
     
      CBitmap *pBitmapImage=CBitmap::FromHandle(imginfo.hbmImage);
      CBitmap *pBitmapMask=CBitmap::FromHandle(imginfo.hbmMask);
     
      BITMAP bm;
      VERIFY(pBitmapImage->GetBitmap(&bm));
     
      CBitmap newimage,newmask;
     
      {
        CDC memdc1,memdc2;
     
        {
          CWindowDC screendc(NULL);
          if (  !newimage.CreateCompatibleBitmap(&screendc,bm.bmWidth,bm.bmHeight+extraheight) ||
                !newmask.CreateBitmap(bm.bmWidth,bm.bmHeight+extraheight,1,1,NULL)  ||
                !memdc1.CreateCompatibleDC(&screendc) ||
                !memdc2.CreateCompatibleDC(&screendc) )
            AfxThrowResourceException();
        }
     
        CBitmap *pOldBitmap1=memdc1.SelectObject(&newimage);
        CBitmap *pOldBitmap2=memdc2.SelectObject(pBitmapImage);
     
        memdc1.BitBlt(0,extraheight>>1,bm.bmWidth,bm.bmHeight,&memdc2,0,0,SRCCOPY);
     
        memdc1.SelectObject(&newmask);
        memdc2.SelectObject(pBitmapMask);
     
        memdc1.PatBlt(0,0,bm.bmWidth,bm.bmHeight+extraheight,BLACKNESS);
        memdc1.BitBlt(0,extraheight>>1,bm.bmWidth,bm.bmHeight,&memdc2,0,0,SRCCOPY);
     
        memdc1.SelectObject(pOldBitmap1);
        memdc2.SelectObject(pOldBitmap2);
      }
     
      if (pDestImgList->Create( (imginfo.rcImage.right-imginfo.rcImage.left),
                                bm.bmHeight+extraheight,ILC_COLOR|ILC_MASK,0,0  ))
      {
        if (pDestImgList->Add(&newimage,&newmask)==0)
          return TRUE;        // succès
        else
          pDestImgList->DeleteImageList();
      }
     
      return FALSE;           // échec
    }
    Le code se compile, mais j'ai pas essayé à l'execution, mais ça devrait le faire.
    J'ai un petit doute sur la logique du bitmap masque, si c'est 0 ou 1 pour masquer une couleur. Si jamais tu as des pixels indesirables en haut et en bas, changes BLACKNESS par WHITENESS dans la ligne du PatBlt()

    Tiens moi au courant si ça fonctionne.

    @+

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2004
    Messages : 114
    Points : 56
    Points
    56
    Par défaut
    Citation Envoyé par stephdim Voir le message
    Bon voila ce que je peux te proposer:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
     
    BOOL ChangeImageListHeight(CImageList *pDestImgList,CImageList *pSrcImgList,LONG extraheight)
    {
      ASSERT(extraheight>0);
     
      IMAGEINFO imginfo;
      VERIFY(pSrcImgList->GetImageInfo(0,&imginfo));
     
      CBitmap *pBitmapImage=CBitmap::FromHandle(imginfo.hbmImage);
      CBitmap *pBitmapMask=CBitmap::FromHandle(imginfo.hbmMask);
     
      BITMAP bm;
      VERIFY(pBitmapImage->GetBitmap(&bm));
     
      CBitmap newimage,newmask;
     
      {
        CDC memdc1,memdc2;
     
        {
          CWindowDC screendc(NULL);
          if (  !newimage.CreateCompatibleBitmap(&screendc,bm.bmWidth,bm.bmHeight+extraheight) ||
                !newmask.CreateBitmap(bm.bmWidth,bm.bmHeight+extraheight,1,1,NULL)  ||
                !memdc1.CreateCompatibleDC(&screendc) ||
                !memdc2.CreateCompatibleDC(&screendc) )
            AfxThrowResourceException();
        }
     
        CBitmap *pOldBitmap1=memdc1.SelectObject(&newimage);
        CBitmap *pOldBitmap2=memdc2.SelectObject(pBitmapImage);
     
        memdc1.BitBlt(0,extraheight>>1,bm.bmWidth,bm.bmHeight,&memdc2,0,0,SRCCOPY);
     
        memdc1.SelectObject(&newmask);
        memdc2.SelectObject(pBitmapMask);
     
        memdc1.PatBlt(0,0,bm.bmWidth,bm.bmHeight+extraheight,BLACKNESS);
        memdc1.BitBlt(0,extraheight>>1,bm.bmWidth,bm.bmHeight,&memdc2,0,0,SRCCOPY);
     
        memdc1.SelectObject(pOldBitmap1);
        memdc2.SelectObject(pOldBitmap2);
      }
     
      if (pDestImgList->Create( (imginfo.rcImage.right-imginfo.rcImage.left),
                                bm.bmHeight+extraheight,ILC_COLOR|ILC_MASK,0,0  ))
      {
        if (pDestImgList->Add(&newimage,&newmask)==0)
          return TRUE;        // succès
        else
          pDestImgList->DeleteImageList();
      }
     
      return FALSE;           // échec
    }
    Le code se compile, mais j'ai pas essayé à l'execution, mais ça devrait le faire.
    J'ai un petit doute sur la logique du bitmap masque, si c'est 0 ou 1 pour masquer une couleur. Si jamais tu as des pixels indesirables en haut et en bas, changes BLACKNESS par WHITENESS dans la ligne du PatBlt()

    Tiens moi au courant si ça fonctionne.

    @+
    Un grand merci pour ta réponse mais cela ne fonctionne pas, la hauteur est bien modifiée mais l'icone est soit toute blanche, soit completement aleatoire.

    Cependant cela m'a permis de vérifier que cette voie n'est pas la bonne car lorsque je redimensionne le dialogue contenant mon CListCtrl, la scrollbar n'apparait toujours pas, ce qui me fait penser qu'en fait le problème vient du fait que je sois en CustomDraw.
    Il faut donc absolument que j'arrive a gérer la scrollbar manuellement.

Discussions similaires

  1. Réponses: 4
    Dernier message: 19/06/2006, 10h09
  2. [MFC] changer la hauteur d'une ligne dans un CListCtrl
    Par hiko-seijuro dans le forum MFC
    Réponses: 2
    Dernier message: 01/07/2005, 10h00
  3. [MFC] CListCtrl : rendre visible un item
    Par eag35 dans le forum MFC
    Réponses: 3
    Dernier message: 17/05/2005, 13h42
  4. [MFC] CListCtrl: colonnes fixes + tri des items
    Par bigboomshakala dans le forum MFC
    Réponses: 5
    Dernier message: 10/05/2004, 22h54
  5. Réponses: 3
    Dernier message: 18/11/2003, 13h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo