Re: AllowLVEdits Version 2.0
Posted: Sun Oct 16, 2011 8:06 pm
....Nothing to apologise for! Thank you for sharing the pbi file, I will study the methods carefully, my own efforts were reliable but way too slow with huge lists.
http://www.purebasic.com
https://www.purebasic.fr/english/
You are on the mark with that observation, that was half of the problem. I reworked it so that it only saves to the file if you click the save toolbar icon and on exit. All these years I've been misunderstanding #PB_EventType_Change for the listicon, it makes me wonder if I'm losing my mindI thought it was happening with updating the file
Excellent suggestion. I had been trying to keep the demo code as simple as possible but this idea is too good not to implement. Cashflow demo is now updated as follows:GeBonet wrote:If I had one suggestion it would be able to create multiple line for each date if necessary ... This would be a perfect time to log movements household budget.
Nah, I think PB getting many new features on each update to have time to test every option in every situation.All these years I've been misunderstanding #PB_EventType_Change for the listicon, it makes me wonder if I'm losing my mindThanks for the testing and feedback, it's appreciated!
Code: Select all
;======================================================================================================================
; Library: AllowLVEdits 3.0
; Author: netmaestro
; Date: June 19, 2007 last update July 7, 2013
; Target OS: Microsoft Windows All
; Target Compiler: PureBasic version 5.20+
; License: Free, unrestricted, no warranty
;
; This library allows the user to edit the contents of ListIcon cells
; by right-clicking on them.
;
; EXPORTED COMMANDS:
;
; StartEditing(WindowNumber, GadgetNumber); Make ListIcon gadget cells editable
;
; StopEditing(); Take ListIcon gadget out of editable mode
;
; SetMoneyColumn(Column, Width) ; Width is number of digits before the decimal place
;
; DecimalMask(char) ; Char is the character you wish to use for decimal point, usually '.' or ',' (46 or 44)
;
; MaskColumn(Column) ; Disallows edits for the passed column
;
; Ale_RowChanged() ; Returns the row of the last-edited item
;
; Ale_ColumnChanged() ; Returns the column of the last-edited item
;
; Ale_OriginalText() ; Returns a string containing the original item text before the edit
;
; DETECTING CHANGES:
;
; When this library detects an edit to a listicon cell, it will send a #PB_Event_Gadget message
; to your WaitWindowEvent() loop with the EventType() of #Ale_Cellcontents_Changed. When you receive
; this message, three commands are available to you:
;
; - Ale_RowChanged()
; - Ale_ColumnChanged()
; - Ale_OriginalText()
;
; These commands may only be called after receiving #PB_Event_Gadget with event type = #Ale_Cellcontents_Changed.
; Additionally, they may only be called once as calling them clears their contents. So if you need them later you
; must save their return values in a variable of your own.
;
; Using these three commands and a linked-list or array of stored changes, you can easily provide a user with
; the option of cancelling all changes or stepping through an undo list.
;
; This version of the program is contstructed using the Module library which is available beginning with v5.20
;
; Include this file in your program and if it's the only module you'll be using in your project you can do:
;
; Usemodule LVEdit
; ... call the commands as needed
; Unusemodule LVEdit
;
; If you are using other modules in your project the commands must be qualified with the module name like so:
;
; LVEdit::StartEditing(<window>, <listicon>)
;
;
;======================================================================================================================
DeclareModule LVEdit
Enumeration #PB_Event_FirstCustomValue
#Ale_Cellcontents_Changed
EndEnumeration
Declare Ale_ColumnChanged(cell = -1)
Declare Ale_RowChanged(Item = -1)
Declare.s Ale_OriginalText(orig$ = "")
Declare SaveAndExit()
Declare SaveAndExit_Desc(newtext$)
Declare SubClass_String(hwnd, Message, wparam, lparam)
Declare.s GetNewText()
Declare ResizeEdit(hwnd)
Declare hookproc(nCode, wparam, lparam)
Declare SubClass_LV(hwnd, Message, wparam, lparam)
Declare StopEditing(); Take ListIcon gadget out of editable mode
Declare StartEditing(WindowNumber, GadgetNumber); Make ListIcon gadget editable
Declare SetMoneyColumn(Column, Width) ; Width is number of digits before the decimal place
Declare DecimalMask(char) ;Char is the symbol to use For decimal point, usually '.' Or ',' (46 Or 44)
Declare MaskColumn(Column) ; Disallows edits for the passed column, the lib will gray it out
EndDeclareModule
Module LVEdit
Import ""
PB_Gadget_SendGadgetCommand(hWnd, EventType)
EndImport
Structure EDITDATA
Array MoneyColumn.i(100)
Array Masked.i(100)
_edits210_oldlist.i
_edits210_EditActive.i
_edits210_oldstring.i
_edits210_string.i
_edits210_decimal.i
_edits210_container.i
_edits210_window.i
_edits210_item.i
_edits210_subitem.i
_edits210_gadget.i
_edits210_itemrect.RECT
_edits210_menuhook.i
EndStructure
Global descpopup = CreatePopupMenu(#PB_Any) ; Scope is limited to the module
MenuItem(10, "Opening Balance")
MenuItem(11, "Deposit")
MenuItem(12, "Campsite Fees")
MenuItem(13, "Firewood Sales")
MenuBar()
MenuItem(14, "Fuel Receipt")
MenuItem(15, "Propane Receipt")
MenuItem(16, "Tools/Supplies Receipt")
MenuItem(17, "Withdrawal")
MenuBar()
MenuItem(18, "<leave blank>")
*LVEdits.EDITDATA = AllocateMemory(SizeOf(EDITDATA))
InitializeStructure(*LVEdits, EDITDATA)
Procedure Ale_ColumnChanged(cell = -1)
Static cellchanged
If cell<> -1
cellchanged = cell
ProcedureReturn
Else
result = cellchanged
cellchanged = -1
ProcedureReturn result
EndIf
EndProcedure
Procedure Ale_RowChanged(Item = -1)
Static Itemchanged
If Item<> -1
Itemchanged = Item
ProcedureReturn
Else
result = Itemchanged
Itemchanged = -1
ProcedureReturn result
EndIf
EndProcedure
Procedure.s Ale_OriginalText(orig$ = "")
Static originaltext$
If orig$ <> ""
originaltext$ = orig$
ProcedureReturn
Else
result$ = originaltext$
originaltext$ = ""
ProcedureReturn result$
EndIf
EndProcedure
Procedure SaveAndExit()
Shared *LVEdits.EDITDATA
tmp$ = GetGadgetText(*LVEdits\_edits210_string)
orig$ = GetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item,*LVEdits\_edits210_subitem)
If Trim(tmp$) <> Trim(orig$)
SendChange = #True
Ale_OriginalText(orig$)
Else
SendChange = #False
EndIf
If *LVEdits\_edits210_item >= 0
SetGadgetState(*LVEdits\_edits210_gadget, *LVEdits\_edits210_item)
EndIf
crlf = FindString(tmp$, #CRLF$, 1)
If crlf
SetGadgetText(*LVEdits\_edits210_string,ReplaceString(tmp$,#CRLF$,""))
SendMessage_(sg,#EM_SETSEL,crlf-1,crlf-1)
EndIf
If *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)
tmpout.s = Trim(GetGadgetText(*LVEdits\_edits210_string))
ploc = FindString(tmpout,Chr(*LVEdits\_edits210_decimal),1)
If ploc
If ploc = 1
tmpout = "0" + tmpout
EndIf
While Len(tmpout) - FindString(tmpout,Chr(*LVEdits\_edits210_decimal),1) < 2
tmpout+"0"
SetGadgetText(*LVEdits\_edits210_string, tmpout)
Wend
Else
If tmpout <> ""
tmpout + Chr(*LVEdits\_edits210_decimal) + "00"
SetGadgetText(*LVEdits\_edits210_string, tmpout)
EndIf
EndIf
If Val(tmpout) = 0
tmpout= ""
EndIf
SetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item, RSet(Trim(tmpout),*LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)+3," "), *LVEdits\_edits210_subitem)
Else
SetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item, GetGadgetText(*LVEdits\_edits210_string), *LVEdits\_edits210_subitem)
EndIf
FreeGadget(*LVEdits\_edits210_string)
FreeGadget(*LVEdits\_edits210_container)
*LVEdits\_edits210_EditActive = #False
If SendChange
Ale_ColumnChanged(*LVEdits\_edits210_subitem)
Ale_RowChanged(*LVEdits\_edits210_item)
PB_Gadget_SendGadgetCommand(GadgetID(*LVEdits\_edits210_gadget), #Ale_Cellcontents_Changed)
EndIf
;UnhookWindowsHookEx_(*LVEdits\_edits210_menuhook)
EndProcedure
Procedure SaveAndExit_Desc(newtext$)
Shared *LVEdits.EDITDATA
tmp$ = newtext$
orig$ = GetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item,*LVEdits\_edits210_subitem)
If Trim(tmp$) <> Trim(orig$)
SendChange = #True
Ale_OriginalText(orig$)
Else
SendChange = #False
EndIf
SetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item, newtext$, *LVEdits\_edits210_subitem)
If SendChange
Ale_ColumnChanged(*LVEdits\_edits210_subitem)
Ale_RowChanged(*LVEdits\_edits210_item)
PB_Gadget_SendGadgetCommand(GadgetID(*LVEdits\_edits210_gadget), #Ale_Cellcontents_Changed)
EndIf
EndProcedure
Procedure.s GetNewDescription()
Shared *LVEdits.EDITDATA
DisplayPopupMenu(descpopup, WindowID(*LVEdits\_edits210_window))
EndProcedure
Procedure SubClass_String(hwnd, Message, wparam, lparam)
Shared *LVEdits.EDITDATA
Protected blocking=0, ploc, tmpout.s
result = CallWindowProc_(*LVEdits\_edits210_oldlist, hwnd, Message, wparam, lparam)
Select Message
Case #WM_RBUTTONDOWN
*LVEdits\_edits210_menuhook = SetWindowsHookEx_(#WH_MOUSE, @hookproc(), 0, GetCurrentThreadId_())
Case #WM_DESTROY
UnhookWindowsHookEx_(*LVEdits\_edits210_menuhook)
Case #WM_KEYDOWN
Select wparam
Case #VK_RETURN
SaveAndExit()
If *LVEdits\_edits210_window <> 1 ; <------ Change for Summit
*LVEdits\_edits210_item + 1
If *LVEdits\_edits210_item < CountGadgetItems(*LVEdits\_edits210_gadget)
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
EndIf
EndIf
Case #VK_ESCAPE
FreeGadget(*LVEdits\_edits210_string)
FreeGadget(*LVEdits\_edits210_container)
*LVEdits\_edits210_EditActive = #False
Case #VK_LEFT
SendMessage_(hwnd, #EM_GETSEL, @first.l, @last.l)
If first = 0
SaveAndExit()
currentsubitem = *LVEdits\_edits210_subitem
*LVEdits\_edits210_subitem - 1
If *LVEdits\_edits210_subitem >= 1
While *LVEdits\Masked(*LVEdits\_edits210_subitem) And *LVEdits\_edits210_subitem >= 0
*LVEdits\_edits210_subitem - 1
If *LVEdits\_edits210_subitem < 1
*LVEdits\_edits210_subitem = currentsubitem
EndIf
Wend
Else
*LVEdits\_edits210_subitem + 1
EndIf
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
EndIf
Case #VK_RIGHT
SendMessage_(hwnd, #EM_GETSEL, @first.l, @last.l)
If Len(GetGadgetText(*LVEdits\_edits210_string)) = last
headerhWnd=SendMessage_(GadgetID(*LVEdits\_edits210_gadget),#LVM_GETHEADER,0,0)
numcolumns = SendMessage_(headerhWnd, #HDM_GETITEMCOUNT,0,0)
If *LVEdits\_edits210_subitem < numcolumns-1
SaveAndExit()
currentsubitem = *LVEdits\_edits210_subitem
*LVEdits\_edits210_subitem + 1
If *LVEdits\_edits210_subitem < numcolumns
While *LVEdits\Masked(*LVEdits\_edits210_subitem) And *LVEdits\_edits210_subitem <= numcolumns
*LVEdits\_edits210_subitem + 1
If *LVEdits\_edits210_subitem >= numcolumns
*LVEdits\_edits210_subitem = currentsubitem
EndIf
Wend
Else
*LVEdits\_edits210_subitem -1
EndIf
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
EndIf
EndIf
Case #VK_UP
SaveAndExit()
*LVEdits\_edits210_item - 1 : If *LVEdits\_edits210_item <= 0 : *LVEdits\_edits210_item = 0 : EndIf
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
Case #VK_DOWN
SaveAndExit()
*LVEdits\_edits210_item + 1:If *LVEdits\_edits210_item >= CountGadgetItems(*LVEdits\_edits210_gadget):*LVEdits\_edits210_item - 1 : EndIf
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
EndSelect
Case #WM_CHAR
If *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)
blocking = 1
Select wparam
Case *LVEdits\_edits210_decimal, 48 To 57
tmpout.s = GetGadgetText(*LVEdits\_edits210_string)
If FindString(tmpout, Chr(*LVEdits\_edits210_decimal), 1) = 0
If Len(tmpout) > *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)
If wparam <> *LVEdits\_edits210_decimal
SendMessage_(hwnd, #EM_GETSEL, 0, @pos)
SetGadgetText(*LVEdits\_edits210_string, Left(tmpout,Len(tmpout)-1))
SendMessage_(hwnd, #EM_SETSEL, pos-1, pos-1)
EndIf
EndIf
EndIf
If wparam = *LVEdits\_edits210_decimal
If CountString(tmpout, Chr(*LVEdits\_edits210_decimal)) > 1
SendMessage_(hwnd, #EM_GETSEL, 0, @pos)
SetGadgetText(*LVEdits\_edits210_string, Left(tmpout,Len(tmpout)-1))
SendMessage_(hwnd, #EM_SETSEL, pos-1, pos-1)
EndIf
EndIf
If FindString(tmpout,Chr(*LVEdits\_edits210_decimal),1)
If Len(tmpout) - FindString(tmpout,Chr(*LVEdits\_edits210_decimal),1) > 2
SendMessage_(hwnd, #EM_GETSEL, 0, @pos)
SetGadgetText(*LVEdits\_edits210_string, Left(tmpout,Len(tmpout)-1))
SendMessage_(hwnd, #EM_SETSEL, pos-1, pos-1)
EndIf
EndIf
Default
If wparam <> 8 And wparam <> 13
tmpout.s = GetGadgetText(*LVEdits\_edits210_string)
SendMessage_(hwnd, #EM_GETSEL, 0, @pos)
SetGadgetText(*LVEdits\_edits210_string, Left(tmpout,Len(tmpout)-1))
SendMessage_(hwnd, #EM_SETSEL, pos-1, pos-1)
EndIf
EndSelect
EndIf
Case #WM_PASTE
If *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)
tmpout.s = GetGadgetText(*LVEdits\_edits210_string)
If FindString(tmpout,Chr(*LVEdits\_edits210_decimal),1)
validlength = *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)+3
Else
validlength = *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)
EndIf
If Len(tmpout)<=validlength
ok = #True
*cc.CHARACTER = @tmpout
While *cc\c
Select *cc\c
Case '0' To '9', *LVEdits\_edits210_decimal
Default
ok = #False
EndSelect
*cc+1
Wend
Else
ok = #False
EndIf
If Not ok
SetGadgetText(*LVEdits\_edits210_string, "")
EndIf
EndIf
EndSelect
ProcedureReturn result
EndProcedure
Procedure hookproc(ncode, wparam, lparam)
Shared *LVEdits.EDITDATA
If ncode<0 Or IsGadget(*LVEdits\_edits210_string) = 0
result = CallNextHookEx_(*LVEdits\_edits210_menuhook, ncode, wparam, lparam)
ProcedureReturn result
EndIf
If wparam = #WM_RBUTTONUP
If IsGadget(*LVEdits\_edits210_string)
*mhs.MOUSEHOOKSTRUCT = lparam
If *mhs\hwnd = GadgetID(*LVEdits\_edits210_string)
ProcedureReturn #True
EndIf
EndIf
EndIf
ProcedureReturn CallNextHookEx_(*LVEdits\_edits210_menuhook, ncode, wparam, lparam)
EndProcedure
Procedure.s GetNewText()
Shared *LVEdits.EDITDATA
*LVEdits\_edits210_EditActive = #True
Protected grect.rect
twleft = *LVEdits\_edits210_itemrect\left+6
twtop = *LVEdits\_edits210_itemrect\top
winwidth = *LVEdits\_edits210_itemrect\right-*LVEdits\_edits210_itemrect\left-8
winheight = *LVEdits\_edits210_itemrect\bottom-*LVEdits\_edits210_itemrect\top-1
oldgadgetlist = UseGadgetList(GadgetID(*LVEdits\_edits210_gadget))
*LVEdits\_edits210_container = ContainerGadget(#PB_Any, twleft-2,twtop-2,winwidth+4,winheight+4)
HideGadget(*LVEdits\_edits210_container, 1)
SetGadgetColor(*LVEdits\_edits210_container,#PB_Gadget_BackColor, #Black)
If *LVEdits\MoneyColumn(*LVEdits\_edits210_subitem)
*LVEdits\_edits210_string = StringGadget(#PB_Any,2,2,winwidth,winheight,RemoveString(GetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item,*LVEdits\_edits210_subitem)," "),#PB_String_BorderLess|#ES_MULTILINE|#ES_AUTOVSCROLL)
Else
*LVEdits\_edits210_string = StringGadget(#PB_Any,2,2,winwidth,winheight,GetGadgetItemText(*LVEdits\_edits210_gadget,*LVEdits\_edits210_item,*LVEdits\_edits210_subitem),#PB_String_BorderLess|#ES_MULTILINE|#ES_AUTOVSCROLL|#PB_String_UpperCase)
EndIf
CloseGadgetList()
SetGadgetFont(*LVEdits\_edits210_string, GetGadgetFont(*LVEdits\_edits210_gadget))
UseGadgetList(oldgadgetlist)
SetActiveGadget(*LVEdits\_edits210_string)
*LVEdits\_edits210_oldstring=SetWindowLong_(GadgetID(*LVEdits\_edits210_string), #GWL_WNDPROC, @SubClass_String())
SetWindowLong_(GadgetID(*LVEdits\_edits210_string), #GWL_EXSTYLE, GetWindowLong_(GadgetID(*LVEdits\_edits210_string), #GWL_EXSTYLE) &~ #WS_EX_CONTEXTHELP)
SendMessage_(GadgetID(*LVEdits\_edits210_string),#EM_SETSEL,0,-1)
HideGadget(*LVEdits\_edits210_container, 0)
GetWindowRect_(GadgetID(*LVEdits\_edits210_gadget), @gr.RECT)
GetWindowRect_(GadgetID(*LVEdits\_edits210_container), @cr.RECT)
GetClientRect_(GadgetID(*LVEdits\_edits210_gadget), @grc.RECT)
If cr\top - gr\top < winheight
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #WM_VSCROLL, #SB_LINEUP ,0)
ElseIf cr\top - gr\top > grc\bottom-grc\top-winheight
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #WM_VSCROLL, #SB_LINEDOWN ,0)
EndIf
If GadgetWidth(*LVEdits\_edits210_gadget)-twleft < winwidth
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #WM_HSCROLL, #SB_RIGHT, 0)
ElseIf twleft<0
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #WM_HSCROLL, #SB_LEFT, 0)
EndIf
EndProcedure
Procedure ResizeEdit(hwnd)
Shared *LVEdits.EDITDATA
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(hwnd, #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
twleft = *LVEdits\_edits210_itemrect\left+6
twtop = *LVEdits\_edits210_itemrect\top
winwidth = *LVEdits\_edits210_itemrect\right-*LVEdits\_edits210_itemrect\left-8
winheight = *LVEdits\_edits210_itemrect\bottom-*LVEdits\_edits210_itemrect\top-1
ResizeGadget(*LVEdits\_edits210_container,twleft-2,twtop-2,winwidth+4,winheight+4)
ResizeGadget(*LVEdits\_edits210_string, 2,2, GadgetWidth(*LVEdits\_edits210_container)-4, GadgetHeight(*LVEdits\_edits210_container)-4)
InvalidateRect_(GadgetID(*LVEdits\_edits210_container),0,1)
If GadgetY(*LVEdits\_edits210_container) < winheight
HideGadget(*LVEdits\_edits210_container, 1)
Else
HideGadget(*LVEdits\_edits210_container, 0)
SetActiveGadget(*LVEdits\_edits210_string)
EndIf
EndProcedure
Procedure SubClass_LV(hwnd, Message, wparam, lparam)
Shared *LVEdits.EDITDATA
result = CallWindowProc_(*LVEdits\_edits210_oldlist, hwnd, Message, wparam, lparam)
If message = #WM_KEYUP
If wparam = #VK_TAB
If GetAsyncKeyState_(#VK_SHIFT) & 32768
SaveAndExit()
currentsubitem = *LVEdits\_edits210_subitem
*LVEdits\_edits210_subitem - 1
If *LVEdits\_edits210_subitem >= 1
While *LVEdits\Masked(*LVEdits\_edits210_subitem) And *LVEdits\_edits210_subitem >= 0
*LVEdits\_edits210_subitem - 1
If *LVEdits\_edits210_subitem < 1
*LVEdits\_edits210_subitem = currentsubitem
EndIf
Wend
Else
*LVEdits\_edits210_subitem + 1
EndIf
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
Else
If IsGadget(*LVEdits\_edits210_string)
headerhWnd=SendMessage_(GadgetID(*LVEdits\_edits210_gadget),#LVM_GETHEADER,0,0)
numcolumns = SendMessage_(headerhWnd, #HDM_GETITEMCOUNT,0,0)
SaveAndExit()
currentsubitem = *LVEdits\_edits210_subitem
*LVEdits\_edits210_subitem + 1
If *LVEdits\_edits210_subitem < numcolumns
While *LVEdits\Masked(*LVEdits\_edits210_subitem) And *LVEdits\_edits210_subitem <= numcolumns
*LVEdits\_edits210_subitem + 1
If *LVEdits\_edits210_subitem >= numcolumns
*LVEdits\_edits210_subitem = currentsubitem
EndIf
Wend
Else
*LVEdits\_edits210_subitem -1
EndIf
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = *LVEdits\_edits210_subitem
SendMessage_(GadgetID(*LVEdits\_edits210_gadget), #LVM_GETSUBITEMRECT, *LVEdits\_edits210_item, @*LVEdits\_edits210_itemrect)
GetNewText()
EndIf
EndIf
EndIf
EndIf
If message = #WM_VSCROLL Or message = #WM_HSCROLL
If IsGadget(*LVEdits\_edits210_container) And *LVEdits\_edits210_container <> 0
ResizeEdit(hwnd)
EndIf
EndIf
If message=#WM_NOTIFY
If IsGadget(*LVEdits\_edits210_container) And *LVEdits\_edits210_container <> 0
*nmHEADER.HD_NOTIFY = lParam
Select *nmHEADER\hdr\code
Case #HDN_ITEMCHANGING
ResizeEdit(hwnd)
EndSelect
EndIf
EndIf
If Message = #WM_RBUTTONDOWN
If Not *LVEdits\_edits210_EditActive
GetCursorPos_(@cp.POINT)
MapWindowPoints_(0,hwnd,@cp,1)
HitInfo.LVHITTESTINFO
Hitinfo\pt\x = cp\x
HitInfo\pt\y = cp\y
SendMessage_(hwnd,#LVM_SUBITEMHITTEST ,0,@HitInfo)
SetGadgetState(*LVEdits\_edits210_gadget, hitinfo\iitem)
If hitinfo\isubitem > 0 And HitInfo\iItem >= 0
RtlZeroMemory_(@*LVEdits\_edits210_itemrect,SizeOf(RECT))
*LVEdits\_edits210_itemrect\top = hitinfo\iSubItem
SendMessage_(hwnd,#LVM_GETSUBITEMRECT, hitinfo\iitem, @*LVEdits\_edits210_itemrect)
*LVEdits\_edits210_item = hitinfo\iitem
*LVEdits\_edits210_subitem = hitinfo\iSubItem
If Not *LVEdits\Masked(*LVEdits\_edits210_subitem)
If *LVEdits\_edits210_subitem = 2 And *LVEdits\_edits210_window = 2
GetNewDescription()
Else
GetNewText()
EndIf
EndIf
EndIf
Else
FreeGadget(*LVEdits\_edits210_string)
FreeGadget(*LVEdits\_edits210_container)
*LVEdits\_edits210_EditActive = #False
EndIf
EndIf
If Message = #WM_LBUTTONDOWN
If *LVEdits\_edits210_EditActive
FreeGadget(*LVEdits\_edits210_string)
FreeGadget(*LVEdits\_edits210_container)
*LVEdits\_edits210_EditActive = #False
EndIf
EndIf
ProcedureReturn result
EndProcedure
Procedure StopEditing(); Take ListIcon gadget out of editable mode
Shared *LVEdits.EDITDATA
*LVEdits\_edits210_editactive = #False
If *LVEdits\_edits210_string
If IsGadget(*LVEdits\_edits210_string) : FreeGadget(*LVEdits\_edits210_string) : EndIf
EndIf
If *LVEdits\_edits210_container
If IsGadget(*LVEdits\_edits210_container) : FreeGadget(*LVEdits\_edits210_container) : EndIf
EndIf
If *LVEdits\_edits210_oldlist
If IsGadget(*LVEdits\_edits210_gadget)
SetWindowLong_(GadgetID(*LVEdits\_edits210_gadget), #GWL_WNDPROC, *LVEdits\_edits210_oldlist)
*LVEdits\_edits210_oldlist = 0
EndIf
EndIf
EndProcedure
Procedure StartEditing(WindowNumber, GadgetNumber); Make ListIcon gadget cells editable
Shared *LVEdits.EDITDATA
StopEditing()
*LVEdits\_edits210_window=WindowNumber
Protected cn$ = Space(100)
GetClassName_(GadgetID(GadgetNumber),@cn$,99)
If UCase(Trim(cn$)) = "SYSLISTVIEW32" And *LVEdits\_edits210_oldlist = 0
*LVEdits\_edits210_oldlist=SetWindowLong_(GadgetID(GadgetNumber), #GWL_WNDPROC, @SubClass_LV())
*LVEdits\_edits210_gadget = GadgetNumber
*LVEdits\_edits210_decimal = 46
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure SetMoneyColumn(Column, Width) ; Width is number of digits before the decimal place
Shared *LVEdits.EDITDATA
If *LVEdits\_edits210_oldlist
With lvc.LV_COLUMN
\Mask = #LVCF_FMT
\fmt=#LVCFMT_RIGHT
EndWith
SendMessage_(GadgetID(*LVEdits\_edits210_gadget),#LVM_SETCOLUMN,column,@lvc)
If width >= 1
*LVEdits\MoneyColumn(Column) = width
Else
*LVEdits\MoneyColumn(Column) = 1
EndIf
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
Procedure DecimalMask(char) ; Char is the character you wish to use for decimal point, usually '.' or ',' (46 or 44)
Shared *LVEdits.EDITDATA
*LVEdits\_edits210_decimal = char
EndProcedure
Procedure MaskColumn(Column) ; Disallows edits for the passed column
Shared *LVEdits.EDITDATA
If *LVEdits\_edits210_oldlist
*LVEdits\Masked(Column) = 1
ProcedureReturn 1
Else
ProcedureReturn 0
EndIf
EndProcedure
EndModule
Code: Select all
;=======================================================
; Program: AllowLVEdits 3.0 Demo program
; Author: netmaestro
;=======================================================
;
IncludeFile "allowlveditsV3.pbi"
UseModule LVEdit
Structure editrecord
row.i
col.i
newtext$
oldtext$
EndStructure
Global NewList edits.editrecord()
AddElement(edits())
Procedure$ DayStr(day)
ProcedureReturn Mid("SunMonTueWedThuFriSat", day*3+1, 3)
EndProcedure
Procedure Recalc()
runningtotal.d = 0
For i = 0 To CountGadgetItems(0)-1
tmp$ = GetGadgetItemText(0,i,2)
If tmp$<>"" : runningtotal+ValD(tmp$) : EndIf
tmp$ = GetGadgetItemText(0,i,3)
If tmp$<>"" : runningtotal-ValD(tmp$) : EndIf
If runningtotal < 0
txtout.s="("+StrD(runningtotal,2)+")"
Else
txtout.s = StrD(runningtotal,2)
EndIf
SetGadgetItemText(0,i,txtout,4)
If runningtotal < 0
SetGadgetItemColor(0,i,#PB_Gadget_FrontColor, #Red, 4)
EndIf
Next
EndProcedure
Procedure Load()
If ReadFile(0, "cashflow.dat")
SendMessage_(GadgetID(0), #WM_SETREDRAW, 0,0)
While Not Eof(0)
AddGadgetItem(0, -1, ReplaceString(ReadString(0),"|",Chr(10)))
Wend
CloseFile(0)
SendMessage_(GadgetID(0), #WM_SETREDRAW, 1, 0)
Else
SendMessage_(GadgetID(0), #WM_SETREDRAW, 0,0)
For i=0 To 365*5
date = AddDate(ParseDate("%mm/%dd/%yyyy","11/01/2011") , #PB_Date_Day, i)
date$ = DayStr(DayOfWeek(date))+FormatDate("%mm/%dd/%yyyy", date)
AddGadgetItem(0, -1, Chr(10)+RSet(date$,14," ")+Chr(10)+Space(0)+Chr(10)+Space(0)+Chr(10)+Space(0)+Chr(10)+Space(0)+Chr(10))
Next
SendMessage_(GadgetID(0), #WM_SETREDRAW, 1,0)
EndIf
For i=0 To CountGadgetItems(0)-1
SetGadgetItemColor(0,i,#PB_Gadget_BackColor,RGB(240,240,240),1)
If FindString(GetGadgetItemText(0,i,4), "(", 1)
SetGadgetItemColor(0,i,#PB_Gadget_FrontColor,#Red,4)
EndIf
SetGadgetItemColor(0,i,#PB_Gadget_BackColor,RGB(240,240,240),4)
Next
EndProcedure
Procedure Save()
Dim t.s(5)
If CreateFile(0, "CashFlow.dat")
For i = 0 To CountGadgetItems(0)-1
For j=1 To 5
t(j) = GetGadgetItemText(0,i,j)
Next
WriteStringN(0, "|"+t(1)+"|"+t(2)+"|"+t(3)+"|"+t(4)+"|"+t(5)+"|" )
Next
CloseFile(0)
EndIf
EndProcedure
LoadFont(0, "Courier New",9)
w = OpenWindow(0,0,0,840,700,"Cash Flow Budget",#PB_Window_ScreenCentered|#PB_Window_SystemMenu)
CreateToolBar(0, WindowID(0))
ToolBarStandardButton(0, #PB_ToolBarIcon_Save)
ToolBarStandardButton(1, #PB_ToolBarIcon_Undo)
ToolBarStandardButton(2, #PB_ToolBarIcon_Redo)
ListIconGadget(0,0,ToolBarHeight(0),840,700-ToolBarHeight(0),"",0,#PB_ListIcon_GridLines)
SetGadgetColor(0, #PB_Gadget_LineColor, RGB(210,210,210))
AddGadgetColumn(0,1,"Date", 150)
AddGadgetColumn(0,2,"Income", 130)
AddGadgetColumn(0,3,"Expense", 130)
AddGadgetColumn(0,4,"Balance", 130)
AddGadgetColumn(0,5,"Description", 275)
SetGadgetFont(0,FontID(0))
LVEdit::StartEditing(0,0)
LVEdit::SetMoneyColumn(2,12)
LVEdit::SetMoneyColumn(3,12)
LVEdit::SetMoneyColumn(4,12)
LVEdit::MaskColumn(1)
LVEdit::MaskColumn(4)
Load()
Repeat
EventID = WaitWindowEvent()
Select EventID
Case #PB_Event_Gadget
If EventGadget() = 0
Select EventType()
Case #Ale_Cellcontents_Changed
; store undo infos
AddElement(edits())
With edits()
\col = Ale_ColumnChanged()
\row = Ale_RowChanged()
\oldtext$ = Ale_OriginalText()
\newtext$ = GetGadgetItemText(0, edits()\row, edits()\col)
EndWith
current=ListIndex(edits())
LastElement(edits())
While ListIndex(edits())<>current
DeleteElement(edits())
Wend
; recalculate the worksheet
Recalc()
Case #PB_EventType_LeftDoubleClick
GetCursorPos_(@cp.POINT)
MapWindowPoints_(0,GadgetID(0),@cp.POINT,1)
HitInfo.LVHITTESTINFO\pt = cp.POINT
SendMessage_(GadgetID(0),#LVM_SUBITEMHITTEST ,0,@HitInfo)
If hitinfo\isubitem = 1
AddGadgetItem(0, hitinfo\iItem+1, Chr(10)+GetGadgetItemText(0,hitinfo\iItem,1))
SetGadgetItemColor(0, hitinfo\iItem+1, #PB_Gadget_BackColor, RGB(240,240,240), 1)
SetGadgetItemColor(0, hitinfo\iItem+1, #PB_Gadget_BackColor, RGB(240,240,240), 4)
recalc()
EndIf
Case #PB_EventType_RightDoubleClick
GetCursorPos_(@cp.POINT)
MapWindowPoints_(0,GadgetID(0),@cp.POINT,1)
HitInfo.LVHITTESTINFO\pt = cp.POINT
SendMessage_(GadgetID(0),#LVM_SUBITEMHITTEST ,0,@HitInfo)
If hitinfo\isubitem = 1
If GetGadgetItemText(0, hitinfo\iItem, 1) = GetGadgetItemText(0, hitinfo\iItem-1, 1)
RemoveGadgetItem(0, hitinfo\iItem)
recalc()
EndIf
EndIf
EndSelect
EndIf
Case #PB_Event_Menu
Select EventMenu()
Case 0
Save()
Case 1
If ListIndex(edits())>0
SetGadgetItemText(0, edits()\row, edits()\oldtext$, edits()\col)
PreviousElement(edits())
recalc()
EndIf
Case 2
NextElement(edits())
SetGadgetItemText(0, edits()\row, edits()\newtext$, edits()\col)
recalc()
EndSelect
EndSelect
Until EventID = #WM_CLOSE
Save()
LVEdit::StopEditing()