【问题标题】:Find out in WM_PAINT handler which region is being invalidated by InvalidateRgn在 WM_PAINT 处理程序中找出 InvalidateRgn 使哪个区域无效
【发布时间】:2020-02-18 19:59:23
【问题描述】:

我的任务是创建带有背景刻度和指针的指标。当指针移动时,我想在之前的位置重新绘制一部分背景,然后绘制一个新的指针。

指针形状被定义为一个多边形,我从中创建了一个 GDI+ 区域。

所以我有 2 个区域对象:旧的和新的。

我每 50 毫秒调用一次以下例程:

procedure TForm1._timerTick(Sender: TObject);
var
  g: TGPGraphics;
  mx: TGPMatrix;
  hr: HRGN;
begin
  if _newRegion <> nil then _newRegion.Free();
  if _oldRegion <> nil then _oldRegion.Free();
  _newRegion := _baseRegion.Clone();
  _oldRegion := _baseRegion.Clone();
  mx := TGPMatrix.Create();
  try
    mx.RotateAt(_angle, MakePoint(250.0, 120.0));
    _oldRegion.Transform(mx);
    mx.Reset();
    Inc(_angle);
    if _angle >= 360 then _angle := 0;
    mx.RotateAt(_angle, MakePoint(250.0, 120.0));
    _newRegion.Transform(mx);
  finally
    mx.Free();
  end;
  g := TGPGraphics.Create(Canvas.Handle);
  try
    hr := _oldRegion.GetHRGN(g);
    try
      InvalidateRgn(Handle, hr, False); //Restore background
    finally
      DeleteObject(hr);
    end;
    hr := _newRegion.GetHRGN(g);
    try
      InvalidateRgn(Handle, hr, False); //Draw new region
    finally
      DeleteObject(hr);
    end;
  finally
    g.Free();
  end;
end;

如您所见,我没有比调用InvalidateRgn 两次更好的主意:一次用于后台恢复,一次用于指针绘制。

WM_PAINT 处理程序如下所示:

procedure TForm1.Paint();
var
  g: TGPGraphics;
  mx: TGPMatrix;
  brs: TGPSolidBrush;
begin
  inherited;
  g := TGPGraphics.Create(Canvas.Handle);
  mx := TGPMatrix.Create();
  brs := TGPSolidBrush.Create(MakeColor(255, 255, 0));
  try
    if _fullDraw then begin
      _fullDraw := False;
    end
    else begin
      g.IntersectClip(_oldRegion);
    end;
    g.DrawImage(_img, 0, 0);
    if _newRegion <> nil then begin
      g.ResetClip();
      g.FillRegion(brs, _newRegion);
    end;
  finally
    brs.Free();
    mx.Free();
    g.Free();
  end;
end;

它总是做两个操作:恢复背景和绘制指针。

如果我执行两次InvalidateRgn,那么 Paint 也会被调用两次,导致四个操作而不是两个。

有什么方法可以在 Windows 级别的 Paint 方法中找出哪个区域正在失效?

【问题讨论】:

    标签: windows gdi+ delphi-10-seattle invalidation


    【解决方案1】:

    在您的 WM_PAINT 处理程序中,您可以使用:

    无论哪种方式都会给你一个更新/剪辑区域,HDC 需要在其中绘制。您在该区域之外所做的任何绘图都将被丢弃。因此,您可以将其用作优化,以免浪费精力绘制任何将被丢弃的东西。

    如果我执行两次InvalidateRgn,那么 Paint 也将被调用两次,导致四个操作而不是两个。

    不正确。窗口失效被缓存和合并,直到窗口被实际绘制和验证。您可以根据需要多次调用InvalidateRect()/InvalidateRgn(),并且在您将控制权返回到消息循环之前不会绘制窗口,因此可以生成WM_PAINT消息(除非您通过调用强制绘制UpdateWindow()RedrawWindow())。 WM_PAINT 是一个低优先级的消息,只有当窗口有一个非空的Update Region 并且没有其他高优先级的消息挂起时,它才会由消息队列生成。在处理WM_PAINT 之前,不会验证窗口(除非您通过调用ValidateRect()/ValidateRgn() 来强制它)。有关详细信息,请参阅 MSDN 上的Invalidating and Validating the Update Region

    【讨论】:

      猜你喜欢
      • 2015-02-14
      • 2011-09-26
      • 1970-01-01
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-10
      • 2011-11-03
      相关资源
      最近更新 更多