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

Composants VCL Delphi Discussion :

Déplacement d'un form transparent (LAYERED) [Archives]


Sujet :

Composants VCL Delphi

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 15
    Points : 8
    Points
    8
    Par défaut Déplacement d'un form transparent (LAYERED)
    J'essaye de créer une application skinnée par des pngs (qui peuvent être transparents).

    J'ai réussi depuis à créer un form transparent en changeant les paramètres de création et enlevant les bords :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    procedure TForm1.CreateParams(var Params:TCreateParams);
    Begin
     inherited CreateParams(Params);
     Params.ExStyle:=WS_EX_LAYERED;
    End;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
     Form1.Brush.Style:=bsClear;
     Form1.BorderStyle:=bsNone;
    end;
    J'ai mis plusieurs images pngs sur le form. La transparence marche niquel , il n'y pas de problème.

    Cependant j'ai fait une méthode pour déplacer le form, celle-ci marche bien mais mon problème est que toute la zone transparente n'est pas raffraichit : toute la zone qui est était transparente se déplace avec la form.
    J'ai essayé plusieurs méthodes, de faire des paint, des repaint,etc.. rien ne marche.
    Pour le déplacement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    var MovePoint: TPoint;
    begin
     if FDragging and FAllowDrag then
       begin
         GetCursorPos(MovePoint);
         SetWindowPos(self.Handle,self.ParentWindow,MovePoint.X - FDownPoint.X,MovePoint.Y - FDownPoint.Y,self.Width,self.Height,0);
       end;
    end;
    Quelqu'un aurait-il une autre idée pour déplacer la form, ou pour rafraichir la zone transparente ? Merci

  2. #2
    Membre chevronné
    Avatar de Pierre Castelain
    Inscrit en
    Avril 2002
    Messages
    523
    Détails du profil
    Informations forums :
    Inscription : Avril 2002
    Messages : 523
    Points : 1 943
    Points
    1 943
    Par défaut
    Il vaut mieux utiliser des régions : http://zewaren.developpez.com/delphi/regions/

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2003
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2003
    Messages : 560
    Points : 576
    Points
    576
    Par défaut
    Bonjour

    quand vous posez un composant transparent sur une fenêtre windows dessine le parent en tenant compte de l'enfant.

    En d'autre terme si l'enfant chnage de place et que le parent n'est pas redessiner il reste une trace sur le parent.
    Dans ce cas si vous cacher la fenêtre (en mettant une autre fenêtre dessus par exemple) puis que vous la réaffichier, l'update du parent est automatique et le resultat est correcte.

    Si c'est le cas, il vous faut forcer le rafraichissment du parent en jouant sur les ordres refresh/update de l'enfant et du parent. Atention pas de généralité. Dans ce cas chaque solution est au coup le coup pour optimser la vitesse de rafraichissement de l'écran.

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    Citation Envoyé par Pierre Castelain
    Il vaut mieux utiliser des régions : http://zewaren.developpez.com/delphi/regions/

    Je ne veux pas utiliser les régions car je voudrais utiliser des pngs avec des transparences sur 8bits comme le format le permet.

    Citation Envoyé par Tardiff Jean-François
    Si c'est le cas, il vous faut forcer le rafraichissment du parent en jouant sur les ordres refresh/update de l'enfant et du parent. Atention pas de généralité. Dans ce cas chaque solution est au coup le coup pour optimser la vitesse de rafraichissement de l'écran.
    En effet, la trace reste sur le form entier donc sur le parent. Je vais essayer de faire des refresh ou update sur le parent, mais je crois que j'avais déjà essayé.

    Je vous tiens au courant, merci pour vos suggestions.

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    Je n'arrive toujours pas à actualiser le fond du form.

    J'ai essaye plusieurs methodes, genre deplacer le form avec l'api de windows mais rien n'y fait.

    J'essaye depuis de créer un window manuellement avec CreateWindowEx. Mais, sous Delphi, je n'arrive pas à refaire la même chose que windows, c'est à dire que la fenetre soit transparente, sans bordures et sans fond.

    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
       wndClass.style          := CS_HREDRAW or CS_VREDRAW;
       wndClass.lpfnWndProc    := @WndProc;
       wndClass.cbClsExtra     := 0;
       wndClass.cbWndExtra     := 0;
       wndClass.hInstance      := hInstance;
       wndClass.hIcon          := LoadIcon(0, IDI_APPLICATION);
       wndClass.hCursor        := LoadCursor(0, IDC_ARROW);
       wndClass.hbrBackground  := COLOR_BACKGROUND+1;
       wndClass.lpszMenuName   := nil;
       wndClass.lpszClassName  := 'GettingStarted';
     
       RegisterClass(wndClass);
     
       hWnd := CreateWindowEx(WS_EX_LAYERED,'GettingStarted','Hello',WS_OVERLAPPEDWINDOW,0,0,
          Integer(CW_USEDEFAULT), // initial x size
          Integer(CW_USEDEFAULT), // initial y size
          0,0,hInstance,nil);
     
       ShowWindow(hWnd, SW_SHOW);
       UpdateWindow(hWnd);
       SetLayeredWindowAttributes (hWnd, 0, 100, LWA_ALPHA);
    Quelqu'un pourrait me donner un exemple sous Delphi de l'implementation de cette fonction pour avoir une fenetre transparente ?
    Merci d'avance

  6. #6
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Points : 37
    Points
    37
    Par défaut
    salut,

    je ne sais pas si c'est ca que tu cherches, mais voici une petite fonction qui applique la transparence sur une fenetre :

    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
     
     
    const WS_EX_LAYERED = $80000;
             LWA_ALPHA    = 2;
     
    type
     TSetLayeredWindowAttributes = function (
         hwnd : HWND;         // handle to the layered window
         crKey : TColor;      // specifies the color key
         bAlpha : byte;       // value for the blend function
         dwFlags : DWORD      // action
         ): BOOL; stdcall;
     
     
    procedure TForm1.SetTransparentForm(AHandle : THandle; AValue : byte = 0);
     
    var SetLayeredWindowAttributes: TSetLayeredWindowAttributes;
     
    begin
         if WindowsTransparencyEnable // test si windows 2000 ou XP
            then
         begin
              try
                 SetLayeredWindowAttributes := 
                       GetProcAddress(GetModulehandle(user32), 'SetLayeredWindowAttributes');
                 if Assigned(SetLayeredWindowAttributes)
                    then
                 begin
                      SetWindowLong(AHandle, GWL_EXSTYLE, GetWindowLong(AHandle, GWL_EXSTYLE) 
                             or WS_EX_LAYERED);
                      SetLayeredWindowAttributes(AHandle, 0, AValue, LWA_ALPHA);
                 end;
              except
     
              end;
         end;
    end;
    Tu peux l'appliquer directement sur une form delphi , en lui passant son Handle
    ;-) phenix

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    @phenixauthor:
    Je recherche à faire un form transparent, mais je ne veux pas que la transparence s'applique à tous les objets du form mais seulement au fond.
    Je m'explique : par ex, si j'ai une image sur mon form, alors lorsque je lancerai l'application, je ne verrai que l'image "qui flotte", je ne veux pas voir les bords, ni la barre de menus.

    La fonction que tu me donnes applique une effet de transparence au form entier, y compris les objets qu'il contient.

    J'ai trouvé un code en c# qui permet de faire ce que je veux, il utilise l'api UpdateLayeredWindow pour charger une png, qu'il a auparavant convertit en bmp avec un alpha channel. Source
    J'avoue que je ne savais pas que c'était possible, j'ai essayé de le porter sous Delphi mais sans succés.

  8. #8
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Points : 37
    Points
    37
    Par défaut
    salut,

    D'accord, je me disais aussi, ca ne devait pas etre ca...

    Oui je vois ce que tu veux faire, effecitvement c'est interessant.

    bon, heureusement le code source à l'air d'etre du .NET, ca devrait se traduire sans trop de douleur, meme à partir de c# ( au moins c'est deja un bon point pour .net je trouve, enfin bref ....)

    Comme ca, en survolant les articles vite fait, il me semble que cela cause pas mal de GDI+.
    Or ne serait-ce pas justement qq chose de typique .net ? Enfin tu veux ptet le faire en delphi .net ?
    ;-) phenix

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    J'ai essaye de porter le code C# sous Delphi mais j'ai Windows qui me dis qu'un paramètre est incorrect.

    Code 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
    bitmap = Image.FromFile(fileName) as Bitmap;
     
    IntPtr screenDc = Win32.GetDC(IntPtr.Zero);
    IntPtr memDc = Win32.CreateCompatibleDC(screenDc);
    IntPtr hBitmap = IntPtr.Zero;
    IntPtr oldBitmap = IntPtr.Zero;
     
    try {
      hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));  // grab a GDI handle from this GDI+ bitmap
     
      Win32.Size size = new Win32.Size(bitmap.Width, bitmap.Height);
      Win32.Point pointSource = new Win32.Point(0, 0);
      Win32.Point topPos = new Win32.Point(Left, Top);
      Win32.BLENDFUNCTION blend = new Win32.BLENDFUNCTION();
      blend.BlendOp             = Win32.AC_SRC_OVER;
      blend.BlendFlags          = 0;
      blend.SourceConstantAlpha = opacity;
      blend.AlphaFormat         = Win32.AC_SRC_ALPHA;
     
      Win32.UpdateLayeredWindow(Handle, screenDc, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, Win32.ULW_ALPHA);
    }
    Code Delphi
    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
    procedure TForm1.FormCreate(Sender: TObject);
    var
      bitmap: HBitmap;
      fic: TBitmap;
      size: PSIZE;
      pointsource,topPos: PPOINT;
      blend: PBLENDFUNCTION;
      memDC,screenDC: HDC;
      retour: boolean;
    begin
       fic := TBitmap.Create;
       fic.LoadFromFile('...\FRUIT.bmp');
     
       screenDC := GetDC(0);
       memDC := CreateCompatibleDC(screenDC);
       bitmap := fic.handle;
     
       New(size);
       New(pointSource);
       New(topPos);
       New(blend);
       size.cx := fic.Width;
       size.cy := fic.Height;
       pointSource.X := 0;
       pointSource.Y := 0;
       topPos.X := 0;
       topPos.Y := 0;
       blend.BlendOp := AC_SRC_OVER;
       blend.BlendFlags := 0;
       blend.SourceConstantAlpha := 255;
       blend.AlphaFormat := AC_SRC_ALPHA;
     
       retour := UpdateLayeredWindow(Form1.Handle,
       screenDc,topPos,size, memDc,pointSource, 0,blend,ULW_ALPHA);
     
       // Affichage de l'erreur
       raise Exception.Create(SysErrorMessage(GetLastError));
       MessageDlg(BoolToStr(retour), mtInformation,[mbOk], 0);
     
    end;
    Je n'ai pas trop l'habitude de coder avec l'api de windows donc si quelqu'un voit l'erreur ? merci bien

  10. #10
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Points : 37
    Points
    37
    Par défaut
    salut,

    Je me suis amusé un peu aussi hier soir sur ces routines...

    Bon, pour ton code en haut, il manque une ligne importante :

    SetWindowLong(Handle, GWL_EXSTYLE,WS_EX_LAYERED)

    Sinon, tu obtiens un code d'erreur ( param incorrect ):

    il faut definir en premier lieu le type de la fenetre à WS_EX_LAYERED avant de lui passer appliquer la methode UpdateLayeredWindow

    ensuite, à première vue le code ne fonctionne pas avec ton CreateCompatibleDC and Co : autant simplifier et lui passer le handle du bitamp d'origine

    Ah, pis j'ai rencontré des soucis avec les coordonnées, j'ai donc modifié le type

    Resultat :

    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
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      fic: TBitmap;
      size: PSIZE;
      TopLeft, BmpTopLeft: TPoint;
      Blend: TBlendFunction;
      memDC,screenDC: HDC;
      retour: boolean;
    begin
     
       fic := TBitmap.Create;
       fic.LoadFromFile('test.bmp');
       fic.PixelFormat := pf32Bit; // important !!
     
       SetWindowLong(Handle, GWL_EXSTYLE,WS_EX_LAYERED);
     
     
       New(size);
     
       size.cx := fic.Width;
       size.cy := fic.Height;
     
       TopLeft := BoundsRect.TopLeft;
       BmpTopLeft := Point(0, 0);
       with Blend do
       begin
          BlendOp :=             AC_SRC_OVER;
          BlendFlags :=          0;
          SourceConstantAlpha := 255;
          AlphaFormat :=         AC_SRC_ALPHA;
       end;
       screenDC := GetDC(0);
     
       retour := UpdateLayeredWindow(Handle,screenDc,@TopLeft,size,fic.canvas.handle,@BmpTopLeft, 0,@blend,ULW_ALPHA);
     
    end;
    Ca marche bien, mais il faut si possible avoir une image combinant le fond et un mask...
    Par contre, j'essaie d'obtenir l'equivalent avec un PNG : j'utilise la librairie pngimage qui à l'air d'etre cool, je continue mes tests
    ;-) phenix

  11. #11
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Salut!

    Si ça peut vous être utile, j'ai les sources Delphi d'un petit utilitaire qui permet de changer la teinte d'une image PNG tout en conservant le masque alpha... Le prog décompose l'image en 2 bitmaps : Le masque alpha et l'image "opaque", change la teinte de cette dernière puis refusionne les 2 bitmaps en une seule image PNG. Voici le lien du topic:
    http://www.developpez.net/forums/viewtopic.php?t=228012

    J'en profite pour vous féliciter car je trouve que ce topic sur comment obtenir une form transparente avec une image PNG est excelent!

    Bonne continuation, à+
    De retour parmis vous après 10 ans!!

  12. #12
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Points : 37
    Points
    37
    Par défaut
    yop,

    Ah bien vu le lien

    bon, j'ai fini et ca marche très bien, en utilisant donc 3 librairies :

    - PNGimage ( PNGImage )
    - Graphics32 ( GR32,GR32_filters )
    - ton module cité : HSLUtils

    La librairie graphics32 apporte plein de bonnes choses, dont la fusion du fond et du masque : IntensityToAlpha

    Du coup, la procedure finale est donc : ( youpi )

    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
     
    procedure TForm1.Button2Click(Sender: TObject);
    var
      FinalBitmap:             TBitmap;
      size:                    PSIZE;
      TopLeft, BmpTopLeft:     TPoint;
      Blend:                   TBlendFunction;
      retour:                  boolean;
      PNG:                     TPNGObject;
      ColorBitmap,AlphaBitmap: Tbitmap32;
      screenDC:                HDC;
      i,j:                     integer;
    begin
     
       FinalBitmap := TBitmap.Create;
       PNG:=TPNGObject.Create;
       PNG.LoadFromFile('aquamala.png');
       ColorBitmap:=TBitmap32.create;
       AlphaBitmap:=TBitmap32.create;
       // 1 : colorBitmap
       ColorBitmap.Assign(PNG);
       // 2: AlphaBitmap
       AlphaBitmap.Height := PNG.Height;
       AlphaBitmap.Width  := PNG.Width;
     
        For i := 0 To PNG.Height-1 Do 
        Begin 
              For j := 0 To PNG.Width-1 Do
              Begin
                   If PNG.AlphaScanline[i][j] > 239
                      Then AlphaBitmap.Canvas.Pixels[j,i] := clWhite
                      Else AlphaBitmap.Canvas.Pixels[j,i] := HSLRangeToRGB(0,0,PNG.AlphaScanline[i][j]);
              End;
        End;
     
       // 3 : fusion
       IntensityToAlpha(ColorBitmap,AlphaBitmap);   // graphic32 librairie
       FinalBitmap.width:= PNG.Width;
       FinalBitmap.Height:= PNG.Height;
       FinalBitmap.PixelFormat := pf32Bit;
       ColorBitmap.DrawTo(FinalBitmap.Canvas.Handle, 0, 0);
     
       // liberation des objets non utiles
       AlphaBitmap.free;
       ColorBitmap.free;
       PNG.Free;
     
       // on peut passer à la fonction principale
       SetWindowLong(Handle, GWL_EXSTYLE,WS_EX_LAYERED);
     
       // ajuster la taille de la form à l'image
       width:= FinalBitmap.Width;
       height:=FinalBitmap.Height;
     
       New(size);
       size.cx := FinalBitmap.Width;
       size.cy := FinalBitmap.Height;
     
       TopLeft := BoundsRect.TopLeft;
       BmpTopLeft := Point(0, 0);
     
       with Blend do
       begin
          BlendOp :=             AC_SRC_OVER;
          BlendFlags :=          0;
          SourceConstantAlpha := 255;
          AlphaFormat :=         AC_SRC_ALPHA;
       end;
       screenDC := GetDC(0);
     
       retour := UpdateLayeredWindow(Handle,screenDc,@TopLeft,size,FinalBitmap.Canvas.handle,@BmpTopLeft, 0,@blend,ULW_ALPHA);
     
    end;
    C'est marrant et plutot sympa comme resultat, c'est clair que ca peut servir pour pas mal de choses....

    [ Ajout ]

    Pour ceux que ca interesse, voici un lien pour visualiser le resultat :

    http://www.phenix-mail.com/files/alphaform.zip

    Le zip contient l'exe et le PNG : Pour transformer la form, un clic sur le boutton, pour quitter l'appli un clic droit sur la bouteille

    C'est rigolo, a consommer ... avec moderation bien sur

    Pour le deplacement de la form, j'ai rajouté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
         if Button=mbRight
            then
         begin
              close;
              exit;
         end;
         ReleaseCapture;
         form1.Perform(WM_SYSCOMMAND, $F012, 0);
    end;
    ;-) phenix

  13. #13
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Points : 37
    Points
    37
    Par défaut
    Je rajoute le code entier ( si ca ne gene pas ) pour ceux qui voudraient compiler ca chez eux :

    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
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
     
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Menus, StdCtrls, ExtCtrls,GR32,GR32_filters,PNGImage,HSLUtils;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormMouseDown(Sender: TObject; Button: TMouseButton;
          Shift: TShiftState; X, Y: Integer);
        procedure FormCreate(Sender: TObject);
      private
     
      public
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
     
     
    {$R *.DFM}
     
    const
      WS_EX_LAYERED = $80000;
     
      AC_SRC_OVER = $0;
      AC_SRC_ALPHA = $1;
     
      LWA_COLORKEY = $1;
      LWA_ALPHA = $2;
     
      ULW_COLORKEY = $1;
      ULW_ALPHA =$2;
      ULW_OPAQUE = $4;
     
    {----------------------------------------------------------------}
    {                         Fonction                               }
    {----------------------------------------------------------------}
     
    function UpdateLayeredWindow(hwnd: HWND; hdcDst: HDC; pptDst: PPoint;
      psize: PSize; hdcSrc: HDC; pptSrc: PPoint; crKey: TColor;
      pblend: PBlendFunction; dwFlags: DWORD): BOOL; stdcall; external 'user32.dll';
     
    {----------------------------------------------------------------}
    {                          FORM1                                 }
    {----------------------------------------------------------------}
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
         doublebuffered:=true;
    end;
     
    procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
         if Button=mbRight
            then
         begin
              close;
              exit;
         end;
         ReleaseCapture;
         form1.Perform(WM_SYSCOMMAND, $F012, 0);
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      FinalBitmap:             TBitmap;
      size:                    PSIZE;
      TopLeft, BmpTopLeft:     TPoint;
      Blend:                   TBlendFunction;
      retour:                  boolean;
      PNG:                     TPNGObject;
      ColorBitmap,AlphaBitmap: Tbitmap32;
      screenDC:                HDC;
      i,j:                     integer;
    begin
     
       FinalBitmap := TBitmap.Create;
       PNG:=TPNGObject.Create;
       PNG.LoadFromFile('aquamala.png');
       ColorBitmap:=TBitmap32.create;
       AlphaBitmap:=TBitmap32.create;
       // 1 : colorBitmap
       ColorBitmap.Assign(PNG);
       // 2: AlphaBitmap
       AlphaBitmap.Height := PNG.Height;
       AlphaBitmap.Width  := PNG.Width;
     
        For i := 0 To PNG.Height-1 Do 
        Begin 
              For j := 0 To PNG.Width-1 Do
              Begin
                   If PNG.AlphaScanline[i][j] > 239
                      Then AlphaBitmap.Canvas.Pixels[j,i] := clWhite
                      Else AlphaBitmap.Canvas.Pixels[j,i] := HSLRangeToRGB(0,0,PNG.AlphaScanline[i][j]);
              End;
        End;
     
       // 3 : fusion
       IntensityToAlpha(ColorBitmap,AlphaBitmap);   // graphic32 librairie
       FinalBitmap.width:= PNG.Width;
       FinalBitmap.Height:= PNG.Height;
       FinalBitmap.PixelFormat := pf32Bit;
       ColorBitmap.DrawTo(FinalBitmap.Canvas.Handle, 0, 0);
     
       // liberation des objets non utiles
       AlphaBitmap.free;
       ColorBitmap.free;
       PNG.Free;
     
       // on peut passer à la fonction principale
       SetWindowLong(Handle, GWL_EXSTYLE,WS_EX_LAYERED);
     
       // ajuster la taille de la form à l'image
       width:= FinalBitmap.Width;
       height:=FinalBitmap.Height;
     
       New(size);
       size.cx := FinalBitmap.Width;
       size.cy := FinalBitmap.Height;
     
       TopLeft := BoundsRect.TopLeft;
       BmpTopLeft := Point(0, 0);
     
       with Blend do
       begin
          BlendOp :=             AC_SRC_OVER;
          BlendFlags :=          0;
          SourceConstantAlpha := 255;
          AlphaFormat :=         AC_SRC_ALPHA;
       end;
       screenDC := GetDC(0);
     
       retour := UpdateLayeredWindow(Handle,screenDc,@TopLeft,size,FinalBitmap.Canvas.handle,@BmpTopLeft, 0,@blend,ULW_ALPHA);
     
       // désactiver le bouton
       Button1.OnClick:=nil;
       FreeAndNil(Button1);
    end;
     
    end.
    ;-) phenix

  14. #14
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Excelent!

    Je pense que je vais proposer ce code à Nono40 pour l'ajouter dans la page Code sources Delphi.

    Beau travail d'équipe! Bonne continuation!
    à+
    De retour parmis vous après 10 ans!!

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 15
    Points : 8
    Points
    8
    Par défaut
    Merci beaucoup phenixauthor

    C'est niquel, c'est exactement ce que je cherchais. Des que j'ai le temps, je vais retravailler dessus.
    Le travail en équipe, c'est vrai que ça aide beaucoup. :p

    En tout cas encore merci.

  16. #16
    Nouveau membre du Club

    Profil pro
    Inscrit en
    Mai 2003
    Messages
    25
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 25
    Points : 37
    Points
    37
    Par défaut
    salut,

    oui, bonne demonstration d'un travail en equipe

    Deux petites precisions :

    * Ce genre de code ne marchera que sous 2000/XP...

    * Le meme programme ( celui d'origine ) compilé en c# sharp prend 8588 en memoire à l'éxecution, celui compilé en delphi 5 prend 2376 Ko....

    A bientot tout le monde et bon dev
    ;-) phenix

  17. #17
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 24
    Points : 24
    Points
    24
    Par défaut
    Hello à tous !

    Je viens de trouver cette source géniale, et j'ai réussi à la faire fonctionner (après quelques tâtonnements, je suis nouveau sur delphi (environ une semaine que je programme avec, à partir de connaissances zéro...) je n'y suis donc pas encore familier, ni à tous les appels api, etc...)

    Par contre, une fois qu'on a cette source, on a une magnifique image alpha-blendée et superbement lissée (si on a réalisé une belle image comme ça en png évidemment ) avec son arrière plan (qui est toutes les fenêtres de windows etc )

    Mais, ensuite, qu'est-ce qu'on fait de cette image ?
    J'ai essayé de charger d'autres png's par-dessus, sans succès... les images n'apparaîssement pas...

    Est-il également possible de modifier par après la transparence de toute la form (donc l'image de fond telle qu'elle est plus éventuellement d'autres composants) ?? (par exemple, pour réaliser un fade-in, fade-out de cette form)

    J'ai essayé des appels à SetLayeredWindowAttributes, ou à UpdateLayeredWindow, mais soit je n'arrive pas utiliser cette dernière, soit la première me donne un joli rectangle gris opaque en supprimant l'image qu'il y avait.

    Merci d'avance !

  18. #18
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Salut et bienvenue dans les forums de Developpez.com !

    IMPORTANT:

    • Merci de lire les règles du forum!

    • Chercher une réponse dans les FAQs
    • Chercher une réponse dans la FAQ Delphi

    • Merci de chercher un peu avant de poster dans le forum...
    • Ne poster qu'en dernier recours!
    Google.fr est ton ami!
    • Merci d'utiliser les balises CODE dans vos posts!
    Pour réaliser ces fonctions de traitement d'image PNG, il faudra modifier l'image PNG, la recharger et actualiser l'affichage. Le pixel d'une image PNG est composé de 4 octets (24bits) : 3 octets pour l'image opaque, 1 octet pour le masque alpha (transparence progressive). Tu trouveras dans les liens ci-dessous, les fonctions permettant de décomposer l'image PNG, de la travailler, et de la recomposer. Par exemple, si tu veux faire une fade-out d'une image PNG pour qu'elle disparaisse progressivement, il faudra décomposer l'image, modifier le masque alpha uniquement, refusionner ce masque, recharger l'image et réactualiser l'affichage. Je t'avertis que cela risque d'être dur à programmer mais pas impossible. La preuve: L'utilitaire Ad-aware possède un splash screen qui apparaît progressivement... Cela dit, je pense que c'est plutôt une animation et non un effet obtenu par programmation... Regarde déjà ces liens si tu trouves ce dont tu as besoin, sinon google. Bon courage, à+

    http://pngdelphi.sourceforge.net/
    http://www.developpez.net/forums/viewtopic.php?t=228012
    http://www.developpez.net/forums/viewtopic.php?t=63949

    De retour parmis vous après 10 ans!!

  19. #19
    Membre à l'essai
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 24
    Points : 24
    Points
    24
    Par défaut
    Ok, merci pour ta réponse, je vais aller voir ça de plus près !

    Mais je me demande finallement si ça vaut vraiment le coup que je m'enbête avec ça vu que mon effet de fade-in/fade out avec ma form et mes 2 images png superposées marche super, à la seule différence que les bords de l'image qui détoure ma form sont aliasés.



    exemple en images :
    L'image que j'utilise actuellement, aliasée, et qui me permets de faire mon fade-in/out de la form





    L'image que j'aurais voulu utiliser, anti-aliasée





    Actuellement, ma feuille prends toute seule la forme de l'image, j'ai utilisé les propriétés transparent=true; transparent-color=fuschia; color=fuschia; autosize=true. La dessus j'ai mis une simple TImage en autosize=true également

    ça me permets de me passer efficacement des régions
    Le seul et unique point noir étant que les bords ne soient pas lissés

    @++

  20. #20
    Expert confirmé
    Avatar de Sub0
    Homme Profil pro
    Développeur Web
    Inscrit en
    Décembre 2002
    Messages
    3 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Décembre 2002
    Messages : 3 573
    Points : 4 219
    Points
    4 219
    Par défaut
    Le masque alpha possède un octet pour l'intensité de transparence de la couleur d'un pixel.
    C'est cela qui crée l'anti-aliasing. La progressivité du masque de transparence n'est donc pas géré par ton programme. Ta transparence est tout ou rien apparemment.
    Lorsque tu affiches le masque à l'écran, tu devrais obtenir une image en niveaux de gris, et non pas en noir et blanc. Ce test permet de vérifier que l'on a bien extrait le masque alpha de l'image...
    Si l'image du masque est noir et blanc, revoir le code de récup du masque...
    à+
    De retour parmis vous après 10 ans!!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [XL-2003] Détection du déplacement d'une forme
    Par martinmacfly dans le forum Macros et VBA Excel
    Réponses: 0
    Dernier message: 18/01/2010, 10h53
  2. Déplacement d'une Form sans bordure ?
    Par arnofly dans le forum Windows Forms
    Réponses: 5
    Dernier message: 03/06/2009, 01h11
  3. form transparent en 32bits
    Par TERRIBLE dans le forum Windows Forms
    Réponses: 5
    Dernier message: 03/02/2009, 17h26
  4. empêcher le déplacement d'une Form
    Par orobin dans le forum Windows Forms
    Réponses: 3
    Dernier message: 21/12/2007, 13h33
  5. Repaint et déplacement d'une forme
    Par PadawanDuDelphi dans le forum Delphi
    Réponses: 2
    Dernier message: 04/10/2006, 11h23

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