Link to home
Start Free TrialLog in
Avatar of teamdad
teamdad

asked on

Sliding panel

I have been working on this bit of code that I really like but I am missing a way to set the bounds or add a grip for the panel. It's a sliding panel

It lets you slide the panel all right but it will let you pull it all the way off the forms edge or all the way back into itself and either case it disapears off the form when this happens. It needs to have a way to set a limit like a form has MaximumSize and MinimumSize type limits or maybe have a grip on the edge or something that would allow you to set some boundries. I have fooled around with getting this much of it to work for months now and would like to put an end to it appearing in my dreams as being unfinished.

Any thoughts on getting it to only open and close to a set size limit? and can someone also tell me how to draw or make the Microsoft nubs is what I call em.  The little dots that are used as seperators or grips in some of Microsoft's apps.  If you are using XP and have your theme set as XP you can see them just to the right of your "Start" button.

Private Sub Panel1_MouseMove(ByVal sender As Object, ByVal e As_
System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseMove

        If _mouseDown = True Then
            Panel1.Width = e.X
        Else
            If e.X >= Panel1.Width - 3 Then
                Panel1.Cursor = Cursors.VSplit
            Else
                Panel1.Cursor = Me.Cursor
            End If
        End If

    End Sub

    Private Sub Panel1_MouseDown(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseDown

        _mouseDown = True
        Panel1.Cursor = Cursors.VSplit
    End Sub

    Private Sub Panel1_MouseUp(ByVal sender As Object, _
    ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel1.MouseUp

        _mouseDown = False
        Panel1.Cursor = Me.Cursor
    End Sub
Avatar of checoo
checoo

you need to clip area for the cursor, so that it does not move beyond the boundary -- have a look at the following code, in the following code you can drag the list box by dragging the label column list

Imports System
Imports System.Drawing
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Data.SqlClient

Public Class frmDrag
    Inherits System.Windows.Forms.Form
    Private WithEvents lstDBColumns As System.Windows.Forms.ListBox
    Private WithEvents lblDBColumns As System.Windows.Forms.Label
    '/ <summary>
    '/ Required designer variable.
    '/ </summary>
    Private components As System.ComponentModel.Container = Nothing
    Private blnDraging As Boolean
    Private mouseX, mouseY As Integer
    Private panelBadgeDesign As System.Windows.Forms.Panel
    Private oldRect As System.Drawing.Rectangle


    Public Sub New()
        '
        ' Required for Windows Form Designer support
        '
        InitializeComponent()
    End Sub 'New

    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub 'Dispose


    Private Sub InitializeComponent()
        Me.lstDBColumns = New System.Windows.Forms.ListBox
        Me.lblDBColumns = New System.Windows.Forms.Label
        Me.panelBadgeDesign = New System.Windows.Forms.Panel
        Me.SuspendLayout()
        '
        ' lstDBColumns
        '
        Me.lstDBColumns.Location = New System.Drawing.Point(680, 112)
        Me.lstDBColumns.Name = "lstDBColumns"
        Me.lstDBColumns.Size = New System.Drawing.Size(120, 173)
        Me.lstDBColumns.TabIndex = 0
        '
        ' lblDBColumns
        '
        Me.lblDBColumns.BackColor = System.Drawing.Color.DarkSlateBlue
        Me.lblDBColumns.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.lblDBColumns.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, CType(0, System.Byte))
        Me.lblDBColumns.ForeColor = System.Drawing.Color.White
        Me.lblDBColumns.Location = New System.Drawing.Point(680, 96)
        Me.lblDBColumns.Name = "lblDBColumns"
        Me.lblDBColumns.Size = New System.Drawing.Size(120, 16)
        Me.lblDBColumns.TabIndex = 1
        Me.lblDBColumns.Text = "Column List"
        '
        ' panelBadgeDesign
        '
        Me.panelBadgeDesign.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D
        Me.panelBadgeDesign.ForeColor = System.Drawing.Color.Black
        Me.panelBadgeDesign.Location = New System.Drawing.Point(256, 136)
        Me.panelBadgeDesign.Name = "panelBadgeDesign"
        Me.panelBadgeDesign.Size = New System.Drawing.Size(304, 192)
        Me.panelBadgeDesign.TabIndex = 2
        '
        ' frmBadgeDesign
        '
        Me.AllowDrop = True
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(808, 501)
        Me.Controls.Add(panelBadgeDesign)
        Me.Controls.Add(lstDBColumns)
        Me.Controls.Add(lblDBColumns)
        Me.Name = "frmBadgeDesign"
        Me.Text = "frmBadgeDesign"
        Me.ResumeLayout(False)
    End Sub 'InitializeComponent


    Public Shared Sub Main()
        Application.Run(New frmDrag)
    End Sub 'Main


    Private Sub lblDBColumns_MouseEnter(ByVal sender As Object, ByVal e As System.EventArgs) Handles lblDBColumns.MouseEnter
        lblDBColumns.BorderStyle = BorderStyle.Fixed3D
    End Sub 'lblDBColumns_MouseEnter


    Private Sub lblDBColumns_MouseLeave(ByVal sender As Object, ByVal e As System.EventArgs) Handles lblDBColumns.MouseLeave
        lblDBColumns.BorderStyle = BorderStyle.FixedSingle
    End Sub 'lblDBColumns_MouseLeave


    Private Sub lblDBColumns_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles lblDBColumns.MouseDown
        Dim clipLeft, clipTop, clipHeight, clipWidth As Integer
        If e.Button = MouseButtons.Left Then
            oldRect = Cursor.Clip
            lblDBColumns.Cursor = Cursors.SizeAll
            lstDBColumns.BorderStyle = BorderStyle.FixedSingle
            blnDraging = True
            mouseX = -e.X
            mouseY = -e.Y
            clipLeft = Me.PointToClient(MousePosition).X - lblDBColumns.Location.X
            clipTop = Me.PointToClient(MousePosition).Y - lblDBColumns.Location.Y
            clipWidth = Me.ClientSize.Width - (lblDBColumns.Width - clipLeft)
            clipHeight = Me.ClientSize.Height - (lstDBColumns.Height - clipTop)
            Cursor.Clip = Me.RectangleToScreen(New Rectangle(clipLeft, clipTop, clipWidth, clipHeight))
            lblDBColumns.Invalidate()
        End If
    End Sub 'lblDBColumns_MouseDown


    Private Sub lblDBColumns_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles lblDBColumns.MouseUp
        If blnDraging Then
            Cursor.Clip = oldRect
            lblDBColumns.Cursor = Cursors.Default
            lstDBColumns.BorderStyle = BorderStyle.Fixed3D
            blnDraging = False
            lblDBColumns.Invalidate()
        End If
    End Sub 'lblDBColumns_MouseUp


    Private Sub lblDBColumns_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles lblDBColumns.MouseMove
        Dim position As System.Drawing.Point
        If blnDraging Then
            position = New Point
            position = Me.PointToClient(MousePosition)
            position.Offset(mouseX, mouseY)
            lblDBColumns.Location = position
            lstDBColumns.Left = lblDBColumns.Left
            lstDBColumns.Top = lblDBColumns.Top + lblDBColumns.Height
        End If
    End Sub 'lblDBColumns_MouseMove


    Private Sub frmBadgeDesign_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        lstDBColumns.Items.Add("One")
        lstDBColumns.Items.Add("Two")
        lstDBColumns.Items.Add("Three")
        lstDBColumns.Items.Add("Four")
        lstDBColumns.Items.Add("Five")
    End Sub
End Class
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of teamdad

ASKER

Idle_Mind,

Any thoughts on how to put the button grips on the edge that you can slide the panel with?
Well, I don't know of any function to draw those "grips" automatically.  You could experiment with trying to draw them manually in the Paint() event of your panel.

Another thought is to place a second panel or picturebox just to the right of the panel you want to slide.  Then allow that panel/picturebox to be moved left/right without resizing it.  As it moves left/right, resize the first panel as you go.  You could draw your nubs in the second panel or set the Image property of the picturebox.

~IM

Avatar of teamdad

ASKER

I'll have to do some research on getting a picturebox to work as you said with the panel.

Thanks for the assist on the code though.
See how you like this:

Public Class Form1
    Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call

    End Sub

    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents Panel1 As System.Windows.Forms.Panel
    Friend WithEvents PictureBox1 As System.Windows.Forms.PictureBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.Panel1 = New System.Windows.Forms.Panel
        Me.PictureBox1 = New System.Windows.Forms.PictureBox
        Me.SuspendLayout()
        '
        'Panel1
        '
        Me.Panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle
        Me.Panel1.Location = New System.Drawing.Point(48, 72)
        Me.Panel1.Name = "Panel1"
        Me.Panel1.Size = New System.Drawing.Size(104, 120)
        Me.Panel1.TabIndex = 1
        '
        'PictureBox1
        '
        Me.PictureBox1.BackColor = System.Drawing.Color.Red
        Me.PictureBox1.Cursor = System.Windows.Forms.Cursors.SizeWE
        Me.PictureBox1.Location = New System.Drawing.Point(152, 72)
        Me.PictureBox1.Name = "PictureBox1"
        Me.PictureBox1.Size = New System.Drawing.Size(8, 120)
        Me.PictureBox1.TabIndex = 2
        Me.PictureBox1.TabStop = False
        '
        'Form1
        '
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.ClientSize = New System.Drawing.Size(292, 266)
        Me.Controls.Add(Me.PictureBox1)
        Me.Controls.Add(Me.Panel1)
        Me.Name = "Form1"
        Me.Text = "Form1"
        Me.ResumeLayout(False)

    End Sub

#End Region

    Private startX As Integer

    Private Sub PictureBox1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
        If e.Button = MouseButtons.Left Then
            Dim p As Point = PictureBox1.PointToScreen(New Point(e.X, e.Y))
            startX = p.X

            Dim pRect As Rectangle = Me.RectangleToScreen(New Rectangle(Panel1.Location, Panel1.Size))
            pRect.X = pRect.X + e.X + 1
            pRect.Width = Me.ClientSize.Width - Panel1.Left - e.X - (PictureBox1.Width - e.X)
            Cursor.Clip = pRect
        End If
    End Sub

    Private Sub PictureBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
        If e.Button = MouseButtons.Left Then
            Dim p As Point = PictureBox1.PointToScreen(New Point(e.X, e.Y))
            PictureBox1.Left = PictureBox1.Left + (p.X - startX)
            Panel1.Width = Panel1.Width + (p.X - startX)
            startX = p.X
        End If
    End Sub

    Private Sub PictureBox1_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
        If e.Button = MouseButtons.Left Then
            Cursor.Clip = New Rectangle(0, 0, Screen.GetBounds(New Point(0, 0)).Width, Screen.GetBounds(New Point(0, 0)).Height)
        End If
    End Sub

End Class
Avatar of teamdad

ASKER

Well I am blown out of the pond with that piece of code.... I have had dreams of how to get my little sliding panel to work and I have been working on that thing for months.  Goes to show you that I have a lot to learn.

One thing tho if you get this comment; how in the code could you restrict the panel to only slide so far and then stop instead of allowing it to go all the way out to the edge of the form.
The code that clips the cursor is this part:

            Dim pRect As Rectangle = Me.RectangleToScreen(New Rectangle(Panel1.Location, Panel1.Size))
            pRect.X = pRect.X + e.X + 1
            pRect.Width = Me.ClientSize.Width - Panel1.Left - e.X - (PictureBox1.Width - e.X)
            Cursor.Clip = pRect

The first line starts by creating a rectangle to represent the location of Panel1 in client (form) coordinates.  The rectangle is then converted to screen coordinates because the Clip() function expects them.  In the second line, I then adjust the left edge of the rectangle by adding e.X + 1 to it.  The value e.X represents how far over we are in the PictureBox when we started dragging.  This means there are e.X pixels to the left of the cursor in our PictureBox.  By adding that amount to the left edge of the clipping rectangle, we cause the left edge of the PictureBox to rest directly over the left edge of the Panel when the PictureBox is dragged to the extreme left of the clipping region.

So the left edge of the clipping region has been adjusted so that the picturebox will not extend beyond where the left edge of our panel is.  The third line adjusts the width of the clipping rectangle and thus adjusts how far to the right the PictureBox and Panel can be dragged.  The first part of the equation, Me.ClientSize.Width - Panel1.Left, calculates the distance between the left edge of our panel and the right edge of the form.  The second part of the equation,  - e.X - (PictureBox1.Width - e.X), then reduces the width to account for the PictureBox.  We subtract e.X because earlier we adjusted the left edge of the clipping region by that much.  Then we subtract (PictureBox1.Width - e.X) so that the right edge of the PictureBox will stop at the right edge of the form.  If your paying attention, the amount that we subtract, - e.X - (PictureBox1.Width - e.X), is actually equivalent to simply PictureBox1.Width so the third line could be rewritten as

            pRect.Width = Me.ClientSize.Width - Panel1.Left - PictureBox1.Width

Finally, we take our computed rectangle and pass it to the Clip() function.  So the short answer to your question is to adjust the Width of the rectangle which is shown above.

~IM
Avatar of teamdad

ASKER

Gotcha.... pRect.Width = Me.ClientSize.Width - Panel1.Left - PictureBox1.Width - 150  simplified answer is to add the - 150 to tell the panel it can't go past that amout to the right side of the form.  Oh and the pRect.X = pRect.X + e.X + 1 part leaves a one pixel buffer of the panel showing on the left but if you take out the + 1 it still works with no change to the function of the panel other than it just matches a clean edge with no buffer of the panel showing.

Thanks so much for your assist on this!!!