文档章节

Direct2D (43) : IDWriteGdiInterop 接口

涂孟超
 涂孟超
发布于 2014/09/26 15:30
字数 947
阅读 12
收藏 0

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;


效果图:



本文转载自:http://www.cnblogs.com/del/archive/2011/04/16/2016973.html

共有 人打赏支持
涂孟超
粉丝 12
博文 2011
码字总数 14107
作品 0
深圳
程序员
私信 提问
Direct2D教程(十)绘制文本

概述 在Direct2D中,文本的绘制是通过DirectWrite来实现的,DirectWrite实际上已经是一个独立的DirectX组件了。关于DirectWrite,我摘录了MSDN的一段文字。 DirectWrite介绍 当今的应用程序应...

吞吞吐吐的
2017/10/17
0
0
关于Direct3D11里汉字显示的一些思考

本系列文章由zhmxy555(毛星云)编写,转载请注明出处。 http://blog.csdn.net/zhmxy555/article/details/8147234 作者:毛星云 邮箱: happylifemxy@163.com 这篇文章里,浅墨希望与大家一起...

长平狐
2012/11/12
794
0
使用 Direct2D 绘制分层窗口

这是我关于Direct2D的第三篇介绍了,今天主要讲下其无可比拟的互操作性。为了避免繁缛末节的讲述,我们从一个实例入手:层级窗口。相对于windows的其它众多功能。层级窗口并未做相应的更新,...

Dy_
2014/01/16
8.2K
10
Wine 1.7.42 发布,Windows 模拟器

Wine 1.7.42 发布,此版本更新内容如下: 支持动态时间域信息 支持初始桌面 shell 窗口 支持更多的 Direct2D 各种 bug 修复 此版本源代码现已提供下载,二进制包会尽快提供在下载页面。 Wine...

oschina
2015/05/02
2.2K
7
Wine 1.7.27 发布,继续改进对 Direct2D 的支持

Wine 1.7.27 发布,此版本更新内容如下: 更好的支持 Direct2D 对 RichEdit 接口进行各种改进 初步支持 ICMP 版本6 各种 bug 修复 Wine 1.7.27 源代码现已提供下载,二进制包将会提供在下载页...

oschina
2014/09/20
1K
2

没有更多内容

加载失败,请刷新页面

加载更多

EFCore DbFirst 生成实体类

1、Nuget引用: Install-package Microsoft.EntityFrameworkCore.Tools Install-package Microsoft.EntityFrameworkCore.Design Install-package Microsoft.EntityFrameworkCore.SqlServer 2......

万邦科技-Anthony
51分钟前
2
0
OSChina 周三乱弹 —— 哽住

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @蓝瞳 :分享高橋広樹的单曲《銀河沿線'05<Vo>》:一直暗恋却无法表白的女孩在电车上疲倦不堪累得靠在他的肩上,播磨拳儿终于忍不住流下了眼泪...

小小编辑
今天
546
10
shell输入内容时不显示内容

简介 大家都知道当我们ssh登录linux服务器的时候输入密码密码是不显示在屏幕上的,同样在我们写shell脚本的时候在获取用户密码的时候,有时候也希望不显示密码,这个是怎么做的呢 实例脚本 ...

bboysoulcn
今天
3
0
第11章 多线程

程序、进程、线程 程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码,静态对象。 **进程(process)**是程序的一次执行过程或是正在运行的一个程序。动...

流小文
今天
10
0
SpringBoot引入第三方jar包或本地jar包的处理方式

在开发过程中有时会用到maven仓库里没有的jar包或者本地的jar包,这时没办法通过pom直接引入,那么该怎么解决呢 一般有两种方法 - 第一种是将本地jar包安装在本地maven库 - 第二种是将本地j...

独钓渔
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部