Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exclude VCL Styles from styling Dialog / ShowMessage borders

Is there any way to exclude VCL Styles from styling a system dialogs' border.

Sepecifically a dialog that is shown by calling MessageDlg or ShowMessage.

I read some articles on "The Road To Delphi" (which is an excellent site btw) but couldn't find the answer.

Here is what i want to achieve:

Now (Carbon Style with styled borders):

now

Goal (Carbon Style with standard windows borders):

enter image description here

I still want to have styled controls but no styled border.

Removing seBorder from the parent forms StyleElements doesn't do the trick.

enter image description here

Thanks!

like image 862
ChrisB Avatar asked Mar 14 '15 07:03

ChrisB


2 Answers

MessageDlg() and ShowMessage() are Delphi VCL functions. They dynamically create a Delphi TForm and display that, so you do not have a chance to customise it. However, you can use CreateMessageDialog() instead to create the same TForm, then modify its style elements as needed, and then show it. For instance:

function DoMessageDlgPosHelp(MessageDialog: TForm; X, Y: Integer): Integer;
begin
  with MessageDialog do
    try
      if X >= 0 then Left := X;
      if Y >= 0 then Top := Y;
      if (Y < 0) and (X < 0) then Position := poScreenCenter;
      Result := ShowModal;
    finally
      Free;
    end;
end;

procedure ShowStyledMessage(const Msg: string; const StyleElements: TStyleElements);
var
  Form: TForm;
begin
  Form := CreateMessageDialog(Msg, mtCustom, [mbOK]);
  Form.StyleElements := StyleElements;
  DoMessageDlgPosHelp(Form, -1, -1);
end;

Call it like this:

ShowStyledMessage('Some text', [seFont, seClient]);

And the dialog looks like this:

screenshot

like image 103
David Heffernan Avatar answered Oct 27 '22 12:10

David Heffernan


To have styled form without borders you have to remove seBorder from form's StyleElements property.

  StyleElements := [seFont, seClient];

From form designer

But you have to set that property for each and every form. If I understood you correctly you want to show message dialog with Windows border. In that case setting StyleElements property for form that invokes ShowMessage will have no effect on dialog box, because that is completely new form.

What you have to do is to somehow set StyleElements property for dialog form that Delphi creates out of your reach. To do that you have to create your own form StyleHook and replace TFormStyleHook registered for all forms.

Just add following unit in your project and all forms will have Windows border, without the need to set it explicitly for every form.

unit WinBorder;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  Vcl.Themes,
  Vcl.Controls,
  Vcl.Forms;

type
  TWinBorderFormStyleHook = class(TFormStyleHook)
  protected
    procedure WndProc(var Message: TMessage); override;
  public
    constructor Create(AControl: TWinControl); override;
  end;

implementation

constructor TWinBorderFormStyleHook.Create(AControl: TWinControl);
begin
  inherited;
  OverridePaintNC := false;
end;

procedure TWinBorderFormStyleHook.WndProc(var Message: TMessage);
begin
  inherited;
  if Message.Msg = CM_VISIBLECHANGED then
    begin
      if (Control is TCustomForm) and (seBorder in TCustomForm(Control).StyleElements) then
        TCustomForm(Control).StyleElements := [seFont, seClient];
    end;
end;

initialization

  TCustomStyleEngine.UnRegisterStyleHook(TCustomForm, TFormStyleHook);
  TCustomStyleEngine.UnRegisterStyleHook(TForm, TFormStyleHook);
  TCustomStyleEngine.RegisterStyleHook(TCustomForm, TWinBorderFormStyleHook);
  TCustomStyleEngine.RegisterStyleHook(TForm, TWinBorderFormStyleHook);

finalization

  TCustomStyleEngine.UnRegisterStyleHook(TCustomForm, TWinBorderFormStyleHook);
  TCustomStyleEngine.UnRegisterStyleHook(TForm, TWinBorderFormStyleHook);
  TCustomStyleEngine.RegisterStyleHook(TCustomForm, TFormStyleHook);
  TCustomStyleEngine.RegisterStyleHook(TForm, TFormStyleHook);

end.
like image 28
Dalija Prasnikar Avatar answered Oct 27 '22 12:10

Dalija Prasnikar