Ticket Q214070
Visible to All Users

How to set the Color of a cxButton when I use Skins

created 16 years ago

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.

Comments (2)
DevExpress Support Team 16 years ago

    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;

      Answers approved by DevExpress Support

      created 16 years ago (modified 12 years ago)

      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.

        Comments (2)

          It's not working with the current version. Can you please give an example for the new ones?

          DevExpress Support Team 10 years ago

            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.

            Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

            Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.