加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

delphi – TEdit和WM_PAINT消息处理程序的奇怪行为

发布时间:2020-12-15 04:00:41 所属栏目:大数据 来源:网络整理
导读:我正在尝试在没有焦点的情况下在TEdit控件上实现我自己的绘图(当编辑器没有完全显示其文本时在TEdit中显示省略号).所以我用这段代码明星?ed: type TEdit = class(StdCtrls.TEdit) private FEllipsis: Boolean; FCanvas: TCanvas; procedure WMPaint(var Mes
我正在尝试在没有焦点的情况下在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;

请注意,当FEllipsis和(未聚焦)消息处理程序不执行任何操作时.

现在我在表单上删除了TButton和2个TEdit控件,并添加了OnCreate形式:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit2.FEllipsis := True;
end;

我希望Edit1正常绘制,Edit2不要在编辑控件中绘制任何内容.

相反,消息处理程序被无休止地处理,Edit1也没有被绘制,整个应用程序都在窒息(占用率为25%!).我也尝试过返回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;

注意我也没有调用继承.

如何解释这种行为?谢谢.

解决方法

当窗口无效时,要求它在下一个绘制周期中使其自身有效.通常,当GetMessage发现队列为空时,会在主线程消息循环中发生.此时,WM_PAINT消息被合成并分派到窗口.

当窗口收到这些消息时,它的任务是绘制自己.这通常是通过调用BeginPaint然后调用EndPaint来完成的.对BeginPaint的调用验证窗口的客户端rect.这是您缺乏的重要信息.

现在,在你的代码中,你没有调用inherited,所以没有绘制任何东西,也没有调用BeginPaint / EndPaint.因为您没有调用BeginPaint,所以窗口仍然无效.因此,生成了源源不断的WM_PAINT消息.

相关文档可以在here找到:

The BeginPaint function automatically validates the entire client area.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读