IDWriteGdiInterop 接口的主要用途是它提供 IDWriteBitmapRenderTarget 留出了 HDC 接口,以与 GDI、GDI+ 交互;
另提供了 LOGFONT 结构与 IDWriteFont、IDWriteFontFace 的相互转换的方法。
IDWriteGdiInterop = interface(IUnknown) function CreateFontFromLOGFONT( { LOGFONT -> IDWriteFont } var logFont: LOGFONTW; // out font: IDWriteFont // ): HResult; stdcall; function ConvertFontToLOGFONT( { IDWriteFont -> LOGFONT } font: IDWriteFont; // var logFont: LOGFONTW; // var isSystemFont: BOOL //如果指定的字体对象是系统字体集合的一部分则返回 True ): HResult; stdcall; function ConvertFontFaceToLOGFONT( { IDWriteFontFace -> LOGFONT } var font: IDWriteFontFace; // var logFont: LOGFONTW // ): HResult; stdcall; function CreateFontFaceFromHdc( { HDC -> IDWriteFontFace } hdc: HDC; // out fontFace: IDWriteFontFace // ): HResult; stdcall; function CreateBitmapRenderTarget( { Create IDWriteBitmapRenderTarget } hdc: HDC; // width: Cardinal; // height: Cardinal; // out renderTarget: IDWriteBitmapRenderTarget // ): HResult; stdcall; end; { 封装可用于呈现字形的位图和内存 DC } IDWriteBitmapRenderTarget = interface(IUnknown) function DrawGlyphRun( { 将字形串绘制到位图中的指定黑框矩形中 } baselineOriginX: Single; //水平位置(DIP) baselineOriginY: Single; //垂直位置(DIP) measuringMode: TDWriteMeasuringMode; //用于字形串中各字形的度量方法 var glyphRun: TDwriteGlyphRun; //包含字形串属性的结构 renderingParams: IDWriteRenderingParams; //控制呈现行为的对象 textColor: COLORREF; //文本的前景色 blackBoxRect: PRect //黑框矩形(单位像素), 可选 ): HResult; stdcall; function GetMemoryDC: HDC; stdcall; { 获取内存设备上下文的句柄 } function GetPixelsPerDip: Single; stdcall; { 设置每个 DIP 的位图像素数;1 DIP(与设备无关的像素) = 1/96 英寸 } function SetPixelsPerDip(pixelsPerDip: Single): HResult; stdcall; { 获取每个 DIP 的位图像素数 } function GetCurrentTransform(var transform: TDwriteMatrix): HResult; stdcall; { 获取将抽象坐标映射为 DIP 的转换, 和世界转换无关 } function SetCurrentTransform(var transform: TDwriteMatrix): HResult; stdcall; { 设置将抽象坐标映射为 DIP 的转换, 和世界转换无关 } function GetSize(var size: TSize): HResult; stdcall; { 获取位图尺寸 } function Resize(width: Cardinal; height: Cardinal): HResult; stdcall; { 调整位图大小 } end; {LOGFONTW 结构} tagLOGFONTW = record lfHeight: Longint; //指定字体的字符单元或字符的高度 lfWidth: Longint; //指定字体中的字符的平均宽度 lfEscapement: Longint; //指定设备的行距向量和 x 轴之间的角度, 单位 1/10 度 lfOrientation: Longint; //指定设备的每个字符的基线和 x 轴之间的角度, 单位 1/10 度 lfWeight: Longint; //粗细 lfItalic: Byte; //斜体 lfUnderline: Byte; //下划线 lfStrikeOut: Byte; //删除线 lfCharSet: Byte; //字符集 lfOutPrecision: Byte; //输出精度 lfClipPrecision: Byte; //剪辑精度 lfQuality: Byte; //输出质量 lfPitchAndFamily: Byte; //字体系列 lfFaceName: array[0..LF_FACESIZE - 1] of WideChar; //字体名称 end;
练习从 GDI 结构获取 IDWriteFont 和 IDWriteFontFace
uses Direct2D, D2D1; { IDWriteGdiInterop.CreateFontFromLOGFONT() 方法测试 } procedure TForm1.Button1Click(Sender: TObject); var iGdiInterop: IDWriteGdiInterop; iFontFace: IDWriteFontFace; begin Self.Font.Name := '宋体'; DWriteFactory.GetGdiInterop(iGdiInterop); //获取 IDWriteGdiInterop 接口 iGdiInterop.CreateFontFaceFromHdc(Canvas.Handle, iFontFace); //TLogFont -> IDWriteFont {获取当前字体的字形总数} ShowMessage(IntToStr(iFontFace.GetGlyphCount)); //22141 end; { IDWriteGdiInterop.CreateFontFromLOGFONT() 方法测试 } procedure TForm1.Button2Click(Sender: TObject); var logFont: TLogFont; iGdiInterop: IDWriteGdiInterop; iFont: IDWriteFont; iFontFace: IDWriteFontFace; iFontFamily: IDWriteFontFamily; iLocalizedStrings: IDWriteLocalizedStrings; buf: array[0..LF_FACESIZE] of Char; begin Self.Font.Name := '宋体'; GetObject(Self.Font.Handle, SizeOf(TLogFont), @logFont); //获取当前窗口使用的 TLogFont 结构 DWriteFactory.GetGdiInterop(iGdiInterop); //获取 IDWriteGdiInterop 接口 iGdiInterop.CreateFontFromLOGFONT(logFont, iFont); //TLogFont -> IDWriteFont {从 IDWriteFont 获取字体名称} iFont.GetFontFamily(iFontFamily); iFontFamily.GetFamilyNames(iLocalizedStrings); iLocalizedStrings.GetString(iLocalizedStrings.GetCount-1, buf, Length(buf)); ShowMessage(buf); //宋体 iFont.CreateFontFace(iFontFace); //IDWriteFont -> IDWriteFontFace {获取当前字体的字形总数} ShowMessage(IntToStr(iFontFace.GetGlyphCount)); //22141 end;
使用 IDWriteBitmapRenderTarget
uses Direct2D, D2D1; procedure TForm1.FormPaint(Sender: TObject); var str1,str2: string; logFont: TLogFont; iGdiInterop: IDWriteGdiInterop; iFont: IDWriteFont; iTextFormat: IDWriteTextFormat; iTextLayout: IDWriteTextLayout; rTextRange: TDwriteTextRange; iBitmapRenderTarget: IDWriteBitmapRenderTarget; cvs: TDirect2DCanvas; iBrush: ID2D1SolidColorBrush; rRect: TRect; gdiCVS: TCanvas; begin str1 := 'Sample text using GDI TextOut.'; str2 := 'Sample text using DirectWrite.'; Canvas.Font.Name := '微软雅黑'; Canvas.Font.Size := 32; rRect := Bounds(0, 0, ClientWidth, ClientHeight div 2); {从 IDWriteGdiInterop.IDWriteBitmapRenderTarget 获取 DC, 并以 GDI 的方式输出文本} DWriteFactory.GetGdiInterop(iGdiInterop); iGdiInterop.CreateBitmapRenderTarget(Canvas.Handle, ClientWidth, ClientHeight div 2, iBitmapRenderTarget); gdiCVS := TCanvas.Create; gdiCVS.Handle := iBitmapRenderTarget.GetMemoryDC; gdiCVS.Font := Canvas.Font; gdiCVS.Rectangle(rRect); gdiCVS.TextRect(rRect, str1, [tfSingleLine, tfCenter, tfVerticalCenter]); gdiCVS.Free; {把 IDWriteBitmapRenderTarget 中的绘制结果复制到当前窗口} BitBlt( Canvas.Handle, 0, 0, ClientWidth, ClientHeight div 2, iBitmapRenderTarget.GetMemoryDC, 0, 0, SRCCOPY ); {根据当前窗口的 Font 建立 IDWriteFont} GetObject(Canvas.Font.Handle, SizeOf(TLogFont), @logFont); iGdiInterop.CreateFontFromLOGFONT(logFont, iFont); {以 DirectWrite 方式输出文本} DWriteFactory.CreateTextFormat( PWideChar(Canvas.Font.Name), nil, iFont.GetWeight, iFont.GetStyle, iFont.GetStretch, -MulDiv(logFont.lfHeight, 96, GetDeviceCaps(Canvas.Handle, LOGPIXELSX)), //FontSize '', iTextFormat ); iTextFormat.SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER); iTextFormat.SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER); DWriteFactory.CreateTextLayout( PWideChar(str2), Length(str2), iTextFormat, ClientWidth, ClientHeight div 2, iTextLayout ); rTextRange.startPosition := 0; rTextRange.length := Length(str1); // iTextLayout.SetUnderline(True, rTextRange); iTextLayout.SetStrikethrough(True, rTextRange); OffsetRect(rRect, 0, ClientHeight div 2); cvs := TDirect2DCanvas.Create(Canvas, rRect); cvs.RenderTarget.CreateSolidColorBrush(D2D1ColorF(clRed), nil, iBrush); cvs.RenderTarget.BeginDraw; cvs.RenderTarget.DrawTextLayout(D2D1PointF(0, 0), iTextLayout, iBrush); cvs.RenderTarget.EndDraw; cvs.Free; end; procedure TForm1.FormResize(Sender: TObject); begin Repaint; end;
效果图:

分类:
Direct2D
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
2010-04-16 学 Win32 汇编[28] - 跳转指令: JMP、JECXZ、JA、JB、JG、JL、JE、JZ、JS、JC、JO、JP 等
2010-04-16 如何放缩 TWebBrowser 中的页面 - 回复 "飘逸的蓝" 的问题
2009-04-16 用一个 Byte 数表示 8 个复选框的选择状态
2008-04-16 Windows 编程[6] - 学习窗体生成的过程六: 最终的代码!