gpt4 book ai didi

delphi - 当 MDIChild 本身包含诸如 TPanel 之类的容器且对齐 := alClient and ParentBackground := False 时,如何重新绘制 MDIChild 表单

转载 作者:行者123 更新时间:2023-12-01 22:39:42 25 4
gpt4 key购买 nike

总结:

请查看 Andreas 的知识渊博的评论!

============================================

如下代码所示,TForm7是MDIForm窗体,TForm8是MDIChild窗体。 TForm8 包含一个 alClient 对齐面板,其中还包含一个 TPaintBox。如果TForm8的面板的ParentBackground设置为False,我无法从TForm7触发TForm8的油漆盒的绘画事件。我想知道为什么会发生这种情况,以及如何在不明确引用它的情况下触发 TForm8 的 Paintbox 的绘制事件。任何建议表示赞赏!

注意:如果我调用 Self.Repaint在TForm8中,例如在其Click事件中,可以触发TForm8的paintbox的paint事件。只有调用 form8.repaint 才能触发TForm8 之外。我想知道为什么会发生这种情况?

可能相关的 SO 页面:
How to repaint a parent form while a modal form is active?

包含 MDIForm 表单的单元。

    unit Unit7;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;

type
TForm7 = class(TForm)
procedure FormShow(Sender: TObject);
procedure FormClick(Sender: TObject);

end;

var
Form7: TForm7;

implementation

{$R *.dfm}

uses
Unit8;

procedure TForm7.FormShow(Sender: TObject);
begin
TForm8.Create(Self);
end;

procedure TForm7.FormClick(Sender: TObject);
begin
TForm8(ActiveMDIChild).Repaint;
end;

end.

上述单元的 Dfm。

    object Form7: TForm7
Left = 0
Top = 0
Caption = 'Form7'
ClientHeight = 379
ClientWidth = 750
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIForm
OldCreateOrder = False
OnClick = FormClick
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
end

包含 MDIChild 表单的单元。

    unit Unit8;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls;

type
TForm8 = class(TForm)
pb1: TPaintBox;
pnl1: TPanel;
procedure pb1Paint(Sender: TObject);
procedure pb1Click(Sender: TObject);
private
fCounter: Integer;

end;

implementation

{$R *.dfm}

procedure TForm8.pb1Click(Sender: TObject);
begin
Self.Repaint;
end;

procedure TForm8.pb1Paint(Sender: TObject);
begin
Self.pb1.Canvas.TextOut(30, 30, IntToStr(Self.fCounter));
Self.fCounter := Self.fCounter + 1;
end;

end.

上述单元的 Dfm。

    object Form8: TForm8
Left = 0
Top = 0
Caption = 'Form8'
ClientHeight = 226
ClientWidth = 233
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
FormStyle = fsMDIChild
OldCreateOrder = False
Visible = True
PixelsPerInch = 96
TextHeight = 13
object pnl1: TPanel
Left = 0
Top = 0
Width = 233
Height = 226
Align = alClient
ShowCaption = False
TabOrder = 0
object pb1: TPaintBox
Left = 1
Top = 1
Width = 231
Height = 224
Align = alClient
OnClick = pb1Click
OnPaint = pb1Paint
ExplicitLeft = 56
ExplicitTop = -64
ExplicitWidth = 105
ExplicitHeight = 105
end
end
end

最佳答案

我认为是这样的:

不管你相信与否,“正常”行为是,如果您重新绘制表单(或其他一些容器),则只有该容器被重新绘制,而不是其中包含的子项被重新绘制。然而,随着视觉主题的出现,控件获得了半透明部分,突然间您需要在重绘父控件时重新绘制子控件,仅仅是因为子控件需要重新混合到新的背景中。

通过仔细检查 VCL 源代码,我的假设(相对)很容易得到验证,例如

procedure TWinControl.CMInvalidate(var Message: TMessage);
begin
{ Removed irrelevant code to avoid copyvio issues. }
InvalidateRect(WindowHandle, nil, not (csOpaque in ControlStyle));
{ Invalidate child windows which use the parentbackground when themed }
if ThemeServices.ThemesEnabled then
for I := 0 to ControlCount - 1 do
if csParentBackground in Controls[I].ControlStyle then
Controls[I].Invalidate;
{ Removed irrelevant code to avoid copyvio issues. }
end;

因此,当 ParentBackground 设置为 false 且面板像经典面板一样时,它不会在其父面板重新绘制时重新绘制。另一方面,如果 ParentBackgroundtrue,它确实会与其父级一起重新绘制。

因此,真的没有问题;您只是期望出现不符合预期的行为。

因此,您需要按照 David 的建议手动重新绘制油漆盒。

关于delphi - 当 MDIChild 本身包含诸如 TPanel 之类的容器且对齐 := alClient and ParentBackground := False 时,如何重新绘制 MDIChild 表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5383061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com