We would like to use cxButtons in our Project with Skins (using cxLookAndFeelController). Well, the Skins are great, but we need the ability to colorize the Buttons with custom colors without loosing the Skins. Is this possible?
The "Colors.Normal"-Property only works, when I have "NativeStyle" Enabled, but the I loose the nice Skins… We need some kind of blending the Skin with a custom color.
Making multiple Skins with other Button-Imags is not reasonable, because we need to many diffrent colors.
Could you implement this Feature? Or where I would be right place to do that, maybe I can do it with a Helper Class.
How to set the Color of a cxButton when I use Skins
Answers approved by DevExpress Support
Hello Rene.
Thank you for the sample code. I should say that it is very a interesting solution.
>>
Do you have an Idea, how I can speedup this? Maybe with GDI+?
<<
Unfortunately, there is no way to improve the performance of this approach, because painting the bitmap pixel-by-pixel takes significant time.
>>
Do you have an Idea, how I can place my procedure directly after painting the skin (before border, text, glyphs)? It should be a solution without modifying the devexpress-Source.
<<
I recommend that you create a SkinPainter descendant for the necessary skin and implement this procedure there.
Attached is an example that shows how to perform this task. Hope, it will help you achieve the required functionality.
Best regards, Ingvar.
It's not working with the current version. Can you please give an example for the new ones?
Hello Andre,
You are right, this approach is used in old versions of our controls. Now (the current version number is 14.2.5) our buttons have custom drawing capabilities, so it is unnecessary anymore to create custom painters. Please review the "TcxCustomButton.OnCustomDraw" help topic where the custom drawing approach is described in detail. There is also a useful code snippet there.
Hello Rene.
Thank you for your message. This functionality conflicts with the ExpressSkins concept.
I'm afraid that it is impossible to achieve the desired result except creating new skins.
Best regards, Ingvar.
Well impossible is nothing ;-) But maybe it will be the best solution at the end…
I made a own skin and override the DrawButton-procedure.
First I tried it with a Semitransparent color layer over the button, but the colors wasn't like that we need. Especially when the skin is another color than AColor. When the Skin is silver or something like that, its not too bad.
My second approach was to separate each Pixel in Hue, Luminance and Saturation then replace the Hue with the Hue of AColor. Now I have something like I wanted, but its little slow and I have some issues with the Borders. It would be much better, when I could overwrite the procedure TdxSkinElement.InternalDraw, but its too invasive…
Do you have an Idea, how I can speedup this? Maybe with GDI+?
Do you have an Idea, how I can place my procedure directly after painting the skin (before border, text, glyphs)? It should be a solution without modifying the devexpress-Source.
-----
uses Types, Graphics, Windows, GraphUtil;
function ColorToBGR(Color : TColor) : Cardinal; inline;
begin
Result := (Color and $FF000000) + ((Color and $000000FF) shl 16) + (Color and $0000FF00) + ((Color and $00FF0000) shr 16);
end;
function BGRToColor(const BGR : Cardinal) : TColor; inline;
begin
Result := (BGR and $FF000000) + ((BGR and $000000FF) shl 16) + (BGR and $0000FF00) + ((BGR and $00FF0000) shr 16);
end;
class procedure TdxLTDefaultSkinPainter.DrawButton(ACanvas: TcxCanvas; R: TRect;
const ACaption: string; AState: TcxButtonState; ADrawBorder: Boolean; AColor,
ATextColor: TColor; AWordWrap, AIsToolButton: Boolean);
var
Bitmap: Graphics.TBitmap;
x, y: Integer;
h, h1, l, s, s1: Word;
p : PIntegerArray;
begin
inherited;
if AColor <> clDefault then begin
ColorRGBToHLS(ColorToRGB(AColor), h1, l, s1);
Bitmap := Graphics.TBitmap.Create;
try
Bitmap.PixelFormat := pf32bit;
Bitmap.SetSize(R.Right, R.Bottom);
BitBlt(Bitmap.Canvas.Handle, 0, 0, R.Right, R.Bottom, ACanvas.Canvas.Handle, 0, 0, SRCCOPY);
for y := 0 to Bitmap.Height -1 do begin
p := Bitmap.ScanLine[y];
for x := 0 to Bitmap.Width -1 do begin
ColorRGBToHLS(BGRToColor(p[x]), h, l, s);
p[x] := ColorToBGR(ColorHLSToRGB(h1, l, s1));
end;
end;
BitBlt(ACanvas.Canvas.Handle, 0, 0, R.Right, R.Bottom, Bitmap.Canvas.Handle, 0, 0, SRCCOPY);
finally
Bitmap.Free;
end;
end;
end;