How to close a form on mouseLeave

I want to create a custom picturebox in which picture is zoomed in a dedicated form on mouse hover.
Everything works fine except the fact that the user must clic out the zoomed image to close it altough i want to close it on mouse leave?

Here’s my code:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code>Public Class CtrlNoticePictureBox
Inherits PictureBox
Private frmPicExtended As New Form
Public Sub New()
AddHandler Me.MouseEnter, New System.EventHandler(AddressOf Me.PictureBox_MouseEnter)
AddHandler Me.MouseLeave, New System.EventHandler(AddressOf Me.PictureBox_MouseLeave)
End Sub
Private Sub PictureBox_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
Dim screenCurrent As Screen = Screen.FromControl(Me)
Dim workingArea As Rectangle = screenCurrent.WorkingArea
Dim locationForm As Point = Me.TopLevelControl.Location
frmPicExtended = New Form With {
.ShowInTaskbar = False,
.MaximizeBox = False,
.ControlBox = False,
.Location = New Point(Me.Width + locationForm.X, Me.Height + locationForm.Y),
.StartPosition = FormStartPosition.Manual,
.FormBorderStyle = FormBorderStyle.None
}
Dim picBoxExtended = New PictureBox With {
.Name = "pictureBox",
.Image = Me.Image,
.SizeMode = PictureBoxSizeMode.Zoom,
.Dock = DockStyle.Fill
}
frmPicExtended.Controls.Add(picBoxExtended)
frmPicExtended.BringToFront()
frmPicExtended.Show()
End Sub
Private Sub PictureBox_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)
Dim rectPicArea As New Rectangle With {.Location = Me.PointToScreen(Point.Empty), .Size = Me.Size}
If IsNothing(frmPicExtended) = False Then
If Not rectPicArea.Contains(Cursor.Position) Then
frmPicExtended.Dispose()
End If
End If
End Sub
Function PointToCurrentScreen(ByVal self As Control, ByVal location As Point) As Point
Dim screenBounds = Screen.FromControl(self).Bounds
Dim globalCoordinates = self.PointToScreen(location)
Return New Point(globalCoordinates.X - screenBounds.X, globalCoordinates.Y - screenBounds.Y)
End Function
End Class
</code>
<code>Public Class CtrlNoticePictureBox Inherits PictureBox Private frmPicExtended As New Form Public Sub New() AddHandler Me.MouseEnter, New System.EventHandler(AddressOf Me.PictureBox_MouseEnter) AddHandler Me.MouseLeave, New System.EventHandler(AddressOf Me.PictureBox_MouseLeave) End Sub Private Sub PictureBox_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Dim screenCurrent As Screen = Screen.FromControl(Me) Dim workingArea As Rectangle = screenCurrent.WorkingArea Dim locationForm As Point = Me.TopLevelControl.Location frmPicExtended = New Form With { .ShowInTaskbar = False, .MaximizeBox = False, .ControlBox = False, .Location = New Point(Me.Width + locationForm.X, Me.Height + locationForm.Y), .StartPosition = FormStartPosition.Manual, .FormBorderStyle = FormBorderStyle.None } Dim picBoxExtended = New PictureBox With { .Name = "pictureBox", .Image = Me.Image, .SizeMode = PictureBoxSizeMode.Zoom, .Dock = DockStyle.Fill } frmPicExtended.Controls.Add(picBoxExtended) frmPicExtended.BringToFront() frmPicExtended.Show() End Sub Private Sub PictureBox_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Dim rectPicArea As New Rectangle With {.Location = Me.PointToScreen(Point.Empty), .Size = Me.Size} If IsNothing(frmPicExtended) = False Then If Not rectPicArea.Contains(Cursor.Position) Then frmPicExtended.Dispose() End If End If End Sub Function PointToCurrentScreen(ByVal self As Control, ByVal location As Point) As Point Dim screenBounds = Screen.FromControl(self).Bounds Dim globalCoordinates = self.PointToScreen(location) Return New Point(globalCoordinates.X - screenBounds.X, globalCoordinates.Y - screenBounds.Y) End Function End Class </code>
Public Class CtrlNoticePictureBox
    Inherits PictureBox
    Private frmPicExtended As New Form
    Public Sub New()
        AddHandler Me.MouseEnter, New System.EventHandler(AddressOf Me.PictureBox_MouseEnter)
        AddHandler Me.MouseLeave, New System.EventHandler(AddressOf Me.PictureBox_MouseLeave)
    End Sub
    Private Sub PictureBox_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim screenCurrent As Screen = Screen.FromControl(Me)
        Dim workingArea As Rectangle = screenCurrent.WorkingArea
        Dim locationForm As Point = Me.TopLevelControl.Location

        frmPicExtended = New Form With {
            .ShowInTaskbar = False,
            .MaximizeBox = False,
            .ControlBox = False,
            .Location = New Point(Me.Width + locationForm.X, Me.Height + locationForm.Y),
            .StartPosition = FormStartPosition.Manual,
            .FormBorderStyle = FormBorderStyle.None
        }
        Dim picBoxExtended = New PictureBox With {
            .Name = "pictureBox",
            .Image = Me.Image,
            .SizeMode = PictureBoxSizeMode.Zoom,
            .Dock = DockStyle.Fill
        }
        frmPicExtended.Controls.Add(picBoxExtended)
        frmPicExtended.BringToFront()
        frmPicExtended.Show()
    End Sub
    Private Sub PictureBox_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim rectPicArea As New Rectangle With {.Location = Me.PointToScreen(Point.Empty), .Size = Me.Size}
        If IsNothing(frmPicExtended) = False Then
            If Not rectPicArea.Contains(Cursor.Position) Then
                frmPicExtended.Dispose()
            End If
        End If
    End Sub
    Function PointToCurrentScreen(ByVal self As Control, ByVal location As Point) As Point
        Dim screenBounds = Screen.FromControl(self).Bounds
        Dim globalCoordinates = self.PointToScreen(location)
        Return New Point(globalCoordinates.X - screenBounds.X, globalCoordinates.Y - screenBounds.Y)
    End Function
