Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

Vous n'avez pas encore de compte Developpez.com ? L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Developpez.com

C++

Choisissez la catégorie, puis la rubrique :

logo
Sommaire > Contrôles > ClistBox
        Comment activer la sélection multiple dans une CListBox ?
        Comment supprimer la ligne sélectionnée dans une CListbox ?
        Comment supprimer une ligne dans une CListbox ?
        Comment empêcher le tri des données dans une CListBox ?
        Comment sélectionner le dernier élément d'une ClistBox ?
        Comment insérer un élément dans une ClistBox ?
        Comment détruire tous les éléments d'une ClistBox ?
        Comment récupérer le texte d'une ligne dans une CListBox ?
        Comment personnaliser l'affichage des lignes dans une CListBox?
        Comment simuler des colonnes dans une CListBox ?
        Comment implémenter l'ascenseur horizontal sur une CListBox ?
        Comment régler la hauteur des lignes dans une CListBox ?
        Comment activer/désactiver dynamiquement l'ascenseur d'une CListBox ?
        Comment enlever dynamiquement la propriété de tri d'une CListBox.



Comment activer la sélection multiple dans une CListBox ?
auteur : Farscape
Sur les propriétés de la CListBox, il suffit de mettre le type de sélection à :extended et les combinaisons de touches ctrl ou maj seront opérationnelles.


Comment supprimer la ligne sélectionnée dans une CListbox ?
auteur : Farscape
En utilisant la fonction GetCurSel qui renvoie l'indice courant sélectionné.

int nIndex = myListBox.GetCurSel();
if((nIndex != LB_ERR))  myListBox.DeleteString( nindex );

Comment supprimer une ligne dans une CListbox ?
auteur : Farscape
Si on ne dispose pas du numéro index de la ligne il faudra la rechercher en utilisant la fonction FindString :

CListBox::FindString 
int FindString( int nStartAfter, LPCTSTR lpszItem ) const;
Exemple:

// ou
nIndex = myListBox.FindString(0,"coucou");
if((nIndex != LB_ERR))  myListBox.DeleteString( nindex );

Comment empêcher le tri des données dans une CListBox ?
auteur : Farscape
Il suffit d'enlever la coche ?Sort ? sur les propriétés de la listbox dans l'éditeur de ressources.


Comment sélectionner le dernier élément d'une ClistBox ?
auteur : Farscape

// nombre d'éléments  dans la listbox 
int nCount = MyListBox.GetCount(); 
// si pas d'erreur listbox non vide , sélection sur l'item nombre d'éléments -1 
// puisque les indices commencent  à zéro 
if (nCount > 0) MyListBox.SetCurSel(nCount-1);

Comment insérer un élément dans une ClistBox ?
auteur : Farscape

CListBox::AddString 
int AddString( LPCTSTR lpszItem );

CString str;
for (int i=0;i < 10;i++)
{
   str.Format(_T("item string %d"), i);
   MyListBox.AddString( str );
}

Comment détruire tous les éléments d'une ClistBox ?
auteur : Farscape
Avec la fonction ResetContent( )

// prototype de la méthode:
CListBox::ResetContent 
void ResetContent( );

// Détruire tous les éléments d'une ClistBox
MyListBox.ResetContent();
ASSERT(MyListBox.GetCount() == 0);

Comment récupérer le texte d'une ligne dans une CListBox ?
auteur : Farscape
Avec la fonction GetText :

CListBox::GetText 
int GetText( int nIndex, LPTSTR lpszBuffer ) const;
void GetText( int nIndex, CString& rString ) const;
Exemple : récupérer le texte de la ligne sélectionnée:

CStrng str;
int nIndex = myListBox.GetCurSel();
if((nIndex != LB_ERR))  myListBox.GetText( nindex,str );
AfxMessageBox(str);

Comment personnaliser l'affichage des lignes dans une CListBox?
Mise à jour le 25/06/2004[haut]
auteur : Farscape
En utilisant la fonction virtuelle DrawItem

CListBox::DrawItem 
virtual void DrawItem( LPDRAWITEMSTRUCT lpDrawItemStruct );
 
Le style Owner Draw devra être sélectionné dans les propriétés de la ListBox et l'option HasString devra être cochée.
Il faudra bien sûr créer une classe dérivée de CListBox avec l'aide de ClassWizard et surcharger la fonction DrawItem toujours avec ClassWizard.

Exemple d'implémentation issue de la documentation MSDN :
Affichage du texte centré horizontalement.


