65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 API 控制滚动

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (17投票s)

2004 年 2 月 5 日

2分钟阅读

viewsIcon

133827

downloadIcon

1461

使用 API 进行滚动。

引言

在某些情况下,我们需要能够通过代码控制滚动条。这看起来应该很容易用标准方法完成,但实际上它们隐藏在 API 中。我将告诉你我是如何在正在开发的应用程序中解决这个问题的。

导入

你必须导入 System.Runtime.InteropServices.Marshal 命名空间,这样如果你遇到错误,就可以访问 GetLastWin32Error,这是该命名空间中的一个方法。所以,让我们从 import 指令开始。

Imports System.Runtime.InteropServices.Marshal

常量

除了许多 API 函数之外,还有大量结构、类型和常量可供你使用。对于这一点,我只使用几个常量(我们真的不需要其余的)。但是,如果你想知道其他滚动条常量是什么,请查看 WinUser.h(位于 .NET SDK 目录树中)。这是我将要使用的常量

    ' Scrollbar direction
    '
    Const SBS_HORZ = 0
    Const SBS_VERT = 1


    ' Windows Messages
    '
    Const WM_VSCROLL = &H115
    Const WM_HSCROLL = &H114
    Const SB_THUMBPOSITION = 4

声明函数

现在到了(不那么)有趣的部分,声明函数。我们要使用的第一个函数叫做 GetScrollPos (位于 afxwin.h 中)。我们向这个函数发送一个句柄和一个方向。它返回一个整数,表示当前的滚动位置。

    Private Declare Function GetScrollPos Lib "user32.dll" ( _
            ByVal hWnd As IntPtr, _
            ByVal nBar As Integer) As Integer
            
      'Example: position = GetScrollPos(textbox1.handle, SBS_HORZ)

下一个函数叫做 SetScrollPos,我们向 SetScrollPos 发送句柄、方向、值和一个标志,指示是否应该重绘控件。

    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

   'Example: SetScrollPos(hWnd, SBS_HORZ, position, True

我们要使用的最后一个函数是 PostMessageAPostMessageA 向控件发送关于接下来要做什么的指令。通常,你不需要为此担心,因为它会为你处理。我们向这个函数发送一个句柄、命令、参数和滚动条的 hWnd (可选)。

    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

    'Example: PostMessageA(hWnd, WM_HSCROLL, SB_THUMBPOSITION _
    '                         + &H10000 * position, Nothing)

用法

假设你的表单上有一个名为 textbox1 的控件,并且你想将其滚动到第 100 行。你可以使用 SetScrollPosPostMessageA 轻松完成此操作。以下是完成此操作的一个示例

    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

记住我们的 imports 指令,这就是 GetLastWin32Error 的位置。如果出现问题,GetLastWin32Error 将返回一个数字错误代码。你可以在 WinError.h 文件中查找这些错误代码。

现在,假设你想向下滚动几行,但你不知道你需要滚动到的确切行。你可以使用这三个函数来完成这项任务

    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

好了,关于使用 API 进行滚动就这些了。

我希望这篇文章对你有所帮助。我将包含一个我在探索这些函数时编写的示例应用程序。

© . All rights reserved.