Difference between revisions of "LMDThemes GradientRenderer"
(23 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
− | |||
− | |||
== Overview == | == Overview == | ||
− | === New units === | + | === New units in LMDRtlx === |
− | The new gradient theme engine was intended to implement themes imitating Office 2007 look. Actually it allows to build and use a wider variety of themes. It uses universal and | + | '''The new gradient theme engine''' was intended to implement themes imitating Office 2007/2010 look. Actually it allows to build and use a wider variety of themes. It uses universal and flexible architecture of gradient fillers which allows to combine complex configurations of gradients. |
− | + | These configurations, from the simplest to complex are:<br>- Solid filler;<br>- Gradient filler;<br>- Composition of fillers (any number of rectangular areas);<br>- Mix of fillers, where each filler in a blend has its weight;<br>- Mix of composition of fillers.<br> | |
− | + | In order to implement the new renderer, we added several new graphical units, which can also be used separately. These are: LMDFillers, LMDFigures, LMDGradientFrames. | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | In order to implement the new renderer, we added several new graphical units, which can also be used separately. These are: | ||
− | LMDFillers, LMDFigures, LMDGradientFrames. | ||
==== LMDFillers ==== | ==== LMDFillers ==== | ||
− | LMDFillers unit contains base TLMDFiller class and its descendants for painting surfaces and borders of figures: - TLMDSolidFiller (floodfills figure with given color);<br> - TLMDVerticalGradient, TLMDHorizontalGradient, TLMDEllipseFiller, TLMDRoundFiller, TLMDLineFiller, TLMDRectangleFiller, TLMDBandFiller (floodfills figure with a given gradient);<br> - TLMDCompositeFiller (floodfilles rectangular areas with given gradients);<br> - TLMDMixedFillers (floodfills figure with a blend of gradients). | + | LMDFillers unit contains base TLMDFiller class and its descendants for painting surfaces and borders of figures:<br>- TLMDSolidFiller (floodfills figure with given color);<br>- TLMDVerticalGradient, TLMDHorizontalGradient, TLMDEllipseFiller, TLMDRoundFiller, TLMDLineFiller, TLMDRectangleFiller, TLMDBandFiller (floodfills figure with a given gradient);<br>- TLMDCompositeFiller (floodfilles rectangular areas with given gradients);<br>- TLMDMixedFillers (floodfills figure with a blend of gradients). |
==== LMDFigures ==== | ==== LMDFigures ==== | ||
− | LMDFigures unit contains TLMDFigure class and its descendants:<br> -TLMDRectangle, TLMDCustomCutRectangle, TLMDRoundRectangle;<br>-TLMDLine;<br>-TLMDEllipse, TLMDCircle;<br>-TLMDUnionFigure, TLMDSubtractionFigure. | + | LMDFigures unit contains TLMDFigure class and its descendants:<br>-TLMDRectangle, TLMDCustomCutRectangle, TLMDRoundRectangle;<br>-TLMDLine;<br>-TLMDEllipse, TLMDCircle;<br>-TLMDUnionFigure, TLMDSubtractionFigure. |
==== LMDGradientFrames ==== | ==== LMDGradientFrames ==== | ||
Line 33: | Line 23: | ||
-TLMDGradientRectFrame draws rectangular frames consisting of three parts (outer border, inner space, inner border). These frames can have three types of corners: rectangular, | -TLMDGradientRectFrame draws rectangular frames consisting of three parts (outer border, inner space, inner border). These frames can have three types of corners: rectangular, | ||
− | round and line. Each corner of a frame can have its own cut type.<br> | + | round and line. Each corner of a frame can have its own cut type.<br>-TLMDGradientCircleFrame draws round frames consisting of three parts (outer border, inner space, inner border).<br>-TLMDGradientCmpFrame draws complex frames consisting of three sets of parts: outer borders parts, inner space parts and inner border parts, each set of parts consists of 4 sides and 4 corners. This class is not used for rendering Office2007-like themes.<br><br> |
− | -TLMDGradientCircleFrame draws round frames consisting of three parts (outer border, inner space, inner border).<br> | + | |
− | -TLMDGradientCmpFrame draws complex frames consisting of three sets of parts: outer borders parts, inner space parts and inner border parts, each set of parts consists of 4 sides | + | === New units in LMD ThemesPack === |
− | + | The new renderer is implemented in LMDThemesGradientThemeBase unit which contains main base class TLMDBaseGradientThemeRenderer. The LMDThemesGradientThemeRenderer introduces no functionality - it is used for registering engine for using by application.<Br> | |
=== Functionality === | === Functionality === | ||
− | The new renderer<br> | + | The new renderer<br>- implements interface declared in TLMDThemeServices class (LMDThemes unit);<br>- allows to use Office2007-like themes (three built-in color schemes: blue, metallic, black);<br>- allows to get access to its settings via helper properties;<br>- allows to change colors and brightness for several elements at a time;<br>- can store themes in XML file;<br>- can read themes from XML file and from CAB file (if it contains XML theme file).<br> |
− | - implements interface declared in TLMDThemeServices class (LMDThemes unit);<br> | ||
− | - allows to use Office2007-like themes (three built-in color schemes: blue, metallic, black);<br> | ||
− | - allows to get access to its settings via helper properties;<br> | ||
− | - allows to change colors and brightness for several elements at a time;<br> | ||
− | - can store themes in XML file;<br> | ||
− | - can read themes from XML file and from CAB file (if it contains XML theme file).<br> | ||
=== Structure === | === Structure === | ||
Each themed element has two arrays of corresponding descriptors, array of fill descriptors and array of frame descriptors:<br> | Each themed element has two arrays of corresponding descriptors, array of fill descriptors and array of frame descriptors:<br> | ||
− | + | <syntaxhighlight lang="delphi">ButtonFill: array[TThemedButton] of TLMDGradientThemeFillDescriptor; | |
− | < | + | ButtonFrame: array[TThemedButton] of TLMDGradientThemeFrameDescriptor;</syntaxhighlight> |
− | ButtonFill: | + | Also, themed element can have array of text descriptors, but in current version text descriptor is used only for setting colors of font in tab text (for teTab element).<br>A gradient theme descriptor is a record that consists of parameters section and filler section: |
− | ButtonFrame: array[TThemedButton] of TLMDGradientThemeFrameDescriptor; | + | <syntaxhighlight lang="delphi">type |
− | </ | + | TLMDGradientThemeFillDescriptor = record |
− | |||
− | Also, themed element can have array of text descriptors, but in current version text descriptor is used only for setting colors of font in tab text (for teTab element).<br> | ||
− | A gradient theme descriptor is a record that consists of parameters section and filler section: | ||
− | |||
− | < | ||
− | type | ||
− | |||
Params: TLMDGradientThemeFillParams; | Params: TLMDGradientThemeFillParams; | ||
Fillers: array[TLMDGradientFillPart] of TLMDFiller; | Fillers: array[TLMDGradientFillPart] of TLMDFiller; | ||
− | + | end; | |
type | type | ||
− | + | TLMDGradientThemeFrameDescriptor = record | |
Params: TLMDGradientThemeFrameParams; | Params: TLMDGradientThemeFrameParams; | ||
Fillers: array[TLMDGradientSFramePart] of TLMDFiller; | Fillers: array[TLMDGradientSFramePart] of TLMDFiller; | ||
− | + | end; | |
− | </ | + | </syntaxhighlight> |
− | + | A fill descriptor determines how element's inner area is painted, whereas a frame descriptor determines how element's frame is painted.<br> | |
− | A fill descriptor determines how element's inner | ||
== Usage == | == Usage == | ||
− | === Loading and | + | === Loading, activating and deactivating themes === |
− | Nothing was changed here: in order to use the new renderer you have to put a reference to LMDThemesGradientThemeRenderer unit somewhere in your application. | + | Nothing was changed here: in order to use the new renderer you have to put a reference to LMDThemesGradientThemeRenderer unit somewhere in your application. Initialization section of this unit registers renderer so that application can use it for painting controls with ThemeMode = ttmNative. When renderer is active, active theme and color scheme can be changed by loading theme from file |
− | Initialization section of this unit registers renderer so that application can use it for painting controls with ThemeMode = ttmNative. | ||
− | When renderer is active, active theme and color scheme can be changed by loading theme from file | ||
− | + | LMDThemeServices.ActivateTheme('Office2007.cab', 'Metallic'); | |
or by activating built-in color scheme: | or by activating built-in color scheme: | ||
− | + | LMDThemeServices.ActivateColorScheme('Black'); | |
+ | |||
+ | |||
+ | In order to deactivate native theme and switch to current system theme | ||
− | |||
− | + | , simply call LMDThemeServices.DeactivateTheme method. | |
− | === Mass changing methods === | + | === Changing colors and other params in run-time === |
+ | |||
+ | ==== Mass changing methods ==== | ||
There are three methods that allow to change colors for several themed elements/details at a time: | There are three methods that allow to change colors for several themed elements/details at a time: | ||
− | < | + | <syntaxhighlight lang="delphi">procedure ChangeBrightness(aPercent: integer; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = -1); |
− | procedure ChangeBrightness(aPercent: integer; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = -1); | ||
procedure ReplaceColor(aOldColor, aNewColor: TColor; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = -1); | procedure ReplaceColor(aOldColor, aNewColor: TColor; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = -1); | ||
− | procedure SetNewColor(aNewColor: TColor; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = 0); | + | procedure SetNewColor(aNewColor: TColor; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = 0);</syntaxhighlight> |
− | </ | ||
Each of these methods walks through all fillers for given element, given detail name mask, fill or frame part and performs required change. <br> | Each of these methods walks through all fillers for given element, given detail name mask, fill or frame part and performs required change. <br> | ||
Line 111: | Line 87: | ||
Examples: | Examples: | ||
− | < | + | <syntaxhighlight lang="delphi">//walks through all fillers for teTab element, for details like 'ttTopTabItem*' |
//and sets new color for each FixedColors entry with index 0 | //and sets new color for each FixedColors entry with index 0 | ||
SetNewColor($0000FFFF, [teTab], 'ttTopTabItemHot*', [gfpMain], [], 0); | SetNewColor($0000FFFF, [teTab], 'ttTopTabItemHot*', [gfpMain], [], 0); | ||
Line 119: | Line 95: | ||
//Changes brightness of all colors: | //Changes brightness of all colors: | ||
− | ChangeBrightness(-10, []);</ | + | ChangeBrightness(-10, []);</syntaxhighlight> |
− | + | ==== Direct access to colors and filler properties ==== | |
− | === Direct access to colors and filler properties === | ||
− | Properties like *FillFiller, *FrameFiller allow to get direct access to fillers. Using them requires knowledge of how the filler is structured. Filler structure can be browsed in XML file. For | + | Properties like *FillFiller, *FrameFiller allow to get direct access to fillers. Using them requires knowledge of how the filler is structured. Filler structure can be browsed in XML file. For |
Office2007-like themes a filler is usually either solid filler, vertical/horizontal/elliptic gradient, composite filler of a mixed filler.<br> | Office2007-like themes a filler is usually either solid filler, vertical/horizontal/elliptic gradient, composite filler of a mixed filler.<br> | ||
− | |||
− | |||
For example, this is how we can change start gradient color for teTab element, detail ttTopTabItemHot: | For example, this is how we can change start gradient color for teTab element, detail ttTopTabItemHot: | ||
− | + | <syntaxhighlight lang="delphi">with CThemeRenderer do | |
− | < | + | TLMDCompositeFiller(TLMDMixedFiller(TabFillFiller[ttTopTabItemHot, gfpMain]).Item[0]).Item[0].FixedColors[0] := clRed;</syntaxhighlight> |
− | |||
− | |||
− | </ | ||
− | |||
This is rather complex construction because the filler in this case is a mix of composite filler and elliptic gradient: | This is rather complex construction because the filler in this case is a mix of composite filler and elliptic gradient: | ||
− | + | <syntaxhighlight lang="xml"> | |
− | < | + | <Filler Class="TLMDMixedFiller" Part="gfpMain" ItemCount="2"> |
− | + | <UseRelativeUnits Value="1"/> | |
− | + | <Item Index="0" Weight="255"> | |
− | + | <Filler Class="TLMDCompositeFiller" ItemCount="2"> | |
− | + | <UseRelativeUnits Value="1"/> | |
− | + | <Item Index="0"> | |
− | + | <FillerRect Left="0" Top="0" Right="100" Bottom="45"/> | |
− | + | <Filler Class="TLMDVerticalGradient"> | |
− | + | <Colors ColorCount="2"> | |
− | + | <Color0 Value="$00FEDDC4"/> | |
− | + | <Color1 Value="clWhite"/> | |
− | + | </Colors> | |
− | + | </Filler> | |
− | + | </Item> | |
− | + | <Item Index="1"> | |
− | + | <FillerRect Left="0" Top="45" Right="100" Bottom="100"/> | |
− | + | <Filler Class="TLMDVerticalGradient"> | |
− | + | <Colors ColorCount="2"> | |
− | + | <Color0 Value="$00FEDDC4"/> | |
− | + | <Color1 Value="clWhite"/> | |
− | + | </Colors> | |
− | + | </Filler> | |
− | + | </Item> | |
− | + | </Filler> | |
− | + | </Item> | |
− | + | <Item Index="1" Weight="255"> | |
− | + | <Filler Class="TLMDEllipseFiller"> | |
− | + | <UseRelativeUnits Value="1"/> | |
− | + | <BasePoint X="50" Y="0"/> | |
− | + | <Axis1 Value="80"/> | |
− | + | <Axis2 Value="80"/> | |
− | + | <FirstAxisDirection X="1" Y="0"/> | |
− | + | <Colors ColorCount="2"> | |
− | + | <Color0 Value="$00FEDDC4"/> | |
− | + | <Color1 Value="$0098D1E3"/> | |
− | + | </Colors> | |
− | + | </Filler> | |
− | + | </Item> | |
− | + | </Filler> | |
− | + | </syntaxhighlight> | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | </ | ||
So, we have to take filler for main fill part (gfpMain index), ttTopTabItemHot detail:<br> | So, we have to take filler for main fill part (gfpMain index), ttTopTabItemHot detail:<br> | ||
− | < | + | <syntaxhighlight lang="delphi">TabFillFiller[ttTopTabItemHot, gfpMain]</syntaxhighlight> |
− | + | then cast it to TLMDMixedFiller and take the first item, which is a composite filler: | |
− | </ | + | <syntaxhighlight lang="delphi">TLMDMixedFiller( * ).Item[0])</syntaxhighlight> |
− | |||
− | then cast it to | ||
− | < | ||
− | |||
− | </ | ||
then cast it to TLMDCompositeFiller and take the first item which is a vertical gradient, and change the first color: | then cast it to TLMDCompositeFiller and take the first item which is a vertical gradient, and change the first color: | ||
− | < | + | <syntaxhighlight lang="delphi">TLMDCompositeFiller( * ).Item[0].FixedColors[0] := clRed;</syntaxhighlight> |
− | |||
− | </ | ||
+ | ==== Changing other filler properties ==== | ||
− | + | Each filler has BasePoint property which determines the coordinate origin for filler. Example:<br> | |
− | + | <syntaxhighlight lang="delphi">with CThemeRenderer do | |
− | Each filler has BasePoint property which determines the coordinate origin for filler. | + | begin |
− | Example:<br> | + | //This will change base point of ellipse gradient filler (bottom part of the filler) |
− | < | + | //Coordinates are relative to rectangle of the element: (100, 100) is |
− | + | //the bottom right corner | |
− | + | TLMDCompositeFiller(ButtonFillFiller[tbPushButtonPressed, gfpMain]).Item[1].BasePoint := Point(100, 100); | |
− | + | TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[1].BasePoint := Point(0, 100); | |
− | + | end;</syntaxhighlight> | |
− | + | === Parameters - detailed description === | |
− | |||
− | |||
− | |||
− | </ | ||
− | |||
− | ===Parameters - detailed description=== | ||
Parameters section is a simple one for fill descriptors and rather complex for frame descriptors. However, each parameter is a byte. | Parameters section is a simple one for fill descriptors and rather complex for frame descriptors. However, each parameter is a byte. | ||
Line 223: | Line 172: | ||
==== Fill descriptors ==== | ==== Fill descriptors ==== | ||
− | Here we have one parameter: gflpRenderMode (prefix gflp: | + | Here we have one parameter: gflpRenderMode (prefix gflp: '''g'''radient '''f'''il'''l''' '''p'''arameter) |
− | < | + | <syntaxhighlight lang="delphi">type |
− | TLMDGradientThemeFillParam = (gflpRenderMode);</ | + | TLMDGradientThemeFillParam = (gflpRenderMode);</syntaxhighlight> |
− | + | Bits 0..1: 0 - standard, 1 - sketch, 2 and 3 - reserved; | |
− | + | Bit 2 - antialiasing for gfpMain; | |
− | + | Bits 3..6 - antialiasing for gfpDeco1..gfpDeco4. | |
− | + | Standard value is 4: 0000 0010. | |
==== Frame descriptors ==== | ==== Frame descriptors ==== | ||
− | Here we have a lot of parameters (prefix gfrp: | + | Here we have a lot of parameters (prefix gfrp: '''g'''radient '''fr'''ame '''p'''arameter).<br>Most of frame parameters relate to determining how corners of a frame should look. For custom cut rectangle, CutX and CutY are the values that, along with corner cut type, determine how corner looks. E.g. here is a round-cut corner with its CutX and CutY values:<br>[[Image:Cutxy.PNG|Image:cutxy.PNG]] |
− | <br>Since there are three possible areas of a frame (outer border, inner space and inner border), each of which can have its own corners description, the number of | + | <br>Since there are three possible areas of a frame (outer border, inner space and inner border), each of which can have its own corners description, the number of parameters section of a frame descriptor is about 40: |
− | + | <syntaxhighlight lang="delphi">type | |
− | |||
− | < | ||
TLMDGradientThemeFrameParam = | TLMDGradientThemeFrameParam = | ||
( | ( | ||
Line 314: | Line 261: | ||
//value types for inner border cut values | //value types for inner border cut values | ||
gfrpInnerBorderOuterCutXValueType, gfrpInnerBorderOuterCutYValueType, | gfrpInnerBorderOuterCutXValueType, gfrpInnerBorderOuterCutYValueType, | ||
− | gfrpInnerBorderInnerCutXValueType, gfrpInnerBorderInnerCutYValueType);</ | + | gfrpInnerBorderInnerCutXValueType, gfrpInnerBorderInnerCutYValueType);</syntaxhighlight> |
+ | |||
+ | === Code samples === | ||
+ | |||
+ | ==== Delphi ==== | ||
+ | ''Changing outer border of a push button''<br> | ||
+ | <syntaxhighlight lang="delphi"> | ||
+ | cThemeRenderer := TLMDBaseGradientThemeRenderer(LMDThemeServices.CurrentRenderer); | ||
+ | with CThemeRenderer do | ||
+ | begin | ||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderWidth] := 2; | ||
+ | ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderWidth] := 2; | ||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderWidth] := 2; | ||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderWidth] := 2; | ||
+ | end; | ||
+ | LMDThemeServices.ApplyThemeChange; | ||
+ | </syntaxhighlight> | ||
+ | ''Changing outline of a push button''<br> | ||
+ | <syntaxhighlight lang="delphi"> | ||
+ | with CThemeRenderer do | ||
+ | begin | ||
+ | //See full list of frame params in LMDThemesGradientThemeBase unit | ||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners); | ||
+ | |||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderOuterCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderInnerCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpInnerBorderOuterCutX] := 7; | ||
+ | ButtonFrameParam[tbPushButtonNormal, gfrpInnerBorderInnerCutX] := 7; | ||
+ | |||
+ | ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderOuterCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderInnerCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonHot, gfrpInnerBorderOuterCutX] := 7; | ||
+ | ButtonFrameParam[tbPushButtonHot, gfrpInnerBorderInnerCutX] := 7; | ||
+ | |||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderOuterCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderInnerCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpInnerBorderOuterCutX] := 7; | ||
+ | ButtonFrameParam[tbPushButtonPressed, gfrpInnerBorderInnerCutX] := 7; | ||
+ | |||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderOuterCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderInnerCutX] := 6; | ||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpInnerBorderOuterCutX] := 7; | ||
+ | ButtonFrameParam[tbPushButtonDisabled, gfrpInnerBorderInnerCutX] := 7; | ||
+ | end; | ||
+ | LMDThemeServices.ApplyThemeChange; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ''Changing base point of an elliptic gradient of a push button''<br> | ||
+ | <syntaxhighlight lang="delphi"> | ||
+ | with CThemeRenderer do | ||
+ | begin | ||
+ | TLMDCompositeFiller(ButtonFillFiller[tbPushButtonPressed, gfpMain]).Item[1].BasePoint := Point(100, 100); | ||
+ | TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[1].BasePoint := Point(0, 100); | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ''Adding third gradient area for a push button''<br> | ||
+ | <syntaxhighlight lang="delphi"> | ||
+ | with CThemeRenderer do | ||
+ | begin | ||
+ | with TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]) do | ||
+ | begin | ||
+ | Add(TLMDVerticalGradient.Create); | ||
+ | FillerRect[0] := Rect(0, 0, 100, 10); | ||
+ | FillerRect[1] := Rect(0, 10, 100, 80); | ||
+ | FillerRect[2] := Rect(0, 80, 100, 100); | ||
+ | Item[2].FixedColors[0] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[0].FixedColors[1]; | ||
+ | Item[2].FixedColors[1] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[0].FixedColors[0]; | ||
+ | end; | ||
+ | |||
+ | with TLMDCompositeFiller(ButtonFillFiller[tbPushButtonPressed, gfpMain]) do | ||
+ | begin | ||
+ | Add(TLMDVerticalGradient.Create); | ||
+ | FillerRect[0] := Rect(0, 0, 100, 10); | ||
+ | FillerRect[1] := Rect(0, 10, 100, 85); | ||
+ | FillerRect[2] := Rect(0, 85, 100, 100); | ||
+ | Item[2].FixedColors[0] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[2].FixedColors[0]; | ||
+ | Item[2].FixedColors[1] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[2].FixedColors[1]; | ||
+ | end; | ||
+ | |||
+ | with TLMDCompositeFiller(ButtonFillFiller[tbPushButtonNormal, gfpMain]) do | ||
+ | begin | ||
+ | Add(TLMDVerticalGradient.Create); | ||
+ | FillerRect[0] := Rect(0, 0, 100, 10); | ||
+ | FillerRect[1] := Rect(0, 10, 100, 85); | ||
+ | FillerRect[2] := Rect(0, 85, 100, 100); | ||
+ | Item[2].FixedColors[0] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonNormal, gfpMain]).Item[0].FixedColors[1]; | ||
+ | Item[2].FixedColors[1] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonNormal, gfpMain]).Item[0].FixedColors[0]; | ||
+ | end; | ||
+ | end; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== C++ Builder ==== | ||
+ | ''Changing hot tab colors of LMDPageControl'' | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | TLMDBaseGradientThemeRenderer *cThemeRenderer; | ||
+ | TLMDFiller *filler; | ||
+ | TLMDCompositeFiller *cfiller; | ||
+ | TLMDMixedFiller *mfiller; | ||
+ | |||
+ | cThemeRenderer = (TLMDBaseGradientThemeRenderer*)LMDThemeServices()->CurrentRenderer; | ||
+ | cThemeRenderer->SetNewColor( | ||
+ | 0x0000FFFF, | ||
+ | Lmdthemescommontypes::TThemedElementSet() << teTab, | ||
+ | "ttTopTabItemHot", | ||
+ | TLMDGradientFillParts() << gfpMain, | ||
+ | Lmdgradientframes::TLMDGradientSimpleFramePartKinds(), | ||
+ | 0 | ||
+ | ); | ||
+ | filler = cThemeRenderer->TabFillFiller[ttTopTabItemHot][gfpMain]; | ||
+ | mfiller = (TLMDMixedFiller*)filler; | ||
+ | cfiller = (TLMDCompositeFiller*)(mfiller->Item[0]); | ||
+ | cfiller->Item[0]->FixedColors[0] = clRed; | ||
+ | </syntaxhighlight> | ||
== Screenshots == | == Screenshots == | ||
Line 324: | Line 391: | ||
=== ElXTree, ElToolBar and LMDButtonBar === | === ElXTree, ElToolBar and LMDButtonBar === | ||
− | '''With blue color scheme'''<br>[[Image:Office2007blue elpack.png|Image:office2007blue_elpack.png]]<br> | + | |
− | '''With black color scheme'''<br>[[Image:Office2007black elpack.png|Image:office2007black_elpack.png]]<br> | + | '''With blue color scheme'''<br>[[Image:Office2007blue elpack.png|Image:office2007blue_elpack.png]]<br>'''With black color scheme'''<br>[[Image:Office2007black elpack.png|Image:office2007black_elpack.png]]<br> |
=== Changing colors at runtime === | === Changing colors at runtime === | ||
− | [[Image:Office2007blue changecolors.png|Image:office2007blue_changecolors.png]] | + | '''Third gradient area added for push buttons, tab colors modified'''<br>[[Image:Office2007blue changecolors.png|Image:office2007blue_changecolors.png]]<br>'''Base point changed for push buttons'''<br>[[Image:Office2007darkblue bpchanged.png|Image:office2007darkblue_bpchanged.png]]<br>'''Dark blue scheme (brightness -30%)'''<br>[[Image:Office2007darkblue moregrads.png|Image:office2007darkblue_moregrads.png]]<br> |
Latest revision as of 13:43, 18 August 2017
Contents
Overview
New units in LMDRtlx
The new gradient theme engine was intended to implement themes imitating Office 2007/2010 look. Actually it allows to build and use a wider variety of themes. It uses universal and flexible architecture of gradient fillers which allows to combine complex configurations of gradients.
These configurations, from the simplest to complex are:
- Solid filler;
- Gradient filler;
- Composition of fillers (any number of rectangular areas);
- Mix of fillers, where each filler in a blend has its weight;
- Mix of composition of fillers.
In order to implement the new renderer, we added several new graphical units, which can also be used separately. These are: LMDFillers, LMDFigures, LMDGradientFrames.
LMDFillers
LMDFillers unit contains base TLMDFiller class and its descendants for painting surfaces and borders of figures:
- TLMDSolidFiller (floodfills figure with given color);
- TLMDVerticalGradient, TLMDHorizontalGradient, TLMDEllipseFiller, TLMDRoundFiller, TLMDLineFiller, TLMDRectangleFiller, TLMDBandFiller (floodfills figure with a given gradient);
- TLMDCompositeFiller (floodfilles rectangular areas with given gradients);
- TLMDMixedFillers (floodfills figure with a blend of gradients).
LMDFigures
LMDFigures unit contains TLMDFigure class and its descendants:
-TLMDRectangle, TLMDCustomCutRectangle, TLMDRoundRectangle;
-TLMDLine;
-TLMDEllipse, TLMDCircle;
-TLMDUnionFigure, TLMDSubtractionFigure.
LMDGradientFrames
LMDGradientFrames unit contains TLMDBaseGradientFrame class and its descendants for painting different gradient frames:
-TLMDGradientRectFrame draws rectangular frames consisting of three parts (outer border, inner space, inner border). These frames can have three types of corners: rectangular,
round and line. Each corner of a frame can have its own cut type.
-TLMDGradientCircleFrame draws round frames consisting of three parts (outer border, inner space, inner border).
-TLMDGradientCmpFrame draws complex frames consisting of three sets of parts: outer borders parts, inner space parts and inner border parts, each set of parts consists of 4 sides and 4 corners. This class is not used for rendering Office2007-like themes.
New units in LMD ThemesPack
The new renderer is implemented in LMDThemesGradientThemeBase unit which contains main base class TLMDBaseGradientThemeRenderer. The LMDThemesGradientThemeRenderer introduces no functionality - it is used for registering engine for using by application.
Functionality
The new renderer
- implements interface declared in TLMDThemeServices class (LMDThemes unit);
- allows to use Office2007-like themes (three built-in color schemes: blue, metallic, black);
- allows to get access to its settings via helper properties;
- allows to change colors and brightness for several elements at a time;
- can store themes in XML file;
- can read themes from XML file and from CAB file (if it contains XML theme file).
Structure
Each themed element has two arrays of corresponding descriptors, array of fill descriptors and array of frame descriptors:
ButtonFill: array[TThemedButton] of TLMDGradientThemeFillDescriptor;
ButtonFrame: array[TThemedButton] of TLMDGradientThemeFrameDescriptor;
Also, themed element can have array of text descriptors, but in current version text descriptor is used only for setting colors of font in tab text (for teTab element).
A gradient theme descriptor is a record that consists of parameters section and filler section:
type
TLMDGradientThemeFillDescriptor = record
Params: TLMDGradientThemeFillParams;
Fillers: array[TLMDGradientFillPart] of TLMDFiller;
end;
type
TLMDGradientThemeFrameDescriptor = record
Params: TLMDGradientThemeFrameParams;
Fillers: array[TLMDGradientSFramePart] of TLMDFiller;
end;
A fill descriptor determines how element's inner area is painted, whereas a frame descriptor determines how element's frame is painted.
Usage
Loading, activating and deactivating themes
Nothing was changed here: in order to use the new renderer you have to put a reference to LMDThemesGradientThemeRenderer unit somewhere in your application. Initialization section of this unit registers renderer so that application can use it for painting controls with ThemeMode = ttmNative. When renderer is active, active theme and color scheme can be changed by loading theme from file
LMDThemeServices.ActivateTheme('Office2007.cab', 'Metallic');
or by activating built-in color scheme:
LMDThemeServices.ActivateColorScheme('Black');
In order to deactivate native theme and switch to current system theme
, simply call LMDThemeServices.DeactivateTheme method.
Changing colors and other params in run-time
Mass changing methods
There are three methods that allow to change colors for several themed elements/details at a time:
procedure ChangeBrightness(aPercent: integer; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = -1);
procedure ReplaceColor(aOldColor, aNewColor: TColor; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = -1);
procedure SetNewColor(aNewColor: TColor; aElements: TThemedElementSet = []; aDetailNameMask: string = ''; aFillParts: TLMDGradientFillParts = cGradientFillAllParts; aFrameParts: TLMDGradientSFrameParts = cGradientSFrameAllParts; aIndex: integer = 0);
Each of these methods walks through all fillers for given element, given detail name mask, fill or frame part and performs required change.
Note: ChangeBrightness and ReplaceColor apply change for all color entries starting from given index , whereas SetNewColor changes one color entry with a given index.
Examples:
//walks through all fillers for teTab element, for details like 'ttTopTabItem*'
//and sets new color for each FixedColors entry with index 0
SetNewColor($0000FFFF, [teTab], 'ttTopTabItemHot*', [gfpMain], [], 0);
//replaces each color entry with value $00F8E0CE by a new value $00F8D0BE
ReplaceColor($00F8E0CE, $00F8D0BE);
//Changes brightness of all colors:
ChangeBrightness(-10, []);
Direct access to colors and filler properties
Properties like *FillFiller, *FrameFiller allow to get direct access to fillers. Using them requires knowledge of how the filler is structured. Filler structure can be browsed in XML file. For
Office2007-like themes a filler is usually either solid filler, vertical/horizontal/elliptic gradient, composite filler of a mixed filler.
For example, this is how we can change start gradient color for teTab element, detail ttTopTabItemHot:
with CThemeRenderer do
TLMDCompositeFiller(TLMDMixedFiller(TabFillFiller[ttTopTabItemHot, gfpMain]).Item[0]).Item[0].FixedColors[0] := clRed;
This is rather complex construction because the filler in this case is a mix of composite filler and elliptic gradient:
<Filler Class="TLMDMixedFiller" Part="gfpMain" ItemCount="2">
<UseRelativeUnits Value="1"/>
<Item Index="0" Weight="255">
<Filler Class="TLMDCompositeFiller" ItemCount="2">
<UseRelativeUnits Value="1"/>
<Item Index="0">
<FillerRect Left="0" Top="0" Right="100" Bottom="45"/>
<Filler Class="TLMDVerticalGradient">
<Colors ColorCount="2">
<Color0 Value="$00FEDDC4"/>
<Color1 Value="clWhite"/>
</Colors>
</Filler>
</Item>
<Item Index="1">
<FillerRect Left="0" Top="45" Right="100" Bottom="100"/>
<Filler Class="TLMDVerticalGradient">
<Colors ColorCount="2">
<Color0 Value="$00FEDDC4"/>
<Color1 Value="clWhite"/>
</Colors>
</Filler>
</Item>
</Filler>
</Item>
<Item Index="1" Weight="255">
<Filler Class="TLMDEllipseFiller">
<UseRelativeUnits Value="1"/>
<BasePoint X="50" Y="0"/>
<Axis1 Value="80"/>
<Axis2 Value="80"/>
<FirstAxisDirection X="1" Y="0"/>
<Colors ColorCount="2">
<Color0 Value="$00FEDDC4"/>
<Color1 Value="$0098D1E3"/>
</Colors>
</Filler>
</Item>
</Filler>
So, we have to take filler for main fill part (gfpMain index), ttTopTabItemHot detail:
TabFillFiller[ttTopTabItemHot, gfpMain]
then cast it to TLMDMixedFiller and take the first item, which is a composite filler:
TLMDMixedFiller( * ).Item[0])
then cast it to TLMDCompositeFiller and take the first item which is a vertical gradient, and change the first color:
TLMDCompositeFiller( * ).Item[0].FixedColors[0] := clRed;
Changing other filler properties
Each filler has BasePoint property which determines the coordinate origin for filler. Example:
with CThemeRenderer do
begin
//This will change base point of ellipse gradient filler (bottom part of the filler)
//Coordinates are relative to rectangle of the element: (100, 100) is
//the bottom right corner
TLMDCompositeFiller(ButtonFillFiller[tbPushButtonPressed, gfpMain]).Item[1].BasePoint := Point(100, 100);
TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[1].BasePoint := Point(0, 100);
end;
Parameters - detailed description
Parameters section is a simple one for fill descriptors and rather complex for frame descriptors. However, each parameter is a byte.
Fill descriptors
Here we have one parameter: gflpRenderMode (prefix gflp: gradient fill parameter)
type
TLMDGradientThemeFillParam = (gflpRenderMode);
Bits 0..1: 0 - standard, 1 - sketch, 2 and 3 - reserved; Bit 2 - antialiasing for gfpMain; Bits 3..6 - antialiasing for gfpDeco1..gfpDeco4. Standard value is 4: 0000 0010.
Frame descriptors
Here we have a lot of parameters (prefix gfrp: gradient frame parameter).
Most of frame parameters relate to determining how corners of a frame should look. For custom cut rectangle, CutX and CutY are the values that, along with corner cut type, determine how corner looks. E.g. here is a round-cut corner with its CutX and CutY values:
Since there are three possible areas of a frame (outer border, inner space and inner border), each of which can have its own corners description, the number of parameters section of a frame descriptor is about 40:
type
TLMDGradientThemeFrameParam =
(
//gfrpRenderMode
//bits 0..1: 0 - standard, 1 - sketch, 2 and 3 - reserved
//bit 2: outerborder antialasing flag - 4
//bit 3: outerborder soft edge flag - 8
//bit 4: innerspace antialasing flag - 16
//bit 5: innerspace soft edge flag - 32
//bit 6: innerborder antialasing flag - 64
//bit 7: innerborder soft edge flag - 128
//---------------- bits 7654 3210
//standard value is 84: 0101 0100
gfrpRenderMode,
//determine what sides of the border should be drawn
gfrpOuterBorderSides,
gfrpInnerBorderSides,
//determine edge width - each of border areas can have edges. Not used for Office2007-like themes
gfrpOuterBorderEdgeWidth,
gfrpInnerBorderEdgeWidth,
gfrpSpaceEdgeWidth,
//determine border areas width
gfrpOuterBorderWidth, gfrpInnerBorderWidth,
//determines gap width between border area and innerspace area
gfrpOuterBorderGap, gfrpInnerBorderGap,
//determine inner space widths
gfrpTopSpaceWidth, gfrpRightSpaceWidth,
gfrpBottomSpaceWidth, gfrpLeftSpaceWidth,
//determines how cut values are calculated
//Possible values are
//cvuBoth - both cut values are used
//cvuXOnly - only CutX value is used
//cvuYOnly - only CutY value is used
//cvuMin - minimum of CutX and CutY values is used
//cvuMax - maximum of CutX and CutY values is used
//cvuAverage - average of CutX and CutY values is used
gfrpCutValueUsage,
//determine inner and outer cut type for outer border
//Possible values are ctNone (rectangular corner), ctLine (line-cut corner), ctRound (rounded corner)
gfrpOuterBorderInnerCutType, gfrpOuterBorderOuterCutType,
//CutX and CutY values for inner and outer corners of outer border
gfrpOuterBorderInnerCutX, gfrpOuterBorderInnerCutY,
gfrpOuterBorderOuterCutX, gfrpOuterBorderOuterCutY,
//value types for outer border cut values
//Possible values are vtAbsolute, vtPercent
gfrpOuterBorderInnerCutXValueType, gfrpOuterBorderInnerCutYValueType,
gfrpOuterBorderOuterCutXValueType, gfrpOuterBorderOuterCutYValueType,
//determine inner and outer cut type for inner space
gfrpInnerSpaceInnerCutType, gfrpInnerSpaceOuterCutType,
//CutX and CutY values for inner and outer corners of inner space
gfrpInnerSpaceInnerCutX, gfrpInnerSpaceInnerCutY,
gfrpInnerSpaceOuterCutX, gfrpInnerSpaceOuterCutY,
//value types for inner space cut values
gfrpInnerSpaceInnerCutXValueType, gfrpInnerSpaceInnerCutYValueType,
gfrpInnerSpaceOuterCutXValueType, gfrpInnerSpaceOuterCutYValueType,
//determine inner and outer cut type for inner border
gfrpInnerBorderOuterCutType, gfrpInnerBorderInnerCutType,
//CutX and CutY values for inner and outer corners of inner border
gfrpInnerBorderOuterCutX, gfrpInnerBorderOuterCutY,
gfrpInnerBorderInnerCutX, gfrpInnerBorderInnerCutY,
//value types for inner border cut values
gfrpInnerBorderOuterCutXValueType, gfrpInnerBorderOuterCutYValueType,
gfrpInnerBorderInnerCutXValueType, gfrpInnerBorderInnerCutYValueType);
Code samples
Delphi
Changing outer border of a push button
cThemeRenderer := TLMDBaseGradientThemeRenderer(LMDThemeServices.CurrentRenderer);
with CThemeRenderer do
begin
ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderWidth] := 2;
ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderWidth] := 2;
ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderWidth] := 2;
ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderWidth] := 2;
end;
LMDThemeServices.ApplyThemeChange;
Changing outline of a push button
with CThemeRenderer do
begin
//See full list of frame params in LMDThemesGradientThemeBase unit
ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderOuterCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderInnerCutType] := LMDCornerCutToByte(cLineCutCorners);
ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderOuterCutX] := 6;
ButtonFrameParam[tbPushButtonNormal, gfrpOuterBorderInnerCutX] := 6;
ButtonFrameParam[tbPushButtonNormal, gfrpInnerBorderOuterCutX] := 7;
ButtonFrameParam[tbPushButtonNormal, gfrpInnerBorderInnerCutX] := 7;
ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderOuterCutX] := 6;
ButtonFrameParam[tbPushButtonHot, gfrpOuterBorderInnerCutX] := 6;
ButtonFrameParam[tbPushButtonHot, gfrpInnerBorderOuterCutX] := 7;
ButtonFrameParam[tbPushButtonHot, gfrpInnerBorderInnerCutX] := 7;
ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderOuterCutX] := 6;
ButtonFrameParam[tbPushButtonPressed, gfrpOuterBorderInnerCutX] := 6;
ButtonFrameParam[tbPushButtonPressed, gfrpInnerBorderOuterCutX] := 7;
ButtonFrameParam[tbPushButtonPressed, gfrpInnerBorderInnerCutX] := 7;
ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderOuterCutX] := 6;
ButtonFrameParam[tbPushButtonDisabled, gfrpOuterBorderInnerCutX] := 6;
ButtonFrameParam[tbPushButtonDisabled, gfrpInnerBorderOuterCutX] := 7;
ButtonFrameParam[tbPushButtonDisabled, gfrpInnerBorderInnerCutX] := 7;
end;
LMDThemeServices.ApplyThemeChange;
Changing base point of an elliptic gradient of a push button
with CThemeRenderer do
begin
TLMDCompositeFiller(ButtonFillFiller[tbPushButtonPressed, gfpMain]).Item[1].BasePoint := Point(100, 100);
TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[1].BasePoint := Point(0, 100);
end;
Adding third gradient area for a push button
with CThemeRenderer do
begin
with TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]) do
begin
Add(TLMDVerticalGradient.Create);
FillerRect[0] := Rect(0, 0, 100, 10);
FillerRect[1] := Rect(0, 10, 100, 80);
FillerRect[2] := Rect(0, 80, 100, 100);
Item[2].FixedColors[0] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[0].FixedColors[1];
Item[2].FixedColors[1] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[0].FixedColors[0];
end;
with TLMDCompositeFiller(ButtonFillFiller[tbPushButtonPressed, gfpMain]) do
begin
Add(TLMDVerticalGradient.Create);
FillerRect[0] := Rect(0, 0, 100, 10);
FillerRect[1] := Rect(0, 10, 100, 85);
FillerRect[2] := Rect(0, 85, 100, 100);
Item[2].FixedColors[0] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[2].FixedColors[0];
Item[2].FixedColors[1] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonHot, gfpMain]).Item[2].FixedColors[1];
end;
with TLMDCompositeFiller(ButtonFillFiller[tbPushButtonNormal, gfpMain]) do
begin
Add(TLMDVerticalGradient.Create);
FillerRect[0] := Rect(0, 0, 100, 10);
FillerRect[1] := Rect(0, 10, 100, 85);
FillerRect[2] := Rect(0, 85, 100, 100);
Item[2].FixedColors[0] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonNormal, gfpMain]).Item[0].FixedColors[1];
Item[2].FixedColors[1] := TLMDCompositeFiller(ButtonFillFiller[tbPushButtonNormal, gfpMain]).Item[0].FixedColors[0];
end;
end;
C++ Builder
Changing hot tab colors of LMDPageControl
TLMDBaseGradientThemeRenderer *cThemeRenderer;
TLMDFiller *filler;
TLMDCompositeFiller *cfiller;
TLMDMixedFiller *mfiller;
cThemeRenderer = (TLMDBaseGradientThemeRenderer*)LMDThemeServices()->CurrentRenderer;
cThemeRenderer->SetNewColor(
0x0000FFFF,
Lmdthemescommontypes::TThemedElementSet() << teTab,
"ttTopTabItemHot",
TLMDGradientFillParts() << gfpMain,
Lmdgradientframes::TLMDGradientSimpleFramePartKinds(),
0
);
filler = cThemeRenderer->TabFillFiller[ttTopTabItemHot][gfpMain];
mfiller = (TLMDMixedFiller*)filler;
cfiller = (TLMDCompositeFiller*)(mfiller->Item[0]);
cfiller->Item[0]->FixedColors[0] = clRed;
Screenshots
Predefined color schemes
ElXTree, ElToolBar and LMDButtonBar
With blue color scheme
With black color scheme
Changing colors at runtime
Third gradient area added for push buttons, tab colors modified
Base point changed for push buttons
Dark blue scheme (brightness -30%)