
Introduction
This article show how to customize a System.Windows.Forms.Panel
to use effectively scrollbars with the AutoScroll
property. In this example, you can change enable or visible property of each
scrollbar of the panel, receive scrolling events, send events to the panel and
change and receive the positions of both scrollbars.
Background
With .Net, use a panel with Autoscroll
property is
really useful, but you can not receive events of scrollbars and personalize some
functionalities like visible or enable properties of only one scrollbar for
example.
Using the code
In your solution, add the file ScrollablePanel.cs to your C# project.
Then, you can change type of a panel in your project by the ScrollablePanel
type. Sorry but I have no time to make a visual
component in a DLL.
Now you have new properties to your panel object:
int AutoScrollHPos
: To get or set the horizontal
scrollbar position
int AutoScrollVPos
: To get or set the vertical
scrollbar position
int AutoScrollHorizontalMinimum
: To get or set the
horizontal scrollbar minimum range
int AutoScrollHorizontalMaximum
: To get or set the
horizontal scrollbar maximum range
int AutoScrollVerticalMinimum
: To get or set the
vertical scrollbar minimum range
int AutoScrollVerticalMaximum
: To get or set the
vertical scrollbar maximum range
bool EnableAutoScrollHorizontal
: Enable horizontal
scrollbar
bool EnableAutoScrollVertical
: Enable vertical
scrollbar
bool VisibleAutoScrollHorizontal
: Visible horizontal
scrollbar
bool VisibleAutoScrollVertical
: Visible vertical
scrollbar
And your panel have now some new events:
public event System.Windows.Forms.ScrollEventHandler
ScrollHorizontal
: receive when the horizontal scroll bar move
public event System.Windows.Forms.ScrollEventHandler
ScrollVertical
: receive when the vertical scroll bar move
public event System.Windows.Forms.MouseEventHandler
ScrollMouseWheel
: receive when mouse wheel move
Explanations about code in the ScrollablePanel
class:
First you must create a new class that overrode the System.Windows.Forms.Panel
. So, you must override the WndProc
function to receive API32 scrolling messages and then to
send .Net ScrollEvents
.
protected override void WndProc(ref Message msg)
{
base.WndProc(ref msg);
if (msg.HWnd != this.Handle)
return;
switch (msg.Msg)
{
case WM_VSCROLL:
try
{
ScrollEventType type = getScrollEventType(msg.WParam);
ScrollEventArgs arg = new ScrollEventArgs(type,
GetScrollPos(this.Handle, (int)SB_VERT));
this.ScrollVertical(this, arg);
}
catch (Exception) { }
break;
case WM_HSCROLL:
try
{
ScrollEventType type = getScrollEventType(msg.WParam);
ScrollEventArgs arg = new ScrollEventArgs(type,
GetScrollPos(this.Handle, (int)SB_HORZ));
this.ScrollHorizontal(this, arg);
}
catch (Exception) { }
break;
default:
break;
}
}
Then, you can see that you are using two main functions:
GetScrollPos
and some
const
from Win32 API.
Analyze the source code to see how are calle the Win32 API functions, like it
for example:
[DllImport("user32.dll")]
static public extern int GetScrollPos(System.IntPtr hWnd,
int nBar);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, uint Msg,
UIntPtr wParam, IntPtr lParam);
...
Note that sometimes, you need the C++ MACRO to get
HIWORD
or
LOWORD
from a
WParam
of a message for example. I use these two functions that
seem to be good:
private static int HiWord(int number)
{
if ((number & 0x80000000) == 0x80000000)
return (number >> 16);
else
return (number >> 16) & 0xffff ;
}
private static int LoWord(int number)
{
return number & 0xffff;
}
private static int MakeLong(int LoWord, int HiWord)
{
return (HiWord << 16) | (LoWord & 0xffff);
}
private static IntPtr MakeLParam(int LoWord, int HiWord)
{
return (IntPtr) ((HiWord << 16) | (LoWord & 0xffff));
}
That's all, enjoy with it in the hope that it will be useful for you...
History
- Version 1.0: receive all scrolling events and mouse wheel. Send scroll
events to your panel. Get or obtain the mouse wheel delta, and
ScrollEventType
. The range doesn't look like to work for the
moment.