When I use AutoScroll, scrollbars never show up if the controls are outside of the container to the left or top of it, only to the right or bottom. How do I fix this
Funny, this is just the behaviour that I would expect, but you are right: ScrollableControl could indeed correct for negative values and move its children accordingly.
Why don't you just do the math yourself 1. Find the top-left child control in the panel and store its offset. 2. Subtract that offset from all child control's positions. The top-left control will now be located at (0,0) and all other controls will have moved the same amount.
The existence of this article suggests that the AutoScroll property isn't the appropriate way to do it at all, as otherwise it would surely refer to that as a simpler way to achieve the same thing. So I'll just put scrollbar controls in like the article suggests. Incidentally, there seems to be no way that I can see to add scrollbars at design time that are docked to a picturebox as the article suggests you should do. To do this they would need to be contained in the picturebox, but it's not possible to add controls at design time so as to be contained in a picture box (so far as I can see). I don't know why, because you can do it at run time OK - perhaps this is an oversight.
I don't want the children all in view - if the user drags one partly off, then that's where it should stay, and a scrollbar should allow him to drag it back on. I think I've managed to translate your code to VB OK (see below) and it doesn't work like this if a child is dragged off the left of the parent panel - it remains in view.
Public Class Form1
Private m_MousePosAtClicked As Point = New Point() Private m_ControlPosAtClicked As Point = New Point() Private m_DragRect As Rectangle = New Rectangle() Private m_IsDragging As Boolean = False
Private Sub Panel2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel2.MouseDown, Panel3.MouseDown If e.Button = Windows.Forms.MouseButtons.Left Then Dim P As Panel = sender m_MousePosAtClicked = e.Location m_ControlPosAtClicked = P.Location P.Capture = True m_DragRect = New Rectangle(P.Location, P.Size) m_IsDragging = True End If End Sub
Private Function GetNewLocation(ByVal e As MouseEventArgs) As Point
Dim delta As Point = e.Location
delta.Offset(-m_MousePosAtClicked.X, -m_MousePosAtClicked.Y) Dim newLoc As Point = m_ControlPosAtClicked newLoc.Offset(delta)
Return newLoc End Function
Private Sub control_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Panel2.MouseMove, Panel3.MouseMove
Dim P As Panel = sender If (e.Button = Windows.Forms.MouseButtons.Left And P.Capture) Then
m_DragRect = New Rectangle(GetNewLocation(e), P.Size) Panel1.Invalidate() End If End Sub
Private Function GetMostLeftControl() As Panel
Dim result As Panel = Nothing Dim minX As Integer = Integer.MaxValue
For Each P As Panel In Panel1.Controls
If (P.Left < minX) Then
result = P minX = P.Left End If next Return result End Function
Private Function GetMostTopControl() As Panel
Dim result As Panel = Nothing Dim minX As Integer = Integer.MaxValue
For Each P As Panel In Panel1.Controls
If (P.Top < minX) Then
result = P minX = P.Top End If Next Return result End Function
Private Sub PerformAutoCorrect()
Dim mostLeftControl As Panel = GetMostLeftControl() Dim mostTopControl As Panel = GetMostTopControl()
Dim offset As Point = New Point(0, 0)
If Not mostLeftControl Is Nothing Then If mostLeftControl.Left < 0 Then offset.X = -mostLeftControl.Left End If If Not mostTopControl Is Nothing Then If mostTopControl.Top < 0 Then offset.Y = -mostLeftControl.Top End If
If (offset.X > 0 Or offset.Y > 0) Then
For Each P As Panel In Panel1.Controls
Dim curLoc As Point = P.Location curLoc.Offset(offset) P.Location = curLoc Next End If
End Sub
Private Sub control_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Panel2.MouseUp, Panel3.MouseUp
Dim P As Panel = sender If (e.Button = Windows.Forms.MouseButtons.Left And P.Capture) Then
m_IsDragging = False P.Capture = False P.Location = GetNewLocation(e) PerformAutoCorrect() Panel1.Invalidate() End If
End Sub
Private Sub panel1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Panel1.Paint
e.Graphics.Clear(Color.Yellow) If (m_IsDragging) Then
e.Graphics.DrawRectangle(Pens.Black, m_DragRect) End If End Sub
Thanks, but I want the control to move with the MouseMove event, not the MouseUp event. Also, I'm not very familiar with C# and couldn't get your code to work.
I don't see what part of the code corrects the locations of all the children here... I also don't understand how Code Writer's suggestion is going to help you on controls that are placed outside of the top-left boundaries.
Anyway, I've written a sample app that does exactly what you are trying to do, or at least how I understond that it should work. There are two child controls (panels) that can be dragged on a parent panel. I've put a background color on all of them so they are clearly visible. When dragged, a drag rectangle is painted, and when stopped dragging, the control is repositioned. The topmost and leftmost control is searched and all controls are moved if the topmost or leftmost position is smaller than zero. By moving them, the scrollbars are enlarged automatically because the panel's child positions change.
You also mentioned about the standard 'ScrollIntoView' behaviour that is sometimes not really desirable. At the back of this message I will post sample code to control that.
Here's the sample code for moving controls:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Diagnostics;
namespace AutoScrollTest { public class Form1 : Form { public Form1() { InitializeComponent(); }
private Point m_MousePosAtClicked = new Point(); private Point m_ControlPosAtClicked = new Point(); private Rectangle m_DragRect = new Rectangle(); private bool m_IsDragging = false;
private void control_MouseDown( object sender, MouseEventArgs e ) { if( e.Button == MouseButtons.Left ) { Control control = (Control)sender; m_MousePosAtClicked = e.Location; m_ControlPosAtClicked = control.Location; control.Capture = true; m_DragRect = new Rectangle( control.Location, control.Size ); m_IsDragging = true;
panel1.Invalidate(); } }
private Point GetNewLocation( MouseEventArgs e ) { Point delta = e.Location; delta.Offset( -m_MousePosAtClicked.X, -m_MousePosAtClicked.Y ); Point newLoc = m_ControlPosAtClicked; newLoc.Offset( delta );
return newLoc; }
private void control_MouseMove( object sender, MouseEventArgs e ) { Control control = (Control)sender; if( e.Button == MouseButtons.Left && control.Capture ) { m_DragRect = new Rectangle( GetNewLocation(e), control.Size ); panel1.Invalidate(); } }
private Control GetMostLeftControl() { Control result = null; int minX = int.MaxValue;
foreach( Control control in panel1.Controls ) { if( control.Left < minX ) { result = control; minX = control.Left; } } return result; }
private Control GetMostTopControl() { Control result = null; int minY = int.MaxValue;
foreach( Control control in panel1.Controls ) { if( control.Top < minY ) { result = control; minY = control.Top; } } return result; }
private void PerformAutoCorrect() { Control mostLeftControl = GetMostLeftControl(); Control mostTopControl = GetMostTopControl();
And here's the code that controls the scroll control into view thingie:
// When a child control gets focus and AutoScroll is true, the scroll bar for the parent will immediatly scroll left // to ensure the selected control is in view. This is undesireable when dealing with several large controls in a panel. // To avoid this, we simply set the scroll bar's postion back to the position is was before // the "Enter" event was fired. We can use a delegate to do this. private AutoScrollPositionEventHandler del = new AutoScrollPositionEventHandler(SetAutoScrollPosition);
private void track_Enter(object sender, EventArgs e) { Point p = trackPanel.AutoScrollPosition; Object[] args = {trackPanel, p}; BeginInvoke(del, args); }
The article from the link contains a sample on how to implement scrollbars for a picturebox without the autoscroll functionality. I think this is just a sample to see how it works, and not a way to evangelize it as a substitute for autoscroll functionality.
In order to get the sample to work from the link you posted, use the method I described earlier, by using a UserControl for instance, or how the sample suggests it should: by just putting a picturebox with autoscroll disabled and two scrollbars...
I started out setting the control's location in the mousemove, but that resulted in some odd sideeffect: the control was flickering and jumping to old positions. I had no time to solve that issue, so I used a drag rectangle instead. Nevertheless, the code demonstrates how to correct the children so that they are all in view, using correct scrollbars. Just check the PerformAutoCorrect method. It shouldn't be all that hard to read for VB programmers.
I think you have pasted the link from the local help . Can you post a link from the msdn site
AutoScroll uses the autoscrollbars. That means that the WS_VSCROLL and/or WS_HSCROLL bits are set on the control. Indead, you can't reach these in the designer, and the operations you can perform on them are limited.
What you can do is create a UserControl, put a panel in it to draw on and put a horizontal and vertical scrollbar beside the panel. Anchor them correctly. This is usually how you would create a virtual plane, and you will have to manage all of the scrolling by yourself. I agree, this is a better way of handling such situations, but that's not what you asked for . If you want my opinion: in case of virtual planes I often prefer not to use scrollbars at all. I scroll by clicking and dragging the plane, and I zoom in and out logarithmically to have an overview. But this depends on your specific needs for your control.
Have thought briefly about both your suggestions, thanks. What I want to do is have some controls on a form that a user can move about, with scroll bars appearing if he moves them off screen. There's another problem with this which is that if the scrollbars are automatically scrolled to keep the control that's being moved fully visible. That doesn't look very good because the control doesn't move as the user would expect. So maybe your suggestions will work but in any case I think I'll just pass on the auto scrollbars and use my own instead.
Imports
System.Math
Public
Class Form1 Dim X1 As Long Dim Y1 As Long WithEvents Button1 As Button Dim B2 As Button 'for reference. Private Sub Button1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
X1 = e.X
Y1 = e.Y
End Sub Private Sub Button1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = Windows.Forms.MouseButtons.Left Then
sender.Location =
New Point(e.X + sender.Left - X1 + Me.AutoScrollPosition.X, e.Y + sender.Top - Y1 + Me.AutoScrollPosition.Y) 'jVanderbeek's suggestion as I understand it. If sender.left < 0 Then
B2.Left = B2.Left - sender.left
sender.left = 0
End If If sender.top < 0 Then
B2.Top = B2.Top - sender.top
sender.top = 0
End If 'Code Writer's Suggestion as I understand it. Me.AutoScrollMinSize = New Point(Max(Max(B2.Right - Button1.Left, Button1.Right - B2.Left), Me.ClientSize.Width), _
Autoscroll
Sridhar S
Why don't you just do the math yourself
1. Find the top-left child control in the panel and store its offset.
2. Subtract that offset from all child control's positions. The top-left control will now be located at (0,0) and all other controls will have moved the same amount.
Hope this helps,
Jelle
TobsTec
jbstearley
Actually, I think I probably could reach the autoscrollbars using the APIs SetScrollInfo and GetScrollInfo. Might try that.
I'm not seeking to achieve anything by using scrollbar controls that I wasn't trying to achieve with Autoscroll, nothing has changed.
Greenrelations-Webmaster
Public Class Form1
Private m_MousePosAtClicked As Point = New Point()
Private m_ControlPosAtClicked As Point = New Point()
Private m_DragRect As Rectangle = New Rectangle()
Private m_IsDragging As Boolean = False
Private Sub Panel2_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Panel2.MouseDown, Panel3.MouseDown
If e.Button = Windows.Forms.MouseButtons.Left Then
Dim P As Panel = sender
m_MousePosAtClicked = e.Location
m_ControlPosAtClicked = P.Location
P.Capture = True
m_DragRect = New Rectangle(P.Location, P.Size)
m_IsDragging = True
End If
End Sub
Private Function GetNewLocation(ByVal e As MouseEventArgs) As Point
Dim delta As Point = e.Location
delta.Offset(-m_MousePosAtClicked.X, -m_MousePosAtClicked.Y)
Dim newLoc As Point = m_ControlPosAtClicked
newLoc.Offset(delta)
Return newLoc
End Function
Private Sub control_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Panel2.MouseMove, Panel3.MouseMove
Dim P As Panel = sender
If (e.Button = Windows.Forms.MouseButtons.Left And P.Capture) Then
m_DragRect = New Rectangle(GetNewLocation(e), P.Size)
Panel1.Invalidate()
End If
End Sub
Private Function GetMostLeftControl() As Panel
Dim result As Panel = Nothing
Dim minX As Integer = Integer.MaxValue
For Each P As Panel In Panel1.Controls
If (P.Left < minX) Then
result = P
minX = P.Left
End If
next
Return result
End Function
Private Function GetMostTopControl() As Panel
Dim result As Panel = Nothing
Dim minX As Integer = Integer.MaxValue
For Each P As Panel In Panel1.Controls
If (P.Top < minX) Then
result = P
minX = P.Top
End If
Next
Return result
End Function
Private Sub PerformAutoCorrect()
Dim mostLeftControl As Panel = GetMostLeftControl()
Dim mostTopControl As Panel = GetMostTopControl()
Dim offset As Point = New Point(0, 0)
If Not mostLeftControl Is Nothing Then
If mostLeftControl.Left < 0 Then offset.X = -mostLeftControl.Left
End If
If Not mostTopControl Is Nothing Then
If mostTopControl.Top < 0 Then offset.Y = -mostLeftControl.Top
End If
If (offset.X > 0 Or offset.Y > 0) Then
For Each P As Panel In Panel1.Controls
Dim curLoc As Point = P.Location
curLoc.Offset(offset)
P.Location = curLoc
Next
End If
End Sub
Private Sub control_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Panel2.MouseUp, Panel3.MouseUp
Dim P As Panel = sender
If (e.Button = Windows.Forms.MouseButtons.Left And P.Capture) Then
m_IsDragging = False
P.Capture = False
P.Location = GetNewLocation(e)
PerformAutoCorrect()
Panel1.Invalidate()
End If
End Sub
Private Sub panel1_Paint(ByVal sender As Object, ByVal e As PaintEventArgs) Handles Panel1.Paint
e.Graphics.Clear(Color.Yellow)
If (m_IsDragging) Then
e.Graphics.DrawRectangle(Pens.Black, m_DragRect)
End If
End Sub
End Class
triplebuffer
Shivaraja K
The AutoScrollMinSize property is not calculated automatically from the positions of the right-most and bottom-most child controls.
Nillac
The only thing you have to do is set the scroll bars so that the view reflects the previous view, that won't be so hard.
Jelle over and out ;)
fabes
To solve this in Windows Forms 2.0 you can use the AutoScrollOffset property or override the ScrollToControl method.
N. Farr
I don't see what part of the code corrects the locations of all the children here...
I also don't understand how Code Writer's suggestion is going to help you on controls that are placed outside of the top-left boundaries.
Anyway, I've written a sample app that does exactly what you are trying to do, or at least how I understond that it should work. There are two child controls (panels) that can be dragged on a parent panel. I've put a background color on all of them so they are clearly visible. When dragged, a drag rectangle is painted, and when stopped dragging, the control is repositioned. The topmost and leftmost control is searched and all controls are moved if the topmost or leftmost position is smaller than zero. By moving them, the scrollbars are enlarged automatically because the panel's child positions change.
You also mentioned about the standard 'ScrollIntoView' behaviour that is sometimes not really desirable. At the back of this message I will post sample code to control that.
Here's the sample code for moving controls:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace AutoScrollTest
{
public class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private Point m_MousePosAtClicked = new Point();
private Point m_ControlPosAtClicked = new Point();
private Rectangle m_DragRect = new Rectangle();
private bool m_IsDragging = false;
private void control_MouseDown( object sender, MouseEventArgs e )
{
if( e.Button == MouseButtons.Left )
{
Control control = (Control)sender;
m_MousePosAtClicked = e.Location;
m_ControlPosAtClicked = control.Location;
control.Capture = true;
m_DragRect = new Rectangle( control.Location, control.Size );
m_IsDragging = true;
panel1.Invalidate();
}
}
private Point GetNewLocation( MouseEventArgs e )
{
Point delta = e.Location;
delta.Offset( -m_MousePosAtClicked.X, -m_MousePosAtClicked.Y );
Point newLoc = m_ControlPosAtClicked;
newLoc.Offset( delta );
return newLoc;
}
private void control_MouseMove( object sender, MouseEventArgs e )
{
Control control = (Control)sender;
if( e.Button == MouseButtons.Left && control.Capture )
{
m_DragRect = new Rectangle( GetNewLocation(e), control.Size );
panel1.Invalidate();
}
}
private Control GetMostLeftControl()
{
Control result = null;
int minX = int.MaxValue;
foreach( Control control in panel1.Controls )
{
if( control.Left < minX )
{
result = control;
minX = control.Left;
}
}
return result;
}
private Control GetMostTopControl()
{
Control result = null;
int minY = int.MaxValue;
foreach( Control control in panel1.Controls )
{
if( control.Top < minY )
{
result = control;
minY = control.Top;
}
}
return result;
}
private void PerformAutoCorrect()
{
Control mostLeftControl = GetMostLeftControl();
Control mostTopControl = GetMostTopControl();
Point offset = new Point( 0, 0 );
if( mostLeftControl != null && mostLeftControl.Left < 0 )
{
offset.X = -mostLeftControl.Left;
}
if( mostTopControl != null && mostTopControl.Top < 0 )
{
offset.Y = -mostTopControl.Top;
}
if( offset.X > 0 || offset.Y > 0 )
{
foreach( Control control in panel1.Controls )
{
Point curLoc = control.Location;
curLoc.Offset( offset );
control.Location = curLoc;
}
}
}
private void control_MouseUp( object sender, MouseEventArgs e )
{
Control control = (Control)sender;
if( e.Button == MouseButtons.Left && control.Capture )
{
m_IsDragging = false;
control.Capture = false;
control.Location = GetNewLocation( e );
PerformAutoCorrect();
panel1.Invalidate();
}
}
private void panel1_Paint( object sender, PaintEventArgs e )
{
e.Graphics.Clear( Color.Yellow );
if( m_IsDragging )
{
e.Graphics.DrawRectangle( Pens.Black, m_DragRect );
}
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose( bool disposing )
{
if( disposing && ( components != null ) )
{
components.Dispose();
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.panel2 = new System.Windows.Forms.Panel();
this.panel3 = new System.Windows.Forms.Panel();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoScroll = true;
this.panel1.BackColor = System.Drawing.Color.Yellow;
this.panel1.Controls.Add( this.panel3 );
this.panel1.Controls.Add( this.panel2 );
this.panel1.Location = new System.Drawing.Point( 88, 82 );
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size( 256, 158 );
this.panel1.TabIndex = 0;
this.panel1.Paint += new System.Windows.Forms.PaintEventHandler( this.panel1_Paint );
//
// panel2
//
this.panel2.BackColor = System.Drawing.Color.Lime;
this.panel2.Location = new System.Drawing.Point( 47, 67 );
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size( 37, 37 );
this.panel2.TabIndex = 2;
this.panel2.MouseDown += new System.Windows.Forms.MouseEventHandler( this.control_MouseDown );
this.panel2.MouseMove += new System.Windows.Forms.MouseEventHandler( this.control_MouseMove );
this.panel2.MouseUp += new System.Windows.Forms.MouseEventHandler( this.control_MouseUp );
//
// panel3
//
this.panel3.BackColor = System.Drawing.Color.Blue;
this.panel3.Location = new System.Drawing.Point( 184, 40 );
this.panel3.Name = "panel3";
this.panel3.Size = new System.Drawing.Size( 37, 37 );
this.panel3.TabIndex = 3;
this.panel3.MouseDown += new System.Windows.Forms.MouseEventHandler( this.control_MouseDown );
this.panel3.MouseMove += new System.Windows.Forms.MouseEventHandler( this.control_MouseMove );
this.panel3.MouseUp += new System.Windows.Forms.MouseEventHandler( this.control_MouseUp );
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF( 6F, 13F );
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size( 403, 289 );
this.Controls.Add( this.panel1 );
this.Name = "Form1";
this.Text = "Form1";
this.panel1.ResumeLayout( false );
this.ResumeLayout( false );
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Panel panel3;
}
}
And here's the code that controls the scroll control into view thingie:
// When a child control gets focus and AutoScroll is true, the scroll bar for the parent will immediatly scroll left
// to ensure the selected control is in view. This is undesireable when dealing with several large controls in a panel.
// To avoid this, we simply set the scroll bar's postion back to the position is was before
// the "Enter" event was fired. We can use a delegate to do this.
private AutoScrollPositionEventHandler del = new AutoScrollPositionEventHandler(SetAutoScrollPosition);
private void track_Enter(object sender, EventArgs e)
{
Point p = trackPanel.AutoScrollPosition;
Object[] args = {trackPanel, p};
BeginInvoke(del, args);
}
private static void SetAutoScrollPosition(ScrollableControl sender, Point p)
{
p.X = Math.Abs(p.X);
p.Y = Math.Abs(p.Y);
sender.AutoScrollPosition = p;
}
Hope this helps,
Jelle
Piotr Stapp
http://msdn.microsoft.com/library/default.asp url=/library/en-us/shellcc/platform/commctls/scrollbars/scrollbarreference/scrollbarfunctions/setscrollinfo.asp
But this is not something you need to do know. Still you might want to check my post on richtextbox & autoscrollbars to see a sample on how it works:
http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=159877&SiteID=1
The article from the link contains a sample on how to implement scrollbars for a picturebox without the autoscroll functionality. I think this is just a sample to see how it works, and not a way to evangelize it as a substitute for autoscroll functionality.
In order to get the sample to work from the link you posted, use the method I described earlier, by using a UserControl for instance, or how the sample suggests it should: by just putting a picturebox with autoscroll disabled and two scrollbars...
tlove
Jelle out
Deeneyman
Dave Relyea
AutoScroll uses the autoscrollbars. That means that the WS_VSCROLL and/or WS_HSCROLL bits are set on the control. Indead, you can't reach these in the designer, and the operations you can perform on them are limited.
What you can do is create a UserControl, put a panel in it to draw on and put a horizontal and vertical scrollbar beside the panel. Anchor them correctly. This is usually how you would create a virtual plane, and you will have to manage all of the scrolling by yourself. I agree, this is a better way of handling such situations, but that's not what you asked for
But I'm anxious to read the article actually!
technobia
Have thought briefly about both your suggestions, thanks. What I want to do is have some controls on a form that a user can move about, with scroll bars appearing if he moves them off screen. There's another problem with this which is that if the scrollbars are automatically scrolled to keep the control that's being moved fully visible. That doesn't look very good because the control doesn't move as the user would expect. So maybe your suggestions will work but in any case I think I'll just pass on the auto scrollbars and use my own instead.
Imports
System.MathPublic
Class Form1 Dim X1 As Long Dim Y1 As Long WithEvents Button1 As Button Dim B2 As Button 'for reference. Private Sub Button1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)X1 = e.X
Y1 = e.Y
End Sub Private Sub Button1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) If e.Button = Windows.Forms.MouseButtons.Left Thensender.Location =
New Point(e.X + sender.Left - X1 + Me.AutoScrollPosition.X, e.Y + sender.Top - Y1 + Me.AutoScrollPosition.Y) 'jVanderbeek's suggestion as I understand it. If sender.left < 0 ThenB2.Left = B2.Left - sender.left
sender.left = 0
End If If sender.top < 0 ThenB2.Top = B2.Top - sender.top
sender.top = 0
End If 'Code Writer's Suggestion as I understand it. Me.AutoScrollMinSize = New Point(Max(Max(B2.Right - Button1.Left, Button1.Right - B2.Left), Me.ClientSize.Width), _Max(Max(B2.Bottom - Button1.Top, Button1.Bottom - B2.Top),
Me.ClientSize.Height)) End If End Sub Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.LoadButton1 =
New Button Me.Controls.Add(Button1)B2 =
New Button Me.Controls.Add(B2)B2.Location =
New Point(Me.Width / 2, Me.Height / 2) AddHandler Button1.MouseDown, AddressOf Button1_MouseDown AddHandler Button1.MouseMove, AddressOf Button1_MouseMove End SubEnd
Class