2012-05-10 15 views
8

純粋なWindows GDIを使用して(GDI +、DirectXなどを使用せず、OpenGLを使用せず、アセンブラもサードパーティのライブラリも使用しないで)キャンバスの領域を混色(指定アルファ値で色付け)したいと思います。この関数は見何をすべきかの概念について純粋なGDIを使用してキャンバス領域を色分け(指定されたアルファ値で色付け)する方法は?

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

Canvas Drawing with AlphaBlendを試しましたか?

ブレンドカラー

ためFillRect更新と組み合わせる

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

のようなもの:そして、ここでいくつかのあなたのインターフェースにできるだけ近いコード、純粋な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を持っています)。新しいことを学ぶのはうれしいですが、私も色付け効果を適用する必要があります。 – TLama

+1

ソリッドビットマップを 'TBitmap'オブジェクトとして作成し、アルファベットを画像の' Canvas'に指定して 'Draw()'し、完成した画像をフォームに 'Draw()'することができます。ところで、最終的な図面を永続的にするには、ボタンのOnClickイベントではなく、フォームのOnPaintイベントから描画する必要があります。 'OnClick'イベントでイメージを準備し、フォームを' Invalidate() 'して再描画をトリガーし、' OnPaint'イベントが発生するたびに現在のイメージを描画することができます。あるいは、最終画像を 'TImage'コンポーネントに入れてください。 –

+0

フランソワ、受け入れ、ありがとう! Btw。 @bem.Canvas.FillRect(bmp.Canvas.ClipRect); 'も便利かもしれません;-) @Remy、図面の永続性についての注釈をありがとうが、この関数はVirtualTreeViewの[' ' OnBeforeCellPaint'](http://stackoverflow.com/a/10537589/960757)背景がアニメーション化されているかもしれません(私はそれを言い忘れました、私の悪い)。 – TLama

関連する問題