LVICE_XXS - LV in-cell editing minimal version

Post your working scripts, libraries and tools.
just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

LVICE_XXS - LV in-cell editing minimal version

Post by just me » 23 Aug 2021, 10:35

Just an example:

Code: Select all

#Requires AutoHotKey v2.0
MainGui := Gui(, "LVICE_XXS Test")
MainGui.MarginX := 20
MainGui.MarginY := 20
Header := ["Column 1", "Column 2", "Column 3", "Column 4", "Column 5", "Column 6"]
MainLV := MainGui.AddListView("w600 r15 cBlue Grid -ReadOnly", Header)
MainLV.SetFont("s16")
Loop 16
   MainLV.Add("", "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index,
                  "Value " . A_Index)
Loop 16
   MainLV.Add("")
MainLV.ModifyCol()
MainGui.AddButton("xm", "Show changes").OnEvent("Click", ShowChanges)
MainGui.OnEvent("Close", MainGuiClose)
MainGui.Show()
LVICE := LVICE_XXS(MainLV)

MainGuiClose(GuiObj) {
   GuiObj.Destroy()
   ExitApp
}

ShowChanges(*) {
   Local Out := ""
   For X In LVICE.Changes
      Out .= X.Row . " - " . X.Col "`n"
   MsgBox(Out, LVICE.Changes.Length . " changes")
   LVICE.Changes.Length := 0 ; <<<<< if you want to reset the array
}
; ======================================================================================================================
;  Class LVICE_XXS      - ListView in-cell editing for AHK v2 - minimal version
; ======================================================================================================================
Class LVICE_XXS {
   ; -------------------------------------------------------------------------------------------------------------------
   __New(LV) {
      If (Type(LV) != "Gui.ListView")
         Throw Error("Class LVICE requires a GuiControl object of type Gui.ListView!")
      This.DoubleClickFunc := ObjBindMethod(This, "DoubleClick")
      This.BeginLabelEditFunc := ObjBindMethod(This, "BeginLabelEdit")
      This.EndLabelEditFunc := ObjBindMethod(This, "EndLabelEdit")
      This.CommandFunc := ObjBindMethod(This, "Command")
      LV.OnNotify(-3, This.DoubleClickFunc)
      This.LV := LV
      This.HWND := LV.Hwnd
      This.Changes := []
   }
   ; -------------------------------------------------------------------------------------------------------------------
   __Delete() {
      If DllCall("IsWindow", "Ptr", This.HWND, "UInt")
         This.LV.OnNotify(-3, This.DoubleClickFunc, 0)
      This.DoubleClickFunc := ""
      This.BeginLabelEditFunc := ""
      This.EndLabelEditFunc := ""
      This.CommandFunc := ""
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; NM_DBLCLK (list view) notification
   ; -------------------------------------------------------------------------------------------------------------------
   DoubleClick(LV, L) {
      Critical -1
      Item := NumGet(L + (A_PtrSize * 3), 0, "Int")
      Subitem := NumGet(L + (A_PtrSize * 3), 4, "Int")
      CellText := LV.GetText(Item + 1, SubItem + 1)
      RC := Buffer(16, 0)
      NumPut("Int", 0, "Int", SubItem, RC)
      DllCall("SendMessage", "Ptr", LV.Hwnd, "UInt", 0x1038, "Ptr", Item, "Ptr", RC) ; LVM_GETSUBITEMRECT
      This.CX := NumGet(RC, 0, "Int")
      If (Subitem = 0)
         This.CW := DllCall("SendMessage", "Ptr", LV.Hwnd, "UInt", 0x101D, "Ptr", 0, "Ptr", 0, "Int") ; LVM_GETCOLUMNWIDTH
      Else
         This.CW := NumGet(RC, 8, "Int") - This.CX
      This.CY := NumGet(RC, 4, "Int")
      This.CH := NumGet(RC, 12, "Int") - This.CY
      This.Item := Item
      This.Subitem := Subitem
      This.LV.OnNotify(-175, This.BeginLabelEditFunc)
      DllCall("PostMessage", "Ptr", LV.Hwnd, "UInt", 0x1076, "Ptr", Item, "Ptr", 0) ; LVM_EDITLABEL
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; LVN_BEGINLABELEDIT notification
   ; -------------------------------------------------------------------------------------------------------------------
   BeginLabelEdit(LV, L) {
      Critical -1
      This.HEDT := DllCall("SendMessage", "Ptr", LV.Hwnd, "UInt", 0x1018, "Ptr", 0, "Ptr", 0, "UPtr")
      This.ItemText := LV.GetText(This.Item + 1, This.Subitem + 1)
      DllCall("SendMessage", "Ptr", This.HEDT, "UInt", 0x00D3, "Ptr", 0x01, "Ptr", 4) ; EM_SETMARGINS, EC_LEFTMARGIN
      DllCall("SendMessage", "Ptr", This.HEDT, "UInt", 0x000C, "Ptr", 0, "Ptr", StrPtr(This.ItemText)) ; WM_SETTEXT
      DllCall("SetWindowPos", "Ptr", This.HEDT, "Ptr", 0, "Int", This.CX, "Int", This.CY,
                              "Int", This.CW, "Int", This.CH, "UInt", 0x04)
      OnMessage(0x0111, This.CommandFunc, -1)
      This.LV.OnNotify(-175, This.BeginLabelEditFunc, 0)
      This.LV.OnNotify(-176, This.EndLabelEditFunc)
      Return False

   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; LVN_ENDLABELEDIT notification
   ; -------------------------------------------------------------------------------------------------------------------
   EndLabelEdit(LV, L) {
      Static OffText := 16 + (A_PtrSize * 4)
      Critical -1
      This.LV.OnNotify(-176, This.EndLabelEditFunc, 0)
      OnMessage(0x0111, This.CommandFunc, 0)
      If (TxtPtr := NumGet(L, OffText, "UPtr")) {
         ItemText := StrGet(TxtPtr)
         If (ItemText != This.ItemText) {
            LV.Modify(This.Item + 1, "Col" . (This.Subitem + 1), ItemText)
            This.Changes.Push({Row: This.Item + 1, Col: This.Subitem + 1})
         }
      }
      Return False
   }
   ; -------------------------------------------------------------------------------------------------------------------
   ; WM_COMMAND notification
   ; -------------------------------------------------------------------------------------------------------------------
   Command(W, L, M, H) {
      Critical -1
      If (L = This.HEDT) {
         N := (W >> 16) & 0xFFFF
         If (N = 0x0400) || (N = 0x0300) || (N = 0x0100) { ; EN_UPDATE | EN_CHANGE | EN_SETFOCUS
            DllCall("SetWindowPos", "Ptr", L, "Ptr", 0, "Int", This.CX, "Int", This.CY,
                                    "Int", This.CW, "Int", This.CH, "UInt", 0x04)
         }
      }
   }
}
Edit: Fixed line 95, thx @kczx3.

Edit: Editorial changes.

Edit: Added a Changes property (array) to hold the row and column index of changed cells.

:arrow: Github
Last edited by just me on 15 Feb 2024, 09:37, edited 4 times in total.

User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by kczx3 » 23 Aug 2021, 11:13

Should line 95 have a zero passed to OnNotify as the third parameter? I assumed you were wanting to remove that callback, yes?

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by just me » 24 Aug 2021, 02:04

Of course, thanks!

AHK_user
Posts: 515
Joined: 04 Dec 2015, 14:52
Location: Belgium

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by AHK_user » 14 May 2022, 01:05

Good work, I was just looking for this Listview in-cell edit function.
Beatifull how you made it with such a short code.

I could not find it on the forum because it did not showed up if you searched on the word "Listview" :D

I noticed one strange side effect, the value of the first column is temporary hidden if you edit a cell.

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by just me » 16 May 2022, 03:29

AHK_user wrote:I noticed one strange side effect, the value of the first column is temporary hidden if you edit a cell.
That's the default ListView behaviour. I did not find a way to prevent it.

User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by kczx3 » 10 Aug 2023, 10:43

You may not need Critical anymore in your callbacks with the somewhat recent fixes made to message handling

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by just me » 11 Aug 2023, 03:02

Might be, did you test it?

Spitzi
Posts: 313
Joined: 24 Feb 2022, 03:45

Re: 2.0-beta.1: LVICE_XXS apha.1 - LV in-cell editing minimal version

Post by Spitzi » 16 Aug 2023, 09:17

Love this, thanks.

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: LVICE_XXS - LV in-cell editing minimal version

Post by just me » 01 Feb 2024, 05:07

Released on Github (see first post).

legeinfo
Posts: 18
Joined: 27 Nov 2016, 07:52

Re: LVICE_XXS - LV in-cell editing minimal version

Post by legeinfo » 13 Feb 2024, 11:42

Very nice!
But i have no clue how to read out a specific cell after editing?
I have seen a "F" label in the V1 version like the checked for checkboxes. But here?

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: LVICE_XXS - LV in-cell editing minimal version

Post by just me » 14 Feb 2024, 04:30

@legeinfo, you want to get the new text immediately after it was changed?

legeinfo
Posts: 18
Joined: 27 Nov 2016, 07:52

Re: LVICE_XXS - LV in-cell editing minimal version

Post by legeinfo » 14 Feb 2024, 11:29

@just me No, after "Save/OK" button is enough. But i have no clue where to start.

just me
Posts: 9442
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: LVICE_XXS - LV in-cell editing minimal version

Post by just me » 15 Feb 2024, 03:46

@legeinfo, something like this?

Code: Select all

You find the changed code in the OP now.
I added a Changes property to the class.
Last edited by just me on 15 Feb 2024, 09:39, edited 1 time in total.

legeinfo
Posts: 18
Joined: 27 Nov 2016, 07:52

Re: LVICE_XXS - LV in-cell editing minimal version

Post by legeinfo » 15 Feb 2024, 09:21

@just me YES! Thank you. So easy! Thanks a lot!

Post Reply

Return to “Scripts and Functions (v2)”