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 FMX Delphi Discussion :

Changer de style au runtime [Windows]


Sujet :

Composants FMX Delphi

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 593
    Billets dans le blog
    65
    Par défaut Changer de style au runtime
    Bonjour, (10.3.3)

    Il m'est venu à l'idée de charger le style principal de mon application à partir d'une base de données (objectif : donner une couleur différente en fonction de la société en cours)
    Voilà en gros le code de chargement du style :

    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
     
    AQuery:=TFDQuery.Create(Self);
      try
        AQuery.Connection:=ConnexionBase;
        AQuery.SQL.Text:='SELECT * FROM SETTINGS WHERE ID=0';
        AQuery.Active:=True;
        // Changement des FormatSettings en fonction de la société 
        if not AQuery.FieldByName('ID').IsNull then
           TFormatSettings.Create(AQuery.FieldByName('IDLANG').asInteger);
        // Changement de style 
        if not AQuery.FieldByName('Style').isNull then
         begin
           AStream:=TmemoryStream.Create;
           try
            TBlobField(AQuery.FieldByName('STYLE')).SaveToStream(AStream);
            AStream.Position:=0;
            StyleSociete.LoadFromStream(AStream);
           finally
             AStream.Free;
           end;
         end
        else StyleSociete.Clear;
        AQuery.Active:=False;
      finally
        AQuery.Free;
      end;
    Le hic, quand je change de société et que je charge le style le cadre windows avec son titre et ses boutons "système" disparait
    Je dois louper quelque chose de tout bête !
    - si après chargement je fais un ApplyStyleLookup cela ne change rien

  2. #2
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 593
    Billets dans le blog
    65
    Par défaut
    Bon, on pourra dire que ce truc m'a fait perdre pas mal de temps et de patience

    Il m'a fallu faire un petit programme parallèle à l'application que je développais et pas mal d'arrachage de cheveux pour comprendre.

    Plusieurs tentatives infructueuses avec les streams m'ont poussées à utiliser un fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     if not AQuery.FieldByName('Style').isNull then
         begin
            TBlobField(AQuery.FieldByName('STYLE')).SaveToFile(parametres.StyleFileName);
            StyleSociete.LoadFromFile(Parametres.StyleFileName);
         end
        else StyleSociete.Clear;
    passer par un stylebook (StyleSociete) se révélant non concluant j'ai encore changé de direction pour utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    TStyleManager.SetStyleFromFile(nomdefichier)
    Et pas de stylebook
    Malgré ça si l'application du premier style fonctionnait, il n'en allait plus de même ensuite sur un point (le plus important pour moi) : un bouton de clôture d'onglets, truc que j'avais rajouté tout d'abord dans un style séparé.
    C'est là que je me suis aperçu que lors du changement de style la procédure assignée pour le onClick sur le bouton était réinitialisée
    Nom : Capture.PNG
Affichages : 846
Taille : 422,0 Ko

    Pas de stylebook ? Oui, je suis revenu dessus pour le cas où aucun style ne serait appliqué
    Nom : Capture_2.PNG
