The Road to Delphi

Delphi – Free Pascal – Oxygene

Disabling the VCL Styles in the non client area of a Form

12 Comments

Today I receive a question about how disable the vcl styles in the non client area of a vcl form. Well that can be done using a Style hook.

Tipically a VCL form with a vcl style look like this

To remove the vcl style in the non client are we need create a style hook which descend of the TMouseTrackControlStyleHook and then override the PaintBackground and Create methods.

Check this sample code

  TFormStyleHookNC= class(TMouseTrackControlStyleHook)
  protected
    procedure PaintBackground(Canvas: TCanvas); override;
    constructor Create(AControl: TWinControl); override;
  end;

constructor TFormStyleHookNC.Create(AControl: TWinControl);
begin
  inherited;
  OverrideEraseBkgnd := True;
end;

procedure TFormStyleHookNC.PaintBackground(Canvas: TCanvas);
var
  Details: TThemedElementDetails;
  R: TRect;
begin
  if StyleServices.Available then
  begin
    Details.Element := teWindow;
    Details.Part := 0;
    R := Rect(0, 0, Control.ClientWidth, Control.ClientHeight);
    StyleServices.DrawElement(Canvas.Handle, Details, R);
  end;
end;

And apply in this way

TStyleManager.Engine.RegisterStyleHook(TForm1, TFormStyleHookNC);

After of that this is the result

Author: Rodrigo

Just another Delphi guy.

12 thoughts on “Disabling the VCL Styles in the non client area of a Form

  1. Rodrigo,

    when I try to apply this stylehook in initialization section:

    initialization
    TStyleManager.Engine.RegisterStyleHook(TForm1, TFormStyleHookNC);

    I get an error immediately after program start:
    —————————
    Debugger Exception Notification
    —————————
    Project Project1.exe raised exception class $C0000005 with message ‘access violation at 0x0057019a: read of address 0x00000000’.
    —————————
    Break Continue Help
    —————————

    if I try to apply this stylehook in TForm1.OnCreate method, I don’t get any errors but this stylehook doesn’t apply (non-client areas are skinned)

    here is the priject:
    http://dl.dropbox.com/u/1237757/share/test/proj1.zip

    help me, please

    • This issue is caused because the vcl styles must be initializated before to call the RegisterStyleHook method, so you must include the Vcl.Styles unit in the implementation part of your main unit or reorder the unit declaration of your project to something like this

      uses
        Vcl.Forms,
        Vcl.Themes,
        Vcl.Styles,//the vcl styles unit is declared before of your main form.
        Unit1 in 'Unit1.pas' {Form1};
      
  2. Great tips on vcl styles, they have helped me tons lately on my project. And a little bit off topic question.. I have some minor issues with VirtualStringTree component, using your tips to do following: TStyleManager.Engine.RegisterStyleHook(TBaseVirtualTree, TListBoxStyleHook);
    (listbox, because TTreeViewStyleHook bugs with the scrollbars a bit), Anyway idea is to apply vcl style to the 3rd party component, it works great for the scrollbars which is what i want, but when vcl styles are enabled the VirtualTreeView flickers alot when the form is resized.. any hidden magic to prevent that or ideas ? it has to do with the repainting the control and the hook..but ? :) ..

  3. Great tip!

    He had problems using the VCL component TRibbon with Styles. The top edge of the screen was all wrong. Take the test yourself.
    But with this solution you have implemented solve the problem.

    I created a unit for class “TFormStyleHookNC” and made the call “TStyleManager.Engine.RegisterStyleHook (TForm1, TFormStyleHookNC)” in the project file (. dpr) after the begin. It worked perfectly.

    Thanks.

  4. Thank you Rodrigo for this hook !

    I have a question : how to apply this hook to “MessageDlg” and “ShowMessage” (…) ?

    Best :)

    Beny

    • If you are using a update minor than 4 you can use this code

      TStyleManager.Engine.RegisterStyleHook(TCustomTaskDialog, TFormStyleHookNC);
      

      If you are using the update 4, is more difficult because the StyleHook inheritance not work correctly (check this QC http://qc.embarcadero.com/wc/qcmain.aspx?d=104035), So the only alternative is use a code like this.

      TStyleManager.Engine.RegisterStyleHook(TForm, TFormStyleHookNC);
      

      And before to call the ShowMessage or MessageDlg functions set the value of the UseLatestCommonDialogs variable to false

        UseLatestCommonDialogs:=False;
        MessageDlg('Hello World',  mtWarning, [mbOK], 0);
        UseLatestCommonDialogs:=True;
      
  5. thx!
    well, how to enable vclstyles only for some control(controls) ?

  6. hi. if i use this hook i have problem with TMainMenu. how can i use TMainMenu with this hook?

    • The TMainMenu is outside of the scope of this hook, so you have two workarounds , 1) implement the TMainMenu Style hook inside of the TFormStyleHookNC class just how is made in the TFormStyleHook style hook, 2) or replace the TMainMenu for the TActionMainMenuBar component.

Leave a comment