我无法摆脱我的 ClipRectangle,我想哭

发布于 2024-11-03 12:20:51 字数 628 浏览 0 评论 0原文

当重写自定义控件的 OnPaint 方法时,我提供了 PaintEventArgs,其中包含一个 Graphics 对象和一个 ClipRectangle。 ClipRectangle 对于我的口味来说太小了,所以我想要么将其扩展 100 像素,要么完全忽略它。

无论我做什么,我似乎都无法摆脱 ClipRectangle。到目前为止,我已经尝试过:

e.ClipRectangle.Inflate(100, 0);
e.Graphics.ResetClip();
e.Graphics.SetClip(new Rectangle(x, y, w, h));

父控件正在调用 Invalidate(true) (以强制所有子控件的子控件失效)。

我还做了一些谷歌搜索并查看了鲍勃·鲍威尔的网站,但找不到海芬。

ResetClip 将 Graphics 对象的剪切区域重置为无限大的 Rectangle,但 Graphics 对象愉快地继续使用提供的 ClipRectangle。

帮助。

When overriding the OnPaint method of a custom control I'm supplied with a PaintEventArgs, which contains a Graphics object and a ClipRectangle. The ClipRectangle is too small for my tastes and so I want to either extend it by say, 100 pixels, or ignore it completely.

No matter what I do, I can't seem to break out of the ClipRectangle. So far I've tried:

e.ClipRectangle.Inflate(100, 0);
e.Graphics.ResetClip();
e.Graphics.SetClip(new Rectangle(x, y, w, h));

The parent control is calling Invalidate(true) (to force an invalidation of all the childs' child controls).

I've also done some googling and looked on bob powell's site but can't find nuffin.

ResetClip resets the clipping region for the Graphics object to an infinitely large Rectangle, but the Graphics object cheerfully continues to use the provided ClipRectangle.

Help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

大姐,你呐 2024-11-10 12:20:51

回顾:听起来您有一个具有自定义绘制方法的子控件。您想要在大于控件本身边界的区域中绘制控件。例如,如果您将控件放置在 (10, 10, 100, 100) 处,您希望在 (0, 10, 110, 100) 处绘制区域。

您不能完全这样做,传递给 Paint 方法的控件的 HDC 用于该控件的本机窗口句柄。它被操作系统剪裁,并且据我所知,无法使用为绘制方法提供的 HDC 在其外部进行绘制。

你可以做什么:一种选择是覆盖父窗口的create方法并删除窗口样式WS_CLIPCHILDREN(0x02000000),然后在父窗口的paint方法中绘制子窗口。

另一种选择是仅扩展子窗口的区域,使其包含您要绘制的区域。如果您还重写控件的 OnPaintBackground 方法,则可以防止背景绘制清除父级的渲染。但这是有问题的,因为父级会剪切子级的区域而不刷新它。因此,您仍然需要删除父级的 WS_CLIPCHILDREN 才能使其正常工作。

我确信还有其他可能性,所有这些可能性基本上都是相同的结果,你不能这样做。

Recap: It sounds like you have a child control with a custom paint method. You want to paint the control in an area that is larger than the control's bounds itself. For instance if you place your control at (10, 10, 100, 100) you want to draw the area at (0, 10, 110, 100).

You can't exactly do that, the control's HDC that is passed to paint method is for that control's native window handle. It is clipped by the OS and AFAIK there is no way to draw outside of it with the HDC given to the paint method.

What you can do: One option is to override the parent window's create method and remove the window style WS_CLIPCHILDREN (0x02000000), then draw the child in the parent's paint method.

Another option is to just expand the area of the child window so that it encompasses the area you want to draw. If you also override the OnPaintBackground method of your control you can prevent the background paint from clearing the parent's rendering. This is problematic though since the parent will clip the area of the child and not refresh it. Thus you still need to remove the parent's WS_CLIPCHILDREN for it to work.

I'm sure there are other possibilities all of which are basically the same result, you can't do that.

瞳孔里扚悲伤 2024-11-10 12:20:51

Rectangle 是一个结构体,而不是一个类 - 它作为值传递,因此调用 e.ClipRectangle.Inflate(100, 0); 即使在理论上也无济于事。

接下来您需要知道的是,e.Graphics 与硬件设备上下文相关,因此 Windows 不会让您扩展绘画区域。解决方案是获取父窗口的设备上下文,然后在您想要的任何地方进行绘制。操作方法如下:

[DllImport("User32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("User32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

IntPtr dcPtr = GetDC(this.ParentForm.Handle);
Graphics g = Graphics.FromHdc(dcPtr);

// your code here

// don't forget to release it
g.Dispose();
ReleaseDC(this.ParentForm.Handle, dcPtr);

Rectangle is a struct, not a class - it's passed as value so calling e.ClipRectangle.Inflate(100, 0); can't help even theoretically.

Next thing you have to know is that e.Graphics is related to hardware device context, so Windows won't let you expand painting area. Solution is to get device context of the parent window and then paint wherever you want to. This is how to do it:

[DllImport("User32.dll")]
static extern IntPtr GetDC(IntPtr hwnd);
[DllImport("User32.dll")]
static extern bool ReleaseDC(IntPtr hWnd, IntPtr hDC);

IntPtr dcPtr = GetDC(this.ParentForm.Handle);
Graphics g = Graphics.FromHdc(dcPtr);

// your code here

// don't forget to release it
g.Dispose();
ReleaseDC(this.ParentForm.Handle, dcPtr);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文