2012-05-10 86 views
8

我想用純粹的Windows GDI(所以沒有GDI +,DirectX或類似的,沒有OpenGL,沒有彙編程序或第三方庫)混色(通過指定的alpha值着色)畫布的區域。
如何使用純GDI進行顏色混合(通過指定的alpha值進行着色)畫布區域?

我創建了下面的函數,我想知道是否有這樣做的更有效或更簡單的方法:

procedure ColorBlend(const ACanvas: HDC; const ARect: TRect; 
    const ABlendColor: TColor; const ABlendValue: Integer); 
var 
    DC: HDC; 
    Brush: HBRUSH; 
    Bitmap: HBITMAP; 
    BlendFunction: TBlendFunction; 
begin 
    DC := CreateCompatibleDC(ACanvas); 
    Bitmap := CreateCompatibleBitmap(ACanvas, ARect.Right - ARect.Left, 
    ARect.Bottom - ARect.Top); 
    Brush := CreateSolidBrush(ColorToRGB(ABlendColor)); 
    try 
    SelectObject(DC, Bitmap); 
    Windows.FillRect(DC, Rect(0, 0, ARect.Right - ARect.Left, 
     ARect.Bottom - ARect.Top), Brush); 
    BlendFunction.BlendOp := AC_SRC_OVER; 
    BlendFunction.BlendFlags := 0; 
    BlendFunction.AlphaFormat := 0; 
    BlendFunction.SourceConstantAlpha := ABlendValue; 
    Windows.AlphaBlend(ACanvas, ARect.Left, ARect.Top, 
     ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, DC, 0, 0, 
     ARect.Right - ARect.Left, ARect.Bottom - ARect.Top, BlendFunction); 
    finally 
    DeleteObject(Brush); 
    DeleteObject(Bitmap); 
    DeleteDC(DC); 
    end; 
end; 

爲了什麼這個功能應該也看到了這一概念以下的(鑑別:-)圖像:

enter image description hereenter image description here

這可以呈現this image在方式的形式的頂部左側上面所示的代碼:

uses 
    PNGImage; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Image: TPNGImage; 
begin 
    Image := TPNGImage.Create; 
    try 
    Image.LoadFromFile('d:\6G3Eg.png'); 
    ColorBlend(Image.Canvas.Handle, Image.Canvas.ClipRect, $0000FF80, 175); 
    Canvas.Draw(0, 0, Image); 
    finally 
    Image.Free; 
    end; 
end; 

有沒有更高效的方法來使用純GDI或Delphi VCL來做到這一點?

+0

爲什麼你認爲你已經擁有的是不是有效? –

+0

這就是我問的原因。我知道這是有效的,但我想要更多(如果可能的話:-) – TLama

+0

你想從中得到什麼? –

回答

4

您是否嘗試過使用AlphaBlend的畫布繪圖?

Canvas.Draw(Arect.Left, ARect.Top, ABitmap, AAlphaBlendValue); 

與FillRect結合的混合色

更新:下面是一些代碼,儘可能靠近你的接口,但純VCL。
可能效率不高,但更簡單(並且稍微便攜)。
由於雷米說,畫中的僞持續的方式在窗體上,你不得不使用的OnPaint ...

procedure ColorBlend(const ACanvas: TCanvas; const ARect: TRect; 
    const ABlendColor: TColor; const ABlendValue: Integer); 
var 
    bmp: TBitmap; 
begin 
    bmp := TBitmap.Create; 
    try 
    bmp.Canvas.Brush.Color := ABlendColor; 
    bmp.Width := ARect.Right - ARect.Left; 
    bmp.Height := ARect.Bottom - ARect.Top; 
    bmp.Canvas.FillRect(Rect(0,0,bmp.Width, bmp.Height)); 
    ACanvas.Draw(ARect.Left, ARect.Top, bmp, ABlendValue); 
    finally 
    bmp.Free; 
    end; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    Image: TPNGImage; 
begin 
    Image := TPNGImage.Create; 
    try 
    Image.LoadFromFile('d:\6G3Eg.png'); 
    ColorBlend(Image.Canvas, Image.Canvas.ClipRect, $0000FF80, 175); 
    Canvas.Draw(0, 0, Image); 
    // then for fun do it to the Form itself 
    ColorBlend(Canvas, ClientRect, clYellow, 15); 
    finally 
    Image.Free; 
    end; 
end; 
+0

+1,謝謝!我從來沒有見過這個過載(我手工使用Delphi 2009)。很高興學習新東西,但是我需要應用colorize效果。 – TLama

+1

您可以將固體位圖創建爲'TBitmap'對象,並將'Draw()'指定爲您的圖像的Canvas,然後將完成的圖像拖放到您的Form上。順便說一句,如果你希望最終的繪圖是持久的,你必須從它的OnPaint事件中將它繪製到窗體上,而不是在按鈕的OnClick事件中。您可以在「OnClick」事件中準備圖像,然後使用「Invalidate()」形式觸發重繪,然後在觸發「OnPaint」事件時繪製當前圖像。或者把最終的圖像放入一個'TImage'組件。 –

+0

弗朗索瓦,接受,謝謝!順便說一句。 'bmp.Canvas.FillRect(bmp.Canvas.ClipRect);'也可能方便;-) @Remy,感謝關於繪製持久性的說明,但這裏並不需要,因爲這個函數是用於VirtualTreeView的[ OnBeforeCellPaint'](http://stackoverflow.com/a/10537589/960757)其中的背景可能是動畫例如(我忘記提及,我的壞)。 – TLama