| auteur : Farscape | L'insertion peut se faire simplement avec la fonction AddString .
Si la combobox n'a pas le style CBS_SORT la chaîne est insérée en fin de liste.
Cette fonction renvoie le numéro d'item dans la liste box la première démarrant à zéro.
CComboBox:: AddString
int AddString ( LPCTSTR lpszString );
|
CString str;
int nIndex;
for (int i= 0 ;i < 20 ;i+ + )
{
str.Format (" Ma chaîne %d " ), i);
nIndex= MyComboBox.AddString ( str );
}
|
Autre fonction utilisable:
CComboBox:: InsertString
int InsertString ( int nIndex, LPCTSTR lpszString );
|
même chose que AddString mais ici on précise l'emplacement avec l'argument nIndex.
Si nIndex == -1 l'insertion se fait en bout de liste .
|
| auteur : Farscape |
CComboBox:: SetCurSel
int SetCurSel ( int nSelect );
|
La valeur retournée est l'indice de l'élément sélectionné si la commande réussit,
Sinon elle renvoie CB_ERR pour indiquer une erreur,
Si nSelect est égal à -1 la sélection en cours est supprimée et le retour sera aussi CB_ERR.
Exemple sélection du dernier élément de la combobox.
int nCount = MyComboBox.GetCount ();
if (nCount > 0 ) MyComboBox.SetCurSel (nCount- 1 );
|
Pour la sélection en fonction d'une chaîne de caractère utiliser :SelectString
qui est la combinaison de FindString et SetCurSel.
|
| auteur : Farscape | Pour changer la couleur dans une «Combobox» il faut reprendre la main sur la fonction « DrawItem »:
Il faudra générer une classe de type CComboBox avec l'aide de « classwizard » et générer la fonction DrawItem .
Exemple de traitement standard sur la gestion des couleurs à modifier selon vos besoins:
void CMyComboBox:: DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct)
{
ASSERT (lpDrawItemStruct- > CtlType = = ODT_COMBOBOX);
if (m_bInit & & (GetStyle () & CBS_HASSTRINGS))
{
for (int i= 0 ;i< GetCount () ;i+ + ) SetItemData (i,i);
}
m_bInit= false ;
LPCTSTR lpszText= NULL ;
CString str;
if (lpDrawItemStruct- > itemID! = CB_ERR & & ! (GetStyle () & CBS_HASSTRINGS))
lpszText= (LPCTSTR) lpDrawItemStruct- > itemData;
else
{
GetLBText (lpDrawItemStruct- > itemData,str);
lpszText= str;
}
ASSERT (lpszText ! = NULL );
CDC dc;
dc.Attach (lpDrawItemStruct- > hDC);
COLORREF crOldTextColor = dc.GetTextColor ();
COLORREF crOldBkColor = dc.GetBkColor ();
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);
}
dc.DrawText (
lpszText,
strlen (lpszText),
& lpDrawItemStruct- > rcItem,DT_SINGLELINE);
dc.SetTextColor (crOldTextColor);
dc.SetBkColor (crOldBkColor);
dc.Detach ();
}
|
Lorsque l'on prend le contrôle sur l'affichage d'une combobox ou Listbox par la fonction « DrawItem » la récupération de la chaîne de caractère se fait par un cast de la zone ItemData que l'utilisateur remplit avec la fonction SetItemData.
Lorsque que le type CBS_HASSTRINGS ou LBS_HASSTRINGS est présent dans une listbox, le traitement standard met dans itemdata le numéro de l'index.
Pour éviter une assertion quand les valeurs sont remplies directement dans l'éditeur de ressources j'ai placé une boucle de remplissage de itemdata la première fois .
Pour gérer les couleurs il suffira de modifier le traitement standard des couleurs selon que l'item est sélectionné ou pas .
|
| auteur : Farscape | Récupération de l'indice de l'item en sélection :
CComboBox:: GetCurSel
int GetCurSel ( ) const ;
|
Récupération d'une chaîne pour un numéro d'indice :
CComboBox:: GetLBText
int GetLBText ( int nIndex, LPTSTR lpszText ) const ;
void GetLBText ( int nIndex, CString& rString ) const ;
|
CString str ;
int nIndex = MyComboBox.GetCurSel ();
if (nIndex! = LB_ERR) MyComboBox.GetLBText (nIndex,str);
AfxMessageBox (str);
|
|
| auteur : Farscape |
CComboBox:: FindString
int FindString ( int nStartAfter, LPCTSTR lpszString ) const ;
|
La valeur retournée sera supérieure ou égale à zéro en case de succès sinon le retour vaudra CB_ERR .
nStartAfter
Contient la valeur de l'index du premier élément où la recherche doit commencer
Quand la recherche atteint la fin de la combobox elle continue à partir du haut jusqu'à la valeur nStartAfter.
Si -1 la recherche démarrera à partir du début.
lpszString
Contient la chaîne terminée par un'\0' qui doit être recherchée.
MyComboBox.SetCurSel (MyComboBox.FindString (0 , ?Ligne 1 ?));
MyComboBox. SelectString (0 ,?Ligne 1 ?);
|
|
| auteur : Farscape | |
int DeleteString ( UINT nIndex );
|
|
for (int i= MyComboBox.GetCount ()- 1 ; i>= 0 ;i- - )
{
MyComboBox.DeleteString ( i );
}
MyComboBox.ResetContent () ;
|
Supprime tous les éléments de la combobox
|
| auteur : Farscape | Dans l'éditeur de ressources sur les propriétés du combo box :
Sélectionner l'onglet général et mettre l'option drop list dans le champ type.
c'est tout.
|
| auteur : Farscape | La taille par défaut de la liste déroulante correspond à celle d'un élément, donnant ainsi l'impression qu'elle ne s'ouvre pas.
Son réglage se fait dans l'éditeur de ressources :
Sélectionner le contrôle ComboBox et cliquer sur la flèche de la liste, un rectangle montrant la hauteur de la liste apparaît, il suffit alors de lui régler sa taille avec la souris.
|
| auteur : Farscape | Il faut utiliser la classe CComboBoxEx :
D'abord déclarer un objet CImageList comme donnée membre de la classe parent.
Remplir la liste d'image avec des bitmaps ou des icônes.
m_ImageList.Create (16 , 16 , ILC_COLOR, 2 , 2 );
m_ImageList.Add (& Bitmap1);
m_ImageList.Add (& Bitmap2);
m_ImageList.Add (& Bitmap3);
|
Après associer l'image à une item de la combobox:
COMBOBOXEXITEM cbi;
CString str;
int i= 0 ;
cbi.mask = CBEIF_IMAGE | CBEIF_INDENT | CBEIF_OVERLAY |
CBEIF_SELECTEDIMAGE | CBEIF_TEXT;
cbi.iItem = i;
str.Format (_T (" Item %02d " ), i);
cbi.pszText = (LPTSTR)(LPCTSTR)str;
cbi.cchTextMax = str.GetLength ();
cbi.iImage = 0 ;
cbi.iSelectedImage = 1 ;
cbi.iOverlay = 2 ;
cbi.iIndent = 0 ;
m_ComboEx.InsertItem (& cbi);
|
voir doc MSDN pour la description de la structure COMBOBOXEXITEM.
|
| auteur : Farscape | La création d'un objet CCombobox avec l'option dropdown ou simple initialise automatiquement un objet CEdit associé à la CComboBox.
Pour changer le comportement de cet Edit ( sous entendu fournir sa propre classe ) il faut subclasser l'édit de la combobox.
Pour cela il faudra créer une classe dérivée de la classe CComboBox et surcharger
la fonction PreSubclassWindow() .
Cette classe devra avoir comme donnée membre la classe CEdit personnalisée.
Enfin, l'identifiant de l'édit dans une CComboBox est 1001 ,il ne reste plus qu'à écrire le code suivant :
void CMyCombo:: PreSubclassWindow ()
{
m_MyEdit.SubclassDlgItem (1001 , this );
CComboBox:: PreSubclassWindow ();
}
|
|
| auteurs : PetitPapaNoël, lucky, Farscape | Dans le cas d'une combobox de type Dropdown (et uniquement dans ce cas), le plus simple est de créer une variable de contrôle associée à la combobox puis de procéder ainsi :
CEdit * pEdit = static_cast < CEdit* > (m_maCombo.GetWindow (GW_CHILD));
if (pEdit)
pEdit- > SetReadOnly (TRUE);
|
Pour retirer le mode de lecture seule à la combobox, il suffit de faire pareil en passant FALSE à la méthode SetReadOnly.
Dans le cas d'une combobox de type Droplist ou Simple, ou si l'on préfère ne pas se préoccuper du type de la combobox (la méthode décrite ci-après fonctionne dans tous les cas), il faudra créer une nouvelle classe, dérivée de CComboBox.
Dans cette nouvelle classe, on redéfinira la méthode PreSubclassWindow de façon à pouvoir prendre le contrôle du CEdit de la combobox comme décrit dans la FAQ Comment prendre le contrôle du CEdit d'une CComboBox ?.
A noter qu'un CEdit n'est associé à la combobox que dans le cas des types Dropdown et Simple.
On définira aussi une méthode SetReadOnly qui fera le nécessaire pour mettre la combobox en lecture seule. Il faudra également intercepter les messages de changement de sélection dans la liste, dans la méthode OnCmdMsg, de façon à annuler ces changements lorsque la combobox est en lecture seule.
La classe CComboBoxLS (LS pour Lecture Seule) proposée ci-dessous fait tout cela, avec en plus la perte de la propriété TabStop lorsque la combobox est en lecture seule (on ne peut plus accéder au contrôle avec la touche de tabulation).
Dans le .h :class CComboBoxLS : public CComboBox
{
# pragma region Attributs
protected :
int m_posSel;
bool m_lectureSeule;
bool m_grise;
bool m_tabStop;
CEdit m_edit;
# pragma endregion
# pragma region Constructeurs & destructeur
public :
CComboBoxLS ();
virtual ~ CComboBoxLS () { } ;
# pragma endregion
# pragma region Accesseurs
public :
BOOL GetReadOnly () { return m_lectureSeule; } ;
BOOL SetReadOnly (BOOL valeur = TRUE);
# pragma endregion
# pragma region Méthodes
public :
int AddString (LPCTSTR texte);
int InsertString (int index, LPCTSTR texte);
int SetCurSel (int index)
{
m_posSel = CComboBox:: SetCurSel (index);
return m_posSel;
} ;
int SelectString (int posDepart, LPCTSTR texte);
int DeleteString (UINT index);
void ResetContent ()
{
CComboBox:: ResetContent ();
SetLectureSeule ();
} ;
protected :
DECLARE_MESSAGE_MAP ()
bool SetLectureSeule (bool valeur = true );
virtual void PreSubclassWindow ()
{
m_edit.SubclassDlgItem (1001 , this );
CComboBox:: PreSubclassWindow ();
} ;
afx_msg HBRUSH CtlColor (CDC * pDC, UINT );
virtual BOOL OnCmdMsg (UINT nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO* pHandlerInfo);
# pragma endregion
} ;
|
Dans le .cpp :
# include "ComboBoxLS.h"
# pragma region Constructeurs & destructeur
CComboBoxLS:: CComboBoxLS ()
{
m_posSel = - 1 ;
m_lectureSeule = m_grise = false ;
m_tabStop = true ;
}
# pragma endregion
# pragma region Accesseurs
BOOL CComboBoxLS:: SetReadOnly (BOOL valeur )
{
bool val = (valeur = = TRUE);
if (val = = m_lectureSeule)
return TRUE;
BOOL resu = SetLectureSeule (val);
if (resu)
m_lectureSeule = val;
return resu;
}
# pragma endregion
# pragma region Méthodes
BEGIN_MESSAGE_MAP (CComboBoxLS, CComboBox)
ON_WM_CTLCOLOR_REFLECT ()
END_MESSAGE_MAP ()
int CComboBoxLS:: AddString (LPCTSTR texte)
{
int resu = CComboBox:: AddString (texte);
if ((resu ! = CB_ERR) & & (resu ! = CB_ERRSPACE) & & ! m_lectureSeule & & GetCount ())
SetLectureSeule (false );
return resu;
}
int CComboBoxLS:: InsertString (int index, LPCTSTR texte)
{
int resu = CComboBox:: InsertString (index, texte);
if ((resu ! = CB_ERR) & & (resu ! = CB_ERRSPACE) & & ! m_lectureSeule & & GetCount ())
SetLectureSeule (false );
return resu;
}
int CComboBoxLS:: SelectString (int posDepart, LPCTSTR texte)
{
int resu = CComboBox:: SelectString (posDepart, texte);
if (resu ! = CB_ERR)
m_posSel = resu;
return resu;
}
int CComboBoxLS:: DeleteString (UINT index)
{
int resu = CComboBox:: DeleteString (index);
if ((resu ! = CB_ERR) & & ! GetCount ())
SetLectureSeule ();
return resu;
}
bool CComboBoxLS:: SetLectureSeule (bool valeur )
{
if (m_grise = = valeur)
return true ;
if (IsWindow (m_edit.m_hWnd) & & ! m_edit.SetReadOnly (valeur))
return false ;
if (IsWindow (m_hWnd))
if (valeur)
{
m_tabStop = (GetStyle () & WS_TABSTOP)? true : false ;
ModifyStyle (WS_TABSTOP, 0 );
}
else if (m_tabStop)
ModifyStyle (0 , WS_TABSTOP);
m_grise = valeur;
Invalidate ();
return true ;
}
HBRUSH CComboBoxLS:: CtlColor (CDC * pDC, UINT )
{
if (IsWindowEnabled () & & ! m_grise)
{
pDC- > SetBkColor (GetSysColor (COLOR_WINDOW));
return GetSysColorBrush (COLOR_WINDOW);
}
else
{
pDC- > SetBkColor (GetSysColor (COLOR_BTNFACE));
return GetSysColorBrush (COLOR_BTNFACE);
}
}
BOOL CComboBoxLS:: OnCmdMsg (UINT nID, int nCode, void * pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
if (nCode = = CBN_SELCHANGE)
{
int pos = GetCurSel ();
if (pos = = m_posSel)
{
ShowDropDown (FALSE);
return TRUE;
}
if (m_lectureSeule)
{
ShowDropDown (FALSE);
CComboBox:: SetCurSel (m_posSel);
return TRUE;
}
else
m_posSel = pos;
}
return CComboBox:: OnCmdMsg (nID, nCode, pExtra, pHandlerInfo);
}
# pragma endregion
|
Utilisation : il suffit de créer une variable de contrôle de type CComboBoxLS associée à la combobox et d'utiliser la méthode SetReadOnly...
|
lien : Comment prendre le contrôle du CEdit d'une CComboBox ?
|
| auteur : bizulk | D'origine, on ne peut définir le style d'une CComboBox que pendant la phase de développement, ainsi que la taille maximum de la liste.
Deux fonctions permettent de résoudre ce problème, sans avoir à créer une classe fille.
Le principe est de recréer une CComboBox avec les nouvelles propriétés qui remplacera la combo actuelle.
Je conseille de définir les propriétés suivantes de la CComboBox dans les ressources : DROPDOWN, VERTICALSCROLL
BOOL MyClass:: RecreateComboBox (CComboBox* pCombo, LPVOID lpParam)
{
if (pCombo = = NULL )
return FALSE;
if (pCombo- > GetSafeHwnd () = = NULL )
return FALSE;
CWnd* pParent = pCombo- > GetParent ();
if (pParent = = NULL )
return FALSE;
DWORD dwStyle = pCombo- > GetStyle ();
DWORD dwStyleEx = pCombo- > GetExStyle ();
CRect rc;
pCombo- > GetDroppedControlRect (& rc);
pParent- > ScreenToClient (& rc);
UINT nID = pCombo- > GetDlgCtrlID ();
CFont* pFont = pCombo- > GetFont ();
CWnd* pWndAfter = pCombo- > GetNextWindow (GW_HWNDPREV);
CString sCurText;
int nCurSel = pCombo- > GetCurSel ();
BOOL bItemSelValid = nCurSel ! = - 1 ;
if (bItemSelValid)
pCombo- > GetLBText (nCurSel, sCurText);
else
pCombo- > GetWindowText (sCurText);
CComboBox comboNew;
if (! comboNew.CreateEx (dwStyleEx, _T (" COMBOBOX " ), _T (" " ),
dwStyle, rc, pParent, nID, lpParam))
return FALSE;
comboNew.SetFont (pFont);
int nNumItems = pCombo- > GetCount ();
for (int n = 0 ; n < nNumItems; n+ + )
{
CString sText;
pCombo- > GetLBText (n, sText);
int nNewIndex = comboNew.AddString (sText);
comboNew.SetItemData (nNewIndex, pCombo- > GetItemData (n));
}
if (bItemSelValid)
comboNew.SetCurSel (comboNew.FindStringExact (- 1 , sCurText));
else
comboNew.SetWindowText (sCurText);
pCombo- > DestroyWindow ();
HWND hwnd = comboNew.Detach ();
pCombo- > Attach (hwnd);
pCombo- > SetWindowPos (pWndAfter = = NULL ?
& CWnd:: wndBottom :
pWndAfter, 0 , 0 , 0 , 0 , SWP_NOMOVE | SWP_NOSIZE);
return TRUE;
}
|
void MyClass:: set_DropDownSize (CComboBoxExt& box, UINT LinesToDisplay)
{
ASSERT (IsWindow (box));
CRect cbSize;
int Height;
box.GetClientRect (cbSize);
Height = box.GetItemHeight (- 1 );
Height + = box.GetItemHeight (0 ) * LinesToDisplay;
Height + = GetSystemMetrics (SM_CYEDGE) * 2 ;
Height + = GetSystemMetrics (SM_CYEDGE) * 2 ;
box.SetWindowPos (NULL ,
0 , 0 ,
cbSize.right, Height,
SWP_NOMOVE | SWP_NOZORDER
);
}
|
|
Consultez les autres F.A.Q.
|
|