|
Publicité ' | |||||||||||||||||||||||
|
|
#1 |
|
Invité de passage
![]() jean-luc GIORGETTAInscription : avril 2011 Messages : 7 ![]() |
Bonjour,
Je fais du dessin avec l'API sur la zone client de ma fenetre principale, occupée partiellement par des toolbars en partie haute de la zc. Je souhaite limiter la zone de dessin à un rectangle, pas de pb pour la souris, je fais un test avec PtInRect pour interdire le dessin ailleurs, mais par exemple un cercle déborde de ce rectangle. J'ai essayé une fenetre child "static", ça dessine mais ça buggue à mort au resize au bout d'un moment (apparemment le "static" gère mal les messages). J'ai testé avec une "clipping region" rectangulaire...ça clippe toute la fenetre y compris les menus! Au final quel type de child utiliser pour le dédier uniquement au dessin? (l'équivalent d'un PaintBox en Delphi par ex). Faut-il sous-classer obligatoirement? Merci d'avance |
|
|
00
|
|
|
#2 |
|
Membre confirmé
![]() Inscription : décembre 2010 Messages : 99 ![]() |
Si ton message concerne Win32, perso, moi je creerais une classe de fenetre a moi, (probablement avec un attribut CS_SAVEBITS pour eviter d'avoir a redessiner a chaque fois, mais a voir), et je creerais une instance de cette classe en child de la fenetre principale.
Si tu dessines directement dans la fenetre principale en faisant un GetDC() sur le handle de la fenetre, fatalement, tu vas perturber les elements qui se trouvent deja a l'interieur, comme les autres boutons, ou bien c'est eux qui vont perturber ta zone de dessin. |
|
|
10
|
|
|
#3 |
|
Invité de passage
![]() jean-luc GIORGETTAInscription : avril 2011 Messages : 7 ![]() |
Ok merci, je vais créer une classe spéciale. Mais je suppose qu'il faut attacher à cette fenetre un WndProc spécial différent de celui de la fenetre principale? (ce qu'on appelle ss-classement??). Il devra contenir le switch de traitement des messages souris (entre autre) je suppose?
|
|
|
00
|
|
|
#4 |
|
Membre confirmé
![]() Inscription : décembre 2010 Messages : 99 ![]() |
Chaque classe de fenetre a un WndProc, generalement distinct.
Mais un ss-classement consiste a remplacer la wndproc d'une fenetre par une autre wndproc DURANT SON EXISTANCE (technique qui permet de modifier le comportement d'une fenetre ou d'un controle sans necessairement modifier son code source). La fonction generalement utilisee pour ca c'est SetWindowLong (via le selecteur GWL_WNDPROC ou qqchose comme ca). Le cas present il ne s'agit donc pas d'un sous-classement, simplement de la definition d'une nouvelle classe (donc via RegisterClass). L'avantage, c'est que si demain tu le souhaites, tu peux reutiliser ta classe "ZoneDeDessin" dans une autre fenetre sans rien modifier a ton code. |
|
|
10
|
|
|
#5 |
|
Invité de passage
![]() jean-luc GIORGETTAInscription : avril 2011 Messages : 7 ![]() |
J'ai modifié le code avec une classe de fenetre CHILD dédiée au dessin, ça a l'air de fonctionner correctement. Les WndProc respectifs traitent les fonctions générales (MainWinProc), l'autre les fonctions de tracé pur sur le DC (GraphWinProc). Par contre j'ai du passer pas mal de variables en "global" pour pouvoir faire dialoguer les 2 WndProc (par exemple mémoriser le curseur en cours, la commande active, le facteur de zoom, les pointeurs sur les LIST stockant les objets graphiques...etc). Peut-on faire autrement ? Si j'en crois les règles de "bonne prog" il faut éviter les variables globales...
|
|
|
00
|
|
|
#6 |
|
Membre confirmé
![]() Inscription : décembre 2010 Messages : 99 ![]() |
Tu peux utiliser le champ cbWndExtra de la structure WNDCLASS pour demander à Windows d'allouer un certain nombre d'octets (qu'il initialisera à 0) associés à chaque fenêtre de cette classe.
Ensuite, tu peux utiliser GetWindowLong et SetWindowLong pour récupérer/modifier ces octets. Rien ne t'empeche d'y stocker un pointeur vers une structure qui contiendra les données que tu associes à ta fenêtre. Il faut juste penser à allouer cette structure au moment du WM_CREATE et à libérer l'espace au moment du WM_DESTROY. Cette technique te permet d'éviter que ta classe de fenêtre n'utilise des globales, ce qui serait très ennuyeux pour sa réutilisabilité : imagine l'horreur si tu voulais avoir deux zones de dessin en même temps dans ton programme ? pire : deux zones de dessin dans deux modes différents ? |
|
|
00
|
|
|
#7 |
|
Invité de passage
![]() jean-luc GIORGETTAInscription : avril 2011 Messages : 7 ![]() |
Merci beaucoup pour tous ces conseils, cela me permet d'utiliser les bonnes méthodes et d'éviter de galérer. Je fais de la prog en amateur et je me familiarise peu à peu avec C++ et l'API Windows.
|
|
|
00
|
|
|
#8 |
|
Expert Confirmé Sénior
![]() |
L'autre moyen, c'est de juste mémoriser un pointeur de structure dans le slot GWLP_USERDATA.
Voir ceci pour un exemple d'utilisation (plus le lien sur SetWindowLongPtr()).
__________________
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant. "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?" Apparently everyone. -- Raymond Chen. Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen. |
|
|
00
|
|
|
#9 | |
|
Membre confirmé
![]() Inscription : décembre 2010 Messages : 99 ![]() |
Citation:
|
|
|
|
00
|
|
|
#10 |
|
Expert Confirmé Sénior
![]() |
Et si on utilise un Visual Studio 2008 ou supérieur, on n'a pas besoin de macros bizarres pour utiliser SetWindowLongPtr() sans warning: Sans le mode hybride de VS 2005, on peut utiliser la fonction directement.
(À noter que le morceau de code pour en-tête que j'ai posté en tient compte).
__________________
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant. "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?" Apparently everyone. -- Raymond Chen. Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen. |
|
|
00
|
|
|
#11 |
|
Invité de passage
![]() jean-luc GIORGETTAInscription : avril 2011 Messages : 7 ![]() |
Bonjour,
La gestion de la fenetre graphique fonctionne bien, mais je tombe sur un autre problème: le CHILD ne réagit pas aux messages clavier. Qd j'appuie sur "echap" je dois désactiver la toolBar graphique de la fenetre principale et simultanément effacer le tracé en cours. La fenetre principale récupère correctement le message mais le WinProc de la fenetre CHILD ne voit rien. Je n'ai pas trouvé de réponse sur MSDN. Je pense bêtement transferer le message par un SendMessage vers le CHILD, ou utiliser le fameux SetWindowLong. Cela ne me semble pas très élégant, y a-t-il une astuce simple? |
|
|
00
|
|
|
#12 |
|
Expert Confirmé Sénior
![]() |
Je pense que c'est la fenêtre principale qui commande, donc pour moi ce serait à elle d'envoyer un message "efface-toi" au CHILD.
__________________
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant. "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?" Apparently everyone. -- Raymond Chen. Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen. |
|
|
00
|
|
|
#13 | ||
|
Invité de passage
![]() jean-luc GIORGETTAInscription : avril 2011 Messages : 7 ![]() |
J'ai fait un SetForegroundWindow(hwnd du CHILD), et là je récupère correctement le code clavier. J'agis sur la ToolBar avec un SendMessage. Voici le switch concerné dans le WndProc de la fenetre CHILD:
Code :
|
||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com