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 TButton en injection dans une cellule d'un TStringGrid


Sujet :

Composants VCL Delphi

  1. #1
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut Problème avec TButton en injection dans une cellule d'un TStringGrid
    Bonjour,

    Je suis sous W11 avec Delphi 6 Personal Edition.

    Je suis en train d'injecter (ou d'essayer...) des contrôles dans des cellules d'un contrôle dérivé d'un TStringGrid.

    J'ai essayé TButton. Ca marche, le bouton apparaît et il est cliquable.
    Mais le clic ne déclenche pas l'évènement OnClick du bouton injecté.
    Par contre, appeler programmatiquement la méthode Click du TButton déclenche bien sa routine OnClick.

    Pui, j'ai essayé TSpeedButton à la place.
    Là encore, le bouton apparaît bien et est cliquable.
    Mais cette fois, le clic déclenche bien l'évènement OnClick du bouton injecté.

    Conclusion: si je veux un bouton dans un TStringGrid, il faut utiliser TSpeedButton.

    Mais pourquoi ? Qu'est-ce qui fait que TSpeedButton fonctionne et pas TButton, en injection dans une cellule d'un TStringGrid ?

    Je joins une capture d'écran après le clic sur un des 6 TSpeedButton injectés - la routine évènement OnClick affiche les coordonnées de la cellule cliquée:
    Nom : Capture d'écran 2025-11-18 152123.png
Affichages : 200
Taille : 28,8 Ko

    D'ailleurs, après un clic sur le bouton dans la cellule ligne 3 colonne 2, un peut cliquer sur "Info" et on obtient des informations sur la cellule clickée:
    Nom : Capture d'écran 2025-11-18 152900.png
Affichages : 180
Taille : 17,7 Ko

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 992
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 992
    Par défaut
    Ajoute Button1.ControlStyle := Button1.ControlStyle +[csClickEvents] pour que le clic soit traité à réception de WM_LBUTTONUP plutôt qu'un CN_COMMAND qui n'arrive pas dans ce cas-là (j'ignore pourquoi).

  3. #3
    Membre éclairé

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

    Ca marche parfaitement. MERCI !

    Suite à ce succès, j'ai cherché un peu plus loin, et j'ai trouvé ceci:
    https://stackoverflow.com/questions/...emouse-exactly

    Il y est dit en particulier:
    Because the mechanism through which you receive clicks for a TButton is different - it generates click events from a BN_CLICKED windows message, which is the windows way of handling buttons, rather than via WML_BUTTONDOWN, which is the default for a TControl.
    .
    Bizarre... Mais pour moi, c'est la solution. Merci encore !

    P.S. La même solution doit être apportée pour TCheckBox, TRadioButton et TComboBox.
    Je continue mes explorations...

  4. #4
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    Suite de mes expériences avec l'injection de contrôles dans des cellules d'un TStringGrid:

    1. La sélection de la cellule contenant le contrôle activé par un clic

    La présence d'un contrôle dans une cellule "bloque" la sélection de la cellule lorsqu'on clique sur ce contrôle.
    Cela ne m'étonne pas - c'est le contrôle qui reçoit le message, pas le TStringGrid.
    S'il est nécessaire de savoir dans quelle cellule le contrôle a été activé, il faut programmativement sélectonner la cellule, par exemple comme ceci:
    Seulement, il y a un problème: lorsqu'on clique sur un bouton injecté (ou un TCheckBox, un TRadioButton, un TSpinEdit etc), on n'a pas les valeurs de aol et aRow.
    Alors, j'ai imaginé une solution que j'emploie maintenant pour tout contrôle injecté quel qu'il soit:
    Pour chaque contrôle injecté, je crée une classe qui donne sa "carte d'identité":
    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
    type TCellID = class
      private
        fRow: integer;
        fCol: integer;
      published
        constructor Create(aOwner: TComponent; aRow, aCol: integer);
        destructor destroy; override;
    end;
     
    constructor TCellID.Create(aOwner: TComponent; aRow, aCol: integer);
    begin
      fRow := aRow;
      fCol := aCol;
    end;
     
    destructor TCellID.destroy;
    begin
    end;
    Et lors de la création d'un contrôle injecté, le lui attache une telle classe via son Tag:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        bt.Tag := integer(TCellID.Create(self,aRow,aCol));
    Lors de sa création, je connais sa destination et donc les valeurs de aRow et aCol. Du coup, je m'affranchis de la limite des 32 bits du Tag pour mémoriser 2 moriser 2 mots de 32 bits pour les coordonnées. (Je sais, je vois large, mais c'est pour expérimenter de telles solutions).

    Ainsi, dans la rourine OnClick (ou dans n'importe quelle routine évènement d'ailleurs), je peux faire ceci:
    - interroger Sender.ClassName, en fonction de cela récuper son TCellID et j'ai les coordonnées de la cellule.

    2. Certains contrôles continuent à poser problème

    C'est le cas des TRadioButton. Je peux en injecter autant que je veux, mais comme leur parent commun est le TStringGrid, un seul parmi ces boutons peut être coché en même temps, quelque soit la position du bouton dans le grid. J'ai essayé de jongler avec des TRadioGroup ou TPanel, cachés ou hors écran), mais rien n'y fait. Dès aue la propriété Parent du TRadioButton est changée, on retombe dans le comportement décrit ci-dessus. Sinon, le TRadioButton n'apparaît tout simplement pas, MEME si je force la propriété ParentWindow.

    J'airais aimé pouvoir créer des ensembles logiques de TRadioButton sans avoir à les grouper visuellement ensemble, mais c'est impossible.

    Par contre, je peux agrandir une colonne en largeur et y injecter un TRadioGroup qui, à son tour, recevra des TRadioButton.

    Un autre cas est celui des TComboBox. Je peux facilement en injecter plusieurs dans des cellules du TStringGrid, mais en apparence, leur bouton permettant de déployer les options semble inactif. Il ne l'est pourtant pas - seulement l'espace d'affichage est limité par l'espace de la cellule, et le déploiement reste invisible. Par contre, on peur parcourir les options via les flèches en haut ou en bas et valider l'option choisie par Return.

    Un autre cas, prohibitif celui-la, est le TSpinEdit. Je peux finalement en injecter autant que je veux et, à première vue, tout semble correct. Mais dès qu'un clic est effectué dans un de ces contrôles ou sur ses flèches d'incrémentation ou décrémentation, l'ensemble des fleches des autres TSpinEdit disparaît et la couleur de fond est visible leur place. Et en quittant le TSpinEdit actif, ses flèches disparaissent également. Je n'ai trouvé aucun moyen d'éviter cela. Evidemment, j'ai pensé à faire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    se: TSprinEdit;
    ...
        se.Button.OnDownClick := sgButtonClickDown;
        se.Button.OnUpClick := sgButtonClickUp;
        se.ControlStyle := se.ControlStyle +[csClickEvents];
        se.Button.ControlStyle := se.ControlStyle +[csClickEvents];
        se.Button.ControlStyle := se.ControlStyle +[csClickEvents];
    Rien n'y fait.
    Je pense que je serai contraint de créer mon propre SpinEdit spécifique pour cet usage...

    Pistes pour la suite

    En-dehors du SpinEdit dont je commencerai l'implémentation bientôt, je vais tenter d'afficher des icônes et/ou de petites images ce qui ne devrait pas être trop difficile.

  5. #5
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    Ok, j'ai complètement réimplémenté un TSpinEdit à partir de zéro, sans me baser sur le TSpinEdit existant. Ce nouveau contrôle s'appelle TKSpinEdit.
    Or, ce contrôle peut être injecté facilement dans mon TKStringGrid, sans aucun problème de réaffichage. En ce qui me concerne, mon problème de TSpinEdit est résolu.

    Je vais maintenant réécrire le TComboBox afin de pouvoir visualiser le déploiement des éléments de ce contrôle lorsqu'on clique sue la flèche de déploiement.
    Je pense que je vais combiner ce contrôle avec un TLIstBox créé dynamiquement pour l'affichage, et supprimé ensuite. A voir...

    P.S.

    J'ai implémenté mon propre TKCombox utilisant un TComboBox standard associé à un TListBox standard, mais indépendant du TComboBox. Et là, après injection de ce composant dans une cellule de mon TKSTringGrid, je peux dérouler le contenu via la TListBox qui s'affiche par-dessus le tout, cliquer sur une des lignes ce qui place cette ligne dans la propriété Text du TComboBox, puis replie le TListBox.

    Donc, j'ai on comportement habituel d'une TComboBox, mais dans une cellule d'un dérivé de TStringGrid.

    La suite: les icônes ou petites images...

  6. #6
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    J'ai ajouté l'injection d'objets TPicture, ainsi que le paramétrage des polices des textes, le tout sélectivement cellule par cellule.
    En plus, j'ai ajouté la fusion verticale et horizontale de cellules: un rectangle de cellules devient une seule cellule.

    Dans la capture d'écran ci-dessous, j'ai injecté 6 TPicture dans les lignes 2 et 3, colonnes 1 et 2. Le contenu texte de ces cellules est interprété comme nom d'un fichier BMP dont le contenu est affiché par StretchDraw dans les cellules associées.
    Il y a aussi les cellules des lignes 4 et 5, colonnes 6 à 12 sont en police "MS Sans Serif" taille 10 couleur bleue, en gras et italique, alors que toutes les autres cellules sont an taille 8 couleur noire, sans attributs.
    Les cellules des lignes 5 à 7 et des colonnes 1 à 2 (6 cellules) sont fusionnées en une seule cellule de référence ligne 5 colonne 1.
    Dans la cellule représentant les 6 cellules fusionnées, j'ai injecté un TPicture que j'ai chargé avec l'image d'une tête de tigre.
    Puis j'ai clique sur l'image du tigre sélectionnant ainsi la cellule ligne 5 colonne 1 (la cellule racine de la sélection), puis j'ai cliqué sur "Info":
    Nom : Capture d'écran 2025-11-24 175232.png
