【发布时间】:2015-07-17 01:20:00
【问题描述】:
问题定义
我正在尝试创建一个具有透明度的自定义位图画笔,但它似乎没有按预期工作。如果你看这个例子。添加代码并连接绘画、创建和销毁事件。
type
TForm3 = class(TForm)
procedure FormDestroy(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
private
FBitmap: TBitmap;
end;
// Implementation
function CreateBlockBitmap(const APenColor: TColor): TBitmap;
begin
Result := TBitmap.Create;
Result.Transparent := True;
Result.Canvas.Brush.Color := clWhite;
Result.Canvas.Brush.Style := bsClear;
Result.PixelFormat := pf32bit;
Result.SetSize(20, 20);
Result.Canvas.Brush.Color := APenColor;
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.FillRect(Rect(0,0,10,10));
end;
procedure TForm3.FormDestroy(Sender: TObject);
begin
FBitmap.Free;
end;
procedure TForm3.FormCreate(Sender: TObject);
begin
FBitmap := CreateBlockBitmap(clRed);
end;
procedure TForm3.FormPaint(Sender: TObject);
var
colNum: Integer;
rowNum: Integer;
begin
// Paint the rectangle using the brush
Canvas.Pen.Color := clGreen;
Canvas.Brush.Bitmap := FBitmap; // This is using bitmap
Canvas.Rectangle(50, 50, 250, 250);
// Draw the block using Canvas.Draw
for rowNum := 0 to 9 do
for colNum := 0 to 9 do
Canvas.Draw(350 + rowNum * 20, 50 + colNum * 20, FBitmap);
end;
此代码生成两个着色块。左侧是使用位图画笔绘制的,右侧是使用多个 Canvas.Draw 调用绘制的。
我需要将画笔涂成透明度,类似于使用阴影画笔时会发生的情况。这个 SO 答案似乎表明它是可能的:
How can I draw a patternBrush with transparent backround (GDI)?
我尝试过的
1) 我尝试使用纯色背景色而不是使用bsClear。这只会使背景变白。
Result.Canvas.Brush.Color := clWhite;
Result.Canvas.Brush.Style := bsSolid;
如果我使用clFuchsia,那么颜色是紫红色。我还尝试绘制背景clFuchsia,然后将TransparentColor 设置为clFuchsia。 Canvas.Draw 选项使用透明度进行绘制,而画笔则没有。
2) 我尝试直接使用以下代码设置 alpha 通道:
procedure SetAlphaBitmap(const Dest: TBitmap;Color : TColor;Alpha:Byte);
type
TRGB32 = record
B, G, R, A: byte;
end;
PRGBArray32 = ^TRGBArray32;
TRGBArray32 = array[0..0] of TRGB32;
var
x, y: integer;
Line, Delta: integer;
ColorRGB : TColor;
begin
if Dest.PixelFormat<>pf32bit then exit;
ColorRGB := ColorToRGB(Color);
Line := integer(Dest.ScanLine[0]);
Delta := integer(Dest.ScanLine[1]) - Line;
for y := 0 to Dest.Height - 1 do
begin
for x := 0 to Dest.Width - 1 do
if TColor(RGB(PRGBArray32(Line)[x].R, PRGBArray32(Line)[x].G, PRGBArray32(Line)[x].B)) = ColorRGB then
PRGBArray32(Line)[x].A := Alpha;
Inc(Line, Delta);
end;
end;
然后在使用背景颜色绘制矩形后立即调用此例程。
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.FillRect(Rect(0,0,10,10));
SetAlphaBitmap(Result, clBlack, 0); // Set the alpha channel
end;
我知道 Alpha 通道正在工作,因为如果我传入 255 的 Alpha 值,那么它在 Canvas.Draw 中也会显示为黑色。
SetAlphaBitmap(Result, clBlack, 255);
3) 我尝试通过创建图案画笔并指定它而不是位图来进行测试。这会产生完全相同的结果。 FBrush 是一个 HBRUSH。
FBrush := CreatePatternBrush(FBitmap.Handle);
然后像这样设置画笔:
Canvas.Brush.Handle := FBrush;
4) 我尝试调用SetBkMode,如上面的 SO 答案所示。这根本没有区别。
Canvas.Pen.Color := clGreen;
Canvas.Brush.Bitmap := FBitmap;
SetBkMode(Canvas.Handle, TRANSPARENT); // This doesn't make a difference
Canvas.Rectangle(50, 50, 250, 250);
编辑
5) 我刚刚用单色位图进行了测试,它也有同样的问题。图像的画笔为白色背景和黑色前景,Canvas.Draw 为透明。
function CreateMonochromeBitmap: TBitmap;
begin
Result := TBitmap.Create;
Result.Transparent := True;
Result.Canvas.Brush.Color := clWhite;
Result.Canvas.Brush.Style := bsSolid;
Result.PixelFormat := pf1bit;
Result.SetSize(20, 20);
Result.Canvas.Brush.Color := clBlack;
Result.Canvas.Brush.Style := bsSolid;
Result.Canvas.FillRect(Rect(0,0,10,10));
end;
在构造函数中:
FBitmap := CreateMonochromeBitmap;
FBrush := CreatePatternBrush(FBitmap.Handle);
在绘画中我们设置句柄而不是位图属性。
Canvas.Brush.Handle := FBrush;
【问题讨论】:
-
您想要达到的最终效果是什么?你能举个例子吗?您是否尝试过使用特定颜色绘制自己的背景,然后将
TBitmap.TransparentColor设置为该颜色,而不是依赖bsClear绘制黑色背景?clFuschia通常用于此目的。 -
MCVE 可以帮助任何想帮助你的人
-
@DavidHeffernan MCVE 添加。
-
@RemyLebeau 我试过了。不幸的是,这只适用于
Canvas.Draw,不适用于画笔。我已更新问题以反映这一点。
标签: delphi delphi-xe7