Affichages : 822
Taille : 10,2 Ko

    Le piège était donc dans le fait que le chargement d'un style effaçait l'assignation de la procédure onClick.
    Un autre piège, j'avais des types différents dans mes styles, un TButton pour (diamond style et le stylebook), un TSpeedButton pour l'autre (ubuntu style), je ne comprenais pas pourquoi l'assignation ne se faisait pas pour ce dernier jusqu'à ce que j'utilise la classe ancêtre
    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
     
    unit EssaiChgtStyle;
     
    interface
     
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.TabControl,
      FMX.Controls.Presentation, FMX.StdCtrls, FMX.Styles;
     
    type
     
     
      TForm102 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        TabControl1: TTabControl;
        Button3: TButton;
        BtnNoStyle: TButton;
        StyleBook1: TStyleBook;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure BtnNoStyleClick(Sender: TObject);
      private
        { Déclarations privées }
        soc : String;
        procedure closetab (sender: TObject);
        procedure stylechange;
      public
        { Déclarations publiques }
      end;
     
    var
      Form102: TForm102;
     
    implementation
     
    {$R *.fmx}
     
    procedure TForm102.BtnNoStyleClick(Sender: TObject);
    begin
     Soc :='';
     TStyleManager.SetStyle(nil);
     StyleChange;
    end;
     
    procedure TForm102.Button1Click(Sender: TObject);
    var ATabItem : TTabItem;
    begin
      ATabItem := TabControl1.Add;
      ATabItem.StyleLookup:='tabitemclosestyle';
      try
      TCustomButton(ATabItem.FindStyleResource('btnclosetab')).OnClick:=CloseTab;
      TCustomButton(ATabItem.FindStyleResource('btnclosetab')).TagString:='Test nostyle';
      except
     
      end;
    end;
     
    procedure TForm102.Button2Click(Sender: TObject);
    var
      i: Integer;
    begin
    Soc := ' Ubuntu';
    TStyleManager.SetStyleFromFile('D:\XE8\FMX\Ubuntu.win.Style');
    StyleChange;
    end;
     
    procedure TForm102.Button3Click(Sender: TObject);
    var
      i: Integer;
    begin
    Soc := ' Diamond';
    TStyleManager.SetStyleFromFile('D:\XE8\FMX\Diamond.win.Style');
    StyleChange;
    end;
     
    procedure TForm102.closetab(sender: TObject);
    begin
    Showmessage(TCustomButton(TabControl1.ActiveTab.FindStyleResource('btnclosetab')).TagString);
    end;
     
    procedure TForm102.stylechange;
    var
      i: Integer;
    begin
    for i:=0 to TabControl1.TabCount-1 do
     begin
    //   TabControl1.Tabs[i].StyleLookup:='tabitemclosestyle';
       TabControl1.Tabs[i].ApplyStyleLookup;
       TCustomButton(TabControl1.Tabs[i].FindStyleResource('btnclosetab')).OnClick:=CloseTab;
       TCustomButton(TabControl1.Tabs[i].FindStyleResource('btnclosetab')).TagString:='Test '+Soc;
     end;
    end;
     
    end.

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

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

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 086
    Par défaut
    Citation Envoyé par SergioMaster Voir le message
    Il m'est venu à l'idée de charger le style principal de mon application à partir d'une base de données (objectif : donner une couleur différente en fonction de la société en cours)
    J'avais eu la même idée en VCL en particulier pour la logistique qui gérait les flux de deux sociétés et devait en faire l'aiguillage, en plus de la couleur, il y a un avait le logo de la société et un bouton pour passer de l'un à l'autre rapidement
    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
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 593
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    Pour VCL, cela faisait un bail que je proposais la couleur de fond pour distinguer les diverses sociétés mais en FMX c'était un peu plus complexe ou plus exactement piègeux (pièges non indiquées dans la doc à ma connaissance).

    Du coup, cela réglé, j'ai voulu aller un peu plus loin en me proposant de montrer la "saveur" du style (en fait le background utilisé) dans un petit rectangle.
    Dans cette discussion https://www.developpez.net/forums/d1...ouleur-defaut/ je pensais trouver le moyen de le faire mais non, car dans la solution présentée c'est le StyleManager qui est utilisé pour obtenir les infos de couleurs, or, dans le cas qui m'intéresse, je veux charger dans un StyleBook à partir d'un fichier, et, sans appliquer le stylebook en extraire les infos
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    aStyle:=TStyleBook.Create(nil);
    try
      aStyle.LoadFromFile('D:\XE8\FMX\ubuntu.win.Style');
      // comment interroger le style aStyle qui n'est pas appliqué ?
      // Rectangle1.Fill:=TRectangle(afmxObj).Fill;
      // Label1.Text:=aStyle.StyleName;
    finally
      aStyle.Free;
    end;

  5. #5
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 593
    Billets dans le blog
    65
    Par défaut
    Bonjour,

    En s'acharnant on fini par trouver après moult essais, ce qui je pense pourrait fournir une jolie FAQ !

    En voilà déjà le schéma principal
    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
    var
      aStyle : TStyleBook;
      aFmxObj : TFMXObject;
    begin
    if Opendialog1.Execute then
    begin
      aStyle := TStyleBook.Create(nil);
      try
        aStyle.LoadfromFile(opendialog1.filename);
        aFmxObj:=aStyle.Style.FindStyleResource('backgroundStyle');
        Image1.Bitmap:=TImage(aStyle.Style.FindStyleResource(TStyleObject(afmxObj).sourcelookup)).Bitmap;
      finally
        aStyle.Free;
      end;
    end;
    Nom : Capture.PNG
