Here is the code. Put the LVM_GETITEM anywhere. Macros follow the first section. Used RadASM for dialog and listview.


.486
.model flat,stdcall
option casemap:none

include ListView.inc

.code

start:

invoke GetModuleHandle,NULL
mov    hInstance,eax
invoke GetCommandLine
invoke InitCommonControls
invoke WinMain,hInstance,NULL,CommandLine,SW_SHOWDEFAULT
invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG

mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style,CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc,OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,DLGWINDOWEXTRA
push hInst
pop wc.hInstance
mov wc.hbrBackground,COLOR_BTNFACE+1
mov wc.lpszMenuName,OFFSET MenuName
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx,addr wc
invoke CreateDialogParam,hInstance,addr DlgName,NULL,addr WndProc,NULL
invoke ShowWindow,hWnd,SW_SHOWNORMAL
invoke UpdateWindow,hWnd
.while TRUE
invoke GetMessage,addr msg,NULL,0,0
  .BREAK .if !eax
invoke TranslateMessage,addr msg
invoke DispatchMessage,addr msg
.endw
mov eax,msg.wParam
ret

WinMain endp

WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rDC:DWORD
LOCAL ps:PAINTSTRUCT
LOCAL rect:RECT

mov eax,uMsg
.if eax==WM_INITDIALOG
push hWin
pop hWnd
mov hIDC_LSV1,rv(GetDlgItem,hWin,IDC_LSV1)
invoke  SendMessage,hIDC_LSV1,LVM_GETNEXTITEM,-1, LVNI_FOCUSED
invoke SendMessage,hIDC_LSV1,LVM_SETEXTENDEDLISTVIEWSTYLE,0,LVS_EX_FULLROWSELECT or LVS_EX_GRIDLINES

InsertColumn 60,"Date",0
InsertColumn 60,"Time",1
InsertColumn 150,"Purpose",2        
InsertColumn 150,"Place",3
InsertItem 0,0,"New Item0"
InsertItem 1,0,"New Item1"
SetItemText 0,1,"New subitem0"
SetItemText 1,1,"Newer subitem1"        
.elseif eax==WM_PAINT
invoke BeginPaint,hWnd,addr ps
mov rDC,eax
invoke GetClientRect,hWnd,addr rect
RGB 100,100,0
invoke FillRect,rDC,addr rect,rv(CreateSolidBrush,eax)

ret
.elseif eax==WM_NOTIFY

.elseif eax==WM_COMMAND
mov eax,wParam
and eax,0FFFFh
.if eax==IDM_FILE_EXIT
invoke SendMessage,hIDC_LSV1,LVM_GETCOLUMN,1,addr col
; Here is the crash point. Move this line anywhere...
invoke SendMessage,hIDC_LSV1,LVM_GETITEM,0,addr pitem
invoke SendMessage,hWin,WM_CLOSE,0,0
.elseif eax==IDM_HELP_ABOUT
invoke ShellAbout,hWin,addr AppName,addr AboutMsg,NULL
.endif
.elseif uMsg==WM_SIZE
mov eax,lParam
mov edx,eax
and eax,0ffffh
sub eax,10
shr edx,16
sub edx,30
invoke MoveWindow,hIDC_LSV1, 5, 25, eax,edx,TRUE
.elseif eax==WM_CLOSE
invoke DestroyWindow,hWin
.elseif uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.else
invoke DefWindowProc,hWin,uMsg,wParam,lParam
ret
.endif
xor    eax,eax
ret
WndProc endp

end start


Thanks...

RGB macro red,green,blue
        xor eax,eax
        mov ah,blue
        shl eax,8
        mov ah,green
        mov al,red
endm

InsertColumn MACRO width,colHeader,colPos
LOCAL lbl
LOCAL header
jmp lbl
header db colHeader,0
lbl:
mov col.imask,LVCF_TEXT or LVCF_WIDTH or LVCF_FMT
mov col.fmt,LVCFMT_LEFT
mov col.lx,width
mov col.pszText,offset header
GetTextLen
invoke SendMessage,hIDC_LSV1,LVM_INSERTCOLUMN,colPos,addr col
ENDM

InsertItem MACRO itemNum,subitemNum,itemText
LOCAL lbl
LOCAL itemTxt
jmp lbl
itemTxt db itemText,0
lbl:
mov pitem.imask,LVIF_TEXT
mov pitem.iItem,itemNum
mov pitem.iSubItem,subitemNum
mov pitem.pszText,offset itemTxt
GetTextLen
invoke SendMessage,hIDC_LSV1,LVM_INSERTITEM,0,addr pitem
ENDM

SetItemText MACRO itemNum,subitemNum,itemText
LOCAL lbl
LOCAL itemTxt
jmp lbl
itemTxt db itemText,0
lbl:
mov pitem.imask,LVIF_TEXT
mov pitem.iItem,itemNum
mov pitem.iSubItem,subitemNum
mov pitem.pszText,offset itemTxt
GetTextLen
invoke SendMessage,hIDC_LSV1,LVM_SETITEMTEXT,itemNum,addr pitem
ENDM

GetTextLen Macro
invoke lstrlen,pitem.pszText
mov pitem.cchTextMax,eax
ENDM
Posted on 2008-09-09 06:31:42 by green
where is pitem defined? is your pitem a ptr to a LV_ITEM struct, or is it the struct itself?
usually the 'p' prefix indicates that the variable concerned is a Pointer - not a Struct.
I am guessing you are passing the address of the pointer to the struct, ie, a pointer to a pointer.
I'd have to see the rest of the code, but I assure you the problem is not LVM_GETITEM.
Posted on 2008-09-09 07:47:53 by Homer
Thanks for your interest Homer and here is the rest from the .inc.