// CMyListBox is my owner-drawn list box derived from CListBox. This 
// example draws an item's text centered vertically and horizontally. The 
// list box control was created with the following code:
//   pmyListBox->Create(
//      WS_CHILD|WS_VISIBLE|WS_BORDER|WS_HSCROLL|WS_VSCROLL|
//      LBS_SORT|LBS_MULTIPLESEL|LBS_OWNERDRAWVARIABLE,
//      myRect, pParentWnd, 1);
//
void CMyListBox::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) 
{
// TODO: Add your code to draw the specified item
   ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX);
    
    LPCTSTR lpszText=NULL ;
    CString str;
    // si le style est <> de LBS_HASSTRINGS on considère que la valeur à afficher 
    //est dans ItemData.
    if(lpDrawItemStruct->itemID!=CB_ERR && !(GetStyle() & LBS_HASSTRINGS))
        lpszText=(LPCTSTR) lpDrawItemStruct->itemData;
    else
    {
        // Récupération de la chaîne grâce à l'index stocké dans ItemID.        
        GetText(lpDrawItemStruct->itemID,str);
        lpszText= str;
    }
   
   ASSERT(lpszText != NULL);
   CDC dc;

   dc.Attach(lpDrawItemStruct->hDC);

   // Save these value to restore them when done drawing.
   COLORREF crOldTextColor = dc.GetTextColor();
   COLORREF crOldBkColor = dc.GetBkColor();

   // If this item is selected, set the background color 
   // and the text color to appropriate values. Also, erase
   // rect by filling it with the background color.
   if ((lpDrawItemStruct->itemAction | ODA_SELECT) &&
      (lpDrawItemStruct->itemState & ODS_SELECTED))
   {
      dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT));
      dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT));
      dc.FillSolidRect(&lpDrawItemStruct->rcItem, 
         ::GetSysColor(COLOR_HIGHLIGHT));
   }
   else
      dc.FillSolidRect(&lpDrawItemStruct->rcItem, crOldBkColor);

   // If this item has the focus, draw a red frame around the
   // item's rect.
   if ((lpDrawItemStruct->itemAction | ODA_FOCUS) &&
      (lpDrawItemStruct->itemState & ODS_FOCUS))
   {
      CBrush br(RGB(255, 0, 0));
      dc.FrameRect(&lpDrawItemStruct->rcItem, &br);
   }

   // Draw the text.
   dc.DrawText(
      lpszText,
      strlen(lpszText),
      &lpDrawItemStruct->rcItem,
      DT_CENTER|DT_SINGLELINE|DT_VCENTER);

   // Reset the background color and the text color back to their
   // original values.
   dc.SetTextColor(crOldTextColor);
   dc.SetBkColor(crOldBkColor);

   dc.Detach();
}
L'exemple ci-dessus montre entre autres qu'il sera très facile d'intervenir sur la couleur d'écriture de fond sur une ligne en sélection ou non.


Comment simuler des colonnes dans une CListBox ?
auteur : Farscape
En insérant dans la chaîne le caractère tabulation entre chaque portion et en appelant la fonction SetTabStop pour fixer les intervalles.
Il faut aussi coché l'option use tab stop sur le contrôle dans l'éditeur de ressources .
 
// Set tabstops at 100 and 200 dialog units 
int tab_stop[2] = {100, 200}; 
 VERIFY(m_listbox.SetTabStops(2, tab_stop)); 
 m_listbox.AddString("String1\tString2\tString3");

Comment implémenter l'ascenseur horizontal sur une CListBox ?
auteur : Farscape
L'ascenseur horizontal dans une ClistBox n'est pas géré malgré la propriété disponible sur le contrôle dans l'éditeur de ressources.
Le code ci-dessous est une classe template permettant l'association à toute classe dérivée d'une CListBox.
Ce code est une version remaniée d'un exemple MSDN.

#if !defined(AFX_TPLSCROLLLISTBOX_H__6D3C28EE_84F0_4612_92CF_4E59952F30C9__INCLUDED_)
#define AFX_TPLSCROLLLISTBOX_H__6D3C28EE_84F0_4612_92CF_4E59952F30C9__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// TplScrollListBox.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// TplScrollListBox window

/////////////////////////////////////////////////////////////////////////////
typedef CArray<int,int> CIntArray;

