3

DrawThemeTextEx是绘制 Windows Vista 和 7 的 Aero 文本的 API,即带有发光光晕的文本。

要更改使用 绘制时使用的文本颜色DrawThemeTextEx,请设置结构的crText字段并在字段中DTTOPTS指定,以指示该字段包含有效值。但是文字后面的模糊发光效果总是画白色。设置阴影或边框颜色以及适当的标志对发光颜色没有影响。结构中的发光颜色没有明显的设置。DTT_TEXTCOLORdwFlagscrTextDTTOPTS

具有自定义文本颜色但白色发光颜色的发光文本

在这里,您可以看到自定义文本颜色(红色),但它仍然在文本后面呈现白色模糊光晕。我想,比如说,黑色发光,因为对于浅色文本颜色,它会使文本更易于阅读。

你如何改变这个白色光晕/辉光的颜色?例如,是否存在Dwm*具有影响的 API 或未记录的标志?

4

1 回答 1

5

简短的回答是,您不能使用DrawThemeTextEx API:它只允许您更改文本颜色,而不是背景发光颜色。

长答案是您可以通过以下方式达到相同的效果:

  • 用发光绘制文本;
  • 使用 alpha 作为颜色强度对生成的图像进行着色,以获得文本加上发光的单色图像;
  • 在没有发光效果的顶部绘制文本。

带有红色发光背景的黑色文本

显示技术结果的示例图像

第二步,为图像着色,是需要解释的主要步骤。

将带有发光的黑色文本绘制到临时位图。然后,您将拥有一个具有白色和黑色的区域(白色是 Windows 呈现的唯一发光颜色)、不同的 alpha 以及在文本边缘的黑色和白色之间的抗锯齿像素(由于使用的算法)可能是略微着色,即不是纯灰色。

彩色背景上的发光文本,放大

在彩色背景上绘制的发光文本,因此您可以看到白光和文本抗锯齿

有两种选择。第一种是使用颜色(“白色”与“黑色”)和色调将白色区域更改为背景颜色,将黑色区域更改为文本颜色。这将起作用,但与 Windows 呈现和抗锯齿的文本相比,可能会产生抗锯齿错误,尤其是彩色文本。更好的方法是意识到文本将被覆盖,并消除锯齿,背景发光:将所有内容(发光和文本)着色为一种颜色 - 无论是 100% alpha 文本都可以被视为 100% 白色发光下面text - 然后简单地再次将文本绘制到背景抗锯齿上。

着色非常简单。像素将具有 alpha 值和预乘的 alpha 颜色值 - 例如,(2, 2, 2, 2) 的 ABGR 是 2 的 alpha,而 BGR 是白色的,预乘了 alpha。忽略现有颜色,并根据像素的现有 alpha 将任何非零 alpha 像素设置为背景颜色的预乘 alpha 值。

使用TQuadColor 结构来表示 alpha 感知的 32 位像素的四个字节,循环通过您的临时位图并使用现有的 alpha 作为强度设置颜色:

// PQuad is a pointer to the first pixel, a TQuadColor (see link, basically a packed struct of ABGR bytes)
for Loop := 0 to FWidth * FHeight - 1 do begin
  if PQuad.Alpha <> 0 then begin
    PQuad.SetFromColorMultAlpha(Color); // Sets the colour, and multiplies the alphas together
  end;
  Inc(PQuad);
end;

关键是PQuad.SetFromColorMultAlpha

procedure TQuadColor.SetFromColorMultAlpha(const Color: TQuadColor);
var
  MultAlpha : Byte;
begin
  Red := Color.Red;
  Green := Color.Green;
  Blue := Color.Blue;
  MultAlpha := Round(Integer(Alpha) * Integer(Color.Alpha) / 255.0);
  SetAlpha(MultAlpha, MultAlpha / 255.0);
end;

这需要一个四边形颜色(即带有 RGB 的 alpha)并将两个 alpha 相乘以获得结果 alpha。 这使您可以通过透明颜色进行着色。 SetAlpha然后转换为预乘 alpha:

procedure TQuadColor.SetAlpha(const Transparency: Byte; const PreMult: Single);
begin
  Alpha := Transparency;
  Blue := Trunc(Blue * PreMult);
  Green := Trunc(Green * PreMult);
  Red := Trunc(Red * PreMult);
end;

结果是有色发光:

有色发光

在顶部绘制文本(使用相同的 API保持相同的文本渲染),不发光:

文字背后的有色光芒

并且您拥有带有彩色、非白色发光颜色的发光文本。

您可以在我的MPL 许可TTransparentCanvas项目中找到完整的源代码,该项目位于 Google Code 上。

于 2013-07-23T16:20:13.733 回答