col LVCOLUMN <>
pitem LVITEM <>


This is what Windows API states:

lResult = SendMessage(      // returns LRESULT in lResult   
(HWND) hWndControl,      // handle to destination control   
(UINT) LVM_GETITEM,      // message ID   
(WPARAM) wParam,      // = 0; not used, must be zero   
(LPARAM) lParam      // = (LPARAM) (LPLVITEM) pitem;
);

Parameters

wParam
      Must be zero.

pitem
      Pointer to an LVITEM structure that specifies the information to retrieve and receives information about the list-view item.

Return Value
      Returns TRUE if successful, or FALSE otherwise.



'addr pitem' is the pointer to the struct as I understand it. Remove LVM_GETITEM and the code runs fine.
Posted on 2008-09-09 08:59:32 by green
Looking at some code i have for using a listview i dont use that LVM_GETITEM directly, but use other LV_ messages to retrieve information

Such as getting the currently selected row:
;**************************************************************************	
; Get Index of Currently Selected Item in Listview
;**************************************************************************
ListViewGetSelection PROC hWin:DWORD
Invoke SendMessage, hListview,LVM_GETNEXTITEM, -1, LVNI_FOCUSED
ret
ListViewGetSelection endp


Getting text from a list item or sub item:
;**************************************************************************
; Gets the text of the specified index. Stored in LVItemText on return
;**************************************************************************
ListViewGetItemText PROC hWin:DWORD, nItem:DWORD, nSubItem:DWORD
mov eax, nSubItem
mov LVItem.iSubItem, eax
invoke SendMessage, hListview, LVM_GETITEMTEXT, nItem, Addr LVItem
ret
ListViewGetItemText endp


In my data section i have:
.DATA
LVItemText db MAX_PATH dup (0) ; Buffer to hold text to display when used with LVItem
LVItem LV_ITEM <LVIF_TEXT,1,0,LVIS_FOCUSED,0,LVItemText,MAX_PATH,0,0>
.DATA?
hListview dd ? ; Listview handle


but im thinking you need to specify in your LVItem variable before hand to tell the message what you are looking to retrieve, so that you will need to set the item index, and mask of the item type to retrieve.

When the message is sent, the iItem and iSubItem members identify the item or subitem to retrieve information about and the mask member specifies which attributes to retrieve.

If the mask member specifies the LVIF_TEXT value, the pszText member must contain the pointer to the buffer that receives the item text and the cchTextMax member must specify the size of the buffer.

If the mask member specifies the LVIF_STATE value, the stateMask member specifies which item states are to be returned.



Not sure if that will help you, ive a few more procs for using listviews if you want.
Posted on 2008-09-09 14:16:21 by keithsrobertson
Hi keithsrobertson, you have evidently got it right. I did some more research after your message and finally came up with this and it did not crash:

mov pitem.iItem,1
mov pitem.iSubItem,1
mov pitem.imask, LVIF_TEXT
lea eax, szBuff
mov pitem.pszText, eax
mov pitem.cchTextMax, 256
invoke SendMessage,hIDC_LSV1,LVM_GETITEM,0,addr pitem


What I have been trying to do is get the current column when it is being resized so that I can save it as a setting and LVM_GETITEM not going to work. Do you have an answer??

Thanks again...
Posted on 2008-09-09 14:48:23 by green
Ive had a look at the list of notification messages passed back to the main window from a listview and cant see an exact one that would allow you to monitor the column resize directly.

Might be better to use the LVM_GETCOLUMNWIDTH message to retrieve the column widths and save them when the user exits the program instead.
Posted on 2008-09-09 16:29:50 by keithsrobertson
Thanks keithsrobertson, I guess we will consider this one as solved at this point. Thanks again.
Posted on 2008-09-09 18:04:31 by green
is the pitem structure defined in the DATA segment or in with the CODE? because writing to that address would cause a GPF due to default page permission for CODE segments.
Posted on 2008-09-10 08:57:58 by Homer
Hello Homer, it is defined in 'data?'. I tried what keithsrobertson said and it worked.
Posted on 2008-09-10 16:29:17 by green
It looks like you're using pitem for every item you add. I think the trouble is that the last time you used it
you left imask=LVIF_TEXT and pszText as the address of a string - which your macro puts in the code section.
When you try to use LVM_GETITEM it uses imask which tells it that pszText points to a buffer in .code -> access violation.

An interesting bit from the sdk
Applications should not assume that the text will necessarily be placed in the specified buffer. The control may instead change the pszText member of the structure to point to the new text, rather than place it in the buffer.

WTF???
Posted on 2008-09-10 21:54:50 by sinsi
Well think about it - handing the user a pointer to the internal string buffer avoids the need to copy the string into the buffer that the user supplied - if we just grab the pszText pointer after the call, its always going to be valid - even if its not the pointer that we supplied.
Posted on 2008-09-11 02:04:04 by Homer
My usual way of using a buffer is

.data?
buffer db 260 dup (?)
.code
...
 mov pitem.pszText,offset buffer
 invoke SendMessage,hIDC_LSV1,LVM_GETITEM,0,offset pitem
 ;here I would use
 invoke lstrlen,offset buffer
 ;rather than
 invoke lstrlen,pitem.pszText

If the pointer gets changed, who owns the memory it points to?
Posted on 2008-09-11 03:24:53 by sinsi