在 C# 中绘制 parent 和 parent children 的自定义背景
Painting custom background of parent and parent children in C#
我正在尝试使用 this tutorial 这样我就可以拥有一个透明按钮。它适用于主背景,但不会覆盖其他 children。如果我使用 BringToFront()
,那么其他 child 的绘图就不会出现在它应该出现的位置。
我已经开始通过将此添加到代码中来绕过它:
foreach (Control child in Parent.Controls) {
if(child != this) {
InvokePaintBackground(child, pea);
InvokePaint(child, pea);
}
}
虽然我得到了 一些 我想要的东西,但它在错误的位置(在左边而不是在它应该在的中间)和绘制的形状child 的绘画事件也没有出现。
我该如何修改才能拥有所有其他 children 以及完全透明的幻觉?
注意: 除了其他 children,我不担心任何人的痛苦,因为我知道没有,还有很多其他地方可以找到如何递归地获取所有 children。
感谢 的回答,它现在可以使用了。我的实现很简单(只有一个其他child),所以这是我的代码。对于未来的读者,请务必阅读 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);
}
}
}
这不是答案,但我不得不做一次类似的事情。这就是我所做的:
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);
}
它确实 不 将 children 拉到后面,但由于某些原因它比 InvokePaintBackground
和 InvokePaint
效果更好。我在尝试绘制 children 时遇到了很多麻烦,尤其是当 children 是一些所有者绘制的第 3 方控件时(我说的是非常奇怪的问题)。我会最喜欢提问,看看是否还有其他想法。祝你好运。
绘制时,所有控件均假定其左上角位于 (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
消息 - 对于同级控件,您可以设置 PRF_CHILDREN
标志让它绘制它的后代也是。
目前您正在绘制 所有 同级控件 - 包括当前控件上方的控件。当您到达当前控件时,您可能希望让循环倒退并 break
。不过,在您开始堆叠多个透明控件之前,这不会是一个真正的问题。
我正在尝试使用 this tutorial 这样我就可以拥有一个透明按钮。它适用于主背景,但不会覆盖其他 children。如果我使用 BringToFront()
,那么其他 child 的绘图就不会出现在它应该出现的位置。
我已经开始通过将此添加到代码中来绕过它:
foreach (Control child in Parent.Controls) {
if(child != this) {
InvokePaintBackground(child, pea);
InvokePaint(child, pea);
}
}
虽然我得到了 一些 我想要的东西,但它在错误的位置(在左边而不是在它应该在的中间)和绘制的形状child 的绘画事件也没有出现。
我该如何修改才能拥有所有其他 children 以及完全透明的幻觉?
注意: 除了其他 children,我不担心任何人的痛苦,因为我知道没有,还有很多其他地方可以找到如何递归地获取所有 children。
感谢
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);
}
}
}
这不是答案,但我不得不做一次类似的事情。这就是我所做的:
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);
}
它确实 不 将 children 拉到后面,但由于某些原因它比 InvokePaintBackground
和 InvokePaint
效果更好。我在尝试绘制 children 时遇到了很多麻烦,尤其是当 children 是一些所有者绘制的第 3 方控件时(我说的是非常奇怪的问题)。我会最喜欢提问,看看是否还有其他想法。祝你好运。
绘制时,所有控件均假定其左上角位于 (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
消息 - 对于同级控件,您可以设置 PRF_CHILDREN
标志让它绘制它的后代也是。
目前您正在绘制 所有 同级控件 - 包括当前控件上方的控件。当您到达当前控件时,您可能希望让循环倒退并 break
。不过,在您开始堆叠多个透明控件之前,这不会是一个真正的问题。