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

Windows Discussion :

[MFC] CDC::TransparentBlt() ne supporte visiblement pas les couches multiples


Sujet :

Windows

  1. #1
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut [MFC] CDC::TransparentBlt() ne supporte visiblement pas les couches multiples
    Bonjour,

    Il se trouve que je dispose d'une boîte de dialogue constituée uniquement d'une view, sur laquelle s'affiche un skin (CBitmap m_skin) durant OnPaint() selon :
    Code C++ : 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
    void CPlayTyleDlg::OnPaint()
    {
    	if (IsIconic())
    	{
    		//...
    	}
    	else
    	{
    		CPaintDC dc(this);
    		CDC memDC;
     
    		memDC.CreateCompatibleDC(&dc);
    		CBitmap *oldBitmap = memDC.SelectObject(&m_skin);
    		CSize skinSize = m_skin.GetBitmapDimension();
     
    		dc.BitBlt(0,0,skinSize.cx, skinSize.cy, &memDC, 0, 0, SRCCOPY);
     
    		memDC.SelectObject(oldBitmap);
    	}
    }
    L'affichage marche correctement, mais quand je rajoute un CTransparentHoverButton, les zones transparentes du bitmap (rendu possible grâce à l'utilisation de CDC::TransparentBlt(), voir ci-dessous) laissent non pas apparaître le bitmap, mais la view (en dessous). J'aimerais savoir pourquoi ?

    Voici la méthode d'affichage des boutons :
    Code C++ : 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
    void CHoverButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    	CDC *mydc=CDC::FromHandle(lpDrawItemStruct->hDC);
     
    	CDC memDC;
    	memDC.CreateCompatibleDC(mydc);
     
    	CBitmap * pOldBitmap;
    	pOldBitmap = memDC.SelectObject(&mybitmap);
     
    	CPoint point(0,0);
     
            //Exemple de blit, avec CSize m_ButtonSize, COLORREF m_crTransparent : 
            mydc->TransparentBlt(0,0,m_ButtonSize.cx,m_ButtonSize.cy,memDC,m_ButtonSize.cx*2,0,m_ButtonSize.cx, m_ButtonSize.cy, m_crTransparent);
     
    	// clean up
    	memDC.SelectObject(pOldBitmap);
    }

    C'est vraiment gênant pour moi, et je n'arrive pas à résoudre ce problème... sauriez-vous y remédier ?

    Merci d'avance.

    P.S: Le bouton est créé avec le style BS_OWNERDRAW.
    Vive l'embarqué.

  2. #2
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    Up
    Vive l'embarqué.

  3. #3
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    J'ai vraiment l'impression d'avoir absolument tout essayé... finalement, je pense que la solution la plus appropriée reste à stocker dans le bouton son arrière-plan, seulement je n'arrive pas à l'obtenir.

    La fenêtre parent de ces boutons possède un skin affiché durant OnPaint()

    J'ai pensé à :

    Code C++ : 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
    //CXDlg::m_skin est le skin de la fenêtre (CBitmap)
    CRect buttonRect;
    CBitmap bkgnd;
     
    button.GetClientRect(&buttonRect);
    button.ClientToScreen(&buttonRect);
    this->ScreenToClient(&buttonRect);
     
    CDC bkgndDC;
    bkgndDC.CreateCompatibleDC(NULL);
    CDC skinDC;
    skinDC.CreateCompatibleDC(NULL);
     
    bkgndDC.BitBlt(0,0,buttonRect.Width(), buttonRect.Height(), &skinDC, buttonRect.left, buttonRect.top, SRCCOPY);
     
    bkgndDC.DeleteDC();
    skinDC.DeleteDC();
     
    button.SetBkgnd(bkgnd);

    Mais je ne pense pas que cela marche (je me demande si CreateCompatibleDC(NULL) est adapté...).

    Aidez-moi, s'il-vous-plaît...

    Merci d'avance.
    Vive l'embarqué.

  4. #4
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    J'ai essayé une dernière chose, c'est mieux, mais c'est pas ça non plus.

    En effet, j'ai procédé comme pour ma listbox transparente, à savoir une récupération du fond du contrôle lors de OnEraseBkgnd(), si ce n'est pas déjà fait. Ensuite, à chaque fois que j'affiche le bouton :

    Code C++ : 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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    void CHoverButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
    {
    	CDC *mydc=CDC::FromHandle(lpDrawItemStruct->hDC);
     
    	CDC memDC;
    	memDC.CreateCompatibleDC(mydc);
            CBitmap * pOldBitmap;
    	pOldBitmap = memDC.SelectObject(&mybitmap);
     
            //Here
            CDC memBkgndDC;
    	memBkgndDC.CreateCompatibleDC(mydc);
    	CBitmap *pOldBkgndBitmap;
    	pOldBkgndBitmap = memBkgndDC.SelectObject(&m_bkgnd);
            //End
     
    	int offset = 0;
     
    	if(lpDrawItemStruct->itemState & ODS_SELECTED)
    		offset = m_ButtonSize.cx*2;
    	else if(m_bHover)
    		offset = m_ButtonSize.cx;
    	else
    		offset = 0;
     
    	for(int x = 0 ; x < m_ButtonSize.cx ; ++x)
    	{
    		for(int y = 0 ; y < m_ButtonSize.cy ; ++y)
    		{
    			if(memDC.GetPixel(offset+x, y) == m_crTransparent)
    				mydc->SetPixel(x, y, memBkgndDC.GetPixel(x, y)); //here
    			else
    				mydc->SetPixel(x, y, memDC.GetPixel(x+offset, y));
    		}
    	}
     
    	// clean up
    	memDC.SelectObject(pOldBitmap);
    	memBkgndDC.SelectObject(pOldBkgndBitmap);
    }

    Maintenant, le fond est toujours noir, quelque soit le bouton

    Je ne sais plus quoi faire, pourriez-vous m'aider ?

    Merci d'avance.

    Edit: D'ailleurs, comment procéderiez-vous pour copier dans un CBitmap le tiers (point de vue largeur) d'un autre CBitmap ? Merci.
    Vive l'embarqué.

  5. #5
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    Euh... up ?
    Vive l'embarqué.

  6. #6
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    ...
    Vive l'embarqué.

  7. #7
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 361
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 361
    Points : 20 381
    Points
    20 381
    Par défaut
    Pas trop le temps de regarder mais TransparentBlt c'est pour les bitmaps plutot.
    Tu veux faire de l'AlphaBlending sur une fenêtre ?
    Regarder avec pSetLayeredWindowAttributes mais cela ne fonctionne qu'avec des CDialog
    Et il y a un forum MFC spécifique
    Au cas ou cela peut servir...
    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
    void CTestDlg2Dlg::OnButton1() 
    {
    HMODULE hDLL = LoadLibrary ("user32");
    SetWindowLong(m_hWnd ,GWL_EXSTYLE,GetWindowLong(m_hWnd , GWL_EXSTYLE) | WS_EX_LAYERED);
    if ( hDLL ) {
    				PSLWA pSetLayeredWindowAttributes =  (PSLWA) GetProcAddress(hDLL,"SetLayeredWindowAttributes");
    					if (pSetLayeredWindowAttributes != NULL) 
    {
    pSetLayeredWindowAttributes (m_hWnd , 0, 128 , LWA_ALPHA);
    }
    }
    FreeLibrary(hDLL);
    }
    
    }

  8. #8
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    Non, je ne veux pas faire d'Alphablending sur des fenêtres. Mon but est d'afficher des bitmaps de boutons, dont les pixels d'une certaine couleur sont transparents et laissent apparaître le fond de la fenêtre (la couche du dessous, pour vulgariser)...
    Vive l'embarqué.

  9. #9
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je ne suis pas sûr que ce soit la source du problème, mais j'ai ceci :
    Si ton CHoverButton n'est pas WindowLess, tu dois lui rajouter le style WS_TRANSPARENT pour t'assurer que tout ce qui est "en-dessous" est bien dessiné "avant".
    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.

  10. #10
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    C'était une très bonne idée (j'ai cru que c'était la solution), mais cela ne marche malheureusement pas... en spécifiant le style WS_EX_TRANSPARENT, retirant mes essais de copie du background etc., et en rajoutant le TransparentBlt, je me retrouve avec le fond de la fenêtre (COLOR_WINDOW) comme arrière-plan du bouton (bien qu'il se dessine correctement). Ce phénomène montre que la fenêtre est redessinée avant le bouton*, mais alors comment se fait-il que le skin n'apparaisse pas à cet endroit (je traite OnPaint() par le dessin du skin en me servant d'un CPaintDC) ?

    Merci de m'aider.

    * : à part s'il s'agit en fait du fond du bouton (COLOR_BUTTON), mais j'en doute étant donné qu'il s'agit d'un Ownerdraw.
    Vive l'embarqué.

  11. #11
    Membre régulier Avatar de kidpaddle2
    Inscrit en
    Avril 2006
    Messages
    430
    Détails du profil
    Informations forums :
    Inscription : Avril 2006
    Messages : 430
    Points : 95
    Points
    95
    Par défaut
    Up
    Vive l'embarqué.

Discussions similaires

  1. Réponses: 14
    Dernier message: 30/04/2010, 07h04
  2. Le serveur ne supporte pas les triggers, que faire
    Par ersoufiane dans le forum MySQL
    Réponses: 3
    Dernier message: 03/10/2009, 13h59
  3. Réponses: 9
    Dernier message: 11/11/2008, 19h27
  4. Réponses: 2
    Dernier message: 29/07/2007, 11h48
  5. Dossir Extras ne supporte pas les scripts?
    Par Donaldo dans le forum 4D
    Réponses: 2
    Dernier message: 21/03/2007, 17h25

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