Winapi 如何通过保持字体平滑度将RichEdit文本渲染到画布

Winapi 如何通过保持字体平滑度将RichEdit文本渲染到画布,winapi,bitmap,gdi,vcl,richedit,Winapi,Bitmap,Gdi,Vcl,Richedit,我正在尝试将RichEdit渲染为位图。我想做一个返校家长。 我可以通过上面的代码实现这一点。问题是,当我将位图设置为tranparent时 只有透明颜色变为透明。有没有办法处理边缘上的像素 它们既不同于背景色,也不同于字体颜色。我是说制作像素 边缘上的半投影,形成平滑视图 Graphics::TBitmap *bitmap = new Graphics::TBitmap(); bitmap->Width = RichEdit1->Width ; bitmap

我正在尝试将RichEdit渲染为位图。我想做一个返校家长。 我可以通过上面的代码实现这一点。问题是,当我将位图设置为tranparent时 只有透明颜色变为透明。有没有办法处理边缘上的像素 它们既不同于背景色,也不同于字体颜色。我是说制作像素 边缘上的半投影,形成平滑视图

    Graphics::TBitmap *bitmap = new Graphics::TBitmap();
    bitmap->Width = RichEdit1->Width ;
    bitmap->Height = RichEdit1->Height ;


    TRect BoundingBox(0,0,RichEdit1->Width, RichEdit1->Height) ;

    // Render RichEdit to bitmap
    TFormatRange formatRange;
    int twipsPerPixel = 1440 / Screen->PixelsPerInch;

    formatRange.hdc = bitmap->Canvas->Handle;
    formatRange.hdcTarget = bitmap->Canvas->Handle;
    formatRange.chrg.cpMin = 0;
    formatRange.chrg.cpMax = -1;

    formatRange.rc.top = 2 * twipsPerPixel;
    formatRange.rc.bottom = (BoundingBox.Height() - 4) * twipsPerPixel + formatRange.rc.top;
    formatRange.rc.left = 2 * twipsPerPixel;
    formatRange.rc.right = (BoundingBox.Width() - 4) * twipsPerPixel;

    // Measure text's height.
    RichEdit1->Perform(EM_FORMATRANGE, 0, 0);
    RichEdit1->Perform(EM_FORMATRANGE, 0, (LPARAM) &formatRange);

    formatRange.rc.bottom = (BoundingBox.Height() - 4) * twipsPerPixel + formatRange.rc.top;
    formatRange.rc.left = 2 * twipsPerPixel;
    formatRange.rc.right = (BoundingBox.Width() - 4) * twipsPerPixel;

    formatRange.rcPage = formatRange.rc;


    /**
    * Draw..
    **************************************************************************/
    RichEdit1->Perform(EM_FORMATRANGE, 1, (LPARAM) &formatRange);
    RichEdit1->Perform(EM_FORMATRANGE, 0, 0);


   // Draw background
   // Use different background color to see the trasparency problem
   this->Canvas->Brush->Color = clRed ;
   this->Canvas->Rectangle(0,0,RichEdit1->Width , RichEdit1->Height );

   // Draw the transparent bitmap
   bitmap->Transparent = true ;
   bitmap->TransparentColor = RichEdit1->Color ;
   this->Canvas->Draw(0,0,bitmap);

Thanx.

字体平滑使用alpha通道与部分透明度一起工作。因此,
TBitmap
Transparent
TransparentColor
属性不适用

<>你没有说你使用的是哪个版本的C++ Builder/VCL,但是更多的现代版本比部分旧版本更好地支持了部分透明性。 要使其工作,您需要将位图的
PixelFormat
设置为
pf32bit
。您可能还需要将
AlphaFormat
设置为
afDefined

如果您无法获得
TBitmap
来执行您需要的操作,那么您必须返回到GDI命令来创建合适的
HBITMAP
。您至少可以将其分配给
TBitmap
Handle
属性,并且通常从该属性开始,一切都会正常运行

注意,我不是C++ Builder的用户,但从Delphi中知道VCL。 更新

我在Delphi中尝试过这一点,以下几点对我来说很好:

procedure TForm4.Button1ClickBMP(Sender: TObject);
var
  BMP: TBitmap;
  fmtRange: TFormatRange;
  intPPI, Flags: Integer;
begin
  BMP := TBitmap.Create;
  Try
    BMP.PixelFormat := pf32bit;
    BMP.SetSize(RichEdit1.Width, RichEdit1.Height);

    FillChar(fmtRange, SizeOf(fmtRange), 0);
    with fmtRange do begin
      hDC := BMP.Canvas.Handle;
      hdcTarget := hDC;
      intPPI := Screen.PixelsPerInch;
      rc := Rect(
        0,
        0,
        RichEdit1.Width*1440 div intPPI,
        RichEdit1.Height*1440 div intPPI
      );
      rcPage := rc;
      chrg.cpMin := 0;
      chrg.cpMax := -1;
    end;
    Flags := 1;
    RichEdit1.Perform(EM_FORMATRANGE, Flags, Longint(@fmtRange));
    RichEdit1.Perform(EM_FORMATRANGE, 0, 0);
    BMP.SaveToFile('c:\desktop\test.bmp');
  Finally
    FreeAndNil(BMP);
  End;
end;
输出如下所示,放大一些以查看抗锯齿:


我希望这能有所帮助,因为看起来你就快到了

正如David已经回答的那样,亚像素抗锯齿需要了解背景颜色。这将在中进行更详细的解释。本质上,当您进行亚像素消除混叠时,您会将三个颜色通道视为具有不同的空间偏移(这就是分辨率明显提高的原因)。这意味着它们需要不同的alpha值,但当然只有一个alpha通道


当然,您可以在透明背景上执行常规的全像素灰度消除混叠。也许这就足够了?上述问题中的其他一些答案提出了实现这一目标的方法。查看
LOGFONT
结构中的
抗锯齿质量
(与
CLEARTYPE\u质量
)。(我还没试过。)

谢谢你的回答。我使用C++ Builder 2010。将PixelFormat设置为FP32位,将AlphaFormat设置为afDefined不会更改输出。你能提供更多关于如何通过GDI commads创建合适位图的信息吗?背景是透明的还是图片中的白色。使用背景色渲染时,会保留抗锯齿。如果我们尝试在不使用bachground的情况下进行渲染(指定位图透明、透明颜色属性),则会出现问题。好的,现在我将更清楚地说明这一点。如果没有背景色,则无法使用antialias。算法在很大程度上取决于这一点。你到底想做什么?我想通过保留字体的平滑曲线,从richedit的文本中选择一个透明位图。我认为这可以通过部分培训支持来实现。我会把那个位图画到我不知道它的颜色的地方。@tutalia实际上这是做不到的。字体抗锯齿渲染算法需要知道背景颜色。