Saturday, January 21, 2017

DELPHI Source Code Function: GetAlternateColor, alternating row color, Color-Shifting algorithm

DELPHI Source Code — Function: GetAlternateColor Color-Shifting for alternating grid-row color

If you ever wanted to create a (Borland, CodeGear, Embarcadero) Delphi grid, or other control, with alternating row-colors / highlight-colors, the first thing you will need is a function with an algorithm that helps automate the determination of the alternate-row-color, based on a given TColor value, that is a rather well coordinated and appropriate color.

In the source code I provide here for one such function, this alternating row-color / highlight-color calculation is done by shifting the individual color-channels (R/G/B) based on their current values. You should be able to modify the code quite easily to your own specific requirements.

Note: To see this method put to use, read my blog entry about how to include this functionality within the Delphi DBGrids.pas source code as a modification which enables alternating grid row colors as demonstrated in these images:

Delphi Grid Control using this Alternating-Row-Color / Highlight logic ("Classic" look)

Delphi Grid Control using this Alternating-Row-Color / Highlight logic ("Aero" / modern look)
This procedure has been tested within Delphi version from Delphi 7 through Delphi 2010.

Delphi Function Source Code

--********************************************************************************
--This source code is Copyright (c) 2007-2017
--     Author: Mike Eberhart
--
--I hereby release this code under the terms of the MIT License (for freeware).
--
--Permission is hereby granted, free of charge, to any person obtaining a copy
--of this software and associated documentation files (the "Software"), to deal
--in the Software without restriction, including without limitation the rights
--to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
--copies of the Software, and to permit persons to whom the Software is
--furnished to do so, subject to the following conditions:
--
--The above copyright notice and this permission notice shall be included in
--all copies or substantial portions of the Software.
--
--THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
--IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
--FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
--AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
--LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
--OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
--THE SOFTWARE.
--********************************************************************************

{*******************************************************************************
GetAlternateColor is just a color-shifting algorithm, where if any component
of a color code (R, G, or B) gets too "close" to either 00 or FF, it is shifted
in the opposite direction.
I use this to achieve a "green-bar" effect in the DBGrid, regardless of what
background color someone has chosen for the grid.  This algorithm makes a fairly
logical guess at what the alternating-band-color should be for a given color.

See other example on this blog https://suretalent.blogspot.com 
for how this code was plugged into Borland / Embarcadero Delphi source-code 
(as tested with Delphi 2006 through 2010)
*******************************************************************************}
function GetAlternateColor(CurrentColor : TColor) : TColor;
var
  r,g,b : Byte;
const
  //The amount of "shifting" per color channel we're going to make (out of 256 max)
  ColorShiftBy = 24;  
  MinShiftThreshold = ColorShiftBy * 2;
  MaxValue = 255;
begin
  CurrentColor := ColorToRGB(CurrentColor);
  r := GetRValue(CurrentColor);
  g := GetGValue(CurrentColor);
  b := GetBValue(CurrentColor);

  //nearly "black" in color already... brighten all channels
  if (r < MinShiftThreshold) and (g < MinShiftThreshold) and (b < MinShiftThreshold) then
  begin
    r := r + ColorShiftBy;
    g := g + ColorShiftBy;
    b := b + ColorShiftBy;
    Result := RGB(r,g,b);
    exit;
  end;

  //Special case to handle "white" fields.  
  //In one of our product GUIs, white fields indicated editable fields in Grids;
  //perform a MINIMAL "shift" in color so field is almost white, but yet visibly different
  if (r = MaxValue ) and (g = MaxValue) and (b = MaxValue) then
  begin
    r := r - ColorShiftBy div 2;
    g := g - ColorShiftBy div 2;
    b := b - ColorShiftBy div 2;
    Result := RGB(r,g,b);
    exit;
  end;

  if r > MinShiftThreshold then
    r := r - ColorShiftBy
  else
    if r > 0 then
      r := r + ColorShiftBy;

  if g > MinShiftThreshold then
    g := g - ColorShiftBy
  else
    if g > 0 then
      g := g + ColorShiftBy;

  if b > MinShiftThreshold then
    b := b - ColorShiftBy
  else
    if b > 0 then
      b := b + ColorShiftBy;

  Result := RGB(r,g,b);

end; //function GetAlternateColor



{*******************************************************************************
Some useful CONSTANTS for row-color testing.
Note:
The HEX values represent RGB, but are in low-order byte to high-order byte
arrangement (i.e., it's really BRG reading left-to-right, so read right-to-left
for two-byte pairs of Red/Green/Blue).  So, use ($00BBGGRR) patterns.
*******************************************************************************}
const
  //                        BBGGRR
  clLightTan    = TColor($00CCEEEE);
  clMidTan      = TColor($00B6D4D4);
  clDarkTan     = TColor($00A0BABA);



Continue to read this Software Development and Technology Blog for computer programming, software development, and technology Techniques, How-To's, Fixes, Reviews, and News — focused on Dart Language, Delphi, SQL Server, Nvidia CUDA, VMware, TypeScript, SVG, other technology tips and how-to's, and my varied political and economic opinions.

No comments: