// Name: Scroller TextBox
// Author: AceInfinity
// Copyright: Tech.Reboot.Pro 2013
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;
class ScrollTextBox : TextBox
{
// Win32 Functions
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);
// Nested Types
[Serializable, StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}
public enum ScrollInfoMask : uint
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
}
// Constants
private const int SB_HORZ = 0;
private const int SB_VERT = 1;
private const int WM_HSCROLL = 0x0114;
private const int WM_VSCROLL = 0x0115;
private const int WM_MOUSEWHEEL = 0x020A;
private const int WM_KEYDOWN = 0x0100;
private const int VK_UP = 0x26;
private const int VK_DOWN = 0x28;
private const int VK_LEFT = 0x25;
private const int VK_RIGHT = 0x27;
// Properties
private int _VerticalScrollPos = 0;
public int VerticalScrollPos
{
get { return _VerticalScrollPos; }
}
private int _HorizontalScrollPos = 0;
public int HorizontalScrollPos
{
get { return _HorizontalScrollPos; }
}
private int MinHorizontal, MinVertical, MaxHorizontal, MaxVertical;
// Constructor
public ScrollTextBox()
{
this.DoubleBuffered = true;
this.Multiline = true;
this.WordWrap = false;
this.ScrollBars = ScrollBars.Both;
}
// Overrides
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
bool raiseEvent = false;
switch (m.Msg)
{
case WM_HSCROLL:
{
ScrollCode nScrollCode = (ScrollCode)loWord(m.WParam.ToInt32());
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf(si);
si.fMask = (int)ScrollInfoMask.SIF_ALL;
if (GetScrollInfo(this.Handle, SB_HORZ, ref si))
{
raiseEvent = si.nPos != _HorizontalScrollPos;
_HorizontalScrollPos = si.nPos;
MinHorizontal = si.nMin;
MaxHorizontal = si.nMax;
}
if (raiseEvent)
{
ScrollPosChanged(this, new ScrollStateChangedEventArgs(_VerticalScrollPos, _HorizontalScrollPos, nScrollCode));
}
}
break;
case WM_VSCROLL:
{
ScrollCode nScrollCode = (ScrollCode)loWord(m.WParam.ToInt32());
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf(si);
si.fMask = (int)ScrollInfoMask.SIF_ALL;
if (GetScrollInfo(this.Handle, SB_VERT, ref si))
{
raiseEvent = si.nPos != _VerticalScrollPos;
_VerticalScrollPos = si.nPos;
MinVertical = si.nMin;
MaxVertical = si.nMax;
}
if (raiseEvent)
{
ScrollPosChanged(this, new ScrollStateChangedEventArgs(_VerticalScrollPos, _HorizontalScrollPos, nScrollCode));
}
}
break;
case WM_MOUSEWHEEL:
{
ScrollCode nScrollCode = (ScrollCode)loWord(m.WParam.ToInt32());
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf(si);
si.fMask = (int)ScrollInfoMask.SIF_ALL;
if (GetScrollInfo(this.Handle, SB_VERT, ref si))
{
raiseEvent = si.nPos != _VerticalScrollPos;
_VerticalScrollPos = si.nPos;
MinVertical = si.nMin;
MaxVertical = si.nMax;
}
if (raiseEvent)
{
ScrollPosChanged(this, new ScrollStateChangedEventArgs(_VerticalScrollPos, _HorizontalScrollPos, nScrollCode));
}
}
break;
case WM_KEYDOWN:
{
ScrollCode nScrollCode = (ScrollCode)loWord(m.WParam.ToInt32());
SCROLLINFO si = new SCROLLINFO();
si.cbSize = (uint)Marshal.SizeOf(si);
si.fMask = (int)ScrollInfoMask.SIF_ALL;
if (m.WParam.ToInt32() == VK_UP || m.WParam.ToInt32() == VK_DOWN)
{
if (GetScrollInfo(this.Handle, SB_VERT, ref si))
{
raiseEvent = si.nPos != _VerticalScrollPos;
_VerticalScrollPos = si.nPos;
MinVertical = si.nMin;
MaxVertical = si.nMax;
}
}
else if (m.WParam.ToInt32() == VK_LEFT || m.WParam.ToInt32() == VK_RIGHT)
{
if (GetScrollInfo(this.Handle, SB_HORZ, ref si))
{
raiseEvent = si.nPos != _HorizontalScrollPos;
_HorizontalScrollPos = si.nPos;
MinVertical = si.nMin;
MaxVertical = si.nMax;
}
}
if (raiseEvent)
{
ScrollPosChanged(this, new ScrollStateChangedEventArgs(_VerticalScrollPos, _HorizontalScrollPos, nScrollCode));
}
}
break;
}
}
// Methods
private static int loWord(int dwInt)
{
return 0xFFFF & dwInt;
}
// Events
public delegate void ScrollStateChanged(object sender, ScrollStateChangedEventArgs e);
public event ScrollStateChanged ScrollPosChanged;
protected virtual void OnScrollPosChanged(ScrollStateChangedEventArgs e)
{
ScrollStateChanged handler = ScrollPosChanged;
if (handler != null)
{
handler(this, e);
}
}
}
public enum ScrollCode
{
SB_LINEUP = 0, // Scrolled one line up
SB_LINEDOWN = 1, // Scrolled one line down
SB_PAGEUP = 2, // Scrolled one page up
SB_PAGEDOWN = 3, // Scrolled one page down
SB_THUMBPOSITION = 4, // Dragged and released scrollbar with mouse
SB_THUMBTRACK = 5, // Dragging the scrollbar
SB_TOP = 6, // Scroll to upper left
SB_BOTTOM = 7, // Scroll to bottom right
SB_ENDSCROLL = 8 // Ends scroll
}
public class ScrollStateChangedEventArgs : EventArgs
{
public ScrollStateChangedEventArgs(int vertical, int horizontal, ScrollCode nScrollCode)
{
_VerticalPosition = vertical;
_HorizontalPosition = horizontal;
_ScrollBarCode = nScrollCode;
}
private ScrollCode _ScrollBarCode;
public ScrollCode ScrollBarCode
{
get { return _ScrollBarCode; }
}
private int _VerticalPosition = 0;
public int VerticalPosition
{
get { return _VerticalPosition; }
}
private int _HorizontalPosition = 0;
public int HorizontalPosition
{
get { return _HorizontalPosition; }
}
}