template <class PARENT_LISTBOX>
class  TplScrollListBox : public PARENT_LISTBOX
{
// Construction
public:
    TplScrollListBox()
    {
        m_bLocked = FALSE;      // start out in auto mode
        m_nLongestExtent = 0;   // tracks longest extent, initially 0
        m_nTabStops = 0;        // no tab stops
        m_lpTabStops = NULL;    // array of tab stops
    }

// Attributes
public:
BOOL        m_bLocked;
CIntArray   m_arrExtents;
int         m_nLongestExtent;
int         m_nTabStops;
int*        m_lpTabStops;
// Operations
public:
void LockHExtentUpdate(){m_bLocked = TRUE;}
void UnlockHExtentUpdate(){m_bLocked = FALSE;}
void UpdateHExtent()
{
    m_arrExtents.RemoveAll();
    m_nLongestExtent = 0;
    int nCount = GetCount();
    
    CDC* pDC = GetDC();
    HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
    CFont *pFont = CFont::FromHandle(hFont);
    ASSERT(pFont);
    CFont* pPrevFont = pDC->SelectObject(pFont);
    CString str;
    for(int i=0; i<nCount; i++)
    {
        GetText(i, str);
        InsertNewExtent(i, str, pDC);
    }
    SetHorizontalExtent(m_nLongestExtent);
    pDC->SelectObject(pPrevFont);
    ReleaseDC(pDC);
}
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(TplScrollListBox)
public:
virtual BOOL OnWndMsg(UINT message,WPARAM wParam,LPARAM lParam,LRESULT* pResult)
{
    switch(message)
    {
    case LB_ADDSTRING:*pResult=OnAddString(wParam,lParam);
        break;
    case LB_INSERTSTRING:*pResult=OnInsertString(wParam,lParam);
        break;
    case LB_DELETESTRING:*pResult=OnDeleteString(wParam,lParam);
        break;
    case LB_SETTABSTOPS :*pResult=OnSetTabStops(wParam,lParam);
        break;
    default:return PARENT_LISTBOX::OnWndMsg(message,wParam,lParam,pResult);
    }
    return TRUE;
}
virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult)
{
    switch (message)
    {
    case WM_DRAWITEM:
        DrawItem((LPDRAWITEMSTRUCT)lParam);
        break;
    case WM_MEASUREITEM:MeasureItem((LPMEASUREITEMSTRUCT)lParam);
        break;
    case WM_COMPAREITEM:
        *pLResult = CompareItem((LPCOMPAREITEMSTRUCT)lParam);
        break;
    case WM_DELETEITEM:
        DeleteItem((LPDELETEITEMSTRUCT)lParam);
        break;
        
    default:return PARENT_LISTBOX::OnChildNotify(message, wParam, lParam, pLResult);    
    } 
    return TRUE;
}
//}}AFX_VIRTUAL

// Implementation
public:
virtual ~TplScrollListBox()
{
    delete [] m_lpTabStops;
}

// Generated message map functions
protected:
void InsertNewExtent(int nItem, LPCTSTR lpszStr)
{
    if (m_bLocked) return;
    CDC* pDC = GetDC();
    HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
    CFont *pFont = CFont::FromHandle(hFont);
    ASSERT(pFont);
    CFont* pPrevFont = pDC->SelectObject(pFont);
    InsertNewExtent(nItem, lpszStr, pDC);
    SetHorizontalExtent(m_nLongestExtent);
    pDC->SelectObject(pPrevFont);
    ReleaseDC(pDC);
}
void InsertNewExtent(int nItem, LPCTSTR lpszStr, CDC* pDC)
{
    if (NULL == m_lpTabStops)InitTabStops();
    
    CSize newExtent;
    if (GetStyle() & LBS_USETABSTOPS)
        newExtent = pDC->GetTabbedTextExtent(lpszStr, strlen(lpszStr),m_nTabStops, m_lpTabStops);
    else
        newExtent = pDC->GetTextExtent(lpszStr, strlen(lpszStr));
    
    newExtent.cx += 6;
    m_arrExtents.InsertAt(nItem, newExtent.cx);
    
    if (newExtent.cx > m_nLongestExtent)
    {
        m_nLongestExtent = newExtent.cx;
    }
}
void InitTabStops()
{
    int nDefault = 2;
    SetTabStops(1, &nDefault);
}

