1 // Permission is hereby granted, free of charge, to any person obtaining
2 // a copy of this software and associated documentation files (the
3 // "Software"), to deal in the Software without restriction, including
4 // without limitation the rights to use, copy, modify, merge, publish,
5 // distribute, sublicense, and/or sell copies of the Software, and to
6 // permit persons to whom the Software is furnished to do so, subject to
7 // the following conditions:
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
12 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
16 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
17 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
18 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 // Copyright (c) 2004 Novell, Inc.
23 // Peter Bartok pbartok@novell.com
27 using System.ComponentModel;
28 using System.ComponentModel.Design;
30 using System.Runtime.InteropServices;
32 namespace System.Windows.Forms {
33 [Designer ("System.Windows.Forms.Design.ScrollableControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
35 [ClassInterface (ClassInterfaceType.AutoDispatch)]
38 public class ScrollableControl : Control {
39 #region Local Variables
40 private bool force_hscroll_visible;
41 private bool force_vscroll_visible;
42 private bool auto_scroll;
43 private Size auto_scroll_margin;
44 private Size auto_scroll_min_size;
45 private Point scroll_position;
46 private DockPaddingEdges dock_padding;
47 private SizeGrip sizegrip;
48 internal ImplicitHScrollBar hscrollbar;
49 internal ImplicitVScrollBar vscrollbar;
50 private Size canvas_size;
51 private Rectangle display_rectangle;
52 private Control old_parent;
55 private HScrollProperties horizontalScroll;
56 private VScrollProperties verticalScroll;
58 #endregion // Local Variables
60 [TypeConverter(typeof(ScrollableControl.DockPaddingEdgesConverter))]
61 #region Subclass DockPaddingEdges
62 public class DockPaddingEdges : ICloneable {
63 #region DockPaddingEdges Local Variables
69 private Control owner;
70 #endregion // DockPaddingEdges Local Variables
72 #region DockPaddingEdges Constructor
73 internal DockPaddingEdges(Control owner) {
81 #endregion // DockPaddingEdges Constructor
83 #region DockPaddingEdges Public Instance Properties
84 [RefreshProperties(RefreshProperties.All)]
97 owner.PerformLayout();
101 [RefreshProperties(RefreshProperties.All)]
111 owner.PerformLayout();
115 [RefreshProperties(RefreshProperties.All)]
125 owner.PerformLayout();
129 [RefreshProperties(RefreshProperties.All)]
139 owner.PerformLayout();
143 [RefreshProperties(RefreshProperties.All)]
153 owner.PerformLayout();
156 #endregion // DockPaddingEdges Public Instance Properties
158 // Public Instance Methods
159 public override bool Equals(object other) {
160 if (! (other is DockPaddingEdges)) {
164 if ( (this.all == ((DockPaddingEdges)other).all) && (this.left == ((DockPaddingEdges)other).left) &&
165 (this.right == ((DockPaddingEdges)other).right) && (this.top == ((DockPaddingEdges)other).top) &&
166 (this.bottom == ((DockPaddingEdges)other).bottom)) {
173 public override int GetHashCode() {
174 return all*top*bottom*right*left;
177 public override string ToString() {
178 return "All = "+all.ToString()+" Top = "+top.ToString()+" Left = "+left.ToString()+" Bottom = "+bottom.ToString()+" Right = "+right.ToString();
181 internal void Scale(float dx, float dy) {
182 left = (int) (left * dx);
183 right = (int) (right * dx);
184 top = (int) (top * dy);
185 bottom = (int) (bottom * dy);
188 object ICloneable.Clone() {
189 DockPaddingEdges padding_edge;
191 padding_edge=new DockPaddingEdges(owner);
193 padding_edge.all=all;
194 padding_edge.left=left;
195 padding_edge.right=right;
196 padding_edge.top=top;
197 padding_edge.bottom=bottom;
202 #endregion // Subclass DockPaddingEdges
204 #region Subclass DockPaddingEdgesConverter
205 public class DockPaddingEdgesConverter : System.ComponentModel.TypeConverter {
206 // Public Constructors
207 public DockPaddingEdgesConverter() {
210 // Public Instance Methods
211 public override PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, Attribute[] attributes) {
212 return TypeDescriptor.GetProperties(typeof(DockPaddingEdges), attributes);
215 public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) {
219 #endregion // Subclass DockPaddingEdgesConverter
221 #region Public Constructors
222 public ScrollableControl() {
223 SetStyle(ControlStyles.ContainerControl, true);
224 SetStyle(ControlStyles.AllPaintingInWmPaint, false);
227 force_hscroll_visible = false;
228 force_vscroll_visible = false;
229 auto_scroll_margin = new Size(0, 0);
230 auto_scroll_min_size = new Size(0, 0);
231 scroll_position = new Point(0, 0);
232 dock_padding = new DockPaddingEdges(this);
233 SizeChanged +=new EventHandler(Recalculate);
234 VisibleChanged += new EventHandler (VisibleChangedHandler);
235 LocationChanged += new EventHandler (LocationChangedHandler);
236 ParentChanged += new EventHandler (ParentChangedHandler);
237 HandleCreated += new EventHandler (AddScrollbars);
242 horizontalScroll = new HScrollProperties (this);
243 verticalScroll = new VScrollProperties (this);
247 void VisibleChangedHandler (object sender, EventArgs e)
252 void LocationChangedHandler (object sender, EventArgs e)
254 UpdateSizeGripVisible ();
257 void ParentChangedHandler (object sender, EventArgs e)
260 if (old_parent == Parent)
263 if (old_parent != null) {
264 old_parent.SizeChanged -= new EventHandler (Parent_SizeChanged);
266 old_parent.PaddingChanged -= new EventHandler (Parent_PaddingChanged);
270 if (Parent != null) {
271 Parent.SizeChanged += new EventHandler (Parent_SizeChanged);
273 Parent.PaddingChanged += new EventHandler (Parent_PaddingChanged);
280 void Parent_PaddingChanged (object sender, EventArgs e)
282 UpdateSizeGripVisible ();
285 void Parent_SizeChanged (object sender, EventArgs e)
287 UpdateSizeGripVisible ();
289 #endregion // Public Constructors
291 #region Protected Static Fields
292 protected const int ScrollStateAutoScrolling = 1;
293 protected const int ScrollStateFullDrag = 16;
294 protected const int ScrollStateHScrollVisible = 2;
295 protected const int ScrollStateUserHasScrolled = 8;
296 protected const int ScrollStateVScrollVisible = 4;
297 #endregion // Protected Static Fields
299 #region Public Instance Properties
300 [DefaultValue(false)]
302 [MWFCategory("Layout")]
303 public virtual bool AutoScroll {
309 if (auto_scroll == value) {
318 [MWFCategory("Layout")]
319 public Size AutoScrollMargin {
321 return auto_scroll_margin;
325 if (value.Width < 0) {
326 throw new ArgumentException("Width is assigned less than 0", "value.Width");
329 if (value.Height < 0) {
330 throw new ArgumentException("Height is assigned less than 0", "value.Height");
333 auto_scroll_margin = value;
338 [MWFCategory("Layout")]
339 public Size AutoScrollMinSize {
341 return auto_scroll_min_size;
345 if (value != auto_scroll_min_size) {
346 auto_scroll_min_size = value;
353 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
354 public Point AutoScrollPosition {
356 return new Point(-scroll_position.X, -scroll_position.Y);
360 if ((value.X != scroll_position.X) || (value.Y != scroll_position.Y)) {
366 if (hscrollbar.VisibleInternal) {
367 shift_x = value.X - scroll_position.X;
370 if (vscrollbar.VisibleInternal) {
371 shift_y = value.Y - scroll_position.Y;
374 ScrollWindow(shift_x, shift_y);
376 if (hscrollbar.VisibleInternal) {
377 hscrollbar.Value = scroll_position.X;
380 if (vscrollbar.VisibleInternal) {
381 vscrollbar.Value = scroll_position.Y;
388 public override Rectangle DisplayRectangle {
394 if (canvas_size.Width <= base.DisplayRectangle.Width) {
395 width = base.DisplayRectangle.Width;
396 if (vscrollbar.VisibleInternal) {
397 width -= vscrollbar.Width;
400 width = canvas_size.Width;
403 if (canvas_size.Height <= base.DisplayRectangle.Height) {
404 height = base.DisplayRectangle.Height;
405 if (hscrollbar.VisibleInternal) {
406 height -= hscrollbar.Height;
409 height = canvas_size.Height;
412 display_rectangle.X = -scroll_position.X;
413 display_rectangle.Y = -scroll_position.Y;
414 display_rectangle.Width = Math.Max(auto_scroll_min_size.Width, width);
415 display_rectangle.Height = Math.Max(auto_scroll_min_size.Height, height);
418 display_rectangle = base.DisplayRectangle;
421 display_rectangle.X += dock_padding.Left;
422 display_rectangle.Y += dock_padding.Top;
423 display_rectangle.Width -= dock_padding.Left + dock_padding.Right;
424 display_rectangle.Height -= dock_padding.Top + dock_padding.Bottom;
426 return display_rectangle;
430 [MWFCategory("Layout")]
433 [EditorBrowsable (EditorBrowsableState.Never)]
434 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
436 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
439 public DockPaddingEdges DockPadding {
447 [EditorBrowsable (EditorBrowsableState.Always)]
448 public HScrollProperties HorizontalScroll {
449 get { return horizontalScroll; }
453 [EditorBrowsable (EditorBrowsableState.Always)]
454 public VScrollProperties VerticalScroll {
455 get { return verticalScroll; }
458 #endregion // Public Instance Properties
460 #region Protected Instance Methods
461 protected override CreateParams CreateParams {
463 return base.CreateParams;
467 protected bool HScroll {
469 return hscrollbar.VisibleInternal;
473 if (hscrollbar.VisibleInternal != value) {
474 force_hscroll_visible = value;
480 protected bool VScroll {
482 return vscrollbar.VisibleInternal;
486 if (vscrollbar.VisibleInternal != value) {
487 force_vscroll_visible = value;
492 #endregion // Protected Instance Methods
494 #region Public Instance Methods
495 public void ScrollControlIntoView(Control activeControl) {
499 Rectangle within = new Rectangle ();
500 within.Size = ClientSize;
502 if (!AutoScroll || (!hscrollbar.VisibleInternal && !vscrollbar.VisibleInternal)) {
506 if (!Contains(activeControl)) {
510 if (vscrollbar.Visible) {
511 within.Width -= vscrollbar.Width;
513 if (hscrollbar.Visible) {
514 within.Height -= hscrollbar.Height;
517 // Don't scroll if already visible
518 if (within.Contains (activeControl.Location) && within.Contains (activeControl.Right, activeControl.Bottom)) {
522 // If the control is above the top or the left, move it down and right until it aligns
523 // with the top/left.
524 // If the control is below the bottom or to the right, move it up/left until it aligns
525 // with the bottom/right, but do never move it further than the top/left side.
526 int x_diff = 0, y_diff = 0;
527 if (activeControl.Top <= 0 || activeControl.Height >= within.Height) {
528 y_diff = -activeControl.Top;
529 } else if (activeControl.Bottom > within.Height) {
530 y_diff = within.Height - activeControl.Bottom;
532 if (activeControl.Left <= 0 || activeControl.Width >= within.Width) {
533 x_diff = -activeControl.Left;
534 } else if (activeControl.Right > within.Width) {
535 x_diff = within.Width - activeControl.Right;
537 corner_x = hscrollbar.Value - x_diff;
538 corner_y = vscrollbar.Value - y_diff;
540 if (hscrollbar.VisibleInternal) {
541 if (corner_x > hscrollbar.Maximum) {
542 corner_x = hscrollbar.Maximum;
543 } else if (corner_x < hscrollbar.Minimum) {
544 corner_x = hscrollbar.Minimum;
546 if (corner_x != hscrollbar.Value) {
547 hscrollbar.Value = corner_x;
551 if (vscrollbar.VisibleInternal) {
552 if (corner_y > vscrollbar.Maximum) {
553 corner_y = vscrollbar.Maximum;
554 } else if (corner_y < vscrollbar.Minimum) {
555 corner_y = vscrollbar.Minimum;
557 if (corner_y != vscrollbar.Value) {
558 vscrollbar.Value = corner_y;
563 public void SetAutoScrollMargin(int x, int y) {
572 auto_scroll_margin = new Size(x, y);
575 #endregion // Public Instance Methods
577 #region Protected Instance Methods
578 [EditorBrowsable(EditorBrowsableState.Advanced)]
579 protected virtual void AdjustFormScrollbars(bool displayScrollbars) {
583 [EditorBrowsable(EditorBrowsableState.Advanced)]
584 protected bool GetScrollState(int bit) {
589 [EditorBrowsable(EditorBrowsableState.Advanced)]
590 protected override void OnLayout(LayoutEventArgs levent) {
591 CalculateCanvasSize();
593 AdjustFormScrollbars(AutoScroll); // Dunno what the logic is. Passing AutoScroll seems to match MS behaviour
594 base.OnLayout(levent);
597 [EditorBrowsable(EditorBrowsableState.Advanced)]
598 protected override void OnMouseWheel(MouseEventArgs e) {
599 if (vscrollbar.VisibleInternal) {
601 if (vscrollbar.Minimum < (vscrollbar.Value - vscrollbar.LargeChange)) {
602 vscrollbar.Value -= vscrollbar.LargeChange;
604 vscrollbar.Value = vscrollbar.Minimum;
607 int maximum_scrollbar_value = vscrollbar.Maximum - vscrollbar.LargeChange + 1;
608 if (maximum_scrollbar_value > (vscrollbar.Value + vscrollbar.LargeChange)) {
609 vscrollbar.Value += vscrollbar.LargeChange;
611 vscrollbar.Value = maximum_scrollbar_value;
615 base.OnMouseWheel(e);
618 [EditorBrowsable(EditorBrowsableState.Advanced)]
619 protected override void OnVisibleChanged(EventArgs e) {
621 UpdateChildrenZOrder ();
622 PerformLayout(this, "Visible");
624 base.OnVisibleChanged(e);
628 [EditorBrowsable (EditorBrowsableState.Never)]
630 protected override void ScaleCore(float dx, float dy) {
631 dock_padding.Scale(dx, dy);
632 base.ScaleCore(dx, dy);
636 protected override void ScaleControl (SizeF factor, BoundsSpecified specified)
638 base.ScaleControl (factor, specified);
641 protected virtual Point ScrollToControl (Control activeControl)
646 Rectangle within = new Rectangle ();
647 within.Size = ClientSize;
649 if (vscrollbar.Visible)
650 within.Width -= vscrollbar.Width;
652 if (hscrollbar.Visible)
653 within.Height -= hscrollbar.Height;
655 // If the control is above the top or the left, move it down and right until it aligns
656 // with the top/left.
657 // If the control is below the bottom or to the right, move it up/left until it aligns
658 // with the bottom/right, but do never move it further than the top/left side.
659 int x_diff = 0, y_diff = 0;
661 if (activeControl.Top <= 0 || activeControl.Height >= within.Height)
662 y_diff = -activeControl.Top;
663 else if (activeControl.Bottom > within.Height)
664 y_diff = within.Height - activeControl.Bottom;
666 if (activeControl.Left <= 0 || activeControl.Width >= within.Width)
667 x_diff = -activeControl.Left;
668 else if (activeControl.Right > within.Width)
669 x_diff = within.Width - activeControl.Right;
671 corner_x = AutoScrollPosition.X + x_diff;
672 corner_y = AutoScrollPosition.Y + y_diff;
674 return new Point (corner_x, corner_y);
678 protected void SetDisplayRectLocation(int x, int y) {
679 // This method is weird. MS documents that the scrollbars are not
680 // updated. We need to move stuff, but leave the scrollbars as is
690 ScrollWindow(scroll_position.X - x , scroll_position.Y - y);
693 protected void SetScrollState(int bit, bool value) {
694 //throw new NotImplementedException();
697 [EditorBrowsable(EditorBrowsableState.Advanced)]
698 protected override void WndProc(ref Message m) {
701 #endregion // Protected Instance Methods
703 #region Internal & Private Methods
704 internal override IntPtr AfterTopMostControl ()
706 // order of scrollbars:
709 // bottom = horizontal
710 if (hscrollbar != null && hscrollbar.Visible)
711 return hscrollbar.Handle;
712 // no need to check for sizegrip since it will only
713 // be visible if hbar is visible.
714 if (vscrollbar != null && vscrollbar.Visible)
715 return hscrollbar.Handle;
717 return base.AfterTopMostControl ();
720 private void CalculateCanvasSize() {
728 num_of_children = Controls.Count;
731 extra_width = dock_padding.Right + hscrollbar.Value;
732 extra_height = dock_padding.Bottom + vscrollbar.Value;
734 for (int i = 0; i < num_of_children; i++) {
736 if (child.Dock == DockStyle.Right) {
737 extra_width += child.Width;
738 } else if (child.Dock == DockStyle.Bottom) {
739 extra_height += child.Height;
743 if (!auto_scroll_min_size.IsEmpty) {
744 width = auto_scroll_min_size.Width;
745 height = auto_scroll_min_size.Height;
748 for (int i = 0; i < num_of_children; i++) {
752 case DockStyle.Left: {
753 if ((child.Right + extra_width) > width) {
754 width = child.Right + extra_width;
759 case DockStyle.Top: {
760 if ((child.Bottom + extra_height) > height) {
761 height = child.Bottom + extra_height;
767 case DockStyle.Right:
768 case DockStyle.Bottom: {
775 anchor = child.Anchor;
777 if (((anchor & AnchorStyles.Left) != 0) && ((anchor & AnchorStyles.Right) == 0)) {
778 if ((child.Right + extra_width) > width) {
779 width = child.Right + extra_width;
783 if (((anchor & AnchorStyles.Top) != 0) || ((anchor & AnchorStyles.Bottom) == 0)) {
784 if ((child.Bottom + extra_height) > height) {
785 height = child.Bottom + extra_height;
793 canvas_size.Width = width;
794 canvas_size.Height = height;
797 private void Recalculate (object sender, EventArgs e) {
801 private void Recalculate (bool doLayout) {
802 if (!IsHandleCreated) {
806 Size canvas = canvas_size;
807 Size client = ClientSize;
809 canvas.Width += auto_scroll_margin.Width;
810 canvas.Height += auto_scroll_margin.Height;
812 int right_edge = client.Width;
813 int bottom_edge = client.Height;
815 int prev_bottom_edge;
817 bool hscroll_visible;
818 bool vscroll_visible;
821 prev_right_edge = right_edge;
822 prev_bottom_edge = bottom_edge;
824 if ((force_hscroll_visible || (canvas.Width > right_edge && auto_scroll)) && client.Width > 0) {
825 hscroll_visible = true;
826 bottom_edge = client.Height - SystemInformation.HorizontalScrollBarHeight;
828 hscroll_visible = false;
829 bottom_edge = client.Height;
832 if ((force_vscroll_visible || (canvas.Height > bottom_edge && auto_scroll)) && client.Height > 0) {
833 vscroll_visible = true;
834 right_edge = client.Width - SystemInformation.VerticalScrollBarWidth;
836 vscroll_visible = false;
837 right_edge = client.Width;
840 } while (right_edge != prev_right_edge || bottom_edge != prev_bottom_edge);
842 if (right_edge < 0) right_edge = 0;
843 if (bottom_edge < 0) bottom_edge = 0;
845 Rectangle hscroll_bounds;
846 Rectangle vscroll_bounds;
848 hscroll_bounds = new Rectangle (0, client.Height - SystemInformation.HorizontalScrollBarHeight,
849 ClientRectangle.Width, SystemInformation.HorizontalScrollBarHeight);
850 vscroll_bounds = new Rectangle (client.Width - SystemInformation.VerticalScrollBarWidth, 0,
851 SystemInformation.VerticalScrollBarWidth, ClientRectangle.Height);
853 /* the ScrollWindow calls here are needed
854 * because (this explanation sucks):
856 * when we transition from having a scrollbar to
857 * not having one, we won't receive a scrollbar
858 * moved (value changed) event, so we need to
859 * manually scroll the canvas.
861 * if you can fix this without requiring the
862 * ScrollWindow calls, pdb and toshok will each
866 if (!vscrollbar.Visible) {
867 vscrollbar.Value = 0;
869 if (!hscrollbar.Visible) {
870 hscrollbar.Value = 0;
873 if (hscroll_visible) {
874 hscrollbar.LargeChange = right_edge;
875 hscrollbar.SmallChange = 5;
876 hscrollbar.Maximum = canvas.Width - 1;
878 if (hscrollbar != null && hscrollbar.VisibleInternal) {
879 ScrollWindow (- scroll_position.X, 0);
881 scroll_position.X = 0;
884 if (vscroll_visible) {
885 vscrollbar.LargeChange = bottom_edge;
886 vscrollbar.SmallChange = 5;
887 vscrollbar.Maximum = canvas.Height - 1;
889 if (vscrollbar != null && vscrollbar.VisibleInternal) {
890 ScrollWindow (0, - scroll_position.Y);
892 scroll_position.Y = 0;
895 if (hscroll_visible && vscroll_visible) {
896 hscroll_bounds.Width -= SystemInformation.VerticalScrollBarWidth;
897 vscroll_bounds.Height -= SystemInformation.HorizontalScrollBarHeight;
899 sizegrip.Bounds = new Rectangle (hscroll_bounds.Right,
900 vscroll_bounds.Bottom,
901 SystemInformation.VerticalScrollBarWidth,
902 SystemInformation.HorizontalScrollBarHeight);
907 hscrollbar.Bounds = hscroll_bounds;
908 hscrollbar.Visible = hscroll_visible;
909 if (hscrollbar.Visible)
910 XplatUI.SetZOrder (hscrollbar.Handle, IntPtr.Zero, true, false);
912 vscrollbar.Bounds = vscroll_bounds;
913 vscrollbar.Visible = vscroll_visible;
914 if (vscrollbar.Visible)
915 XplatUI.SetZOrder (vscrollbar.Handle, IntPtr.Zero, true, false);
917 UpdateSizeGripVisible ();
919 ResumeLayout (doLayout);
921 // We should now scroll the active control into view,
922 // the funny part is that ScrollableControl does not have
923 // the concept of active control.
924 ContainerControl container = this as ContainerControl;
925 if (container != null && container.ActiveControl != null) {
926 ScrollControlIntoView (container.ActiveControl);
930 internal void UpdateSizeGripVisible ()
932 if (!IsHandleCreated) {
936 sizegrip.CapturedControl = Parent;
937 // This is really wierd, the size grip is only showing up
938 // if the bottom right corner of the scrollable control is within
939 // two pixels from the bottom right corner of its parent.
940 bool show_sizegrip = hscrollbar.VisibleInternal && vscrollbar.VisibleInternal;
941 bool enable_sizegrip = false;
942 if (show_sizegrip && Parent != null) {
943 Point diff = new Point (Parent.ClientRectangle.Bottom - Bottom, Parent.ClientRectangle.Right - Right);
944 enable_sizegrip = diff.X <= 2 && diff.X >= 0 && diff.Y <= 2 && diff.Y >= 0;
946 sizegrip.Visible = show_sizegrip;
947 sizegrip.Enabled = enable_sizegrip || sizegrip.Capture;
948 if (sizegrip.Visible)
949 XplatUI.SetZOrder (sizegrip.Handle, vscrollbar.Handle, false, false);
952 private void HandleScrollBar(object sender, EventArgs e) {
953 if (sender == vscrollbar) {
954 if (!vscrollbar.Visible)
956 ScrollWindow(0, vscrollbar.Value- scroll_position.Y);
958 if (!hscrollbar.Visible)
960 ScrollWindow(hscrollbar.Value - scroll_position.X, 0);
964 private void AddScrollbars (object o, EventArgs e)
966 Controls.AddRangeImplicit (new Control[] {hscrollbar, vscrollbar, sizegrip});
967 HandleCreated -= new EventHandler (AddScrollbars);
970 private void CreateScrollbars ()
972 hscrollbar = new ImplicitHScrollBar ();
973 hscrollbar.Visible = false;
974 hscrollbar.ValueChanged += new EventHandler (HandleScrollBar);
975 hscrollbar.Height = SystemInformation.HorizontalScrollBarHeight;
977 vscrollbar = new ImplicitVScrollBar ();
978 vscrollbar.Visible = false;
979 vscrollbar.ValueChanged += new EventHandler (HandleScrollBar);
980 vscrollbar.Width = SystemInformation.VerticalScrollBarWidth;
982 sizegrip = new SizeGrip (this);
983 sizegrip.Visible = false;
986 private void ScrollWindow(int XOffset, int YOffset) {
989 if (XOffset == 0 && YOffset == 0) {
995 num_of_children = Controls.Count;
997 for (int i = 0; i < num_of_children; i++) {
998 Controls[i].Location = new Point (Controls[i].Left - XOffset, Controls[i].Top - YOffset);
999 //Controls[i].Left -= XOffset;
1000 //Controls[i].Top -= YOffset;
1001 // Is this faster? Controls[i].Location -= new Size(XOffset, YOffset);
1004 scroll_position.X += XOffset;
1005 scroll_position.Y += YOffset;
1007 // Should we call XplatUI.ScrollWindow??? If so, we need to position our windows by other means above
1008 // Since we're already causing a redraw above
1010 ResumeLayout(false);
1012 #endregion // Internal & Private Methods
1015 static object OnScrollEvent = new object ();
1017 protected virtual void OnScroll (ScrollEventArgs se)
1019 EventHandler eh = (EventHandler) (Events [OnScrollEvent]);
1024 protected override void OnPaddingChanged (EventArgs e)
1026 base.OnPaddingChanged (e);
1029 protected override void OnPaintBackground (PaintEventArgs e)
1031 base.OnPaintBackground (e);
1034 [EditorBrowsable (EditorBrowsableState.Advanced)]
1035 protected override void OnRightToLeftChanged (EventArgs e)
1037 base.OnRightToLeftChanged (e);
1040 public event ScrollEventHandler Scroll {
1041 add { Events.AddHandler (OnScrollEvent, value); }
1042 remove { Events.RemoveHandler (OnScrollEvent, value); }