Affichages : 753
Taille : 89,7 Ko
    Reste que tous les styles ne sont pas sur le même schéma, si ce code fonctionne pour les deux styles que j'ai, pour l'instant, adopté il n'en va pas de même pour la "collection" qu'Embarcadero fourni.
    La ligne 11 est à améliorer

  6. #6
    Membre Expert
    Avatar de ALWEBER
    Homme Profil pro
    Expert Delphi
    Inscrit en
    Mars 2006
    Messages
    1 539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 70
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Expert Delphi

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 539
    Billets dans le blog
    10
    Par défaut
    Pour info, sur les précédentes versions de Delphi tu pouvait accéder au style en mode texte (voir les messages que j'ai posté il y a quelques années à ce sujet). Il est toujours possible de récupérer le texte du style en copiant la racine du style dans le presse papier. Je ne suis pas allé plus loin dans me recherches.

  7. #7
    Rédacteur/Modérateur

    Avatar de SergioMaster
    Homme Profil pro
    Développeur informatique retraité
    Inscrit en
    Janvier 2007
    Messages
    15 593
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 69
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur informatique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 15 593
    Billets dans le blog
    65
    Par défaut
    Bonjour Alain

    Oui, dans mes pistes de recherche il y avait aussi la solution "parser un fichier texte" et même ce que tu nommes la "sérialisation/dé-sérialisation" d'objets.

    Ma méthode, "passer par un stylebook" est avantageuse dans le sens où le "parser" est inutile et remplacée par un "simple" FindStyleResource. Cependant il faut quand même "intimement" connaitre le contenu du fichier style, pour mes recherches j'ai utilisé à la fois le style designer et Notepad++

    Entre-temps ma solution à évoluée
    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
     
    procedure TForm102.EllipsesEditButton1Click(Sender: TObject);
    var
      aStyle : TStyleBook;
      aFmxObj : TFMXObject;
      aBitmap : TBitmap;
      aBounds : TBounds;
      aRect : TRect;
    begin
    if Opendialog1.Execute then
    begin
      Edit1.Text:=OpenDialog1.FileName;
      aStyle := TStyleBook.Create(nil);
      aBitmap:=TBitmap.Create;
      try
        aStyle.LoadfromFile(opendialog1.filename);
        aFmxObj:=aStyle.Style.FindStyleResource('backgroundstyle');
        if aFMXObj is TStyleObject then
         begin
          if Assigned(TStyleObject(aFMXObj).SourceLink) then
           begin
            aBounds:=TBitmapLinks(TStyleObject(aFMXObj).SourceLink).Links[0].SourceRect;
            aRect:=TRect.Create(Trunc(aBounds.Left),Trunc(aBounds.Top),Trunc(aBounds.Right),Trunc(aBounds.Bottom));
            ABitmap.Width:=ARect.Right-ARect.Left;
            ABitmap.Height:=ARect.Bottom-ARect.Top;
            aBitmap.CopyFromBitmap(TImage(aStyle.Style.FindStyleResource(TStyleObject(afmxObj).sourcelookup)).Bitmap,aRect,0,0);
           end
          else ABitmap:=TImage(aStyle.Style.FindStyleResource(TStyleObject(afmxObj).sourcelookup)).Bitmap;
         end;
        if aFMXObj is TRectangle then
          begin
            aBitmap.Width:=Trunc(Image1.Width);
            aBitmap.Height:=Trunc(Image1.Height);
            aBitmap.Clear(TRectangle(aFMXObj).Fill.Color);
          end;
        Image1.Bitmap:=aBitmap;
      finally
        aBitmap.Free;
        aStyle.Free;
      end;
     end;
    end;
    Il doit y avoir des simplifications à faire ce n'est encore qu'une ébauche
    Cela à l'air de fonctionner pour tous les styles windows, pour les styles à la pomme ou au droïd impossible de savoir, pour l'instant, si cela ne fonctionne pas à cause du fait que je teste sous windows ou s'il me manque quelque chose genre sélection de l'élément de collection. Je penche pour l'hypothèse "si le style n'est pas supporté, il n'est pas chargé", hypothèse que j'avais du déjà émettre (j'ai une impression de déjà vu)
    Pour pallier ce problème un test pour savoir si le style à charger est supporté sera nécessaire.

    P.S. Je viens de découvrir également comment obtenir titre, auteur, cibles, etc.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    TStyleDescription(aStyle.Style.FindStyleResource('description')).Title
    TStyleDescription(aStyle.Style.FindStyleResource('description')).Author
    TStyleDescription(aStyle.Style.FindStyleResource('description')).AuthorURL
    TStyleDescription(aStyle.Style.FindStyleResource('description')).PlatFormTarget

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

Discussions similaires

  1. Réponses: 8
    Dernier message: 16/11/2005, 14h05
  2. [JTable] Changer le style de certaines cellulles
    Par bourinator dans le forum Composants
    Réponses: 4
    Dernier message: 08/10/2005, 14h40
  3. Changer le style en JavaScript [besoin d'aide]
    Par maximenet dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 13/09/2005, 17h21
  4. Changer plusieur style avec des IDs différents?
    Par YanK dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 02/07/2005, 14h33
  5. Changer le style d'une cellule
    Par LE NEINDRE dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 29/06/2005, 16h18

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