fastreport的中文乱码问题,确实让人头疼,我使用的是delphi6+fastrepport4.7,在4.7版本中,主要表现在以下几种情况。
- 预览不乱码,保存乱码。
- 简体不乱码,繁体乱码。
- 简体系统不乱码,繁体系统乱码。
- 繁体字,写死在模板里面不乱码,但是在数据流中,显示在Memo中就乱码了。
或者还有其他种情况,反正各种情况都可能有, 百度下fastreport乱码,都是说改源码,但是到对应位置一找,也没有找到相对的代码。问题就是这样的问题,而且fastreport的技术支持完全不行,本地化的机构还得重新交钱才能获取到技术支持,直接无语了,看了得自己解决了,但是怎么解决呢。仔细思考,大致有这么两种:
- 根本解决,从fastreport源码里面把这个问题根本解决。由于这个问题异常复杂,而且由于对fastreport工程不了解,从源码解决费时费力,没有这个精力,这个方法基本无望。
- 曲线救国。这个虽然看起来很牛逼的样子,但是需要对fastreport的机制相当了解,而且需要对fastreport处理字符的机制出现乱码问题的根源了解,再考虑躲避方法。看起来很简单的样子,其实也是异常繁琐复杂,但是相对第一种来说,这个还是相对来说比较省时省力。
既然方法已经确定,首先的就是需要对fastreport的运行机制有个大致的了解了。大致的三层架构我就不想说了。这个大家都知道。乱码问题主要出现在渲染层面上。所以我们需要对这个机制进行了解。这时候麻烦来了,网上压根就没有这类资料。怎么办呢,难道去看代码,浩大的fastreport工程不是一两个月能够熟悉的,如果从这里入手,那么还不如从根本上解决这个问题呢,没有资料,又不想看源码,怎么办呢,只能发挥自己充分的想象力啦。
我说下我的思路。如果我们手工画一张报表,需要怎么做呢,每一个Memo都是我们自己手工一个一个画上去的吧,如果我们需要把某个memo的字体改掉,只要改这个memo就好了,那么按照软件设计的常规思路,memo里面应该有能够设置字体的属性,字体中应该是带有编码的。每次渲染的时候,MasterData是怎么工作的呢,我觉得应该是这样的,跟我们手动做报表一样,也是将一个一个memo创建出来然后放到了对应的位置,只不过是MasterData对这些控件进行了抽象。
思路倒是有了,不过都是想象,毕竟没有跟fastreport的开发人员沟通过,不知道他们是不是原来就是这么设计的,我只是从常规的思路猜测了下,现在就先验证下思路是否正确。
的确在Memo属性下找到了字体设置。有编码也有字体类型。
按照正常思路,一般设置字体就能够解决乱码问题。因为有时候是由于字体只支持单字节导致中文乱码,把字体改为新宋体,的确解决了简体的乱码,保存成PDF都不乱码了。又发现繁体乱码,还有编码可以设置。直接设置成CHINESEBIG5_CHARSET的编码。繁体也正常了。到这里,乱码问题的一二三项都解决了。
第四项问题稍微有点头疼了。我们明明设定好了memo的字体和编码,理论上只要不是碰上BIG5编码的时候的简体字,或者默认编码下的繁体字,应该不会是乱码的。经过一番思考,分析如下:
- 既然设定好编码不会乱码了,证明设定编码的方式是有效的。
- MasterData进行数据展示的时候,Memo控件也是一个个生成的,那么设定好编码的话,理论上也不会发生乱码。
由以上分析得出,猜测是动态生成的时候编码没有设定好,或者是编码乱掉了。那么,尝试解决思路就是如何在动态生成的时候重新设定编码。然后看到控件meno里面有几个事件。看事件名字也可以知道大概的执行顺序。不过,我们也可以用showmessage这个赖皮招来测试事件的执行顺序,这个是个技巧啦。经测试发现,beforeprint->afterdata->afterprint。但是是在afterdata的时候能够接收到数据。
现在可以在afterdata的时候指定控件的编码啦。但是有一个问题,发现指定的编码CHINESEBIG5_CHARSET这个是个宏定义。但是在代码里面不支持这个宏定义,那么就需要找出这个宏定义是代表什么值了。那么,还是用个笨方法找吧。showmessage。 先把meno的编码设置成CHINESEBIG5_CHARSET,然后把这个编码显示出来就知道了。
在AfterData里面。弹个窗。
frxMemoView := TFrxMemoView(Sender); showmessage(inttostr(frxMemoView.Font.Charset));
通过这个段测试代码得知CHINESEBIG5_CHARSET是编码是136;
那么反过来,我们就可以定义如下。
procedure DealTraditionalCharset(Sender: TfrxComponent); var startStr,memoValue:string; frxMemoView:TFrxMemoView; begin frxMemoView := TFrxMemoView(Sender); memoValue := frxMemoView.Value; if trim(memoValue) = '' then //有些是空值,很奇怪的。过滤掉。 Exit; frxMemoView.Memo.Text := memoValue; frxMemoView.Font.Charset := 136; // CHINESEBIG5_CHARSET end;
以上代码就是动态设置memo为繁体编码。如果数据流中,简体和繁体同时存在,目前所发现的编码中,由于我所使用的4.7版本尚未支持UFT8编码。所以这个是肯定会有乱码的。不过,如果繁体和简体不是同时存在,就是说繁体和简体不会存在同一段数据流,只是间隔数据流的话,如果在数据流里面加一个字体的标记,那么就可以动态控制memo的编码使之不乱码了。
fastreport资料是在是太少了,而且网上估计也有不少人为这个编码问题头疼吧。在这个啥资料都没有的情况下,我觉得突破思路不外乎我这种了,从底层,内部结构开始构思,很多这种没有资料的东西,就假设如果是你自己开发的fastreport,你会怎么设计呢,也不外乎计算机的原理罢了。理同其理,法同其法,万物归一。