End Class

Here is the result:

5

If you look closely at the gif image, when the mouse moves to the greenish container, it actually leaves the internal picBoxExtended, not the CtrlNoticePictureBox instance. The covered area of the main PictureBox – by the modeless Form – does not receive the mouse inputs unless that Form and its children are transparent to the mouse inputs. As a result, the MouseLeave event does not fire and the zoom Form remains. You also need to implement the MouseLeave event of the internal PictureBox to hide the Form.

Here’s a working example with some additions and modifications.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<code><DesignerCategory("Code")>
Public Class CtrlNoticePictureBox
Inherits PictureBox
Public Enum StartPosition
Relative
Center
Cursor
End Enum
Private FrmZoom As Form
Private PicZoom As PictureBox
<DefaultValue(StartPosition.Center)>
Public Property ZoomFormStartPosition As StartPosition = StartPosition.Center
<DefaultValue(True)>
Public Property KeepZoomFormWithinScreen As Boolean = True
Protected Overrides Sub OnMouseEnter(e As EventArgs)
MyBase.OnMouseEnter(e)
If Image Is Nothing Then Return
If FrmZoom Is Nothing Then CreateZoomForm()
If FrmZoom.Visible Then Return
Dim loc As Point
Select Case ZoomFormStartPosition
Case StartPosition.Relative
loc = PointToScreen(Point.Empty)
Case StartPosition.Center
loc = PointToScreen(Point.Empty)
loc.X += (Width - FrmZoom.Width) 2
loc.Y += (Height - FrmZoom.Height) 2
Case Else
loc = Cursor.Position
End Select
If KeepZoomFormWithinScreen Then
Dim sc = Screen.FromControl(Me).Bounds ' or .WorkingArea
If loc.X + FrmZoom.Width > sc.Width Then
loc.X = sc.Right - FrmZoom.Width
End If
If loc.Y + FrmZoom.Height > sc.Height Then
loc.Y = sc.Bottom - FrmZoom.Height
End If
loc.X = Math.Max(0, loc.X)
loc.Y = Math.Max(0, loc.Y)
End If
FrmZoom.Location = loc
PicZoom.Image = Image
FrmZoom.Show()
End Sub
Protected Overrides Sub OnMouseLeave(e As EventArgs)
MyBase.OnMouseLeave(e)
If Not ClientRectangle.Contains(PointToClient(Cursor.Position)) Then
FrmZoom.Hide()
End If
End Sub
Protected Overrides Sub Dispose(disposing As Boolean)
If disposing Then
FrmZoom?.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Private Sub CreateZoomForm()
PicZoom = New PictureBox With {
.SizeMode = PictureBoxSizeMode.Zoom,
.Dock = DockStyle.Fill,
}
FrmZoom = New Form With {
.FormBorderStyle = FormBorderStyle.None,
.ControlBox = False,
.ShowInTaskbar = False,
.TopMost = True,
.StartPosition = FormStartPosition.Manual,
.Size = New Size(Width * 2, Height * 2)
}
FrmZoom.Controls.Add(PicZoom)
AddHandler FrmZoom.Disposed, Sub(s, e) PicZoom.Dispose()
AddHandler PicZoom.MouseLeave, Sub(s, e) OnMouseLeave(EventArgs.Empty)
End Sub
End Class
</code>
<code><DesignerCategory("Code")> Public Class CtrlNoticePictureBox Inherits PictureBox Public Enum StartPosition Relative Center Cursor End Enum Private FrmZoom As Form Private PicZoom As PictureBox <DefaultValue(StartPosition.Center)> Public Property ZoomFormStartPosition As StartPosition = StartPosition.Center <DefaultValue(True)> Public Property KeepZoomFormWithinScreen As Boolean = True Protected Overrides Sub OnMouseEnter(e As EventArgs) MyBase.OnMouseEnter(e) If Image Is Nothing Then Return If FrmZoom Is Nothing Then CreateZoomForm() If FrmZoom.Visible Then Return Dim loc As Point Select Case ZoomFormStartPosition Case StartPosition.Relative loc = PointToScreen(Point.Empty) Case StartPosition.Center loc = PointToScreen(Point.Empty) loc.X += (Width - FrmZoom.Width) 2 loc.Y += (Height - FrmZoom.Height) 2 Case Else loc = Cursor.Position End Select If KeepZoomFormWithinScreen Then Dim sc = Screen.FromControl(Me).Bounds ' or .WorkingArea If loc.X + FrmZoom.Width > sc.Width Then loc.X = sc.Right - FrmZoom.Width End If If loc.Y + FrmZoom.Height > sc.Height Then loc.Y = sc.Bottom - FrmZoom.Height End If loc.X = Math.Max(0, loc.X) loc.Y = Math.Max(0, loc.Y) End If FrmZoom.Location = loc PicZoom.Image = Image FrmZoom.Show() End Sub Protected Overrides Sub OnMouseLeave(e As EventArgs) MyBase.OnMouseLeave(e) If Not ClientRectangle.Contains(PointToClient(Cursor.Position)) Then FrmZoom.Hide() End If End Sub Protected Overrides Sub Dispose(disposing As Boolean) If disposing Then FrmZoom?.Dispose() End If MyBase.Dispose(disposing) End Sub Private Sub CreateZoomForm() PicZoom = New PictureBox With { .SizeMode = PictureBoxSizeMode.Zoom, .Dock = DockStyle.Fill, } FrmZoom = New Form With { .FormBorderStyle = FormBorderStyle.None, .ControlBox = False, .ShowInTaskbar = False, .TopMost = True, .StartPosition = FormStartPosition.Manual, .Size = New Size(Width * 2, Height * 2) } FrmZoom.Controls.Add(PicZoom) AddHandler FrmZoom.Disposed, Sub(s, e) PicZoom.Dispose() AddHandler PicZoom.MouseLeave, Sub(s, e) OnMouseLeave(EventArgs.Empty) End Sub End Class </code>
<DesignerCategory("Code")>
Public Class CtrlNoticePictureBox
    Inherits PictureBox

    Public Enum StartPosition
        Relative
        Center
        Cursor
    End Enum

    Private FrmZoom As Form
    Private PicZoom As PictureBox

    <DefaultValue(StartPosition.Center)>
    Public Property ZoomFormStartPosition As StartPosition = StartPosition.Center

    <DefaultValue(True)>
    Public Property KeepZoomFormWithinScreen As Boolean = True

    Protected Overrides Sub OnMouseEnter(e As EventArgs)
        MyBase.OnMouseEnter(e)
        If Image Is Nothing Then Return
        If FrmZoom Is Nothing Then CreateZoomForm()
        If FrmZoom.Visible Then Return
        Dim loc As Point
        Select Case ZoomFormStartPosition
            Case StartPosition.Relative
                loc = PointToScreen(Point.Empty)
            Case StartPosition.Center
                loc = PointToScreen(Point.Empty)
                loc.X += (Width - FrmZoom.Width)  2
                loc.Y += (Height - FrmZoom.Height)  2
            Case Else
                loc = Cursor.Position
        End Select
        If KeepZoomFormWithinScreen Then
            Dim sc = Screen.FromControl(Me).Bounds ' or .WorkingArea
            If loc.X + FrmZoom.Width > sc.Width Then
                loc.X = sc.Right - FrmZoom.Width
            End If
            If loc.Y + FrmZoom.Height > sc.Height Then
                loc.Y = sc.Bottom - FrmZoom.Height
            End If
            loc.X = Math.Max(0, loc.X)
            loc.Y = Math.Max(0, loc.Y)
        End If
        FrmZoom.Location = loc
        PicZoom.Image = Image
        FrmZoom.Show()
    End Sub

    Protected Overrides Sub OnMouseLeave(e As EventArgs)
        MyBase.OnMouseLeave(e)
        If Not ClientRectangle.Contains(PointToClient(Cursor.Position)) Then
            FrmZoom.Hide()
        End If
    End Sub

    Protected Overrides Sub Dispose(disposing As Boolean)
        If disposing Then
            FrmZoom?.Dispose()
        End If
        MyBase.Dispose(disposing)
    End Sub

    Private Sub CreateZoomForm()
        PicZoom = New PictureBox With {
            .SizeMode = PictureBoxSizeMode.Zoom,
            .Dock = DockStyle.Fill,
        }
        FrmZoom = New Form With {
            .FormBorderStyle = FormBorderStyle.None,
            .ControlBox = False,
            .ShowInTaskbar = False,
            .TopMost = True,
            .StartPosition = FormStartPosition.Manual,
            .Size = New Size(Width * 2, Height * 2)
        }
        FrmZoom.Controls.Add(PicZoom)
        AddHandler FrmZoom.Disposed, Sub(s, e) PicZoom.Dispose()
        AddHandler PicZoom.MouseLeave, Sub(s, e) OnMouseLeave(EventArgs.Empty)
    End Sub
End Class

Notes

  • In a derived class, override the methods of the base class and do not subscribe to its events. Other controls can subscribe to events if needed.
  • No need to keep creating and destroying the zoom Form. Create it on first access and override the owner’s Dispose method to dispose of it.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật