Recent

Author Topic: Application colors - Dark.  (Read 6820 times)

mdalacu

  • Full Member
  • ***
  • Posts: 233
    • dmSimpleApps
Application colors - Dark.
« on: August 06, 2015, 01:28:53 pm »
I have already made an application which uses default colors for all of the controls. (dmMediaConverter)
Now i want to have an option to color the whole app in dark colors (a dark theme).
Does anyone know how can i achieve this the most simple way?
Thanks.

lainz

  • Hero Member
  • *****
  • Posts: 4460
    • https://lainz.github.io/
Re: Application colors - Dark.
« Reply #1 on: August 06, 2015, 03:17:07 pm »
I don't know any simple way.

All I know includes:
- Custom Drawn Controls
- BGRA-Controls
- Create your own controls

The first includes making your own drawing code and replace your controls. And some (or most) of these components don't work very well under desktop IMHO.

The second includes to replace your controls and there are not too much you can use, according to a screenshot I seen of your application.

The third is the most difficult but the one will give you more control over the whole skinning of your application.

mdalacu

  • Full Member
  • ***
  • Posts: 233
    • dmSimpleApps
Re: Application colors - Dark.
« Reply #2 on: August 06, 2015, 03:27:33 pm »
Thanks for the answer but i was thinking of something more simple, of changing controls colors (x.Color) and fonts colors the proper way.
Or redefine system colors,,,ex clDefault.
The problems are with setting color of a Panel the same as a TabSheet where it belongs...and controling Active/Inactive colors.
Can i do this?
« Last Edit: August 06, 2015, 03:44:08 pm by mdalacu »

Graeme

  • Hero Member
  • *****
  • Posts: 1428
    • Graeme on the web
Re: Application colors - Dark.
« Reply #3 on: August 06, 2015, 04:08:27 pm »
The problems are with setting color of a Panel the same as a TabSheet where it belongs...and controling Active/Inactive colors.
Can i do this?
That's the problem of using LCL. They want everything to look native, and reduce the customisation that the developer can do. This caused me to move away from LCL back in 2006. I was told that if you want your LCL application to look different, change the theme of you OS!! That was out of the question. You might be able to do it if you use LCL-Qt, as Qt allows you to specify themes via the --style command line parameter, but of course then you need to implement a Qt theme using C++.

My suggestion, use a toolkit that supports themes. Take a look at fpGUI Toolkit. Implementing themes are quick and easy. Themes can also be applied to the application as a whole, a specific form or a specific widget. Here are a couple of fpGUI's standard themes: [http://geldenhuys.co.uk/~graemeg/themes/].  Other users have created many more too.
--
fpGUI Toolkit - a cross-platform GUI toolkit using Free Pascal
http://fpgui.sourceforge.net/

mdalacu

  • Full Member
  • ***
  • Posts: 233
    • dmSimpleApps
