精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
锐英源精品开源心得,转载请注明:“锐英源www.wisestudy.cn,孙老师作品,电话13803810136。需要全文内容也请联系孙老师。
As you will probably encounter this problem in WinForm development--you can't create System.Drawing.Font instances from OpenType fonts. That's because the implementation of that class has used GDI+, which provides very limited support for OpenType fonts.
你可能在WinForm开发中遇到这样的问题——你不能从OpenType字体创建System.Drawing字体实例。这是因为该类使用GDI+来实现,它提供对OpenType字体提供的支持非常有限。
There are several way-outs. One is to switch to WPF from WinForm, which supports OpenType fonts, but I guess you won't do so easily, especially when the other parts of your code are fine and nice and the only missing feature is just the OpenType font files support. The second way is to use FreeType, a fabulous font rendering engine. It is viable but you have some good stuff to learn.
有几种途径。一种是从WinForm的,它支持OpenType字体切换到WPF,,但我猜你做起来不会那么容易,尤其是当您的代码的其他部分都很好,唯一缺失的功能就是对OpenType字体文件的支持。第二种方法是使用FreeType,令人难以置信的字体绘制引擎。它是可行的,但是你有一些好东西要学。
Hereby, this tip provides a method of rendering text with OpenType fonts by P/Invoking the system API. 在此,本文提供一种通过API系统调用来实现OpenType字体绘制文本。
The GDI+ API used by the .NET platform does not support OpenType fonts well, but the system wide API, GDI (without the plus sign, but does more here), supports OpenType much better. We can use Platform Invoke to call functions exposed by the GDI and render texts with OpenType fonts.
GDI + API使用的网络平台不支持OpenType字体,但系统级API,如GDI(没有加号,但能做更多),能更好的支持OpenType。我们可以使用平台调用来调用公开的GDI函数和绘制文本的OpenType字体。
The procedure is listed below. The major functions to use are the CreateFont function and the DrawText function. 该过程如下。所使用的主要功能是CreateFont函数和DrawText函数。
Get the device context (DC) from the graphics. 从图形获取设备描述表(DC)。
Call the CreateFont function and create the GDI font. 调用CreateFont函数并创建GDI字体。
Use the font in the DC by calling SelectObject. 通过调用选择对象使用DC的字体
Call the DrawText function and draw the text onto the specific region of the DC. 调用DrawText函数并且绘制文本的特定区域。
Release the resources by calling DeleteObject. 通过调用DeleteObject释放资源。
The C# code is listed below, there are some other functions involved, but they are just listed for your reference. 下面列出的c#代码,还有一些其他的功能,但他们只是列出,供您参考。
public static void RenderText(IDeviceContext hdc, string text, string fontFamily, Color color, Rectangle region, int size) { // create the handle of DC var h = new HandleRef (null, hdc.GetHdc ()); // create the font var p = new HandleRef (null, NativeMethods.CreateFont (size, 0, 0, 0, 0, 0, 0, 0, 1/*Ansi_encoding*/, 0, 0, 4, 0, fontFamily)); try { // use the font in the DC NativeMethods.SelectObject (h, p.Handle); // set the background to transparent NativeMethods.SetBkMode (h, 1); // set the color of the text NativeMethods.SetTextColor (h, color); // draw the text to the region NativeMethods.DrawText (h, text, region, 0x0100); } finally { // release the resources NativeMethods.DeleteObject (p); hdc.ReleaseHdc (); } }
We should firstly prepare our P/Invoke code for use. The protocol of the CreateFont function and DrawText function can be found out from MSDN.
我们应该首先准备P/ Invoke代码备用。该协议CreateFont函数和DrawText函数可以从MSDN找到。
HFONT CreateFont( __in int nHeight, __in int nWidth, __in int nEscapement, __in int nOrientation, __in int fnWeight, __in DWORD fdwItalic, __in DWORD fdwUnderline, __in DWORD fdwStrikeOut, __in DWORD fdwCharSet, __in DWORD fdwOutputPrecision, __in DWORD fdwClipPrecision, __in DWORD fdwQuality, __in DWORD fdwPitchAndFamily, __in LPCTSTR lpszFace ); int DrawText( __in HDC hDC, __inout LPCTSTR lpchText, __in int nCount, __inout LPRECT lpRect, __in UINT uFormat );
And the corresponding P/Invoke code can be the following: 相应的 P/Invoke 代码如下:
const string GDI32 = "gdi32.dll"; struct Rect { public long Left, Top, Right, Bottom; public Rect (Rectangle rect) { this.Left = rect.Left; this.Top = rect.Top; this.Right = rect.Right; this.Bottom = rect.Bottom; } } [DllImport (GDI32)] internal static extern IntPtr CreateFont ( int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, uint fdwItalic, uint fdwUnderline, uint fdwStrikeOut, uint fdwCharSet, uint fdwOutputPrecision, uint fdwClipPrecision, uint fdwQuality, uint fdwPitchAndFamily, string lpszFace ); [DllImport (USER32, CharSet = CharSet.Auto)] static extern int DrawText (HandleRef hDC, string lpchText, int nCount, ref Rect lpRect, uint uFormat); internal static int DrawText (HandleRef hDC, string text, Rectangle rect, uint format) { var r = new Rect (rect); return DrawText (hDC, text, text.Length, ref r, format); }
With the above stuff ready, the rest is quite easy. You just need to gather the parameters and call the RenderText method, like the following code shows:
上面的东西准备好了,剩下的就很容易了。你只需要收集参数并调用RenderText方法,就像下面的代码显示:
private void panel1_Paint (object sender, PaintEventArgs e) { int size; if (Int32.TryParse (comboBox1.Text, out size) == false) { size = (int)SystemFonts.DefaultFont.Size; } RenderText (e.Graphics, textBox1.Text, textBox2.Text, Color.Red, panel1.ClientRectangle, size); }
You can download the demo application and see how it works. The screen shot at the top of this tip shows an OpenType font LiheiPro is used to render some Chinese and Japanese fonts, which is impossible with the managed .NET API that calls GDI+.
你可以下载演示应用程序,看看它是如何工作的。本文章的顶部屏幕截图显示一个OpenType字体LiheiPro用于绘制一些中国和日本的字体,.托管的NET API 调用GDI+是不可能w完成的。
The GDI methods can return error codes. However, our demo application just assumes everything will go well. You shall refer to the documentation on MSDN and see how to deal with them.
GDI方法可以返回错误代码。然而,我们演示的应用程序一切顺利。你要参考MSDN文档,看看如何处理它们。