TPageControl有很多选项卡时闪烁

时间:2016-05-25 05:59:14

标签: delphi controls flicker delphi-10-seattle tpagecontrol

我的问题是我有e.sender.showColumn(n);,其中包含动态创建的数量的标签,每个标签都包含一个(TPageControlalClient。当此数量的选项卡超出控件的宽度并且选项卡标题上显示滚动箭头时,所有(很多)我的控件开始闪烁很多。只有当页面控件滚动出其停止的TMemo视图时,才会出现此闪烁。调整页面控件的大小,以便不再需要滚动箭头来查看所有选项卡,然后闪烁停止。

我相当自信这个问题是由滚动箭头引起的,导致一些绘画发生,因为当我将TPageControl设置为true时,没有闪烁。理想情况下,我不想使用MultiLine标签,希望有人能提供解决方案。

有关表单布局的信息

我有一个(个人详细信息)表单,其中包含许多TPageControl.MultiLineTSpeedButtonsTLabelsTEdits等等。其中许多元素位于TImage内,并使用TScrollBox分组为多个部分。面板在滚动框中设置为TPanels,并将自动调整大小设置为true,但它们的高度永远不会改变。

我已尝试将所有控件设置为尽可能将alTop设置为true并DoubleBuffered但遗憾的是没有任何效果。

在添加PageControls并使用David的快速黑客答案之前,我遇到了闪烁的问题TLabel and TGroupbox Captions Flicker on Resize我在调整表单大小时能够改善闪烁。通过扩展TLabel并从Paint程序中删除背景清除,按照其他地方的建议,我能够99%删除滚动ScrollBox时闪烁的标签,但现在我有一个新的闪烁问题。

--- --- EDIT

这是指向我的表单的精简版本的链接,闪烁发生flickering example

Personnel.DetailsForm.pas

ParentBackground/Color = false

Personnel.DetailsForm.dfm

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.   

1 个答案:

答案 0 :(得分:2)

我发现问题是由于快速破解大卫回答TLabel and TGroupbox Captions Flicker on Resize后我删除了TPageControl标签滚动按钮可见时疯狂闪烁消失了。所以现在我将不得不看看他更深入的解决方案,看看这是否有助于我之前看到的一些闪烁。