找回密码
 立即注册

QQ登录

只需一步,快速开始

graper

高级会员

45

主题

63

帖子

1348

积分

高级会员

积分
1348

活字格认证

graper
高级会员   /  发表于:2009-12-14 09:42  /   查看:8828  /  回复:1
Post by "KevinShan",  02-27-2007, 12:20
-----------------------------------------------------

使用TextRenderer.DrawText在控件上面画文字,在Win2000环境下所画的文字显示不出来。而在WinXP下可以正常显示 (微软的Label控件也是用TextRenderer画的,在两种环境下都可以显示出来)。 不知道是什么问题,在这里寻求大家的帮助。谢谢!

开发环境: .NET2.0 + Vs2005

下面使我测试用的画文字的代码,

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Text;
  7. using System.Windows.Forms;

  8. namespace DrawTextDemo
  9. {
  10.     public class TestControl : Control
  11.     {
  12.         protected override void OnPaint(PaintEventArgs pe)
  13.         {
  14.             // 使用TextRenderer.DrawText在Win2000下显示不处理,XP系统下正常.
  15.             TextRenderer.DrawText(pe.Graphics, this.Text, this.Font, Point.Empty, this.ForeColor);

  16.             // 使用Graphics.DrawString在Win2000下和Xp下面均正常.
  17.             pe.Graphics.DrawString(this.Text, this.Font, SystemBrushes.WindowText, new PointF(0f, 50f));
  18.             base.OnPaint(pe);
  19.         }
  20.     }
  21. }
复制代码
Reply by "ted",  02-28-2007, 16:51
-----------------------------------------------------

貌视很诡异的问题:
Reflector Lable的代码后发现,其使用了另外一个重载的DrawText函数:

  1. public static void DrawText (
  2. IDeviceContext dc,
  3. string text,
  4. Font font,
  5. Rectangle bounds, // 注意到这里传入是Rectangle
  6. Color foreColor
  7. )
复制代码
于是更改TestControl的写法如下:

  1. public class TestControl : Control   
  2. {      
  3. protected override void OnPaint(PaintEventArgs pe)      
  4. {            
  5.              // Use TextRenderer.           
  6.             TextRenderer.DrawText(pe.Graphics, this.Text, this.Font, new Rectangle(0,0,100,30), this.ForeColor);
  7.              // Use Graphics           
  8.             pe.Graphics.DrawString(this.Text, this.Font, SystemBrushes.WindowText, new PointF(0f, 50f));           
  9.            base.OnPaint(pe);      
  10. }   
  11. }
复制代码
Text将被画出。

于是再Reflector TextRenderer的public static void DrawText(IDeviceContext dc, string text, Font font, Point pt, Color foreColor){}函数,发现其最终调到的代码是:

  1. public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, IntTextFormatFlags flags)
  2. {
  3.     Rectangle bounds = new Rectangle(pt.X, pt.Y, 0x7fffffff, 0x7fffffff);
  4.     this.DrawText(text, font, bounds, foreColor, backColor, flags);
  5. }
复制代码
其内部创建了一个长宽均为0x7fffffff的矩形来绘画文字。

尝试下面的代码:

  1. TextRenderer.DrawText(pe.Graphics, this.Text, this.Font, new Rectangle(0,0,0x7fffffff,0x7fffffff), this.ForeColor);
复制代码
没有任何显示。

所以我想原因可能在于在Win2000上实际绘画的API函数不能处理长宽均为0x7fffffff的矩形,而Xp及以后的操作系统均支持。



Reply by "KevinShan",  02-28-2007, 17:01
-----------------------------------------------------

非常感谢!

这应该是微软的一个Bug, 我原来也碰到过类似的问题。如CreateRectRgn的API也只能接受小于27 bit的整数。

问题出在TextRenderer在调用native code的时候传递的Rectangle太大导致在Win2000下面API调用出错,XP以上系统已经解决。



Reply by "Leo",  02-28-2007, 17:33
-----------------------------------------------------

简单的试了一下Code。发现如果我们使用DrawText方法传参数是一个点而不是一个Rectangle就会导致在2000系统下完全不显示。

使用Reflector重新拜读了TextRenderer的代码。发现有这么一段

  1. public void DrawText(string text, WindowsFont font, Point pt, Color foreColor, Color backColor, IntTextFormatFlags flags)
  2. {
  3.     Rectangle bounds = new Rectangle(pt.X, pt.Y, 0x7fffffff, 0x7fffffff);
  4.     this.DrawText(text, font, bounds, foreColor, backColor, flags);
  5. }
复制代码
发现给的Rectangle的长和宽都比较大。不知道是否会导致API调用失败。然后尝试跟了一下API调用结果。发现返回结果非零,说明API调用成功。但是什么也画不出来。

目前这个问题已经解决了。使用TextRenderer的时候传参数给出具体的Rectangle的大小。但是为什么这样还不是很清楚。不知道那位高手能指点一下。

1 个回复

倒序浏览
gw0506
超级版主   /  发表于:2010-9-26 16:40:00
沙发
棒!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 立即注册
返回顶部