using System;
using System.Windows.Forms;
using System.Text;
using DevComponents.DotNetBar.ScrollBar;
using System.Drawing;
using DevComponents.DotNetBar.Rendering;
using System.Runtime.InteropServices;
namespace DevComponents.DotNetBar.Controls
{
    internal class ScrollBarImplementation: IDisposable
    {
        #region Private Variables
        private System.Windows.Forms.ScrollBar m_ParentScrollBar = null;
        private ScrollBarCore m_ScrollBarCore = null;
        private bool m_FirstPaint = true;
        private int m_MouseDownTrackOffset = 0;
        private Timer m_PaintTimer = null;
        private bool m_IsVScrollBar = false;
        private IScrollBarExtender m_ParentScrollBarWndProc = null;
        private bool m_UseLockWindowUpdate = false;
        #endregion
        #region Constructor
        public ScrollBarImplementation(System.Windows.Forms.ScrollBar sb)
        {
            m_ParentScrollBar = sb;
            m_ParentScrollBarWndProc = (IScrollBarExtender)m_ParentScrollBar;
            m_IsVScrollBar = m_ParentScrollBar is VScrollBar;
            m_PaintTimer = new Timer();
            m_PaintTimer.Interval = 50;
            m_PaintTimer.Tick += new EventHandler(PaintTimerTick);
            m_ScrollBarCore = new ScrollBarCore(m_ParentScrollBar, true);
            //m_ScrollBarCore.IsAppScrollBarStyle = false;
            if (m_ParentScrollBar is HScrollBar)
                m_ScrollBarCore.Orientation = eOrientation.Horizontal;
            else
                m_ScrollBarCore.Orientation = eOrientation.Vertical;
            m_ScrollBarCore.Minimum = m_ParentScrollBar.Minimum;
            m_ScrollBarCore.Maximum = m_ParentScrollBar.Maximum;
            m_ScrollBarCore.Value = m_ParentScrollBar.Value;
        }
        #endregion
        #region Internal Implementation
        internal void OnHandleCreated()
        {
            Themes.SetWindowTheme(m_ParentScrollBar.Handle, "", "");
            UpdateScrollValues();
        }
        internal bool WndProc(ref Message m)
        {
            if (m.Msg == (int)WinApi.WindowsMessages.SBM_SETSCROLLINFO || m.Msg == 0x2114 || m.Msg == 0x2115 || m.Msg == (int)WinApi.WindowsMessages.WM_MOUSEMOVE)
            {
                CallBaseWndProc(ref m);
                SendDelayPaintMessage();
                return false;
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_SIZE)
            {
                CallBaseWndProc(ref m);
                m_FirstPaint = true;
                SendDelayPaintMessage();
                return false;
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_ERASEBKGND)
            {
                //PaintUsingDC();
                //m.Result = new IntPtr(1);
                return false;
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_LBUTTONDOWN)
            {
                Point p = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam));
                InternalMouseDown(new MouseEventArgs(GetMouseButton(m.WParam.ToInt32()), 0, p.X, p.Y, 0));
                return false;
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_LBUTTONUP)
            {
                Point p = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam));
                InternalMouseUp(new MouseEventArgs(GetMouseButton(m.WParam.ToInt32()), 0, p.X, p.Y, 0));
                return false;
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_LBUTTONDBLCLK)
            {
                Point p = new Point(WinApi.LOWORD(m.LParam), WinApi.HIWORD(m.LParam));
                InternalMouseDoubleClick(new MouseEventArgs(GetMouseButton(m.WParam.ToInt32()), 0, p.X, p.Y, 0));
                return false;
            }
            else if (m.Msg == NativeFunctions.WM_USER + 7)
            {
                PaintUsingDC();
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_SYSTIMER)
            {
                if (m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.Track && Control.MouseButtons == MouseButtons.Left)
                {
                    Point p = m_ParentScrollBar.PointToClient(Control.MousePosition);
                    OnMouseMove(new MouseEventArgs(Control.MouseButtons, 0, p.X, p.Y, 0));
                }
            }
            else if (m.Msg == (int)WinApi.WindowsMessages.WM_CAPTURECHANGED)
            {
                // Recapture the mouse...
                if (m.LParam == IntPtr.Zero && Control.MouseButtons == MouseButtons.Left && m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.Track)
                {
                    m_ParentScrollBar.Capture = true;
                }
            }
            if (m.Msg == (int)WinApi.WindowsMessages.WM_PAINT)
            {
                if (m_FirstPaint)
                {
                    // Call to base actually updates values returned by GetScrollBarInfo
                    CallBaseWndProc(ref m);
                    // Repaint the control once that is done
                    SendDelayPaintMessage();
                    m_FirstPaint = false;
                }
                WinApi.PAINTSTRUCT ps = new WinApi.PAINTSTRUCT();
                IntPtr hdc = WinApi.BeginPaint(m.HWnd, ref ps);
                try
                {
                    Graphics g = Graphics.FromHdc(hdc);
                    try
                    {
                        PaintInternal(g, hdc);
                    }
                    finally
                    {
                        g.Dispose();
                    }
                }
                finally
                {
                    WinApi.EndPaint(m.HWnd, ref ps);
                }
                return false;
            }
            return true;
        }
        private void CallBaseWndProc(ref Message m)
        {
            m_ParentScrollBarWndProc.CallBaseWndProc(ref m);
        }
        private void SendDelayPaintMessage()
        {
            m_PaintTimer.Start();
        }
        void PaintTimerTick(object sender, EventArgs e)
        {
            m_PaintTimer.Stop();
            PaintUsingDC();
        }
        private void InternalMouseDoubleClick(MouseEventArgs me)
        {
            PerformThumbClick(me.X, me.Y);
        }
        private void PerformThumbClick(int mouseX, int mouseY)
        {
            if (m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.ThumbDecrease)
                this.SetValue(Math.Max(m_ParentScrollBar.Value - m_ParentScrollBar.SmallChange, m_ParentScrollBar.Minimum), ScrollEventType.SmallDecrement);
            else if (m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.ThumbIncrease)
                this.SetValue(Math.Min(m_ParentScrollBar.Value + m_ParentScrollBar.SmallChange, m_ParentScrollBar.Maximum), ScrollEventType.SmallIncrement);
            else if (m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.Control)
            {
                if (this.IsVScroll)
                {
                    if (mouseY < m_ScrollBarCore.TrackRectangle.Y)
                        this.SetValue(Math.Max(m_ParentScrollBar.Value - m_ParentScrollBar.LargeChange, m_ParentScrollBar.Minimum), ScrollEventType.LargeDecrement);
                    else if (mouseY > m_ScrollBarCore.TrackRectangle.Bottom)
                        this.SetValue(Math.Min(m_ParentScrollBar.Value + m_ParentScrollBar.LargeChange, m_ParentScrollBar.Maximum), ScrollEventType.LargeIncrement);
                }
                else
                {
                    if (mouseX < m_ScrollBarCore.TrackRectangle.X)
                        this.SetValue(Math.Max(m_ParentScrollBar.Value - m_ParentScrollBar.LargeChange, m_ParentScrollBar.Minimum), ScrollEventType.LargeDecrement);
                    else if (mouseX > m_ScrollBarCore.TrackRectangle.Right)
                        this.SetValue(Math.Min(m_ParentScrollBar.Value + m_ParentScrollBar.LargeChange, m_ParentScrollBar.Maximum), ScrollEventType.LargeIncrement);
                }
            }
        }
        private void SetValue(int newValue, ScrollEventType type)
        {
            //FieldInfo fi = typeof(System.Windows.Forms.ScrollBar).GetField("value", BindingFlags.NonPublic | BindingFlags.Instance);
            //if (fi != null)
            //{
            //    fi.SetValue(this, newValue);
            //    UpdateSystemScrollInfo();
            //}
            //else
            if (m_ParentScrollBar.Value == newValue) return;
            if (m_UseLockWindowUpdate && m_ParentScrollBar.Parent != null)
                NativeFunctions.LockWindowUpdate(m_ParentScrollBar.Parent.Handle);
            else
                NativeFunctions.SendMessage(m_ParentScrollBar.Handle, NativeFunctions.WM_SETREDRAW, 0, 0);
            m_ParentScrollBarWndProc.SetValue(newValue, type);
            if (m_UseLockWindowUpdate && m_ParentScrollBar.Parent != null)
                NativeFunctions.LockWindowUpdate(IntPtr.Zero);
            else
                NativeFunctions.SendMessage(m_ParentScrollBar.Handle, NativeFunctions.WM_SETREDRAW, 1, 0);
            if (m_ParentScrollBar.Parent is DataGridView && type == ScrollEventType.ThumbTrack)
            {
                if (m_UseLockWindowUpdate)
                    m_ParentScrollBar.Parent.Refresh();
                else
                {
                    Point p = m_ParentScrollBar.PointToClient(Control.MousePosition);
                    if (!m_ParentScrollBar.ClientRectangle.Contains(p)) 
                        m_ParentScrollBar.Parent.Refresh();
                }
            }
            PaintUsingDC();
        }
        //private void UpdateSystemScrollInfo()
        //{
        //    if (this.IsHandleCreated && this.Enabled)
        //    {
        //        WinApi.SCROLLINFO si = new WinApi.SCROLLINFO();
        //        si.cbSize = Marshal.SizeOf(typeof(WinApi.SCROLLINFO));
        //        si.fMask = 0x17;
        //        si.nMin = this.Minimum;
        //        si.nMax = this.Maximum;
        //        si.nPage = this.LargeChange;
        //        if (this.RightToLeft == RightToLeft.Yes)
        //        {
        //            MethodInfo mi = typeof(System.Windows.Forms.ScrollBar).GetMethod("ReflectPosition", BindingFlags.NonPublic | BindingFlags.Instance);
        //            if(mi!=null)
        //                si.nPos = (int)mi.Invoke(this, new object[]{this.Value});
        //            //= this.ReflectPosition(this.value);
        //        }
        //        else
        //        {
        //            si.nPos = this.Value;
        //        }
        //        si.nTrackPos = 0;
        //        WinApi.SetScrollInfo(new HandleRef(this, this.Handle), 2, ref si, false);
        //    }
        //}
        private void InternalMouseUp(MouseEventArgs mouseEventArgs)
        {
            StopAutoScrollTimer();
            m_ScrollBarCore.MouseUp(mouseEventArgs);
            m_ParentScrollBar.Invalidate();
            m_MouseDownTrackOffset = 0;
            if (m_ParentScrollBar.Capture)
                m_ParentScrollBar.Capture = false;
        }
        private void InternalMouseDown(MouseEventArgs me)
        {
            m_MouseDownTrackOffset = 0;
            m_ScrollBarCore.MouseDown(me);
            if (m_ScrollBarCore.MouseOverPart != ScrollBarCore.eScrollPart.Track && m_ScrollBarCore.MouseOverPart != ScrollBarCore.eScrollPart.None)
            {
                PerformThumbClick(me.X, me.Y);
                StartAutoScrollTimer();
            }
            else if (m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.Track)
            {
                if (IsVScroll)
                    m_MouseDownTrackOffset = me.Y - m_ScrollBarCore.TrackRectangle.Y;
                else
                    m_MouseDownTrackOffset = me.X - m_ScrollBarCore.TrackRectangle.X;
            }
            PaintUsingDC();
        }
        private Timer m_Timer = null;
        private void StartAutoScrollTimer()
        {
            if (m_Timer == null)
            {
                m_Timer = new Timer();
                m_Timer.Interval = 150;
                m_Timer.Tick += new EventHandler(TimerScrollTick);
            }
            m_Timer.Start();
        }
        private void TimerScrollTick(object sender, EventArgs e)
        {
            Point p = m_ParentScrollBar.PointToClient(Control.MousePosition);
            PerformThumbClick(p.X, p.Y);
        }
        private void StopAutoScrollTimer()
        {
            if (m_Timer != null)
            {
                m_Timer.Stop();
                m_Timer.Dispose();
                m_Timer = null;
            }
        }
        private MouseButtons GetMouseButton(int wParam)
        {
            MouseButtons mb = MouseButtons.None;
            if ((wParam & (int)WinApi.MouseKeyState.MK_LBUTTON) != 0)
                mb |= MouseButtons.Left;
            if ((wParam & (int)WinApi.MouseKeyState.MK_MBUTTON) != 0)
                mb |= MouseButtons.Middle;
            if ((wParam & (int)WinApi.MouseKeyState.MK_RBUTTON) != 0)
                mb |= MouseButtons.Right;
            if ((wParam & (int)WinApi.MouseKeyState.MK_XBUTTON1) != 0)
                mb |= MouseButtons.XButton1;
            if ((wParam & (int)WinApi.MouseKeyState.MK_XBUTTON2) != 0)
                mb |= MouseButtons.XButton2;
            return mb;
        }
        private void PaintUsingDC()
        {
            IntPtr hdc = WinApi.GetWindowDC(m_ParentScrollBar.Handle);
            try
            {
                Graphics g = Graphics.FromHdc(hdc);
                try
                {
                    PaintInternal(g, hdc);
                }
                finally
                {
                    g.Dispose();
                }
            }
            finally
            {
                WinApi.ReleaseDC(m_ParentScrollBar.Handle, hdc);
            }
        }
        private void PaintInternal(Graphics g, IntPtr hdc)
        {
            UpdateScrollValues();
            using (BufferedBitmap bmp = new BufferedBitmap(g, new Rectangle(0, 0, m_ParentScrollBar.Width, m_ParentScrollBar.Height)))
            {
                m_ScrollBarCore.Paint(GetItemPaintArgs(bmp.Graphics));
                bmp.Render(g);
            }
        }
        private ItemPaintArgs GetItemPaintArgs(Graphics g)
        {
            ItemPaintArgs pa = new ItemPaintArgs(m_ParentScrollBar as IOwner, m_ParentScrollBar, g, GetColorScheme());
            pa.Renderer = this.GetRenderer();
            pa.DesignerSelection = false;
            pa.GlassEnabled = false;
            return pa;
        }
        private ColorScheme m_ColorScheme = null;
        /// 
        /// Returns the color scheme used by control. Color scheme for Office2007 style will be retrived from the current renderer instead of
        /// local color scheme referenced by ColorScheme property.
        /// 
        /// An instance of ColorScheme object.
        protected virtual ColorScheme GetColorScheme()
        {
            BaseRenderer r = GetRenderer();
            if (r is Office2007Renderer)
                return ((Office2007Renderer)r).ColorTable.LegacyColors;
            if (m_ColorScheme == null)
                m_ColorScheme = new ColorScheme(eDotNetBarStyle.Office2007);
            return m_ColorScheme;
        }
        private Rendering.BaseRenderer m_DefaultRenderer = null;
        private Rendering.BaseRenderer m_Renderer = null;
        private eRenderMode m_RenderMode = eRenderMode.Global;
        /// 
        /// Returns the renderer control will be rendered with.
        /// 
        /// The current renderer.
        public virtual Rendering.BaseRenderer GetRenderer()
        {
            if (m_RenderMode == eRenderMode.Global && Rendering.GlobalManager.Renderer != null)
                return Rendering.GlobalManager.Renderer;
            else if (m_RenderMode == eRenderMode.Custom && m_Renderer != null)
                return m_Renderer;
            if (m_DefaultRenderer == null)
                m_DefaultRenderer = new Rendering.Office2007Renderer();
            return m_DefaultRenderer;
        }
        /// 
        /// Gets or sets the redering mode used by control. Default value is eRenderMode.Global which means that static GlobalManager.Renderer is used. If set to Custom then Renderer property must
        /// also be set to the custom renderer that will be used.
        /// 
        public eRenderMode RenderMode
        {
            get { return m_RenderMode; }
            set
            {
                if (m_RenderMode != value)
                {
                    m_RenderMode = value;
                    m_ParentScrollBar.Invalidate(true);
                }
            }
        }
        /// 
        /// Gets or sets the custom renderer used by the items on this control. RenderMode property must also be set to eRenderMode.Custom in order renderer
        /// specified here to be used.
        /// 
        public DevComponents.DotNetBar.Rendering.BaseRenderer Renderer
        {
            get
            {
                return m_Renderer;
            }
            set { m_Renderer = value; }
        }
        internal void OnMouseEnter(EventArgs e)
        {
            if (m_ParentScrollBar.Capture)
                m_ParentScrollBar.Capture = false;
        }
        internal void OnMouseLeave(EventArgs e)
        {
            StopAutoScrollTimer();
            if (m_ScrollBarCore.MouseOverPart != ScrollBarCore.eScrollPart.None && Control.MouseButtons == MouseButtons.Left)
                m_ParentScrollBar.Capture = true;
            if (m_ScrollBarCore.IsMouseDown && Control.MouseButtons == MouseButtons.None)
            {
                m_ScrollBarCore.MouseUp(new MouseEventArgs(MouseButtons.Left, 0, -10, -10, 0));
                SendDelayPaintMessage();
            }
            else
                m_ScrollBarCore.MouseLeave();
        }
        internal void OnMouseMove(MouseEventArgs e)
        {
            m_ScrollBarCore.MouseMove(e);
            if (m_ScrollBarCore.MouseOverPart == ScrollBarCore.eScrollPart.Track && e.Button == MouseButtons.Left)
            {
                Point p = m_ParentScrollBar.PointToClient(Control.MousePosition);
                SetValue(ValueFromMouseCoordinates(p), ScrollEventType.ThumbTrack);
            }
        }
        private int ValueFromMouseCoordinates(Point p)
        {
            if (IsVScroll)
            {
                int trackY = p.Y - m_MouseDownTrackOffset;
                trackY = Math.Max(trackY, m_ScrollBarCore.ThumbDecreaseRectangle.Bottom);
                trackY = Math.Min(trackY, m_ScrollBarCore.ThumbIncreaseRectangle.Y - GetTrackSize());
                trackY -= m_ScrollBarCore.ThumbDecreaseRectangle.Bottom;
                int totalSize = GetAvailableTrackArea() - GetTrackSize();
                return (int)((m_ParentScrollBar.Maximum - m_ParentScrollBar.Minimum) * ((float)trackY / (float)totalSize));
            }
            else
            {
                int trackX = p.X - m_MouseDownTrackOffset;
                trackX = Math.Max(trackX, m_ScrollBarCore.ThumbDecreaseRectangle.Right);
                trackX = Math.Min(trackX, m_ScrollBarCore.ThumbIncreaseRectangle.X - GetTrackSize());
                trackX -= m_ScrollBarCore.ThumbDecreaseRectangle.Right;
                int totalSize = GetAvailableTrackArea() - GetTrackSize();
                return (int)((m_ParentScrollBar.Maximum - m_ParentScrollBar.Minimum) * ((float)trackX / (float)totalSize));
            }
        }
        private int GetTrackSize()
        {
            if (IsVScroll)
                return m_ScrollBarCore.TrackRectangle.Height;
            else
                return m_ScrollBarCore.TrackRectangle.Width;
        }
        private int GetAvailableTrackArea()
        {
            if (IsVScroll)
                return m_ScrollBarCore.DisplayRectangle.Height - m_ScrollBarCore.ThumbDecreaseRectangle.Height - m_ScrollBarCore.ThumbIncreaseRectangle.Height;
            else
                return m_ScrollBarCore.DisplayRectangle.Width - m_ScrollBarCore.ThumbDecreaseRectangle.Width - m_ScrollBarCore.ThumbIncreaseRectangle.Width;
        }
        private bool IsVScroll
        {
            get
            {
                return m_IsVScrollBar;
            }
        }
        private void UpdateScrollValues()
        {
            WinApi.SCROLLBARINFO psbi = new WinApi.SCROLLBARINFO();
            psbi.cbSize = Marshal.SizeOf(psbi);
            WinApi.GetScrollBarInfo(m_ParentScrollBar.Handle, (uint)WinApi.eObjectId.OBJID_CLIENT, ref psbi);
            Rectangle displayRect = new Rectangle(0, 0, m_ParentScrollBar.Width, m_ParentScrollBar.Height);
            if (IsVScroll)
            {
                if (m_ScrollBarCore.DisplayRectangle != displayRect)
                    m_ScrollBarCore.DisplayRectangle = displayRect;
                Rectangle thumbRect = new Rectangle(displayRect.X, displayRect.Y, displayRect.Width, psbi.dxyLineButton);
                if (m_ScrollBarCore.ThumbDecreaseRectangle != thumbRect)
                    m_ScrollBarCore.ThumbDecreaseRectangle = thumbRect;
                thumbRect = new Rectangle(displayRect.X, displayRect.Bottom - psbi.dxyLineButton, displayRect.Width, psbi.dxyLineButton);
                if (m_ScrollBarCore.ThumbIncreaseRectangle != thumbRect)
                    m_ScrollBarCore.ThumbIncreaseRectangle = thumbRect;
                thumbRect = new Rectangle(displayRect.X, displayRect.Y + psbi.xyThumbTop, displayRect.Width, psbi.xyThumbBottom - psbi.xyThumbTop);
                if (m_ScrollBarCore.TrackRectangle != thumbRect)
                    m_ScrollBarCore.TrackRectangle = thumbRect;
            }
            else
            {
                if (m_ScrollBarCore.DisplayRectangle != displayRect)
                    m_ScrollBarCore.DisplayRectangle = displayRect;
                Rectangle thumbRect = new Rectangle(displayRect.X, displayRect.Y, psbi.dxyLineButton, displayRect.Height);
                if (m_ScrollBarCore.ThumbDecreaseRectangle != thumbRect)
                    m_ScrollBarCore.ThumbDecreaseRectangle = thumbRect;
                thumbRect = new Rectangle(displayRect.Right - psbi.dxyLineButton, displayRect.Y, psbi.dxyLineButton, displayRect.Height);
                if (m_ScrollBarCore.ThumbIncreaseRectangle != thumbRect)
                    m_ScrollBarCore.ThumbIncreaseRectangle = thumbRect;
                thumbRect = new Rectangle(displayRect.X + psbi.xyThumbTop, displayRect.Y, psbi.xyThumbBottom - psbi.xyThumbTop, displayRect.Height);
                if (m_ScrollBarCore.TrackRectangle != thumbRect)
                    m_ScrollBarCore.TrackRectangle = thumbRect;
            }
            if (m_ScrollBarCore.Minimum != m_ParentScrollBar.Minimum)
                m_ScrollBarCore.Minimum = m_ParentScrollBar.Minimum;
            if (m_ScrollBarCore.Maximum != m_ParentScrollBar.Maximum)
                m_ScrollBarCore.Maximum = m_ParentScrollBar.Maximum;
            if (m_ScrollBarCore.SmallChange != m_ParentScrollBar.SmallChange)
                m_ScrollBarCore.SmallChange = m_ParentScrollBar.SmallChange;
            if (m_ScrollBarCore.LargeChange != m_ParentScrollBar.LargeChange)
                m_ScrollBarCore.LargeChange = m_ParentScrollBar.LargeChange;
            if (m_ScrollBarCore.Value != m_ParentScrollBar.Value)
                m_ScrollBarCore.Value = m_ParentScrollBar.Value;
        }
        internal void NotifyInvalidate(Rectangle invalidatedArea)
        {
        }
        //public bool IsAppScrollBarStyle
        //{
        //    get { return m_ScrollBarCore.IsAppScrollBarStyle; }
        //    set
        //    {
        //        m_ScrollBarCore.IsAppScrollBarStyle = value;
        //        m_ParentScrollBar.Invalidate();
        //    }
        //}
        #endregion
        #region IDisposable Members
        public void Dispose()
        {
            if (m_ScrollBarCore != null)
            {
                m_ScrollBarCore.Dispose();
                m_ScrollBarCore = null;
            }
            if (m_PaintTimer != null)
            {
                m_PaintTimer.Stop();
                m_PaintTimer.Dispose();
                m_PaintTimer = null;
            }
            StopAutoScrollTimer();
        }
        #endregion
        internal interface IScrollBarExtender
        {
            void CallBaseWndProc(ref Message m);
            void SetValue(int newValue, ScrollEventType type);
        }
    }
}