'WIP - Work in Progress - not complete -
'Everybody is invited to improve this code
$ filename "LV_cell_selection.exe"
'uses rtl32
'uses rtl64
uses WinUtil
% LVCF_FMT 1
% LVCF_WIDTH 2
% LVCF_TEXT=4
% LVCF_SUBITEM 8
% LVIF_TEXT=1
% LVIF_PARAM=4
% LVIF_STATE=8
% LVIS_FOCUSED=1
% LVN_ITEMCHANGING= -100
% LVM_INSERTITEM=4103
% LVM_SETITEM=4102
% LVM_INSERTCOLUMN=4123
% LVM_SETEXTENDEDLISTVIEWSTYLE= 4150
% LVM_SETCOLUMNWIDTH=4126
% LVS_REPORT=1
% LVM_ENSUREVISIBLE=4115
% LVS_SINGLESEL=4
% LVS_SHOWSELALWAYS=8
% LVS_EX_GRIDLINES=1
% LVS_EX_FULLROWSELECT=32
% LVSCW_AUTOSIZE_USEHEADER= -2
% NM_CLICK= -2
% NM_CUSTOMDRAW= -12
% GWLP_WNDPROC= -4
% CDRF_DODEFAULT=0
% CDRF_NOTIFYITEMDRAW=32
% CDRF_NOTIFYSUBITEMDRAW=32
% CDDS_PREPAINT=1
% CDDS_ITEM=65536
% CDDS_SUBITEM=131072
type NMHDR
sys hwndFrom
sys idFrom 'uint ptr
'uint code
sys code
end type
type LVCOLUMN
uint mask
int fmt
int cx
char* pszText
int cchTextMax
int iSubItem
int iImage
int iOrder
int cxMin
int cxDefault
int cxIdeal
end type
typedef LVCOLUMN LV_COLUMN
type LVITEM
uint mask
int iItem
int iSubItem
uint state
uint stateMask
char* pszText
int cchTextMax
int iImage // index of the list view item's icon
sys lParam // 32-bit value to associate with item
int iIndent
int iGroupId
uint cColumns
'uint *puColumns
'int *piColFmt
'int iGroup
end type
typedef LVITEM LV_ITEM
type NMLISTVIEW
NMHDR hdr
int iItem
int iSubItem
UINT uNewState
UINT uOldState
UINT uChanged
POINT ptAction
sys lParam
end type
typedef NMLISTVIEW NM_LISTVIEW
type NMCUSTOMDRAW
NMHDR hdr
DWORD dwDrawStage
sys hdc
RECT rc
sys dwItemSpec 'DWORD_PTR
UINT uItemState
sys lItemlParam
end type
type NMLVCUSTOMDRAW
NMCUSTOMDRAW nmcd
int clrText 'COLORREF
int clrTextBk 'COLORREF
int iSubItem
DWORD dwItemType
int clrFace 'COLORREF
int iIconEffect
int iIconPhase
int iPartId
int iStateId
RECT rcText
UINT uAlign
end type
macro ListView_InsertColumn(hwnd,iCol,pcol) (SendMessage(hwnd, LVM_INSERTCOLUMN, iCol, pcol))
macro ListView_InsertItem(hwnd,pitem) (SendMessage(hwnd, LVM_INSERTITEM,0, pitem))
macro ListView_SetItem(hwnd,pitem) (SendMessage(hwnd, LVM_SETITEM, 0, pitem))
sub ListView_Insert_Column(sys hwnd, int id, col, string Expr, int width, int fmt)
LV_COLUMN lvc
lvc.mask = LVCF_FMT OR LVCF_WIDTH OR LVCF_TEXT OR LVCF_SUBITEM
lvc.fmt = fmt
lvc.pszText = Expr
lvc.cx = width
ListView_InsertColumn(GetDlgItem(hwnd, id), col-1, &lvc)
end sub
sub ListView_Insert_Item(sys hwnd, int id, row, image, string Expr)
LV_ITEM lvi
lvi.stateMask = LVIS_FOCUSED
lvi.mask = LVIF_TEXT
lvi.pszText = Expr
lvi.iItem = row
ListView_InsertItem(GetDlgItem(hwnd,id), &lvi)
end sub
sub ListView_Set_Text(sys hwnd, int id, row, col, string Expr)
LV_ITEM lvi
if col=1 then
lvi.mask = LVIF_TEXT or LVIF_STATE or lVIF_PARAM
else
lvi.mask = LVIF_TEXT or LVIF_STATE
end if
lvi.pszText = Expr
lvi.iItem = row-1
lvi.iSubItem = col-1
ListView_SetItem(GetDlgItem(hwnd,id), &lvi)
end sub
function MAX(int num1, num2) as int
if num1 > num2 then return num1
return num2
end function
function MIN(int num1, num2) as int
if num1 < num2 then return num1
return num2
end function
% IDC_ListView = 500
sys hMainWin, hListView ', int SortDirection
int MaxRow, MaxCol, CurrentRow, CurrentCol
sys OrigLVProc
'Load the common controls library...
INITCOMMONCONTROLSEXt icce
icce.dwSize = sizeof(INITCOMMONCONTROLSEXt)
icce.dwICC = 0xffff
InitCommonControlsEx(&icce)
char* cmdline
&cmdline=GetCommandLine()
sys hInstance = GetModuleHandle(null)
declare sub CreateLVData(sys hwnd)
declare sub UpdateTitleBar(sys hwnd)
declare function CustomDraw(NMLVCUSTOMDRAW* pcd) as sys
MainWindow 420,260,WS_OVERLAPPEDWINDOW
function WndProc(sys hwnd, uint uMsg, sys wParam, lParam) as sys callback
int i,j
NM_LISTVIEW *lpLvNm
NMLVCUSTOMDRAW *lpLvCd
NMHDR *pnmhdr
select uMsg
case WM_CREATE
uint Style = WS_CHILD or WS_VISIBLE or LVS_REPORT or WS_TABSTOP or LVS_SHOWSELALWAYS or LVS_SINGLESEL
uint StyleEx = WS_EX_CLIENTEDGE
hListView = CreateWindowEx(StyleEx, "SysListView32", "",Style,
10,10,360,200,
hwnd, IDC_LISTVIEW, hInstance, null)
if hListview=null then mbox "Error: Cannot create Listview"
SendMessage(hListview, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_FULLROWSELECT or LVS_EX_GRIDLINES)
'initialize data/location
CreateLVData(hwnd)
CurrentRow = 1 : CurrentCol = 1
UpdateTitleBar(hwnd)
SetFocus(hListview)
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, 1)
'subclass LV
OrigLVProc = SetWindowLongPtr(hListView, GWLP_WndProc, @NewLVProc)
case WM_NOTIFY
@pnmhdr=lParam
select case pnmhdr.idFrom
case IDC_ListView
select case pnmhdr.code
case LVN_ITEMCHANGING
return 1
case NM_CLICK
&LpLvNm=lParam
CurrentRow = LpLvNm.iiTem + 1
CurrentCol = LpLvNm.iSubItem + 1
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, 1)
SetFocus(hListview)
UpdateTitleBar(hwnd)
case NM_CUSTOMDRAW
&lpLvCd=lParam
return CustomDraw(lpLvCd)
end select
end select
case WM_SIZE:
RECT rc
GetClientRect(hWnd, &rc)
MoveWindow(hListview, rc.left, rc.top, rc.right, rc.bottom, 1)
SendMessage(hListview, LVM_SETCOLUMNWIDTH, 1, LVSCW_AUTOSIZE_USEHEADER)
case WM_CLOSE
DestroyWindow(hwnd)
case WM_DESTROY
SetWindowLongPtr(hListView, GWLP_WNDPROC, OrigLVProc)
PostQuitMessage(0)
case else
return DefWindowProc(hwnd, uMsg, wParam, lParam)
end select
end function
'=========================
sub CreateLVData(sys hwnd)
int i,j
MaxRow=50 : MaxCol=10
LV_COLUMN lvc
for i = 1 to MaxCol
Listview_insert_column (hwnd, IDC_ListView, i, "Col " + str(i), 100, 0)
next i
for i = 1 to MaxRow
Listview_insert_item (hwnd, IDC_ListView, i, 0, "Row " + str(i) + " Col 1")
for j = 1 to MaxCol
Listview_set_text (hwnd, IDC_ListView, i, j, "Row " + str(i) + " Col " + str(j))
next j
next i
end sub
'==================
sub UpdateTitleBar(sys hwnd)
SetWindowText (hwnd, "ListView Grid Demo: " + str(CurrentRow) + " : " + str(CurrentCol))
end sub
'======================
' Subclass ListView procedure
function NewLVProc(sys hwnd, uint wMsg, sys wParam, lParam) as sys callback
select case wMsg
case WM_KEYDOWN
select case wParam
case VK_Up
CurrentRow = MAX(1,CurrentRow-1)
UpdateTitleBar(GetParent(hwnd))
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, false)
SendMessage(hListView, LVM_ENSUREVISIBLE, CurrentRow, 1)
case VK_Down
CurrentRow = MIN(MaxRow,CurrentRow+1)
UpdateTitleBar(GetParent(hwnd))
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, false)
SendMessage(hListView, LVM_ENSUREVISIBLE, CurrentRow, 1)
case VK_Left
CurrentCol = MAX(1,CurrentCol-1)
UpdateTitleBar(GetParent(hwnd))
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, false)
SendMessage(hListView, LVM_ENSUREVISIBLE, CurrentRow, 1)
case VK_Right
CurrentCol = MIN(MaxCol,CurrentCol+1)
UpdateTitleBar(GetParent(hwnd))
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, false)
SendMessage(hListView, LVM_ENSUREVISIBLE, CurrentRow, 1)
case VK_Home
CurrentCol = 1
if GetKeyState(VK_Control) then CurrentRow = 1
UpdateTitleBar(GetParent(hwnd))
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, false)
SendMessage(hListView, LVM_ENSUREVISIBLE, CurrentRow, 1)
case VK_End
CurrentCol = MaxCol
if GetKeyState(VK_Control) then CurrentRow = MaxRow
UpdateTitleBar(GetParent(hwnd))
InvalidateRect(GetDlgItem(hwnd, IDC_ListView), null, false)
SendMessage(hListView, LVM_ENSUREVISIBLE, CurrentRow, false)
end select
end select
return CallWindowProc(OrigLVProc, hwnd, wMsg, wParam, lParam)
end function
'==================
function CustomDraw(NMLVCUSTOMDRAW* pcd) as sys
select case (pcd.nmcd.dwDrawStage)
case CDDS_PREPAINT:
'item notification
return CDRF_DODEFAULT | CDRF_NOTIFYITEMDRAW
case (CDDS_ITEM | CDDS_PREPAINT):
'subitem notification
return CDRF_DODEFAULT | CDRF_NOTIFYSUBITEMDRAW
case (CDDS_ITEM | CDDS_SUBITEM | CDDS_PREPAINT):
select case (pcd.iSubItem)
if pcd.nmcd.dwItemSpec=CurrentRow-1 and pcd.iSubItem=CurrentCol-1 then
'highlight the selected row
pcd.clrTextBk = GREEN
else
pcd.clrTextBk = WHITE
end if
end select
end select
return CDRF_DODEFAULT
end function