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 :

Pourquoi TIcon.LoadFromFile produit toujours le format 16x16


Sujet :

Composants VCL Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    mars 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2010
    Messages : 237
    Points : 132
    Points
    132
    Billets dans le blog
    1
    Par défaut Pourquoi TIcon.LoadFromFile produit toujours le format 16x16
    J'utilise Delphi 6 Personal Edition.

    Je cherche à charger un fichier icône dans un objet TIcon. Lors de la création de l'objet TIcon, sa dimension est de 32x32 pixelsL
    Je veux charger un fichier icône de 32x32 pixels dans in tel objet. Le fichier charge bien et le contenu est explotable.
    Mais le format de l'icône dans l'objet TIcon est changé en 16x16 pixels.

    Voici une démo, avec un objet TOpenDialog et TButton placé sur la form:
    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
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        OpenDialog1: TOpenDialog;
        procedure FormCreate(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
      Icon: TIcon;
     
    implementation
     
    {$R *.dfm}
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      Icon := TIcon.Create;
      showmessage('Création: Icon='+inttostr(Icon.Width)+'x'+inttostr(Icon.Height));
    end;
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
      nom: string;
    begin
      OpenDialog1.Filter := 'Icônes|*.ico';
      if not OpenDialog1.Execute then exit;
      nom := OpenDialog1.FileName;
      Icon.LoadFromFile(nom);
      showmessage('Après chargement: '+inttostr(Icon.Width)+'x'+inttostr(Icon.Height));
    end;
     
    end.
    On voit clairement que le format de l'icône a changé après LoadFromFile. Pourquoi ?

    Comment puis-je faire pour préserver le format de l'icône contenue dans le fichier ?
    En extrapolant, comment pui-je faire pour charger une icône de 48x48 pixels ?

    Merci beaucoup de votre aide !

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

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juillet 2006
    Messages : 11 841
    Points : 20 660
    Points
    20 660
    Par défaut
    Ton fichier ICO doit contenir plusieurs icones de différentes tailles, celle en 16x16 et d'autres plus grandes, Windows utilisera la résolution qui convient le mieux selon où doit être affiché l'icone

    Un outil comme GIMP affichera un icone mutli-résolution comme une image avec différents calques
    le TIcon lui comme la documentation l'explique n'affichera qu'une seule icone par défaut mais tu peux l'encourager à choisir une autre icone

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var
      nom: string;
    begin
      OpenDialog1.Filter := 'Icônes|*.ico';
      if not OpenDialog1.Execute then exit;
      nom := OpenDialog1.FileName;
      Icon.Width := 64;
      Icon.Height:= 64; // SM_CXICON est à 32 chez moi, on le force à choisir plus grand que 16x16 si il ne trouve pas une 32x32, il pourra prendre la 48x48 si elle existe dans le fichier
      Icon.LoadFromFile(nom);
      showmessage('Après chargement: '+inttostr(Icon.Width)+'x'+inttostr(Icon.Height));
    end;
    Ainsi 32x32 sera le RequestedSize à la place de SM_CXICON x SM_CYICON contenant la taille par défaut d'une icone
    Entre D6 et D10, l'ordre à d'ailleurs changer, Delphi avant devait prendre la plus petite et maintenant, il aurait tendance à choisir la plus grande dans les limites de la taille exigée
    Mais attention, le fichier doit contenir une icone 32x32 si il contient une image d'une autre résolution, la plus petite approchante sera choisie à place donc la 16x16

    Remarque : TIcon peut être utilisée pour afficher la valeur d'une icône multi-résolution (>16 couleurs). Cependant, elle ne peut pas supporter la création d'icônes multi-résolutions, ni le redimensionnement de l'image après qu'elle ait été chargée à partir d'un fichier ou d'un flux.
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juillet 2006
    Messages : 11 841
    Points : 20 660
    Points
    20 660
    Par défaut
    Un sujet qui m'a diverti, en D10 ça fonctionne, je te laisse retirer tout ce qui est en trop pour D6 et trouver ce qu'il manque, je me suis inspiré du code de D7 et D10 pour ce résultat

    Nom : IconLoader.png
Affichages : 41
Taille : 56,1 Ko

    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
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    unit IconLoader_MainForm;
     
    interface
     
    uses
      (*Winapi.*)Windows, (*Winapi.*)
      (*System.*)SysUtils, (*System.*)Variants, (*System.*)Classes,
      (*Vcl.*)Graphics, (*Vcl.*)Controls, (*Vcl.*)Forms,
      (*Vcl.*)Dialogs, (*Vcl.*)StdCtrls, Vcl.ExtCtrls;
     
    type
      TIconLoaderMainForm = class(TForm)
        btnLoad: TButton;
        OpenDialogIcon: TOpenDialog;
        ImageDefault: TImage;
        ScrollBoxSubIcons: TScrollBox;
        lblImageDefaultResolution: TLabel;
        procedure btnLoadClick(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      IconLoaderMainForm: TIconLoaderMainForm;
     
    implementation
     
    uses
      (*System.*)Math,
      (*System.Generics.Collections, *)(*System.*)Contnrs;
     
    type
      TIconMulti = class(TIcon)
      private
        FIcons: TObjectList(*<TIcon>*);
        function GetIconCount(): Integer;
        function GetIcon(Index: Integer): TIcon;
      public
        constructor Create(); override;
        destructor Destroy(); override;
     
        procedure LoadFromStream(Stream: TStream); override;
     
        property IconCount: Integer read GetIconCount;
        property Icons[Index: Integer]: TIcon read GetIcon;
      end;
     
    {$R *.dfm}
     
    procedure TIconLoaderMainForm.btnLoadClick(Sender: TObject);
    var
      LIcon: TIconMulti;
      LSubIcon: TIcon;
      I, Y: Integer;
      PanelSub: TPanel;
      LabelSub: TLabel;
      ImageSub: TImage;
      DefaultRes: string;
    begin
      ImageDefault.Picture.Bitmap.Assign(nil);
      for I := ScrollBoxSubIcons.ControlCount - 1 downto 0 do
        ScrollBoxSubIcons.Controls[I].Free();
     
    //  OpenDialogIcon.FileName := 'C:\Program Files (x86)\Embarcadero\Studio\17.0\Images\Default\Default.ico';
    //  OpenDialogIcon.FileName := 'C:\Program Files (x86)\Embarcadero\Studio\17.0\bin\delphi_PROJECTICON.ico';
      if OpenDialogIcon.Execute then
      begin
        LIcon := TIconMulti.Create();
        try
          DefaultRes := Format('%d x %d', [LIcon.Width, LIcon.Height]);
     
          LIcon.LoadFromFile(OpenDialogIcon.FileName);
     
          ImageDefault.Width := LIcon.Width;
          ImageDefault.Height := LIcon.Height;
          ImageDefault.Picture.Bitmap.Assign(LIcon);
          lblImageDefaultResolution.Caption := Format('%d x %d (Expected: %s)', [LIcon.Width, LIcon.Height, DefaultRes]);
     
          Y := 0;
          for I := 0 to LIcon.IconCount - 1 do
          begin
            LSubIcon := LIcon.Icons[I];
     
            PanelSub := TPanel.Create(Self);
            LabelSub := TLabel.Create(Self);
            ImageSub := TImage.Create(Self);
     
            ImageSub.Width := LSubIcon.Width;
            ImageSub.Height := LSubIcon.Height;
            ImageSub.Picture.Bitmap.Assign(LSubIcon);
     
            LabelSub.Caption := Format('%d x %d', [LSubIcon.Width, LSubIcon.Height]);
     
            PanelSub.Parent := ScrollBoxSubIcons;
            LabelSub.Parent := PanelSub;
            LabelSub.Align := alTop;
            ImageSub.Parent := PanelSub;
            ImageSub.Align := alClient;
     
            PanelSub.ClientHeight := LSubIcon.Height + LabelSub.Height + 8;
            PanelSub.ClientWidth := Max(LSubIcon.Width, LabelSub.Canvas.TextWidth(LabelSub.Caption)) + 8;
            PanelSub.Left := 4;
            PanelSub.Top := Y;
            Inc(Y, PanelSub.Height);
          end;
        finally
          LIcon.Free();
        end;
      end;
    end;
     
     
    { TIconMulti }
     
    constructor TIconMulti.Create();
    begin
      inherited Create();
     
      FIcons := TObjectList(*<TIcon>*).Create(True);
    end;
     
    destructor TIconMulti.Destroy();
    begin
      FreeAndNil(FIcons);
     
      inherited Destroy();
    end;
     
    function TIconMulti.GetIcon(Index: Integer): TIcon;
    begin
      Result := FIcons[Index] as TIcon;
    end;
     
    function TIconMulti.GetIconCount(): Integer;
    begin
      Result := FIcons.Count;
    end;
     
    procedure TIconMulti.LoadFromStream(Stream: TStream);
    type
      PIconRecArray = ^TIconRecArray;
      TIconRecArray = array[0..300] of TIconRec;
    var
      CI: TCursorOrIcon;
      I: Integer;
      HeaderLen: Integer;
      ListIcon: PIconRecArray;
      SubIcon: TIcon;
    begin
      FIcons.Clear();
     
      inherited LoadFromStream(Stream);
     
      Stream.Seek(0, soBeginning); // ou soFromBeginning en D6
      Stream.ReadBuffer(CI, SizeOf(CI));
     
      if CI.wType = RC3_ICON then
      begin
        HeaderLen := SizeOf(TIconRec) * CI.Count;
        ListIcon := AllocMem(HeaderLen);
        try
          Stream.Read(ListIcon^, HeaderLen);
          for I := 0 to CI.Count - 1 do
          begin
            SubIcon := TIcon.Create();
            try
              SubIcon.Width := ListIcon^[I].Width;
              SubIcon.Height := ListIcon^[I].Height;
              Stream.Seek(0, soBeginning); // ou soFromBeginning en D6
              SubIcon.LoadFromStream(Stream);
              FIcons.Add(SubIcon);
            except
              SubIcon.Free();
              raise;
            end;
          end;
        finally
          FreeMem(ListIcon, HeaderLen);
        end;
      end;
    end;
     
    end.
    Code DFM : 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
     
    object IconLoaderMainForm: TIconLoaderMainForm
      Left = 0
      Top = 0
      Caption = 'Icon Loader'
      ClientHeight = 299
      ClientWidth = 635
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      DesignSize = (
        635
        299)
      PixelsPerInch = 96
      TextHeight = 13
      object ImageDefault: TImage
        Left = 8
        Top = 39
        Width = 105
        Height = 105
      end
      object lblImageDefaultResolution: TLabel
        Left = 8
        Top = 159
        Width = 105
        Height = 43
        AutoSize = False
        Caption = 'Resolution ?'
        WordWrap = True
      end
      object btnLoad: TButton
        Left = 8
        Top = 8
        Width = 75
        Height = 25
        Caption = 'Load'
        TabOrder = 0
        OnClick = btnLoadClick
      end
      object ScrollBoxSubIcons: TScrollBox
        Left = 119
        Top = 8
        Width = 508
        Height = 283
        Anchors = [akLeft, akTop, akRight, akBottom]
        TabOrder = 1
      end
      object OpenDialogIcon: TOpenDialog
        Filter = 'Ic'#244'nes|*.ico'
        Left = 305
        Top = 88
      end
    end
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    mars 2010
    Messages
    237
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Informaticien retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : mars 2010
    Messages : 237
    Points : 132
    Points
    132
    Billets dans le blog
    1
    Par défaut
    Merci, ShaiLeTroll !

    J'ai installé GIMP et j'ai bien vu que dans mon icône, il y avait 3 calques: 16x16, 32x32 et 48x48.
    J'ai supprimé les deux calques non souhaités, et mon TIcon charge bien la bonne image.

    Problème résolu. Merci beaucoup !

    EDIT

    Je viens de voir ta publication ci-dessus. Super ! Je vais regarder cela de près !

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

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : juillet 2006
    Messages : 11 841
    Points : 20 660
    Points
    20 660
    Par défaut
    Correction à faire en D7
    Vcl.ExtCtrls devient (*Vcl.*)ExtCtrls,
    ImageDefault.Picture.Bitmap.Assign(LIcon); devient TIconMulti.DrawTo(ImageDefault.Picture.Bitmap, LIcon);,
    ImageSub.Picture.Bitmap.Assign(LSubIcon); devient TIconMulti.DrawTo(ImageSub.Picture.Bitmap, LSubIcon);,

    et il faut donc une nouvelle fonction DrawTo inspiré de Draw

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class procedure TIconMulti.DrawTo(Bitmap: TBitmap; Source: TIcon);
    begin
      if Source.Handle <> 0 then
      begin
        Bitmap.Width := Source.Width; // Width et Height ne sont valide que si l'on récupère le Handle avant !
        Bitmap.Height := Source.Height;
        Bitmap.PixelFormat := pf32bit;
        DrawIconEx(Bitmap.Canvas.Handle, 0,0, Source.Handle, Source.Width, Source.Height, 0,0, DI_NORMAL);
      end;
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

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

Discussions similaires

  1. Réponses: 58
    Dernier message: 12/06/2015, 23h32
  2. Réponses: 1
    Dernier message: 01/05/2013, 22h27
  3. Pourquoi ma division renvoi toujours 0?
    Par miniil dans le forum Langage
    Réponses: 4
    Dernier message: 31/01/2010, 23h53
  4. Réponses: 2
    Dernier message: 16/04/2005, 21h24

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