在C#中绘制父级和父级子级的自定义背景

我正在尝试使用本教程,以便我可以使用透明按钮。 它适用于主背景,但它不会覆盖其他孩子。 如果我使用BringToFront() ,那么它就没有其他孩子的绘图。

我已经开始通过将其添加到代码来解决它:

 foreach (Control child in Parent.Controls) { if(child != this) { InvokePaintBackground(child, pea); InvokePaint(child, pea); } } 

虽然我得到了一些我想要的东西,但是它位于错误的位置(在左边而不是在它的中间)并且在孩子的绘画事件中绘制的形状也没有显示出来。

我如何修改以便让所有其他孩子都充分发挥透明度的幻觉?

注意:我并不担心除了其他孩子之外的任何人的痛苦,因为我知道没有任何人,而且还有其他地方很难找到如何递归地让所有的孩子。


感谢C.Evenhuis回答,它现在正在工作。 我的实现很简单(只有一个孩子),所以这是我的代码。 对于未来的读者,请务必阅读该post,但要获得一个小范围。

 using (PaintEventArgs pea = new PaintEventArgs(e.Graphics, rect)) { pea.Graphics.SetClip(rect); InvokePaintBackground(Parent, pea); InvokePaint(Parent, pea); foreach (Control child in Parent.Controls) { if (child != this) { pea.Graphics.ResetTransform(); pea.Graphics.TranslateTransform(child.Left - Left, child.Top - Top); InvokePaintBackground(child, pea); InvokePaint(child, pea); } } } 

绘画时,所有控件都假设它们的左上角位于(0,0)坐标处。 这是通过在调用OnPaint之前将Graphics对象的视口设置为控件的坐标来实现的。

要绘制其他控件,您必须手动执行此操作:

 if (child != this) { int offsetX = control.Left - Left; int offsetY = control.Top - Top; // Set the viewport to that of the control pevent.Graphics.TranslateTransform(offsetX, offsetY); // Translate the clip rectangle to the new coordinate base Rectangle clip = pevent.ClipRectangle; clip.Offset(-offsetX, -offsetY); // Ugly self-modifying struct PaintEventArgs clippedArgs = new PaintEventArgs(pevent.Graphics, clip); InvokePaintBackground(control, clippedArgs); InvokePaint(control, clippedArgs); pevent.Graphics.TranslateTransform(-offsetX, -offsetY) } 

如果底层控件是包含其自身子控件的Panel ,则事情会变得复杂一些 – 这些控件不会自动与其父控件一起绘制。 如果你也需要支持,我建议将WM_PRINT消息发送到父控件和当前控件下面的silbing控件 – 对于兄弟控件,你可以设置PRF_CHILDREN标志让它也画出它的后代。

目前你正在绘制所有兄弟控件 – 包括当前控件之上的控件。 当你到达当前控件时,你可能想让循环向后移动并break 。 在您开始堆叠多个透明控件之前,这不会是一个真正的问题。

这不是答案,但我必须做一次类似的事情。 这就是我做的:

 this.SetStyle( ControlStyles.ResizeRedraw | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true); this.BackColor = Color.Transparent; protected override void OnPaint(PaintEventArgs e) { // TODO: Draw the button here base.OnPaint(e); } 

它不会吸引孩子,但由于某种原因,它比InvokePaintBackgroundInvokePaint更好。 我有很多麻烦试图吸引孩子,特别是当孩子们被一些所有者吸引到第三方控制时(我说的是非常奇怪的问题)。 我会倾向于询问是否还有其他想法。 祝好运。