TTitleBarPanel overlapping nested Panel when the main Form loses focus - delphi

When running a 32-bit VCL Application in Windows 10 in Delphi 11 Alexandria, initially it looks fine (except the Mainmenu is hidden):
But as soon as the window loses focus, the TTitleBarPanel OVERLAPS pnlHeader (which is a nested TPanel inside a TCard):
But I have done as the Documentation says: Put everything except the TTitleBarPanel on a client-aligned Panel.
How can this overlapping be avoided?
Here is the Unit:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.Menus,
Vcl.TitleBarCtrls, Vcl.WinXPanels;
type
TForm1 = class(TForm)
MainMenu1: TMainMenu;
menuitemOptions: TMenuItem;
menuitemPreferences: TMenuItem;
menuitemAbout: TMenuItem;
pnlHeader: TPanel;
TitleBarPanel1: TTitleBarPanel;
CardPanel1: TCardPanel;
Card1: TCard;
Panel1: TPanel;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
end.
And here is the Form:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 294
ClientWidth = 515
Color = clSilver
CustomTitleBar.Control = TitleBarPanel1
CustomTitleBar.Enabled = True
CustomTitleBar.Height = 34
CustomTitleBar.BackgroundColor = clWhite
CustomTitleBar.ForegroundColor = 65793
CustomTitleBar.InactiveBackgroundColor = clWhite
CustomTitleBar.InactiveForegroundColor = 10066329
CustomTitleBar.ButtonForegroundColor = 65793
CustomTitleBar.ButtonBackgroundColor = clWhite
CustomTitleBar.ButtonHoverForegroundColor = 65793
CustomTitleBar.ButtonHoverBackgroundColor = 16053492
CustomTitleBar.ButtonPressedForegroundColor = 65793
CustomTitleBar.ButtonPressedBackgroundColor = 15395562
CustomTitleBar.ButtonInactiveForegroundColor = 10066329
CustomTitleBar.ButtonInactiveBackgroundColor = clWhite
DoubleBuffered = True
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Segoe UI'
Font.Style = []
GlassFrame.Enabled = True
GlassFrame.Top = 34
Menu = MainMenu1
Position = poScreenCenter
StyleElements = [seFont, seClient]
PixelsPerInch = 96
TextHeight = 15
object TitleBarPanel1: TTitleBarPanel
Left = 0
Top = 0
Width = 515
Height = 34
CustomButtons = <>
ExplicitWidth = 608
end
object Panel1: TPanel
Left = 0
Top = 34
Width = 515
Height = 260
Align = alClient
BevelOuter = bvNone
TabOrder = 1
ExplicitTop = 33
ExplicitWidth = 608
ExplicitHeight = 296
object CardPanel1: TCardPanel
Left = 0
Top = 0
Width = 515
Height = 260
Align = alClient
ActiveCard = Card1
BevelOuter = bvNone
Caption = 'CardPanel1'
TabOrder = 0
ExplicitTop = 34
ExplicitWidth = 608
ExplicitHeight = 355
object Card1: TCard
Left = 0
Top = 0
Width = 515
Height = 260
Caption = 'Card1'
CardIndex = 0
DoubleBuffered = True
ParentDoubleBuffered = False
TabOrder = 0
ExplicitWidth = 608
ExplicitHeight = 355
object pnlHeader: TPanel
Left = 0
Top = 0
Width = 515
Height = 32
Margins.Left = 100
Margins.Top = 0
Margins.Right = 150
Margins.Bottom = 0
Align = alTop
Alignment = taLeftJustify
BevelOuter = bvNone
Color = 16443110
Font.Charset = DEFAULT_CHARSET
Font.Color = clGrayText
Font.Height = -19
Font.Name = 'Segoe UI'
Font.Style = []
ParentBackground = False
ParentFont = False
TabOrder = 0
ExplicitWidth = 608
end
end
end
end
object MainMenu1: TMainMenu
Left = 320
Top = 192
object menuitemOptions: TMenuItem
Caption = 'Options'
object menuitemPreferences: TMenuItem
Caption = 'Toggle Preferences'
ShortCut = 123
end
object menuitemAbout: TMenuItem
Caption = 'About'
ShortCut = 121
end
end
end
end

Related

Delphi-docking form hides panel

I have a problem that docking form hides some other components inside of panel.
This is simple example of my problem: I have Panel1 with DockSite set to True. Inside Panel1 is Panel2. Panel2 alignts to client (Align=alClient). Inside Panel2 is memo field that is also aligned to client. It overlaps the entire Panel1.
I have another form (Form2) that I want to dock to Panel1. But it overlaps entire Panel1 and hides memo filed. I want to overlap only part of Panel1 (width of the form) and move Panel2 to the rigth or to te left.
Main form:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Panel1: TPanel;
Panel2: TPanel;
Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses Unit2;
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.Show;
end;
end.
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 333
ClientWidth = 754
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Segoe UI'
Font.Style = []
PixelsPerInch = 96
TextHeight = 15
object Button1: TButton
Left = 288
Top = 271
Width = 153
Height = 41
Caption = 'Show dockable form'
TabOrder = 0
OnClick = Button1Click
end
object Panel1: TPanel
Left = 8
Top = 8
Width = 729
Height = 257
Caption = 'Panel1'
DockSite = True
TabOrder = 1
object Panel2: TPanel
Left = 1
Top = 1
Width = 727
Height = 255
Align = alClient
Caption = 'Panel2'
TabOrder = 0
ExplicitLeft = 360
ExplicitTop = 8
ExplicitWidth = 337
ExplicitHeight = 241
object Memo1: TMemo
Left = 1
Top = 1
Width = 725
Height = 253
Align = alClient
Lines.Strings = (
'Memo1')
TabOrder = 0
ExplicitWidth = 216
ExplicitHeight = 144
end
end
end
end
Docking form:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm2 = class(TForm)
Label1: TLabel;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
end.
object Form2: TForm2
Left = 0
Top = 0
Caption = 'Form2'
ClientHeight = 103
ClientWidth = 273
Color = clBtnFace
DragKind = dkDock
DragMode = dmAutomatic
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Segoe UI'
Font.Style = []
PixelsPerInch = 96
TextHeight = 15
object Label1: TLabel
Left = 22
Top = 24
Width = 227
Height = 45
Caption = 'Dockable form'
DragKind = dkDock
DragMode = dmAutomatic
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -33
Font.Name = 'Segoe UI'
Font.Style = []
ParentFont = False
end
end
The dynamics soon become difficult to master with changing dock sites and alignment changes, but I think the following will do what you ask for.
Change the hierarchy of Form1 to the following and note that Panel2 and Memo1 both are childs of Panel1. Panel2 will act as the docking target. I have set Panel2.Width to 8, to have a visual area where to drop Form2. Here are the essential properties:
object Form1: TForm1
object Button1: TButton
object Panel1: TPanel
Caption = 'Panel1'
object Panel2: TPanel
Width = 8
Align = alRight
Caption = 'Panel2'
DockSite = True
OnDockDrop = Panel2DockDrop
OnDockOver = Panel2DockOver
OnUnDock = Panel2UnDock
end
object Memo1: TMemo
Align = alClient
end
end
end
When Form2 is dragged over Panel2 the OnDockOver event is triggered. Panel2 sets its width to half the width of Panel1, which in turn reduces the Memo1 width with the same amount. (Change as you need)
procedure TForm1.Panel2DockOver(Sender: TObject; Source: TDragDockObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
Panel2.Width := Panel1.Width div 2;
end;
When Form2 is dropped on Panel2, the DockRect of the form is set to the rect of Panel2.
procedure TForm1.Panel2DockDrop(Sender: TObject; Source: TDragDockObject; X, Y: Integer);
begin
Source.DockRect := Rect(Panel2.Width, Panel2.Top, Panel2.Width, Panel2.Height);
end;
When Form2 is undocked from Panel2 it reduces its width to the 8 pixels, which again widen the Memo1 to its original width.
procedure TForm1.Panel2UnDock(Sender: TObject; Client: TControl; NewTarget: TWinControl;
var Allow: Boolean);
begin
Panel2.Width := 8;
end;
Here's the complete .dfm of Form1:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 333
ClientWidth = 425
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -12
Font.Name = 'Segoe UI'
Font.Style = []
OldCreateOrder = True
PixelsPerInch = 96
TextHeight = 15
object Button1: TButton
Left = 120
Top = 284
Width = 153
Height = 41
Caption = 'Show dockable form'
TabOrder = 0
OnClick = Button1Click
end
object Panel1: TPanel
Left = 8
Top = 8
Width = 400
Height = 257
Caption = 'Panel1'
TabOrder = 1
object Panel2: TPanel
Left = 391
Top = 1
Width = 8
Height = 255
Align = alRight
Caption = 'Panel2'
DockSite = True
TabOrder = 0
OnDockDrop = Panel2DockDrop
OnDockOver = Panel2DockOver
OnUnDock = Panel2UnDock
ExplicitLeft = 394
end
object Memo1: TMemo
Left = 1
Top = 1
Width = 390
Height = 255
Align = alClient
Lines.Strings = (
'Memo1')
TabOrder = 1
ExplicitWidth = 725
ExplicitHeight = 253
end
end
end

TCoolBar band resizing problem in Delphi 10.3

I put a TCoolBar component into a brand new project in Delphi 10.3. There are some bands in a row. When I resize one band, the others on its right in the same row resize too. I can decrease or increase the band size, the others on the right always grow by the difference. If I resize the form all the band gone wild. They all increase their sizes.
The error does not occure if I create a band by the band editor. It occures when I drop down some TActionToolBar into the TCoolBar.
The CoolBar AutoSize does not set. The bands or TActionToolBar has not a property like this.
The pas file:
unit Unit2;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ToolWin, Vcl.ComCtrls,
Vcl.PlatformDefaultStyleActnCtrls, System.Actions, Vcl.ActnList, Vcl.ActnMan,
Vcl.ActnCtrls;
type
TForm2 = class(TForm)
ActionManager1: TActionManager;
CoolBar1: TCoolBar;
ActionToolBar1: TActionToolBar;
ActionToolBar2: TActionToolBar;
ActionToolBar3: TActionToolBar;
ActionToolBar4: TActionToolBar;
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
end.
The dpr file:
object Form2: TForm2
Left = 0
Top = 0
Caption = 'Form2'
ClientHeight = 405
ClientWidth = 635
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object CoolBar1: TCoolBar
Left = 0
Top = 0
Width = 635
Height = 65
Bands = <
item
Control = ActionToolBar1
ImageIndex = -1
Width = 148
end
item
Break = False
Control = ActionToolBar2
ImageIndex = -1
Width = 477
end
item
Control = ActionToolBar3
ImageIndex = -1
Width = 146
end
item
Break = False
Control = ActionToolBar4
ImageIndex = -1
Width = 479
end>
FixedSize = True
object ActionToolBar1: TActionToolBar
Left = 11
Top = 0
Width = 135
Height = 25
Caption = 'ActionToolBar1'
Color = clMenuBar
ColorMap.DisabledFontColor = 7171437
ColorMap.HighlightColor = clWhite
ColorMap.BtnSelectedFont = clBlack
ColorMap.UnusedColor = clWhite
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
Spacing = 0
end
object ActionToolBar2: TActionToolBar
Left = 163
Top = 0
Width = 468
Height = 25
Caption = 'ActionToolBar2'
Color = clMenuBar
ColorMap.DisabledFontColor = 7171437
ColorMap.HighlightColor = clWhite
ColorMap.BtnSelectedFont = clBlack
ColorMap.UnusedColor = clWhite
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
Spacing = 0
end
object ActionToolBar3: TActionToolBar
Left = 11
Top = 27
Width = 133
Height = 25
Caption = 'ActionToolBar3'
Color = clMenuBar
ColorMap.DisabledFontColor = 7171437
ColorMap.HighlightColor = clWhite
ColorMap.BtnSelectedFont = clBlack
ColorMap.UnusedColor = clWhite
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
Spacing = 0
end
object ActionToolBar4: TActionToolBar
Left = 161
Top = 27
Width = 470
Height = 25
Caption = 'ActionToolBar4'
Color = clMenuBar
ColorMap.DisabledFontColor = 7171437
ColorMap.HighlightColor = clWhite
ColorMap.BtnSelectedFont = clBlack
ColorMap.UnusedColor = clWhite
Font.Charset = DEFAULT_CHARSET
Font.Color = clBlack
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
ParentFont = False
Spacing = 0
end
end
object ActionManager1: TActionManager
Left = 248
Top = 160
StyleName = 'Platform Default'
end
end
Is there any solution for this problem?

How to correctly use TGridPanel when display PPI scaling is active?

I have written a small test VCL application with a monitor PPI of 96.
The application has a TGridPanel on it with a absolute pixel sized column.
On that column I placed a TComboBox and aligned it alClient.
Here is the DFM code:
object Form1: TForm1
Left = 0
Top = 0
Caption = 'Form1'
ClientHeight = 182
ClientWidth = 514
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object GridPanel1: TGridPanel
Left = 0
Top = 0
Width = 514
Height = 182
Align = alClient
Caption = 'GridPanel1'
ColumnCollection = <
item
Value = 100.000000000000000000
end
item
SizeStyle = ssAbsolute
Value = 150.000000000000000000
end>
ControlCollection = <
item
Column = 0
Control = Button1
Row = 0
end
item
Column = 1
Control = ComboBox1
Row = 0
end
item
Column = 0
Control = Edit1
Row = 1
end>
RowCollection = <
item
Value = 50.000000000000000000
end
item
Value = 50.000000000000000000
end>
TabOrder = 0
object Button1: TButton
Left = 1
Top = 1
Width = 362
Height = 21
Align = alTop
Caption = 'Button1'
TabOrder = 0
OnClick = Button1Click
end
object ComboBox1: TComboBox
Left = 363
Top = 1
Width = 150
Height = 21
Align = alClient
TabOrder = 1
Text = 'ComboBox1'
end
object Edit1: TEdit
Left = 1
Top = 91
Width = 362
Height = 21
Align = alTop
TabOrder = 2
Text = 'Edit1'
end
end
end
and the PAS code:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;
type
TForm1 = class(TForm)
GridPanel1: TGridPanel;
Button1: TButton;
ComboBox1: TComboBox;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
PPI: Integer;
begin
PPI := Integer.Parse(Edit1.Text);
GridPanel1.ScaleForPPI(PPI);
end;
procedure TForm1.FormShow(Sender: TObject);
begin
Edit1.Text := Screen.PixelsPerInch.ToString;
end;
end.
I then changed the custom scaling factor to 125 in Windows 10 in the advanced scaling settings.
After signing off and signing on again when I run the application again the drop down button of the combo box is not visible any more.
How do you deal with this problem?
I tried to call GridPanel1.ScaleForPPI(96) which restores the drop down button on the combo box. This kind of defeats the purpose of PPI scaling though, doesn't it?
The problem is gone in Delphi 10.3.1.
So this is a bug in at least Delphi 10.1 (and possible other older versions).

How to have an absolute row between two percentage rows when adding to a TGridPanel from code?

I am trying to create a Form with a TGridPanel from code.
It contains:
A memo at the top (which is set to 50%)
A navigator at the center (which is set to 24 pixels)
A grid at the bottom (which is set to 50%)
This is the code I wrote:
uses
Winapi.Messages, Winapi.Windows, System.Classes, System.SysUtils,
System.UITypes, System.Variants, Vcl.Controls, Vcl.DBCtrls, Vcl.DBGrids,
Vcl.Dialogs, Vcl.ExtCtrls, Vcl.Forms, Vcl.Graphics, Vcl.Grids, Vcl.StdCtrls,
Data.DB;
procedure Test;
var
View: TForm;
GridPanel: TGridPanel;
Grid: TDBGrid;
DataSource: TDataSource;
Navigator: TDBNavigator;
Memo: TMemo;
begin
View := TForm.Create(Application);
try
View.Name := 'Form2';
// SystemFont(View.Font);
View.Width := 640;
View.Height := 480;
View.Position := TPosition.poOwnerFormCenter;
GridPanel := TGridPanel.Create(View);
GridPanel.Name := 'GridPanel';
GridPanel.Caption := '';
GridPanel.BevelOuter := TBevelCut.bvNone;
GridPanel.FullRepaint := False;
GridPanel.Parent := View;
GridPanel.Align := TAlign.alClient;
GridPanel.ColumnCollection.BeginUpdate;
GridPanel.ColumnCollection.Delete(1);
GridPanel.ColumnCollection[0].Value := 100;
GridPanel.ColumnCollection.EndUpdate;
GridPanel.RowCollection.BeginUpdate;
GridPanel.RowCollection.Add;
TCellItem(GridPanel.RowCollection[0]).Value := 50;
TCellItem(GridPanel.RowCollection[0]).SizeStyle := TSizeStyle.ssPercent;
TCellItem(GridPanel.RowCollection[1]).Value := 24;
TCellItem(GridPanel.RowCollection[1]).SizeStyle := TSizeStyle.ssAbsolute;
TCellItem(GridPanel.RowCollection[2]).Value := 50;
TCellItem(GridPanel.RowCollection[2]).SizeStyle := TSizeStyle.ssPercent;
GridPanel.RowCollection.EndUpdate;
Memo := TMemo.Create(View);
Memo.Name := 'Memo';
Memo.Parent := GridPanel;
Memo.Lines.Clear;
Memo.Align := TAlign.alClient;
DataSource := TDataSource.Create(View);
Navigator := TDBNavigator.Create(View);
Navigator.Name := 'Navigator';
Navigator.DataSource := DataSource;
Navigator.Parent := GridPanel;
Navigator.Align := TAlign.alClient;
Grid := TDBGrid.Create(View);
Grid.Name := 'Grid';
Grid.Parent := GridPanel;
Grid.Align := TAlign.alClient;
Grid.DataSource := DataSource;
{
GridPanel.ControlCollection.BeginUpdate;
GridPanel.ControlCollection.AddControl(Memo, 0, 0);
GridPanel.ControlCollection.AddControl(Navigator, 0, 1);
GridPanel.ControlCollection.AddControl(Grid, 0, 2);
GridPanel.ControlCollection.EndUpdate;
}
// ShowMessage(ComponentToString(View));
View.ShowModal;
finally
View.Free;
end;
end
The result looks like this:
The Problem: There is a gap at the bottom of the form and no DB navigator to be seen!
A dump of the DFM looks fine to me:
object Form2: TForm
Left = 0
Top = 0
Caption = 'Form2'
ClientHeight = 441
ClientWidth = 624
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
Position = poOwnerFormCenter
PixelsPerInch = 96
TextHeight = 13
object GridPanel: TGridPanel
Left = 0
Top = 0
Width = 624
Height = 441
Align = alClient
BevelOuter = bvNone
ColumnCollection = <
item
Value = 100.000000000000000000
end>
ControlCollection = <
item
Column = 0
Control = Memo
Row = 0
end
item
Column = 0
Control = Navigator
Row = 1
end
item
Column = 0
Control = Grid
Row = 2
end>
FullRepaint = False
RowCollection = <
item
Value = 50.000000000000000000
end
item
SizeStyle = ssAbsolute
Value = 24.000000000000000000
end
item
Value = 50.000000000000000000
end>
TabOrder = 0
object Memo: TMemo
Left = 0
Top = 0
Width = 624
Height = 208
Align = alClient
TabOrder = 0
ExplicitLeft = 219
ExplicitTop = 59
ExplicitWidth = 185
ExplicitHeight = 89
end
object Navigator: TDBNavigator
Left = 0
Top = 208
Width = 624
Height = 18
Align = alClient
TabOrder = 1
ExplicitTop = 0
ExplicitWidth = 240
ExplicitHeight = 25
end
object Grid: TDBGrid
Left = 0
Top = 208
Width = 624
Height = 209
Align = alClient
TabOrder = 2
TitleFont.Charset = DEFAULT_CHARSET
TitleFont.Color = clWindowText
TitleFont.Height = -11
TitleFont.Name = 'Tahoma'
TitleFont.Style = []
end
end
object TDataSource
end
end
When I change the position, the Navigator is at the correct position, but I want it to be absolute.
TCellItem(GridPanel.RowCollection[1]).Value := 5;
TCellItem(GridPanel.RowCollection[1]).SizeStyle := TSizeStyle.ssPercent;
Why does TGridPanel behave so strange in this case? What can I do about it?
Change the order of setting SizeStyle and Value.
TCellItem(GridPanel.RowCollection[0]).SizeStyle := TSizeStyle.ssPercent;
TCellItem(GridPanel.RowCollection[0]).Value := 50;
TCellItem(GridPanel.RowCollection[1]).SizeStyle := TSizeStyle.ssAbsolute;
TCellItem(GridPanel.RowCollection[1]).Value := 24;
TCellItem(GridPanel.RowCollection[2]).SizeStyle := TSizeStyle.ssPercent;
TCellItem(GridPanel.RowCollection[2]).Value := 50;

Flickering when TPageControl has many tabs

My problem is that I have a TPageControl which contains a dynamically created number of tabs each containing a single (alClient) TMemo. When this number of tabs exceeds the width of the control and the scroll arrows appear on the tab header, all (well a large number) of my controls start to flicker a lot. This flicker only occurs when the pagecontrol is visible once you scroll out of view of the TPageControl it stops. When the pagecontrol is resized so that the scroll arrows are no longer required to see all of the tabs then the flickering stops.
I'm fairly confident that the problem is caused by the scroll arrows causing some painting to occur because when I set the TPageControl.MultiLine to true then there is no flickering. Ideally I wouldn't want to use MultiLine tabs and hope someone can provide a solution.
Information about form layout
I have a (Personal Details) form which contains a number of TSpeedButtons, TLabels, TEdits, a TImage and so on. Many of these elements are inside of a TScrollBox and are grouped into sections using TPanels. The panels are set to alTop in the scrollbox and have autosize set to true but their height never changes.
I have tried setting all controls to have DoubleBuffered set to true where possible and ParentBackground/Color = false but sadly nothing works.
I had flickering issues before adding the PageControls and using David's quick hack answer here TLabel and TGroupbox Captions Flicker on Resize I was able to improve the flickering when resizing the form. By extending TLabel and removing the background clearing from the Paint procedure, as recommended somewhere else, I was able to 99% remove the labels flickering when scrolling the ScrollBox but now I have a new flickering problem.
---EDIT---
Here is a link to a stripped down version of my form with the flickering occurring flickering example
Personnel.DetailsForm.pas
unit Personnel.DetailsForm;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, System.Actions,
Vcl.ActnList, Vcl.Buttons, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.WinXCtrls, Vcl.Imaging.jpeg;
type
TPersonnelDetailsForm = class(TForm)
ScrollBox_Content: TScrollBox;
panel_AddressDetails: TPanel;
gpanel_Address: TGridPanel;
edit_HomeMobilePhone: TEdit;
edit_HomeTown: TEdit;
edit_HomeStreet: TEdit;
edit_HomePhone: TEdit;
lbl_HomeStreet: TLabel;
lbl_HomePhone: TLabel;
lbl_MobilePhone: TLabel;
lbl_HomeTown: TLabel;
edit_HomeState: TEdit;
edit_HomeEmail: TEdit;
edit_HomeCountry: TEdit;
edit_HomeFax: TEdit;
lbl_HomeState: TLabel;
lbl_Fax: TLabel;
lbl_Email: TLabel;
lbl_HomeCountry: TLabel;
edit_HomePostCode: TEdit;
lbl_HomePostCode: TLabel;
panel_HomeAddressTitle: TPanel;
panel_GeneralNotesDetails: TPanel;
gpanel_GeneralNotesDetails_: TGridPanel;
pageControl_GeneralNotes: TPageControl;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormShow(Sender: TObject);
procedure FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
private
{ Private declarations }
public
{ Public declarations }
end;
var
PersonnelDetailsForm: TPersonnelDetailsForm;
implementation
{$R *.dfm}
uses
System.Math,
System.DateUtils,
System.Threading,
System.RegularExpressions,
System.StrUtils,
System.Contnrs,
System.UITypes,
System.Types,
Winapi.Shellapi,
Vcl.ExtDlgs;
procedure EnableComposited(WinControl: TWinControl);
var
i: Integer;
NewExStyle: DWORD;
begin
NewExStyle := GetWindowLong(WinControl.Handle, GWL_EXSTYLE) or WS_EX_COMPOSITED;
SetWindowLong(WinControl.Handle, GWL_EXSTYLE, NewExStyle);
for i := 0 to WinControl.ControlCount - 1 do
if WinControl.Controls[i] is TWinControl then
EnableComposited(TWinControl(WinControl.Controls[i]));
end;
procedure TPersonnelDetailsForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// Close the form and make sure it frees itself
Action := caFree; // Should allow it to free itself on close
self.Release; // Sends a Release message to itself as backup
end;
procedure TPersonnelDetailsForm.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
var Handled: Boolean);
var
LTopLeft, LTopRight, LBottomLeft, LBottomRight: Integer;
LPoint: TPoint;
begin
Handled := true;
// First you have to get the position of the control on screen
// as MousePos coordinates are based on the screen positions.
LPoint := self.ScrollBox_Content.ClientToScreen(Point(0, 0));
LTopLeft := LPoint.X;
LTopRight := LTopLeft + self.ScrollBox_Content.Width;
LBottomLeft := LPoint.Y;
LBottomRight := LBottomLeft + self.ScrollBox_Content.Width;
if (MousePos.X >= LTopLeft) and (MousePos.X <= LTopRight) and (MousePos.Y >= LBottomLeft) and (MousePos.Y <= LBottomRight) then
begin
// If the mouse is inside the scrollbox coordinates,
// scroll it by setting .VertScrollBar.Position.
self.ScrollBox_Content.VertScrollBar.Position := self.ScrollBox_Content.VertScrollBar.Position - WheelDelta;
Handled := true;
end;
if FindVCLWindow(MousePos) is TComboBox then
Handled := true;
end;
procedure TPersonnelDetailsForm.FormShow(Sender: TObject);
var
memo: TMemo;
tabsheet: TTabSheet;
ii: Integer;
begin
for ii := 0 to 7 do
begin
memo := TMemo.Create(self);
memo.Align := TAlign.alClient;
memo.ReadOnly := true;
memo.ScrollBars := TScrollStyle.ssVertical;
memo.ParentColor := false;
tabsheet := TTabSheet.Create(self);
tabsheet.InsertControl(memo);
tabsheet.PageControl := self.pageControl_GeneralNotes;
tabsheet.Caption := 'A New TabSheet ' + IntToStr(ii);
tabsheet.Tag := ii;
memo.Text := 'A New Memo ' + IntToStr(ii);
end;
EnableComposited(self);
self.ScrollBox_Content.ScrollInView(self.panel_AddressDetails);
self.Invalidate;
end;
end.
Personnel.DetailsForm.dfm
object PersonnelDetailsForm: TPersonnelDetailsForm
Left = 0
Top = 0
Caption = 'Personnel Details Form'
ClientHeight = 371
ClientWidth = 800
Color = clBtnFace
DoubleBuffered = True
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = []
OldCreateOrder = False
OnClose = FormClose
OnMouseWheel = FormMouseWheel
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 17
object ScrollBox_Content: TScrollBox
Left = 0
Top = 0
Width = 800
Height = 371
VertScrollBar.Smooth = True
VertScrollBar.Tracking = True
Align = alClient
TabOrder = 0
object panel_AddressDetails: TPanel
Tag = 101
Left = 0
Top = 0
Width = 796
Height = 174
Align = alTop
Padding.Left = 5
Padding.Top = 5
Padding.Right = 5
Padding.Bottom = 5
ParentBackground = False
TabOrder = 0
object gpanel_Address: TGridPanel
Left = 6
Top = 30
Width = 784
Height = 138
Align = alClient
BevelOuter = bvNone
ColumnCollection = <
item
SizeStyle = ssAbsolute
Value = 105.000000000000000000
end
item
Value = 50.000762951094850000
end
item
SizeStyle = ssAbsolute
Value = 105.000000000000000000
end
item
Value = 49.999237048905160000
end>
ControlCollection = <
item
Column = 3
Control = edit_HomeMobilePhone
Row = 1
end
item
Column = 1
Control = edit_HomeTown
Row = 1
end
item
Column = 1
Control = edit_HomeStreet
Row = 0
end
item
Column = 3
Control = edit_HomePhone
Row = 0
end
item
Column = 0
Control = lbl_HomeStreet
Row = 0
end
item
Column = 2
Control = lbl_HomePhone
Row = 0
end
item
Column = 2
Control = lbl_MobilePhone
Row = 1
end
item
Column = 0
Control = lbl_HomeTown
Row = 1
end
item
Column = 1
Control = edit_HomeState
Row = 2
end
item
Column = 3
Control = edit_HomeEmail
Row = 2
end
item
Column = 1
Control = edit_HomeCountry
Row = 3
end
item
Column = 3
Control = edit_HomeFax
Row = 3
end
item
Column = 0
Control = lbl_HomeState
Row = 2
end
item
Column = 2
Control = lbl_Fax
Row = 3
end
item
Column = 2
Control = lbl_Email
Row = 2
end
item
Column = 0
Control = lbl_HomeCountry
Row = 3
end
item
Column = 1
Control = edit_HomePostCode
Row = 4
end
item
Column = 0
Control = lbl_HomePostCode
Row = 4
end>
Padding.Left = 1
Padding.Top = 1
Padding.Right = 1
Padding.Bottom = 1
RowCollection = <
item
SizeStyle = ssAbsolute
Value = 27.000000000000000000
end
item
SizeStyle = ssAbsolute
Value = 27.000000000000000000
end
item
SizeStyle = ssAbsolute
Value = 27.000000000000000000
end
item
SizeStyle = ssAbsolute
Value = 27.000000000000000000
end
item
SizeStyle = ssAbsolute
Value = 27.000000000000000000
end>
TabOrder = 0
object edit_HomeMobilePhone: TEdit
Left = 498
Top = 29
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 6
Text = 'Mobile Phone'
end
object edit_HomeTown: TEdit
Left = 107
Top = 29
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 1
Text = 'Home Town'
end
object edit_HomeStreet: TEdit
Left = 107
Top = 2
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 0
Text = 'Home Street'
end
object edit_HomePhone: TEdit
Left = 498
Top = 2
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 5
Text = 'Home Phone'
end
object lbl_HomeStreet: TLabel
Left = 2
Top = 2
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Street: '
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentColor = False
ParentFont = False
Transparent = True
Layout = tlCenter
ExplicitLeft = 61
ExplicitWidth = 44
ExplicitHeight = 17
end
object lbl_HomePhone: TLabel
Left = 393
Top = 2
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Home Phone: '
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentFont = False
Layout = tlCenter
ExplicitLeft = 408
ExplicitWidth = 88
ExplicitHeight = 17
end
object lbl_MobilePhone: TLabel
Left = 393
Top = 29
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Mobile Phone: '
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentFont = False
Layout = tlCenter
ExplicitLeft = 402
ExplicitWidth = 94
ExplicitHeight = 17
end
object lbl_HomeTown: TLabel
Left = 2
Top = 29
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Town: '
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentColor = False
ParentFont = False
Transparent = True
Layout = tlCenter
ExplicitLeft = 64
ExplicitWidth = 41
ExplicitHeight = 17
end
object edit_HomeState: TEdit
Left = 107
Top = 56
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 2
Text = 'Home State'
end
object edit_HomeEmail: TEdit
Left = 498
Top = 56
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 7
Text = 'Home Email'
end
object edit_HomeCountry: TEdit
Left = 107
Top = 83
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 3
Text = 'Home Country'
end
object edit_HomeFax: TEdit
Left = 498
Top = 83
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 8
Text = 'Home Fax'
end
object lbl_HomeState: TLabel
Left = 2
Top = 56
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'State: '
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentColor = False
ParentFont = False
Transparent = True
Layout = tlCenter
ExplicitLeft = 66
ExplicitWidth = 39
ExplicitHeight = 17
end
object lbl_Fax: TLabel
Left = 393
Top = 83
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Fax: '
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentFont = False
Layout = tlCenter
ExplicitLeft = 467
ExplicitWidth = 29
ExplicitHeight = 17
end
object lbl_Email: TLabel
Left = 393
Top = 56
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Email: '
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentFont = False
Layout = tlCenter
ExplicitLeft = 454
ExplicitWidth = 42
ExplicitHeight = 17
end
object lbl_HomeCountry: TLabel
Left = 2
Top = 83
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Country: '
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentColor = False
ParentFont = False
Transparent = True
Layout = tlCenter
ExplicitLeft = 47
ExplicitWidth = 58
ExplicitHeight = 17
end
object edit_HomePostCode: TEdit
Left = 107
Top = 110
Width = 284
Height = 25
Align = alClient
BevelInner = bvNone
BevelOuter = bvNone
TabOrder = 4
Text = 'Home Post Code'
end
object lbl_HomePostCode: TLabel
Left = 2
Top = 110
Width = 103
Height = 25
Align = alClient
Alignment = taRightJustify
Caption = 'Post Code: '
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold]
ParentColor = False
ParentFont = False
Transparent = True
Layout = tlCenter
ExplicitLeft = 35
ExplicitWidth = 70
ExplicitHeight = 17
end
end
object panel_HomeAddressTitle: TPanel
Left = 6
Top = 6
Width = 784
Height = 24
Align = alTop
Alignment = taLeftJustify
BevelOuter = bvNone
Caption = ' Home Address '
Color = clMedGray
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -13
Font.Name = 'Segoe UI'
Font.Style = [fsBold, fsUnderline]
ParentBackground = False
ParentFont = False
TabOrder = 1
end
end
object panel_GeneralNotesDetails: TPanel
Tag = 303
Left = 0
Top = 174
Width = 796
Height = 172
Align = alTop
AutoSize = True
Padding.Left = 5
Padding.Top = 5
Padding.Right = 5
Padding.Bottom = 5
ParentBackground = False
TabOrder = 1
object gpanel_GeneralNotesDetails_: TGridPanel
Left = 6
Top = 6
Width = 784
Height = 160
Align = alTop
BevelOuter = bvNone
ColumnCollection = <
item
Value = 100.000000000000000000
end>
ControlCollection = <
item
Column = 0
Control = pageControl_GeneralNotes
Row = 0
end>
Padding.Left = 1
Padding.Top = 1
Padding.Right = 1
Padding.Bottom = 1
RowCollection = <
item
SizeStyle = ssAbsolute
Value = 160.000000000000000000
end>
TabOrder = 0
object pageControl_GeneralNotes: TPageControl
Left = 2
Top = 2
Width = 780
Height = 158
Align = alClient
TabOrder = 0
end
end
end
end
end
I figured out that the problem was caused by the quick hack David answered to TLabel and TGroupbox Captions Flicker on Resize after I removed that the mad flickering when the TPageControl tab scroll buttons were visible went away. So now I'll have to look at his more in-depth solution and see if that can help with some of the flickering I was seeing before.

Resources