当 MDIChild 本身包含 TPanel 等容器时,如何重新绘制 MDIChild 窗体,其对齐:= alClient 和 ParentBackground := False
总结:
请参阅 Andreas 的知识渊博的评论!
============================================
如下代码所示,TForm7是MDIForm 窗体,TForm8 是MDIChild 窗体。 TForm8 包含一个 alClient 对齐面板,其中还包含一个 TPaintBox。如果TForm8的面板的ParentBackground设置为False,我无法从TForm7触发TForm8的油漆盒的绘画事件。我想知道为什么会发生这种情况,以及如何在不明确引用的情况下触发 TForm8 的 Paintbox 的绘制事件。任何建议表示赞赏!
注意:如果我在 TForm8 内调用 Self.Repaint
,例如在其 Click 事件内,则可以触发 TForm8 的 Paintbox 的 Paint 事件。仅当我在 TForm8 外部调用 form8.repaint
时才能触发它。我想知道为什么会发生这种情况?
可能相关的 SO 页面:
如何在模态表单是否处于活动状态?
包含 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
Summarization:
Please see Andreas' knowledgeable comments!
==========================================
As shown in the following code, TForm7 is the MDIForm form, TForm8 is the MDIChild form. TForm8 contains an alClient aligned panel, which further contains a TPaintBox. If the TForm8's panel's ParentBackground is set to False, I cannot trigger TForm8's paintbox's paint event from TForm7. I am wondering why would this happen, and how can I trigger TForm8's paintbox's paint event without exlicitly refering to it. Any suggestion is appreciated!
Note: If I call Self.Repaint
withint TForm8, for example inside its Click event, TForm8's paintbox's paint event can be triggered. It cannot be triggered only when I call form8.repaint
outside TForm8. I am wondering why would this happen?
Possibly relevant SO pages:
How to repaint a parent form while a modal form is active?
Unit that contains the MDIForm form.
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 of the above Unit.
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
Unit that contains the MDIChild form.
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 of the above Unit.
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我认为情况是这样的:
不管你信不信,“正常”行为是,如果您重新绘制表单(或其他一些容器),则只有该容器被重新绘制,而不是其中包含的子项被重新绘制。然而,随着视觉主题的出现,控件获得了半透明部分,突然间您需要在重绘父控件时重新绘制子控件,仅仅是因为子控件需要重新混合到新的背景中。
通过仔细检查 VCL 源代码,我的假设(相对)很容易得到验证,例如
因此,当
ParentBackground
设置为false
时,并且面板像经典面板一样,它不是当其父级重新绘制时,不会重新绘制。另一方面,如果ParentBackground
为true
,它确实会与其父级一起重新绘制。因此,确实没有问题;你只是期待一种不符合预期的行为。
因此,您需要按照大卫的建议手动重新绘制油漆盒。
I think this is the case:
Believe it or not, the "normal" behaviour is that, if you repaint a form (or some other container), only that container gets repainted, not the children contained in it. However, with the advent of visual themes, controls got semi-transparent parts, and all of a sudden you need to repaint the child controls when the parent is redrawn, simply because the children need to reblend into the new background.
My hypothesis is (relatively) readily validated by scrutinizing the VCL source code, e.g.
Therefore, when
ParentBackground
is set tofalse
, and the panel bahaves like a classic panel, it isn't repainted when its parent is. On the other hand, ifParentBackground
istrue
, it does get repainted along with its parent.Hence there is no problem, really; you simply expect a behaviour that isn't to be expected.
So you need to repaint the paint box manually, by following David's advice.
当您希望绘画框重新绘制自身时,您只需要调用
pb1.Invalidate
即可。或者我误解了你的问题?
You just need to call
pb1.Invalidate
when you want the paint box to re-draw itself.Or am I misunderstanding your question?