我将记录集Global_rst绑定到DataGrid上,在Global_Rst记录集记录发生变化时,我需要重新绑定,即:
Global_Rst.Requery,这样以后,DataGrid当前指向的记录集将指向第一条,而实际上我当时操作的可能是第100条记录,这样,我用了一个过程:
'刷新表格
Public Sub RefreshGrid()
    On Error Resume Next
    L = Global_Rst.Book
    Global_Rst.Requery
    Call LoadDataRst(Global_Rst)          '负责绑定的过程
    Grid.Book = L
End Sub
即:先记录当前Book的位置,修改后再给表格赋回来.
但是这样做还有一个小问题:比如我当时操作是第100条记录,假设它是当前屏幕的第5条(意思是说当前我在屏幕可见的记录是第96,97,98,99,100,101条....).我修改完成后,这条记录就跑到"当前屏幕的第一条"上了.即当前屏幕为:第100,101,102.....
我现在要实现的就是当前窗口显示的记录的位置不要变.归根结底,是因为Grid.Book=L这句,使表格中可见的记录的第一条为L这条.我想了办法:
取得修改前的滚动条的位置(Pos)值,重新绑定后,再设回去.实际上,我也实现了:
模块中:
Public Declare Function SetScrollPos Lib "user32" (ByVal hWnd As Long, ByVal nBar As Long, ByVal nPos As Long, ByVal bRedraw As Long) As Long
Public Const SB_CTL = 2
Public Declare Function GetScrollPos Lib "user32" (ByVal hWnd As Long, ByVal nBar As Long) As Long
Private Declare Function GetWindowText Lib "user32" _
    Alias "GetWindowTextA" _
   (ByVal hWnd As Long, _
    ByVal lpString As String, _
    ByVal cch As Long) As Long
Public Declare Function EnumChildWindows Lib "user32" _
  (ByVal hWndParent As Long, _
   ByVal lpEnumFunc As Long, _
   ByVal lParam As Long) As Long
Public Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hWnd As Long) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
Public Const SBM_SETPOS = &HE0 ' not in win3.1
Public Const SB_THUMBPOSITION = 4
Public Const WM_VSCROLL = &H115
Public Const SB_THUMBTRACK = 5
Public Const WM_SETCURSOR = &H20Public gsiGridScrollInfo As DataGridScrollInfo
Public Type DataGridScrollInfo
    hWnd As Long
    Pos As Integer
End Type
'找到垂直滚动条的句柄和得到它的当前位置
Public Function EnumChildProc(ByVal hWnd As Long, _
                              ByVal lParam As Long) As Long
    
    Dim buff As String
    Dim nSize As Long
    nSize = GetWindowTextLength(hWnd)
    If nSize > 0 Then
        buff = Space(255)
        GetWindowText hWnd, buff, nSize + 1
        buff = Trim(buff)
        If UCase(Left(buff, Len(buff) - 1)) = Trim(UCase("DataGridSplitVScroll")) Then
            gsiGridScrollInfo.hWnd = hWnd
            MsgBox gsiGridScrollInfo.hWnd
            gsiGridScrollInfo.Pos = GetScrollPos(hWnd, SB_CTL)
        End If
    End If
    EnumChildProc = 1
End Function'刷新表格
Public Sub RefreshGrid()
    On Error Resume Next
    Call EnumChildWindows(Me.Grid.hWnd, AddressOf EnumChildProc, &H0)
    Dim L As Long
    L = Global_Rst.Book
    Global_Rst.Requery
    Call LoadDataRst(Global_Rst)
    Grid.Book = L
    '恢复滚动条位置
    If gsiGridScrollInfo.hWnd <> 0 Then
        SendMessage gsiGridScrollInfo.hwnd, SBM_SETPOS, gsiGridScrollInfo.Pos, CInt(True)
    End If
End Sub这样以后,位置的确变回修改前的值了.但是表格并未刷新.我分析认为,我只是修改了ScrollBar的当前的Pos,并未使DataGrid控件得到得到"滚动条位置已变"这个消息,但是我用如下代码:
'刷新表格
Public Sub RefreshGrid()
    On Error Resume Next
    Call EnumChildWindows(Me.Grid.hWnd, AddressOf EnumChildProc, &H0)
    Dim L As Long
    L = Global_Rst.Book
    Global_Rst.Requery
    Call LoadDataRst(Global_Rst)
    Grid.Book = L
    '恢复滚动条位置
    If gsiGridScrollInfo.hWnd <> 0 Then
        SendMessage gsiGridScrollInfo.hwnd, SBM_SETPOS, gsiGridScrollInfo.Pos, CInt(True)
        Dim m, n As Integer
        m = SB_THUMBTRACK
        n = gsiGridScrollInfo.Pos
        L = n * 2 ^ 16 + m
        SendMessage Me.Grid.hWnd, WM_VSCROLL, L, gsiGridScrollInfo.hWnd
    End If
