Painting custom background of parent and parent children in C#

↘锁芯ラ 提交于 2019-12-06 00:32:52

When painting, all controls assume their top-left corner is at the (0, 0) coordinate. This is achieved by setting the viewport of the Graphics object to the coordinates of the control before OnPaint is called.

To paint the other controls, you'll have to do this manually:

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)
}

Things get a bit more complicated if the underlying control is a Panel containing child controls of its own - these are not automatically painted along with their parent. If you need to support that too I suggest sending a WM_PRINT message to the parent control and to the silbing controls below the current control - for the sibling controls you can then set the PRF_CHILDREN flag to let it paint its descendants too.

Also currently you're painting all sibling controls - including the ones above the current control. You might want to let the loop go backwards and break when you reach the current control. This won't be a real issue though until you start stacking multiple transparent controls.

This isn't an answer but I had to do something similar once. This is what I did:

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);
}

It does not draw the children behind but it worked better than InvokePaintBackground and InvokePaint for some reason. I had a lot of troubles attempting to draw the children especially when children were some owner drawn 3rd party controls (I'm talking really weird issues). I'll fav question to see if there's other ideas. Good luck.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!