Search code examples
vb.netwinformsscrollbarpanelpicturebox

Scrolling a Picturebox inside a Panel with a static label over


I have a PictureBox inside a Panel, to get automatic scrollbars when the picture is big, a Label with the photo title.
If I place the Label over the PictureBox, the "transparent" backcolor shows correctly but the Label remains at the top of the PictureBox and gets out of the screen if I scroll up-down or side-side the Panel's scrollbar!

Instead, if I put the Label outside the Panel (over the Form), the Label remains static on top of the screen, as I want, but the transparent backcolor doesn't show correctly becomes opaque.

Then if I set the Label's Parent property to the PictureBox, the transparent backcolor works fine again, but the static position of the Label is not respected anymore and joins PictureBox again!

How can I get a static Label with transparent backcolor over a PictureBox when using the scrollbars of the Panel?


Solution

  • I've tested the Overlay Form. It seems to work pretty well in your context.
    Source Code in PasteBin
    Uploaded the modified Project in OneDrive
    (I don't have FW 4.5.2, tested with FW 4.5.1 and FW 4.7.1)

    An Overlay can be an interesting feature, but, as I already said, this can also be done with TextRender.DrawText() or Graphics.DrawString(), backed by the simple math needed to offset the painted text when the picture container is scrolled.

    enter image description here


    In your Project, I've eliminated Label1 and all references to it.
    Then, I've set this class field:

    Private OverlayShown As Boolean = False
    

    In frmPho_Load()

    Overlay.Size = New Size(200, 50)
    Overlay.OverlayPosition = Overlay.Alignment.Center
    Overlay.Reposition(Me.Location, Me.Size)
    OverlayShown = True
    Overlay.Visible = False
    Overlay.Show(Me)
    

    In frmPho_Deactivate():

    If OverlayShown = False Then
        antip.Width = Me.Width
        antip.Height = Me.Height
        antip.Visible = True
    End If
    OverlayShown = False
    


    These are all the changes made to the hosting Form (Form4), the form that uses the Overlay.

    Public Class frmPho
    
        Private Overlay As New OverlayForm
    
        Private Sub frmPho_Load(sender As Object, e As EventArgs) Handles Me.Load
            Overlay.Size = New Size(200, 50)
            Overlay.OverlayPosition = Overlay.Alignment.Center
            Overlay.Reposition(Me.Location, Me.Size)
            OverlayShown = True
            Overlay.Visible = False
            Overlay.Show(Me)
            '(...)
            Overlay.Text = IO.Path.GetFileNameWithoutExtension(_ImageFileNames(_CurrentImage))
        End Sub
    
        Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
            If CheckBox1.CheckState = False Then
                Overlay.Visible = False
            Else
                OverlayShown = True
                Overlay.Visible = True
            End If
        End Sub
    
        Private Sub ShowPrevImage()
            '(...)
            OverlayShown = True
            Overlay.Text = IO.Path.GetFileNameWithoutExtension(_ImageFileNames(_CurrentImage))
        End Sub
    
        Private Sub ShowNextImage()
            '(...)
            OverlayShown = True
            Overlay.Text = IO.Path.GetFileNameWithoutExtension(_ImageFileNames(_CurrentImage))
        End Sub
    
        Private Sub frmPho_Deactivate(sender As Object, e As EventArgs) Handles Me.Deactivate
            If OverlayShown = False Then
                antip.Width = Me.Width
                antip.Height = Me.Height
                antip.Visible = True
            End If
            OverlayShown = False
        End Sub
    
        Private Sub frmPho_Move(sender As Object, e As EventArgs) Handles Me.Move
            Overlay.Reposition(Me.Location, Me.Size)
        End Sub
    
        Private Sub frmPho_Resize(sender As Object, e As EventArgs) Handles Me.Resize
            Overlay.Reposition(Me.Location, Me.Size)
        End Sub
    
        Private Sub frmPho_Shown(sender As Object, e As EventArgs) Handles Me.Shown
            ShowOverlay(300)
        End Sub
    
        Private Async Sub ShowOverlay(Delay As Integer)
            Await Task.Delay(Delay)
            Overlay.Visible = True
            Me.Focus()
        End Sub
    

    And this is the complete OverlayForm:

    All Borders/Control Boxes to None (It's a borderless Form)
    .StartPosition = Manual
    .TransparncyKey = WhiteSmoke <= Depends on the font color (mod. when needed)
    .BackColor = WhiteSmoke <= Depends on the font color (mod. when needed)
    .ShowInTaskbar = False

    Public Class OverlayForm
    
        Private _Text As String
        Private TextPosition As Point
        Private _Brush As SolidBrush = New SolidBrush(Color.White)
        Private _Flags As StringFormatFlags = StringFormatFlags.NoWrap
    
        Public Enum Alignment
            Left = 0
            Right = 1
            Center = 2
        End Enum
    
        Public Sub New()
            InitializeComponent()
        End Sub
    
        Public Overrides Property Text() As String
            Get
                Return Me._Text
            End Get
            Set(ByVal value As String)
                _Text = value
                Me.Invalidate()
            End Set
        End Property
    
        Public Property OverlayPosition As Alignment
    
        Private Sub OverlayForm_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    
            e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit
            e.Graphics.TextContrast = 12
            Dim _Size As SizeF = e.Graphics.MeasureString(Me._Text, Me.Font,
                                                          New SizeF(Me.Width, Me.Height),
                                                          New StringFormat(Me._Flags))
    
            e.Graphics.DrawString(Me._Text, Me.Font, Me._Brush, New RectangleF(TextAlign(_Size.Width), _Size))
    
        End Sub
    
        Private Sub OverlayForm_ForeColorChanged(sender As Object, e As EventArgs) Handles Me.ForeColorChanged
            Me._Brush = New SolidBrush(Me.ForeColor)
            Me.Invalidate()
        End Sub
    
        Public Sub Reposition(ParentPosition As Point, ParentSize As Size)
            Select OverlayPosition
                Case Alignment.Left
                    Me.Location = New Point(ParentPosition.X + 20, ParentPosition.Y + 40)
                Case Alignment.Right
                    Me.Location = New Point(ParentSize.Width - Me.Width - 20, ParentPosition.Y + 40)
                Case Alignment.Center
                     Me.Location = New Point(ParentPosition.X + 20 + (ParentSize.Width \ 2) - (Me.Width \ 2), ParentPosition.Y + 40)
            End Select
        End Sub
    
        Private Function TextAlign(TextWidth As Single) As PointF
            Select Case OverlayPosition
                Case Alignment.Left
                    Return New PointF(1, 1)
                Case Alignment.Right
                    Return New PointF((Me.Width - TextWidth) - 1, 1)
                Case Alignment.Center
                    If TextWidth > Me.Width Then TextWidth = Me.Width - 2
                    Return New PointF(CSng((Me.Width - TextWidth) / 4) - 1, 1)
            End Select
        End Function
    
    End Class