Introduction
In certain circumstances, we need to be able to control the scroll bars from our code. This may seem like it should be easily done with standard methods when in fact they are buried in the API. I will tell you how I solved this problem in the application I am working on.
Imports
You have to import
the System.Runtime.InteropServices.Marshal
namespace so if you get an error you can access GetLastWin32Error
, a method in this namespace. So, let's begin with the import
directive.
Imports System.Runtime.InteropServices.Marshal
Constants
Along with many API functions, there are a slew of structures, types and constants that are at your disposal. For this, I am only going to use a few constants (we really don't need the rest). However, if you are wondering what the other scrollbar constants are, take a look at WinUser.h (located in the .NET SDK directory tree). Here are the constants I will be using:
Const SBS_HORZ = 0
Const SBS_VERT = 1
Const WM_VSCROLL = &H115
Const WM_HSCROLL = &H114
Const SB_THUMBPOSITION = 4
Declaring the functions
Now comes the (not so) fun part of declaring the functions. The first function we are going to be using is called GetScrollPos
(located in afxwin.h). We send this function a handle and a direction. It sends back an integer of the current scroll position.
Private Declare Function GetScrollPos Lib "user32.dll" ( _
ByVal hWnd As IntPtr, _
ByVal nBar As Integer) As Integer
The next function is called SetScrollPos
, we send SetScrollPos
the handle, direction, value and a flag of whether or not it should redraw the control.
Private Declare Function SetScrollPos Lib "user32.dll" ( _
ByVal hWnd As IntPtr, _
ByVal nBar As Integer, _
ByVal nPos As Integer, _
ByVal bRedraw As Boolean) As Integer
The last function we will be using is PostMessageA
. PostMessageA
sends instructions to the control about what to do next. Normally, you don't have to worry about this as it is handled for you. We send this function a handle, command, parameters and the hWnd of the scroll bar (optional).
Private Declare Function PostMessageA Lib "user32.dll" ( _
ByVal hwnd As IntPtr, _
ByVal wMsg As Integer, _
ByVal wParam As Integer, _
ByVal lParam As Integer) As Boolean
Usage
Suppose you have a control called textbox1
on your form and you want to scroll it to line 100. You can do this easily using SetScrollPos
and PostMessageA
. Here is an example of how this can be accomplished:
If (SetScrollPos(hWnd, SBS_HORZ, position, True) <> -1) Then
PostMessageA(hWnd, WM_HSCROLL, SB_THUMBPOSITION +_
&H10000 * position, Nothing)
Else
MsgBox("Can't set info (Err: " & GetLastWin32Error() & ")")
End If
Remember our imports
directive, this is where GetLastWin32Error
is located. GetLastWin32Error
will return a numeric error code if there is a problem. You can look these error codes up in the WinError.h file.
Now, suppose you want to scroll down a few lines but you don't know where exactly the line you need to scroll to. You can use all three of these functions to accomplish this task:
Dim Position = GetScrollPos(hWnd, SBS_VERT) + 20
If (SetScrollPos(hWnd, SBS_VERT, position, True) <> -1) Then
PostMessageA(hWnd, WM_VSCROLL, SB_THUMBPOSITION + _
&H10000 * position, Nothing)
Else
MsgBox("Can't set info (Err: " & GetLastWin32Error() & ")")
End If
Well, that's about it for scrolling with API.
I hope you found this article informative. I will include a sample application that I wrote as I was exploring these functions.