zig*_*zig 8 delphi vcl editcontrol
我试图在TEdit没有焦点的控件上实现我自己的绘图(TEdit当编辑器没有完全显示其文本时显示省略号).所以我用这段代码加注了ed:
type
TEdit = class(StdCtrls.TEdit)
private
FEllipsis: Boolean;
FCanvas: TCanvas;
procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
end;
constructor TEdit.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
FEllipsis := False;
FCanvas := TControlCanvas.Create;
TControlCanvas(FCanvas).Control := Self;
end;
destructor TEdit.Destroy;
begin
FCanvas.Free;
inherited;
end;
procedure TEdit.WMPaint(var Message: TWMPaint);
begin
if FEllipsis and (not Focused) then
begin
// Message.Result := 0;
// TODO...
end
else
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
请注意,当FEllipsis and (not Focused)消息处理程序什么都不做时.
现在我在表单上删除了一个TButton和两个TEdit控件,并添加了表单OnCreate:
procedure TForm1.FormCreate(Sender: TObject);
begin
Edit2.FEllipsis := True;
end;
Run Code Online (Sandbox Code Playgroud)
我期望Edit1正常绘制,而Edit2不是在编辑控件中绘制任何内容.
相反,消息处理程序被无休止地处理,Edit1也没有被绘制,并且整个应用程序都在窒息(具有25%的CPU使用率!).我也试过回来Message.Result := 0- 效果一样.
现在,对于"奇怪"部分:当我获得画布句柄时BeginPaint,一切都按预期工作.
procedure TEdit.WMPaint(var Message: TWMPaint);
var
PS: TPaintStruct;
begin
if FEllipsis and (not Focused) then
begin
if Message.DC = 0 then
FCanvas.Handle := BeginPaint(Handle, PS)
else
FCanvas.Handle := Message.DC;
try
// paint on FCanvas...
finally
FCanvas.Handle := 0;
if Message.DC = 0 then EndPaint(Handle, PS);
end;
end
else
inherited;
end;
Run Code Online (Sandbox Code Playgroud)
注意我也没有打过电话inherited.
如何解释这种行为?谢谢.
Dav*_*nan 13
当窗口无效时,要求它在下一个绘制周期中使其自身有效.通常,当GetMessage发现队列为空时,会在主线程消息循环中发生.此时,WM_PAINT消息被合成并分派到窗口.
当窗口收到这些消息时,它的任务是绘制自己.这通常是通过调用BeginPaint然后调用来完成的EndPaint.调用BeginPaint验证窗口的客户端rect.这是您缺乏的关键信息.
现在,在你的代码中,你没有调用inherited,因此没有绘制任何内容,也没有调用BeginPaint/ EndPaint.因为您没有打电话BeginPaint,窗口仍然无效.因此产生了无穷无尽的WM_PAINT消息流.
相关文档可在此处找到:
该BeginPaint的功能会自动验证整个客户区.