1

要約:

アンドレアスの知識豊富なコメントをご覧ください!

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

次のコードに示すように、TForm7はMDIFormフォーム、TForm8はMDIChildフォームです。TForm8には、alClientに整列されたパネルが含まれ、さらにTPaintBoxが含まれます。TForm8のパネルのParentBackgroundがFalseに設定されている場合、TForm7からTForm8のペイントボックスのペイントイベントをトリガーできません。なぜこれが発生するのか、明示的に参照せずにTForm8のペイントボックスのペイントイベントをトリガーするにはどうすればよいのでしょうか。どんな提案でも大歓迎です!

注:Self.RepaintたとえばClickイベント内などでTForm8内を呼び出すと、TForm8のペイントボックスのペイントイベントがトリガーされる可能性があります。form8.repaintTForm8の外部を呼び出した場合にのみトリガーできません。なぜこれが起こるのだろうか?

関連する可能性のある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
4

2 に答える 2

5

私はこれが事実だと思います:

信じられないかもしれませんが、"通常の" 動作では、フォーム (または他のコンテナー) を再描画すると、そのコンテナーだけが再描画され、そこに含まれる子は再描画されません。しかし、ビジュアル テーマの出現により、コントロールは半透明の部分になり、親が再描画されたときに子コントロールを再描画する必要が突然発生しました。

私の仮説は、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いて、パネルがクラシック パネルのように動作する場合、親が再描画されている場合は再描画されません。一方、ParentBackgroundistrueの場合、親と一緒に再描画されます。

したがって、実際には問題はありません。予期しない動作を期待するだけです。

そのため、David のアドバイスに従って、ペイント ボックスを手動で再描画する必要があります。

于 2011-03-21T20:57:31.140 に答える
1

pb1.Invalidateペイントボックス自体を再描画したいときに呼び出すだけです。

それとも私はあなたの質問を誤解していますか?

于 2011-03-21T20:30:26.333 に答える