我该如何在Delphi中获取TEdit的画布?

7
我想将文件名缩短以适应TEdit,类似于:
Edit1.Text := MinimizeName(FileName, Edit1.Canvas, Edit1.Width);

很遗憾,这段代码无法编译,因为TEdit没有直接的Canvas属性。Canvas属性是需要用来获取字体度量信息的。

我该如何访问TEdit的Canvas属性呢?

MinimizeName在Vcl.FileCtrl中声明。)

3个回答

7
你可以使用 TControlCanvas。同时,你需要考虑控件的字体。
var
  Canvas: TControlCanvas;

Canvas := TControlCanvas.Create;
try
  Canvas.Control := Edit1;
  Canvas.Font.Assign(Edit1.Font); 

  // Do something with Canvas... 
finally
  Canvas.Free;
end;

好主意,但不能包装在一个接收TWinControl作为参数的函数中,因为Font属性在TWinControl中没有公开。所以,我们只是将一个问题(无法访问画布)换成了另一个问题(无法访问字体)。 - Gabriel

6

好的,我找到了。对于那些感兴趣的人:

procedure TForm1.Button1Click(Sender: TObject);  
var  
  aCanvas: TCanvas;  
begin  
  if FileOpenDialog1.Execute then begin  
    aCanvas := TCanvas.Create;  
    try  
      aCanvas.Handle := GetDC(Edit1.Handle);  
      Edit1.Text := MinimizeName(FileOpenDialog1.FileName, aCanvas, Edit1.Width - 8);  
    finally  
      ReleaseDC(Edit1.Handle, aCanvas.Handle);
      aCanvas.Free;  
    end;  
  end;  
end;



1
@Jerry,关于ReleaseDC的想法很好,但我不同意在启动时获取Handle的做法:你不应该为比必需更长的时间分配内存。此外,我不需要WM_PAINT;我只需要画布来获取字体度量,就像我在我的OP中说的那样。我将文件名分配给TEdit的文本属性,然后VCL负责绘制。 - Joris Groosman
“不同意”。在性能方面,这取决于您。我不太确定您所说的不要分配比所需更长的内存是什么意思。这可能在20年前是正确的,但在2015年,那只是一点点微不足道的内存。 - Jerry Dodge
4
如果你想准确地编辑内容,需要将字体选择为设备上下文。 - Sertac Akyuz
更简单的解决方案是直接使用 aCanvas.Font.Assign(Edit1.Font),而不是使用 GetDC/ReleaseDC。 - djsoft
1
@djsoft 看起来确实更简单,但我遇到了一个运行时错误:“画布不允许绘制”。 - Joris Groosman
显示剩余4条评论

1

由于画布只用于获取度量标准,如果您假设TEdit的度量标准与表单度量标准相同,则在MinimizeName调用中使用表单画布就足够了。这更简单,并且有效,除非有理由认为度量标准会有所不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接