在Delphi中的TCanvas上绘制透明的TMetaFile

发布于 2024-09-28 07:09:26 字数 1275 浏览 3 评论 0原文

我想在画布上绘制一个透明的 TMetaFile,用于打印水印。

问题是 AlphaBlend 函数不会将 TMetaFile.Handle 识别为源,因为它需要画布句柄。

我创建了一个具有透明度的 32 位位图,但在其上绘图会强制使用白色背景,因此在 Canvas 上您可以看到一个 alpha 混合矩形。 如何在屏幕/打印机画布上绘制透明的 TMetaFile?

TMetaFile肯定是透明的,我已经使用非标准背景颜色的IE在简单的网页上测试了它。 源代码:

procedure TPainter.DrawAlpha(ACanvas: TCanvas; ARect: TRect; AGraphic: TMetafile; AAlpha: Byte);
var
  bmp: TBitmap;
  bf: BLENDFUNCTION;
begin
  bmp := TBitmap.Create;
  try
    bmp.PixelFormat := pf32bit;
    bmp.SetSize(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top);
    bmp.Transparent := True;
    bmp.Canvas.Brush.Color := clNone;
    bmp.Canvas.Brush.Style := bsClear;
    bmp.Canvas.FillRect(Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top));
    bmp.Canvas.StretchDraw(Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top), AGraphic);

    bf.BlendOp := AC_SRC_OVER;
    bf.BlendFlags := 0;
    bf.SourceConstantAlpha := 230;
    bf.AlphaFormat := 0;

    AlphaBlend(
      ACanvas.Handle,
      ARect.Left,
      ARect.Top,
      ARect.Right - ARect.Left,
      ARect.Bottom - ARect.Top,
      bmp.Canvas.Handle,
      0,
      0,
      ARect.Right - ARect.Left,
      ARect.Bottom - ARect.Top,
      bf
    );
  finally
    bmp.Free;
  end;
end;

I would like to draw a transparent TMetaFile on a Canvas, used for print watermark.

The problem is AlphaBlend function won't recognize TMetaFile.Handle as source as it expects canvas handle.

I created a 32bit bitmap with transparency but drawing on it will force white background thus on Canvas you can see an alpha blended rectangle.
How can I paint a transparent TMetaFile on screen/printer Canvas?

TMetaFile is surely transparent, I have tested it on simple web page using IE with non-standard background color.
The source code:

procedure TPainter.DrawAlpha(ACanvas: TCanvas; ARect: TRect; AGraphic: TMetafile; AAlpha: Byte);
var
  bmp: TBitmap;
  bf: BLENDFUNCTION;
begin
  bmp := TBitmap.Create;
  try
    bmp.PixelFormat := pf32bit;
    bmp.SetSize(ARect.Right - ARect.Left, ARect.Bottom - ARect.Top);
    bmp.Transparent := True;
    bmp.Canvas.Brush.Color := clNone;
    bmp.Canvas.Brush.Style := bsClear;
    bmp.Canvas.FillRect(Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top));
    bmp.Canvas.StretchDraw(Rect(0, 0, ARect.Right - ARect.Left, ARect.Bottom - ARect.Top), AGraphic);

    bf.BlendOp := AC_SRC_OVER;
    bf.BlendFlags := 0;
    bf.SourceConstantAlpha := 230;
    bf.AlphaFormat := 0;

    AlphaBlend(
      ACanvas.Handle,
      ARect.Left,
      ARect.Top,
      ARect.Right - ARect.Left,
      ARect.Bottom - ARect.Top,
      bmp.Canvas.Handle,
      0,
      0,
      ARect.Right - ARect.Left,
      ARect.Bottom - ARect.Top,
      bf
    );
  finally
    bmp.Free;
  end;
end;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

几味少女 2024-10-05 07:09:26

如果你查一下MSDN官方文档,你会得到这样的说法:
http://msdn.microsoft.com/en-us/库/dd183351(VS.85).aspx

如果源设备上下文标识增强型图元文件设备上下文,则会发生错误(并且函数返回 FALSE)。

我的第一个猜测是,即使 MSDN 仅讨论源设备上下文,您的代码也永远无法与 AlphaBlend 一起使用,而 AlphaBlend 旨在在两个位图之间工作。

但是,经过第二次调查,元文件枚举类型中有一个专用的 TEMRAlphaBlend 记录类型。所以它应该按预期工作。

您用什么来显示图元文件?
我们需要您用于在此处显示图元文件的代码。

我的建议是将图元文件保存到 emf 文件中,然后使用 emfexplorer 检查其上下文。

我们开发了一个开源单元,名为 SynGdiPlus,用于在纯 Delphi 中使用 GDI+ 绘制元文件,因此具有抗锯齿功能。但我们还没有实现 TEMRAlphaBlend 记录类型。如果您觉得在应用程序中使用抗锯齿绘图很有趣,我可以考虑实现它。

If you check for the MSDN official documentation, you'll get this statement:
http://msdn.microsoft.com/en-us/library/dd183351(VS.85).aspx

An error occurs (and the function returns FALSE) if the source device context identifies an enhanced metafile device context.

My first guess was that, even if the MSDN is talking only about the source device context, your code will never work with AlphaBlend, which is intended to work between two bitmaps.

But, after second investigation, there is a dedicated TEMRAlphaBlend record type in the Meta File enumeration tyles. So it should work as expected.

What are you using to display your metafile?
We'll need the code you use for displaying the metafile here.

My advice is to save your metafile into an emf file, then use emfexplorer to inspect its context.

We've developed an open source unit, named SynGdiPlus, for drawing a meta file using GDI+, therefore with anti-aliasing, in pure Delphi. But we didn't implement the TEMRAlphaBlend record type yet. If you would find interesting to have anti-aliasing drawing in your app, I could take a look into implementing it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文