Re: Application colors - Dark.
« Reply #4 on: August 07, 2015, 07:06:21 am »
The reason i started this thread is that on Ubuntu with Numix theme my application looks terrible  :(

varianus

  • New Member
  • *
  • Posts: 22
Re: Application colors - Dark.
« Reply #5 on: August 07, 2015, 08:52:39 am »
If using GTK2 widgetset you could try to change the theme used by your application setting the environment variable GTK2_RC_FILES

Start your application with
Code: [Select]
GTK2_RC_FILES=/path/to/theme/gtkrc <command>
Info found here :http://crunchbang.org/forums/viewtopic.php?id=37487

mdalacu

  • Full Member
  • ***
  • Posts: 233
    • dmSimpleApps
Re: Application colors - Dark.
« Reply #6 on: August 07, 2015, 12:09:26 pm »
Thanks, but i search for a more cross platform solution.

Does anyone know how can i change the color of an diasbled button (enabled:=false) without onpaint event?
Thanks.

Blaazen

  • Hero Member
  • *****
  • Posts: 3237
  • POKE 54296,15
    • Eye-Candy Controls
Re: Application colors - Dark.
« Reply #7 on: August 07, 2015, 02:32:28 pm »
The only native buttons capable to change its color are TButton and TBitBtn and they have no OnPaint event. Buttons painted via Themes (like TSpeedBtn) cannot do it.

You can do some method like this:
Code: [Select]
procedure EnableButton(AEnabled: Boolean; ABtn: TBitBtn);
  if AEnabled then
    begin
      ABitBtn.Color:=clDefault;
      ABitBtn.Enabled:=True;
    end else
    begin
      ABitBtn.Color:=cl3DShadow;
      ABitBtn.Enabled:=False;
    end; 

but it will work only if you call it directly, if you will change Parent.Enabled, it will have no effect.
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

hrayon

  • Full Member
  • ***
  • Posts: 118
Re: Application colors - Dark.
« Reply #8 on: August 07, 2015, 04:08:27 pm »
Hi!
I do not know if it helps, and shows the limitations that Mr. Graeme said.
I use form inheritance, and put this code to change some colors in the parent form:
Code: [Select]
procedure TForm_Basic.FormCreate(Sender: TObject);
var
  l_integer_aux2, l_integer_aux3 : Integer;
  Component : TComponent;
begin
  inherited;
  self.Color:=StringtoColor(DataModule_Base.a_string_cor_form);
  for Component in Self do
  begin
    if Component is TDBGrid then
    begin
      TDBGrid(Component).ParentColor := false;
      TDBGrid(Component).AlternateColor:=StringtoColor(DataModule_Base.a_string_cor_grid_ac);
      TDBGrid(Component).Color:=StringtoColor(DataModule_Base.a_string_cor_grid_col);
       for l_integer_aux2 := TDBGrid(Component).Columns.Count - 1 downto 0 do
       begin
         if not TDBGrid(Component).Columns[l_integer_aux2].ReadOnly then
           TDBGrid(Component).Columns[l_integer_aux2].Title.Color:=StringtoColor(DataModule_Base.a_string_cor_grid_tit)
         else
           TDBGrid(Component).Columns[l_integer_aux2].Title.Color:=StringtoColor(DataModule_Base.a_string_cor_grid_tit_readonly);
       end;
    end
    else if (Component is TLabel) then
    begin
         TLabel(Component).Color:=StringtoColor(DataModule_Base.a_string_cor_form);
    end
    else if (Component is TPageControl) then
    begin
      for l_integer_aux2 := TPageControl(Component).PageCount - 1 downto 0 do
      begin
        for l_integer_aux3 := TPageControl(Component).Pages[l_integer_aux2].ControlCount - 1 downto 0 do
        begin
          if (TPageControl(Component).Pages[l_integer_aux2].Controls[l_integer_aux3] is TPanel) then
          begin
            (TPageControl(Component).Pages[l_integer_aux2].Controls[l_integer_aux3] as TPanel).Color:=StringtoColor(DataModule_Base.a_string_cor_form);
          end;
        end;
      end;
    end;
  end;
end;

Later, I decided to change the colors on the fly, and put a popup menu the color swap options from the main form of the application:

Code: [Select]
procedure TForm_Main.pc_PaintWindows();
var
  l_integer_TotalForms, l_integer_aux1 : Integer;
  l_integer_aux, l_integer_aux2, l_integer_aux3 : Integer;
begin
  l_integer_TotalForms := screen.CustomFormCount;
  for l_integer_aux1 := 0 to l_integer_TotalForms - 1 do
  begin
    //form
    screen.CustomForms[l_integer_aux1].Color:=StringtoColor(DataModule_Base.a_string_cor_form);
    for l_integer_aux := screen.CustomForms[l_integer_aux1].ComponentCount - 1 downto 0 do
    begin
      //ac grid
      if (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] is TDBGrid) then
      begin
        (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).ParentColor := false;
        (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).AlternateColor:=StringtoColor(DataModule_Base.a_string_cor_grid_ac);
        (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).Color:=StringtoColor(DataModule_Base.a_string_cor_grid_col);
        for l_integer_aux2 := (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).Columns.Count - 1 downto 0 do
        begin
          if not (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).Columns[l_integer_aux2].ReadOnly then
            (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).Columns[l_integer_aux2].Title.Color:=StringtoColor(DataModule_Base.a_string_cor_grid_tit)
          else
            (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TDBGrid).Columns[l_integer_aux2].Title.Color:=StringtoColor(DataModule_Base.a_string_cor_grid_tit_readonly);
        end;
      end
      else if (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] is TStringGrid) then
      begin
        (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).ParentColor := false;
        (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).AlternateColor:=StringtoColor(DataModule_Base.a_string_cor_grid_ac);
        (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).Color:=StringtoColor(DataModule_Base.a_string_cor_grid_col);
         for l_integer_aux2 := (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).Columns.Count - 1 downto 0 do
         begin
           if not (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).Columns[l_integer_aux2].ReadOnly then
             (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).Columns[l_integer_aux2].Title.Color:=StringtoColor(DataModule_Base.a_string_cor_grid_tit)
           else
             (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TStringGrid).Columns[l_integer_aux2].Title.Color:=StringtoColor(DataModule_Base.a_string_cor_grid_tit_readonly);
         end;
      end
      else if (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] is TLabel) then
      begin
           (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] as TLabel).Color:=StringtoColor(DataModule_Base.a_string_cor_form);
      end
      else if (screen.CustomForms[l_integer_aux1].Components[l_integer_aux] is TPageControl) then
      begin
        for l_integer_aux2 := TPageControl(screen.CustomForms[l_integer_aux1].Components[l_integer_aux]).PageCount - 1 downto 0 do
        begin
          for l_integer_aux3 := TPageControl(screen.CustomForms[l_integer_aux1].Components[l_integer_aux]).Pages[l_integer_aux2].ControlCount - 1 downto 0 do
          begin
            if (TPageControl(screen.CustomForms[l_integer_aux1].Components[l_integer_aux]).Pages[l_integer_aux2].Controls[l_integer_aux3] is TPanel) then
            begin
              (TPageControl(screen.CustomForms[l_integer_aux1].Components[l_integer_aux]).Pages[l_integer_aux2].Controls[l_integer_aux3] as TPanel).Color:=StringtoColor(DataModule_Base.a_string_cor_form);
            end;
          end;
        end;
      end;
    end;
  end;
end;

Probably the code should be unified to the above, to avoid duplications (I see this later - run first, optimize later).

You can add more properties of components that accept change colors.

See attached:

(google translator)

derek.john.evans

  • Guest
Re: Application colors - Dark.
« Reply #9 on: August 07, 2015, 05:00:36 pm »
A more generic approach would be to iterate the components. Ive done this in the past todo language translations and to ensure all controls had the correct options setup. ie: Scrollbars, pagecontrols starting on the first tab, forms are centered, etc.

I use this idea even as a sanity check to make sure I haven't forgotten to set an option in some dialog I haven't looked at in weeks.

Example code:
Code: Pascal  [Select][+][-]
  1. unit ColorTheme;
  2.  
  3. {$MODE DELPHI}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Graphics, StdCtrls;
  9.  
  10. type
  11.   TColorTheme = class
  12.   public
  13.     ColorForm, ColorEdit: TColor;
  14.   strict private
  15.     procedure Apply(const AControl: TMemo); overload;
  16.     procedure Apply(const AControl: TEdit); overload;
  17.     procedure Apply(const AControl: TCustomForm); overload;
  18.   public
  19.     procedure InitDefault;
  20.     procedure Apply; overload;
  21.   end;
  22.  
  23. var
  24.   GColorTheme: TColorTheme;
  25.  
  26. implementation
  27.  
  28. procedure TColorTheme.InitDefault;
  29. begin
  30.   ColorForm := clSkyBlue;
  31.   ColorEdit := clYellow;
  32. end;
  33.  
  34. procedure TColorTheme.Apply(const AControl: TMemo);
  35. begin
  36.   AControl.Color := ColorEdit;
  37. end;
  38.  
  39. procedure TColorTheme.Apply(const AControl: TEdit);
  40. begin
  41.   AControl.Color := ColorEdit;
  42. end;
  43.  
  44. procedure TColorTheme.Apply(const AControl: TCustomForm);
  45. var
  46.   LIndex: Integer;
  47. begin
  48.   with AControl do
  49.   begin
  50.     Color := ColorForm;
  51.     for LIndex := 0 to ComponentCount - 1 do
  52.     begin
  53.       if Components[LIndex] is TEdit then
  54.       begin
  55.         Apply(TEdit(Components[LIndex]));
  56.       end else if Components[LIndex] is TMemo then
  57.       begin
  58.         Apply(TMemo(Components[LIndex]));
  59.       end;
  60.     end;
  61.   end;
  62. end;
  63.  
  64. procedure TColorTheme.Apply;
  65. var
  66.   LIndex: Integer;
  67. begin
  68.   with Screen do
  69.   begin
  70.     for LIndex := 0 to CustomFormCount - 1 do
  71.     begin
  72.       Apply(CustomForms[LIndex]);
  73.     end;
  74.   end;
  75. end;
  76.  
  77. initialization
  78.  
  79.   GColorTheme := TColorTheme.Create;
  80.   GColorTheme.InitDefault;
  81.  
  82. end.
  83.  

I use this kinda stuff for auto label generation as well, because I HATE labeling controls. This is the code from Geep Jeez. I call J2C_WinControlCreateLabels(Self) in OnShow for a dialog.

Labels are grabbed from controls which have hint strings, and showhint is false. The hint can also be multi lined. The first line will be used for the label, the rest will be used for the hint of the control.

Code: Pascal  [Select][+][-]
  1. function J2C_ControlCreateLabel(const AControl: TControl): TPanel;
  2. var
  3.   LIndex: Integer;
  4.   LCaption, LHint: String;
  5.   LRect, LUnion: TRect;
  6. begin
  7.   Result := nil;
  8.   LHint := Trim(AControl.Hint);
  9.   if not AControl.ShowHint and (LHint <> EmptyStr) then
  10.   begin
  11.     AControl.ShowHint := True;
  12.     LRect := Rect(0, AControl.Top, AControl.Left, AControl.BoundsRect.Bottom);
  13.     for LIndex := 0 to AControl.Parent.ControlCount - 1 do
  14.     begin
  15.       LUnion := Bounds(0, 0, 0, 0);
  16.       if IntersectRect(LUnion, LRect, AControl.Parent.Controls[LIndex].BoundsRect) then
  17.       begin
  18.         LRect.Left := LUnion.Right;
  19.       end;
  20.     end;
  21.     if not IsRectEmpty(LRect) then
  22.     begin
  23.       LIndex := Pos(#10, LHint);
  24.       if LIndex > 0 then
  25.       begin
  26.         LCaption := Trim(Copy(LHint, 1, LIndex - 1));
  27.         LHint := Trim(Copy(LHint, LIndex + 1, MaxInt));
  28.       end else begin
  29.         LCaption := LHint;
  30.       end;
  31.       AControl.Hint := LHint;
  32.       if not GPlatform.IsWindows9x then
  33.       begin
  34.         AControl.Color := clInfoBlock;
  35.       end;
  36.       Result := TPanel.Create(AControl);
  37.       Result.BoundsRect := LRect;
  38.       Result.BorderWidth := 6;
  39.       Result.Alignment := taRightJustify;
  40.       Result.BevelOuter := bvNone;
  41.       Result.Caption := LCaption;
  42.       Result.Hint := LHint;
  43.       Result.ShowHint := True;
  44.       Result.Cursor := crHelp;
  45.       Result.Parent := AControl.Parent;
  46.       Result.Font.Color := clBlack;
  47.     end;
  48.   end;
  49. end;
  50.  
  51. procedure J2C_WinControlCreateLabels(const AWinControl: TWinControl);
  52. var
  53.   LIndex: Integer;
  54. begin
  55.   if (AWinControl is TCustomEdit) or (AWinControl is TDirectoryEdit) or
  56.     (AWinControl is TCustomComboBox) then
  57.   begin
  58.     J2C_ControlCreateLabel(AWinControl);
  59.   end;
  60.   for LIndex := 0 to AWinControl.ControlCount - 1 do
  61.   begin
  62.     if AWinControl.Controls[LIndex] is TWinControl then
  63.     begin
  64.       J2C_WinControlCreateLabels(TWinControl(AWinControl.Controls[LIndex]));
  65.     end;
  66.   end;
  67. end;
  68.  


EDIT: O, yeay. I also use it for saving/loading control settings to a inifile. Im sure there is a better way, but I seem to alway use the same idea. The code is a little long, and off topic.

« Last Edit: October 02, 2015, 03:34:01 am by Geepster »

 

TinyPortal © 2005-2018