我无法突破我的ClipRectangle,我想哭

Mat*_*sen 12 c# system.drawing custom-controls winforms

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

无论我做什么,我似乎都无法突破ClipRectangle.到目前为止,我已经尝试过:

e.ClipRectangle.Inflate(100, 0);
e.Graphics.ResetClip();
e.Graphics.SetClip(new Rectangle(x, y, w, h));
Run Code Online (Sandbox Code Playgroud)

父控件调用Invalidate(true)(强制所有子控件的子控件失效).

我也做了一些谷歌搜索,看着鲍勃鲍威尔的网站,但找不到核武器.

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

救命.

csh*_*net 5

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

你不能完全这样做,传递给paint方法的控件的HDC是针对该控件的本机窗口句柄.它被操作系统和AFAIK截断,没有办法在绘制方法的HDC之外绘制它.

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

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

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


rot*_*man 5

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);
Run Code Online (Sandbox Code Playgroud)