Виртуальный ListView

Два примера виртуального списка. Один с использованием библиотеки Window9 (а значит проще), второй на чистом API. В примерах идет заполнение списка в четыре колонки по 50000 строковых значений. При выделении какого нибудь пункта и последующего нажатия правой кнопки мыши, отображается значение из этого пункта.

Автор: Станислав Будинов.

virtuallistview.jpeg

C использованием Библиотеки Window9

#INCLUDE "window9.bi"

Dim Shared As Integer Count=50000
Dim Shared As String array(Count ,3)
#DEFINE Style LVS_OWNERDATA Or LVS_REPORT
#DEFINE ExStyle LVS_EX_FULLROWSELECT Or LVS_EX_GRIDLINES Or LVS_EX_SUBITEMIMAGES

Function WinProc(hwnd As hwnd, msg As UINT, wParam As WPARAM, lParam As lparam) As Integer
    Select Case  msg
        Case WM_NOTIFY
            Dim Nmhdr As NMHDR Ptr=Cast(NMHDR Ptr,lParam)
            Select Case  Nmhdr->code
                Case LVN_GETDISPINFO
                    Dim Ndisp As NMLVDISPINFO Ptr = Cast(NMLVDISPINFO Ptr,lParam)
                    If Ndisp->item.mask And LVIF_TEXT Then
                        Ndisp->item.pszText = Strptr(array(Ndisp->item.iItem,Ndisp->item.iSubItem))
                    Endif
                Case NM_RCLICK
                    SetGadgetText(2,GetTextItemListView(1,GetItemListView(),GetSubItemListView()))
            End Select
    End Select
    Return 0
End Function

OpenWindow("Виртуальный список", 0, 0, 490, 350)
ListViewGadget(1,10,10,440,250,ExStyle,Style)
AddListViewColumn(1,"Column1",0,1,110)
AddListViewColumn(1,"Column2",1,2,110)
AddListViewColumn(1,"Column3",2,3,110)
AddListViewColumn(1,"Column4",3,4,110)
TextGadget(2,100,280,140,20,"номер")
ButtonGadget(3,300,280,140,20,"Заполнить список")
SetWindowCallback(Cast(Integer,@WinProc()))

Do
    Select Case WaitEvent()
        Case EventGadget
            Select Case EventNumber
                Case 3
                    DeleteListViewItemsAll(1)
                    SendMessage(GadgetID(1), LVM_SETITEMCOUNT, Count,1 )
                    For a As Integer = 0 To Count
                        array(a,0) = "1_" & a
                        array(a,1) = "2_" & a
                        array(a,2) = "3_" & a
                        array(a,3) = "4_" & a
                    Next
            End Select
        Case EventClose
            Exit Do
    End Select
Loop

На чистом API

#INCLUDE "windows.bi"
#INCLUDE Once "win\commctrl.bi"
InitCommonControls()
Type LV_ITEM
    As UINT         mask
    As Integer      iItem
    As Integer      iSubItem
    As UINT         state
    As UINT         stateMask
    As LPTSTR       pszText
    As Integer      cchTextMax
    As Integer      iImage
    As LPARAM       lParam
End Type
Dim Shared As Integer Count=50000
Dim Shared As String array(Count ,3)
Dim Shared As HINSTANCE Hinst
Dim Shared As HWND LWHwnd,BnHwnd,StHwnd
Dim msg As MSG
Dim As WNDCLASSEX wc
Dim As String NameClass="MyClass"
Hinst=GetModuleHandle(0)
#DEFINE StyleLW LVS_OWNERDATA Or LVS_REPORT Or WS_VISIBLE Or WS_CHILD
#DEFINE ExStyle LVS_EX_FULLROWSELECT Or LVS_EX_GRIDLINES

