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 :

Problème avec composant PicButton en création dynamique


Sujet :

Composants VCL Delphi

  1. #1
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut Problème avec composant PicButton en création dynamique
    Je suis sous W8.1 Personal Edition, avec Delphi 6 Personal Edition.

    Je voulais créer un bouton descendant de TButton, avec une image BMP sur laquelle je veux écrire le libellé. J'ai bien essayé TSpeedButton et TBitBtn, mais pour différentes raisons cela ne correspond pas.

    En cherchant sur internet, j'ai trouvé une unité PicButton qui fait exactement ce que je veux. Certes, j'au trouvé l'unité "nue", juste une page de texte, à copier dans un fichier PAS. C'est ce que j'ai fait. Je l'ai installé comme composant, ce qui n'a posé aucun problème. Le composant est reconnu dans l'IDE, je peux le placer sur une form, le configurer et l'utiliser. J'ai eu deux petits ennuis avec des bugs dans l'unité, mais je les au trouvés et corrigés, en les marquant avec un commentaire.

    Mais, j'ai un vrai problème lorsque j'essaie d'utiliser ce bouton en création dynamique. Le bouton apparaît bien dans ma form, je peux configurer certains paramètres, y compris l'évènement OnClick - ça marche. Mais les images n'apparaissent pas ! Je les charge dans un BitMap créé dynamiquement, puis j'affecte le BitMap aux propriétés Pic... (normal, pushed et hilight) pour avoir l'image comme bouton "sorti", bouton "avancé" et "en survol"). Mais rien n'apparaît, dans aucun de ces 3 états.

    J'ai fait un petit programme de démo, avec un PicButton créé dans l'IDE, et un autre créé dynamiquement en cliquant sur un bouton normal. Le projet est en pièce jointe, sous forme de fichier ZIP. Il contient le composant comme PicButton.pas. A tout hasard, voici cette unité:
    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
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    unit PicButton;
     
    interface
    uses
      Windows, Messages, Classes, Graphics, Controls, stdCtrls, Dialogs, SysUtils;
     
     
    type
    TPicButton = class(TButton)
        private
        FOver, FDoRect, FDoText: Boolean;
        FFocusColor: TColor;
        FNormalPic, FHiLightPic, FDownPic, FDisabledPic, FFocusPic: TBitmap;
        procedure setNormal(Value: TBitMap);
        procedure setHiLight(Value: TBitMap);
        procedure setDown(Value: TBitMap);
        procedure setDisabled(Value: TBitmap);
        procedure setFocusPic(Value: TBitMap);
        procedure DrawItem(const DIRec: TDrawItemStruct);
        procedure CNMeasureItem(var Message: TWMMeasureItem); message CN_MEASUREITEM;
        procedure CNDrawItem(var Message: TWMDrawItem); message CN_DRAWITEM;
        procedure CMFontChanged(var Message: TMessage); message CM_FONTCHANGED;
        procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED;
        procedure CMEnabledChanged(var Message: TMessage); message CM_ENABLEDCHANGED;
     
        protected
        property Brush;
        property Default;
        property Action;
        procedure SetButtonStyle(ADefault: Boolean); overRide;
        procedure WMPaint(var Message: TMessage); message WM_PAINT;
        procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
        procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
     
        public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure Loaded; override;
     
        published
        { Published declarations }
        property PicNormal: TBitMap read FNormalPic write setNormal;
        property PicHiLight: TBitMap read FHiLightPic write setHiLight;
        property PicPushed: TBitMap read FDownPic write setDown;
        property PicDisabled: TBitmap read FDisabledPic write setDisabled;
        property PicFocus: TBitmap read FFocusPic write setFocusPic;
        property FocusColor: TColor read FFocusColor write FFocusColor default clRed;
        property DoFocusText: Boolean read FDoText write FDoText default False;
        property DoFocusRect: Boolean read FDoRect write FDoRect default False;
        property Caption;
        property Enabled;
        property ParentShowHint;
        property ParentBiDiMode;
        property ShowHint;
        property TabOrder;
        property TabStop;
        property Visible;
        property OnEnter;
        property OnExit;
     
    end;
     
    procedure Register;
     
    implementation
     
    type
      TMyState = (bsUp, bsDown, bsHigh, bsDisabled);
     
    procedure Register;
    begin
      RegisterComponents('DelphiFr', [TPicButton]);
    end;
     
    constructor TPicButton.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      ControlStyle:= ControlStyle - [csSetCaption, csOpaque];
      FOver := False;
      FNormalPic  := TBitMap.Create;
      FHiLightPic := TBitmap.Create;
      FDownPic  := TBitmap.Create;
      FDisabledPic := TBitmap.Create;
      FFocusPic := TBitmap.Create;
      FDoText := False;
      FDoRect := False;
      FFocusColor := clRed;
      Constraints.MaxHeight := Height;
      Constraints.MinHeight := 0; // Height;
      Constraints.MaxWidth := Width;
      Constraints.MinWidth := Width;     // Klaus Constraints.MinHeight corrected by Constraints.MinWidth
    end;
     
    destructor TPicButton.Destroy;
    begin
      inherited Destroy;
      FNormalPic.Free;
      FHiLightPic.Free;
      FDownPic.Free;
      FDisabledPic.Free;
      FFocusPic.Free;
    end;
     
    procedure TPicButton.Loaded;
    begin
      inherited Loaded;
      if FNormalPic.Empty then Exit;
      Constraints.MaxHeight := FNormalPic.Height;
      Constraints.MinHeight := 0; // FNormalPic.Height;
      Constraints.MaxWidth := FNormalPic.Width;
      Constraints.MinWidth := FNormalPic.Width;    // Klaus  Constraints.MinHeight corrected by Constraints.MinWidth
      Width := FNormalPic.Width;
      Height := FNormalPic.Height;
    end;
     
    procedure TPicButton.SetButtonStyle(ADefault: Boolean);
    begin
      if HandleAllocated then
        SendMessage(Handle, BM_SETSTYLE, BS_PUSHBUTTON or BS_OWNERDRAW, 1);
    end;
     
    procedure TPicButton.setNormal(Value: TBitMap);
    begin
      FNormalPic.Assign(Value);
      if not FNormalPic.Empty then
        begin
          Constraints.MaxHeight := FNormalPic.Height;
          Constraints.MinHeight := 0; // FNormalPic.Height;
          Constraints.MaxWidth := FNormalPic.Width;
          Constraints.MinWidth := FNormalPic.Width;      // Klaus  Constraints.MinHeigt corrected by Constraints.MinWidth
          Height := FNormalPic.Height;
          Width := FNormalPic.Width;
        end;
      Invalidate;
    end;
     
    procedure TPicButton.setHiLight(Value: TBitMap);
    begin
      FHiLightPic.Assign(Value);
    end;
     
    procedure TPicButton.setDown(Value: TBitMap);
    begin
      FDownPic.Assign(Value);
    end;
     
    procedure TPicButton.setDisabled(Value: TBitMap);
    begin
      FDisabledPic.Assign(Value);
    end;
     
    procedure TPicButton.setFocusPic(Value: TBitMap);
    begin
      FFocusPic.Assign(Value);
    end;
     
    procedure TPicButton.CNMeasureItem(var Message: TWMMeasureItem);
    begin
      Message.MeasureItemStruct^.itemWidth := Width;
      Message.MeasureItemStruct^.itemHeight := Height;
    end;
     
    procedure TPicButton.CNDrawItem(var Message: TWMDrawItem);
    begin
      DrawItem(Message.DrawItemStruct^);
    end;
     
    procedure TPicButton.CMTextChanged(var Message: TMessage);
    begin
      Invalidate;
    end;
     
    procedure TPicButton.CMMouseLeave(var Message: TMessage);
    begin
      FOver := False;
      if Enabled and Assigned(FHiLightPic) then
        Invalidate;
    end;
     
    procedure TPicButton.CMMouseEnter(var Message: TMessage);
    begin
      FOver := True;
      if Enabled and Assigned(FHiLightPic) then
        Invalidate;
    end;
     
    procedure TPicButton.CMFontChanged(var Message: TMessage);
    begin
      inherited;
      Invalidate;
    end;
     
    procedure TPicButton.CMEnabledChanged(var Message: TMessage);
    begin
      inherited;
      Invalidate;
    end;
     
    procedure TPicButton.WMPaint(var Message: TMessage);
    var
      BmpDC: Integer;
      PaintS: TPaintStruct;
      cRect: TRect;
      PenO: Cardinal;
    begin
      if not (csDesigning in ComponentState) then
        begin
          Inherited;
          Exit;
        end;
     
      Message.Result := 0;
      BeginPaint(Handle, PaintS);
      if FNormalPic.Empty then
        begin
          PenO := SelectObject(PaintS.hDC, CreatePen(PS_SOLID, 1, $999999));
          SetROP2(PaintS.hdc, R2_XORPEN);
          Rectangle(PaintS.hdc, 0, 0, Width, Height);
          DeleteObject(SelectObject(PaintS.hdc, PenO));
          EndPaint(Handle,PaintS);
          Exit;         // deactivated by Klaus
        end;
     
      BmpDC := CreateCompatibleDC(0);
      SelectObject(BmpDC, FNormalPic.Handle);
      BitBlt(PaintS.hdc, PaintS.rcPaint.Left, PaintS.rcPaint.Top,
               PaintS.rcPaint.Right, PaintS.rcPaint.Bottom, BmpDC,
               PaintS.rcPaint.Left, PaintS.rcPaint.Top, SRCCOPY);
      DeleteDC(BmpDC);
     
      if Length(Caption) > 0 then
        begin
          cRect := ClientRect;
     
          SelectObject(PaintS.hdc, Font.Handle);
          SetBkMode(PaintS.hdc, TRANSPARENT);
          DrawText(PaintS.hdc,PChar(Caption),-1,cRect,DT_SINGLELINE or DT_VCENTER or DT_CENTER);
        end;
      EndPaint(Handle,PaintS);
    end;
     
    procedure TPicButton.DrawItem(const DIRec: TDrawItemStruct);
    var
      Pic: TBitmap;
      IsFocus: Boolean;
      State: TMyState;
      cRect: TRect;
    begin
      if (csDesigning in ComponentState) then Exit;
     
      cRect := ClientRect;
      {I assign a State to get the correct Image}
      if not Enabled then State := bsDisabled else
      if DIRec.itemState and ODS_SELECTED <> 0 then
        State := bsDown else
      if FOver then
        State := bsHigh else
        State := bsUp;
     
      IsFocus := DIRec.itemState and ODS_FOCUS <> 0;
     
      Pic := FNormalPic;                     // added by Klaus
      SetTextColor(DIRec.hdc, Font.Color);   // added by Klaus
      case State of
      {set the Pic and cRect}
        bsUp: if IsFocus then
            if not FFocusPic.Empty then Pic := FFocusPic;
        bsDown: begin
              if not FDownPic.Empty then
                Pic := FDownPic else
                if not FHiLightPic.Empty then Pic := FHiLightPic;
              cRect := Rect(2,2,Width+2,Height+2)
              end;
        bsHigh: if not FHiLightPic.Empty then Pic := FHiLightPic;
        bsDisabled: begin
                  if not FDisabledPic.Empty then Pic := FDisabledPic;
                  SetTextColor(DIRec.hdc, clSilver);
                  end;
      end;
     
      if not Pic.Empty then
        BitBlt(DIRec.hDC, 0, 0, Width, Height, Pic.Canvas.Handle, 0, 0, SRCCOPY);
     
      if IsFocus and FDoText then
        SetTextColor(DIRec.hdc, FFocusColor);
     
      SelectObject(DIRec.hDC, Font.Handle);
      SetBkMode(DiRec.hdc, TRANSPARENT);
      if Length(Caption) > 0 then
        DrawText(DIRec.hDC,PChar(Caption),-1,cRect,DT_SINGLELINE or DT_VCENTER or DT_CENTER);
     
      if IsFocus and FDoRect then
        begin
          InflateRect(cRect, -3, -3);
          windows.DrawFocusRect(DIRec.hdc, cRect);
        end;
    end;
     
    end.
    Le problème vient, soit d'un bug dans l'unité PicButton.bas, soit d'une incompréhension de ma part. Je serais très heureux si vous pouviez jeter un regard sur ce problème. Merci d'avance.

    Cordialement
    Klaus
    Fichiers attachés Fichiers attachés

  2. #2
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    Je vais approfondir ma question.

    J'ai découvert un autre problème, lié à ma création dynamique. J'étudie 2 cas:
    1. création dynamique dans le programme lui-même. Résultat: les bitmaps ne s'affichent pas, mais le bouton réagit normalement, aussi bien par un clic gauche sur le bouton qu'en forçant l'appel de la routine Onclick par la méthode Click.
    2. création dynamique dans une fonction placée dans une DLL. Résultat: les bitmaps ne s'affichent pas, et le bouton ne réagit pas à un clic gauche sur le bouton, mais en forçant l'appel de la routine Onclick par la méthode Click, ça marche.

    C'est tout de même un comble pour un objet qui se dit PicButton: en création dynamique, il n'affiche pas les bitmaps et ne réagit pas aux clics si la création a lieu dans une DLL ! Alors qu'en création par l'IDE (design time), tout fonctionne bien !

    J'ai étendu mon programme de démo de mon post précédent.

    Le programme de démo affiche 3 parties:
    1. en haut à gauche, un PicButton créé par l'IDE (fonctionne normalement)
    2. en-dessous à gauche: 3 boutons standards pour créer un PicButton dynamiquement dans le code de l'unité Form1, pour le supprimer et pour simuler l'évènement Onclick. Ces 3 boutons produisent le résultat escompté, mais le PicButton créé n'affiche pas les bitmaps. Cependant, il réagit correctement sur un clic gauche.
    3. à droite, la même série de boutons pour une création d'un bouton PicButton par une DLL. Au-dessus, il y a une ComboBox permettant de choisir la méthode de définition de la routine évènement Onclick. 3 choix sont possibles:
    - (pas de Onclick) = choix par défaut - le bouton de réagit pas.
    - Onclick par la méthode des "class procedure" - le bouton réagit à la simulation du clic, mais pas au clic réel
    - Onclick par la méthode des "TMethodPointer"- le bouton réagit à la simulation du clic, mais pas au clic réel

    Dans le ZIP fourni en pièce jounte, deux projets Delphi 6 Personal Edition sont fournis:
    - PicButtonProblem.dpr = projet pour la construction du programme de démo
    - PicButtonByDLL.dpr = projet de la petite DLL contenant les 3 fonctions utilisées

    La dll est chargée lors de la création de Form1, par LoadLibrary, et les adresses des 3 routines utilisées sont mémorisées dans des variables spécifiques. La DLL reste chargée pendant toute l'exécution du programme.

    Je n'ai pas réussi à comprendre ce qui se passe. Deux questions précises se posent:
    1. pourquoi les bitmaps ne s'affichent pas lorsque le PicButton est créé dynamiquement ?
    2. pourquoi, si le PicButton est créé dynamiquement dans une DLL, la routine évènement Onclick n'est pas exécutée par un clic gauche physique, alors qu'elle s'exécute bien par la métode Click ?


    Je vous serais sincèrement reconnaissant de m'aider à trouver une solution.
    Cordialement
    Klaus

    EDIT

    Je précise que le problème, avec certitude, vient du source du composant PicButton qui se trouve dans PicButton.pas. J'utilise ces techniques de création dynamique d'objets dans une DLL, depuis longtemps, avec divers objets, et cela fonctionne partout pour les évènement Onclick, que ce soit par la méthode des "class procedure" ou par la méthode des "TMethodPointer".
    Fichiers attachés Fichiers attachés

  3. #3
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    Ce n'est évidemment pas vital, mais j'aimerais vraiment avoir une réponse à ma question, détaillée et précisée dans le post précédent. J'ai mis en pièce jointe un ZIP contenant toutes les sources et les binaires. Je rappelle qu'il s'agit de Delphi 6 Personal Edition.

    Il y a forcément un bug dans le composant PicButton.pas que j'ai trouvé sur le net. J'y ai déjà apporté une petite modif mineure qui est marquée d'un commentaire. Cependant, je reste bloqué sur les deux questions du post précédent. je vous serais reconnaissant de jeter un oeil sur ce problème.

  4. #4
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Bonsoir,

    J'ai testé ton premier zip (affichage des bitmaps).

    Dans TForm1.Button1Click : il ne faut pas utiliser ParentWindow, mais simplement PicButtonDynamique.Parent:= Form1.
    Mais cela ne marche pas du premier coup, il faut faire un premier MouseDown avant !!! histoire de lui attribuer le focus.
    Il faudrait vraiment retravailler le code du composant pcq... hmmm, j'ai déjà vu mieux !!! Un message WMPaint qui, en mode runtime, fait un inherited suivi d'un exit... bizarre, vous avez dit bizarre...

    Cordialement
    Thierry

  5. #5
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    Merci, ThWilliam !

    C'est rassurant de recevoir un coup de main. J'ai essayé ce que tu suggères. Voici la routine TForm1.Button1Click:
    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
    procedure TForm1.Button1Click(Sender: TObject);
    var
      bm: TBitMap;
    begin
      if assigned(PicButtonDynamique) then begin
        ShowMessage('Le bouton est déjà créé !');
        exit;
      end;
      try
        PicButtonDynamique := TPicButton.Create(self);
    //    PicButtonDynamique.ParentWindow := Form1.Handle;
        PicButtonDynamique.Parent := Form1;
        PicButtonDynamique.Top := Button1.Top+100;
        PicButtonDynamique.Left := PicButton1.Left;
        PicButtonDynamique.OnClick := PicButtonDynamiqueClick;
     
        bm := TBitMap.Create;
        bm.LoadFromFile('Boutons2.bmp');
        PicButtonDynamique.PicNormal := bm;
        bm.LoadFromFile('Boutons2Down.bmp');
        PicButtonDynamique.PicPushed := bm;
        bm.LoadFromFile('Boutons2Hover.bmp');
        PicButtonDynamique.PicHiLight := bm;
        bm.Free;
        PicButtonDynamique.SetFocus;          // <========== pour afficher l'image !
      except
        ShowMessage('Oups... Erreur en création.');
      end;
    end;
    Puisque tu me dis que c'est une histoire de focus initial, j'ai donc ajouté la commande PicButtonDynamique.SetFocus; à la fin du traitement, et le problème d'affichage pour le bouton créé dynamiquement dans UNIT1 elle-même fonctionne bien maintenant, tant pour l'affichage des images que pour la réaction aux clics. Parfait.

    Ceci dit, cela indique tout de même qu'il y a un bug dans le composant. Et ce bug devient alors bloquant lorsque j'essaie de faire la création dans ma DLL. Car, dans ce cas, je ne peux pas utiliser la propriété PARENT - je ne dispose que de PARENTWINDOW. J'utilise cette technique souvent, avec plein d'objets différents que je veux créer dans ma DLL et injecter dans une fenêtre dont je ne connais que le handle. Et ça marche sans problème. Si ça ne marche pas avec PicButton.pas, c'est que PicButton.pas a un problème. Mais là, c'est malheureusement au-delà de mes compétences.

    Je joins un nouveau fichier ZIP qui intègre la modification qui a débloqué la création dynamique à partir de UNIT1 du programme principal. J'ai ajouté la ligne SetFocus dans la DLL aussi, mais les images n'apparaissent pas, certainement parce que je ne peux pas utiliser la propriété Parent comme dans l'autre cas. Et le clic sur le bouton ne réagit pas, alors que le clic par simulation (méthode Click) fonctionne.

    Certes, il faut plonger dans PicButton.pas. Est-ce que tu aurais une idée pour ces deux problèmes (nécessité d'utiliser Parent au lieu de ParentWindow, et la non-réaction sur un clic physique) ? Ou peut-être un autre spécialiste des composants ? En tout cas, un grand MERCI pour ton aide qui a ouvert la voie et indiqué le chemin à suivre !
    Fichiers attachés Fichiers attachés

  6. #6
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Bonjour,

    Je suis loin d'être un spécialiste en DLL (très loin ), mais je crois que PARENT est autorisé.
    Voir ceci : http://www.swissdelphicenter.ch/torr...de.php?id=2294

    Meilleurs voeux de nouvelle année.

    Cordialement
    Thierry

  7. #7
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    C'est vrai s'il s'agit d'un programme principal en Delphi qui appelle une fonction ou procédure dans une DLL, en lui passant l'objet parent (ici Form1) en paramètre.

    Malheureusement, je ne dispose que du handle (Form1.handle) qui est passé en paramètre à ma fonction. Certes, mon programme principal EST en Delphi, mais c'est juste pour mettre le problème en évidence. Dans mon application réelle, le programme principal est écrit dans un autre langage, et ce programme ne peut que passer le handle, pas l'objet.

    Ce qui est étrange, c'est que ce mécanisme marche avec d'autres objets (TWebBrowser, TButton, TRichEdit, TMaskEdit etc. Tous peuvent être injectés dans la form (ou le panel etc) dont je reçois le handle en paramètre. J'utilise une TFormBidon invisible, créée dans la DLL, comme Owner, et je spécifie ParentWindow pour faire apparaître l'objet dans la destination voulue. Mais ça ne marche pas pour PicButton. Il y a donc forcément un problème dans la construction de PicButton, mais je n'ai pas réussi à le localiser.

    Heureuse Bonne Année 2015 à toi et les tiens
    Klaus

  8. #8
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Avec ceci, Parentwindow marche.

    PicButton.zip

    Testé en mode création dynamique. Pour le design time, il faudra adapter.

    Bon réveillon.

    Thierry

  9. #9
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    Merci de ton aide, Thierry. J'ai téléchargé, mais je testerai l'année prochaine
    Et maintenant, on se prépare pour le réveillon en famille. Bonne année à toi, et à tous les membres de ce forum fantastique !

  10. #10
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    Bon, après ces moments de détente en famille, je reviens à la charge. J'ai utilise le module PicButton.pas que tu as posté, à la place du mien. Et, même e, création du bouton par l'IDE, il n'y avait plus aucune bitmap affichée - seulement le dessin du bouton normal. Egalement en création dynamique. J'ai donc comparé les deux sources et j'ai trouvé que tu as désactive la procédure SetButtonStyle(ADefault: Boolean); overRide; , bloquant ainsi le dessin du bouton à partir des bitmaps installées. J'ai réactive cette procédure, et le bouton s'affiche à nouveau normalement en création par l'IDE.

    Mais maintenant, il s'affiche également normalement en création dynamique dans le module UNIT1 du programme principal, et l'évènement OnClick se déclenche bien (ce qui était déjà le cas avant). Et je l'ai fait avec la propriété ParentHandle au lieu de Parent, et ça marche bien ainsi. Bravo !

    Par contre, ça ne marche toujours pas à partir d'une DLL. Le bouton créé dans la DLL s'affiche bien dans la page, mais sans les bitmaps, et l'évènement OnClick ne se déclenche pas. Cependant, les routines évènement sont bien installées, car un clic sur le bouton "Simulation" déclenche bien m'évènement (par la méthode Click).

    Donc, Oui, il y a du mieux, mais non, mon problème global n'est pas encore résolu. Je remets un ZIP en pièce jointe. Il suffit de lancer PicButtonProblem.exe pour le vérifier:
    1. le bouton créé par l'IDE en haut à gauche fonctionne bien
    2. le bouton créé en bas à gauche fonctionne bien. Il est créé en cliquant sur le bouton "Créer PicButton dynamique". Bravo.
    3. le bouton créé en bas à droite ne montre pas les bitmaps et le réagis pas aux clics. Ce bouton est créé par un clic sur le bouton "Créer PicButton par DLL".

    Je vais continuer à chercher, mais je suis sûr ce ce problème est encore à chercher dans PicButton.pas...

    Cordialement
    Klaus
    Fichiers attachés Fichiers attachés

  11. #11
    Membre chevronné

    Homme Profil pro
    au repos
    Inscrit en
    Février 2014
    Messages
    429
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations professionnelles :
    Activité : au repos

    Informations forums :
    Inscription : Février 2014
    Messages : 429
    Points : 1 884
    Points
    1 884
    Par défaut
    Bonsoir Klaus,

    En ce qui concerne la création dans l'IDE, c'est normal que l'affichage des bitmaps ne marche pas, dans mon message, je précisais qu'il fallait adapter.
    En fait, dans le code, j'ai enlevé tout ce qui pouvait poser problème (dont l'implémentation du WMPaint utilisé en designtime), j'ai ajouté la création de FCanvas et la procedure CreateParams. En création dynamique, cela fonctionne sans la procédure SetButtonStyle. Testé sous D7.
    Pour le problème avec la dll, là je jette l'éponge...

    Cordialement
    Thierry

  12. #12
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    Je te suis reconnaissant de ton aide, Thierry. En fait,tu as débloqué le problème d'affichage des images en création dynamique à partir de Unit1- j'avais juste à réactiver la procédure SetButtonStyle. Maintenant, en création dynamique à partir de Unit1, tout fonctionne parfaitement, ce qui n'était pas le cas avant.

    Mais effectivement, ce qu'il me faut réellement, c'est la création à partir d'une DLL. C'est par là que j'avais commencé, et lorsque j'ai constaté le problème, j'ai recopié le code des fonctions de la DLL dans Unit1 pour faire une création dynamique sans passer par la DLL. Et ça ne marchait pas non plus. Et donc, tu as résolu ce problème, en particulier en rendant possible la création dynamique dans Unit1. Parfait.

    Mais même ainsi, ça ne marche pas à partir de la DLL. Et n'oublie pas: je suis sous DELPHI V6 Personal Edition, pas DELPHI V7 (que je ne connais pas). Il y a peut-être une différence à ce niveau-là.

    Donc, un a fait un pas en avant, et c'est bien. Et j'aimerais bien qu'un spécialiste des composants pour DELPHI V6 m'aide à résoudre ce problème. Mon post précédent contient un ZIP contenant 2 projets Delphi V6: PicButtonByDll.dpr est le projet pour la DLL, et PicButtonProblem.dpr est le projet du programme de démo. Toutes les sources sont dans ce ZIP, ainsi que les images (très simples) et les binaires. On peut donc, après décompression, faire marcher directement PicButtonProblem.exe pour visualiser le problème - le mode d'emploi est dans mon post précédent.

  13. #13
    Membre habitué

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    294
    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 : 294
    Points : 171
    Points
    171
    Billets dans le blog
    1
    Par défaut
    HEUREKA !!!!!!

    J'ai fini par trouver. C'est encore et toujours le problème de contrôles parentés qui m'a piégé. Je croyais pouvoir changer simplement la propriété ParentHandle, mais ça ne marche pas à partir d'une DLL. Ne ne sais pas pourquoi, mais c'est ainsi. Je ne peux pas non plus remplacer ma méthode Create par CreateParented (dans laquelle un spécifie le handle du parent souhaité). Sûrement pour la même raison.

    Alors, j'ai suivi une autre piste. J'ai créé un TPanel, dans lequel j'ai injecté mon PicButton. Je crée le Picbutton avec ce TPanel comme owner, et je mets ce TPanel comme parent et son handle comme parenthandle. Et pour finir, j'injecte le TPanel dans la form via sa propriété parenthandle. Et ça marche. Les images apparaissent, et le bouton réagit au clic.

    Seul problème: la taille du panel. Je l'ajuste après la création du PicButton pour épouser exactement la taille de ce dernier. Et c'est presque fini. Il reste un détail à régler. En effet, dans mon application réelle, je donne une forme de rectangle au coins arrondis à mon bouton, comme le montre l'image affichée dansla form. Or, aussi bien PicButton que Panel sont rectangulaires. Dans mon application réelle, j'utilise les API de gestion des régions Windows pour "tailler" les coins en arrondi, selon le rayon désiré. Pour un bouton seul, pas de problème. Mais dans ce cas, le panel réapparaît en-dessous (au moins les parties qui ne sont plus couvertes par les coins arrondis). J'ai donc créé un dérivé de TPanel en le rendant transparent, et le tout est joué (j'ai trouvé ce composant sur le net - auteur Timo Lappalainen, Instrumentarium Imaging). Pour ceux qui s'y intéressent, vous trouverez les projets complets (DLL et programme de démo), sources et binaires, dans le fichier ZIP en pièce jointe.

    Je remercie tous ceux qui ont consenti à se pencher sur mon problème, et tout particulièrement ThWilliam !
    Fichiers attachés Fichiers attachés

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

Discussions similaires

  1. Problème avec Excel et tableau croisé dynamique
    Par françois62 dans le forum VBScript
    Réponses: 9
    Dernier message: 19/11/2006, 22h17
  2. Problème avec la "Gestion des bibliothèques dynamiques"
    Par GoustiFruit dans le forum Delphi
    Réponses: 15
    Dernier message: 31/05/2006, 09h54
  3. Réponses: 21
    Dernier message: 09/04/2006, 23h13
  4. [VBA] Problème avec composant VB6
    Par Diablo_22 dans le forum Général VBA
    Réponses: 8
    Dernier message: 16/03/2006, 20h41
  5. Problème avec PtInRegion et un tableau dynamique
    Par mduse dans le forum Langage
    Réponses: 2
    Dernier message: 06/12/2005, 09h29

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