Difference between revisions of "LMD 2009 - Theme Engine"

From LMD
Jump to: navigation, search
 
(15 intermediate revisions by 2 users not shown)
Line 3: Line 3:
 
== Overview ==
 
== Overview ==
  
From LMD-Tools 2009 releases we introduce new approach to Theme Engine. This approach aims at following  
+
From LMD-Tools 2009 releases we introduce new approach to Theme Engine. This approach aims at following main goals:
main goals:
 
  
* Basic theme engine causes no or only small overhead (by using System Themes support of Delphi, which  
+
* Basic theme engine causes no or only small overhead (by using System Themes support of Delphi, which is integrated since Delphi 7);
 
 
is integrated since Delphi 7);
 
 
* Management of any calls for internal theme services is centralized;
 
* Management of any calls for internal theme services is centralized;
* No theme related switches and recompilation of library code, but a separate package which you can  
+
* No theme related switches and recompilation of library code, but a separate package which you can decide to use or not at runtime;
 
 
decide to use or not at runtime;
 
 
* Possibility of using custom theme and system theme simultaneously.
 
* Possibility of using custom theme and system theme simultaneously.
  
 
The entry point for new theme services is now ''LMDThemes'' unit.<br>
 
The entry point for new theme services is now ''LMDThemes'' unit.<br>
 
+
This unit introduces '''TLMDThemeRenderer''' and '''TLMDThemeServices''' classes,
This unit introduces '''TLMDThemeRenderer''' and '''TLMDThemeServices''' classes,  
+
LMDThemeServices (global method to access a singleton instance of TLMDThemeServices class), some
LMDThemeServices (global method to access a singleton instance of TLMDThemeServices class), some
 
 
helper methods like LMDSetThemeMode, and a number of theme related constants.<br>
 
helper methods like LMDSetThemeMode, and a number of theme related constants.<br>
 
+
'''TLMDThemeRenderer''' class is an abstract ancestor class for any custom theme renderers. <br>'''TLMDThemeServices''' class provides centralized and unified access to theme rendering routines.<br>
'''TLMDThemeRenderer''' class is an abstract ancestor class for any custom theme renderers. <br>
 
'''TLMDThemeServices''' class provides centralized and unified access to theme rendering routines.<br>
 
 
 
  
 
== Changes from LMD-Tools 2007 version of theme services ==
 
== Changes from LMD-Tools 2007 version of theme services ==
Line 29: Line 20:
 
=== General changes ===
 
=== General changes ===
  
''LMDXPStyles'' and ''LMDXPThemeManager'' units removed. <br>
+
''LMDXPStyles'' and ''LMDXPThemeManager'' units removed. <br>Wherever it is possible, system ''Themes'' and ''UxTheme'' units are used.<br>CtlXP property is now deprecated (moved to public), it is no longer used and remains only for compatibility reasons. ThemeMode (of TLMDThemeMode type, defined in LMDClass unit) property introduced to be used instead of CtlXP. <br>Type '''TLMDThemeMode''' = (ttmNone, ttmPlatform, ttmNative):<br>ttmNone = No global themeing, use control settings<br>ttmPlatform = CtlXP or UseXPThemes<br>ttmNative = our native theme engine<br>The ''intfThemes'' unit is now deprecated.<br>LMDSetCtlXP helper method, which was defined in ''intfThemes'', is replaced by LMDSetThemeMode, defined in ''LMDThemes'' unit:<br>
Wherever it is possible, system ''Themes'' and ''UxTheme'' units are used.<br>
+
<syntaxhighlight lang="delphi">procedure LMDSetThemeMode(aParent: TWinControl; const Value: TLMDThemeMode);overload;
CtlXP property is now deprecated (was moved to public), it is no longer used and remains only for  
+
procedure LMDSetThemeMode(aParent: TCustomForm; const Value: TLMDThemeMode);overload;</syntaxhighlight>
 
 
compatibility reasons. ThemeMode (of TLMDThemeMode type, defined in LMDClass unit) property introduced  
 
 
 
to be used instead of CtlXP. <br>
 
 
 
Type '''TLMDThemeMode''' = (ttmNone, ttmPlatform, ttmNative):
 
 
 
ttmNone = No global themeing, use control settings
 
ttmPlatform = CtlXP or UseXPThemes
 
ttmNative = our native theme engine
 
 
 
The ''intfThemes'' unit is now deprecated.  
 
 
 
LMDSetCtlXP helper method, which was defined in ''intfThemes'', is replaced by LMDSetThemeMode, defined  
 
 
 
in ''LMDThemes'' unit:
 
 
 
  procedure LMDSetThemeMode(aParent: TWinControl; const Value: TLMDThemeMode);overload;
 
  procedure LMDSetThemeMode(aParent: TCustomForm; const Value: TLMDThemeMode);overload;
 
 
 
 
 
 
The call<br>
 
The call<br>
 
+
<syntaxhighlight lang="delphi">LMDSetCtlXP (self, true);</syntaxhighlight>
<delphi>
 
      LMDSetCtlXP (self, true);
 
</delphi>
 
 
 
 
must be replaced by<br>
 
must be replaced by<br>
<delphi>
+
<syntaxhighlight lang="delphi">LMDSetThemeMode(self, ttmPlatform);</syntaxhighlight>
      LMDSetThemeMode(self, ttmPlatform)
+
The call like<br>
</delphi>  
+
<syntaxhighlight lang="delphi">LMDSetCtlXP (self, false);</syntaxhighlight>
The call like<bR>
 
<delphi>
 
      LMDSetCtlXP (self, false);
 
</delphi>
 
 
must be replaced by<br>
 
must be replaced by<br>
<delphi>
+
<syntaxhighlight lang="delphi">LMDSetThemeMode(self, ttmNone);</syntaxhighlight>
      LMDSetThemeMode(self, ttmNone);
 
</delphi>
 
  
 
=== Changes to component code ===
 
=== Changes to component code ===
  
A standard example for replacing code:
+
A standard example for replacing code:  
<delphi>
+
 
        if UseXP or (LMDApplication.UseXPThemes and (Bevel.Mode=bmWindows)) then
+
<syntaxhighlight lang="delphi">
          begin
+
if UseXP or (LMDApplication.UseXPThemes and (Bevel.Mode=bmWindows)) then
            aPartId := PP_BAR;
+
begin
            if Direction in [mdVertical, mdVerticalReverse] then
+
    aPartId&nbsp;:= PP_BAR;
              aPartId := PP_BARVERT;
+
    if Direction in [mdVertical, mdVerticalReverse] then
            DrawThemeBackGround (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, nil);
+
        aPartId&nbsp;:= PP_BARVERT;
            {$ifdef CLR}
+
   
            GetThemeBackgroundContentRect (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, FRect);
+
    DrawThemeBackGround (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, nil);
            {$else ifdef CLR}
+
    {$ifdef CLR}
            GetThemeBackgroundContentRect (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, {$IFDEF LMDDISABLE_LMDTHEMES}@{$ENDIF}FRect);
+
    GetThemeBackgroundContentRect (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, FRect);
            {$endif ifdef CLR}
+
    {$else ifdef CLR}
          end
+
    GetThemeBackgroundContentRect (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, {$IFDEF LMDDISABLE_LMDTHEMES}@{$ENDIF}FRect);
</delphi>
+
    {$endif ifdef CLR}
changes now to:
+
end
<delphi>  
+
 
        lThemeMode := UseThemeMode;   // store current ThemeMode locally when it is used more than once
+
</syntaxhighlight>changes now to:
        if (lThemeMode <> ttmNone) then   // same as IsThemed, because UseThemeMode was already determined, this is faster  
+
 
          begin
+
<syntaxhighlight lang="delphi">
            if Direction in [mdVertical, mdVerticalReverse] then
+
lThemeMode&nbsp;:= UseThemeMode; // store current ThemeMode locally when it is used more than once
              Details := tpBarVert
+
if (lThemeMode &lt;&gt; ttmNone) then // same as IsThemed, because UseThemeMode was already determined, this is faster  
            else
+
begin
              Details := tpBar;
+
    if Direction in [mdVertical, mdVerticalReverse] then
            LMDThemeServices.DrawElement(lThemeMode, Canvas.Handle, Details, FRect);
+
        Details&nbsp;:= tpBarVert
            FRect := LMDThemeServices.ContentRect(lThemeMode, Canvas.Handle, ThemeServices.GetElementDetails(Details), FRect);
+
    else
          end
+
        Details&nbsp;:= tpBar;
</delphi>
+
    LMDThemeServices.DrawElement(lThemeMode, Canvas.Handle, Details, FRect);
 +
    FRect&nbsp;:= LMDThemeServices.ContentRect(lThemeMode, Canvas.Handle, ThemeServices.GetElementDetails(Details), FRect);
 +
end
 +
</syntaxhighlight>
 
As one can see, code becomes much more cleaner and readable. Notes:
 
As one can see, code becomes much more cleaner and readable. Notes:
* All ThemeModes <> ttmNone are handled by LMDThemeServices.
+
 
 +
* All ThemeModes &lt;&gt; ttmNone are handled by LMDThemeServices.
 
* UseThemeMode takes care to check whether a specific thememode is available. It will automatically provide least possible theme mode, e.g. ttmNone on Win98 systems if ThemeMode = ttmPlatform.
 
* UseThemeMode takes care to check whether a specific thememode is available. It will automatically provide least possible theme mode, e.g. ttmNone on Win98 systems if ThemeMode = ttmPlatform.
* Take GlobalThemeMode intto account. GlobalThemeMode allows programmer to change ThemeMode for complete application with one boolean property.
+
* Take GlobalThemeMode into account. GlobalThemeMode allows programmer to change ThemeMode for complete application with one boolean property.
 
* LMDApplication.UseXPThemes is only available for compatibility, never use it in new code (use LMDThemeService methods)
 
* LMDApplication.UseXPThemes is only available for compatibility, never use it in new code (use LMDThemeService methods)
* Use LMDPtrToRect, LMDRectToPtr methods for PRect/IntPtr variables (to avoid {$IFNDEF CRL}@{$ENDIF} code).  
+
* Use LMDPtrToRect, LMDRectToPtr methods for PRect/IntPtr variables (to avoid {$IFNDEF CRL}@{$ENDIF} code).
  
 
=== Changes to native theme engine ===
 
=== Changes to native theme engine ===
  
Native theme engine is available now as a standalone package LMD Themes Pack. No compiler switches are  
+
Native theme engine is available now as a standalone package LMD Themes Pack. No compiler switches are needed to enable/disable native theme engine.<br>Components '''TLMDThemeEngineController''' and '''TLMDFormThemeProvider''' moved to LMD Themes Pack. Theme engine can load only one theme at a time, LoadTheme methods removed. This allowed to simplify code greately.<br>'''TLMDThemeEngine''' is now a descendand of '''TLMDThemeRenderer''' class.<br>''ActivateColorScheme'' method added:<br>
needed to enable/disable native theme engine.<br>
+
<syntaxhighlight lang="delphi">function ActivateColorScheme(ColorScheme: WideString = ''): boolean;</syntaxhighlight>
Components '''TLMDThemeEngineController''' and '''TLMDFormThemeProvider''' moved to LMD Themes Pack.
+
'''TLMDThemeEngine''' methods return (where applicable) boolean values (true if succeeded, false if failed) instead of HRESULT values.<br>'''Note:''' The behaviour of ''ActivateTheme''method changed. In previous version, if LMDThemeEngine.Enabled was false, then ActivateTheme failed. In new version, ActivateTheme method can be called even if theme engine is disabled, and, if succeeded, it activates theme engine, too.
Theme engine can load only one theme at a time, LoadTheme methods removed. This allowed to simplify code  
 
greately.<br>
 
 
 
'''TLMDThemeEngine''' is now a descendand of '''TLMDThemeRenderer''' class.<br>
 
''ActivateColorScheme'' method added:<br>
 
<delphi>
 
    function ActivateColorScheme(ColorScheme: WideString = ''): boolean;
 
</delphi>
 
 
 
TLMDThemeEngine methods return (where applicable) boolean value (true if succeeded, false if failed)  
 
instead of HRESULT value.<br>
 

Latest revision as of 13:03, 18 August 2017

<< Back to Getting started or Product Resources page

[edit]

Overview

From LMD-Tools 2009 releases we introduce new approach to Theme Engine. This approach aims at following main goals:

  • Basic theme engine causes no or only small overhead (by using System Themes support of Delphi, which is integrated since Delphi 7);
  • Management of any calls for internal theme services is centralized;
  • No theme related switches and recompilation of library code, but a separate package which you can decide to use or not at runtime;
  • Possibility of using custom theme and system theme simultaneously.

The entry point for new theme services is now LMDThemes unit.
This unit introduces TLMDThemeRenderer and TLMDThemeServices classes, LMDThemeServices (global method to access a singleton instance of TLMDThemeServices class), some helper methods like LMDSetThemeMode, and a number of theme related constants.
TLMDThemeRenderer class is an abstract ancestor class for any custom theme renderers.
TLMDThemeServices class provides centralized and unified access to theme rendering routines.

Changes from LMD-Tools 2007 version of theme services

General changes

LMDXPStyles and LMDXPThemeManager units removed.
Wherever it is possible, system Themes and UxTheme units are used.
CtlXP property is now deprecated (moved to public), it is no longer used and remains only for compatibility reasons. ThemeMode (of TLMDThemeMode type, defined in LMDClass unit) property introduced to be used instead of CtlXP.
Type TLMDThemeMode = (ttmNone, ttmPlatform, ttmNative):
ttmNone = No global themeing, use control settings
ttmPlatform = CtlXP or UseXPThemes
ttmNative = our native theme engine
The intfThemes unit is now deprecated.
LMDSetCtlXP helper method, which was defined in intfThemes, is replaced by LMDSetThemeMode, defined in LMDThemes unit:

procedure LMDSetThemeMode(aParent: TWinControl; const Value: TLMDThemeMode);overload;
 procedure LMDSetThemeMode(aParent: TCustomForm; const Value: TLMDThemeMode);overload;

The call

LMDSetCtlXP (self, true);

must be replaced by

LMDSetThemeMode(self, ttmPlatform);

The call like

LMDSetCtlXP (self, false);

must be replaced by

LMDSetThemeMode(self, ttmNone);

Changes to component code

A standard example for replacing code:

 if UseXP or (LMDApplication.UseXPThemes and (Bevel.Mode=bmWindows)) then
 begin
     aPartId&nbsp;:= PP_BAR;
     if Direction in [mdVertical, mdVerticalReverse] then
        aPartId&nbsp;:= PP_BARVERT;
     
     DrawThemeBackGround (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, nil);
     {$ifdef CLR}
     GetThemeBackgroundContentRect (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, FRect);
     {$else ifdef CLR}
     GetThemeBackgroundContentRect (LMDThemeService.Theme[tiProgress], Canvas.Handle, aPartId, 0, FRect, {$IFDEF LMDDISABLE_LMDTHEMES}@{$ENDIF}FRect);
     {$endif ifdef CLR}
 end
changes now to:
 lThemeMode&nbsp;:= UseThemeMode; // store current ThemeMode locally when it is used more than once
 if (lThemeMode &lt;&gt; ttmNone) then // same as IsThemed, because UseThemeMode was already determined, this is faster 
 begin
     if Direction in [mdVertical, mdVerticalReverse] then
        Details&nbsp;:= tpBarVert
     else
        Details&nbsp;:= tpBar;
     LMDThemeServices.DrawElement(lThemeMode, Canvas.Handle, Details, FRect);
     FRect&nbsp;:= LMDThemeServices.ContentRect(lThemeMode, Canvas.Handle, ThemeServices.GetElementDetails(Details), FRect);
 end

As one can see, code becomes much more cleaner and readable. Notes:

  • All ThemeModes <> ttmNone are handled by LMDThemeServices.
  • UseThemeMode takes care to check whether a specific thememode is available. It will automatically provide least possible theme mode, e.g. ttmNone on Win98 systems if ThemeMode = ttmPlatform.
  • Take GlobalThemeMode into account. GlobalThemeMode allows programmer to change ThemeMode for complete application with one boolean property.
  • LMDApplication.UseXPThemes is only available for compatibility, never use it in new code (use LMDThemeService methods)
  • Use LMDPtrToRect, LMDRectToPtr methods for PRect/IntPtr variables (to avoid {$IFNDEF CRL}@{$ENDIF} code).

Changes to native theme engine

Native theme engine is available now as a standalone package LMD Themes Pack. No compiler switches are needed to enable/disable native theme engine.
Components TLMDThemeEngineController and TLMDFormThemeProvider moved to LMD Themes Pack. Theme engine can load only one theme at a time, LoadTheme methods removed. This allowed to simplify code greately.
TLMDThemeEngine is now a descendand of TLMDThemeRenderer class.
ActivateColorScheme method added:

function ActivateColorScheme(ColorScheme: WideString = ''): boolean;

TLMDThemeEngine methods return (where applicable) boolean values (true if succeeded, false if failed) instead of HRESULT values.
Note: The behaviour of ActivateThememethod changed. In previous version, if LMDThemeEngine.Enabled was false, then ActivateTheme failed. In new version, ActivateTheme method can be called even if theme engine is disabled, and, if succeeded, it activates theme engine, too.