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

Résolu
skirby Messages postés 96 Date d'inscription vendredi 1 avril 2005 Statut Membre Dernière intervention 26 juillet 2007 - 5 mai 2006 à 11:38
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.

7 réponses

racpp Messages postés 1909 Date d'inscription vendredi 18 juin 2004 Statut Modérateur Dernière intervention 14 novembre 2014 17
7 mai 2006 à 04:21
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.
3
Gendal67 Messages postés 627 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 24 juillet 2011 2
6 mai 2006 à 23:31
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
0
skirby Messages postés 96 Date d'inscription vendredi 1 avril 2005 Statut Membre Dernière intervention 26 juillet 2007
7 mai 2006 à 11:01
Salut racpp,

merci de ta réponse, je vais essayer ça de suite.
0
skirby Messages postés 96 Date d'inscription vendredi 1 avril 2005 Statut Membre Dernière intervention 26 juillet 2007
9 mai 2006 à 12:34
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.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Gendal67 Messages postés 627 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 24 juillet 2011 2
9 mai 2006 à 13:48
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
0
skirby Messages postés 96 Date d'inscription vendredi 1 avril 2005 Statut Membre Dernière intervention 26 juillet 2007
9 mai 2006 à 15:04
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 ?
0
Gendal67 Messages postés 627 Date d'inscription mercredi 16 juin 2004 Statut Membre Dernière intervention 24 juillet 2011 2
9 mai 2006 à 19:25
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
0
Rejoignez-nous