Hello all,
In the game I'm currently writing, I use a List View control to display a list of high scores.
However, after it is displayed, its appearance gets all screwed up after you manually try to resize the columns. One of the things that happens is that the scroll bars appear and disappear in an unpredictable fashion, and there are some other visual errors as well.
Is there a way to declare the column headers as non-resizable?
Anyone else come across this behavior?
Here's some code Paul did for IBasic that uses subclassing to disable column resizing.
'for subclassing
def hLV as UINT
def origfp as UINT
declare import,CallWindowProcA(lpPrevWndFunc:int,hWnd:int,Msg:int,wParam:int,lParam:int),int
declare import,SetWindowLongA(hWnd:int,nIndex:int,dwNewLong:int),int
declare import,GetWindowLongA(hWnd:int,nIndex:int),int
declare import,GetDlgItem(hDlg:int,nIDDlgItem:int),int
const GWL_WNDPROC=-4
'This is a simple list view demo. The list view is created in report mode
'and two columns are added.
'requires IBasic Professional 1.0 or greater
def d1:Dialog
def str:STRING
def p as pointer
'standard NMLISTVIEW
'when a column ic clicked on Windows sends a variable
'of this type in @LPARAM.
TYPE NMLISTVIEW
def hwndFrom:UINT
def idFrom:INT
def code:INT
def iItem:INT
def iSubItem:INT
def uNewState:UINT
def uOldState:UINT
def uChanged:UINT
def ptActionx:INT
def ptActiony:INT
def lParam:INT
ENDTYPE
CONST HDN_FIRST = (-300)
CONST HDN_ENDTRACKA = (HDN_FIRST-7)
CONST HDN_BEGINTRACKA = (HDN_FIRST-6)
CONST HDN_BEGINTRACKW = (HDN_FIRST-26)
CONST WM_NOTIFY = 0x4E
CREATEDIALOG d1,0,0,295,168,0x80C80080,0,"List view test",&handler
CONTROL d1,@LISTVIEW,"",27,24,240,110,0x50000001,100
CONTROL d1,@STATIC,"TEST",27,140,240,20,0x50000000,200
domodal d1
end
SUB handler
select @MESSAGE
case @IDINITDIALOG
centerwindow d1
'insert columns and some items
'after an item is inserted we use @LVSETTEXT to
'change the subitems text
CONTROLCMD d1,100,@LVINSERTCOLUMN,0,"Column1"
CONTROLCMD d1,100,@LVINSERTCOLUMN,1,"Column2"
CONTROLCMD d1,100,@LVINSERTITEM,0,"Item 1"
CONTROLCMD d1,100,@LVSETTEXT,0,1,"Subitem 1"
CONTROLCMD d1,100,@LVINSERTITEM,1,"Item 2"
CONTROLCMD d1,100,@LVSETTEXT,1,1,"Subitem 2"
'subclass the listview control
hLV = GetDlgItem(d1.hwnd,100)
origfp=GetWindowLongA(hLV,GWL_WNDPROC)
'Replace it with our handler...
SetWindowLongA(hLV,GWL_WNDPROC,&myLVHandler)
case @IDCONTROL
if(@CONTROLID = 100)
'someone clicked on a column header. Read the data from @LPARAM which is
' a pointer to a NMLISTVIEW UDT. Using the C dereferencing style makes
' it much easier
if(@NOTIFYCODE = @LVNCOLUMNCLICK)
CONTROLCMD d1,100,@LVSETCOLUMNTEXT,*<NMLISTVIEW>@LPARAM.iSubItem,"Clicked!"
endif
ENDIF
CASE @IDDESTROY
'remove the subclass
SetWindowLongA(hLV,GWL_WNDPROC,origfp)
endselect
return
ENDSUB
SUB myLVHandler(hwnd:int,uMsg:int,wParam:int,lParam:pointer),int
'prevent columns from resizing.
SELECT uMsg
case WM_NOTIFY
if (#<NMHDR>lParam.code = HDN_BEGINTRACKA) OR (#<NMHDR>lParam.code = HDN_BEGINTRACKW)
RETURN 1
ENDIF
ENDSELECT
RETURN CallWindowProcA(origfp,hwnd,uMsg,wParam,lParam)
ENDSUB
That code worked in my project to prevent the columns from resizing. Thank you.
(By the way, I hope I didn't sound too critical toward EBasic when I said that things got "screwed up." I still think Emergence is a great language and compiler.)
how does one create lines separating the items/subitems?
Partial code
CONST LVM_FIRST = 0x1000
CONST LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54)
CONST LVS_EX_FULLROWSELECT = 0x20
CONST LVS_EX_GRIDLINES = 1
CONST LVS_EX_FLATSB = 0x100
CONST LVS_EX_LABELTIP = 0x4000
select @MESSAGE
case @IDINITDIALOG
CONTROLCMD dlgNameIDMenu,1,@LVINSERTCOLUMN,0,""
CONTROLCMD dlgNameIDMenu,1,@LVINSERTCOLUMN,1,""
CONTROLCMD dlgNameIDMenu,1, @LVSETCOLWIDTH, 0, 326
CONTROLCMD dlgNameIDMenu,1, @LVSETCOLWIDTH, 1, 50
SENDMESSAGE dlgNameIDMenu,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FLATSB|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,1
Thanks Larry,
I tried it but it didn't seem to work. Can you help?
I did use the column width parameter successfully which was another question I had.
'ListView subclassing
'This is a simple list view demo.
'The list view is created in report mode and two columns are added.
def hLV as UINT
def origfp as UINT
declare import,CallWindowProcA(lpPrevWndFunc:int,hWnd:int,Msg:int,wParam:int,lParam:int),int
declare import,SetWindowLongA(hWnd:int,nIndex:int,dwNewLong:int),int
declare import,GetWindowLongA(hWnd:int,nIndex:int),int
declare import,GetDlgItem(hDlg:int,nIDDlgItem:int),int
const GWL_WNDPROC = -4
def d1:Dialog
def str:STRING
def p as pointer
'standard NMLISTVIEW
'when a column ic clicked on Windows sends a variable of this type in @LPARAM.
TYPE NMLISTVIEW
def hwndFrom:UINT
def idFrom:INT
def code:INT
def iItem:INT
def iSubItem:INT
def uNewState:UINT
def uOldState:UINT
def uChanged:UINT
def ptActionx:INT
def ptActiony:INT
def lParam:INT
ENDTYPE
CONST HDN_FIRST = (-300)
CONST HDN_ENDTRACKA = (HDN_FIRST-7)
CONST HDN_BEGINTRACKA = (HDN_FIRST-6)
CONST HDN_BEGINTRACKW = (HDN_FIRST-26)
CONST WM_NOTIFY = 0x4E
CONST LVM_FIRST = 0x1000
CONST LVM_SETEXTENDEDLISTVIEWSTYLE = (LVM_FIRST + 54)
CONST LVS_EX_FULLROWSELECT = 0x20
CONST LVS_EX_GRIDLINES = 1
CONST LVS_EX_FLATSB = 0x100
CONST LVS_EX_LABELTIP = 0x4000
CREATEDIALOG d1,0,0,255,168,0x80C80080,0,"List view test",&handler
CONTROL d1,@LISTVIEW,"",27,24,200,110,0x50000001,100
CONTROL d1,@STATIC,"TEST",27,140,240,20,0x50000000,200
domodal d1
end
SUB handler
select @MESSAGE
case @IDINITDIALOG
centerwindow d1
'insert columns and some items
'then use @LVSETTEXT to change the subitems text
'then reset column width with @LVSETCOLWIDTH
CONTROLCMD d1,100,@LVINSERTCOLUMN,0,"Column 1"
CONTROLCMD d1,100,@LVINSERTCOLUMN,1,"Column 2"
CONTROLCMD d1,100,@LVINSERTITEM,0,"Item 1"
CONTROLCMD d1,100,@LVSETTEXT,0,1,"Subitem 1"
CONTROLCMD d1,100,@LVINSERTITEM,1,"Item 2"
CONTROLCMD d1,100,@LVSETTEXT,1,1,"Subitem 2"
CONTROLCMD d1,100,@LVSETCOLWIDTH, 0, 100
CONTROLCMD d1,100,@LVSETCOLWIDTH, 1, 100
SENDMESSAGE d1,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FLATSB|LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES,1
'subclass the listview control
hLV = GetDlgItem(d1.hwnd,100)
origfp=GetWindowLongA(hLV,GWL_WNDPROC)
'Replace it with our handler...
SetWindowLongA(hLV,GWL_WNDPROC,&myLVHandler)
case @IDCONTROL
if(@CONTROLID = 100)
'someone clicked on a column header. Read the data from @LPARAM which is
' a pointer to a NMLISTVIEW UDT. Using the C dereferencing style makes
' it much easier
if(@NOTIFYCODE = @LVNCOLUMNCLICK)
CONTROLCMD d1,100,@LVSETCOLUMNTEXT,*<NMLISTVIEW>@LPARAM.iSubItem,"Clicked!"
CONTROLCMD d1,100,@LVSETCOLWIDTH, 0, 100
CONTROLCMD d1,100,@LVSETCOLWIDTH, 1, 100
endif
ENDIF
CASE @IDDESTROY
'remove the subclass
SetWindowLongA(hLV,GWL_WNDPROC,origfp)
endselect
return
ENDSUB
SUB myLVHandler(hwnd:int,uMsg:int,wParam:int,lParam:pointer),int
'prevent columns from resizing.
SELECT uMsg
case WM_NOTIFY
if (#<NMHDR>lParam.code = HDN_BEGINTRACKA) OR (#<NMHDR>lParam.code = HDN_BEGINTRACKW)
RETURN 1
ENDIF
ENDSELECT
RETURN CallWindowProcA(origfp,hwnd,uMsg,wParam,lParam)
ENDSUB
when you copied the sendmessage you left the last parameter as a '1' which was my listview id.
you're using 100 so just add the 2 '00' to the end of the sendmessage line and it will work.
Larry
thanks Larry!
How do you spell, Doh! ?
QuoteHow do you spell, Doh! ?
I do it so often I have it as a macro on my keyboard! ;D