8

I'm loading a custom style from file using:

TStyleManager.LoadFromFile(filename)

When the file is changed I want to load it again. But if I try that I get a EDuplicateStyleException because the style is already registered.

Is there a way to unload a style so I can load it again? The typical case for this is that you are making changes to a custom style and want to see it in action without restarting the whole application.

RRUZ
  • 134,889
  • 20
  • 356
  • 483
Ville Krumlinde
  • 7,021
  • 1
  • 33
  • 41

5 Answers5

7

After scanning the sources I guess that is not possible in a straight forward way. Your only chance might be to implement some dirty hack.

Whatever you do, you should write a QC for this. Embarcadero could implement to reload the file if the style already exists instead of raising an exception. That would look like a natural behaviour to me.

Uwe Raabe
  • 45,288
  • 3
  • 82
  • 130
  • Thanks Uwe, I've posted a feature request here: http://qc.embarcadero.com/wc/qcmain.aspx?d=98852 – Ville Krumlinde Sep 13 '11 at 07:57
  • 1
    Looks like they removed the bug report: "Either there is no report #98852" – Gabriel May 19 '15 at 13:53
  • 1
    The feature request is gone. What's up with that? – James Johnston Jan 27 '16 at 16:12
  • For whatever reason the report is not visible in public. Nevertheless, it is closed and the resolution comment mentions the issue being fixed in XE3. – Uwe Raabe Jan 27 '16 at 16:21
  • @Everybody_hates_BillTheLizard: Actually, that is no surprise as they did shutdown QC quite a while ago. The current place now is quality.embarcadero.com, but I doubt you will find it there as the issue presumably is already fixed in XE3. – Uwe Raabe Oct 23 '18 at 13:35
  • @UweRaabe - Actually, no. I struggle right now to reload a vsf file from disk in C++ Tokyo. If you call LoadFromFile and then SetStyle it will tell you that the style is already registered. – Gabriel Oct 23 '18 at 14:00
  • @Everybody_hates_BillTheLizard - In that case please file a new bug report. – Uwe Raabe Oct 23 '18 at 14:33
  • Neeee.... My subscription will expire soon. I won't have access to that bug fix without paying for it. – Gabriel Oct 24 '18 at 07:06
  • But perhaps others may benefit? – Uwe Raabe Oct 24 '18 at 07:39
  • 1
    I agree. And this is why I will try to post a piece of code that works (I ALREADY posted something but there is a problem with UnRegisterStyle). Others will benefit better from this: 1. they don't have to wait for Emba to fix it (if ever fixed). 2. they won't have to purchase the bug fix. In other words I think it is better if we solve this here instead of relying on Embarcadero. – Gabriel Oct 24 '18 at 08:44
4

Check this project vcl styles utils, one of the features exposed is the capacity of unload a vcl style. Just include the Vcl.Styles.Ext unit in your project and then use this code.

 TStyleManager.RemoveStyle('Carbon');
RRUZ
  • 134,889
  • 20
  • 356
  • 483
3

Another idea: This might work. Partial code for simplicity. In the code below, you first get a handle to the already registered Style. I guess then, you can dispose and re-assign the pointer with the one you loaded from the file. I believe the exception only show when you try to apply the style, not when you load it. Forgive me if I am wrong.

var
  StyleName: String;
  Style    : TStyleManager.TStyleServicesHandle;
  FileName : String;

begin

  StyleName := 'Obsidian';       // or another style name
  FileName  := 'obsidian.vsf';   // or any other valid style file name

  Style     := TStyleManager.Style[ StyleName];

  if Assigned( Style) then   // style already registered
  begin
    TStyleManager.TrySetStyle( StyleName);
    // insert other processing here

  end
  else // style not registered
  begin 
    if TStyleManager.IsValidStyle( FileName) then
    begin
      Style := TStyleManager.LoadFromFile( FileName);
      if Assigned( Style) then
      begin   
        // insert other processing here, such as
        // TStyleManager.SetStyle( Style);

      end;
    end;
  end;

end;
  • Your concept is right but it won't work because file names are without spaces and style names are with spaces. ie. IcebergClassic.vsf is style filename and style name is 'Iceberg Classico'. So small workaround to add spaces and your code will work. – Nix Mar 06 '15 at 15:39
1

Try this:

procedure TfrmMain.Button11Click(TObject *Sender);    
 var
    MyStyle TCustomStyleServices;
 const
    usStylePath= 'c:\Users\Public\Documents\Embarcadero\Studio\19.0\Styles\vcl\MINE.vsf';
begin
 if TStyleManager.IsValidStyle(usStylePath)
    begin
    // Get current style
    MyStyle:= TStyleManager.Style["Emerald"];   // this will return a TCustomStyleServices obj

    if (MyStyle <> NULL)
       begin
       // Set default Windows style (no style)
       TStyleManager.SetStyle(TStyleManager.SystemStyle);

       // Remove it
       TStyleManager.UnRegisterStyle(MyStyle);
       end;

    // Load style from disk
    TStyleManager.LoadFromFile(usStylePath);
    TStyleManager.SetStyle(Emerald");
    end;
end;

Note: I never complied the code. But it should work.

Anyway, you should use RRuz's library. He knows a lot about these VCL styles.

Gabriel
  • 20,797
  • 27
  • 159
  • 293
0

You could make a copy of each style in another file with different name of the style. Then you could load it's copy as a workaround. If you really need original then you can load it after loading copy.

avra
  • 3,690
  • 19
  • 19
  • Thanks, it's an idea but not very practical when making lots of changes in a style and want to test after each change. Saving "MyStyle_copy_nr_442" etc and remembering to change the style-name property too each time is a lot of typing which makes it faster to just restart the application instead. – Ville Krumlinde Sep 13 '11 at 14:58