Canvas属性中SetCanvas处理的疑问 |
尚未結案
|
fangwy
中階會員 發表:99 回覆:139 積分:62 註冊:2003-09-10 發送簡訊給我 |
我设计的class部分代码如下:
property Canvas: TCanvas read GetCanvas write SetCanvas; function TBASPrinter.GetCanvas: TCanvas;
begin
if FCanvas = nil then
begin
FCanvas := TCanvas.Create;
FCanvas.Font := CurrencyPrinter.Canvas.Font;
end;
Result := FCanvas;
end;
procedure TBASPrinter.SetCanvas(Value: TCanvas);
begin
if FCanvas = nil then
FCanvas := TCanvas.Create;
FCanvas := Value;
SetLength(PrinterCanvas, FLines.Count - 1);
if PrinterCanvas[FLines.Count - 1] = nil then
PrinterCanvas[FLines.Count - 1] := TCanvas.Create;
PrinterCanvas[FLines.Count - 1] := FCanvas;
end;
我发现
SetLength(PrinterCanvas, FLines.Count - 1);
if PrinterCanvas[FLines.Count - 1] = nil then
PrinterCanvas[FLines.Count - 1] := TCanvas.Create;
PrinterCanvas[FLines.Count - 1] := FCanvas;
这一段好象根本没执行到,PrinterCanvas在使用时根本没被创建和赋值.想在这段上设断点跟踪,发现根本没法跟踪(运行起来,断点的颜色不再是红色).但是FCanvas 执行时明明已变成了设置的新值.
请教各位大大,SetXXXX个procedure的原理,及如何运用.
另外说明一下:FLines这个变量对应的属性在运行时正确.
|
aquarius
資深會員 發表:3 回覆:347 積分:330 註冊:2003-05-21 發送簡訊給我 |
PrinterCanvas 的定義是什麼? string or dynamic-array variable? 看你的程式, 應該只是想把 Canvas 記在一個 List 中.
建議使用 TList
lst : TList ; procedure TBASPrinter.SetCanvas(Value: TCanvas); begin if FCanvas = nil then FCanvas := TCanvas.Create; FCanvas := Value; if lst=nil then lst:=TList.create ; if lst.count
------
水瓶男的blog: http://791909.blogspot.com |
fangwy
中階會員 發表:99 回覆:139 積分:62 註冊:2003-09-10 發送簡訊給我 |
aquarius:
PrinterCanvas定义如下
PrinterCanvas: array of TCanvas; //打印格式;
其作用是记录运用中设置的Canvas
如下应用的例子:
var
Tcr: TTCRPrinter;
begin
try
Tcr := TTCRPrinter.Create(pBill);
except
on E: Exception do
begin
Label3.Caption := E.Message;
Abort;
end;
end;
Tcr.Canvas.Font.Name := '宋体';
Tcr.Canvas.Font.Size := 11;
Tcr.Lines.Add('0,0,第一行');
Tcr.Lines.Add('5,5,第二行');
Tcr.Lines.Add('10,10,第三行');
Tcr.Lines.Add('15,15,第四行');
Tcr.Lines.Add('20,20,第五行');
Tcr.Canvas.Font.Name := '黑体';
Tcr.Canvas.Font.Size := 12;
Tcr.Lines.Add('25,25,第六行');
Tcr.Lines.Add('30,30,第七行');
Tcr.Lines.Add('35,35,第八行');
Tcr.Canvas.Font.Name := '楷体';
Tcr.Canvas.Font.Size := 14;
Tcr.Lines.Add('40,40,第九行');
Tcr.Lines.Add('45,45,第十行');
Tcr.Lines.Add('L,45,第十一行');
Tcr.Lines.Add('C,45,第十二行');
Tcr.Lines.Add('R,45,第十三行');
Tcr.Print();
Label3.Caption := Tcr.Error;
end;
Tcr.Lines(TString型)是Print()打印的数据,使用PrinterCanvas的目的是记录三次设置的Canvas,并在打印时正确的使用到指定的行. 發表人 - fangwy 於 2004/12/07 09:36:08 發表人 - fangwy 於 2004/12/07 09:41:49
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
FCanvas: array of TCanvas; property Canvas[LineNo: Integer]: TCanvas read GetCanvas; TBASPrinter.Create; begin ... FCanvas := nil; end; TBASPrinter.Destroy; var I: Integer; begin for I := 0 to Length(FCanvas)-1 do if Assigned(FCanvas[I]) then FCanvas[I].Free; FCanvas := nil; end; TBASPrinter.GetCanvas(LineNo: Integer): TCanvas; begin Result := nil; if(LineNo>-1)and(LineNo |
fangwy
中階會員 發表:99 回覆:139 積分:62 註冊:2003-09-10 發送簡訊給我 |
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
LineNo 並不用來累加,它只是用來作為索引用的,
用來透過property Canvas 的 GetMethod指向一個物件,
也就是說FLines中的每一個Item(string)可以有
其相對應的TCanvas.
procedure TBASPrinter.SetCanvas(Value: TCanvas); begin if FCanvas = nil then FCanvas := TCanvas.Create;FCanvas指向產生的物件 FCanvas := Value; FCanvas又指定為傳入物件 如此將產生記憶體遺漏,有物件沒有被釋放 SetLength(PrinterCanvas, FLines.Count - 1); if PrinterCanvas[FLines.Count - 1] = nil then PrinterCanvas[FLines.Count-1] := TCanvas.Create;<---同上 PrinterCanvas[FLines.Count-1] := FCanvas; <---同上 end; [blue] A, B: TPersistent; A := TPersistent.Create; 可視為 (1) TPersistent.Create ---> 產生一個TPersistent (2) 物件指標 A 指向新產出的物件 B := A; //B 與 A 指向同一物件 最後必須保留 A 或 B 來釋放物件 A := nil; B.Free; 或 B := nil; A.Free; ==>property Canvas 透過 GetCanvas(LineNo: Integer): TCanvas; 取得一個TCanvas 物件指標. ==>FCanvas: array of TCanvas; 用來指向產出的TCanvas,提供做為被索引的目標,最後也用來釋放所有自行產生的所有TCanvas. |
fangwy
中階會員 發表:99 回覆:139 積分:62 註冊:2003-09-10 發送簡訊給我 |
谢谢jow.不过我试了一下,这种做法不符合我的要求,因为每次设定Canvas时都必须指定对应的LineNo,而我想达到的效果是用户只要设置Canvas,至于如何记录使打印时与行匹配,由程序处理.就如我的例子:
Tcr.Canvas.Font.Name := '宋体';
Tcr.Canvas.Font.Size := 11;
Tcr.Lines.Add('0,0,第一行');
Tcr.Lines.Add('5,5,第二行');
Tcr.Lines.Add('10,10,第三行');
Tcr.Lines.Add('15,15,第四行');
Tcr.Lines.Add('20,20,第五行');
Tcr.Canvas.Font.Name := '黑体';
Tcr.Canvas.Font.Size := 12;
Tcr.Lines.Add('25,25,第六行');
Tcr.Lines.Add('30,30,第七行');
Tcr.Lines.Add('35,35,第八行');
Tcr.Canvas.Font.Name := '楷体';
Tcr.Canvas.Font.Size := 14;
Tcr.Lines.Add('40,40,第九行');
Tcr.Lines.Add('45,45,第十行');
Tcr.Lines.Add('L,45,第十一行');
Tcr.Lines.Add('C,45,第十二行');
Tcr.Lines.Add('R,45,第十三行');
Tcr.Print();
对用户而言只需要在以不同字体打印的行前设置一下Canvas就行,而不必关心新设置的Canvas对应的是哪个LineNo.这样比较方便.
不知我是否完全理解jow兄的做法.
|
jow
尊榮會員 發表:66 回覆:751 積分:1253 註冊:2002-03-13 發送簡訊給我 |
sorry,我想我弄錯了你的需求,不過你的程式碼好像不是你說的這樣喔!
以下是你的程式碼 function TBASPrinter.GetCanvas: TCanvas; begin if FCanvas = nil then begin FCanvas := TCanvas.Create; FCanvas.Font := CurrencyPrinter.Canvas.Font; end; Result := FCanvas; end; procedure TBASPrinter.SetCanvas(Value: TCanvas); begin if FCanvas = nil then FCanvas := TCanvas.Create; FCanvas := Value; SetLength(PrinterCanvas, FLines.Count - 1); if PrinterCanvas[FLines.Count - 1] = nil then PrinterCanvas[FLines.Count - 1] := TCanvas.Create; PrinterCanvas[FLines.Count - 1] := FCanvas; 這段程式碼好像是為FLines的每一行,至少是為FLines.Count-1行,各配置一個TCanvas 吧 end;我想我要說的是你在所寫的Class中對於TCanvas的產生及指定的做法上,可能會產生記憶體遺漏的問題.還有就是指定TCanvas做為動作目標點的HDC的問題. 如果你的需求只是Keep由用戶端指定一個TCanvas的話,我認為你的Class裡只需要保留一個TCanvas的物件指標,而不需要去Create它,至於TCanvas 的生成和釋放的動作應由用戶端負責. 個人看法,謹供參考. |
fangwy
中階會員 發表:99 回覆:139 積分:62 註冊:2003-09-10 發送簡訊給我 |
谢谢jow兄的耐心解答,我第一次贴的代码有问题,所以达不到想要的效果,仅管有些class的原理我还不很明白,但try了几种方法,我已实现了我的设计.就是每增加一行就增加一个PrinterCanvas元素,如果有新的Canvas设置就在新增加的PrinterCanvas元素中记录.在开始打印时,每一行打印前都检查对应的printerCanvas元素是否为空,如果不为空则使用.在Destroy中统一将创建的PrinterCanvas一次性释放.
也要谢谢aquarius兄. 發表人 - fangwy 於 2004/12/13 09:25:10
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |