Как получить доступ к холсту TFrame?

Использование: Delphi XE2, VCL 32-битное приложение, Windows 8

Я пытаюсь нарисовать фон моего фрейма на панели (я использую TJvPanel, потому что он выставляет событие OnPaint), который является дочерним элементом управления фрейма.

После прочтения этого поста и добавления холста в качестве поля я все еще не добился успеха.

После вызова ShowAddReceiptPanel он должен нарисовать содержимое окна фрейма (TfrmMyFrame) со всеми уже имеющимися на нем элементами управления (включая сетку и управление страницами) на панели переднего плана, в оттенках серого, после обработки методом ProEffectImage, но вместо этого он показывает непрозрачный белый фон. Я что-то пропустил?

Вот мой код:

type
  TfrmMyFrame = class(TFrame)
    pnlHdr: TPanel;
    pnlAddNewBG: TJvPanel;
    procedure pnlAddNewBGPaint(Sender: TObject);
  private
    { Private declarations }
    FBGImg: TProEffectImage;
    Fcnvs: TCanvas;

    procedure PaintWindow(DC: HDC); override;
    procedure ShowAddReceiptPanel;
    procedure HideAddReceiptPanel;
    procedure ResizePanel_pnlAddNewBG;

  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

constructor TfrmMyFrame.Create(AOwner: TComponent);
begin
  inherited;

  FBGImg := TProEffectImage.Create(nil);
  Fcnvs := TCanvas.Create;

end;

destructor TfrmMyFrame.Destroy;
begin
  if Assigned(FBGImg) then
    FBGImg.Free;

  if Assigned(Fcnvs) then
    Fcnvs.Free;

  inherited;
end;

procedure TfrmMyFrame.ShowAddReceiptPanel;
begin
  ResizePanel_pnlAddNewBG;
  pnlAddNewBG.Visible := True;
end;

procedure TfrmMyFrame.PaintWindow(DC: HDC);
begin
  inherited;

  Fcnvs.Handle := DC;
end;

procedure TfrmMyFrame.pnlAddNewBGPaint(Sender: TObject);
var
  l, t, w, h: Integer;
  srct, drct: TRect;
begin

  // Copy Frame canvas to BGImg bitmap
  l := 0;
  t := pnlHdr.Height;
  w := ClientWidth;
  h := ClientHeight - t;

  srct := TRect.Create(l, t, w, h);
  FBGImg.Width := w;
  FBGImg.Height := h;
  drct := TRect.Create(l, t, w, h);
  FBGImg.Canvas.CopyMode := cmSrcCopy;
  FBGImg.Canvas.CopyRect(drct, Fcnvs, srct);
//  FBGImg.Picture.SaveToFile('c:\tmp\a.bmp');

  FBGImg.Effect_AntiAlias;
  FBGImg.Effect_GrayScale;

  // Draw BGImg onto Option panel
  TJvPanel(Sender).Canvas.CopyMode := cmSrcCopy;
  TJvPanel(Sender).Canvas.Draw(0, 0, FBGImg.Picture.Graphic);
end;

procedure TfrmMyFrame.ResizePanel_pnlAddNewBG;
var
  x1, y1, x2, y2: Integer;
  bmp: TBitmap;
begin
  x1 := 0;
  y1 := pnlHdr.Height;
  x2 := ClientWidth;
  y2 := ClientHeight - y1;

  pnlAddNewBG.SetBounds(x1, y1, x2, y2);
end;

3 ответа

Решение

DC, который вы назначаете своему дескриптору canvas, действителен только во время вызова PaintWindow. Вы используете его вне этой функции, когда оно недопустимо, и, следовательно, поведение, которое вы наблюдаете.

Я думаю, что вы должны быть в состоянии решить вашу проблему, вызвав метод PaintTo. Создайте растровое изображение нужного размера и передайте его холст в PaintTo.

TFrame не имеет холста. Вы можете создать / добавить один, как TCustomControl делает, но вы не должны. Холст - это просто удобная оболочка для контекста устройства Windows. PaintWindow подпрограмма вызывается всякий раз, когда кадр должен быть (частично) перерисован. Параметр показывает DC, или вы можете получить один с GetDC,

Тогда псевдокод будет выглядеть следующим образом:

procedure TfrmMyFrame.PaintWindow(DC: HDC);
begin
  - Resize BG image and hide it (otherwise image itself will be copied too)
  - Paint the frame's contents to the image with:
    Self.PaintTo(FBGImg.Canvas.Handle, 0, 0)
  - Process the special effects on FBGImg
  - Paint the image onto DC with:
    BitBlt(DC, 0, 0, ClientWidth, ClientHeight, FBGImage.Canvas.Handle, 0, 0, SRCCOPY);
end;

Простой способ получить доступ к Canvas на TFrame это добавить TPaintBox на вершине этого с Align := alClient и используя его Canvas имущество.

Я ожидаю, что этот метод будет работать с любой версией Delphi, а также в будущем, и, следовательно, использовать его вместо PaintWindow метод, который кажется хитрым.

Другие вопросы по тегам