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

C++Builder Discussion :

probleme de gestion de la transparence d'un Bitmap


Sujet :

C++Builder

  1. #1
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut probleme de gestion de la transparence d'un Bitmap
    Bonjours
    Je tente de realiser un petit curseur, le curseur est un petit bitmap de 9x9 pixels, j'arrive a le dessiner mais je n'arrive pas a programmer la transparence j'ai pourtant inclus "wingdi.h", j'ai vu sur le net que l'on pouvait appeler "msimg32.dll", j'ai reussi a compiler et a executer le code sans erreurs mais la transparence ne fonctionne pas, et je ne vois pas d'ou cela vient
    le .cpp
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h"
    #include "windows.h"
    #include "wingdi.h"
    #include <conio.h>
     
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    PAINTSTRUCT ps;
    static HDC hDC, hdcMem;
    static HBITMAP hBitmap;
    static BITMAP bitmap;
    COLORREF crTransColor = RGB(0, 0, 0);
    typedef long (__cdecl *transparentblt)(HDC,int,int,int,int,HDC,int,int,int,int,UINT);
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
         : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    hBitmap = LoadImage(NULL, "C:\\Users\\home\\Documents\\Prog_Fraisage\\Bitmap18.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
    GetObject(hBitmap, sizeof(bitmap), &bitmap);
    hDC = GetDC(Form1->Handle);
    hdcMem = CreateCompatibleDC(hDC);
    SelectObject(hdcMem, hBitmap);
    transparentblt ImpFuncDLL;
    HINSTANCE msimg = LoadLibrary("msimg32.dll");
    ImpFuncDLL= (transparentblt)GetProcAddress(msimg, "TransparentBlt");
    if (ImpFuncDLL)
    {
    transparentblt(hDC, 120, 120, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, crTransColor);
    }
    BeginPaint(hDC, &ps);
    BitBlt(hDC, 120, 120, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); // SRCAND NOTSRCCOPY SRCPAINT SRCCOPY
    EndPaint(hDC, &ps);
    }
    //---------------------------------------------------------------------------

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 705
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 705
    Points : 25 575
    Points
    25 575
    Par défaut
    Tu fais tout par API ?
    Est-ce une volonté ?

    TImageList.Draw + TDrawingStyle dsTransparent gère cela à la perfection pour copier une image transparente vers un TBitmap
    Etudie le code Pascal pour en extraire les API

  3. #3
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Merci pour ta reponse ShaiLeTroll
    Je fais des testes pour voir si le code s'execute plus rapidement avec les Api, le dessin va s'afficher et s'effacer pour simuler le deplacement d'un outil, je veux eviter le scintillement a l'ecran, et puis cela permet d'apprendre la programmation non assistee

  4. #4
    Membre actif Avatar de Argol_Medusa
    Homme Profil pro
    Ingénieur Radiofréquences
    Inscrit en
    Août 2005
    Messages
    208
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur Radiofréquences
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Août 2005
    Messages : 208
    Points : 245
    Points
    245
    Par défaut
    Bonjour,

    je ne suis pas sur que ce soit beaucoup plus rapide "à l'échelle humaine" en utilisant les API, maintenant on a tout de même des sacrées bêtes de course niveau ordinateur, et de toute façon 25 Hz de rafraichissement suffit.

    Je ne connais pas les commandes que tu utilises, mais par contre pour confirmation : est-ce que par "curseur" tu parles du curseur de la souris que tu déplaces par logiciel ou simplement d'un curseur que tu ajoutes sur ton images mais qui n'a rien à voir avec le curseur de souris ?

    Dans le second cas, personnellement j'utilise la technologie de la superposition de Form transparentes, qui a l'avantage de passer partout, y compris sur de la video passant directement par la carte 3D ( accélération matériel 3D).

    J'avais fais un HUD tete haute de drone quadcopter avec cette technique ça marche pas mal ).

    D'ailleurs maintenant que j'y pense, je me demande si ce n'est pas toi qui m'avait conseillé cette technique il y a quelques années Blondelles sur ce forum

    Sinon en mettant à true le double buffer on n'a pas de scintillement normalement, et avec un PNG, aucun problème, la transparence est gérée nativement ( enfin sur le XE3 en tout cas pour le builder 6 je ne suis pas sur )

  5. #5
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Merci pour ta reponse Argol_Medusa
    C'est pour l'interface graphique d'un logiciel de pilotage de fraiseuse d'etabli
    le curseur que je cherche a controler, n'est pas celui gere par la souris, mais un repere visuel qui represente la position de l'outil sur la piece en cours d'usinage
    je pensais utiliser un TImage transparent, qui peut s'effacer facilement avec " Picture = NULL "
    les déplacements sont de l'ordre de quelque centiemes de mm, il y a donc beaucoup d'affichages / effacements, et un scintillement desagreable
    j'ai aussi la posibilite de mettre un compteur et d'effectuer un affichage / effacement sur 10 ou 100
    ou ce que j'essaye de tester les APIs
    le materiel informatique sejourne dans un atelier et n'est pas de premiere jeunesse
    j'utilise souvent les Images transparentes, la gestion en est beaucoup plus simple quand on a de nombreuses choses a afficher
    je suis encore avec mon vieux bcb6
    les PNG je n'ai jamais utilise

  6. #6
    Membre averti

    Profil pro
    Inscrit en
    Janvier 2003
    Messages
    288
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations forums :
    Inscription : Janvier 2003
    Messages : 288
    Points : 334
    Points
    334
    Par défaut
    J'ai souvent eu des problèmes avec la transparence des icones.
    En gros les API n'ont pas beaucoup d'influence sur la transparence des icones (ou cruseurs), c'est l'icone qui doit contenir ses infos de transparence.
    Donc ça dépend surtout:
    1- de l'outil d'édition que tu utilise.
    2- de la façon dont il est stocké dans CBuilder.

    1- Je crée mes icones avec un freeware qui s'appelle IcoFx puis je les édite dans VisualStudio pour ajouter la transparence (je pense que IcoFx pourrais tout faire mais c'est la force de l'habitude).

    2- L'éditeur de resource de CBuilder n'est pas fiable et à tendance à réécrire les ressources et alors adieux la transparence. Je crée donc un fichier resource windows (.rc + resource.h) de type VisualStudio (avec VS ou ResEDit - un freeware) et je joint les ressource au projet.
    Ensuite je charge les ressources avec les API.

    Si ça t'intéresse je peut mettre un exemple.

  7. #7
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Merci pour ta reponse yarp
    A la suite de ta reponse j'ai teste la transparence sur tous les types de BMP du grise au 24bits ca ne fonctionnait pas, en regardant de plus prêt la fonction " LoadImage " je me suis apercu qu'il y avait la posibilite de passer des parametres de transparence apres essais voici un code qui fonctionne chez moi
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    #include "wingdi.h"
    #include <conio.h>
    
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    PAINTSTRUCT ps;
    static HDC hDC, hdcMem;
    static HBITMAP hBitmap;
    static BITMAP bitmap;
    COLORREF crTransColor = RGB(0, 0, 0);
    typedef long (__cdecl *transparentblt)(HDC,int,int,int,int,HDC,int,int,int,int,UINT);
    //typedef long (__declspec(dllimport) *transparentblt)(HDC,int,int,int,int,HDC,int,int,int,int,UINT);
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
         : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    hBitmap = LoadImage(NULL, "C:\\Users\\home\\Documents\\Prog_Fraisage\\Bitmap18.bmp", IMAGE_BITMAP, 9, 9, LR_LOADFROMFILE | LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS); //
    GetObject(hBitmap, sizeof(bitmap), &bitmap);
    hDC = GetDC(Form1->Handle);
    hdcMem = CreateCompatibleDC(hDC);
    SelectObject(hdcMem, hBitmap);
    //SetLayeredWindowAttributes(hdcMem, crTransColor, 255, LWA_COLORKEY);
    transparentblt ImpFuncDLL;
    HINSTANCE msimg = LoadLibrary("C:\\Windows\\System32\\msimg32.dll");
    ImpFuncDLL= (transparentblt)GetProcAddress(msimg, "TransparentBlt");
    if (ImpFuncDLL)
    {
    transparentblt(hDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, crTransColor);
    Label1->Caption = "ok";
    }
    //for(int i = 1; i <= 200; i = i+20)
    //{
    BeginPaint(hDC, &ps);
    BitBlt(hDC, 120, 120, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); // SRCAND NOTSRCCOPY SRCPAINT SRCCOPY
    EndPaint(hDC, &ps);
    //}
    }
    //---------------------------------------------------------------------------
    yarp si tu pouvait essayer la modif chez toi avec un code qui ne fonctionnait pas cela permettrait de voir si le code est valable

  8. #8
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Je viens de m'apercevoir que quelque soit la valeur de " crTransColor " le BMP est transparent

  9. #9
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    J'ai simplifie le code
    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
    22
    23
    24
    25
    26
    27
    28
     
    //---------------------------------------------------------------------------
    #include <vcl.h>
    #pragma hdrstop
    #include "Unit1.h" 
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm1 *Form1;
    static HDC hDC, hdcMem;
    static HBITMAP hBitmap;
    static BITMAP bitmap;
    //---------------------------------------------------------------------------
    __fastcall TForm1::TForm1(TComponent* Owner)
         : TForm(Owner)
    {
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
    hBitmap = LoadImage(NULL, "C:\\Users\\home\\Documents\\Prog_Fraisage\\Bitmap21.bmp", IMAGE_BITMAP, 9, 9, LR_LOADFROMFILE | LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS); //
    GetObject(hBitmap, sizeof(bitmap), &bitmap);
    hDC = GetDC(Form1->Handle);
    hdcMem = CreateCompatibleDC(hDC);
    SelectObject(hdcMem, hBitmap);
    BitBlt(hDC, 120, 120, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY); // SRCAND NOTSRCCOPY SRCPAINT SRCCOPY
    }
    //---------------------------------------------------------------------------

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Citation Envoyé par blondelle Voir le message
    Je viens de m'apercevoir que quelque soit la valeur de " crTransColor " le BMP est transparent
    Parce que dans ton cas, c'est le premier pixel du bitmap qui sert de couleur de transparence. Donc si ton sprite utilise ce pixel ... ça ne marche plus comme prévu (tel que tu pourrais penser que ...) !

    A plus !

  11. #11
    Membre chevronné

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    1 390
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 390
    Points : 1 777
    Points
    1 777
    Par défaut
    Salut !

    J'ai retrouvé dans mes archives perso une classe qui me permettait de modéliser un sprite sachant se dessiner sur un arrière plan sans que ce dernier ait besoin d'être redessiné.
    Celà signifie qu'on peut travailler sans double buffering.

    Voici brièvement les mécanismes mis en oeuvre :

    - à la construction, le sprite extrait les pixels à dessiner en les mettant en liste.
    - lorsque le sprite se dessine pour la première fois, il sauvegarde chaque pixel de l'arrière plan et y dessine le sien.
    - les autres fois, il restitue d'abord les pixels d'arrière plan et réalise les opérations précédentes sur une nouvelle position de l'arrière plan.

    Le code a été développé avec BCB3 Pro et exécuté jadis sur une machine tournant à 233 MHz.

    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
    22
    //-----------
    class jPixel
    {
    public :
    TPoint Bkgnd_Pos;
    TColor Bkgnd_Color;
    TPoint Off;
    TColor Color;
    };
    //-----------
    class jSprite : public TComponent
    {
    public :
    bool InUse;
    TPoint Pos;
    TList *Pixels;
        __fastcall jSprite(TComponent *AOwner);
        __fastcall jSprite(TComponent *AOwner, Graphics::TBitmap *Sprite, TColor AColor);
        __fastcall ~jSprite();
        void __fastcall Draw(TCanvas *C);
    };
    //-----------


    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    //-----------
    __fastcall jSprite::jSprite(TComponent *AOwner)
        : TComponent(AOwner)
    {
    Pixels = new TList;
    }
    //-----------
    __fastcall jSprite::~jSprite()
    {
    int j;
    for(j=0; j < Pixels->Count; j++)
        {
        delete (jPixel*)Pixels->Items[j];
        }
    Pixels->Clear();
    delete Pixels;
    }
    //-----------
    __fastcall jSprite::jSprite(TComponent *AOwner,
                               Graphics::TBitmap *Sprite, TColor AColor)
        : TComponent(AOwner)
    {
    Pixels = new TList;
    jPixel *P;
    int x, y;
    TColor color;
    TCanvas *C = Sprite->Canvas;
    for(y = 0; y < Sprite->Height; y++)
        {
        for(x = 0; x < Sprite->Width; x++)
            {
            color = C->Pixels[x][y];
            if(color != AColor)
                {
                P = new jPixel();
                Pixels->Add(P);
                P->Color = color;
                P->Off = Point(x,y);
                }
            }
        }
    InUse = false;
    }
    //-----------
    void __fastcall jSprite::Draw(TCanvas *C)
    {
    int j;
    jPixel *Pix;
    if(InUse)
        {
        // restauration des pixels de l'arrière plan
        for(j=0; j < Pixels->Count; j++)
            {
            Pix = (jPixel*)Pixels->Items[j];
            C->Pixels[Pix->Bkgnd_Pos.x][Pix->Bkgnd_Pos.y] = Pix->Bkgnd_Color;
            }
        }
    else
        {
        InUse = true;
        }
    for(j=0; j < Pixels->Count; j++)
        {
        Pix = (jPixel*)Pixels->Items[j];
        // position du pixel du sprite sur l'arrière plan
        Pix->Bkgnd_Pos.x = Pos.x + Pix->Off.x;
        Pix->Bkgnd_Pos.y = Pos.y + Pix->Off.y;
        // sauvegarde du pixel de l'arrière plan
        Pix->Bkgnd_Color = C->Pixels[Pix->Bkgnd_Pos.x][Pix->Bkgnd_Pos.y];
        // dessin du pixel du sprite sur l'arrière plan
        C->Pixels[Pix->Bkgnd_Pos.x][Pix->Bkgnd_Pos.y] = Pix->Color;
        }
    }
    //-----------

    Voici la mise en oeuvre avec un TImage Image1 (invisible) sur la form et préchargé avec le bitmap du sprite :

    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    jSprite *Sprite;
     
     
    //-----------
    __fastcall TForm1::TForm1(TComponent* Owner)
        : TForm(Owner)
    {
    Sprite = new jSprite(this, Image1->Picture->Bitmap, clBlack);
    Sprite->Pos = Point(100,100);
    }
    //-----------
    void __fastcall TForm1::FormPaint(TObject *Sender)
    {
    Canvas->Brush->Color = Color;
    Canvas->FillRect(ClientRect);
    Canvas->Brush->Color = clRed;
    Canvas->Ellipse(50,50, 300,300);
    Sprite->Draw(Canvas);
    }
    //----------- OnMouseDown de la form
    void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
          TShiftState Shift, int X, int Y)
    {
    Sprite->Pos = Point(X,Y);
    Sprite->Draw(Canvas);
    }
    //----------- OnResize de la form
    void __fastcall TForm1::FormResize(TObject *Sender)
    {
    Sprite->InUse = false;
    Repaint();
    }
    //-----------
    En espérant que ça te soit utile !

    A plus !

  12. #12
    Rédacteur
    Avatar de blondelle
    Homme Profil pro
    Inscrit en
    Mars 2006
    Messages
    2 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 2 738
    Points : 3 766
    Points
    3 766
    Par défaut
    Merci Henderson
    Je vais tester ton code

Discussions similaires

  1. [Oracle]probleme de gestion des utilisateurs
    Par gentarik dans le forum Oracle
    Réponses: 5
    Dernier message: 09/03/2005, 13h58
  2. Probleme a la noix de transparence sous c# [TROUVé]
    Par FranckF57 dans le forum DirectX
    Réponses: 2
    Dernier message: 07/09/2004, 17h57
  3. probleme avec les exposions et transparence ?
    Par ilimo dans le forum DirectX
    Réponses: 11
    Dernier message: 29/05/2004, 01h24
  4. [TP]Probleme de gestion d'écriture écran
    Par @tom@ dans le forum Turbo Pascal
    Réponses: 6
    Dernier message: 22/12/2003, 21h49
  5. probleme de gestion de clients avec des sockets....
    Par ludvo dans le forum Réseau
    Réponses: 6
    Dernier message: 25/09/2003, 13h37

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