我正在尝试使用this tutorial,以便我可以使用透明按钮。它适用于主背景,但它不会吸引其他孩子。如果我使用BringToFront()
,那么它就没有其他孩子的绘图。
我已经开始通过将其添加到代码来解决它:
foreach (Control child in Parent.Controls) {
if(child != this) {
InvokePaintBackground(child, pea);
InvokePaint(child, pea);
}
}
虽然我得到了我想要的一些,但是它位于错误的位置(在左边而不是在它的中间)以及在孩子的绘画事件中绘制的形状也没有出现。
我如何修改以便让所有其他孩子都充分展现透明度?
注意:我并不担心除了其他孩子之外的任何人的痛苦,因为我知道没有任何人,而且还有其他地方很难找到如何递归地获取所有孩子。
感谢C.Evenhuis回答,它现在正在运作。我的实现很简单(只有一个孩子),所以这是我的代码。对于未来的读者,请务必阅读该帖子以获得一个小范围。
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 :(得分:2)
绘画时,所有控件都假设它们的左上角位于(0,0)坐标处。这是通过在调用Graphics
之前将OnPaint
对象的视口设置为控件的坐标来实现的。
要绘制其他控件,您必须手动执行此操作:
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
,则事情会变得复杂一些 - 这些控件不会自动与其父控件一起绘制。如果你也需要支持,我建议向父控件和当前控件下面的silbing控件发送WM_PRINT
消息 - 对于兄弟控件,你可以设置PRF_CHILDREN
标志让它画画它的后代也是。
目前你正在绘制所有兄弟控件 - 包括当前控件之上的控件。当您到达当前控件时,您可能希望让循环向后移动break
。在您开始堆叠多个透明控件之前,这不会是一个真正的问题。
答案 1 :(得分:1)
这不是一个答案,但我必须做一次类似的事情。这就是我所做的:
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);
}
确实不吸引孩子,但由于某种原因,它比InvokePaintBackground
和InvokePaint
效果更好。我有很多麻烦试图吸引孩子,特别是当孩子们被一些所有者吸引到第三方控制时(我说的是非常奇怪的问题)。我想问一下是否还有其他想法。祝你好运。