Delphi SelectClipRGN 隐藏绘制的位图

Delphi SelectClipRGN Hides Drawn Bitmap

我正在绘制带边框的自定义背景(派生自 TGraphicControl)。在 DrawBorderRect 函数中绘制边框后,我 return "client" 区域,并希望将以后的绘制限制在这个新区域。如果我不使用 ClipRgn,一切正常。

工作代码:

var
  R : TRect;

begin;
  R := GetClientRect;     //(R -> 0, 0, 300, 200)
  R := DrawBorderRect(R); //(R -> 20, 20, 280, 180)
  Canvas.StretchDraw(R, FBitmap); //FBitmap is a 3 pixel x 3 pixel square
end;

上面的代码给了我这个:

但是,我想使用 ClipRgn,并且尝试了以下方法。这次没有显示该模式(但是,如果我在该区域上单击鼠标按钮,那么该模式就会显示。所以它正在工作,但由于某种原因被覆盖了?)。

有问题的代码:

var
  R : TRect;
  ClientRegion: HRGN;

begin;
  R := GetClientRect;     //(R -> 0, 0, 300, 200)
  R := DrawBorderRect(R); //(R -> 20, 20, 280, 180)

  ClientRegion := CreateRectRgn(R.Left, R.top, R.Right, R.Bottom);
  SelectClipRgn(Canvas.Handle, ClientRegion);
  try
    Canvas.StretchDraw(R, FBitmap); //FBitmap is a 3 pixel x 3 pixel square
  finally
    SelectClipRgn(Canvas.Handle, HRGN(nil));
    DeleteObject(ClientRegion);
  end;
end;

我明白了(除非我单击鼠标左键,在这种情况下我会看到上面的内容)

关于正在发生的事情以及我遗漏了什么的任何见解?

SelectClipRgn 假定设备坐标。

TGraphicControl 后代为其父 window 检索了设备上下文。移动视口原点以能够将客户端原点设置为 (0, 0),但它们是逻辑坐标。

简而言之,您需要偏移您的区域:

...
ClientRegion := CreateRectRgn(R.Left, R.top, R.Right, R.Bottom);
OffsetRgn(ClientRegion, Left, Top);           // <--
SelectClipRgn(Canvas.Handle, ClientRegion);
...