To determine the index of the first visible line in a multiline TextBox control you only need to send it the EM_GETFIRSTVISIBLELINE message:
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal _ hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, _ lParam As Any) As LongConst EM_GETFIRSTVISIBLELINE = &HCEFirstVisibleLine = SendMessage(Text1.hwnd, EM_GETFIRSTVISIBLELINE, 0, ByVal 0&)
The previous of code returns the index of the first visible line (0 for the first line in the TextBox). When applied to a single-line control, this code returns the index of the first visible character (0 for the first character in the Text property).