Affichages : 70
Taille : 58,5 Ko

  7. #7
    Invité
    Invité(e)
    Par défaut
    Est-ce que l'unité Themes est disponible en D6 elle permet de dessiner des contrôles sur un canvas ce qui évite l’insertion de vrais contrôles dans le TStringgrid qui n'est pas fait pour cela.

    voila un exemple des checkboxs dessinés dans une version plus récente mais le même code fonctionne avec D7 avec un look différent



    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
     ;
           for I := TopIndex to Count -1 do
           begin
              R := ItemRect(I);
              if R.Bottom  >= FBottomBand.Top then
               break;
              sel := Selected[I];
              R.Top:= R.Top +4;
              R.Left := FLeftBand.Left;
              R.Right := FLeftBand.Right;
              if sel then
                Details := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal)
              else
                Details := ThemeServices.GetElementDetails(tbCheckBoxUncheckedNormal);
              ThemeServices.DrawElement(DC, Details, R, nil);
     
           end;
    Dernière modification par Invité ; 27/11/2025 à 12h40.

  8. #8
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mist2024 Voir le message
    Est-ce que l'unité Themes est disponible en D6 elle permet de dessiner des contrôles sur un canvas ce qui évite l’insertion de vrais contrôles dans le TStringgrid qui n'est pas fait pour cela.

    voila un exemple des checkboxs dessinés dans une version plus récente mais le même code fonctionne avec D7 avec un look différent



    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
     ;
           for I := TopIndex to Count -1 do
           begin
              R := ItemRect(I);
              if R.Bottom  >= FBottomBand.Top then
               break;
              sel := Selected[I];
              R.Top:= R.Top +4;
              R.Left := FLeftBand.Left;
              R.Right := FLeftBand.Right;
              if sel then
                Details := ThemeServices.GetElementDetails(tbCheckBoxCheckedNormal)
              else
                Details := ThemeServices.GetElementDetails(tbCheckBoxUncheckedNormal);
              ThemeServices.DrawElement(DC, Details, R, nil);
     
           end;
    Non, cela n'existe pas en Delphi 6 Personal Edition. Dommage...

  9. #9
    Invité
    Invité(e)
    Par défaut
    Essaie ce vieux code ça devrait fonctionner également en D6 en réalité les fonctionnalités basiques des thèmes sont importées de windows Delphi ne fait que les encapsuler et les étendre pour gérer de nouveaux styles.

    Lancer le code dans une fiche vide avec un simple bouton .
    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
     
    function  OpenThemeData(hwnd: HWND; pszClassList: LPCWSTR): THandle; stdcall ;external 'uxtheme.dll';
    function  CloseThemeData(hTheme: THandle): HRESULT; stdcall;external 'uxtheme.dll';
     
     
    procedure DrawTheme(dc:HDC; iPartId, iStateId: integer; const R: TRect);
    var
     h: THandle;
     s: WideString;
    begin
     S := 'button';
     h := OpenThemeData(0, PWidechar(S));
     DrawThemeBackground(h, dc, iPartId, iStateId, R, nil);
     CloseThemeData(h);
    end;
     
    procedure TForm1.Button3Click(Sender: TObject);
    var
     h: integer;
    begin
      h := canvas.Handle;
      DrawTheme(h,  1, 1, bounds(80 * 0, 10, 70, 30));
      //Hot
      DrawTheme(h,  1, 2, bounds(80 * 1, 10, 70, 30));
      //Pushed
      DrawTheme(h,  1, 3, bounds(80 * 2, 10, 70, 30));
      //Disabled
      DrawTheme(h,  1, 4, bounds(80 * 3, 10, 70, 30));
      //Fucused
      DrawTheme(h,  1, 5, bounds(80 * 4, 10, 70, 30));
     
    //OptionButton
      //Normal
      DrawTheme(h,  2, 1, bounds(80 * 0, 50, 70, 30));
      //Hot
      DrawTheme(h,  2, 2, bounds(80 * 1, 50, 70, 30));
      //Pushed
      DrawTheme(h,  2, 3, bounds(80 * 2, 50, 70, 30));
      //Disabled
      DrawTheme(h,  2, 4, bounds(80 * 3, 50, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 50, 70, 30));
     
    //CheckButton
      //Normal
      DrawTheme(h,  3, 1, bounds(80 * 0, 70, 70, 30));
      //Hot
      DrawTheme(h,  3, 2, bounds(80 * 1, 70, 70, 30));
      //Pushed
      DrawTheme(h,  3, 3, bounds(80 * 2, 70, 70, 30));
      //Disabled
      DrawTheme(h,  3, 4, bounds(80 * 3, 70, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 70, 70, 30));
     
    end;

  10. #10
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Mist2024 Voir le message
    Essaie ce vieux code ça devrait fonctionner également en D6 en réalité les fonctionnalités basiques des thèmes sont importées de windows Delphi ne fait que les encapsuler et les étendre pour gérer de nouveaux styles.

    Lancer le code dans une fiche vide avec un simple bouton .
    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
     
    function  OpenThemeData(hwnd: HWND; pszClassList: LPCWSTR): THandle; stdcall ;external 'uxtheme.dll';
    function  CloseThemeData(hTheme: THandle): HRESULT; stdcall;external 'uxtheme.dll';
     
     
    procedure DrawTheme(dc:HDC; iPartId, iStateId: integer; const R: TRect);
    var
     h: THandle;
     s: WideString;
    begin
     S := 'button';
     h := OpenThemeData(0, PWidechar(S));
     DrawThemeBackground(h, dc, iPartId, iStateId, R, nil);
     CloseThemeData(h);
    end;
     
    procedure TForm1.Button3Click(Sender: TObject);
    var
     h: integer;
    begin
      h := canvas.Handle;
      DrawTheme(h,  1, 1, bounds(80 * 0, 10, 70, 30));
      //Hot
      DrawTheme(h,  1, 2, bounds(80 * 1, 10, 70, 30));
      //Pushed
      DrawTheme(h,  1, 3, bounds(80 * 2, 10, 70, 30));
      //Disabled
      DrawTheme(h,  1, 4, bounds(80 * 3, 10, 70, 30));
      //Fucused
      DrawTheme(h,  1, 5, bounds(80 * 4, 10, 70, 30));
     
    //OptionButton
      //Normal
      DrawTheme(h,  2, 1, bounds(80 * 0, 50, 70, 30));
      //Hot
      DrawTheme(h,  2, 2, bounds(80 * 1, 50, 70, 30));
      //Pushed
      DrawTheme(h,  2, 3, bounds(80 * 2, 50, 70, 30));
      //Disabled
      DrawTheme(h,  2, 4, bounds(80 * 3, 50, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 50, 70, 30));
     
    //CheckButton
      //Normal
      DrawTheme(h,  3, 1, bounds(80 * 0, 70, 70, 30));
      //Hot
      DrawTheme(h,  3, 2, bounds(80 * 1, 70, 70, 30));
      //Pushed
      DrawTheme(h,  3, 3, bounds(80 * 2, 70, 70, 30));
      //Disabled
      DrawTheme(h,  3, 4, bounds(80 * 3, 70, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 70, 70, 30));
     
    end;
    J'ai essayé et j'ai produit ceci:
    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
    unit Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
     
    function  OpenThemeData(hwnd: HWND; pszClassList: LPCWSTR): THandle; stdcall ;external 'uxtheme.dll';
    function  CloseThemeData(hTheme: THandle): HRESULT; stdcall;external 'uxtheme.dll';
    function DrawThemeBackground(hTheme: THandle; hdc: Hdc; iPartId: integer; iStateId: integer;
      pRect: TRect; pClipRect: pointer): hresult;external 'uxtheme.dll';
     
    procedure DrawTheme(dc:HDC; iPartId, iStateId: integer; const R: TRect);
    var
     h: THandle;
     s: WideString;
    begin
     S := 'button';
     h := OpenThemeData(0, PWidechar(S));
     DrawThemeBackground(h, dc, iPartId, iStateId, R, nil);
     CloseThemeData(h);
    end;
     
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
     h: integer;
    begin
      h := canvas.Handle;
      DrawTheme(h,  1, 1, bounds(80 * 0, 10, 70, 30));
      //Hot
      DrawTheme(h,  1, 2, bounds(80 * 1, 10, 70, 30));
      //Pushed
      DrawTheme(h,  1, 3, bounds(80 * 2, 10, 70, 30));
      //Disabled
      DrawTheme(h,  1, 4, bounds(80 * 3, 10, 70, 30));
      //Fucused
      DrawTheme(h,  1, 5, bounds(80 * 4, 10, 70, 30));
     
    //OptionButton
      //Normal
      DrawTheme(h,  2, 1, bounds(80 * 0, 50, 70, 30));
      //Hot
      DrawTheme(h,  2, 2, bounds(80 * 1, 50, 70, 30));
      //Pushed
      DrawTheme(h,  2, 3, bounds(80 * 2, 50, 70, 30));
      //Disabled
      DrawTheme(h,  2, 4, bounds(80 * 3, 50, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 50, 70, 30));
     
    //CheckButton
      //Normal
      DrawTheme(h,  3, 1, bounds(80 * 0, 70, 70, 30));
      //Hot
      DrawTheme(h,  3, 2, bounds(80 * 1, 70, 70, 30));
      //Pushed
      DrawTheme(h,  3, 3, bounds(80 * 2, 70, 70, 30));
      //Disabled
      DrawTheme(h,  3, 4, bounds(80 * 3, 70, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 70, 70, 30));
    end;
     
    end.
    J'ai juste ajouté la référence à DrawThemeBackground (elle manquait dans le code). Mais j'ai dû me planter avec cette définition, car j'obtiens ceci:
    Nom : Capture d'écran 2025-11-28 005255.png
