richview中的行高改变有点特别。必须在AfterData 事件执行的时候才能修改;
也就是说,如果简单的放一个按钮,去发送消息给richView->RichEdit ,然后调用frxReport1->ShowReport 是没有用的
正确的做法如下
- 在C++ BUILDER 中增加一个函数SetLineSpace,用来修改RichView的行高
- 在Form的Create事件中,调用frxReport->AddFunction 方法注册一个函数SetLineSpace
- 在Form的Create时间中,调用frxReport->ScriptText 添加AfterData 响应脚本 (这不是必须的,如果直接编辑脚本固定死,也可以)
- 在AfterData的脚本中,调用SetLineSpace
- 在frxReport1->frxReport1UserFunction 响应事件中,调用SetLineSpace 函数。完成设置
下面是实现的代码
头文件
//--------------------------------------------------------------------------- #ifndef Unit1H #define Unit1H //--------------------------------------------------------------------------- #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include "frxClass.hpp" #include "frxDBSet.hpp" #include "frxPreview.hpp" #include <ADODB.hpp> #include <DB.hpp> #include "frxRich.hpp" //--------------------------------------------------------------------------- class TForm1 : public TForm { __published: // IDE-managed Components TfrxReport *frxReport1; TfrxPreview *frxPreview1; TfrxDBDataset *frxDBDataset1; TADOConnection *ADOConnection1; TADOQuery *ADOQuery1; TButton *Button1; TfrxRichObject *frxRichObject1; TEdit *Edit1; TEdit *Edit2; TLabel *Label1; TLabel *Label2; void __fastcall FormCreate(TObject *Sender); Variant __fastcall frxReport1UserFunction(const AnsiString MethodName, Variant &Params); void __fastcall frxReport1EndDoc(TObject *Sender); void __fastcall Button1Click(TObject *Sender); private: // User declarations bool d_flag; public: // User declarations __fastcall TForm1(TComponent* Owner); void TForm1::SetLineSpace(AnsiString name); }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- #endif
//--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #include "Unit1.h" //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "frxClass" #pragma link "frxDBSet" #pragma link "frxPreview" #pragma link "frxRich" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { d_flag = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::FormCreate(TObject *Sender) { ADOQuery1->Open(); //add event notify function frxReport1->AddFunction("void SetLineSpace(name:String)", "SetLineSpace","change the linspace"); //add script for event handle frxReport1->ScriptLanguage = "C++Script"; frxReport1->ScriptText->Clear(); frxReport1->ScriptText->Add( "void richOnAfterData(TfrxComponent sender)" "{" " SetLineSpace(Sender.Name); " "}" ); //don't forget it frxReport1->ScriptText->Add("{}"); //set the event handle for richview's onAfterData TfrxRichView* rich = dynamic_cast<TfrxRichView*>( frxReport1->FindObject("Rich1")); rich->OnAfterData = "richOnAfterData"; } //--------------------------------------------------------------------------- void TForm1::SetLineSpace(AnsiString name) { TfrxRichView* rich = (TfrxRichView*)frxReport1->FindObject(name); rich->RichEdit->SelectAll(); PARAFORMAT2 Para; Para.cbSize = sizeof(Para); Para.dwMask = PFM_LINESPACING; Para.bLineSpacingRule = 4; Para.dyLineSpacing = Edit1->Text.ToIntDef(200); SendMessage(rich->RichEdit->Handle, EM_SETPARAFORMAT, 0, LPARAM(&Para)); rich->RichEdit->SelAttributes->Size = Edit2->Text.ToIntDef(20); } Variant __fastcall TForm1::frxReport1UserFunction( const AnsiString MethodName, Variant &Params) { if (MethodName.UpperCase() == AnsiString("SetLineSpace").UpperCase()) { SetLineSpace(Params.GetElement(0)); } } //--------------------------------------------------------------------------- void __fastcall TForm1::frxReport1EndDoc(TObject *Sender) { d_flag = true; } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { //if click quickly ,the d_flag'll protect the thread synchrolized //otherwise your may get an error if (d_flag) {
d_flag = false; //这句一定要放在前面 frxReport1->ShowReport(); } } //---------------------------------------------------------------------------
实现的效果
此时文字重叠了
除了上述方法之外,还有一个更简单的办法。
在frxReport的OnBeginDoc事件中,调用下面的代码来修改行距,关键点是,给RichView发送消息,必须在BeginOnDoc事件或者是RichView的RTF被赋值之后调用修改行距的函数。
void TDataMod_T::SetRichEditLineSpace() { TfrxRichView* rich = dynamic_cast <TfrxRichView *> (frxReport1->FindObject("Rich1")); if (rich != NULL && rich->Tag > 0) { rich->RichEdit->SelectAll(); PARAFORMAT2 Para; Para.cbSize = sizeof(Para); Para.dwMask = PFM_LINESPACING; Para.bLineSpacingRule = 4; Para.dyLineSpacing = rich->Tag*4; SendMessage(rich->RichEdit->Handle, EM_SETPARAFORMAT, 0, LPARAM(&Para)); } }
除了OnBeginDoc,还可以使用frxReport组件的OnBeforePrint
void __fastcall TForm1::frxReport1BeforePrint(TfrxReportComponent *Sender) { TfrxRichView* rich = dynamic_cast<TfrxRichView*>(Sender); if (rich == NULL) { return; } rich->Tag = 20; if (rich != NULL && rich->Tag > 0) { rich->AllowExpressions = false; AnsiString text = rich->RichEdit->Text; rich->RichEdit->SelectAll(); PARAFORMAT2 Para; Para.cbSize = sizeof(Para); Para.dwMask = PFM_LINESPACING; Para.bLineSpacingRule = 4; Para.dyLineSpacing = rich->Tag*40; SendMessage(rich->RichEdit->Handle, EM_SETPARAFORMAT, 0, LPARAM(&Para)); } }