|
|
@@ -39,11 +39,14 @@ namespace System.Windows.Forms {
|
|
|
private bool auto_hscroll;
|
|
|
private bool hscroll_visible;
|
|
|
private bool vscroll_visible;
|
|
|
+ private bool force_hscroll_visible;
|
|
|
+ private bool force_vscroll_visible;
|
|
|
private bool auto_scroll;
|
|
|
private Size auto_scroll_margin;
|
|
|
private Size auto_scroll_min_size;
|
|
|
- private Point auto_scroll_position;
|
|
|
+ private Point scroll_position;
|
|
|
private DockPaddingEdges dock_padding;
|
|
|
+ private SizeGrip sizegrip;
|
|
|
private HScrollBar hscrollbar;
|
|
|
private VScrollBar vscrollbar;
|
|
|
#endregion // Local Variables
|
|
|
@@ -183,11 +186,11 @@ namespace System.Windows.Forms {
|
|
|
|
|
|
// Public Instance Methods
|
|
|
public override PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, Attribute[] attributes) {
|
|
|
- throw new NotImplementedException();
|
|
|
+ return TypeDescriptor.GetProperties(typeof(DockPaddingEdges), attributes);
|
|
|
}
|
|
|
|
|
|
public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) {
|
|
|
- throw new NotImplementedException();
|
|
|
+ return true;
|
|
|
}
|
|
|
}
|
|
|
#endregion // Subclass DockPaddingEdgesConverter
|
|
|
@@ -200,10 +203,14 @@ namespace System.Windows.Forms {
|
|
|
auto_vscroll = false;
|
|
|
hscroll_visible = false;
|
|
|
vscroll_visible = false;
|
|
|
+ force_hscroll_visible = false;
|
|
|
+ force_vscroll_visible = false;
|
|
|
auto_scroll_margin = new Size(0, 0);
|
|
|
auto_scroll_min_size = new Size(0, 0);
|
|
|
- auto_scroll_position = new Point(0, 0);
|
|
|
+ scroll_position = new Point(0, 0);
|
|
|
dock_padding = new DockPaddingEdges();
|
|
|
+ SizeChanged +=new EventHandler(Recalculate);
|
|
|
+ VisibleChanged += new EventHandler(Recalculate);
|
|
|
}
|
|
|
#endregion // Public Constructors
|
|
|
|
|
|
@@ -229,6 +236,35 @@ namespace System.Windows.Forms {
|
|
|
}
|
|
|
|
|
|
auto_scroll = value;
|
|
|
+ if (!auto_scroll) {
|
|
|
+ Controls.Remove(hscrollbar);
|
|
|
+ hscrollbar.Dispose();
|
|
|
+ hscrollbar = null;
|
|
|
+
|
|
|
+ Controls.Remove(vscrollbar);
|
|
|
+ vscrollbar.Dispose();
|
|
|
+ vscrollbar = null;
|
|
|
+
|
|
|
+ Controls.Remove(sizegrip);
|
|
|
+ sizegrip.Dispose();
|
|
|
+ sizegrip = null;
|
|
|
+ } else {
|
|
|
+ hscrollbar = new HScrollBar();
|
|
|
+ hscrollbar.Visible = false;
|
|
|
+ hscrollbar.ValueChanged += new EventHandler(HandleScrollBar);
|
|
|
+ hscrollbar.Height = SystemInformation.HorizontalScrollBarHeight;
|
|
|
+ this.Controls.Add(hscrollbar);
|
|
|
+
|
|
|
+ vscrollbar = new VScrollBar();
|
|
|
+ vscrollbar.Visible = false;
|
|
|
+ vscrollbar.ValueChanged += new EventHandler(HandleScrollBar);
|
|
|
+ vscrollbar.Width = SystemInformation.VerticalScrollBarWidth;
|
|
|
+ this.Controls.Add(vscrollbar);
|
|
|
+
|
|
|
+ sizegrip = new SizeGrip();
|
|
|
+ sizegrip.Visible = false;
|
|
|
+ this.Controls.Add(sizegrip);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -266,11 +302,35 @@ namespace System.Windows.Forms {
|
|
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
|
|
|
public Point AutoScrollPosition {
|
|
|
get {
|
|
|
- return auto_scroll_position;
|
|
|
+ return new Point(-scroll_position.X, -scroll_position.Y);
|
|
|
}
|
|
|
|
|
|
set {
|
|
|
- auto_scroll_position = value;
|
|
|
+ if ((value.X != scroll_position.X) || (value.Y != scroll_position.Y)) {
|
|
|
+ int shift_x;
|
|
|
+ int shift_y;
|
|
|
+
|
|
|
+ shift_x = 0;
|
|
|
+ shift_y = 0;
|
|
|
+ if (hscroll_visible) {
|
|
|
+ shift_x = value.X - scroll_position.X;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vscroll_visible) {
|
|
|
+ shift_y = value.Y - scroll_position.Y;
|
|
|
+ }
|
|
|
+
|
|
|
+ ScrollWindow(shift_x, shift_y);
|
|
|
+
|
|
|
+ if (hscroll_visible) {
|
|
|
+ hscrollbar.Value = scroll_position.X;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vscroll_visible) {
|
|
|
+ vscrollbar.Value = scroll_position.Y;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -305,7 +365,7 @@ namespace System.Windows.Forms {
|
|
|
}
|
|
|
|
|
|
// DockPadding is documented as 'get' only ( http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemWindowsFormsScrollableControlClassAutoScrollTopic.asp )
|
|
|
- // but Microsoft's on that pageexamples show 'set' usage
|
|
|
+ // but Microsoft's examples on that page show 'set' usage
|
|
|
// set {
|
|
|
// dock_padding = value;
|
|
|
// }
|
|
|
@@ -332,9 +392,8 @@ namespace System.Windows.Forms {
|
|
|
|
|
|
set {
|
|
|
if (hscroll_visible != value) {
|
|
|
- hscroll_visible = value;
|
|
|
- if (hscroll_visible && hscrollbar == null)
|
|
|
- hscrollbar = new HScrollBar ();
|
|
|
+ force_hscroll_visible = value;
|
|
|
+ Recalculate(this, EventArgs.Empty);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -346,9 +405,8 @@ namespace System.Windows.Forms {
|
|
|
|
|
|
set {
|
|
|
if (vscroll_visible != value) {
|
|
|
- vscroll_visible = value;
|
|
|
- if (vscroll_visible && vscrollbar == null)
|
|
|
- vscrollbar = new VScrollBar ();
|
|
|
+ force_vscroll_visible = value;
|
|
|
+ Recalculate(this, EventArgs.Empty);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -359,17 +417,29 @@ namespace System.Windows.Forms {
|
|
|
}
|
|
|
|
|
|
public void SetAutoScrollMargin(int x, int y) {
|
|
|
+ if (x < 0) {
|
|
|
+ x = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (y < 0) {
|
|
|
+ y = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ auto_scroll_margin = new Size(x, y);
|
|
|
+ Recalculate(this, EventArgs.Empty);
|
|
|
}
|
|
|
#endregion // Public Instance Methods
|
|
|
|
|
|
#region Protected Instance Methods
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
|
protected virtual void AdjustFormScrollbars(bool displayScrollbars) {
|
|
|
+ // Internal MS
|
|
|
}
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
|
protected bool GetScrollState(int bit) {
|
|
|
- throw new NotImplementedException();
|
|
|
+ return false;
|
|
|
+ // Internal MS
|
|
|
}
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
|
@@ -379,6 +449,21 @@ namespace System.Windows.Forms {
|
|
|
|
|
|
[EditorBrowsable(EditorBrowsableState.Advanced)]
|
|
|
protected override void OnMouseWheel(MouseEventArgs e) {
|
|
|
+ if (vscroll_visible) {
|
|
|
+ if (e.Delta > 0) {
|
|
|
+ if (vscrollbar.Minimum < (vscrollbar.Value - vscrollbar.LargeChange)) {
|
|
|
+ vscrollbar.Value -= vscrollbar.LargeChange;
|
|
|
+ } else {
|
|
|
+ vscrollbar.Value = vscrollbar.Minimum;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (vscrollbar.Maximum > (vscrollbar.Value + vscrollbar.LargeChange)) {
|
|
|
+ vscrollbar.Value += vscrollbar.LargeChange;
|
|
|
+ } else {
|
|
|
+ vscrollbar.Value = vscrollbar.Maximum;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
base.OnMouseWheel(e);
|
|
|
}
|
|
|
|
|
|
@@ -404,5 +489,143 @@ namespace System.Windows.Forms {
|
|
|
base.WndProc(ref m);
|
|
|
}
|
|
|
#endregion // Protected Instance Methods
|
|
|
+
|
|
|
+ #region Internal & Private Methods
|
|
|
+ private Size Canvas {
|
|
|
+ get {
|
|
|
+ int num_of_children;
|
|
|
+ int width;
|
|
|
+ int height;
|
|
|
+
|
|
|
+ num_of_children = child_controls.Count;
|
|
|
+ width = 0;
|
|
|
+ height = 0;
|
|
|
+
|
|
|
+ for (int i = 0; i < num_of_children; i++) {
|
|
|
+ if ((child_controls[i].Visible == false) || (child_controls[i] == hscrollbar) || (child_controls[i] == vscrollbar) || (child_controls[i] == sizegrip)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (child_controls[i].Right > width) {
|
|
|
+ width = child_controls[i].Right;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (child_controls[i].Bottom > height) {
|
|
|
+ height = child_controls[i].Bottom;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return new Size(width, height);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void Recalculate(object sender, EventArgs e) {
|
|
|
+ Size canvas;
|
|
|
+ Size client;
|
|
|
+
|
|
|
+ // FIXME - this whole function begs for optimizations, all the math
|
|
|
+ // shouldn't have to be done over and over
|
|
|
+
|
|
|
+ // Check if we need scrollbars
|
|
|
+ if (!this.auto_scroll && !force_hscroll_visible && !force_vscroll_visible) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ canvas = Canvas;
|
|
|
+ client = ClientRectangle.Size;
|
|
|
+
|
|
|
+ canvas.Width += auto_scroll_margin.Width + SystemInformation.VerticalScrollBarWidth;
|
|
|
+ canvas.Height += auto_scroll_margin.Height + SystemInformation.HorizontalScrollBarHeight;
|
|
|
+
|
|
|
+ // || (scroll_position.X == 0 && scroll_position.Y == 0)
|
|
|
+
|
|
|
+ if ((canvas.Width >= client.Width) || (auto_scroll_min_size.Width > client.Width) || force_hscroll_visible) {
|
|
|
+ // Need horz
|
|
|
+
|
|
|
+ hscrollbar.Left = 0;
|
|
|
+ hscrollbar.Top = client.Height - SystemInformation.HorizontalScrollBarHeight;
|
|
|
+ hscrollbar.Maximum = Math.Max(0, canvas.Width - client.Width + SystemInformation.VerticalScrollBarWidth);
|
|
|
+
|
|
|
+ hscroll_visible = true;
|
|
|
+ } else {
|
|
|
+ hscroll_visible = false;
|
|
|
+ scroll_position.X = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((canvas.Height >= client.Height) || (auto_scroll_min_size.Height > client.Height) || force_vscroll_visible) {
|
|
|
+ // Need vert
|
|
|
+ vscrollbar.Left = client.Width - SystemInformation.VerticalScrollBarWidth;
|
|
|
+ vscrollbar.Top = 0;
|
|
|
+
|
|
|
+ // FIXME - Working around some scrollbar bugs here; shouldn't have to add the height again (see canvas+= above)
|
|
|
+ vscrollbar.Maximum = Math.Max(0, canvas.Height - client.Height + SystemInformation.HorizontalScrollBarHeight);
|
|
|
+ vscroll_visible = true;
|
|
|
+ } else {
|
|
|
+ vscroll_visible = false;
|
|
|
+ scroll_position.Y = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (hscroll_visible && vscroll_visible) {
|
|
|
+ hscrollbar.Width = ClientRectangle.Width - SystemInformation.VerticalScrollBarWidth;
|
|
|
+ vscrollbar.Height = ClientRectangle.Height - SystemInformation.HorizontalScrollBarHeight;
|
|
|
+
|
|
|
+ sizegrip.Left = hscrollbar.Right;
|
|
|
+ sizegrip.Top = vscrollbar.Bottom;
|
|
|
+ sizegrip.Width = SystemInformation.VerticalScrollBarWidth;
|
|
|
+ sizegrip.Height = SystemInformation.HorizontalScrollBarHeight;
|
|
|
+
|
|
|
+ hscrollbar.Visible = true;
|
|
|
+ vscrollbar.Visible = true;
|
|
|
+ sizegrip.Visible = true;
|
|
|
+ } else {
|
|
|
+ sizegrip.Visible = false;
|
|
|
+ if (hscroll_visible) {
|
|
|
+ hscrollbar.Width = ClientRectangle.Width;
|
|
|
+ hscrollbar.Visible = true;
|
|
|
+ } else {
|
|
|
+ hscrollbar.Visible = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vscroll_visible) {
|
|
|
+ vscrollbar.Height = ClientRectangle.Height;
|
|
|
+ vscrollbar.Visible = true;
|
|
|
+ } else {
|
|
|
+ vscrollbar.Visible = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void HandleScrollBar(object sender, EventArgs e) {
|
|
|
+ if (sender == vscrollbar) {
|
|
|
+ ScrollWindow(0, vscrollbar.Value- scroll_position.Y);
|
|
|
+ } else {
|
|
|
+ ScrollWindow(hscrollbar.Value - scroll_position.X, 0);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void ScrollWindow(int XOffset, int YOffset) {
|
|
|
+ int num_of_children;
|
|
|
+
|
|
|
+ SuspendLayout();
|
|
|
+
|
|
|
+ num_of_children = child_controls.Count;
|
|
|
+
|
|
|
+ for (int i = 0; i < num_of_children; i++) {
|
|
|
+ if (child_controls[i] == hscrollbar || child_controls[i] == vscrollbar || child_controls[i] == sizegrip) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ child_controls[i].Left -= XOffset;
|
|
|
+ child_controls[i].Top -= YOffset;
|
|
|
+ // Is this faster? child_controls[i].Location -= new Size(XOffset, YOffset);
|
|
|
+ }
|
|
|
+
|
|
|
+ scroll_position.X += XOffset;
|
|
|
+ scroll_position.Y += YOffset;
|
|
|
+
|
|
|
+ // Should we call XplatUI.ScrollWindow???
|
|
|
+ Invalidate();
|
|
|
+ ResumeLayout();
|
|
|
+ }
|
|
|
+ #endregion // Internal & Private Methods
|
|
|
+
|
|
|
}
|
|
|
}
|