2013-04-05 13 views
2

사용 : Delphi XE2, VCL 32 비트 응용 프로그램, Windows 8TFrame의 캔버스에 액세스하는 방법?

내 프레임의 배경을 (OnPaint 이벤트를 노출하므로 TJvPanel을 사용하고 있습니다.) 패널에 페인트하려고합니다. 프레임의 자식 제어.

this post을 읽고 필드로 캔버스를 추가 한 후에도 나는 아직 성공적이지 않습니다.

ShowAddReceiptPanel을 호출하면 ProEffectImage 메서드로 처리 한 후 그레이 스케일링 된 전경 패널에 이미있는 모든 컨트롤 (격자 및 페이지 컨트롤 포함)이있는 프레임의 (TfrmMyFrame) 창 내용을 그릴 수 있지만 대신 불투명 한 흰색 배경을 보여줍니다. 내가 놓친 게 있니? 당신이 당신의 캔버스 핸들에 할당

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; 
+0

소멸자의 if 할당 테스트를 제거 할 수 있고 제거해야합니다. 포함 된 Free를 호출하면됩니다. –

+0

감사! 무료로 배정 된 수표가 포함되어 있습니다 - 언제 그 기능을 소개 했습니까? –

+0

Er, Delphi 1에서. 나는 이것을 다음과 같이 참조한다 : http://stackoverflow.com/questions/8548843/why-should-i-not-use-if-assigned-before-using-or-freeing-things/8550628 # 8550628 –

답변

2

직류는 PaintWindow 호출시에만 유효합니다 :

여기 내 코드입니다. 유효하지 않으므로 해당 함수 외부에서 사용하므로 사용자가 관찰하는 동작을 사용합니다.

PaintTo 메서드를 호출하여 문제를 해결할 수 있어야한다고 생각합니다. 올바른 크기의 비트 맵을 만들고 캔버스를 PaintTo에 전달합니다.

+0

배경을 페인트하고 싶습니까? 또는 틀의 아이들도. –

+0

프레임의 자식을 페인트해야합니다. 전면 패널은 그 아래에 무엇이 있는지에 대한 흑백 이미지를 보여줍니다. 이것이 전체적인 목적입니다. –

+0

두 번째 단락에 나와 있습니다. –

0

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; 
+0

GetWindowDC가 항상 같은 DC를 반환하지는 않습니다. –

+0

죄송합니다.'GetWindowDC'는 클라이언트가 아닌 부분을 실제로 반환합니다. – NGLN

+0

그 이상으로 DC는 사용자가 제공 할 수 있습니다. "내 비트 맵에 페인트하기"에서처럼. –

0

TFrameCanvas에 접근하는 쉬운 방법은 Align := alClient하고 Canvas 속성을 사용하여 그것의 위에 TPaintBox을 추가하는 것입니다 : 다음과 같이

그런 다음 의사 코드가 될 것이다.

이 방법은 앞으로도 모든 버전의 Delphi에서 작동하므로 PaintWindow 메서드 대신이 메서드를 사용하면 문제가 발생할 것으로 예상됩니다.

+0

그러나 TFrame *의 Canvas에 액세스 할 수는 없지만 * TFrame *의 TPaintBox에 액세스 할 수 있습니다. –

+0

'TPaintBox.Canvas'는 Canvas입니다. 필자의 의견으로는'PaintWindow'에서 생성 된'Canvas'만큼이나 마찬가지입니다. 처음에는'PaintWindow' 메서드를 사용했지만 자동으로 변경되는 글꼴에 문제가 발생했습니다. 따라서 간단하고 델파이 코드를 중심으로 Windows API로 아무 것도하지 않는'TPaintBox'를 사용하기로했습니다. – Marthein