Affichages : 44
Taille : 15,6 Ko
    et ceci se produit dès le premier appel à DrawTheme.

  11. #11
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    Ok, j'ai trouvé. Le wrapper de cette fonction doit être:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    function  DrawThemeBackground(hTheme: Thandle; hdc: HDC; iPartId, iStateId: Integer;
      const pRect: TRect; pClipRect: PRECT): HRESULT; stdcall;external 'uxtheme.dll';
    voir

    Maintenant, ça fonctionne. Je voir ce que je peux faire avec ça...

  12. #12
    Membre éclairé

    Homme Profil pro
    Informaticien retraité
    Inscrit en
    Mars 2010
    Messages
    407
    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 : 407
    Billets dans le blog
    1
    Par défaut
    J'ai trouvé un lien pour télécharger UxTheme.pas: https://www.google.com/url?sa=t&sour...SEoyogjv-Y0Gcx

    Il suffit alors d'inclure ce fichier dans les clauses Uses, et d'inclure ceci dans les évènements de la Form1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      InitThemeLibrary;
    end;
     
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      FreeThemeLibrary;
    end;
    On a alors un chargement dynamique de la DLL, avec un wrapper complet autour des fonctions de UxTheme.dll.
    Et cela marche en Delphi 6 PE !

    Voici le code du programme adapté avec cette technique:
    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
    unit TestTheme_Unit1;
     
    interface
     
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, UxTheme;
     
    type
      TForm1 = class(TForm)
        Button1: TButton;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Déclarations privées }
      public
        { Déclarations publiques }
      end;
     
    var
      Form1: TForm1;
     
    implementation
     
    {$R *.dfm}
     
    procedure DrawTheme(dc:HDC; iPartId, iStateId: integer; const R: TRect);
    var
     h: THandle;
     s: WideString;
    begin
     S := 'button';
     h := OpenThemeData(0, PWidechar(S));
     DrawThemeBackground(h, dc, iPartId, iStateId, R, nil);
     CloseThemeData(h);
    end;
     
     
    procedure TForm1.Button1Click(Sender: TObject);
    var
     h: integer;
    begin
      h := canvas.Handle;
     
    //Button
      //Normal
      DrawTheme(h,  1, 1, bounds(80 * 0, 10, 70, 30));
      //Hot
      DrawTheme(h,  1, 2, bounds(80 * 1, 10, 70, 30));
      //Pushed
      DrawTheme(h,  1, 3, bounds(80 * 2, 10, 70, 30));
      //Disabled
      DrawTheme(h,  1, 4, bounds(80 * 3, 10, 70, 30));
      //Focused
      DrawTheme(h,  1, 5, bounds(80 * 4, 10, 70, 30));
     
    //OptionButton
      //Normal
      DrawTheme(h,  2, 1, bounds(80 * 0, 50, 70, 30));
      //Hot
      DrawTheme(h,  2, 2, bounds(80 * 1, 50, 70, 30));
      //Pushed
      DrawTheme(h,  2, 3, bounds(80 * 2, 50, 70, 30));
      //Disabled
      DrawTheme(h,  2, 4, bounds(80 * 3, 50, 70, 30));
      //Fucused
      DrawTheme(h,  2, 5, bounds(80 * 4, 50, 70, 30));
     
    //CheckButton
      //Normal
      DrawTheme(h,  3, 1, bounds(80 * 0, 70, 70, 30));
      //Hot
      DrawTheme(h,  3, 2, bounds(80 * 1, 70, 70, 30));
      //Pushed
      DrawTheme(h,  3, 3, bounds(80 * 2, 70, 70, 30));
      //Disabled
      DrawTheme(h,  3, 4, bounds(80 * 3, 70, 70, 30));
      //Fucused
      DrawTheme(h,  3, 5, bounds(80 * 4, 70, 70, 30));
    end;
     
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      InitThemeLibrary;
    end;
     
    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      FreeThemeLibrary;
    end;
     
    end.
    Pour les valeurs possibles de iPartID et iStateID, voir ici: // Info about iParID and iStateID: learn.microsoft.com/en-us/windows/win32/controls/parts-and-states

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

Discussions similaires

  1. Formule avec Nom d'onglet dans une cellule
    Par Krisprolls86 dans le forum Excel
    Réponses: 2
    Dernier message: 12/10/2015, 10h48
  2. Réponses: 11
    Dernier message: 09/07/2010, 18h44
  3. Réponses: 5
    Dernier message: 16/03/2010, 10h58
  4. Réponses: 19
    Dernier message: 09/06/2009, 13h07
  5. Utiliser un TProgressBar dans une cellule d'un TStringGrid ?
    Par [ZiP] dans le forum Composants VCL
    Réponses: 6
    Dernier message: 26/06/2008, 10h09

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