Как получить доступ к холсту 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
метод, который кажется хитрым.