vbAccelerator - Contents of code file: acclExplorerBar_ControllableScrollableControl.csusing System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace vbAccelerator.Components.Controls.ExplorerBarUtility
{
#region Enum
/// <summary>
/// Scroll bar orientation constants for the
/// <see cref="ControllableScrollableControl"/>.
/// </summary>
public enum ScrollBarOrientation : int
{
/// <summary>
/// The Horizontal scroll bar.
/// </summary>
Horizontal = 0, // SB_HORZ
/// <summary>
/// The Vertical scroll bar.
/// </summary>
Vertical = 1 // SB_VERT
}
#endregion
/// <summary>
/// Event Arguments describing a scroll event.
/// </summary>
public class ControllableScrollEventArgs : ScrollEventArgs
{
/// <summary>
/// The bar orientation
/// </summary>
private ScrollBarOrientation orientation =
ScrollBarOrientation.Horizontal;
/// <summary>
/// Constructs a new instance of this class.
/// </summary>
/// <param name="orientation">Scroll bar orientation which has
changed.</param>
/// <param name="type">Scroll bar event type.</param>
/// <param name="newValue">New scroll bar value.</param>
internal ControllableScrollEventArgs(
ScrollBarOrientation orientation,
ScrollEventType type ,
int newValue
) : base(type, newValue)
{
this.orientation = orientation;
}
/// <summary>
/// Gets the orientation of the scroll bar which changed.
/// </summary>
public ScrollBarOrientation Orientation
{
get
{
return orientation;
}
}
}
#region Delegate
/// <summary>
/// Represents the method that responds to the <see
cref="ControllableScrollableControl"/>
/// <see cref="ControllableScrollableControl.Scroll"/> event.
/// </summary>
public delegate void ControllableScrollEventHandler(object sender,
ControllableScrollEventArgs e);
#endregion
/// <summary>
/// This control offers an alternative to the .NET Framework
ScrollableControl.
/// This version is more controllable (changing the Max size does not affect
the
/// value unless the max is made smaller than the value, when the scroll
/// position is maintained at the bottom of the control) and also
/// supports > 16 bit signed scroll ranges.
/// </summary>
public class ControllableScrollableControl : System.Windows.Forms.UserControl
{
#region Unmanaged Code
private struct SCROLLINFO
{
public int cbSize;
public int fMask;
public int nMin;
public int nMax;
public int nPage;
public int nPos;
public int nTrackPos;
}
[DllImport("user32.dll")]
private static extern int SetScrollInfo (IntPtr hwnd, int n, ref
SCROLLINFO lpcScrollInfo, bool b);
[DllImport("user32.dll")]
private static extern int GetScrollInfo (IntPtr hwnd, int n, ref
SCROLLINFO lpScrollInfo);
[DllImport("user32.dll")]
private static extern int GetScrollPos (IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
private static extern int GetScrollRange (IntPtr hWnd, int nBar, ref int
lpMinPos, ref int lpMaxPos);
[DllImport("user32.dll")]
private static extern int SetScrollPos (IntPtr hWnd, int nBar, int nPos,
int bRedraw);
[DllImport("user32.dll")]
private static extern int SetScrollRange (IntPtr hWnd, int nBar, int
nMinPos, int nMaxPos, int bRedraw);
private const int SB_BOTH = 3;
private const int SB_BOTTOM = 7;
private const int SB_CTL = 2;
private const int SB_ENDSCROLL = 8;
private const int SB_HORZ = 0;
private const int SB_LEFT = 6;
private const int SB_LINEDOWN = 1;
private const int SB_LINELEFT = 0;
private const int SB_LINERIGHT = 1;
private const int SB_LINEUP = 0;
private const int SB_PAGEDOWN = 3;
private const int SB_PAGELEFT = 2;
private const int SB_PAGERIGHT = 3;
private const int SB_PAGEUP = 2;
private const int SB_RIGHT = 7;
private const int SB_THUMBPOSITION = 4;
private const int SB_THUMBTRACK = 5;
private const int SB_TOP = 6;
private const int SB_VERT = 1;
private const int SIF_RANGE = 0x1;
private const int SIF_PAGE = 0x2;
private const int SIF_POS = 0x4;
private const int SIF_DISABLENOSCROLL = 0x8;
private const int SIF_TRACKPOS = 0x10;
private const int SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS |
SIF_TRACKPOS);
private const int ESB_DISABLE_BOTH = 0x3;
private const int ESB_ENABLE_BOTH = 0x0;
private const int SBS_SIZEGRIP = 0x10;
[DllImport("user32.dll")]
private static extern int EnableScrollBar (IntPtr hWnd, int wSBflags, int
wArrows);
[DllImport("user32.dll")]
private static extern int ShowScrollBar (IntPtr hWnd, int wBar, bool
bShow);
// Non-client messages:
private const int WM_NCLBUTTONDOWN = 0xA1;
private const int WM_NCRBUTTONDOWN = 0xA4;
private const int WM_NCMBUTTONDOWN = 0xA7;
// Hit test codes for scroll bars:
private const int HTHSCROLL = 6;
private const int HTVSCROLL = 7;
// Scroll bar messages:
private const int WM_VSCROLL = 0x115;
private const int WM_HSCROLL = 0x114;
private const int WM_MOUSEWHEEL = 0x20A;
// Mouse wheel stuff:
private const int WHEEL_DELTA = 120;
private const int WHEEL_PAGESCROLL = -1;
private const int SPI_GETWHEELSCROLLLINES = 0x68;
#endregion
#region events
/// <summary>
/// Raised when the scroll position changed.
/// </summary>
public event ControllableScrollEventHandler Scroll;
/// <summary>
/// Raised when the user clicks a scroll bar.
/// </summary>
public event EventHandler ScrollClick;
#endregion
#region Member Variables
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// Object enabling properties of the horizontal scroll bar
/// to be read/changed.
/// </summary>
private ScrollBar horizontal = null;
/// <summary>
/// Object enabling properties of the vertical scroll bar
/// to be read/changed.
/// </summary>
private ScrollBar vertical = null;
/// <summary>
/// Minimum value of the scroll bars.
/// </summary>
private int[] min = {0, 0};
/// <summary>
/// Maximum value of the scroll bars.
/// </summary>
private int[] max = {100, 100};
/// <summary>
/// SmallChange amount of the scroll bars.
/// </summary>
private int[] smallChange = {1, 1};
/// <summary>
/// LargeChange amount of the scroll bars.
/// </summary>
private int[] largeChange = {10, 10};
/// <summary>
/// Position of the scroll bars.
/// </summary>
private int[] pos = {0, 0};
/// <summary>
/// Whether the scroll bars are visible.
/// </summary>
private bool[] visible = {false, false};
/// <summary>
/// Whether the scroll bars are enabled.
/// </summary>
private bool[] enabled = {true, true};
#endregion
/// <summary>
/// Constructs a new instance of the control.
/// </summary>
public ControllableScrollableControl()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
horizontal = new ScrollBar(this, ScrollBarOrientation.Horizontal);
vertical = new ScrollBar(this, ScrollBarOrientation.Vertical);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
#region Public Implementation
/// <summary>
/// Gets an object which can be used to get/set the properties
/// of the horizontal scroll bar.
/// </summary>
public ScrollBar HorizontalScrollBar
{
get
{
return horizontal;
}
}
/// <summary>
/// Gets an object which can be used to get/set the properties
/// of the vertical scroll bar.
/// </summary>
public ScrollBar VerticalScrollBar
{
get
{
return vertical;
}
}
#endregion
#region Internal Implementation
internal int InternalValue(ScrollBarOrientation orientation)
{
if (Handle == IntPtr.Zero)
{
return pos[(int) orientation];
}
else
{
SCROLLINFO si = GetScrollInfo(orientation);
return si.nPos;
}
}
internal bool InternalValue(ScrollBarOrientation orientation, int value)
{
bool changed = false;
if (!Handle.Equals(IntPtr.Zero))
{
if (InternalValue(orientation) != value)
{
SCROLLINFO si = new SCROLLINFO();
si.fMask = SIF_POS;
si.nPos = value;
SetScrollInfo(orientation, si);
changed = true;
}
}
pos[(int) orientation] = value;
return changed;
}
internal int InternalSmallChange(ScrollBarOrientation orientation)
{
return smallChange[(int) orientation];
}
internal void InternalSmallChange(ScrollBarOrientation orientation, int
value)
{
smallChange[(int) orientation] = value;
}
internal int InternalLargeChange(ScrollBarOrientation orientation)
{
return largeChange[(int) orientation];
}
internal void InternalLargeChange(ScrollBarOrientation orientation, int
value)
{
if (!Handle.Equals(IntPtr.Zero))
{
if (largeChange[(int) orientation] != value)
{
SCROLLINFO si = GetScrollInfo(orientation);
si.nMax += value - si.nPage;
si.nPage = value;
si.fMask &= ~SIF_POS;
SetScrollInfo(orientation, si);
}
}
largeChange[(int) orientation] = value;
}
internal int InternalMin(ScrollBarOrientation orientation)
{
return min[(int) orientation];
}
internal void InternalMin(ScrollBarOrientation orientation, int value)
{
if (!Handle.Equals(IntPtr.Zero))
{
if (largeChange[(int) orientation] != value)
{
SCROLLINFO si = GetScrollInfo(orientation);
si.nMin = value;
si.fMask &= ~SIF_POS;
SetScrollInfo(orientation, si);
}
}
min[(int) orientation] = value;
}
internal int InternalMax(ScrollBarOrientation orientation)
{
return max[(int) orientation];
}
internal void InternalMax(ScrollBarOrientation orientation, int value)
{
if (!Handle.Equals(IntPtr.Zero))
{
SCROLLINFO si = new SCROLLINFO();
si.nMax = value + largeChange[(int) orientation] - 1;
si.nMin = min[(int) orientation];
si.fMask = SIF_RANGE;
SetScrollInfo(orientation, si);
}
max[(int) orientation] = value;
}
internal bool InternalVisible(ScrollBarOrientation orientation)
{
return visible[(int) orientation];
}
internal void InternalVisible(ScrollBarOrientation orientation, bool
value)
{
if (value != visible[(int) orientation])
{
if (!Handle.Equals(IntPtr.Zero))
{
ShowScrollBar(Handle, (int) orientation, value);
}
}
visible[(int) orientation] = value;
}
internal bool InternalEnabled(ScrollBarOrientation bar)
{
return enabled[0];
}
internal void InternalEnabled(ScrollBarOrientation orientation, bool
value)
{
if (value != enabled[(int) orientation])
{
if (!Handle.Equals(IntPtr.Zero))
{
EnableScrollBar(Handle, ((int) orientation), (value ?
ESB_ENABLE_BOTH : ESB_DISABLE_BOTH));
}
enabled[(int) orientation] = value;
}
}
#endregion
#region Private Implementation
private SCROLLINFO GetScrollInfo(ScrollBarOrientation orientation)
{
SCROLLINFO si = new SCROLLINFO();
si.fMask = SIF_ALL;
si.cbSize = Marshal.SizeOf(si.GetType());
GetScrollInfo(Handle, (int) orientation, ref si);
return si;
}
private void SetScrollInfo(ScrollBarOrientation orientation, SCROLLINFO
si)
{
si.cbSize = Marshal.SizeOf(si.GetType());
SetScrollInfo(Handle, (int) orientation, ref si, true);
}
#endregion
#region Virtuals and Overrides
/// <summary>
/// Raises the <see cref="System.Windows.Forms.Control.HandleCreated"/>
event and creates
/// the scroll bars in their initial state.
/// </summary>
/// <param name="e">Not used.</param>
protected override void OnHandleCreated(EventArgs e)
{
EnableScrollBar(Handle, SB_HORZ, (enabled[0] ? ESB_ENABLE_BOTH :
ESB_DISABLE_BOTH));
for (int i = 0; i < 2; i++)
{
SCROLLINFO si = new SCROLLINFO();
si.cbSize = Marshal.SizeOf(si.GetType());
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMax = max[i] + largeChange[i] - 1;
si.nMin = min[i];
si.nPage = largeChange[i];
si.nPos = pos[i];
SetScrollInfo((ScrollBarOrientation) i, si);
ShowScrollBar(Handle, i, visible[i]);
}
}
/// <summary>
/// Responds to control messages and performs scroll
/// bar processing.
/// </summary>
/// <param name="m">Windows message to process</param>
protected override void WndProc(ref Message m)
{
int nPos = 0;
ControllableScrollEventArgs e = null;
switch (m.Msg)
{
case WM_MOUSEWHEEL:
// High order word is the distance the wheel has been rotated,
// in multiples of WHEEL_DELTA:
int zDelta = 0;
if (((int) m.WParam & 0x8000000) == 0x8000000)
{
// Towards the user:
zDelta = 0x8000 - ((int) m.WParam & 0x7FFF0000) / 0x10000;
}
else
{
zDelta = -((int) m.WParam & 0x7FFF000) / 0x10000;
}
int delta = (zDelta / WHEEL_DELTA) * smallChange[SB_VERT] *
SystemInformation.MouseWheelScrollLines;
MouseEventArgs me = new MouseEventArgs(MouseButtons.None, 0, 0,
0, delta);
OnMouseWheel(me);
if (me.Delta != 0)
{
if (visible[SB_VERT])
{
nPos = InternalValue(ScrollBarOrientation.Vertical);
nPos += delta;
if (nPos >= max[(int) ScrollBarOrientation.Vertical])
{
nPos = max[(int) ScrollBarOrientation.Vertical];
}
if (InternalValue(ScrollBarOrientation.Vertical, nPos))
{
e = new ControllableScrollEventArgs(
ScrollBarOrientation.Vertical,
ScrollEventType.First,
InternalValue(ScrollBarOrientation.Vertical ));
OnScroll(e);
}
m.Result = (IntPtr) 1;
}
}
break;
case WM_VSCROLL:
case WM_HSCROLL:
base.WndProc(ref m);
ScrollBarOrientation orientation =
ScrollBarOrientation.Horizontal;
if (m.Msg == WM_VSCROLL)
{
orientation = ScrollBarOrientation.Vertical;
}
int scrollCode = ((int) m.WParam) & 0xFFFF;
switch (scrollCode)
{
case SB_THUMBTRACK:
SCROLLINFO si = GetScrollInfo(orientation);
if (InternalValue(orientation, si.nTrackPos))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.ThumbTrack, si.nTrackPos);
OnScroll(e);
}
break;
case SB_LEFT: // == SB_TOP
if (InternalValue(orientation, InternalMin(orientation)))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.First,
InternalValue(orientation));
}
OnScroll(e);
break;
case SB_RIGHT: // == SB_BOTTOM
if (InternalValue(orientation, InternalMax(orientation)))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.Last,
InternalValue(orientation));
OnScroll(e);
}
break;
case SB_LINELEFT: // == SB_LINEUP
nPos = InternalValue(orientation);
nPos -= smallChange[(int) orientation];
if (nPos < min[(int) orientation])
{
nPos = min[(int) orientation];
}
if (InternalValue(orientation, nPos))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.SmallDecrement,
InternalValue(orientation));
OnScroll(e);
}
break;
case SB_LINERIGHT: // == SB_LINEDOWN
nPos = InternalValue(orientation);
nPos += smallChange[(int) orientation];
if (nPos >= max[(int) orientation])
{
nPos = max[(int) orientation];
}
if (InternalValue(orientation, nPos))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.SmallIncrement,
InternalValue(orientation));
OnScroll(e);
}
break;
case SB_PAGELEFT: // == SB_PAGEUP
nPos = InternalValue(orientation);
nPos -= largeChange[(int) orientation];
if (nPos < min[(int) orientation])
{
nPos = min[(int) orientation];
}
if (InternalValue(orientation, nPos))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.LargeDecrement,
InternalValue(orientation));
OnScroll(e);
}
break;
case SB_PAGERIGHT: // == SB_PAGEDOWN
nPos = InternalValue(orientation);
nPos += largeChange[(int) orientation];
if (nPos >= max[(int) orientation] )
{
nPos = max[(int) orientation];
}
if (InternalValue(orientation, nPos))
{
e = new ControllableScrollEventArgs(
orientation, ScrollEventType.LargeIncrement,
InternalValue(orientation));
OnScroll(e);
}
break;
case SB_ENDSCROLL:
break;
}
break;
case WM_NCLBUTTONDOWN:
case WM_NCRBUTTONDOWN:
base.WndProc(ref m);
OnScrollClick(new EventArgs());
break;
default:
base.WndProc(ref m);
break;
}
}
/// <summary>
/// Raises the <see cref="Scroll"/> event.
/// </summary>
/// <param name="e"><see cref="ControllableScrollEventArgs"/>
/// describing the scroll event.</param>
protected virtual void OnScroll(ControllableScrollEventArgs e)
{
if (Scroll != null)
{
Scroll(this, e);
}
}
/// <summary>
/// Raises the <see cref="ScrollClick"/> event.
/// </summary>
/// <param name="e">Not used.</param>
protected virtual void OnScrollClick(EventArgs e)
{
if (ScrollClick != null)
{
ScrollClick(this, e);
}
}
#endregion
}
/// <summary>
/// Enables the properties of a scroll bar to read/changed.
/// </summary>
public class ScrollBar
{
/// <summary>
/// Owning control for this instance of the class.
/// </summary>
private ControllableScrollableControl owner = null;
/// <summary>
/// Orientation of this scroll bar.
/// </summary>
private ScrollBarOrientation orientation =
ScrollBarOrientation.Horizontal;
/// <summary>
/// Constructs a new instance of this class.
/// </summary>
/// <param name="owner"><see cref="ControllableScrollableControl"/>
/// which owns this object.</param>
/// <param name="orientation">Scroll Bar orientation for this
object.</param>
internal ScrollBar(ControllableScrollableControl owner,
ScrollBarOrientation orientation)
{
this.owner = owner;
this.orientation = orientation;
}
/// <summary>
/// Gets/sets whether the scroll bar is visible.
/// </summary>
public bool Visible
{
get
{
return owner.InternalVisible(orientation);
}
set
{
owner.InternalVisible(orientation, value);
}
}
/// <summary>
/// Gets/sets whether the scroll bar is enabled.
/// </summary>
public bool Enabled
{
get
{
return owner.InternalEnabled(orientation);
}
set
{
owner.InternalEnabled(orientation, value);
}
}
/// <summary>
/// Gets/sets the large change amount for the scroll bar.
/// </summary>
public int LargeChange
{
get
{
return owner.InternalLargeChange(orientation);
}
set
{
owner.InternalLargeChange(orientation, value);
}
}
/// <summary>
/// Gets/sets the small change amount for the scroll bar.
/// </summary>
public int SmallChange
{
get
{
return owner.InternalSmallChange(orientation);
}
set
{
owner.InternalSmallChange(orientation, value);
}
}
/// <summary>
/// Gets/sets the minimum value of the scroll bar.
/// </summary>
public int Min
{
get
{
return owner.InternalMin(orientation);
}
set
{
owner.InternalMin(orientation, value);
}
}
/// <summary>
/// Gets/sets the maximum value of the scroll bar.
/// </summary>
public int Max
{
get
{
return owner.InternalMax(orientation);
}
set
{
owner.InternalMax(orientation, value);
}
}
/// <summary>
/// Gets/sets the current value of the scroll bar.
/// </summary>
public int Value
{
get
{
return owner.InternalValue(orientation);
}
set
{
owner.InternalValue(orientation, value);
}
}
}
}
|
|