I have a program that use TRichViewEdit to list info , but run several minutes it show " Raise exception class EInvalidOperation with Message 'Canvas does not allow drawing'". who can help me !
This is my all code:
Main Form code
Code: Select all
unit main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,SyncObjs, ToolWin, ComCtrls, StdCtrls, ImgList,UwriteThread,UreadThread,
RVStyle, RVScroll, RichView, RVEdit, CRVFData;
type
TMainForm = class(TForm)
ToolBar1: TToolBar;
ImageList1: TImageList;
ToolButton1: TToolButton;
ToolButton2: TToolButton;
ToolButton3: TToolButton;
RichViewEdit1: TRichViewEdit;
RVStyle1: TRVStyle;
Label1: TLabel;
ImageList2: TImageList;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure ToolButton3Click(Sender: TObject);
procedure ToolButton1Click(Sender: TObject);
procedure ToolButton2Click(Sender: TObject);
procedure RichViewEdit1Jump(Sender: TObject; id: Integer);
private
{ Private declarations }
public
{ Public declarations }
Function MakeTag(s:String):Integer;
function GetTagStr(tag:integer):string; //»сИЎ±кЗ©ПВµДЦµЈ¬
end;
type
myInfo = class
id:integer;
name:string;
end;
var
MainForm: TMainForm;
GLogCS: TCriticalSection;
aList:TList;
Twrite:writeThread;
Tread:readThread;
implementation
{$R *.dfm}
procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
aList.Clear;
FreeAndNil(GLogCS);
FreeAndNil(aList);
Action:=caFree;
end;
procedure TMainForm.FormCreate(Sender: TObject);
begin
RichViewEdit1.Clear;
RichViewEdit1.Format;
GLogCS := TCriticalSection.Create;
aList:=TList.Create;
end;
procedure TMainForm.ToolButton3Click(Sender: TObject);
begin
if Tread <> nil then
Tread.Terminate;
if Twrite <> nil then
Twrite.Terminate;
close;
Application.Terminate;
end;
procedure TMainForm.ToolButton1Click(Sender: TObject);
begin
try
if Tread = nil then
Tread:=readThread.Create(aList)
else
Tread.Resume;
if Twrite = nil then
Twrite:=writeThread.Create(aList,RichViewEdit1)
else
Twrite.Resume;
except
if Twrite <> nil then
Twrite.Terminate;
Twrite:=writeThread.Create(aList,RichViewEdit1);
end;
end;
procedure TMainForm.ToolButton2Click(Sender: TObject);
begin
if Tread <> nil then
Tread.Suspend;
if Twrite <> nil then
Twrite.Suspend;
end;
function TMainForm.MakeTag(s: String): Integer;
begin
Result := Integer(StrNew(PChar(s)));
end;
function TMainForm.GetTagStr(tag: integer): string;
var i: Integer;
begin
Result := PChar(tag);
for i := 1 to Length(Result) do
if Result[i]=#1 then
Result[i] := ' ';
end;
procedure TMainForm.RichViewEdit1Jump(Sender: TObject; id: Integer);
var
RVData: TCustomRVFormattedData;
ItemNo: Integer;
i:integer;
hideInfo:string;
begin
RichViewEdit1.GetJumpPointLocation(id,Rvdata,itemNo);
if RVData<>nil then begin
hideInfo := GetTagStr(RVData.GetItemTag(ItemNo));
RichViewEdit1.ReadOnly := false;
RichViewEdit1.SetItemTextEd(ItemNo,'ХвКЗТюІШєуµДРЕПўЈє'+hideInfo);//¶ЇМ¬ЙиЦГПФКѕµДРЕПўОЄТюІШµДРЕПўДЪИЭ
RichViewEdit1.ReadOnly := true;
RichViewEdit1.Refresh;
end;
end;
end.
Code: Select all
unit UwriteThread;
interface
uses
Classes,SysUtils, StdCtrls, RVEdit, RVStyle,Graphics;
type
writeThread = class(TThread)
private
writeList:TList;
RichViewEdit: TRichViewEdit;
protected
procedure writeToMemo;
procedure Execute; override;
public
constructor Create(strList:TList;me:TRichViewEdit);
end;
implementation
uses main;
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure writeThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
{ writeThread }
constructor writeThread.Create(strList:TList;me:TRichViewEdit);
begin
writeList:=strList;
RichViewEdit :=me;
//Memo:=me;
FreeOnTerminate := True; // ЧФ¶ЇЙѕіэ
inherited Create(false);
end;
procedure writeThread.Execute;
begin
while not Terminated do
begin
//Synchronize(writeToMemo);
writeToMemo;
sleep(1000);
end;
end;
procedure writeThread.writeToMemo;
var
sinfo:myInfo;
begin
if writeList.Count > 0 then begin
sinfo:=myInfo.create;
try
GLogCS.Enter;
sinfo:=writeList[0];
writeList.Delete(0);
GLogCS.Leave;
RichViewEdit.ReadOnly:=false;
RichViewEdit.TopLevelEditor.BeginUndoGroup(rvutInsert);
RichViewEdit.TopLevelEditor.SetUndoGroupMode(True);
RichViewEdit.InsertText(#13);
RichViewEdit.ApplyParaStyle(2);
RichViewEdit.ApplyTextStyle(0);
RichViewEdit.InsertText('title');
RichViewEdit.InsertTab;
if RichViewEdit.InsertHotspot(0,0,Mainform.ImageList2) then begin
RichViewEdit.SetCurrentItemText('phone');
RichViewEdit.SetCurrentTag(mainform.MakeTag(sinfo.name));
end;
RichViewEdit.InsertText(#13);
RichViewEdit.ApplyParaStyle(0);
RichViewEdit.ApplyTextStyle(2);
RichViewEdit.InsertStringTag(sinfo.name, mainform.MakeTag(sinfo.name));
RichViewEdit.InsertBreak(0, rvbsLine, clRed);
RichViewEdit.ReadOnly:=true;
RichViewEdit.FormatTail;
RichViewEdit.SetSelectionBounds(0, RichViewEdit.GetOffsBeforeItem(0), 0, RichViewEdit.GetOffsBeforeItem(0));
finally
RichViewEdit.TopLevelEditor.SetUndoGroupMode(False);
sinfo.Free;
end;
end;
end;
end.
read thread code
Code: Select all
unit UreadThread;
interface
uses
Classes,SysUtils, StdCtrls;
type
readThread = class(TThread)
private
readList:TList;
protected
procedure Execute; override;
procedure readText;
public
constructor Create(strList:TList);
end;
implementation
uses main;
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure readThread.UpdateCaption;
begin
Form1.Caption := 'Updated in a thread';
end; }
{ readThread }
constructor readThread.Create(strList: TList);
begin
readList:=strList;
FreeOnTerminate := True; // ЧФ¶ЇЙѕіэ
inherited Create(false);
end;
procedure readThread.Execute;
begin
while not Terminated do
begin
readText;
sleep(15000);
end;
end;
procedure readThread.readText;
var
f:TextFile;
S:string;
sinfo:myInfo;
begin
try
AssignFile(f, '.\log.txt');
Reset(f);
while not eof(F)do
begin
sinfo:=myInfo.create;
Readln(F, S);
GLogCS.Enter;
sinfo.id:=0;
sinfo.name:=S;
readList.Add(sinfo);
GLogCS.Leave;
Mainform.Label1.Caption:=inttostr(readList.Count);
end;
finally
FreeAndNil(sinfo);
CloseFile(F);
end;
end;
end.
Code: Select all
program ThreadTest;
uses
Forms,
main in 'main.pas' {MainForm},
UwriteThread in 'UwriteThread.pas',
UreadThread in 'UreadThread.pas';
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.