ElektroStudios
ElektroStudios

Reputation: 20464

Visual problems with the form background image

This is the design of the app:

enter image description here

And this is what happens when i use the scrollbar up or down:

enter image description here

the checkboxes are inside a panel, the panel is transparent (obvious) only the form uses the background image.

why happens that distortion and how I can resolve the problem?

PS: If you need more information or all the form or something just tell me.

Upvotes: 0

Views: 4963

Answers (3)

seba123neo
seba123neo

Reputation: 4748

the solution that worked, is to create a custom panel (a class that inherits from the control panel), and in making the necessary code to lock the redraw, with the api call LockWindowUpdate and OptimizedDoubleBuffer property that is used to prevent flickering the scrolling.

Public Class MyPanel
Inherits Panel
Public Sub New()
    Me.AutoScroll = True
    Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
    Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
End Sub
Private mImage As Image
Public Property Image() As Image
    Get
        Return mImage
    End Get
    Set(ByVal value As Image)
        mImage = value
        Invalidate()
    End Set
End Property
Protected Overrides Sub OnScroll(ByVal se As ScrollEventArgs)
    If se.Type = ScrollEventType.First Then
        LockWindowUpdate(Me.Handle)
    ElseIf se.Type = ScrollEventType.ThumbTrack OrElse se.Type = ScrollEventType.ThumbPosition Then
        LockWindowUpdate(IntPtr.Zero)
        Me.Refresh()
        LockWindowUpdate(Me.Handle)
    Else
        LockWindowUpdate(IntPtr.Zero)
        Me.Invalidate()
    End If
    MyBase.OnScroll(se)
End Sub
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    Console.WriteLine(e.ClipRectangle.ToString())
    Using br As New SolidBrush(Me.BackColor)
        e.Graphics.FillRectangle(br, Me.ClientRectangle)
    End Using
    If mImage IsNot Nothing Then
        e.Graphics.DrawImage(mImage, 0, 0)
    End If
    MyBase.OnPaint(e)
End Sub
<DllImport("user32.dll")> _
Private Shared Function LockWindowUpdate(ByVal hWnd As IntPtr) As Boolean
End Function
End Class

is like a common panel of Visual Basic, it inherits all the properties of the panel, unless you program in to do what you want. Note that you have to appear like a control in the control bar, called "MyPanel" then rename it to the one you want. to appear as you control, you have to build the solution.

you put on the form and voila, you use that.

Upvotes: 2

Stan
Stan

Reputation: 26511

At first glance it seems that this is impossible without some low-level tweaking. But I've found a "somewhat" workaround.

  1. Create OnScroll event on your Panel
  2. Re-draw it using some background color (like black) and then set it to transparent again

This is my C# code inside my panel scroll event handler.

private void panel1_Scroll(object sender, ScrollEventArgs e)
{
    panel1.BackColor = System.Drawing.Color.Empty;
    panel1.BackColor = System.Drawing.Color.Transparent;
}

EDIT

Since this event will only work on your scroll bars you want to implement same thing on mouse wheel scroll. In VB it is very simple, just add another function.

This is full code

Private Sub Panel1_Scroll(sender As Object, e As ScrollEventArgs) Handles Panel1.Scroll
    Panel1.BackColor = System.Drawing.Color.Empty
    Panel1.BackColor = System.Drawing.Color.Transparent
End Sub

Private Sub Panel1_MouseScroll(sender As Object, e As MouseEventArgs) Handles Panel1.MouseWheel
    Panel1.BackColor = System.Drawing.Color.Empty
    Panel1.BackColor = System.Drawing.Color.Transparent
End Sub

That's it. Now it works the same on scroll bars and mouse wheel.

Upvotes: 2

Hans Passant
Hans Passant

Reputation: 941635

The ScrollableControl class, the parent of Panel, doesn't override the OnPaintbackground() method like it should to draw the image correctly. The combination with the "Show window contents while dragging" option that's turned on for all modern Windows versions makes a mess of it.

Add a new class to your project and paste the code shown below. Compile. Drag the new control from the top of the toolbox onto your form, replacing the old one.

using System;
using System.Windows.Forms;

class MyPanel : Panel {
    public MyPanel() {
        this.DoubleBuffered = true;
    }
    protected override void OnPaintBackground(PaintEventArgs e) {
        if (this.BackgroundImage != null) {
            e.Graphics.TranslateTransform(this.AutoScrollPosition.X, this.AutoScrollPosition.Y);
            e.Graphics.Clear(this.BackColor);
            e.Graphics.DrawImage(this.BackgroundImage, 0, 0);
        }
        else base.OnPaintBackground(e);
    }
}

Upvotes: 1

Related Questions