FAQ VC++ et MFCConsultez toutes les FAQ
Nombre d'auteurs : 20, nombre de questions : 545, dernière mise à jour : 5 avril 2013 Ajouter une question
Cette faq a été réalisée pour répondre aux questions les plus fréquement posées sur le forum Développement Visual C++
Je tiens à souligner que cette faq ne garantit en aucun cas que les informations qu'elle contient sont correctes ; Les auteurs font le maximum, mais l'erreur est humaine. Si vous trouvez une erreur, ou si vous souhaitez devenir redacteur, lisez ceci.
Sur ce, je vous souhaite une bonne lecture. Farscape
La gestion de la couleur d'ecriture et de fond s'obtient en mappant le message reflect :
voir note msdn:TN062: Message Reflection for Windows Controls
Code c++ : | Sélectionner tout |
1 2 | HBRUSH CtlColor(CDC* pDC, UINT nCtlColor) |
Code c++ : | Sélectionner tout |
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | // include ///////////////////////////////////////////////////////////////////////////// // Classe Template attributs couleurs template <class GENERIC_CTRLCOLOR> class CTplCtrl : public GENERIC_CTRLCOLOR { // Construction public: CTplCtrl() { m_arClrCtlText[0]=::GetSysColor(COLOR_WINDOWTEXT); m_arClrCtlText[1]=RGB(0 ,0 ,255); // LtBlue m_arClrCtlText[2]=RGB(128,0,0); // Red. m_arClrCtlBkText[0]=::GetSysColor(COLOR_WINDOW); m_arClrCtlBkText[1]=::GetSysColor(COLOR_WINDOW); m_arClrCtlBkText[2]=::GetSysColor(COLOR_WINDOW); for(int i=0;i<3;i++) m_arHbrClrCtlBk[i]=::CreateSolidBrush(m_arClrCtlBkText[i]); } enum ModeColor { Normal, Disable, ReadOnly }; void SetBkColor(COLORREF clrCtlBk = RGB(192, 192, 192), // couleur de fond COLORREF clrCtlText = RGB(0, 0, 0), // couleur d'écriture. ModeColor eMode=Normal) // mode actif/Inactif/lecture seule. { m_arClrCtlText[eMode]=clrCtlText; m_arClrCtlBkText[eMode]=clrCtlBk; if(m_arHbrClrCtlBk[eMode]) ::DeleteObject(m_arHbrClrCtlBk[eMode]); m_arHbrClrCtlBk[eMode] = ::CreateSolidBrush(clrCtlBk); if(m_hWnd) Invalidate(); } // Attributes public: HBRUSH m_arHbrClrCtlBk[3]; // brush de fond COLORREF m_arClrCtlBkText[3];// couleur du fond. COLORREF m_arClrCtlText[3]; // couleurs d'ecriture. // Operations public: virtual ~CTplCtrl() { for(int i=0;i<3;i++) if(m_arHbrClrCtlBk[i]) ::DeleteObject(m_arHbrClrCtlBk[i]); }; HBRUSH CtlColor(CDC* pDC, UINT nCtlColor) { bool bCEdit=(IsKindOf(RUNTIME_CLASS(CEdit))?true:false); HBRUSH hbr=NULL; ModeColor eMode=Normal; if(GetStyle() & ES_READONLY) eMode=ReadOnly; if(!IsWindowEnabled()) eMode=Disable; // TODO: Change any attributes of the DC here pDC->SetTextColor(m_arClrCtlText[eMode]); // Fixe le fond en transparent pour le texte if(!bCEdit) pDC->SetBkMode(TRANSPARENT); else pDC->SetBkColor(m_arClrCtlBkText[eMode]); // retourne le handle de la brush pour le fond si il existe. if(m_arHbrClrCtlBk[eMode]) hbr = m_arHbrClrCtlBk[eMode]; // TODO: Return a different brush if the default is not desired return hbr; } virtual BOOL OnChildNotify( UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult ) { // interception du message reflect if(message >= WM_CTLCOLORMSGBOX && message <= WM_CTLCOLORSTATIC) { UINT nCtlType = message - WM_CTLCOLORMSGBOX; ASSERT(nCtlType >= CTLCOLOR_MSGBOX); ASSERT(nCtlType <= CTLCOLOR_STATIC); CDC dcTemp; dcTemp.m_hDC = (HDC)wParam; HBRUSH hbr = CtlColor(&dcTemp, nCtlType); // fast detach of temporary objects dcTemp.m_hDC = NULL; *pLResult = (LRESULT)hbr; return TRUE; } return GENERIC_CTRLCOLOR::OnChildNotify( message,wParam, lParam,pLResult ); } }; |
celle ci intercepte le message à destination des contrôles pour la gestion de la couleur.
si on ne veut pas utiliser ce principe on pourra toujours intercepter manuellement le message reflect au niveau du contrôle et s'inspirer du traitement effectué dans la fonction CtlColor de la classe template proposée.
On pourra utiliser cette classe directement de cette manière:
Code c++ : | Sélectionner tout |
1 2 3 | CTplCtrl<CEdit> m_EditNom; CTplCtrl<CStatic> m_StaticNom; |
Code c++ : | Sélectionner tout |
1 2 | typedef CTplCtrl<CEdit> CEditEx |
On pourra faire de même pour un CStatic.
Pour changer la couleur il suffira d'appeler la fonction SetBkColor dans la fonction OnInitialUpdate pour une CFormView ou OnInitDialog pour une CDialog, par exemple.
Il existe une fonction au niveau de la classe d'application permettant de gérer pour toute l'application la couleur de fond et la couleur d'écriture du texte des contrôles :
Code C++ : | Sélectionner tout |
1 2 | CWinApp::SetDialogBkColor void SetDialogBkColor( COLORREF clrCtlBk = RGB(192, 192, 192), COLORREF clrCtlText = RGB(0, 0, 0) ); |
Mais cette méthode ne permet pas un changement dynamique par boîte de dialogue, donc voici une autre méthode.
Il faut implémenter le message WM_CTLCOLOR sur la CDialog
Code C++ : | Sélectionner tout |
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 55 56 | CTestsDiversDlg:: CTestsDiversDlg () : CDialog(CTestsDiversDlg::IDD) { //{{AFX_DATA_INIT(CTestsDiversDlg) //}}AFX_DATA_INIT /* HBRUSH */ m_HbrClrCtlBk=NULL ; /* COLORREF */ m_ClrCtlText= RGB(0, 0, 0) ; } CTestsDiversDlg:: ~CTestsDiversDlg () { if(m_HbrClrCtlBk) ::DeleteObject(m_HbrClrCtlBk); } void CTestsDiversDlg::SetDialogBkColor(COLORREF clrCtlBk /*= RGB(192, 192, 192)*/, COLORREF clrCtlText /*= RGB(0, 0, 0) */) { //m_HbrClrCtlBk est à null dans le constructeur if(m_HbrClrCtlBk) ::DeleteObject(m_HbrClrCtlBk); m_HbrClrCtlBk = ::CreateSolidBrush(clrCtlBk); m_ClrCtlText = clrCtlText; /* COLORREF */m_ClrCtlBk= clrCtlBk; } HBRUSH CTestsDiversDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor); /* CTLCOLOR_BTN button control CTLCOLOR_DLG dialog box CTLCOLOR_EDIT edit control CTLCOLOR_LISTBOX list box CTLCOLOR_MSGBOX message box CTLCOLOR_SCROLLBAR scroll bar CTLCOLOR_STATIC static text, frame, or rectangle */ // TODO: Change any attributes of the DC here // par exemple en fonction de nCtlColor voir doc. switch(nCtlColor) { // Intercepte le message pour la dialogue et les statics. case CTLCOLOR_DLG: case CTLCOLOR_STATIC : // Fixe la couleur d'ecriture du texte pDC->SetTextColor(m_ClrCtlText); // enventuellement suivant les cas // pDC->pDC->SetBkColor(m_ClrCtlBk); // Fixe le fond en transparent pour le texte // à ne pas faire pour un edit. pDC->SetBkMode(TRANSPARENT); // retourne le handle de la brush pour le fond si il existe. If(m_HbrClrCtlBk ) hbr = m_HbrClrCtlBk; break; } // TODO: Return a different brush if the default is not desired return hbr; } |
Le même code fonctionne avec une CFormView : MDIColorView.zip
Si l'image est dans les ressources on peut utiliser le contrôle Picture et dans les propriétés du contrôle sélectionner le type Bitmap ainsi que l'id de la ressource dans la combobox.
Pour un affichage d'une image externe il vaudra mieux passer par une classe CButton dérivée pour gérer l'affichage.
Pour les besoins de l'exemple j'ai fait simple je m'appuie sur un exemple de lecture d'image à partir de l'objet IPicture.
Le lien pour la classe CPicture : http://www.codeguru.com/bitmap/CPicture.html
Code C++ : | Sélectionner tout |
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | #include "Picture.h" class CBtPicture : public CButton { // Construction public: CBtPicture(); // Attributes public: CPicture m_Picture; CString m_sFilePathName; // Operations public: bool LoadImg(CString sFilePathName) { m_sFilePathName=sFilePathName; return (m_Picture.Load(sFilePathName)?true:false); } CString GetPictureName(){return m_sFilePathName;} // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CBtPicture) public: virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); //}}AFX_VIRTUAL // Implementation public: virtual ~CBtPicture(); // Generated message map functions protected: //{{AFX_MSG(CBtPicture) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG DECLARE_MESSAGE_MAP() }; // source CBtPicture::CBtPicture() { } CBtPicture::~CBtPicture() { } BEGIN_MESSAGE_MAP(CBtPicture, CButton) //{{AFX_MSG_MAP(CBtPicture) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CBtPicture message handlers void CBtPicture::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) { // TODO: Add your code to draw the specified item ASSERT(lpDrawItemStruct != NULL); CDC* pDC = CDC::FromHandle(lpDrawItemStruct->hDC); //UINT nState = lpDrawItemStruct->itemState; CRect itemRect = lpDrawItemStruct->rcItem; if(m_Picture.m_IPicture) { // Get Picture Dimentions In Pixels m_Picture.UpdateSizeOnDC(pDC); m_Picture.Show(pDC, CPoint(0,0), CPoint(m_Picture.m_Width, m_Picture.m_Height), 0,0); // Change Original Dimentions m_Picture.Show(pDC,itemRect); } } |
Le dessin de l'image est réalisé dans la fonction Drawitem.
Note : il faut mettre dans les propriétés du contrôle l'option OWner Draw sinon ça ne fonctionne pas.
Il reste plus qu'à attacher une variable de type contrôle bouton avec class wizard et de remplacer la classe Cbutton par CBtPicture et le tour est joué.
Utilisation :
Code C++ : | Sélectionner tout |
1 2 | m_BtPicture.LoadImg("artemis.bmp"); m_BtPicture.Invalidate(); |
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes 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 © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et 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.