I have it ready faster then I thought. The code below is an unfinished virtual listview. Moving horizontal and vertical scrollbars will execute code from the script, not from the listview itself. You can resize the columns and also the form. I made for this example a little array of 100 records. But it in my original script the listview is filled from a database-file with 30.000 records and it ''loads'' within a millisecond ;) The code is a little mess, because I cut it out from my original script, sorry. You can see the bad behavour from the blue selectbar if you hold the Down key for a while.
USES "ui"
BEGIN CONST
%Listview1 = 13
%ID_SLAVE=14
%timer3=702
%ID_Main_TAB=200
%ID_scrollbarV =9
%ID_scrollbarH =10
%line1=4
END CONST
type LVKEYDOWN
hdr as NMHDR
wVKey as WORD
flags as dword
end type
GLOBAL WindowMain,hslave as long
global reccount as long=100
GLOBAL selecteditem AS LONG=1
GLOBAL lvnm AS NM_LISTVIEW PTR
dim lvitem(100,4) as string
FUNCTION TBMAIN()
for i as long = 1 to 100
lvitem(i,1)="column 1, row " & i
lvitem(i,2)="column 2, row " & i
lvitem(i,3)="column 3, row " & i
lvitem(i,4)=tstr$(I)
next i
DIALOG NEW PIXELS, 0, "Virtual Listview Test", -1,-1, 400,400, %WS_DLGFRAME | %WS_CAPTION | %WS_SYSMENU | %WS_OVERLAPPEDWINDOW | %WS_CLIPSIBLINGS, 0 TO WindowMain
DIALOG SHOW MODAL WindowMain CALL windowmainproc
END FUNCTION
CALLBACK FUNCTION cbSlave()
static lvnm AS NM_LISTVIEW PTR
static pNM_LISTVIEW as NM_LISTVIEW ptr
static pLVKEYDOWN as LVKEYDOWN ptr
SELECT CASE cbMsg
CASE %WM_NOTIFY
SELECT CASE cbCTL
CASE %listview1
lvnm = cblParam
SELECT CASE lvnm.hdr.code
CASE %nm_click
selecteditem=VAL(LISTVIEW_GETITEMTEXT(hslave, %listview1,LISTVIEW_GETNEXTITEM(hslave, %listview1, -1, %LVNI_SELECTED),4))
CASE %NM_SETFOCUS
case %LVN_ITEMCHANGING
CASE %lvn_keydown
LOCAL Inscreen AS BOOLEAN=%false
pLVKEYDOWN = cblparam
select case pLVKEYDOWN.wVKey
case %vk_up
IF selecteditem>1 THEN DECR selecteditem
FOR rij AS LONG = 1 TO VisibleRows
IF selecteditem=VAL(LISTVIEW_GETITEMTEXT(hslave, %listview1,rij,4)) THEN
InScreen=%true
EXIT FOR
END IF
NEXT rij
IF NOT Inscreen THEN
SCROLLBAR_SETPOS(tabdatabase, %ID_ScrollBarV, SCROLLBAR_GETPOS(tabdatabase, %ID_ScrollBarV) - 1)
loadrecords
END IF
case %vk_down
IF selecteditem<reccount THEN INCR selecteditem
FOR rij AS LONG = 1 TO VisibleRows
IF selecteditem=VAL(LISTVIEW_GETITEMTEXT(hslave, %listview1,rij,4)) THEN
InScreen=%true
EXIT FOR
END IF
NEXT rij
IF NOT Inscreen THEN
SCROLLBAR_SETPOS(tabdatabase, %ID_ScrollBarV, SCROLLBAR_GETPOS(tabdatabase, %ID_ScrollBarV)+1)
loadrecords
END IF
end select
END SELECT
END SELECT
END SELECT
END FUNCTION
CALLBACK FUNCTION cb_Tab_1()
LOCAL I,w,h AS LONG
SELECT CASE cbMsg
CASE %WM_INITDIALOG
DIALOG GET CLIENT CBHNDL TO w, h
DIALOG NEW PIXELS, CBHNDL, "", 1, 38, w - 22, h - 100, %WS_CHILD TO hSlave
DIALOG SHOW MODELESS hSlave, CALL cbSlave
DIALOG GET CLIENT hSlave TO w, h
CONTROL ADD LISTVIEW hslave, %listview1, "", 0,0, w + WIN_GETSYSTEMMETRICS(%SM_CXVSCROLL),h + WIN_GETSYSTEMMETRICS(%SM_CXHSCROLL), %LVS_SINGLESEL | %WS_VISIBLE | %WS_CHILD | %LVS_SHOWSELALWAYS, %LVS_EX_FULLROWSELECT | %LVS_EX_LABELTIP | %LVS_EX_GRIDLINES
LISTVIEW_SETVIEW hSlave, %listview1, %LV_VIEW_DETAILS
LISTVIEW_INSERTCOLUMN hslave, %listview1, 1, 100, "Column 1", %LVCF_FMT | %LVCF_TEXT | %LVCF_WIDTH, %LVCFMT_LEFT
LISTVIEW_INSERTCOLUMN hslave, %listview1, 2, 100, "Column 2", %LVCF_FMT | %LVCF_TEXT | %LVCF_WIDTH, %LVCFMT_LEFT
LISTVIEW_INSERTCOLUMN hslave, %listview1, 3, 100, "Column 3", %LVCF_FMT | %LVCF_TEXT | %LVCF_WIDTH, %LVCFMT_LEFT
LISTVIEW_INSERTCOLUMN hslave, %listview1, 4, 0, "Hidden Column", %LVCF_FMT | %LVCF_TEXT | %LVCF_WIDTH, %LVCFMT_LEFT
CONTROL ADD SCROLLBAR, cbhndl, %ID_ScrollBarV, "", w,56,17,h-17, %SBS_VERT CALL cb_SBV_proc
CONTROL ADD SCROLLBAR, cbhndl, %ID_ScrollBarH, "", 1,38+h,w,17, %SBS_HORZ CALL cb_SBH_proc
CONTROL DISABLE cbhndl, %ID_ScrollBarV
CONTROL DISABLE cbhndl, %ID_ScrollBarH
CONTROL ADD LINE, cbhndl, %line1, "",0, 36, w+19, h+21
SCROLLBAR_SETRANGE(cbhndl,%ID_ScrollBarH,1,kolbreedte)
SCROLLBAR_SETPAGESIZE(cbhndl, %ID_ScrollBarH,w)
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, 1)
loadrecords
DIALOG SET TIMER windowmain,%timer3,15
CASE %WM_PAINT
CONTROL REDRAW hslave,%listview1
CASE %WM_SIZE
DIALOG GET CLIENT CBHNDL TO w, h
DIALOG SET SIZE hslave,w-22,h-100
DIALOG GET CLIENT hSlave TO w, h
CONTROL SET LOC cbhndl, %ID_ScrollBarV, w,56
CONTROL SET SIZE cbhndl, %ID_ScrollBarV,-1,h-17
CONTROL SET LOC cbhndl, %ID_ScrollBarH, 0,38+h
CONTROL SET SIZE cbhndl, %ID_ScrollBarH,w,-1
CONTROL SET SIZE cbhndl, %line1, w+19, h+21
LOCAL x,y AS LONG
CONTROL GET SIZE cbhndl, %ID_ScrollBarH TO x,y
CONTROL SET SIZE hSlave, %listview1, x+17, h+17
CONTROL SET LOC hslave,%listview1,-SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarH) ,-1
SCROLLBAR_SETPAGESIZE(cbhndl, %ID_ScrollBarH,w)
SCROLLBAR_SETRANGE(cbhndl,%ID_ScrollBarH,1,kolbreedte)
loadrecords
END SELECT
END FUNCTION
FUNCTION kolbreedte() AS LONG
LOCAL i,kol AS LONG
FOR i=1 TO 4
kol+=LISTVIEW_GETCOLUMNWIDTH(hslave, %listview1, i)
NEXT i
FUNCTION=kol
END FUNCTION
CALLBACK FUNCTION cb_SBV_proc() AS LONG
SELECT CASE cbmsg
CASE %WM_VSCROLL
SELECT CASE LOWRD(cbwParam)
CASE %SB_TOP
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETRANGELOW(cbhndl, %ID_ScrollBarV))
CASE %SB_BOTTOM
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETRANGEHI(cbhndl, %ID_ScrollBarV))
CASE %SB_LINEUP
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarV) - 1)
CASE %SB_LINEDOWN
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarV) + 1)
CASE %SB_PAGEUP
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarV) - SCROLLBAR_GETPAGESIZE(cbhndl, %ID_ScrollBarV))
CASE %SB_PAGEDOWN
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarV) + SCROLLBAR_GETPAGESIZE(cbhndl, %ID_ScrollBarV))
CASE %SB_THUMBTRACK
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarV, SCROLLBAR_GETTRACKPOS(cbhndl, %ID_ScrollBarV))
END SELECT
loadrecords
END SELECT
END FUNCTION
CALLBACK FUNCTION cb_SBH_proc() AS LONG
LOCAL w,h AS LONG
CONTROL SET SIZE hSlave, %listview1, kolbreedte , -1
DIALOG GET CLIENT hslave TO w, h
SCROLLBAR_SETPAGESIZE(cbhndl, %ID_ScrollBarH,w)
SCROLLBAR_SETRANGE(cbhndl,%ID_ScrollBarH,1,kolbreedte)
SELECT CASE cbmsg
CASE %WM_HSCROLL
SELECT CASE LOWRD(cbwParam)
CASE %SB_TOP
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETRANGELOW(cbhndl, %ID_ScrollBarH))
CASE %SB_BOTTOM
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETRANGEHI(cbhndl, %ID_ScrollBarH))
CASE %SB_LINEUP 'links
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarH) - 5)
CASE %SB_LINEDOWN 'rechts
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarH) + 5)
CASE %SB_PAGEUP
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarH) - SCROLLBAR_GETPAGESIZE(cbhndl, %ID_ScrollBarH))
CASE %SB_PAGEDOWN
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarH) + SCROLLBAR_GETPAGESIZE(cbhndl, %ID_ScrollBarH))
CASE %SB_THUMBTRACK
SCROLLBAR_SETPOS(cbhndl, %ID_ScrollBarH, SCROLLBAR_GETTRACKPOS(cbhndl, %ID_ScrollBarH))
END SELECT
CONTROL SET LOC hslave,%listview1,-SCROLLBAR_GETPOS(cbhndl, %ID_ScrollBarH) ,-1
END SELECT
END FUNCTION
CALLBACK FUNCTION cb_Tab_2() 'HELP TAB
LOCAL xx,yy AS LONG
SELECT CASE cbMsg
CASE %WM_INITDIALOG
CASE %WM_SIZE
CASE %WM_DESTROY
END SELECT
END FUNCTION
CALLBACK FUNCTION WindowMainProc() AS LONG 'Callback for dialog
SELECT CASE CBMSG 'Test for messages
CASE %WM_INITDIALOG
LOCAL xpos,ypos,sbWidth, sbHeight AS LONG
DIALOG GET CLIENT cbhndl TO xPos, yPos
CONTROL ADD TAB, cbhndl, %ID_Main_TAB, "", 0, 0, xpos, ypos - sbHeight
TAB_PAGEINSERT cbhndl, %ID_Main_TAB, 1, 0, "Virtual Listview" CALL cb_Tab_1
TAB_PAGEINSERT cbhndl, %ID_Main_TAB, 2, 0, "Nothing" CALL cb_Tab_2
CONTROL SET RESIZE cbhndl, %ID_Main_TAB, 1, 1, 1, 1
CONTROL UNTHEME cbhndl, %id_main_tab
GLOBAL TabDatabase AS LONG = TAB_PAGEGETHANDLE(cbhndl, %ID_Main_TAB, 1)
CASE %WM_TIMER
SELECT CASE cbwparam
CASE %timer3
SetScrollbars
END SELECT
CASE %WM_SIZE
TAB_ONRESIZE(cbhndl, %ID_Main_TAB)
CASE %WM_DESTROY
TAB_ONDESTROY(cbhndl, %ID_Main_TAB)
CASE %WM_NOTIFY
SELECT CASE cbCTL
CASE %ID_Main_TAB
TAB_ONNOTIFY(cbhndl, %ID_Main_TAB, cblparam)
END SELECT
CASE %WM_COMMAND
CASE %WM_CLOSE
DIALOG KILL TIMER windowmain,%timer3
STOP
END SELECT
END FUNCTION
FUNCTION SetScrollbars()
LOCAL w,h AS LONG
DIALOG GET CLIENT hSlave TO w, h
IF kolbreedte>w THEN
CONTROL ENABLE tabdatabase, %ID_ScrollBarH
SCROLLBAR_SETPAGESIZE(tabdatabase, %ID_ScrollBarH,w)
SCROLLBAR_SETRANGE(tabdatabase,%ID_ScrollBarH,1,kolbreedte)
ELSE
CONTROL DISABLE tabdatabase, %ID_ScrollBarH
END IF
IF RecCount>VisibleRows THEN
CONTROL ENABLE tabdatabase, %ID_ScrollBarV
ELSE
CONTROL DISABLE tabdatabase, %ID_ScrollBarV
END IF
IF LISTVIEW_GETCOLUMNWIDTH(hslave, %listview1, 4)>0 THEN LISTVIEW_SETCOLUMNWIDTH(hslave, %listview1, 4,0)
FOR rij AS LONG = 1 TO VisibleRows
IF selecteditem=VAL(LISTVIEW_GETITEMTEXT(hslave, %listview1,rij,4)) THEN
LISTVIEW_SETITEMSELECTED(hslave, %listview1, rij, %true)
exit for
END IF
NEXT rij
END FUNCTION
FUNCTION visiblerows() AS LONG
LOCAL x,y AS LONG
CONTROL GET SIZE tabdatabase,%ID_ScrollBarV TO x,y
FUNCTION =int(y/14)
END FUNCTION
FUNCTION loadrecords()
LOCAL rij,BlueRow,i AS LONG
SCROLLBAR_SETPAGESIZE(tabdatabase, %ID_ScrollBarV,visiblerows)
SCROLLBAR_SETRANGE(tabdatabase, %ID_ScrollBarV, 1,RecCount)
I=SCROLLBAR_GETPOS(tabdatabase, %ID_ScrollBarV)
LISTVIEW_BEGINUPDATE hslave, %listview1
LISTVIEW_DELETEALLITEMS hslave, %listview1
FOR rij = 1 TO VisibleRows
IF i>reccount THEN EXIT FOR
IF i=selecteditem THEN BlueRow=rij
LISTVIEW_INSERTITEM(hslave, %listview1, rij,lvitem(i,1) & "|" & lvitem(i,2) & "|" & lvitem(i,3)& "|" & lvitem(i,4))
INCR i
NEXT rij
IF BlueRow>0 THEN
LISTVIEW_SETITEMSELECTED(hslave, %listview1, BlueRow, %true)
LISTVIEW_ENSUREVISIBLE(hslave,%listview1,BlueRow,%false)
END IF
LISTVIEW_ENDUPDATE hslave, %listview1
eND FUNCTION