杰克日记http://blog.yesky.com/Blog/1happyjack/复制地址

药学、化学及其他

控制面板
日历
<2008年10月>
SuMoTuWeThFrSa
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678
留言簿(2)
文章分类
文章档案

近日,用Delphi编程时,遇到一个莫名其妙的异常:EOutOfResources,这是一个可以重复再现的异常。开始以为是程序中创建的对象太多,导致占用了过多的资源,引起了这个异常。于是在代码中将许多不必要创建的对象统统删减,对代码进行了彻底的大瘦身,谁知竟然毫无效果!

此时才注意到提示中有一句:“EOutOfResources with message 'RichEdit line insertion error'”。这就奇怪了,RichEdit控件中明明才添加了很少的几行文字,怎么会引起EOutOfResources这样的异常呢?

在著名的大富翁论坛上搜索了一下,发现有关于此问题的两个讨论,其中一位仁兄认为初始化时加上这句就行了:

SendMessage(RichEdit1.Handle,WM_USER+53,0,$7FFFFFFF);

这句的意图是为RichEdit1分配指定大小($7FFFFFFF)的空间,看起来不错,但实际试验了一下,不行。很显然,虽然抛出的是EOutOfResources异常,但实际上并非真的资源不足。

也有人认为是DELPHI VCLBUG。在

procedure TRichEditStrings.Insert(Index: Integer; const S: string);

这个例程中有一句:

if RichEdit.SelStart <> (Selection.cpMax + Length(Str)) then 

raise EOutOfResources.Create(sRichEditInsertError); // 这里报错了!!

这位仁兄认为是WINDOWS RTF计算长度的方法与DELPHI不一致造成了这个bug

很偶然地,我发现RichEdit的这个异常实际上与使用了不恰当的字符集有关。例如:

        RichEdit1.SelAttributes.Name := 'Symbol';

        RichEdit1.SelAttributes.Charset := SYMBOL_CHARSET;

        RichEdit1.Lines.Add(‘这里输入中文字符就出错’);

以上一段代码先指定RichEdit1的字符集为SYMBOL_CHARSET(即“符号”字符集),但随后添加的文本却是由中文字符组成的。Delphi按照SYMBOL_CHARSET字符集计算长度,结果当然与中文字符的长度不同,因为中文字符是双字节字符。此时,RichEdit1就会抛出一个EOutOfResources异常。

再例如,想在RichEdit中加入希腊字母a,写如下语句:

        RichEdit1.Lines.Add(‘α’);

其中的α是用输入法的软键盘输入的。这样也会引起EOutOfResources异常。正确的写法应该是:

        RichEdit1.SelAttributes.Name := 'Symbol';

        RichEdit1.SelAttributes.Charset := SYMBOL_CHARSET;

        RichEdit1.Lines.Add(‘a’);

字母aSYMBOL_CHARSET中就是希腊字母a

至此,真相大白。原来是不同字符集下计算长度的规则不同引起了这个异常。差点错怪了Borland!不过,其实Borland也不能算太冤,分明是字符集设置不当,却偏要不明不白地抛出个EOutOfResources异常来,帮助文档中也没有提到这个问题,看来Borland可能的确疏忽了些什么。


作者:1happyjack 阅读() 评论()  编辑 发表于:2005-03-14 09:41
相关内容
文章评论

  • # re: TRichEdit抛出EOutOfResources的原因分析
  •   RichEdit1.Clear;
      RichEdit1.Lines.Append('');
      RichEdit1.Lines.Append('   【进货凭证管理】');
      RichEdit1.Lines.Append('');
      RichEdit1.Lines.Append('  进货凭证管理是用来管理进货信息的,它将记录下这批货是谁进的、什么时间进');
      RichEdit1.Lines.Append('的、放在哪个仓库里、进货的单据号是多少。');
      RichEdit1.Lines.Append('');
      RichEdit1.Lines.Append('用户在使用进货凭证时,必需登记姓名及储存仓库.这样系统将会在每条进货信?');
    到最好一句为什么就报错。
    dun | 2007-01-25 10:55

    发表评论
    标题 *  
    姓名 *  
    内容 *  
       验证码: *       
           
    版权声明:天极是本Blog托管服务提供商。如本文牵涉版权问题,天极不承担相关责任,请版权拥有者直接与文章作者联系解决。
    Powered by:

    Copyright © 1happyjack