Function wndproc(hwnd As HWND, msg As Uinteger,_
    wparam As WPARAM, lparam As LPARAM) As Integer
    Select Case msg
        Case WM_CREATE
            LWHwnd=CreateWindowEx(0,"SysListView32","",StyleLW,10,10,440,250,hWnd,Cast(HMENU,1),HINST,0)
            StHwnd=CreateWindowEx(0,"Static","Number",WS_VISIBLE Or WS_CHILD,100,280,140,20,hWnd,Cast(HMENU,2),HINST,0)
            BnHwnd=CreateWindowEx(0,"button","Go",WS_VISIBLE Or WS_CHILD,300,280,140,20,hWnd,Cast(HMENU,3),HINST,0)
            Dim As LVCOLUMN LVS9
            Dim As String column="Column_",TCol
            For i As Integer=1 To 4
                TCol=column & i
                LVS9.mask=LVCF_FMT Or LVCF_SUBITEM Or LVCF_TEXT Or LVCF_WIDTH
                LVS9.fmt=LVCFMT_CENTER
                LVS9.cx=110
                LVS9.pszText =StrPtr(Tcol)
                LVS9.cchTextMax = Len(column)+1
                LVS9.iSubItem = i
                SendMessage(LWHwnd,LVM_INSERTCOLUMN,i-1,Cast(LPARAM,@LVS9))
            Next
            SendMessage(LWHwnd,LVM_SETEXTENDEDLISTVIEWSTYLE,0 ,Cast(LPARAM,ExStyle))
        Case WM_COMMAND
            Select Case Loword(wparam)
                Case 3
                    SendMessage(LWHwnd,LVM_DELETEALLITEMS,0,0)
                    SendMessage(LWHwnd, LVM_SETITEMCOUNT, Count,1 )
                    For a As Integer = 0 To Count
                        array(a,0) = "1_" & a
                        array(a,1) = "2_" & a
                        array(a,2) = "3_" & a
                        array(a,3) = "4_" & a
                    Next
            End Select
        Case WM_NOTIFY
            Dim Nmhdr As NMHDR Ptr=Cast(NMHDR Ptr,lParam)
            Select Case  Nmhdr->code
                Case LVN_GETDISPINFO
                    Dim Ndisp As NMLVDISPINFO Ptr = Cast(NMLVDISPINFO Ptr,lParam)
                    If Ndisp->item.mask And LVIF_TEXT Then
                        Ndisp->item.pszText = Strptr(array(Ndisp->item.iItem,Ndisp->item.iSubItem))
                    Endif
                Case NM_RCLICK
                    Dim buf As String*256
                    Dim act_ As LPNMITEMACTIVATE=Cast(LPNMITEMACTIVATE,Nmhdr)
                    Dim LV_ITEM As LV_ITEM
                    LV_ITEM.iSubItem=act_->iSubItem
                    LV_ITEM.pszText= Cast(LPSTR,@buf)
                    LV_ITEM.cchTextMax=256
                    SendMessage(LWHwnd,LVM_GETITEMTEXT,act_->iItem,Cast(lparam,@LV_ITEM))
                    SetWindowText(StHwnd,buf)
            End Select
        Case WM_DESTROY
            PostQuitMessage(0)
    End Select
    Return DefWindowProc(hwnd,msg,wparam,lparam)
End Function

With wc
    .cbSize=SizeOf(WNDCLASSEX)
    .style=CS_HREDRAW Or CS_VREDRAW
    .lpfnWndProc=@wndproc
    .hInstance=Hinst
    .hIcon=LoadIcon(0,IDI_QUESTION)
    .hCursor=LoadCursor(0,IDC_ARROW)
    .hbrBackground=Cast(HBRUSH,COLOR_WINDOW)
    .lpszClassName=StrPtr(NameClass)
    .hIconSm=.hIcon
End With

If RegisterClassEx(@wc)=0 Then
    Print "Register error, press any key"
    Sleep
    End
Endif

CreateWindowEx(0,NameClass,"Virtual ListView",_
WS_VISIBLE Or WS_OVERLAPPEDWINDOW,100,100,480,350,0,0,Hinst,0)

While GetMessage(@msg,0,0,0)
    TranslateMessage(@msg)
    DispatchMessage(@msg)
Wend