2012-10-03 70 views
1

我想使用Windows alphablend API調用將兩個畫布混合在一起。首先,我在主畫布上繪製一些東西(目標),然後使用TBitmap實例化另一個畫布,然後將它們混合在一起(在這裏回答這個問題)。爲什麼AlphaBlend總是返回false(在畫布上繪圖)?

但是,我發現它始終返回false,起初我認爲它與傳遞源和目標的錯誤句柄有關,但我無法弄清楚。會是什麼呢?

unit MainWnd; 

interface 

uses 
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
    Dialogs, ExtCtrls, ControlsEx; 

type 
{------------------------------------------------------------------------------} 
    TfrmMain = class(TForm) 
    PaintBox1: TPaintBox; 
    procedure PaintBox1Paint(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    frmMain: TfrmMain; 

implementation 

{$R *.dfm} 

{..............................................................................} 
procedure alphaBlendf(
     const in_target  : TCanvas; 
     const in_transperancy : integer; 
     const in_color  : TColor; 
     const in_rect   : TRect; 
     const in_width  : integer; 
     const in_height  : integer); 
var 
    w   : integer; 
    h   : integer; 
    bitmap  : TBitmap; 
    blendFn : BLENDFUNCTION; 
    ret  : boolean; 
begin 
    blendFn.BlendOp    := AC_SRC_OVER; 
    blendFn.SourceConstantAlpha := 80; 

try 
    w := in_rect.Right - in_rect.Left - 1; 
    h := in_rect.Bottom - in_rect.Top - 1; 

    bitmap     := TBitmap.Create; 
    bitmap.PixelFormat  := pf32bit; 
    bitmap.Width    := w; 
    bitmap.Height    := h; 
    bitmap.Canvas.Brush.Color := in_color; 

    bitmap.Canvas.Rectangle(in_rect); 

    ret := Windows.AlphaBlend(
     in_target.Handle, 
     0, 
     0, 
     in_width, 
     in_height, 
     bitmap.Canvas.Handle, 
     0, 
     0, 
     in_width, 
     in_height, 
     blendFn); 

    if ret then in_target.TextOut(0, 0, 'ok') 
      else in_target.TextOut(0, 0, 'fail'); 
    finally 
    bitmap.Free; 
    end; 
end; 

{..............................................................................} 
procedure TfrmMain.PaintBox1Paint(Sender: TObject); 
var 
    r: TRect; 
begin 
    PaintBox1.Canvas.Brush.Color := $FCFFB5; 
    PaintBox1.Canvas.FillRect(r); 

    r := Rect(0, 0, 100, 100); 
    alphaBlendf(PaintBox1.Canvas, 0, clLime, r, PaintBox1.ClientWidth, PaintBox1.ClientHeight); 
end; 

end. 

回答

7

您的代碼中存在各種錯誤。

您沒有填寫BLENDFUNCTION的某些成員。他們不是可選的,提供他們的價值。

您的位圖對象創建應該在try語句之前(這與爲什麼AlphaBlend失敗不相關)。

您正在請求AlphaBlend函數從源頭混合更多,即您的位圖是99x99,但您希望api混合105x105。

另請注意,在paintbox的paint處理程序中,您正在填充任意矩形(您的r未初始化)。

procedure alphaBlendf(
     const in_target  : TCanvas; 
     const in_transperancy : integer; 
     const in_color  : TColor; 
     const in_rect   : TRect; 
     const in_width  : integer; 
     const in_height  : integer); 
var 
    w   : integer; 
    h   : integer; 
    bitmap  : TBitmap; 
    blendFn : BLENDFUNCTION; 
    ret  : boolean; 
begin 
    blendFn.BlendOp    := AC_SRC_OVER; 
    blendFn.BlendFlags   := 0; 
    blendFn.SourceConstantAlpha := 80; 
    blendFn.AlphaFormat   := 0; 

    bitmap     := TBitmap.Create; 
    try 
    w := in_rect.Right - in_rect.Left - 1; 
    h := in_rect.Bottom - in_rect.Top - 1; 

    bitmap.PixelFormat  := pf32bit; 
    bitmap.Width    := w; 
    bitmap.Height    := h; 
    bitmap.Canvas.Brush.Color := in_color; 

    bitmap.Canvas.Rectangle(in_rect); 

    ret := Windows.AlphaBlend(
     in_target.Handle, 
     0, 
     0, 
     in_width, 
     in_height, 
     bitmap.Canvas.Handle, 
     0, 
     0, 
     bitmap.width, 
     bitmap.height, 
     blendFn); 

    if ret then in_target.TextOut(0, 0, 'ok') 
      else in_target.TextOut(0, 0, 'fail'); 
    finally 
    bitmap.Free; 
    end; 
end; 

{..............................................................................} 
procedure TfrmMain.PaintBox1Paint(Sender: TObject); 
var 
    r: TRect; 
begin 
    PaintBox1.Canvas.Brush.Color := $FCFFB5; 
    r := Rect(0, 0, 100, 100); 
    PaintBox1.Canvas.FillRect(r); 

    alphaBlendf(PaintBox1.Canvas, 0, clLime, r, 
     PaintBox1.ClientWidth, PaintBox1.ClientHeight); 
end; 
+0

粘貼從我* * *的sl code代碼;現在完美的工作,謝謝! – wmercer

+0

不客氣! –

相關問題