End Sub
在执行到SendMessage时,提示我"内存不能读",报错退出,有时候不报错直接退出.
我分析的原因可能是DataGrid不能接收我发送的消息?这点需要各位大侠帮忙了!

解决方案 »

  1.   

    相关资料如下:
    WM_VSCROLL
    The WM_VSCROLL message is sent to a window when a scroll event occurs in the window's standard vertical scroll bar. This message is also sent to the owner of a vertical scroll bar control when a scroll event occurs in the control. WM_VSCROLL 
    nScrollCode = (int) LOWORD(wParam); // scroll bar value 
    nPos = (short int) HIWORD(wParam);  // scroll box position 
    hwndScrollBar = (HWND) lParam;      // handle to scroll bar 
     
    Parameters
    nScrollCode 
    Value of the low-order word of wParam. Specifies a scroll bar value that indicates the user's scrolling request. This parameter can be one of the following values: Value Meaning 
    SB_BOTTOM Scrolls to the lower right. 
    SB_ENDSCROLL Ends scroll. 
    SB_LINEDOWN Scrolls one line down. 
    SB_LINEUP Scrolls one line up. 
    SB_PAGEDOWN Scrolls one page down. 
    SB_PAGEUP Scrolls one page up. 
    SB_THUMBPOSITION The user has dragged the scroll box (thumb) and released the mouse button. The nPos parameter indicates the position of the scroll box at the end of the drag operation. 
    SB_THUMBTRACK The user is dragging the scroll box. This message is sent repeatedly until the user releases the mouse button. The nPos parameter indicates the position that the scroll box has been dragged to. 
    SB_TOP Scrolls to the upper left. 
    nPos 
    Value of the high-order word of wParam. Specifies the current position of the scroll box if the nScrollCode parameter is SB_THUMBPOSITION or SB_THUMBTRACK; otherwise, nPos is not used. 
    hwndScrollBar 
    Value of lParam. If the message is sent by a scroll bar, then hwndScrollBar is the handle to the scroll bar control. If the message is not sent by a scroll bar, hwndScrollBar is NULL. 
    Return Values
    If an application processes this message, it should return zero. Res
    The SB_THUMBTRACK notification message is typically used by applications that provide feedback as the user drags the scroll box. If an application scrolls the content of the window, it must also reset the position of the scroll box by using the SetScrollPos function. Note that the WM_VSCROLL message carries only 16 bits of scroll box position data. Thus, applications that rely solely on WM_VSCROLL (and WM_HSCROLL) for scroll position data have a practical maximum position value of 65,535. However, because the SetScrollInfo, SetScrollPos, SetScrollRange, GetScrollInfo, GetScrollPos, and GetScrollRange functions support 32-bit scroll bar position data, there is a way to circumvent the 16-bit barrier of the WM_HSCROLL and WM_VSCROLL messages. See GetScrollInfo for a description of the technique. 
      

  2.   

    http://community.csdn.net/Expert/TopicView.asp?id=3915789
    这是我另一个未能解决的问题.为了学这些,我特意看了Windows程序设计,候捷译的吧,好像是,电子版的,学到不少东西,特别的,我感觉我认为给DataGrid发送这个消息按理说是没有问题的,而且lParam我分解的也是对的,wparam也是我得到的垂直滚动条的Hwnd.如果有索要<Windows程序设计>者,与我联系:1669436     在网上这个应该也有很多,相信看过这本书之后会对使用VB有更深层的理解.特别是API.
      

  3.   

    Public Sub RefreshGrid()
        On Error Resume Next
        j=Grid.row
        L = Global_Rst.Book-j
        Global_Rst.Requery
        Call LoadDataRst(Global_Rst)          '负责绑定的过程
        Grid.Book = L
        Grid.row=j
    End Sub
      

  4.   

    为了这一点小问题有必要这样大动干戈吗~~~~~~建议你换用MSFLEXGRID,我从来不用DBGRID!!
    这样修改完以后也省得你刷新记录集了,速度还快!
      

  5.   

    楼上给的方法行不通!
    被修改的行还是出现在当前屏幕的第一行,而用了你的代码,Grid.Row的确是我刚才的位置了,但是指向的是另外一条记录.
      

  6.   

    Public Sub RefreshGrid()
        On Error Resume Next    L = Grid.Book
        L1 = Grid.FirstRow     Global_Rst.Requery    Grid.FirstRow = L1
        Grid.Book = L
    End Sub
      

  7.   

    OK了.
    of123的方法行得通.谢谢啦!
      

  8.   

    但是我挺希望我的Sendmessage的办法能行得通,这样我就有办法让DataGrid支持滚轮了.