IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

MFC Discussion :

Rafraichir la position d'un bouton...


Sujet :

MFC

  1. #1
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 79
    Points : 46
    Points
    46
    Par défaut Rafraichir la position d'un bouton...
    Bonsoir,

    J'ai un petit problème pour rafraichir la position d'un CButton sur une boite de dialogue...
    (Je suis désolé de balancer des gros bouts de code comme ça, je vous assure avoir cherché... et vraiment longtemps, avant de venir vous demander votre aide)

    Je m'explique :
    J'ai une CDialog dont la méthode OnPaint() est la suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    	CPaintDC	      dc(this); 
    	CRect			myRect;
    	CDC			MemDC;			
    	CBitmap			bmp;
    	CBrush			lBrush(RGB(221,221,221));
     
    	isOnce=false;
    	dc.GetWindow()->GetClientRect(&myRect);
    	MemDC.CreateCompatibleDC(&dc);
    	MemDC.SetBkMode(OPAQUE);
    	MemDC.SetBkColor(RGB(221,221,221));
    	bmp.CreateCompatibleBitmap(&dc,myRect.Width(),myRect.Height());
    	CBitmap *pOldBitmap =MemDC.SelectObject (&bmp); 
    	MemDC.SelectObject(&lBrush);
    	MemDC.PatBlt(0,0,myRect.Width(),myRect.Height(),PATCOPY); 
    	pObject->Draw(&MemDC,20,30,&myRect); //pObject est un autre objet d'une autre classe qui possède une méthode Draw                                                          permettant de dessiner sur un DC
    dc.BitBlt(0,0,myRect.Width(),myRect.Height(),&MemDC,0,0,SRCCOPY); 
     	MemDC.SelectObject (pOldBitmap);
    Pour éviter le flickering, j'utilise un DC mémoire dans lequel je dessine puis je fais un blit de l'ensemble de la boite de dialogue.

    Sur cette boite de dialogue, j'ai un bouton CMyButton qui est une classe dérivée de CButton des MFC. Les boutons CMyButton ont la particularité suivante:
    Lorsqu'on clique sur le bouton, le bouton va suivre le mouvement du pointeur de souris. En recliquant sur le bouton, on met fin à ce drag.

    J'ai ainsi la méthode suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void CMyButton::OnMouseMove(UINT nFlags, CPoint point) 
    {
    	if (isDrag) //si on est en cours de drag
    	{
    		CPoint		pointCourant;
    		CRect		rectButton;
    		NMHDR hdr;
     
    		hdr.hwndFrom = GetSafeHwnd();
                    hdr.idFrom   = GetDlgCtrlID();
                   hdr.code     = BN_MOUSEMOVE;
     
    		this->GetWindowRect(&rectButton);
    		this->GetParent()->ScreenToClient(&rectButton);
    		GetCursorPos(&pointCourant);
    		this->GetParent()->ScreenToClient(&pointCourant);
    		MoveWindow(pointCourant.x,rectButton.top,20,20,true);
     
    		GetParent()->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&hdr);
     
    	}
    Cette méthode capture le survol du bouton et si on est en cours de drag & drop, on déplace l'objet (MoveWindow). La fenetre parente (celle qui contient le bouton) en est avertie à l'aide d'un SendMessage.

    et dans ma boite de dialogue, j'ai la méthode qui est appelé par ce SendMessage:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    void CMyDlg::OnMouseMoveBtn(UINT id,NMHDR* pNMHDR, LRESULT* pResult)
    {
           /* ICI, JE MODIFIE LE pObject QUI SE TROUVE DANS LA METHODE ONPAINT. IL FAUT DONC REDESSINER LA FENETRE D'OU LE INVALIDATE*/
     
    	Invalidate();
     
    	CRect rect;
    	m_tabBtn.ElementAt(0)->GetWindowRect(&rect); //m_tabBtn est un bouton CMyButton
    	ScreenToClient(&rect);
    	ValidateRect(&rect);
     
    }
    En fait, ds cette méthode, je modifie l'objet pointé par pObject (que je dessine sur la boite de dialogue) => il faut donc redessiner la fenetre (d'où le Invalidate).
    Mais en faisant ça, mon bouton est effacé... (par le bitblit). J'essaye donc de valider la zone où se trouve le bouton avec le code:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    CRect rect;
    m_tabBtn.ElementAt(0)->GetWindowRect(&rect); //m_tabBtn est un bouton CMyButton
    ScreenToClient(&rect);
    ValidateRect(&rect);
    Mais cela ne fonctionne que moyennement (il ne semble pas valider toute la surface du bouton... ).

    Et là, c'est le drame.. cela fait plusieurs jours que je lutte sur ce problème..sans succès
    Avez vous des idées possibles pour résoudre ce problème? Une autre manière de faire?
    En gros, si je savais JUSTE (re)dessiner un bouton d'une boite de dialogue sans à avoir à redessiner la boite entière, ce serait gagné j'imagine... Il suffirait que je fasse ça, après le bitblit dans le OnPaint de la boite...

    Merci d'avance!

  2. #2
    Rédacteur
    Avatar de farscape
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2003
    Messages
    9 055
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2003
    Messages : 9 055
    Points : 17 323
    Points
    17 323
    Par défaut
    salut,
    une regle de base :
    chaque fenetre,controle etc .. doit savoir se redessiner par sa methode paint
    ondraw etc..
    tout dessin sur un control de maniere exterieur au controle donnera des resultats mitigés puisque l'on sort de la logique naturel.
    pour raffraichir un control il suffit de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    moncontrol.Invalidate()
    ce qui va provoquer un paint sur le controle.

  3. #3
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 79
    Points : 46
    Points
    46
    Par défaut
    Malheureusement, j'ai déjà essayé le Invalidate du bouton... mais cela ne marche pas non plus... peut-etre que je le place au mauvais endroit:

    (dans la méthode onpaint() de la boite de dialogue)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
       CPaintDC         dc(this);
       CRect         myRect;
       CDC         MemDC;         
       CBitmap         bmp;
       CBrush         lBrush(RGB(221,221,221));
     
       isOnce=false;
       dc.GetWindow()->GetClientRect(&myRect);
       MemDC.CreateCompatibleDC(&dc);
       MemDC.SetBkMode(OPAQUE);
       MemDC.SetBkColor(RGB(221,221,221));
       bmp.CreateCompatibleBitmap(&dc,myRect.Width(),myRect.Height());
       CBitmap *pOldBitmap =MemDC.SelectObject (&bmp);
       MemDC.SelectObject(&lBrush);
       MemDC.PatBlt(0,0,myRect.Width(),myRect.Height(),PATCOPY);
       pObject->Draw(&MemDC,20,30,&myRect); //pObject est un autre objet d'une autre classe qui possède une méthode Draw                                                          permettant de dessiner sur un DC
    dc.BitBlt(0,0,myRect.Width(),myRect.Height(),&MemDC,0,0,SRCCOPY);
    [b]pMyButton->Invalidate();[/b]
        MemDC.SelectObject (pOldBitmap);
    A noter que j'ai modifié le Onerasebkgnd() de la boite pour qu'il renvoie false au lieu de faire le comportement par défaut (dans l'optique d'éviter le flickering...)... je ne sais pas si cela a une incidence...

    A noter également que je n'ai pas écrit de méthode OnPaint pour mon CMybutton, si je fais un Invalidate() du bouton, ne va-t-il pas appeler la méthode OnPaint() du CButton? (puisque CMyButton est dérivée de CButton...)

  4. #4
    Membre du Club
    Inscrit en
    Juin 2004
    Messages
    79
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 79
    Points : 46
    Points
    46
    Par défaut
    Avec un pMyButton->UpdateWindow() au lieu du Invalidate() dans le code précédent, ca marche... je ne comprends pas pourquoi mais bon...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Trouver la position d'un bouton et le nom de la macro ?
    Par -=ET=- dans le forum Macros et VBA Excel
    Réponses: 7
    Dernier message: 23/10/2019, 19h50
  2. passer un tag(ou position) a un bouton
    Par ulquiorra dans le forum Composants graphiques
    Réponses: 2
    Dernier message: 03/05/2010, 16h10
  3. position d'un bouton
    Par lorie dans le forum Windows Presentation Foundation
    Réponses: 4
    Dernier message: 27/03/2010, 01h21
  4. position d'un bouton toujours a droite
    Par skunkies dans le forum Windows Forms
    Réponses: 8
    Dernier message: 19/12/2008, 10h26
  5. Bloquer la position d'un bouton sur une feuille à l'impression
    Par benpinta dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 26/10/2007, 17h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo