Как перекрасить форму MDIChild, когда сам MDIChild содержит контейнеры, такие как TPanel с выровненными: = alClient и ParentBackground: = False - PullRequest
1 голос
/ 21 марта 2011

Суммирование:

Пожалуйста, ознакомьтесь с хорошо осведомленными комментариями Андреаса!

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

Как показано в следующем коде, TForm7 - это форма MDIForm, TForm8 - это форма MDIChild. TForm8 содержит панель выравнивания alClient, которая дополнительно содержит TPaintBox. Если ParentBackground панели TForm8 имеет значение False, я не могу вызвать событие рисования TForm8 из TForm7. Мне интересно, почему это произошло, и как я могу вызвать событие рисования TForm8 paintbox без явного обращения к нему. Любое предложение приветствуется!

Примечание. Если я вызываю Self.Repaint с помощью TForm8, например, внутри его события Click, событие рисования TForm8 в paintbox может быть запущено. Это не может быть вызвано, только когда я звоню form8.repaint за пределами TForm8. Мне интересно, почему это случилось?

Возможно, соответствующие страницы 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

Ответы [ 2 ]

5 голосов
/ 21 марта 2011

Я думаю, что это так:

Верьте или нет, "нормальное" поведение состоит в том, что, если вы перерисовываете форму (или какой-либо другой контейнер), перекрашивается только этот контейнер, а не дочерние элементы, содержащиеся в нем. Однако с появлением визуальных тем элементы управления получили полупрозрачные части, и внезапно вам необходимо перекрасить дочерние элементы управления, когда родительский элемент перерисовывается, просто потому, что дочерние элементы должны вернуться на новый фон.

Моя гипотеза (относительно) легко проверяется путем тщательного изучения исходного кода 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, и панель ведет себя как классическая панель, она не перекрашивается, когда ее родительский элемент. С другой стороны, если ParentBackground равен true, он перерисовывается вместе со своим родителем.

Следовательно, на самом деле проблем нет; вы просто ожидаете поведения, которого не следует ожидать.

Так что вам нужно перекрасить коробку с краской вручную, следуя совету Дэвида.

1 голос
/ 21 марта 2011

Вам просто нужно позвонить pb1.Invalidate, если вы хотите, чтобы коробка рисования заново нарисовала себя.

Или я неправильно понял ваш вопрос?

...