//{{AFX_MSG(TplScrollListBox)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
afx_msg LRESULT OnAddString(WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = Default();
    if (LB_ERR == lResult || LB_ERRSPACE == lResult) // check for error first!
        return lResult;
    InsertNewExtent(lResult, (LPCTSTR)lParam);
    return lResult;
}
afx_msg LRESULT OnInsertString(WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = Default();
    if (LB_ERR == lResult || LB_ERRSPACE == lResult) // check for error first!
        return lResult;
    InsertNewExtent(lResult, (LPCTSTR)lParam);
    return lResult;
}
afx_msg LRESULT OnDeleteString(WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = Default();
    if (LB_ERR == lResult) // check for error first!
        return lResult;
    
    if (m_bLocked) // don't do anything if locked
        return lResult;
    
    int nExtent = m_arrExtents[wParam];
    m_arrExtents.RemoveAt(wParam);
    if (nExtent >= m_nLongestExtent)
    {
        m_nLongestExtent = 0;
        for(int i = 0; i<lResult; i++)
        {
            if (m_arrExtents[i] > m_nLongestExtent)
                m_nLongestExtent = m_arrExtents[i];
        }
    }
    SetHorizontalExtent(m_nLongestExtent);
    return lResult;
}
afx_msg LRESULT OnSetTabStops(WPARAM wParam, LPARAM lParam)
{
    LRESULT lResult = Default();
    if (!lResult) return lResult;
    
    m_nTabStops = wParam;    
    if (NULL != m_lpTabStops)        
    {
        delete [] m_lpTabStops;
        m_lpTabStops = NULL;
    }
    if (m_nTabStops > 0)
    {
        m_lpTabStops = new int[m_nTabStops];
        memcpy(m_lpTabStops, (void*)lParam, m_nTabStops * sizeof(int));
        CDC* pDC = GetDC();
        HFONT hFont = (HFONT)SendMessage(WM_GETFONT);
        CFont *pFont = CFont::FromHandle(hFont);
        ASSERT(pFont);
        CFont* pPrevFont = pDC->SelectObject(pFont);
        CSize size;
        GetTextExtentPoint32(pDC->GetSafeHdc(),
            _T("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"),
            52, &size);
        pDC->SelectObject(pPrevFont);
        ReleaseDC(pDC);
        int aveCharWidth = (size.cx/26 +1)/2;
        for(int i=0; i<m_nTabStops; i++)
            m_lpTabStops[i] = (m_lpTabStops[i] * aveCharWidth + 2)/4;
    }
    if (!m_bLocked) UpdateHExtent(); // tabs changed, recalc everything!
    return lResult;
}
};
/////////////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_TPLSCROLLLISTBOX_H__6D3C28EE_84F0_4612_92CF_4E59952F30C9__INCLUDED_)
Utilisation: il suffit de compléter la déclaration existante comme suit:

TplScrollListBox<CListBox> m_MyListBox;
Note : l'option notify doit être cochée sur le contrôle.


Comment régler la hauteur des lignes dans une CListBox ?
Créé le 27/11/2005[haut]
auteur : Farscape
Le réglage de la hauteur pourra s'effectuer avec la fonction :

CListBox::SetItemHeight 
int SetItemHeight( int nIndex, UINT cyItemHeight );
Dans le cas d'une Listbox classique l'argument nIndex n'est pas pris en compte et doit rester à zéro, l'ensemble des lignes de la Listbox aura la même hauteur.
Exemple :

CSize   sz;
CDC*    pDC = m_ListboxNormal.GetDC();
m_ListboxNormal.GetText( 0, str );
CFont* pOldFont = pDC->SelectObject(&m_Font);      
sz = pDC->GetTextExtent(str);
m_ListboxNormal.SetItemHeight(0,sz.cy*2);
pDC->SelectObject(pOldFont);  
m_ListboxNormal.ReleaseDC(pDC);      
L'argument nIndex sera pris en compte avec une Listbox possédant le style LBS_OWNERDRAWVARIABLE, permettant ainsi de spécifier la hauteur de chaque ligne de la ListBox.

// extrait de MSDN
// réglage de la hauteur de chaque ligne de listbox avec la fonte courante.
CString str;
CSize   sz;
int     dx=0;
CDC*    pDC = pmyListBox->GetDC();
for (int i=0;i < pmyListBox->GetCount();i++)
{
   pmyListBox->GetText( i, str );
   sz = pDC->GetTextExtent(str);

   pmyListBox->SetItemHeight( i, sz.cy );
}
pmyListBox->ReleaseDC(pDC);
Si la Listbox est LBS_OWNERDRAWFIXED SetItemHeight permettra de spécifier la hauteur pour l'ensemble des lignes de la Listbox .

