2007-03-19 Chris Toshok <toshok@ximian.com>
[mono-project.git] / mcs / class / Managed.Windows.Forms / System.Windows.Forms / ScrollableControl.cs
blobd40697c6002b4f266e48017b8342f4679e82ff8b
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:
8 //
9 // The above copyright notice and this permission notice shall be
10 // included in all copies or substantial portions of the Software.
11 //
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.
22 // Authors:
23 // Peter Bartok pbartok@novell.com
26 using System;
27 using System.ComponentModel;
28 using System.ComponentModel.Design;
29 using System.Drawing;
30 using System.Runtime.InteropServices;
32 namespace System.Windows.Forms {
33 [Designer ("System.Windows.Forms.Design.ScrollableControlDesigner, " + Consts.AssemblySystem_Design, "System.ComponentModel.Design.IDesigner")]
34 #if NET_2_0
35 [ClassInterface (ClassInterfaceType.AutoDispatch)]
36 [ComVisible (true)]
37 #endif
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 private ImplicitHScrollBar hscrollbar;
49 private ImplicitVScrollBar vscrollbar;
50 private Size canvas_size;
51 private Rectangle display_rectangle;
52 private Control old_parent;
53 #endregion // Local Variables
55 [TypeConverter(typeof(ScrollableControl.DockPaddingEdgesConverter))]
56 #region Subclass DockPaddingEdges
57 public class DockPaddingEdges : ICloneable {
58 #region DockPaddingEdges Local Variables
59 private int all;
60 private int left;
61 private int right;
62 private int top;
63 private int bottom;
64 private Control owner;
65 #endregion // DockPaddingEdges Local Variables
67 #region DockPaddingEdges Constructor
68 internal DockPaddingEdges(Control owner) {
69 all = 0;
70 left = 0;
71 right = 0;
72 top = 0;
73 bottom = 0;
74 this.owner = owner;
76 #endregion // DockPaddingEdges Constructor
78 #region DockPaddingEdges Public Instance Properties
79 [RefreshProperties(RefreshProperties.All)]
80 public int All {
81 get {
82 return all;
85 set {
86 all = value;
87 left = value;
88 right = value;
89 top = value;
90 bottom = value;
92 owner.PerformLayout();
96 [RefreshProperties(RefreshProperties.All)]
97 public int Bottom {
98 get {
99 return bottom;
102 set {
103 bottom = value;
104 all = 0;
106 owner.PerformLayout();
110 [RefreshProperties(RefreshProperties.All)]
111 public int Left {
112 get {
113 return left;
116 set {
117 left=value;
118 all = 0;
120 owner.PerformLayout();
124 [RefreshProperties(RefreshProperties.All)]
125 public int Right {
126 get {
127 return right;
130 set {
131 right=value;
132 all = 0;
134 owner.PerformLayout();
138 [RefreshProperties(RefreshProperties.All)]
139 public int Top {
140 get {
141 return top;
144 set {
145 top=value;
146 all = 0;
148 owner.PerformLayout();
151 #endregion // DockPaddingEdges Public Instance Properties
153 // Public Instance Methods
154 public override bool Equals(object other) {
155 if (! (other is DockPaddingEdges)) {
156 return false;
159 if ( (this.all == ((DockPaddingEdges)other).all) && (this.left == ((DockPaddingEdges)other).left) &&
160 (this.right == ((DockPaddingEdges)other).right) && (this.top == ((DockPaddingEdges)other).top) &&
161 (this.bottom == ((DockPaddingEdges)other).bottom)) {
162 return true;
165 return false;
168 public override int GetHashCode() {
169 return all*top*bottom*right*left;
172 public override string ToString() {
173 return "All = "+all.ToString()+" Top = "+top.ToString()+" Left = "+left.ToString()+" Bottom = "+bottom.ToString()+" Right = "+right.ToString();
176 internal void Scale(float dx, float dy) {
177 left = (int) (left * dx);
178 right = (int) (right * dx);
179 top = (int) (top * dy);
180 bottom = (int) (bottom * dy);
183 object ICloneable.Clone() {
184 DockPaddingEdges padding_edge;
186 padding_edge=new DockPaddingEdges(owner);
188 padding_edge.all=all;
189 padding_edge.left=left;
190 padding_edge.right=right;
191 padding_edge.top=top;
192 padding_edge.bottom=bottom;
194 return padding_edge;
197 #endregion // Subclass DockPaddingEdges
199 #region Subclass DockPaddingEdgesConverter
200 public class DockPaddingEdgesConverter : System.ComponentModel.TypeConverter {
201 // Public Constructors
202 public DockPaddingEdgesConverter() {
205 // Public Instance Methods
206 public override PropertyDescriptorCollection GetProperties(System.ComponentModel.ITypeDescriptorContext context, object value, Attribute[] attributes) {
207 return TypeDescriptor.GetProperties(typeof(DockPaddingEdges), attributes);
210 public override bool GetPropertiesSupported(System.ComponentModel.ITypeDescriptorContext context) {
211 return true;
214 #endregion // Subclass DockPaddingEdgesConverter
216 #region Public Constructors
217 public ScrollableControl() {
218 SetStyle(ControlStyles.ContainerControl, true);
219 SetStyle(ControlStyles.AllPaintingInWmPaint, false);
221 auto_scroll = false;
222 force_hscroll_visible = false;
223 force_vscroll_visible = false;
224 auto_scroll_margin = new Size(0, 0);
225 auto_scroll_min_size = new Size(0, 0);
226 scroll_position = new Point(0, 0);
227 dock_padding = new DockPaddingEdges(this);
228 SizeChanged +=new EventHandler(Recalculate);
229 VisibleChanged += new EventHandler(Recalculate);
230 LocationChanged += new EventHandler (LocationChangedHandler);
231 ParentChanged += new EventHandler (ParentChangedHandler);
233 CreateScrollbars ();
236 void LocationChangedHandler (object sender, EventArgs e)
238 UpdateSizeGripVisible ();
241 void ParentChangedHandler (object sender, EventArgs e)
244 if (old_parent == Parent)
245 return;
247 if (old_parent != null) {
248 old_parent.SizeChanged -= new EventHandler (Parent_SizeChanged);
249 #if NET_2_0
250 old_parent.PaddingChanged -= new EventHandler (Parent_PaddingChanged);
251 #endif
254 if (Parent != null) {
255 Parent.SizeChanged += new EventHandler (Parent_SizeChanged);
256 #if NET_2_0
257 Parent.PaddingChanged += new EventHandler (Parent_PaddingChanged);
258 #endif
261 old_parent = Parent;
263 #if NET_2_0
264 void Parent_PaddingChanged (object sender, EventArgs e)
266 UpdateSizeGripVisible ();
268 #endif
269 void Parent_SizeChanged (object sender, EventArgs e)
271 UpdateSizeGripVisible ();
273 #endregion // Public Constructors
275 #region Protected Static Fields
276 protected const int ScrollStateAutoScrolling = 1;
277 protected const int ScrollStateFullDrag = 16;
278 protected const int ScrollStateHScrollVisible = 2;
279 protected const int ScrollStateUserHasScrolled = 8;
280 protected const int ScrollStateVScrollVisible = 4;
281 #endregion // Protected Static Fields
283 #region Public Instance Properties
284 [DefaultValue(false)]
285 [Localizable(true)]
286 [MWFCategory("Layout")]
287 public virtual bool AutoScroll {
288 get {
289 return auto_scroll;
292 set {
293 if (auto_scroll == value) {
294 return;
297 auto_scroll = value;
301 [Localizable(true)]
302 [MWFCategory("Layout")]
303 public Size AutoScrollMargin {
304 get {
305 return auto_scroll_margin;
308 set {
309 if (value.Width < 0) {
310 throw new ArgumentException("Width is assigned less than 0", "value.Width");
313 if (value.Height < 0) {
314 throw new ArgumentException("Height is assigned less than 0", "value.Height");
317 auto_scroll_margin = value;
321 [Localizable(true)]
322 [MWFCategory("Layout")]
323 public Size AutoScrollMinSize {
324 get {
325 return auto_scroll_min_size;
328 set {
329 if (value != auto_scroll_min_size) {
330 auto_scroll_min_size = value;
331 AutoScroll = true;
336 [Browsable(false)]
337 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
338 public Point AutoScrollPosition {
339 get {
340 return new Point(-scroll_position.X, -scroll_position.Y);
343 set {
344 if ((value.X != scroll_position.X) || (value.Y != scroll_position.Y)) {
345 int shift_x;
346 int shift_y;
348 shift_x = 0;
349 shift_y = 0;
350 if (hscrollbar.VisibleInternal) {
351 shift_x = value.X - scroll_position.X;
354 if (vscrollbar.VisibleInternal) {
355 shift_y = value.Y - scroll_position.Y;
358 ScrollWindow(shift_x, shift_y);
360 if (hscrollbar.VisibleInternal) {
361 hscrollbar.Value = scroll_position.X;
364 if (vscrollbar.VisibleInternal) {
365 vscrollbar.Value = scroll_position.Y;
372 public override Rectangle DisplayRectangle {
373 get {
374 if (auto_scroll) {
375 int width;
376 int height;
378 if (canvas_size.Width <= base.DisplayRectangle.Width) {
379 width = base.DisplayRectangle.Width;
380 if (vscrollbar.VisibleInternal) {
381 width -= vscrollbar.Width;
383 } else {
384 width = canvas_size.Width;
387 if (canvas_size.Height <= base.DisplayRectangle.Height) {
388 height = base.DisplayRectangle.Height;
389 if (hscrollbar.VisibleInternal) {
390 height -= hscrollbar.Height;
392 } else {
393 height = canvas_size.Height;
396 display_rectangle.X = -scroll_position.X;
397 display_rectangle.Y = -scroll_position.Y;
398 display_rectangle.Width = Math.Max(auto_scroll_min_size.Width, width);
399 display_rectangle.Height = Math.Max(auto_scroll_min_size.Height, height);
401 else {
402 display_rectangle = base.DisplayRectangle;
405 display_rectangle.X += dock_padding.Left;
406 display_rectangle.Y += dock_padding.Top;
407 display_rectangle.Width -= dock_padding.Left + dock_padding.Right;
408 display_rectangle.Height -= dock_padding.Top + dock_padding.Bottom;
410 return display_rectangle;
414 [MWFCategory("Layout")]
415 #if NET_2_0
416 [Browsable (false)]
417 [EditorBrowsable (EditorBrowsableState.Never)]
418 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
419 #else
420 [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
421 [Localizable(true)]
422 #endif
423 public DockPaddingEdges DockPadding {
424 get {
425 return dock_padding;
428 #endregion // Public Instance Properties
430 #region Protected Instance Methods
431 protected override CreateParams CreateParams {
432 get {
433 return base.CreateParams;
437 protected bool HScroll {
438 get {
439 return hscrollbar.VisibleInternal;
442 set {
443 if (hscrollbar.VisibleInternal != value) {
444 force_hscroll_visible = value;
445 Recalculate(this, EventArgs.Empty);
450 protected bool VScroll {
451 get {
452 return vscrollbar.VisibleInternal;
455 set {
456 if (vscrollbar.VisibleInternal != value) {
457 force_vscroll_visible = value;
458 Recalculate(this, EventArgs.Empty);
462 #endregion // Protected Instance Methods
464 #region Public Instance Methods
465 public void ScrollControlIntoView(Control activeControl) {
466 int x;
467 int y;
468 int corner_x;
469 int corner_y;
471 if (!AutoScroll || (!hscrollbar.VisibleInternal && !vscrollbar.VisibleInternal)) {
472 return;
475 if (!Contains(activeControl)) {
476 return;
479 x = activeControl.Left;
480 y = activeControl.Top;
482 // Translate into coords relative to us
483 if (activeControl.Parent != this) {
484 activeControl.PointToScreen(ref x, ref y);
485 PointToClient(ref x, ref y);
488 x += scroll_position.X;
489 y += scroll_position.Y;
491 // Don't scroll if already visible
492 if ((activeControl.Left >= scroll_position.X) && (activeControl.Left < (scroll_position.X + ClientSize.Width)) &&
493 (activeControl.Top >= scroll_position.Y) && (activeControl.Top < (scroll_position.Y + ClientSize.Height))) {
494 return;
497 // try to center
498 corner_x = Math.Max(0, x + activeControl.Width / 2 - ClientSize.Width / 2);
499 corner_y = Math.Max(0, y + activeControl.Height / 2 - ClientSize.Height / 2);
501 if (hscrollbar.VisibleInternal && (corner_x > hscrollbar.Maximum)) {
502 corner_x = Math.Max(0, hscrollbar.Maximum - ClientSize.Width);
505 if (vscrollbar.VisibleInternal && (corner_y > vscrollbar.Maximum)) {
506 corner_y = Math.Max(0, vscrollbar.Maximum - ClientSize.Height);
508 if ((corner_x == scroll_position.X) && (corner_y == scroll_position.Y)) {
509 return;
512 //this.SetDisplayRectLocation(-corner_x, -corner_y);
513 hscrollbar.Value = corner_x;
514 vscrollbar.Value = corner_y;
517 public void SetAutoScrollMargin(int x, int y) {
518 if (x < 0) {
519 x = 0;
522 if (y < 0) {
523 y = 0;
526 auto_scroll_margin = new Size(x, y);
527 Recalculate(this, EventArgs.Empty);
529 #endregion // Public Instance Methods
531 #region Protected Instance Methods
532 [EditorBrowsable(EditorBrowsableState.Advanced)]
533 protected virtual void AdjustFormScrollbars(bool displayScrollbars) {
534 Recalculate(this, EventArgs.Empty);
537 [EditorBrowsable(EditorBrowsableState.Advanced)]
538 protected bool GetScrollState(int bit) {
539 // Internal MS
540 return false;
543 [EditorBrowsable(EditorBrowsableState.Advanced)]
544 protected override void OnLayout(LayoutEventArgs levent) {
545 CalculateCanvasSize();
547 AdjustFormScrollbars(AutoScroll); // Dunno what the logic is. Passing AutoScroll seems to match MS behaviour
548 base.OnLayout(levent);
551 [EditorBrowsable(EditorBrowsableState.Advanced)]
552 protected override void OnMouseWheel(MouseEventArgs e) {
553 if (vscrollbar.VisibleInternal) {
554 if (e.Delta > 0) {
555 if (vscrollbar.Minimum < (vscrollbar.Value - vscrollbar.LargeChange)) {
556 vscrollbar.Value -= vscrollbar.LargeChange;
557 } else {
558 vscrollbar.Value = vscrollbar.Minimum;
560 } else {
561 int maximum_scrollbar_value = vscrollbar.Maximum - vscrollbar.LargeChange + 1;
562 if (maximum_scrollbar_value > (vscrollbar.Value + vscrollbar.LargeChange)) {
563 vscrollbar.Value += vscrollbar.LargeChange;
564 } else {
565 vscrollbar.Value = maximum_scrollbar_value;
569 base.OnMouseWheel(e);
572 [EditorBrowsable(EditorBrowsableState.Advanced)]
573 protected override void OnVisibleChanged(EventArgs e) {
574 if (Visible) {
575 UpdateChildrenZOrder ();
576 PerformLayout();
578 base.OnVisibleChanged(e);
581 #if NET_2_0
582 [EditorBrowsable (EditorBrowsableState.Never)]
583 #endif
584 protected override void ScaleCore(float dx, float dy) {
585 dock_padding.Scale(dx, dy);
586 base.ScaleCore(dx, dy);
589 protected void SetDisplayRectLocation(int x, int y) {
590 // This method is weird. MS documents that the scrollbars are not
591 // updated. We need to move stuff, but leave the scrollbars as is
593 if (x > 0) {
594 x = 0;
597 if (y > 0) {
598 y = 0;
601 ScrollWindow(scroll_position.X - x , scroll_position.Y - y);
604 protected void SetScrollState(int bit, bool value) {
605 //throw new NotImplementedException();
608 [EditorBrowsable(EditorBrowsableState.Advanced)]
609 protected override void WndProc(ref Message m) {
610 base.WndProc(ref m);
612 #endregion // Protected Instance Methods
614 #region Internal & Private Methods
615 private void CalculateCanvasSize() {
616 Control child;
617 int num_of_children;
618 int width;
619 int height;
620 int extra_width;
621 int extra_height;
623 num_of_children = Controls.Count;
624 width = 0;
625 height = 0;
626 extra_width = dock_padding.Right;
627 extra_height = dock_padding.Bottom;
629 for (int i = 0; i < num_of_children; i++) {
630 child = Controls[i];
631 if (child.Dock == DockStyle.Right) {
632 extra_width += child.Width;
633 } else if (child.Dock == DockStyle.Bottom) {
634 extra_height += child.Height;
638 if (!auto_scroll_min_size.IsEmpty) {
639 width = auto_scroll_min_size.Width;
640 height = auto_scroll_min_size.Height;
643 for (int i = 0; i < num_of_children; i++) {
644 child = Controls[i];
646 switch(child.Dock) {
647 case DockStyle.Left: {
648 if ((child.Right + extra_width) > width) {
649 width = child.Right + extra_width;
651 continue;
654 case DockStyle.Top: {
655 if ((child.Bottom + extra_height) > height) {
656 height = child.Bottom + extra_height;
658 continue;
661 case DockStyle.Fill:
662 case DockStyle.Right:
663 case DockStyle.Bottom: {
664 continue;
667 default: {
668 AnchorStyles anchor;
670 anchor = child.Anchor;
672 if (((anchor & AnchorStyles.Left) != 0) && ((anchor & AnchorStyles.Right) == 0)) {
673 if ((child.Right + extra_width) > width) {
674 width = child.Right + extra_width;
678 if (((anchor & AnchorStyles.Top) != 0) || ((anchor & AnchorStyles.Bottom) == 0)) {
679 if ((child.Bottom + extra_height) > height) {
680 height = child.Bottom + extra_height;
683 continue;
687 width += scroll_position.X;
688 height += scroll_position.Y;
690 canvas_size.Width = width;
691 canvas_size.Height = height;
694 private void Recalculate (object sender, EventArgs e) {
695 if (!IsHandleCreated) {
696 return;
699 Size canvas = canvas_size;
700 Size client = ClientSize;
702 canvas.Width += auto_scroll_margin.Width;
703 canvas.Height += auto_scroll_margin.Height;
705 int right_edge = client.Width;
706 int bottom_edge = client.Height;
707 int prev_right_edge;
708 int prev_bottom_edge;
710 bool hscroll_visible;
711 bool vscroll_visible;
713 do {
714 prev_right_edge = right_edge;
715 prev_bottom_edge = bottom_edge;
717 if ((force_hscroll_visible || canvas.Width > right_edge) && client.Width > 0) {
718 hscroll_visible = true;
719 bottom_edge = client.Height - SystemInformation.HorizontalScrollBarHeight;
720 } else {
721 hscroll_visible = false;
722 bottom_edge = client.Height;
725 if ((force_vscroll_visible || canvas.Height > bottom_edge) && client.Height > 0) {
726 vscroll_visible = true;
727 right_edge = client.Width - SystemInformation.VerticalScrollBarWidth;
728 } else {
729 vscroll_visible = false;
730 right_edge = client.Width;
733 } while (right_edge != prev_right_edge || bottom_edge != prev_bottom_edge);
735 if (right_edge < 0) right_edge = 0;
736 if (bottom_edge < 0) bottom_edge = 0;
738 Rectangle hscroll_bounds;
739 Rectangle vscroll_bounds;
741 hscroll_bounds = new Rectangle (0, client.Height - SystemInformation.HorizontalScrollBarHeight,
742 ClientRectangle.Width, SystemInformation.HorizontalScrollBarHeight);
743 vscroll_bounds = new Rectangle (client.Width - SystemInformation.VerticalScrollBarWidth, 0,
744 SystemInformation.VerticalScrollBarWidth, ClientRectangle.Height);
746 /* the ScrollWindow calls here are needed
747 * because (this explanation sucks):
749 * when we transition from having a scrollbar to
750 * not having one, we won't receive a scrollbar
751 * moved (value changed) event, so we need to
752 * manually scroll the canvas.
754 * if you can fix this without requiring the
755 * ScrollWindow calls, pdb and toshok will each
756 * pay you $5.
758 if (hscroll_visible) {
759 hscrollbar.LargeChange = right_edge;
760 hscrollbar.SmallChange = 5;
761 hscrollbar.Maximum = canvas.Width - 1;
762 } else {
763 if (hscrollbar != null && hscrollbar.VisibleInternal) {
764 ScrollWindow (- scroll_position.X, 0);
766 scroll_position.X = 0;
769 if (vscroll_visible) {
770 vscrollbar.LargeChange = bottom_edge;
771 vscrollbar.SmallChange = 5;
772 vscrollbar.Maximum = canvas.Height - 1;
773 } else {
774 if (vscrollbar != null && vscrollbar.VisibleInternal) {
775 ScrollWindow (0, - scroll_position.Y);
777 scroll_position.Y = 0;
780 if (hscroll_visible && vscroll_visible) {
781 hscroll_bounds.Width -= SystemInformation.VerticalScrollBarWidth;
782 vscroll_bounds.Height -= SystemInformation.HorizontalScrollBarHeight;
784 sizegrip.Bounds = new Rectangle (hscroll_bounds.Right,
785 vscroll_bounds.Bottom,
786 SystemInformation.VerticalScrollBarWidth,
787 SystemInformation.HorizontalScrollBarHeight);
790 SuspendLayout ();
792 hscrollbar.Bounds = hscroll_bounds;
793 hscrollbar.Visible = hscroll_visible;
795 vscrollbar.Bounds = vscroll_bounds;
796 vscrollbar.Visible = vscroll_visible;
798 UpdateSizeGripVisible ();
800 ResumeLayout ();
803 internal void UpdateSizeGripVisible ()
805 sizegrip.CapturedControl = Parent;
806 // This is really wierd, the size grip is only showing up
807 // if the bottom right corner of the scrollable control is within
808 // two pixels from the bottom right corner of its parent.
809 bool show_sizegrip = hscrollbar.VisibleInternal && vscrollbar.VisibleInternal;
810 bool enable_sizegrip = false;
811 if (show_sizegrip && Parent != null) {
812 Point diff = new Point (Parent.ClientRectangle.Bottom - Bottom, Parent.ClientRectangle.Right - Right);
813 enable_sizegrip = diff.X <= 2 && diff.X >= 0 && diff.Y <= 2 && diff.Y >= 0;
815 sizegrip.Visible = show_sizegrip;
816 sizegrip.Enabled = enable_sizegrip || sizegrip.Capture;
819 private void HandleScrollBar(object sender, EventArgs e) {
820 if (sender == vscrollbar) {
821 ScrollWindow(0, vscrollbar.Value- scroll_position.Y);
822 } else {
823 ScrollWindow(hscrollbar.Value - scroll_position.X, 0);
827 private void CreateScrollbars ()
829 hscrollbar = new ImplicitHScrollBar ();
830 hscrollbar.Visible = false;
831 hscrollbar.ValueChanged += new EventHandler (HandleScrollBar);
832 hscrollbar.Height = SystemInformation.HorizontalScrollBarHeight;
833 this.Controls.AddImplicit (hscrollbar);
835 vscrollbar = new ImplicitVScrollBar ();
836 vscrollbar.Visible = false;
837 vscrollbar.ValueChanged += new EventHandler (HandleScrollBar);
838 vscrollbar.Width = SystemInformation.VerticalScrollBarWidth;
839 this.Controls.AddImplicit (vscrollbar);
841 sizegrip = new SizeGrip (this);
842 sizegrip.Visible = false;
843 this.Controls.AddImplicit (sizegrip);
846 private void ScrollWindow(int XOffset, int YOffset) {
847 int num_of_children;
849 if (XOffset == 0 && YOffset == 0) {
850 return;
853 SuspendLayout();
855 num_of_children = Controls.Count;
857 for (int i = 0; i < num_of_children; i++) {
858 Controls[i].Left -= XOffset;
859 Controls[i].Top -= YOffset;
860 // Is this faster? Controls[i].Location -= new Size(XOffset, YOffset);
863 scroll_position.X += XOffset;
864 scroll_position.Y += YOffset;
866 // Should we call XplatUI.ScrollWindow??? If so, we need to position our windows by other means above
867 // Since we're already causing a redraw above
868 Invalidate(false);
869 ResumeLayout(false);
871 #endregion // Internal & Private Methods
873 #if NET_2_0
874 static object OnScrollEvent = new object ();
876 protected virtual void OnScroll (ScrollEventArgs se)
878 EventHandler eh = (EventHandler) (Events [OnScrollEvent]);
879 if (eh != null)
880 eh (this, se);
883 protected override void OnPaintBackground (PaintEventArgs e)
885 base.OnPaintBackground (e);
888 [EditorBrowsable (EditorBrowsableState.Advanced)]
889 protected override void OnRightToLeftChanged (EventArgs e)
891 base.OnRightToLeftChanged (e);
894 public event ScrollEventHandler Scroll {
895 add { Events.AddHandler (OnScrollEvent, value); }
896 remove { Events.RemoveHandler (OnScrollEvent, value); }
898 #endif