【发布时间】:2020-10-23 13:44:33
【问题描述】:
Delphi 版本 10.3.3(社区)。
下面是显示不需要的行为的表单单元。它只有一个按钮和一个滚动框。如果在表单的项目中启用了任何 VCL 样式,并且窗口很大,例如最大化,则通过滚动条滚动会导致窗口更新延迟,看起来很难接受。当使用鼠标滚轮时,一切都很好。此外,当从滚动框的 StyleElements 中删除 seBorder 时,该行为就消失了。 我看过人们抱怨闪烁的帖子,我认为这个错误已经被报告了。
有人知道如何解决这个问题吗? 当我查看源代码时,我看不到树木的森林:)。
编辑:我在 Listbox-View 中将滚动框的宽度设置为 3 倍,这样效果更明显。 这里有两张截图,第一张来自测试应用,第二张来自我的真实应用,其中的绘画有点复杂。
unit UStoryTest;
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
TfrmSTest = class(TForm)
Scroller: TScrollBox;
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure PaintBoxPaint(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure ScrollerMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
private
{ Private declarations }
Picturelist, Colorlist: TList;
ScrollerSize: integer;
Procedure DisplayStoryBoard;
procedure DisplayListbox;
public
{ Public declarations }
end;
var
frmSTest: TfrmSTest;
implementation
{$R *.dfm}
procedure TfrmSTest.Button1Click(Sender: TObject);
begin
if Scroller.Align = alRight then
DisplayStoryBoard
else
DisplayListbox;
end;
procedure TfrmSTest.DisplayStoryBoard;
var
i, x, dx: integer;
aP: TPaintbox;
begin
for i := 0 to Picturelist.Count - 1 do
TControl(Picturelist[i]).Parent := nil;
Scroller.Align := alNone;
Scroller.Height := MulDiv(ScrollerSize,Monitor.PixelsPerInch,96);
Scroller.VertScrollBar.Visible := false;
Scroller.HorzScrollBar.Visible := true;
Scroller.AutoScroll := true;
Scroller.HorzScrollBar.Tracking := true;
Scroller.Align := alBottom;
dx := 10;
x := dx - Scroller.HorzScrollBar.Position;
Scroller.DisableAlign;
for i := 0 to Picturelist.Count - 1 do
begin
aP := TPaintbox(Picturelist[i]);
aP.Parent := Scroller;
aP.SetBounds(x, dx, aP.Width, aP.Height);
x := x + aP.Width + dx;
end;
Scroller.EnableAlign;
Scroller.Invalidate;
end;
procedure TfrmSTest.DisplayListbox;
var
i, x, y, dx: integer;
aP: TPaintbox;
begin
for i := 0 to Picturelist.Count - 1 do
TControl(Picturelist[i]).Parent := nil;
Scroller.Align := alNone;
Scroller.Width := MulDiv(3*ScrollerSize,Monitor.PixelsPerInch,96);
Scroller.HorzScrollBar.Visible := false;
Scroller.VertScrollBar.Visible := true;
Scroller.AutoScroll := true;
Scroller.VertScrollBar.Tracking := true;
Scroller.Align := alRight;
dx := 10;
y := dx - Scroller.VertScrollBar.Position;
Scroller.DisableAlign;
x := dx;
for i := 0 to Picturelist.Count - 1 do
begin
aP := TPaintbox(Picturelist[i]);
aP.Parent := Scroller;
aP.SetBounds(x, y, aP.Width, aP.Height);
x := x + aP.Width + dx;
if x + aP.Width > Scroller.Width then
begin
x := dx;
y := y + aP.Height + dx
end;
end;
Scroller.EnableAlign;
Scroller.Invalidate;
end;
procedure TfrmSTest.FormCreate(Sender: TObject);
var
i: integer;
aP: TPaintbox;
begin
Picturelist := TList.Create;
Colorlist := TList.Create;
ScrollerSize:=200;
for i := 0 to 120 do
begin
aP := TPaintbox.Create(self);
aP.Height := ScrollerSize - 40;
aP.Width := aP.Height;
aP.OnPaint := PaintBoxPaint;
aP.Tag := i;
Picturelist.Add(aP);
Colorlist.Add(Pointer(RGB(random(255), random(255), random(255))));
end;
end;
procedure TfrmSTest.FormDestroy(Sender: TObject);
begin
Picturelist.Free;
Colorlist.Free;
end;
procedure TfrmSTest.FormShow(Sender: TObject);
begin
DisplayStoryBoard;
end;
procedure TfrmSTest.PaintBoxPaint(Sender: TObject);
var
aP: TPaintbox;
begin
if Sender is TPaintbox then
begin
aP := TPaintbox(Sender);
aP.Canvas.Brush.Color := TColor(Colorlist[aP.Tag]);
aP.Canvas.Pen.Color := clLime;
aP.Canvas.Rectangle(aP.ClientRect);
aP.Canvas.Font.Color := clWhite;
aP.Canvas.Font.Style := [fsBold];
aP.Canvas.TextOut(3, 3, IntToStr(aP.Tag));
end;
end;
procedure TfrmSTest.ScrollerMouseWheel(Sender: TObject; Shift: TShiftState;
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var SB: TControlScrollbar;
begin
if (Scroller.Align=alBottom) then
SB:=Scroller.HorzScrollBar
else
SB:=Scroller.VertScrollBar;
SB.Position:=SB.Position-WheelDelta;
Handled:=true;
end;
initialization
ReportMemoryLeaksOnShutDown := true;
end.
为了让事情变得更舒服,这里是表格:
object frmSTest: TfrmSTest
Left = 0
Top = 0
Caption = 'frmSTest'
ClientHeight = 291
ClientWidth = 505
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnCreate = FormCreate
OnDestroy = FormDestroy
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Scroller: TScrollBox
Left = 0
Top = 98
Width = 505
Height = 193
Align = alBottom
DoubleBuffered = False
ParentDoubleBuffered = False
TabOrder = 0
OnMouseWheel = ScrollerMouseWheel
ExplicitLeft = 2
end
object Button1: TButton
Left = 8
Top = 8
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 1
OnClick = Button1Click
end
end
【问题讨论】:
-
我不确定这是否会有所帮助,但请尝试将 ScrollBox 的
DoubleBuffered属性更改为 true 以查看是否有帮助。 -
双缓冲没有区别。
-
我试图复制,但我不确定您的接受程度。你能制作一个 gif 或其他东西来显示你看到的效果吗?
-
@Uwe Raabe 查看我的编辑。使用更强大的图形效果可能会变得不那么明显。我的是 Nvidia GeForce GTX 1050 TI
-
这可能是我在这里看不到的原因。您可以尝试将 TPaintBox 替换为 TImage 并绘制到 TImage.Picture.Bitmap,但这仅在绘图不是动态的情况下才有效。
标签: delphi scrollbar vcl-styles