1

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?

Jimi
  • 29,621
  • 8
  • 43
  • 61
arc95
  • 97
  • 1
  • 8
  • Please add your existing code, so we can figure out what's going on? – Sunil Jan 25 '18 at 08:25
  • @Sunil Create 1 PictureBox, 1 Panel, 1 Label Transparent .backcolor to Label- Autoscroll at Panel - Load picture and autosize. PictureBox inside Panel. Label over Picturebox. add: `Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load` `Label1.Parent = PictureBox1` `End Sub` Use Scrollbar, the label gets out! Now move the Label outside of Picturebox change all code `Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load` `Label1.Left = 45` `End Sub` Set (programatically) the position of the Label over Picture. Now move the scrollbars – arc95 Jan 25 '18 at 22:43
  • @Sunil you see? if you set the Label position programatically, Label loose the transparent backcolor but if you .parent the PictureBox the static position gets loose! i also try adding timer to repositioning each second or reparenting to Form and later to PictureBox fast but that don't work! How can i get transparent & static label? – arc95 Jan 25 '18 at 22:50
  • You could do this with an overlay, using a transparent twin-form. Painting a control over another, will always cause flickering while scrolling. An overlay is better. If you're interested, ping back. – Jimi Jan 26 '18 at 16:48
  • @Jimi I cant defocus the Form with other Form because I get Label over the PictureBox to protect of third snapshotsoftware, at this post they offer a solution: https://stackoverflow.com/questions/9387267/transparent-control-over-picturebox but i cant reach to adapt to my vb.net project.. – arc95 Jan 26 '18 at 20:42
  • I don't know what you mean with *protect of third snapshotsoftware*. Try to rephrase that. -- The overlay doesn't capture the focus; it's an invisible, borderless control. -- You can do this with a parented Label (what the code in your link does). But painting a Label over a Picturebox causes flickering when the image is scrolled. Maybe I can show you how both work, so that you can test the differences. (BTW, TextRender.DrawText() or Graphics.DrawString() can do the job, depending on the context). – Jimi Jan 27 '18 at 03:29
  • @Jimi The main purpose is a picture viewer, you can use the mousewheel to zoom, left/right to preview/next, slideshow, protective: if screen resolution is higher than 1024 (width) will show just resized version of the image low quality. If you try the most common (prtscr key) to copy the image, the software automatically clear the clipboard. if you open a third party snapshot software a label appear due th defocus form.. i understand wrongly: you suggest use of secondary form with transparent backcolor, that results on anticopy label. try https://1drv.ms/f/s!AlqVaIM2GTrSlTmW9VKyqG1KzOoE – arc95 Jan 27 '18 at 05:12
  • @Jimi Notes for you at: `Private Sub ShowPrevImage() & Private Sub ShowNextImage()` fast way to try what you say... – arc95 Jan 27 '18 at 05:21

1 Answers1

1

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
Jimi
  • 29,621
  • 8
  • 43
  • 61
  • If you mark 2 times checkbox1 the "unauthorized layer" becomes visible... – arc95 Jan 28 '18 at 03:11
  • In `CheckBox1_CheckedChanged()` event, in `Else` part, just notify that the Overlay is Shown: `(...) Else OverlayShown = True Overlay.Visible = True`. Do the same thing each time you have to show the Overlay. I'll add it to the _Changes_ part ot the code. – Jimi Jan 28 '18 at 08:41