Dans le cas où la listbox est LBS_OWNERDRAWVARIABLE nous disposons d'une autre possibilité pour spécifier la hauteur d'une ligne :
Redéfinir la fonction virtuelle MeasureItem avec l'aide de classwizard.

virtual void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct);
Exemple:

void CMyListBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) 
{
   // TODO: Add your code to determine the size of specified item
   CDC *pDC = GetDC();   
   if(m_pFont)
   {
      CFont* pOldFont = pDC->SelectObject(m_pFont);      
       TEXTMETRIC tm;
       pDC->GetTextMetrics(&tm);
       lpMeasureItemStruct->itemHeight = tm.tmHeight + tm.tmExternalLeading;
       lpMeasureItemStruct->itemHeight += lpMeasureItemStruct->itemHeight / 2;   
      pDC->SelectObject(pOldFont);
   }
   ReleaseDC(pDC);      
}
Note: ici l'ensemble des lignes sera réglé à la même hauteur, il est possible de personnaliser la hauteur de chaque ligne grâce la zone itemData de la structure MEASUREITEMSTRUCT

Le projet de tests :
http://farscape.developpez.com/Samples/CustomListBox.zip


Comment activer/désactiver dynamiquement l'ascenseur d'une CListBox ?
Créé le 20/05/2006[haut]
auteur : Farscape
La première réponse serait de faire :

MyListBox.ModifyStyle(WS_VSCROLL,0); // enlève la scrollbar 
MyListBox.ModifyStyle(0,WS_VSCROLL); // remet la scrollbar
Malheureusement ça ne fonctionne pas,
la Listbox n'accepte pas les changements de style après sa création ,
Il faut donc la recréer pour que le style soit pris en compte.
On procédera par recopie des infos de l'objet à l'identique :

//---------------------------------------
BOOL CMyListBox::Recreate(LPVOID lpParam/*=0*/)
{    
    if (GetSafeHwnd() == NULL)return FALSE;
    
    CWnd* pParent = GetParent();
    if (pParent == NULL) return FALSE;
    
    // get current attributes
    DWORD dwStyle = GetStyle();
    DWORD dwStyleEx = GetExStyle();
    CRect rc;
    
    GetWindowRect(&rc);
    pParent->ScreenToClient(&rc);// map to client co-ords
    UINT nID = GetDlgCtrlID();
    CFont* pFont = GetFont();
    CWnd* pWndAfter = GetNextWindow(GW_HWNDPREV);
    
    // get the currently selected text (and whether it is a valid list selection)
    CString sCurText;
    int nCurSel = GetCurSel();
    BOOL bItemSelValid = nCurSel != -1;
    if (bItemSelValid)GetText(nCurSel, sCurText);
    
    CMyListBox listboxNew;
    if (! listboxNew.CreateEx(dwStyleEx, _T("ListBox"), _T(""), 
        dwStyle, rc, pParent, nID, lpParam))
        return FALSE;
    
    listboxNew.SetFont(pFont);
    
    int nNumItems = GetCount();
    
    for (int n = 0; n < nNumItems; n++)
    {
        CString sText;
        GetText(n, sText);
        int nNewIndex = listboxNew.AddString(sText);
        listboxNew.SetItemData(nNewIndex,GetItemData(n));
    }
    // re-set selected text
    if (bItemSelValid)
        listboxNew.SetCurSel(listboxNew.FindStringExact(-1, sCurText));
    
    
    // destroy the existing window, then attach the new one
    DestroyWindow();
    HWND hwnd = listboxNew.Detach();
    Attach(hwnd);
    
    // position correctly in z-order
    SetWindowPos(pWndAfter == NULL ? 
        &CWnd::wndBottom : 
    pWndAfter, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);   
    return TRUE;
}


Comment enlever dynamiquement la propriété de tri d'une CListBox.
Créé le 20/05/2006[haut]
auteur : Farscape
Les propriétés sont modifiables en utilisant la fonction de la classe CWnd :ModifyStyle qui permet de supprimer /d'ajouter en un seul appel des styles au contrôle.

MyListBox.ModifyStyle(LBS_SORT  ,0); 
Les styles sont visibles dans l'aide MSDN sur la fonction create, on trouve un lien List-Box Styles.



Consultez les autres F.A.Q.


Valid XHTML 1.0 TransitionalValid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2004 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Contacter le responsable de la rubrique C++

Partenaire : Hébergement Web