Page 3 of 4

Re: AllowLVEdits Version 2.0

Posted: Sun Oct 16, 2011 8:06 pm
by IdeasVacuum
....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.

Re: AllowLVEdits Version 2.0

Posted: Fri Nov 25, 2011 2:20 am
by electrochrisso
Ripper piece of coding there NM. :wink:

Re: AllowLVEdits Version 2.0

Posted: Fri Nov 25, 2011 1:46 pm
by Zach
Wow this is a pretty neat .pbi !

I wonder if I could use this. :mrgreen:

Re: AllowLVEdits Version 2.2

Posted: Sun Nov 27, 2011 4:08 pm
by netmaestro
Update today, current version is 2.20.

While using the cashflow sample provided in the first post, I noticed that there was a delay in the edit box coming up. I traced it to too many recalcs being done, and this turned out to be happening because the library was sending #PB_EventType_Change to the calling program when a cell was edited. I had assumed that #PB_EventType_Change for the ListIcon meant cell contents were changed. I was wrong, it turns out that event type means only that the currently selected item is changed. Since there is no event type for cell changes, I had to make a custom one for this library. Also, I added three new commands useful to the programmer for when edits happen. Upon receiving the message #PB_Event_Gadget with EventType() = #Ale_Cellcontents_Changed, these commands are available:

Ale_ColumnChanged()
Ale_RowChanged()
Ale_OriginalText()

Details are in the preamble to the code in the first post, code is updated and the cashflow example is updated with undo/redo demonstration.

Re: AllowLVEdits Version 2.2

Posted: Mon Nov 28, 2011 4:21 am
by electrochrisso
I noticed that too NM, I thought it was happening with updating the file, but still I only had a quick look at the code.
Those extra commands are a great edition. :D
Anyway thanks for the code to play with. :wink:

Re: AllowLVEdits Version 2.2

Posted: Mon Nov 28, 2011 4:33 am
by netmaestro
I thought it was happening with updating the file
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 mind :shock: Thanks for the testing and feedback, it's appreciated!

Re: AllowLVEdits Version 2.2

Posted: Mon Nov 28, 2011 11:47 am
by GeBonet
Very good job ... :D :D
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.
But hey, it's just an idea ... :wink:

Re: AllowLVEdits Version 2.2

Posted: Mon Nov 28, 2011 12:44 pm
by Tomi
Thanks for update, very useful
please me if maybe it and you find a bit free^free time:
if i paste from clipboard into a cell and then click on other cell , i need my pasted things remain into cell and don't remove in event, sorry for my bad English :D

Re: AllowLVEdits Version 2.2

Posted: Mon Nov 28, 2011 11:11 pm
by netmaestro
@Tomi: If you hit <Enter> after the paste the data will stay.
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.
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:

-Left doubleclick a date and a duplicate is inserted below it
-Right doubleclick a duplicated date and the row is deleted.

Right-doubleclicks for deletions are bulletproof because they are only executed if the date in the row above is identical. This way you can't accidentally remove a date altogether or remove the wrong date.

Thanks for the suggestion, it makes the program much more usable as a cashflow worksheet :mrgreen:

Re: AllowLVEdits Version 2.2

Posted: Tue Nov 29, 2011 12:13 am
by GeBonet
Well now, I am glad it is useful ... And thank you! :lol:
A thousand apologies if this shows the reality of balances :cry: :mrgreen:
Very good job. :lol: :lol:

Re: AllowLVEdits Version 2.2

Posted: Tue Nov 29, 2011 7:22 am
by electrochrisso
All these years I've been misunderstanding #PB_EventType_Change for the listicon, it makes me wonder if I'm losing my mind :shock: Thanks for the testing and feedback, it's appreciated!
Nah, I think PB getting many new features on each update to have time to test every option in every situation. :)

Re: AllowLVEdits Version 2.2

Posted: Tue Jul 09, 2013 12:18 am
by netmaestro
This program is updated to use the new module library. Here's the code:

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
I should mention that this version I pulled from a project and it has special processing for window# 2 and column# 2, it pops up a menu to make a choice from. You won't need this so just find SaveAndExitDesc() and use SaveAndExit() for everything.

Re: AllowLVEdits Version 2.2 Updated for V3.0

Posted: Mon Aug 05, 2013 1:08 pm
by Zebuddi123
Updated this example cause i needed the Pbi. Hope I`ve got it correct (this new fangle Module stuff) :shock: my poor little brain hurts :lol:

Big Thanks for the V3.0 Update netmaestro :D :D :D

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()
Zebuddi :D

Re: AllowLVEdits Version 2.2

Posted: Sat Nov 16, 2013 6:50 am
by loulou
It seems that allowedit consume a lot of memeory ? Is there a way to avoid that
Thanks in advance

Re: AllowLVEdits Version 2.2

Posted: Thu Jun 30, 2016 12:03 pm
by dobro
hum :)
why the function: LVEdit::StartEditing()
edite the Listicon only In capital letters ?? :shock: