Jump to content
Sign in to follow this  
Gustav Schubert

About MedGray and WindowWhite

Recommended Posts

I think the VCL version of MedGray contains a typo:

// Search for MedGray in unit System.UITypes:
  MedGray = TColor($A4A0A0);
  MedGray = Alpha or TAlphaColor($A0A0A0);

See (also) the following docwiki topics:
  RADStudio/Sydney/en/Colors_in_the_VCL
  RADStudio/Sydney/en/Colors_in_FireMonkey

 

Already known:

  • Gray is darker than DarkGray, this is ok ( I learned it from Stackoverflow).
  • Use Dimgray if you want a darker gray than Gray.
  • The default background color of a Window is not a named color in TAlphaColorRec.
  • Duplicate color values in TAlphaColorRec are by design.
  • There is an open RSP (29269) which complains about duplicated color values in System.UITypes.TAlphaColorRec.

 

Questions:

  Are color values other then web colors allowed to have a name in TAlphaColorRec?

  If so, what color names would you like to be included, for convenience?

  QuickSilver = Alpha or TAlphaColor($A0A0A0); // Mediumgrey or Mediumgray or MedGray?
  WindowWhite = Alpha or TAlphaColor($F0F0F0); // ButtonFace or BtnFace or Buttonface or Windowgray?

I never used MedGray, but I need a WindowWhite in FMX.

 

I intend to specify a reduced set of named colors for use in my application. I need those colors to have a good name. I will have VCL, FMX, and LCL versions of my very own TRggColors, which will be available under the same name to client code in VCL and FMX.

  • Gray would be ok.
  • ( Not sure about DarkGray. )
  • Mediumgray will look nice next to Lightgray.
  • Not sure about WindowWhite.

 

( This topic is about accessing color values by name for drawing to the canvas of the platform, without creating noise in the diff, and without stopping at surprises. )

Edited by Gustav Schubert
corrected WindowWhite = $FFF0F0F0

Share this post


Link to post
Guest

if your doubt is "find A name for your colors const", try this site:

 

Chir.ag  by Chirag Mehta

the have created this site for easy find your colors names, include using Hex values! And others goods!

 

https://chir.ag/projects/name-that-color/#E0E0E0

 

image.thumb.png.eb069d1b2a280e5a0f53d157f8a60e0d.png

 

Here, you can have another options like a little app

https://www.raymond.cc/blog/how-to-find-out-the-name-of-a-color/

 

hug

Edited by Guest

Share this post


Link to post

My problem is that I cannot find the FMX version of clBtnFace in TAlphaColorRec. (WindowWhite)

 

Btw, by now I have decided that grey has lost! I know this is a little unfair, but only a little, and I am not really sorry, mainly because the chance was there, with FMX, in the beginning.

 

As far as the DarkGray problem is concerned, any suggestion for a more appropiate name? I would consider a French name too, for my internal cross platform TRggColors helper.

Share this post


Link to post
Guest

 

4 hours ago, Gustav Schubert said:

I cannot find the FMX version of clBtnFace in TAlphaColorRec. (WindowWhite)

Dont forget that FMX is based in Styles (VCL too) :))) Themes, that control many visual aspect!

  • VCL and FMX is 2 frameworks made by 2 different teams!
  • clBtnFace does not exist, but "$FFF0F0F0", yes!

 

image.thumb.png.a58ae2f42083142e09429ecfb38519a3.png

procedure TForm1.Button2Click(Sender: TObject);
begin
  // init value on design = $FF8A2BE2 = 4287245282
  //
  // FMX - Blueviolet = 4293980400 = $FF8A2BE2
  // VCL - clBtnFace (FMX $FFF0F0F0 = 4293980400)
  //
  {
    if (Label1.TextSettings.FontColor = 4293980400) then
    Label1.TextSettings.FontColor := 4287245282
    else
    Label1.TextSettings.FontColor := 4293980400;
  }
  //
  if (Label1.TextSettings.FontColor = $FFF0F0F0) then
    Label1.TextSettings.FontColor := $FF8A2BE2
  else
    Label1.TextSettings.FontColor := $FFF0F0F0;
end;

hug

Edited by Guest

Share this post


Link to post

I am dealing with two missing colors, one ambiguous color (MedGray), one misleading color (DarkGray), and duplicated color values (gray vs. grey).

 

Joke: I suggest that the wiki pages add two buttons, "sort by gray" and "sort by grey".

 

In my test program I show 10 overlapping rectangles (FMX) or shapes (VCL) to verify my understanding of the color values.
The second 'color name' in the following output is returned from AlphaColorToString(color) or ColorToString(color).

#FFF0F0F0 - default color for a Window background in FMX.
#FFE0E0E0 - default value of Rectangle1.Fill.Color in FMX.

// FormatString := '%d: [%20s]: %12s = %x = (%d, %d, %d)';

Testprogram output for FMX:

0: [   Whitesmoke F5 245]:   Whitesmoke = FFF5F5F5 = (245, 245, 245)
1: [  WindowWhite F0 240]:    #FFF0F0F0 = FFF0F0F0 = (240, 240, 240)
2: [   ChinaWhite E0 224]:    #FFE0E0E0 = FFE0E0E0 = (224, 224, 224)
3: [    Gainsboro DC 220]:    Gainsboro = FFDCDCDC = (220, 220, 220)
4: [    Lightgray D3 211]:    Lightgray = FFD3D3D3 = (211, 211, 211)
5: [       Silver C0 192]:       Silver = FFC0C0C0 = (192, 192, 192)
6: [     Darkgray A9 169]:     Darkgray = FFA9A9A9 = (169, 169, 169)
7: [      MedGray A0 160]:    #FFA0A0A0 = FFA0A0A0 = (160, 160, 160)
8: [         Gray 80 128]:         Gray = FF808080 = (128, 128, 128)
9: [      Dimgray 69 105]:      Dimgray = FF696969 = (105, 105, 105)

Testprogram output for VCL colors:

0: [   Whitesmoke F5 245]:    $00F5F5F5 = F5F5F5 = (245, 245, 245)
1: [  WindowWhite F0 240]:    $00F0F0F0 = F0F0F0 = (240, 240, 240)
2: [   ChinaWhite E0 224]:    $00E0E0E0 = E0E0E0 = (224, 224, 224)
3: [    Gainsboro DC 220]:    $00DCDCDC = DCDCDC = (220, 220, 220)
4: [    Lightgray D3 211]:    $00D3D3D3 = D3D3D3 = (211, 211, 211)
5: [       Silver C0 192]:     clSilver = C0C0C0 = (192, 192, 192)
6: [     Darkgray A9 169]:    $00A9A9A9 = A9A9A9 = (169, 169, 169)
7: [      MedGray A0 160]:    clMedGray = A4A0A0 = (160, 160, 164)
8: [         Gray 80 128]:       clGray = 808080 = (128, 128, 128)
9: [      Dimgray 69 105]:    $00696969 = 696969 = (105, 105, 105)

Color names according to chir.ag:

F5 245 Wild Sand approx. (Whitesmoke)
F0 240 Gallery approx. (clBtnFace, "WindowWhite")
E0 224 Alto approx. ()
DC 220 Alto approx.(Gainsboro)
D3 211 Alto approx. (Lightgray)
C0 192 Silver solid (Silver)
A9 169 Silver Chalice approx. (Darkgray)
A0 160 Silver Chalice approx. (MedGray FMX)
80 128 Gray solid (Gray) 
69 105 Dove Gray approx. (DimGray)

A0A0A4 Santas Gray approx. (MedGray VCL)

clBtnFace is not a named color:

  https://encycolorpedia.com/named
  https://colorate.azurewebsites.net/Color/F0F0F0

 

Edited by Gustav Schubert
formatting

Share this post


Link to post

I only want to use colors that are defined in TAlphaColorRec, and which return the name from AlphaColorToString. This is what I want to figure out.

GrayTestFMX.thumb.png.19601237440084add3dfc6dbfab64896.png

Share this post


Link to post
Guest

look this:

image.thumb.png.5580bbaf647317324558ae1707e0423e.png

 

in Delphi, you can find the "color name" is exist a "const defined in "System.UIConst (FMC) / System.UITypes (VCL) "! in fact, the "names" is "arbitrared" by language, not for a color itself! you see?

See at: System.Classes.pas, line: 4205, function IntToIdent(Int: Integer; var Ident: string; const Map: array of TIdentMapEntry): Boolean;

  • Map is the "magic"! 
  • Map: array of TIdentMapEntry
  • TIdentMapEntry = record ... feeded by some other point in system! maybe some API function...
    • Syste.pas, line 26225, procedure _UStrAsg(var Dest: UnicodeString; const Source: UnicodeString); // globals (need copy) ...
procedure TForm1.btn_TAlphaColor_in_A_R_G_B_valuesClick(Sender: TObject);
var
  lMyAlphaColorRec: TAlphaColorRec;
  lMyAlphaColors  : TAlphaColors;
  // iColor          : integer;
begin
  Memo1.Lines.Clear;
  //
  { no result } lMyAlphaColorRec.Create($FFF0F0F0); // clBtnFace (VCL)

  { iColor := } lMyAlphaColors.ColorToRGB($FFF0F0F0); // clBtnFace (VCL)
  //
  Label1.TextSettings.FontColor := { RGBtoBGR( } lMyAlphaColors.Color; // );
  //
  Label2.TextSettings.FontColor := { RGBtoBGR( } lMyAlphaColorRec.Color; // );
  //
  Memo1.Lines.Add('Using TAlphaColorRec:');
  Memo1.Lines.Add(Format('A=%d, R=%d, G=%d, B=%d, AlphaColor=%s', [ { }
    lMyAlphaColorRec.A,                                             { }
    lMyAlphaColorRec.R,                                             { }
    lMyAlphaColorRec.G,                                             { }
    lMyAlphaColorRec.B,                                             { }
    AlphaColorToString(lMyAlphaColorRec.Color)                      { }
    ]));
  //
  Memo1.Lines.Add('Using TAlphaColors:');
  Memo1.Lines.Add(Format('A=%d, R=%d, G=%d, B=%d, AlphaColor=%s', { }
    [lMyAlphaColors.A,                                            { }
    lMyAlphaColors.R,                                             { }
    lMyAlphaColors.G,                                             { }
    lMyAlphaColors.B,                                             { }
    AlphaColorToString(lMyAlphaColors.Color)                      { }
    ]));

end;

procedure TForm1.btnLabels_with_claAqua_default_colorsClick(Sender: TObject);
begin
  Label1.TextSettings.FontColor := claAqua; // TAlphaColors.claAqua
  //
  Label2.TextSettings.FontColor := claAqua; // TAlphaColors.claAqua
end;

 

What you can to, it's a create your "array" with your colors names and values pertinent! Like this:

image.thumb.png.44021bbdfc0545cc0a35d965f8fdc177.png

 

type
  TMyAlphaColorsNames = record
    Name: string;
    Color: TAlphaColor;
  end;
procedure TForm1.btnLabels_with_claAqua_default_colorsClick(Sender: TObject);
var
  lMyAlphaColorsNames: array [0 .. 1] of TMyAlphaColorsNames;
begin
  lMyAlphaColorsNames[0].Name  := 'clBtnFace';
  lMyAlphaColorsNames[0].Color := $FFF0F0F0;
  lMyAlphaColorsNames[1].Name  := 'Aqua';
  lMyAlphaColorsNames[1].Color := claAqua;
  //
  Label1.Text                   := lMyAlphaColorsNames[0].Name;
  Label1.TextSettings.FontColor := lMyAlphaColorsNames[0].Color;
  //
  Label2.Text                   := lMyAlphaColorsNames[1].Name;
  Label2.TextSettings.FontColor := lMyAlphaColorsNames[1].Color;
end;

 

 

 

 

hug

Edited by Guest

Share this post


Link to post

This is from my application:

  A0B0 := TRggLine.Create('A0B0');
  L := A0B0;
  //L.StrokeColor := TAlphaColors.Gray; // FMX only
  L.StrokeColor := TRggColors.Gray; // VCL and FMX and LCL
  L.Point1 := A0;
  L.Point2 := B0;
  Add(L);

I am designing a color palette (from well known color names) and I am thinking about color names to be included. The user (myself, to begin with) is expected to specify names that can be remembered. I took TAlphaColorRec as a starting point, and I am free to fix any potential problems.

 

For example:

  • F0F0F0 (BtnFace) is not a named color, not in the realm of Delphi FMX. Should Embarcadero give a name to that color, and which?
  • How about MedGray and DarkGray.
  • What to do with the duplicated colors, keep them?

Want is your opinion, of the palette of named colors in Delphi?

Share this post


Link to post
Guest
35 minutes ago, Gustav Schubert said:

Want is your opinion, of the palette of named colors in Delphi?

First, let's remember that Embarcadero bought the Borland estate (CodeGear, InPrise, etc ... other names for the Borland estate throughout its existence).
Therefore, many things could not just disappear! There were many companies that used Delphi and CBuilder, for example! So, see that the pyramid would be collapsed if the base was destroyed!

 

Second, many of the names, classes, components, interfaces, etc ... were and still are "inherited" from the MSWindows APIs. And, now from other platforms, such as: Android, Linux, macOS, iOS, etc ... who knows what will come around! Python is already a reality, PHP, Java too, etc ...

 

Third, as inheritance makes sense, when it comes to having a standard required by operating systems, then, I couldn't just "determine" what would be created or what name it would have! It was necessary to meet the requirements of MSWindows, at that time ... and so, it continues today! Imposition of the market, or simply, rules of Capitalism in action!

 

If, what you intend to create is only for your use! So, you are the one who determines what will be created and how it will be defined!

 

If, on the contrary, you intend to distribute to other professional developers or not, then the rule changes! You must serve the market, and not just your expectations! Unless you buy the entire computer technology market and start dictating the market, as many companies have done in the past!

 

IBM dictated rules in mainframes, Microsoft in operating systems, etc ... But we have already seen that this is no longer valid! With globalization and the unrestricted use of the internet, we can no longer think of ourselves, but of the whole!

 

Regarding whether or not to have duplicate "color names", the most sensible answer is: NO!

 

Duplicity generates mistakes, many times, imperceptible!

 

If you check the source files of RAD Studio (Delphi, for example), you will see that this happens! Therefore, it is advisable to use "name-space" for types, for example:

  • System.faDirectory in System.SysUtils
  • TFileAttribute.faDirectory in System.IOUtils

 

note that "faDirectory" is used by default when you do not use "System.IOUtils" in the "Uses" and "TFileAttribute" clause to determine the enumeration where the "faDirectory" value comes from!

 

So, nobody, especially when they are on a team with many minds thinking, will be free of this type of error!

 

So, my advice is:

  • For colors with equal values, choose only one to use, or, at best, make the next name refer to the previous one, such as:
    • caBtnFace = $ xxxxxxxx;
    • myColorBtnFace = caBtnFace;

 

Now, I can have both references in my list of choice, however, for a better layout, when assembling the color list, you could check if the value already exists in the list, and if so, then do not add the new name / value. Understood?

 

It would be wiser than having two names for the same color value!

 

Regarding the names you will use, try to be sensible here too! If you can try to follow the universal rules for naming your color list!

 

Not to mention that you can have the list of your constants or even your class with the definitions for the colors, using the platform identifiers:

  • {$ IF DEFINED (MSWINDOWS)}
  • ... here you can try verify if "FMX" or "VCL" project --- please see on Help which as global vars for each one
  • {$ ENDIF}
  • {$ IF DEFINED (ANDROID)} // etc...
  • {$ ENDIF}

 

But it is always recommended to have units for framework! And, ultimately, you could have a single for more than one framework!

 

For example, RTL can be used by VCL or FMX projects! However, specific classes for FMX are not defined in the units for VCL!

 

hug

Edited by Guest

Share this post


Link to post

BtnFace-F0F0F0 is the most important color in the Delphi universe. A great opportunity still exists for Embarcadero to give this unnamed color a proper place in the encyclopedia of color names. All that is needed is to include it in TAlphaColorRec, and return the name from the AlphaColorToString function. Since there are duplicate names already (defined for some of the gray values), it does not matter much to add one more, and another one for E0E0E0, and an alternative name for DarkGray. Maybe they are reading this and will act. Then I could just clone the TAlphaColorRec and delete everything I do not want. All the standard functions like AlphaColorToString would work for me out of the box. I don't know if that idea was the reason why I posted here. Sometimes it is a bit fuzzy. But thank you for giving me the opportunity to explain my point!

 

mfg

Share this post


Link to post
Guest

u're wellcome!

 

note: if possible, rate my answers.

 

hug

Edited by Guest

Share this post


Link to post

Analysis of the day:

      140 web colors
    +   1 Alpha
    +   1 Null
    +   7 Grey duplicats
    +   6 (LtGray, MedGray, DkGray, MoneyGreen, LegacySkyBlue, Cream)
    -----
      155 named colors in TAlphaColorRec in System.UITypes
    =====

      140 web color // see https://www.w3schools.com/cssref/css_colors.asp
    +   1 Null (claNull)
    +   7 Grey duplicates // claDarkgrey, claDarkslategrey, claDimgrey, claGrey, claLightgrey, claLightslategrey, claSlategrey
    -----
      148 global cla Constants in System.UIConsts
    =====
  • The 148 named color constants can be iterated over using AlphaColors array, which is private in System.UIConsts.
  • You are supposed to do it with the help of procedure GetAlphaColorValues(Proc: TGetStrProc);
  • See constructor of FMX.Colors.TRTLColors for an example of how to use it.
  • The problem with GetAlphaColorValues is described in RSP-30408.
  • A TWebColors type similar to TAlphaColors but with only 140 entries would be nice.
  • FFF0F0F0 is still a candidate for inclusion in TAlphaColorRec (to be dropped later).
  • I no longer want E0E0E0 (only used as default color for TRectangle.Fill).
  • Like 1

Share this post


Link to post
Guest

ok. if possible, when ready, share your project-color.

 

hug

Share this post


Link to post

Actually, there are 138 unique color values in the 140 web colors, because of Aqua = Cyan and Fuchsia = Magenta.

 

AlphaColors array in System.UIConsts has a 'unique constraint' on the Name but not on the Value.

 

Definitions of Cream and LegacySkyBlue are wrong in FMX.

// Colors do not match - verified with pipette in MS Paint.
Rectangle1.Fill.Color := TAlphaColors.Cream; // FMX
Shape1.Brush.Color := TColors.Cream; // VCL

Reason:

TAlphaColorRec
    Red = Alpha or TAlphaColor($FF0000); // correct
    MoneyGreen = TAlphaColor($FFC0DCC0); // symmetry
    LegacySkyBlue = Alpha or TAlphaColor($F0CAA6); // wrong
    Cream = Alpha or TAlphaColor($F0FBFF); // wrong
{$IFDEF BIGENDIAN}
        (A, R, G, B: System.Byte);
{$ELSE}
        (B, G, R, A: System.Byte);
{$ENDIF}

TColorRec
    Red = TColor($0000FF); // correct
    MoneyGreen = TColor($C0DCC0); // the original
    LegacySkyBlue = TColor($F0CAA6); // the original
    Cream = TColor($F0FBFF); // the original
{$IFDEF BIGENDIAN}
        (A, B, G, R: System.Byte);
{$ELSE}
        (R, G, B, A: System.Byte);
{$ENDIF}

Test program:

program CreamTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  System.UIConsts,
  System.UITypes;

var
  c: TAlphaColor;
  cr: TColorRec;
  acr: TAlphaColorRec;
  i: Integer;

begin
  try
    cr.Color := TColors.Red;
    acr.Color := TAlphaColors.Red;
    Assert(cr.R = acr.R);
    Assert(cr.G = acr.G);
    Assert(cr.B = acr.B);
    WriteLn('Red test ok.');
    // Green and Blue are ok as well

    WriteLn;

    cr.Color := TColors.Cream;
    acr.Color := TAlphaColors.Cream;
    Assert(cr.R = acr.B);
    Assert(cr.G = acr.G);
    Assert(cr.B = acr.R);
    WriteLn('Verified: R and B are swapped for Cream!');

    cr.Color := TColors.LegacySkyBlue;
    acr.Color := TAlphaColors.LegacySkyBlue;
    Assert(cr.R = acr.B);
    Assert(cr.G = acr.G);
    Assert(cr.B = acr.R);
    WriteLn('Verified: R and B are swapped for LegacySkyBlue!');

    WriteLn;

    WriteLn('Cream Test begins');
    cr.Color := TColors.Cream;
    acr.Color := TAlphaColors.Cream;
    i := 0;
    if cr.R <> acr.R then
    begin
      WriteLn('R is wrong.');
      Inc(i);
    end;
    if cr.B <> acr.B then
    begin
      WriteLn('B is wrong.');
      Inc(i);
    end;
    if i = 0 then
      WriteLn('Test ok.')
    else
      WriteLn('Cream test failed.');

    WriteLn;

    WriteLn('AlphaColorToString Tests:');
    WriteLn('Aqua', '=', AlphaColorToString(TAlphaColors.Aqua));
    WriteLn('Cyan', '=', AlphaColorToString(TAlphaColors.Cyan));
    WriteLn('Fuchsia', '=', AlphaColorToString(TAlphaColors.Fuchsia));
    WriteLn('Magenta', '=', AlphaColorToString(TAlphaColors.Magenta));
    WriteLn('MoneyGreen', '=', AlphaColorToString(TAlphaColors.MoneyGreen));
    WriteLn('LegacySkyBlue', '=', AlphaColorToString(TAlphaColors.LegacySkyBlue));
    WriteLn('Cream', '=', AlphaColorToString(TAlphaColors.Cream));

    WriteLn;

    WriteLn('ColorToString Tests:');
    WriteLn('Aqua', '=', ColorToString(TColors.Aqua));
    WriteLn('Cyan', '=', ColorToString(TColors.Cyan));
    WriteLn('Fuchsia', '=', ColorToString(TColors.Fuchsia));
    WriteLn('Magenta', '=', ColorToString(TColors.Magenta));
    WriteLn('MoneyGreen', '=', ColorToString(TColors.MoneyGreen));
    WriteLn('LegacySkyBlue', '=', ColorToString(TColors.LegacySkyBlue));
    WriteLn('Cream', '=', ColorToString(TColors.Cream));

    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Output:

Red test ok.

Verified: R and B are swapped for Cream!
Verified: R and B are swapped for LegacySkyBlue!

Cream Test begins
R is wrong.
B is wrong.
Cream test failed.

AlphaColorToString Tests:
Aqua=Aqua
Cyan=Aqua
Fuchsia=Fuchsia
Magenta=Fuchsia
MoneyGreen=#FFC0DCC0
LegacySkyBlue=#FFF0CAA6
Cream=#FFF0FBFF

ColorToString Tests:
Aqua=clAqua
Cyan=clAqua
Fuchsia=clFuchsia
Magenta=clFuchsia
MoneyGreen=clMoneyGreen
LegacySkyBlue=clSkyBlue
Cream=clCream

I am playing with colors, but not yet used in any feature of the app:

(  https://github.com/federgraph/RiggVar-RG38/blob/master/FB/RiggVar.FB.Color.pas  )
 

Edited by Gustav Schubert
typo

Share this post


Link to post

Update:

  • There are now 141 web colors (139 unique).
  • The relatively new web color is Rebeccapurple, not (yet) included in TAlphaColorRec.
  • In my temporary capacity as an expert on LegacySkyBlue I have reported to Quality: RSP-32781.
  • And I have uploaded FrmColor.pas (the main form in RG69.dpr) as a test for my TRggWebColorListBox runtime component.

( The component can show colors in a sort order that is NOT alphabetically, and filter by group of web colors. )

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×