Modifier les propriétés des controles boutons (image, texte, couleur, ...) [Résolu]

Messages postés
96
Date d'inscription
vendredi 1 avril 2005
Statut
Membre
Dernière intervention
26 juillet 2007
- - Dernière réponse : Gendal67
Messages postés
627
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
24 juillet 2011
- 9 mai 2006 à 19:25
Bonjour tout le monde,

J'aurais voulu savoir si il était possible de créer des boutons sur lesquels on pourrait :
- afficher une icone (depuis un fichier .ico)
- afficher un texte sous l'icone
- modifier la couleur de fond du bouton

le tout sans utiliser BS_OWNERDRAW

Je vais me faire fusiller mais sous VB ou Delphi c'est possible directement depuis l'IDE.
J'imagine que cela doit être possible en appelant quelques API de Windows non ?

Voici ce que j'arrive à faire pour le moment:
- je créer ma boite de dialogue depuis ResED, je place un bouton de style icone et j'ajoute mon icone dans les ressources
- depuis mon code, j'arrive à lui affecter mon icone (LoadIcon)

Mon problème et que je n'arrive pas à changer la couleur de fond du bouton.
J'ai cru comprendre que ce n'était pas possible sans gérer complètement le bouton soit même.
Est-ce vrai ?

Sinon j'ai essayé de m'inspirer de la source suivante:
http://www.cppfrance.com/codes/COULEURS-TRANSPARENCE-CONTROLES-API_27889.aspx

J'arrive à changer la couleur et mettre un texte sur mon bouton mais je n'arrive pas à ajouter mon icone.

Merci d'avance pour vos réponses.
Afficher la suite 

7 réponses

Meilleure réponse
Messages postés
1910
Date d'inscription
vendredi 18 juin 2004
Statut
Modérateur
Dernière intervention
14 novembre 2014
6
3
Merci
Salut,
Gendal67 >> A ma connaissance, le message WM_CTLCOLORBTN ne permet pas de changer la couleur de fond d'un bouton. Si c'était possible je l'aurais utilisé dans mon code source cité par l'auteur de cette question. Tu as déjà utilisé ce message? Et ça a marché?

skirby >> Un bouton n'est pas comme les autres controles. Son apparence dépend de son état: enfoncé, relaché, ayant ou non le focus etc. Pour faire ce qu'on veut de notre bouton, il faut obligatoirement qu'il soit de type BS_OWNERDRAW. Ainsi, on peut le personnaliser comme on veut. Pour charger une icone à partir d'un fichier on utilise la fonction LoadImage() comme ceci per exemple:
HICON icone=(HICON)LoadImage(0,"monicone.ico",IMAGE_ICON,16,16,LR_LOADFROMFILE);
Pour afficher cette icone quelque part sur le bouton, on utilise la fonction DrawIcon() pendant le traitement du message WM_DRAWITEM comme ceci:
ExtTextOut(lpds->hDC.....//Cette fonction efface le fond et écrit du texte
DrawIcon(lpds->hDC,x,y,icone);// x et y indiquent la position de l'icone.
Ainsi, l'icone sera placée là où on veut: sous le texte, en dessus, à droite, à gauche etc.
Il est vrai qu'avec VB ou Delphi c'esp plus facile, mais grâce aux API on peut faire beaucoup plus car on maitrise totalement l'apparence et le comportement de notre bouton.

Dire « Merci » 3

Quelques mots de remerciements seront grandement appréciés. Ajouter un commentaire

Codes Sources 136 internautes nous ont dit merci ce mois-ci

Commenter la réponse de racpp
Messages postés
627
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
24 juillet 2011
0
Merci
bonsoir,

il faut traiter le message WM_CTLCOLORBTN et retourner un (long) HBRUSH.
exemple :

// WinProc

case WM_CTLCOLORBTN:

return (long) (HBRUSH) GetStockObject(BLACK_BRUSH);
break;

Et voila
Commenter la réponse de Gendal67
Messages postés
96
Date d'inscription
vendredi 1 avril 2005
Statut
Membre
Dernière intervention
26 juillet 2007
0
Merci
Salut racpp,

merci de ta réponse, je vais essayer ça de suite.
Commenter la réponse de skirby
Messages postés
96
Date d'inscription
vendredi 1 avril 2005
Statut
Membre
Dernière intervention
26 juillet 2007
0
Merci
C'est encore moi.
J'ai suivi tes explications racpp et ça fonctionne très bien (j'ai un bouton de couleur avec une icône).
Le seul truc qui ne va pas c'est que je n'arrive pas à avoir l'effet "bouton appuyé"
En fait, l'icône reste en position 0,0 (position donnée dans la fonction DrawIcon)

