Interface graphique [c/c++] - C++ - Programmation
Marsh Posté le 14-04-2003 à 21:16:39
Salut,
Si j'ai bien compris bool est une variable, et tu es en C car bool est un mot réservé en C++.
Code :
|
Donc, si tu gére toi même tes boutons, il te faut bien passé par l'evenement WM_PAINT, car c'est lui qui appelé quand une partie de la fenêtre doit être affiché. Ce qui peut être provoqué manuellement par InvalidateRect.
Code :
|
Donc, il te faut juste modifier bool selon l'evenement que tu veux traiter, WM_LBUTTONDOWN je presume, en utilsant InvalidateRect plutot que RedrawWindow() ou UpdateWindow().
Si tu veux eviter les scintillement, il faut utiliser un DC mémoire et utiliser InvalidateRect avec FALSE en dernier parametre.
Tu peux aussi créer une fenêtre enfant, et en faire un bouton personalisé...
Marsh Posté le 14-04-2003 à 22:14:37
touxe a écrit : G reussi apres de longue tentative a cree une fenetre. |
faudrait eviter ce genre de choses normalement, tester les coordonnées de la souris pour savoir ou l'utilisateur clique. Si tu as des controles pré-définis (a savoir 'button', c'est pas pour rien. tu les fais ownerdraw, tu traces 'tes rectangles' en interceptant wm_drawitem, et apres qd l'utilisateur clique dessus, c'est géré tout seul.
enfin bon, si t'as commencé comme ca et que tu t'en sors, je vais pas te forcer a tout recommencer.
sur ce, bonne lutte... (au moins ca t'apprendra le win32)
Marsh Posté le 15-04-2003 à 00:16:41
Merci Poireau.
G fait ce que tu as dis mais g l'impression que ma fenetre n'est pas mis a jours mais tt les autres fenetre qui sont derrier ou meme le bureau de windows le sont!!
g appeler mas fonction comme ceci et c dans
case WM_LBUTTONDOWN:
InvalidateRect(NULL, NULL, FALSE);
Konar merci a toi aussi mais g pas tout compris
Si ca peut etre utile voila le code
Code :
|
Et ca si ca peut aider a comprendre ce que je fais
Marsh Posté le 15-04-2003 à 18:43:41
Ok, tu utilise mal la fonction InvalidateRect, car tu lui passe NULL en premier argument, alors qu'il faut indentifier la fenetre a rafraîchir. Et tu dispose de l'indentifiant de la fenetre le Handle Window :
Code :
|
Le fait de ne pas mettre d'identifiant permet de rafraîchir le bureau.
Sinon vu la longueur de ton code, la solution de Konar qui consiste a traiter les WM_DRAWITEM est plus propre, et plus simple a lire.
Tu aurais juste a créer une boîte de dialogue avec tes boutons et tes edit boxes, et modifier leur affichage.
Mais bon, comme tu es parti sur ta méthode...
Marsh Posté le 15-04-2003 à 18:53:52
Ca ne veut pas marcher je sais pas pourquoi. Soit la fenetre n'est pas effacer soit il passe toujours dans la meme chose pour le WM_PAINT.
G l'impression qu'il efface juste le cadre du bouton.
L'appel de InvalidateRect est il bien placé ?
Peut etre une idee est ce que il garde mes variable annuler et reserver apres l'appel de invalidate ? si il ne les garde pas et qu'il les reinitialise c normal qu'il dessine la meme chose.
C bon ca marche mais je suis obliger de mettre les variable annuler et reserver (ma bool) en global
Marsh Posté le 15-04-2003 à 21:47:09
Essaye alors
Code :
|
Ca permt d'effacer avant de reafficher, mais ça a la facheuse tendance à faire des scintillements...
Marsh Posté le 15-04-2003 à 21:57:18
Euh, j'avais pas trop lu ton code, mais le code de dessin dans le traitement de l'evenement WM_LBUTTONDOWN n'est pas approprié...
En effet, seul la procédure WM_PAINT doit dessiner, donc il te faut positionner une variable dans le traitement de l'evenement WM_LBUTTONDOWN. Et changer l'affichage selon cette variable, ce qui sera fait via InvalidateRect (hWnd, NULL, FALSE), car il transmet un evenement WM_PAINT...
Pareil dans WM_MOUSEMOVE.
En fait, ce n'est pas faux de dessiner dans un autre evenement que WM_PAINT, mais le dessin sera efface si une fenetre passe au dessus par exemple. Alors que si tu utilise WM_PAINT, le systeme se charge d'envoyer l'evenement WM_PAINT, et donc ca ce reaffichera. InvalidateRect permet de forcer cette affichage...
Marsh Posté le 15-04-2003 à 22:38:26
Ok merci je commence a piger le truc !
Est ce que il y a une fonction qui renvoit un WM_CREATE car qd je v cliquer sur l'un des bouton et afficher ma page correspondante je voudrais cree des edit box pour recevoir les nom, prenom etc ...
Merci
Marsh Posté le 15-04-2003 à 23:07:34
touxe a écrit : Ok merci je commence a piger le truc ! |
Oui, c'est CreateWindow ...
C'est le premier évenement que reçoit la fenêtre.
Mais sinon, tu peut provoquer manuellement les évenements, avec SendMessage ou PostMessage.
Marsh Posté le 15-04-2003 à 23:19:21
Donc si je veux cree mes editbox pendant que je redessine la fenetre je fais invalidaterectangle et sendmessage(WM_CREATE)
(je comprend pas les parametre de SendMessage )
g fait ca en fait mais forcement c une erreur
Code :
|
Le WM_CREATE est le meme que ds le message precedent.
Une fois que j'aurais reussi a cree ces edite box (hwndEdit) si je dois changer de page (l'utilisateur clique sur l'un des boutons) faut il detruir ces editebox et si oui comment )
Je crois que ce sera mes dernieres questions tous commencant a bien prendre forme
Merci
Marsh Posté le 16-04-2003 à 13:36:06
Salut, j'aimerais juste savoir avec quel librairie vous faites ce genre de programmation ??? Vous utiliser SDL ???
Marsh Posté le 16-04-2003 à 13:38:12
Joey_Joe a écrit : |
Non, c'est du GDI tout simple
Marsh Posté le 16-04-2003 à 13:45:40
Ouais, ca marche comment ? Tu fais un #include quoi au début ?
Marsh Posté le 16-04-2003 à 13:48:15
Joey_Joe a écrit : |
En général, c'est Winuser.h et Windows.h
Marsh Posté le 16-04-2003 à 15:16:32
touxe a écrit : Donc si je veux cree mes editbox pendant que je redessine la fenetre je fais invalidaterectangle et sendmessage(WM_CREATE) |
J'ai répondu à ta question précédente sans me soucier de ta manière d'organiser le code, à savoir si on pouvait générer l'évenement WM_CREATE. Oui, c'est possible, mais c'est pas propre.
L'évenement WM_CREATE doit correspondre uniquement au traitement de la création de le fenêtre, c'est à dire ici créer "objets" : les boutons,...
Donc, pour aller dans ta vision des choses, pour créer des objets suivant le clic de la souris, tu as deux possibilités plus propre.
La première est de créer l'objet avec un CreateWindow(...) dans l'evenement WM_LBUTTONDOWN ce qui donne un truc du genre :
Code :
|
La deuxième est je pense la plus simple à faire et surtout à lire, c'est de créer tous les objets dont tu as besoin dans WM_CREATE à l'aide de CreateWindow.
Le problème est qu'ils seront tous affichés, la solution est de les caché tant que l'on en a pas besoin.
Pour cela tu peux positionner un indicateur à la création de la fenêtre enfant, ou bien utiliser la fonction ShowWindow :
Code :
|
Marsh Posté le 16-04-2003 à 15:52:31
Ok g choisie la deuxieme solution ca marche bien ! merci
Pour l'instant pas d'autres question
Merci pour toutes ton aide
Marsh Posté le 16-04-2003 à 16:09:53
touxe a écrit : Ok g choisie la deuxieme solution ca marche bien ! merci |
No pb
C'est dans ces moments que l'on se rend compte que l'API Win32 et la msdn, sont compliquées, mal faites, mais somme toute puissante...
Marsh Posté le 16-04-2003 à 16:15:56
Ca aura été rapide ma periode sans question
J'arrive tres bien maintenat a traiter ce que l'utilisateur ecrit dans les editBox masi comment effacer ce qui est dedans ?
Car qd je passe d'une fenetre a l'autre (annuler ou reserver) sans valider mes reponses, le texte reste.
Quand je valide ma reponse, je traite ce qui est ecrit et je le reaffiche et la le texte s'efface je suppise grace a ReleaseDC.
Code :
|
Seulement si j'essai de faire la meme chose dans WM_LBUTTONDOWN il ne se passe rien.
Au fait aurais tu un site qui explique tout ca. Ca eviterais de t'embetter
MErci
Marsh Posté le 16-04-2003 à 17:06:32
Pour effacer une edit box faut utiliser comme tu fais un SetWindowText (hEdit, "" ) ;
A part ça, je vois pas bien d'où vient ton problème, il faudrait que tu décompose la WndProc, en procedure que tu appelles, ce serait bien plus lisible.
Et aussi d'afficher le code en entier.
Si tu dessinais que dans WM_PAINT, tu trouverais plus facilement le problème.
Pour des sites :
http://www.developpez.com/
http://www.winprog.org
http://www.programmationworld.com
http://win32.planet-d.net
Marsh Posté le 16-04-2003 à 21:08:20
Merci tout marche parfaitement bien.
Je m'aataque a des petits truc pour ameliorer le programme.
G une COMBOBOX comment faire pour selectionner par defaut un item. Car ma COMBOBOX qd elle est afficher n'a aucun texte, il faut cliquer dessus pour voir les differents choix.
G cru comprendre ne cherchant ds la MSDN qu'il fallait utiliser envoyer comme message WM_DRAWITEM mais je comprend pas le parametre "lpdis = (LPDRAWITEMSTRUCT) lParam"
lpdis
Value of lParam. Pointer to a DRAWITEMSTRUCT structure containing information about the item to be drawn and the type of drawing required.
Je ne comprend pas l'utilisation de la structure DRAWITEMSTRUCT.
Voila ce que g essayer de faire mais ca a pas l'aire de marcher
Code :
|
Marsh Posté le 16-04-2003 à 21:32:42
touxe a écrit : Merci tout marche parfaitement bien. |
Hum, DRAWITEMSTRUCT, c'est ce dont parlais Konar en debut de post, c'est pour gérer l'affichage du combo. C'est pas ce qui nous intéresse ici...
Il suffi juste après avoir créer et rempli la combobox, de sélectionner une ligne :
Code :
|
Marsh Posté le 16-04-2003 à 21:43:56
hé he je l'avais pas vu celui la pourtant je l'ai epluché la MSDN
Marsh Posté le 18-04-2003 à 00:04:21
Allé ! je revient a l'attaque !!!
J'aimerais integrer des image dans mon logiciel maintenant. Comment faut il faire ? est il possible de les caché a certain moment et de les montre a d'autre comme tu m'as fait faire pour les editbox avec la fonction ShowWindows.
Merci
Marsh Posté le 18-04-2003 à 01:12:37
Tu peux utiliser un static (style SS_BITMAP).
Pareil, tu le créé sans WS_VISIBLE.
Puis tu le montre / cache avec ShowWindow.
Marsh Posté le 18-04-2003 à 18:21:49
qqn pourrais m'aider, je ne comprend pas les parametre de cette fonction. J'arrive a afficher mes image mais je verifie a chaque fois si elle est bien place en changeant sans comprendre les parametre
Code :
|
Mon probleme c pour les coordonnée je pige pas la difference
Merci
Marsh Posté le 18-04-2003 à 19:06:23
Voila un morceau de code :
Code :
|
Ici donc j'affiche une image à partir du pixel (0,0) de la fenêtre (donc l'origine en haut à gauche), et de la largeur et de la hauteur propre de l'image...
Donc pour dessiner autre part il suffit de changer les deux premieres coordonnees (nXDest, nYDest).
Les deux suivantes sont la largeur et la hauteur de l'image à afficher (nWidth, nHeight).
Les deux dernieres permettent de dessiner l'image à partir d'une coordonnées de l'image source (utile si l'image est découpé) (nXSrc, nYSrc).
Marsh Posté le 18-04-2003 à 19:12:10
OK merci ! g vu ta reponse qd j'allais effacer mon message car j'avais comris. Par contre, je voudrais utiliser ShowWindows pour afficher ou non mes image mais ca ne marche pas.
En fait, g changer mes rectangle qui me servait de bouton par une image qui change si on est au dessu et si on clique dessus. Seulement, pour changer l'image en fonction de la position de la souris, je fais invalidateRectangle et comme tu m'as prevenue ca l'image saute.
Il y a t il alors une fonction equivalente a ShowWindows pour les images. C'est peut etre la solution de HelloWorld mais g pas compris
Merci
Marsh Posté le 18-04-2003 à 19:19:40
touxe a écrit : OK merci ! g vu ta reponse qd j'allais effacer mon message car j'avais comris. Par contre, je voudrais utiliser ShowWindows pour afficher ou non mes image mais ca ne marche pas. |
ShowWindow ne fonctionne pas car ce n'est pas une fenêtre, c'est juste un dessin.
Tu peux utiliser InvalidateRect (hWnd, &rect, FALSE) avec rect qui est les coordonnées de ton images dans la fenêtre. Ici, tu peux utiliser FALSE qui ne provoque pas de scintillement. Car FALSE n'efface pas la fenêtre avant de redessiner, et comme tu redessine totalement la partie de la fenêtre ca fonctionne. TRUE sert à effacer la fenêtre avant de la redessiner, d'où un passage rapide, mais visible de l'image vers un pinceau de fond de fenêtre (HBRUSH) puis vers la nouvelle image.
La méthode que j'utilise pour afficher une image différente est d'utiliser les deux dernières coordonnées de la focntion BltBit comme j'ai dit précédemment.
C'est à dire un truc du genre, avec une image composé de deux 'sous-images' horizontales de même taille :
Code :
|
Marsh Posté le 18-04-2003 à 21:38:42
est il normal que l'affchage d'image prenne autant de ressources avec 4 imgages g 130 Mo de RAM prise
Marsh Posté le 18-04-2003 à 22:57:37
touxe a écrit : est il normal que l'affchage d'image prenne autant de ressources avec 4 imgages g 130 Mo de RAM prise |
130 Mo de RAM, c'est l'utilisation totale ?
Et avant le programme il y a combien ?
Marsh Posté le 18-04-2003 à 23:16:17
touxe a écrit : sans les image je suis a 40 Mo c enorme c ouf ca |
Donc, il y a une fuite de ressources...
Est ce que tu fais un DeleteObject (hBmp) ; sur toutes images dans WM_DESTROY ?
Marsh Posté le 18-04-2003 à 23:31:44
En fait je crois qu'il faut que je reorganise totalement mon algo je fais beaucoup trop de InvalidateRectangle et c ca qui bouffe toutes la memoire il est sans cesse en train de reafficher. (je suis monté a 320 Mo de RAM )
G effacer qq ligne ou cette fonction etais et je tombe a 4 Mo ce qui je pense est bon.
Faut il aussi detruire ds WM_DESTROY tous ce que g cree avec CreateWindows
Marsh Posté le 18-04-2003 à 23:44:15
touxe a écrit : |
Il me semble que le système envoit le message WM_DESTROY aux fenêtres enfants...
Marsh Posté le 18-04-2003 à 23:52:16
touxe a écrit : En fait je crois qu'il faut que je reorganise totalement mon algo je fais beaucoup trop de InvalidateRectangle et c ca qui bouffe toutes la memoire il est sans cesse en train de reafficher. (je suis monté a 320 Mo de RAM ) |
me sert jms de InvalidateRect(), mais d'apres les man :
"The invalidated areas accumulate in the update region until the region is processed when the next WM_PAINT message occurs or until the region is validated by using the ValidateRect or ValidateRgn function."
Donc si t'as moins de perte de ram quand tu vires le InvalidateRect(), ca viens ptet de la... Essayes de rajouter un DefWindowProc(hWnd, msg, wParam, lParam) tout a la fin du handler WM_PAINT.
sinon pour le WM_DESTROY, oui c'est mieux d'essayer de liberer un maximum le max d'objets, surtout sous des os qui avaient un peu de mal avec la mémoire (95 ou 98)
Marsh Posté le 18-04-2003 à 23:56:29
merci de ta reponse !
tu met quoi dans msg ?
Sinon je viens de liberer pas mal de InvalidateRectangle et je prend les image de l'exterieur et je suis a 4,2 Mo.
Une autre question il faut mettre quoi comme parametre a SetBkColor(hdc, ... ) pour ecrire sur un fond transparent pour ne pas avoir de carré blanc sur mon image de fond.
Marsh Posté le 19-04-2003 à 00:06:19
touxe a écrit : merci de ta reponse ! |
DefWindowProc(hWnd, msg, wParam, lParam)
a les mêmes paramètres que
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
donc msg = message
Il y a SetBkMode (hdc, TRANSPARENT) ;
Marsh Posté le 14-04-2003 à 20:34:08
G reussi apres de longue tentative a cree une fenetre.
Dedans g cree des bouton (g trace des rectangle et je verifie ou ce situe la souris et si l'utilisateur clique). Une fois qu' l'utilisateur clique sur un de ces bouton, je voudrais redessiner la fenetre. Comment puis-je faire pour effacer la fenetre et en redessiner une autre en fonction du bouton qui a été cliqué.
Est il possible de repasser par WM_PAINT. En fait lorsque je clique sur l'un des boutons, g un booleen et en fonction de ce booleen je veux dessiner des choses differentes ( g essayer avec :
RedrawWindow();
UpdateWindow();
Merci
Message édité par touxe le 14-04-2003 à 20:34:35