如何更改使用DrawThemeTextEx绘制的文本的发光颜色?

Dav*_*vid 3 winapi aero aero-glass

DrawThemeTextEx 是用于绘制Windows Vista和7的Aero文本的API,即带有发光光环的文本.

要更改与绘图时所使用的文本颜色DrawThemeTextEx,可以设置crText基于场DTTOPTS结构,并指定DTT_TEXTCOLORdwFlags现场,以指示crText字段包含一个有效的值.但文字背后模糊的发光效果总是呈现白色.设置阴影或边框颜色以及相应的标记对发光颜色没有影响.DTTOPTS结构中的发光颜色没有明显的设置.

发光文字采用自定义文字颜色,但白色发光颜色

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

你如何改变这种白色光晕/发光的颜色?例如,是否存在Dwm*具有效果的API或未记录的标志?

Dav*_*vid 5

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

答案很长,你可以通过以下方式达到同样的效果:

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

黑文本有红色焕发背景

显示该技术结果的示例图像

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

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

在色的背景的发光的文本,迅速移动

在彩色背景绘制的发光文本,所以你可以看到白色的光芒和文本抗锯齿

有两种选择.第一种是使用颜色("白度"与"黑度")和色调将白色区域更改为背景颜色,将黑色区域更改为文本颜色.这将起作用,但与Windows文本呈现和抗锯齿的方式相比,可能会产生抗锯齿错误,尤其是彩色文本.一个更好的方法是意识到文本将被叠加,并且反对,背景发光:将一切(发光和文本)着色为一种颜色 - 无论100%的alpha文本可以被视为100%白色发光下面文本 - 然后简单地将文本再次抗锯齿绘制到背景中.

色彩很简单.像素将具有α值和预乘的α颜色值 - 例如,(2,2,2,2)的ABGR是2的α,白色的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;
Run Code Online (Sandbox Code Playgroud)

关键是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;
Run Code Online (Sandbox Code Playgroud)

这采用四色(即带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;
Run Code Online (Sandbox Code Playgroud)

结果是有色发光:

有色发光

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

文字背后的有色发光

而且你的发光文字带有彩色的非白色发光颜色.

您可以在Google Code上的MPL许可TTransparentCanvas项目中找到完整的源代码.