Comment faire pour que mon image donne la sensation de s'enfoncer quand on appui sur le bouton ?

Merci d'avance.
Commenter la réponse de skirby
Messages postés
627
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
24 juillet 2011
0
Merci
case WM_DRAWITEM:

DRAWITEMSTRUCT* pdis = (LPDRAWITEMSTRUCT) lParam;

if(pdis->itemState & ODS_SELECTED)
InvertRect(pdis->hDC, &pdis->rcItem);

return 0;

Et voila, tu obtiens bien un effet de pression de boutton...si tu veux quelque chose de +complexe, rajoute des commandes autre que InvertRect
Commenter la réponse de Gendal67
Messages postés
96
Date d'inscription
vendredi 1 avril 2005
Statut
Membre
Dernière intervention
26 juillet 2007
0
Merci
Salut Gendal67,

Ce n'est pas tout à fait ça que je voulais.
InvertRect fait un NOT logique sur la couleur de chaque pixel.

J'aurais aimé avoir un bouton avec une image qui s'enfonce quand on clique sur le bouton tout simplement.
En fait c'est le mode de fonctionnement normal quand le bouton n'utilise pas le style BS_OWNERDRAW

Une idée ?
Commenter la réponse de skirby
Messages postés
627
Date d'inscription
mercredi 16 juin 2004
Statut
Membre
Dernière intervention
24 juillet 2011
0
Merci
Oui oui ne t'inquiète pas j'avais compris
Je pensais juste que tu ne savais pas où mettre le code correspondant, dans quel cas je t'ai répondu en disant : "à la place du InvertRect".

Pour ton problême, je te conseille carrément de dessinner son apparence "normale de bouton enfoncé". Essaie voir de mettre une ligne en pointillée pour montrer que le bouton a le focus et une ligne noire tout autour ombrée en haut et sur le coté gauche.

J'imagine que je suis très clair -_-" ....en fait j'ai testé la "tête" qu'avait un bouton lorsqu'on cliquait dessus (sans relacher la souris pour avoir le temps de voir ).

Donc voila ce que personnellement j'écrirais en code :

case WM_DRAWITEMSTRUCT:

DRAWITEMSTRUCT* pdis = (LPDRAWITEMSTRUCT) lParam;
int cx, cy;

cx = pdis->rcItem.right - pdis->rcItem.left;
cy = pdis->rcItem.bottom - pdis->rcItem.top;

HPEN hPen, hOld;

if(pdis->itemState & ODS_SELECTED) {

hPen = CreatePen(PS_SOLID, 3, RGB(128,128,128));
hOld = SelectObject(pdis->hDC, hPen);

MoveToEx(pdis->hDC, 0, 0, NULL);
LineTo(pdis->hDC, cx - 1, 0);

MoveToEx(pdis->hDC, 0, 0, NULL);
LineTo(pdis->hDC, 0, cy - 1);

SelectObject(pdis->hDC, hOld);
DeleteObject(hPen);
}

if(pdis->itemState & ODS_FOCUS) {

FrameRect(pdis->hDC, &pdis->rcItem, (HBRUSH) GetStockObject(BLACK_BRUSH));

pdis->rcItem.left += cx / 16;
pdis->rcItem.top += cx / 16;
pdis->rcItem.right -= cx / 16;
pdis->rcItem.bottom -= cx / 16;

DrawFocusRect(pdis->hDC, &pdis->rcItem);
}

return 0;

Essayez peut-être ceci et dites moi si cela correspond à ce que vous cherchiez.
Par contre, il faut peut-être ajuster les positions en x et y dans MoveToEx....tout dépend de comment Windows dessine. Là je suis parti du principe qu'avec le pinceau de 3 pixels d'épaisseur, le pixel le plus proche du coté sera dessiné aux positions indiquées par cette fonction.

Enfin voila, tenez moi au courant
Commenter la réponse de Gendal67