I wrote this function that can be used to "Add" or "Edit" rows from ListView controls!
For my needs, the function is ready! But, if anyone here wants to improve it, feel free to do it so! (If there are better functions out there than this one, please share here!)
V2 uses SimpleObject "o()" function instead AHK Built-in Object!
v2.0 (Click here)
v1.1 (Click here)
v1.0 (Below)
Basic - 1 Listview control
Code: Select all
gui, add, listview, w310 vLV1 gLVEvents BackgroundWhite Grid, Id|A|B|C|D
loop, 5
LV_ModifyCol(a_index, 55) ;columns change columns width
loop, 4
LV_Add("", a_index) ;add rows
gui, add, button, xm gAdd, Add
gui, add, button, x+5 gEdit, Edit
gui, add, text, x+5, "Alternative: Double-Click rows to edit them!"
gui, show
return
LVEvents: ;_____________ LVEvents ________________
if (A_GuiEvent = "DoubleClick")
LV_AddEditRow(A_Gui, A_GuiControl, "Modify")
return
Edit: ;____________ Edit _______________
LV_AddEditRow(A_Gui, "LV1", "Modify")
return
Add: ;____________ Add _______________
LV_AddEditRow(A_Gui, "LV1", "Add")
return
guiclose: ;_____________ gui close _______________
exitapp
LV_AddEditRow(GuiWnd, LVCtrl, Status, Optns := "") ;_______________ Add/Edit ListView Controls Rows - v1.0 (Function) ___________________
{
;Local ;uncomment this line if you use AutoHotKey v1.1.27+
;Force all variables in this function to be "Local" vars (with no exceptions)
;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
;this function was tested in AutoHotKey 1.1.23.05
;Local TempControlId ;this line was disabled because otherwise it would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)
Static ControlHwndId := [], CtrlType := [], CtrlHwnd := [] ;declare the variable as an object and remember its values between function calls
Static GuiWindow, LVControl, FocusedRow, TotalCols, Options, GuiHwnd ;"Static" variables, remember values between function calls
if (Status = "GetVar")
return, (%LVCtrl%) ;return the values of static variables from this function
if (Status = "GetObject") ;return the values of static Objects from this function
return, %GuiWnd%[LVCtrl]
GuiWindow := GuiWnd
LVControl := LVCtrl
Options := Optns.Clone()
;"Clone()", Returns a shallow (not always a 100% clone???) copy of the object.
;"Clone()" creates a new object from the object referenced by "Optns" variable!
;then, "Options" variable will reference that newly created/cloned object!
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
FocusedRow := LV_GetNext(0, "Focused")
;Search for the focused row ("0", the search starts from row number 1!
;there is never more than one focused row in the entire list, and sometimes there is none at all!
if (Status = "Modify" and FocusedRow = 0)
{
msgbox, 8240, Warning!, No row is selected! Please, select a row to be modified!
;"8240" sum of 8192 and 48 (8192 for "Task Modal" option \ 48 for Icon Exclamation + sound)
;"52" sum of 4 and 48 (4 for "yes - no" options \ 48 for Icon Exclamation + sound)
gui, LVAddEditRow:Destroy
return
}
TotalCols := LV_GetCount("Col") ;the function returns the number of columns in the control
gui, LVAddEditRow:Default
gui, destroy
Gui +HwndGuiHwnd
loop, % TotalCols
{
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
LV_GetText(TempHeader, 0, a_index) ;"0" is the columns header row / "a_index" is the column number
if (Status = "Modify")
LV_GetText(TempText, FocusedRow, a_index) ;"a_index" is the column number
gui, LVAddEditRow:Default
TempIndex := a_index
loop
{
if (Options["BeforeCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
gui, add, % Options["BeforeCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["BeforeCell" TempIndex "Ctrl" a_index "Options"], % Options["BeforeCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["BeforeCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
gui, add, text, % Options["Cell" a_index "HeaderOptions"], % TempHeader
;Ternary operator, ( ? = if ) and ( : = else )
ControlType := ControlOption := ControlText := "" ;blank\empty values
ControlType := CtrlType[a_index] := Options["Cell" a_index "Type"] != "" ? Options["Cell" a_index "Type"] : "Edit"
if (ControlType = "Checkbox")
{
ControlOption := Status = "Add" ? "" : "Checked" TempText
}
else if (ControlType = "DateTime")
{
TempText := TempText = "" ? "None" : RegExReplace(TempText, "\D") ;"\D" means any non-digit (remove any non-digit characters)
ControlOption := Status = "Add" ? "" : "Choose" TempText
}
else if (ControlType = "ListBox" or ControlType = "DropDownList" or ControlType = "DDL")
{
if (Status = "Modify")
{
TempIndex := a_index
TempList := Options["Cell" TempIndex "Text"], Options["Cell" TempIndex "Text"] := ""
loop, parse, TempList, |
{
if (A_LoopField == "") ;if blank\empty (== is case-sensitive)
continue ;Skips the rest of the current loop iteration and begins a new one. Valid inside any kind of loop.
TempString := A_LoopField
loop, parse, TempText, |
{
if ("S" TempString == "S" A_LoopField) ;"==" is case-sensitive, "S" forces "string" comprisons and avoids "number" comparisons!
{
TempString .= "|"
break
}
}
Options["Cell" TempIndex "Text"] .= TempString "|"
}
}
}
else if (ControlType != "Edit" and ControlType != "ComboBox")
{
if (ControlType = "MonthCal")
TempText := RegExReplace(TempText, "\Q/") ;remove any "/" character
if (Status = "Modify")
ControlText := TempText, Options["Cell" a_index "Text"] := ""
}
gui, add, % ControlType, % "+HwndTempControlId " Options["Cell" a_index "Options"] " " ControlOption, % Options["Cell" a_index "Text"] ControlText
if (Status = "Modify")
{
if (ControlType = "Edit" or ControlType = "ComboBox")
ControlSetText, , % TempText, % "ahk_id" TempControlId ;"ControlSetText" prevents "EOL" (End of LIne Translation), no "`n" is translated to "`r`n"
}
ControlHwndId[a_index] := TempControlId ;the variable must be declared as an object first ("ControlHwndId := []")
TempKey := Options["Cell" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
TempIndex := a_index
loop
{
if (Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
if (a_index = "1" and Status = "Modify" and Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "UpDown")
Options["AfterCell" TempIndex "Ctrl" a_index "Text"] := RegExReplace(TempText, "\.|,") ;Regex removes thousands separator (. or ,)
gui, add, % Options["AfterCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["AfterCell" TempIndex "Ctrl" a_index "Options"], % Options["AfterCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["AfterCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
}
TempText := "" ;make variable blank (free memory)
if (Status = "Modify")
GuiCaption := ButtonCaption := "Modify"
else
GuiCaption := ButtonCaption := "Add"
gui, add, button, xm gLVAddEditRowLabel Default, % ButtonCaption
if (Status = "Modify")
{
gui, add, button, x+5 gLVAddEditRowLabel , Add
gui, add, button, x+5 gLVAddEditRowLabel , Delete
}
gui, add, button, x+5 gLVAddEditRowGuiClose, Cancel
gui, show, , % GuiCaption
return
LVAddEditRowLabel: ;_________ Function Label __________
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
if (a_guicontrol = "Delete")
{
LV_Delete(FocusedRow)
FocusedRow := LV_GetNext(0, "Focused") ;Search for the focused row ("0", the search starts from row number 1!
}
if (a_guicontrol = "Add" or a_guicontrol = "Modify")
{
if (a_guicontrol = "Add")
{
FocusedRow := LV_Insert(Options["NewRowIndex"] = "" ? LV_GetCount() + 1 : Options["NewRowIndex"], Options["NewRowOptions"])
;The function adds a new row to the specified index position (if the ListView control does not have the "Sort" or "SortDesc" style)
;The function returns the new row number, which is not necessarily the specified index position if the ListView has the "Sort" or "SortDesc" style.
;Ternary operator, (? = if) and (: = else)
;if Options["NewRowIndex"] is blank\empty, the new row will be inserted to the end of the listview control, "LV_GetCount() + 1"
;for some reason, the Options["NewRowOptions"] prevents Autohotkey from crashing if Options["NewRowIndex"] is blank/empty and the ListView control contains "Sort" or "SortDesc" options
}
if (a_guicontrol = "Modify")
{
LV_Modify(FocusedRow, Options["RowOptions"])
}
loop, % TotalCols
{
if (CtrlType[a_index] = "Edit" or CtrlType[a_index] = "ComboBox")
ControlGetText, TempText, , % "ahk_id" ControlHwndId[a_index] ;"ControlGetText" prevents EOL "End of line translation", no "`r`n" is translated to "`n"
else
GuiControlGet, TempText, LVAddEditRow:, % ControlHwndId[a_index]
if (CtrlType[a_index] = "DateTime")
{
if (TempText != "")
FormatTime, TempText, % TempText, yyyy-MM-dd/HH:mm:ss ;"HH" 24-hour format (00 – 23)
}
else if (CtrlType[a_index] = "MonthCal")
{
if (TempText != "")
{
Loop, Parse, TempText, -
{
TempText := a_index = 1 ? "" : TempText
FormatTime, TempTime, % A_LoopField, yyyy/MM/dd ;"MonthCal" does not retrieve "HH24MISS" time portion , retrieves only "YYYYMMDD" Date
TempText .= TempTime "-"
}
TempText := RegExReplace(TempText, "-$") ;remove the last "-" character at the end of the string
}
}
LV_Modify(FocusedRow, "Col" a_index, TempText)
}
}
LV_Modify(0, "-Select") ;Deselect all rows
LV_Modify(FocusedRow, "Focus Select Vis")
;"vis", Ensures that the specified row is completely visible by scrolling the ListView, if necessary.
;"Vis", has an effect only for "LV_Modify()" function! (does not work with "LV_Add()" function!)
;"Focus", Sets keyboard focus to the row / "Select", highlight the row
LVAddEditRowGuiClose: ;_______ LVAddEditRow Gui Close _______
LVAddEditRowGuiEscape:
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
GuiControl, Focus, % A_DefaultListView ;"A_DefaultListView" supported from [v1.1.23+]
if (Options["GoSub"] != "") ;if not blank/empty
GoSub, % Options["GoSub"] ;"GoTo" is not allowed inside functions, only "GoSub" is!
TempText := "", ControlHwndId := [], CtrlType := [], CtrlHwnd := [], Options := [] ;make variable blank (free memory)
gui, LVAddEditRow:Destroy ;by destroying the gui window, "a_guicontrol" will be made blank\empty!
return
}
Code: Select all
gui, add, listview, w310 vLV1 gLVEvents BackgroundWhite Grid, Id|A|B|C|D
loop, 5
LV_ModifyCol(a_index, 55) ;columns change columns width
loop, 4
LV_Add("", a_index) ;add rows
gui, add, button, xm gAdd1, Add
gui, add, button, x+5 gEdit1, Edit
gui, add, text, x+5, "Alternative: Double-Click rows to edit them!"
;____________
gui, add, listview, xm w310 vLV2 gLVEvents BackgroundWhite Grid, Id|E|F|G|H
loop, 5
LV_ModifyCol(a_index, 55) ;columns change columns width
loop, 4
LV_Add("", a_index) ;add rows
gui, add, button, xm gAdd2, Add
gui, add, button, x+5 gEdit2, Edit
gui, add, text, x+5, "Alternative: Double-Click rows to edit them!"
gui, show
return
LVEvents: ;_____________ LVEvents (LV1 and Lv2) ________________
if (A_GuiEvent = "DoubleClick")
LV_AddEditRow(A_Gui, A_GuiControl, "Modify")
return
Edit1: ;____________ Edit 1 _______________
LV_AddEditRow(A_Gui, "LV1", "Modify")
return
Add1: ;____________ Add 1 _______________
LV_AddEditRow(A_Gui, "LV1", "Add")
return
Edit2: ;____________ Edit 2 _______________
LV_AddEditRow(A_Gui, "LV2", "Modify")
return
Add2: ;____________ Add 2 _______________
LV_AddEditRow(A_Gui, "LV2", "Add")
return
guiclose: ;_____________ gui close _______________
exitapp
LV_AddEditRow(GuiWnd, LVCtrl, Status, Optns := "") ;_______________ Add/Edit ListView Controls Rows - v1.0 (Function) ___________________
{
;Local ;uncomment this line if you use AutoHotKey v1.1.27+
;Force all variables in this function to be "Local" vars (with no exceptions)
;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
;this function was tested in AutoHotKey 1.1.23.05
;Local TempControlId ;this line was disabled because otherwise it would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)
Static ControlHwndId := [], CtrlType := [], CtrlHwnd := [] ;declare the variable as an object and remember its values between function calls
Static GuiWindow, LVControl, FocusedRow, TotalCols, Options, GuiHwnd ;"Static" variables, remember values between function calls
if (Status = "GetVar")
return, (%LVCtrl%) ;return the values of static variables from this function
if (Status = "GetObject") ;return the values of static Objects from this function
return, %GuiWnd%[LVCtrl]
GuiWindow := GuiWnd
LVControl := LVCtrl
Options := Optns.Clone()
;"Clone()", Returns a shallow (not always a 100% clone???) copy of the object.
;"Clone()" creates a new object from the object referenced by "Optns" variable!
;then, "Options" variable will reference that newly created/cloned object!
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
FocusedRow := LV_GetNext(0, "Focused")
;Search for the focused row ("0", the search starts from row number 1!
;there is never more than one focused row in the entire list, and sometimes there is none at all!
if (Status = "Modify" and FocusedRow = 0)
{
msgbox, 8240, Warning!, No row is selected! Please, select a row to be modified!
;"8240" sum of 8192 and 48 (8192 for "Task Modal" option \ 48 for Icon Exclamation + sound)
;"52" sum of 4 and 48 (4 for "yes - no" options \ 48 for Icon Exclamation + sound)
gui, LVAddEditRow:Destroy
return
}
TotalCols := LV_GetCount("Col") ;the function returns the number of columns in the control
gui, LVAddEditRow:Default
gui, destroy
Gui +HwndGuiHwnd
loop, % TotalCols
{
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
LV_GetText(TempHeader, 0, a_index) ;"0" is the columns header row / "a_index" is the column number
if (Status = "Modify")
LV_GetText(TempText, FocusedRow, a_index) ;"a_index" is the column number
gui, LVAddEditRow:Default
TempIndex := a_index
loop
{
if (Options["BeforeCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
gui, add, % Options["BeforeCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["BeforeCell" TempIndex "Ctrl" a_index "Options"], % Options["BeforeCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["BeforeCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
gui, add, text, % Options["Cell" a_index "HeaderOptions"], % TempHeader
;Ternary operator, ( ? = if ) and ( : = else )
ControlType := ControlOption := ControlText := "" ;blank\empty values
ControlType := CtrlType[a_index] := Options["Cell" a_index "Type"] != "" ? Options["Cell" a_index "Type"] : "Edit"
if (ControlType = "Checkbox")
{
ControlOption := Status = "Add" ? "" : "Checked" TempText
}
else if (ControlType = "DateTime")
{
TempText := TempText = "" ? "None" : RegExReplace(TempText, "\D") ;"\D" means any non-digit (remove any non-digit characters)
ControlOption := Status = "Add" ? "" : "Choose" TempText
}
else if (ControlType = "ListBox" or ControlType = "DropDownList" or ControlType = "DDL")
{
if (Status = "Modify")
{
TempIndex := a_index
TempList := Options["Cell" TempIndex "Text"], Options["Cell" TempIndex "Text"] := ""
loop, parse, TempList, |
{
if (A_LoopField == "") ;if blank\empty (== is case-sensitive)
continue ;Skips the rest of the current loop iteration and begins a new one. Valid inside any kind of loop.
TempString := A_LoopField
loop, parse, TempText, |
{
if ("S" TempString == "S" A_LoopField) ;"==" is case-sensitive, "S" forces "string" comprisons and avoids "number" comparisons!
{
TempString .= "|"
break
}
}
Options["Cell" TempIndex "Text"] .= TempString "|"
}
}
}
else if (ControlType != "Edit" and ControlType != "ComboBox")
{
if (ControlType = "MonthCal")
TempText := RegExReplace(TempText, "\Q/") ;remove any "/" character
if (Status = "Modify")
ControlText := TempText, Options["Cell" a_index "Text"] := ""
}
gui, add, % ControlType, % "+HwndTempControlId " Options["Cell" a_index "Options"] " " ControlOption, % Options["Cell" a_index "Text"] ControlText
if (Status = "Modify")
{
if (ControlType = "Edit" or ControlType = "ComboBox")
ControlSetText, , % TempText, % "ahk_id" TempControlId ;"ControlSetText" prevents "EOL" (End of LIne Translation), no "`n" is translated to "`r`n"
}
ControlHwndId[a_index] := TempControlId ;the variable must be declared as an object first ("ControlHwndId := []")
TempKey := Options["Cell" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
TempIndex := a_index
loop
{
if (Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
if (a_index = "1" and Status = "Modify" and Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "UpDown")
Options["AfterCell" TempIndex "Ctrl" a_index "Text"] := RegExReplace(TempText, "\.|,") ;Regex removes thousands separator (. or ,)
gui, add, % Options["AfterCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["AfterCell" TempIndex "Ctrl" a_index "Options"], % Options["AfterCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["AfterCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
}
TempText := "" ;make variable blank (free memory)
if (Status = "Modify")
GuiCaption := ButtonCaption := "Modify"
else
GuiCaption := ButtonCaption := "Add"
gui, add, button, xm gLVAddEditRowLabel Default, % ButtonCaption
if (Status = "Modify")
{
gui, add, button, x+5 gLVAddEditRowLabel , Add
gui, add, button, x+5 gLVAddEditRowLabel , Delete
}
gui, add, button, x+5 gLVAddEditRowGuiClose, Cancel
gui, show, , % GuiCaption
return
LVAddEditRowLabel: ;_________ Function Label __________
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
if (a_guicontrol = "Delete")
{
LV_Delete(FocusedRow)
FocusedRow := LV_GetNext(0, "Focused") ;Search for the focused row ("0", the search starts from row number 1!
}
if (a_guicontrol = "Add" or a_guicontrol = "Modify")
{
if (a_guicontrol = "Add")
{
FocusedRow := LV_Insert(Options["NewRowIndex"] = "" ? LV_GetCount() + 1 : Options["NewRowIndex"], Options["NewRowOptions"])
;The function adds a new row to the specified index position (if the ListView control does not have the "Sort" or "SortDesc" style)
;The function returns the new row number, which is not necessarily the specified index position if the ListView has the "Sort" or "SortDesc" style.
;Ternary operator, (? = if) and (: = else)
;if Options["NewRowIndex"] is blank\empty, the new row will be inserted to the end of the listview control, "LV_GetCount() + 1"
;for some reason, the Options["NewRowOptions"] prevents Autohotkey from crashing if Options["NewRowIndex"] is blank/empty and the ListView control contains "Sort" or "SortDesc" options
}
if (a_guicontrol = "Modify")
{
LV_Modify(FocusedRow, Options["RowOptions"])
}
loop, % TotalCols
{
if (CtrlType[a_index] = "Edit" or CtrlType[a_index] = "ComboBox")
ControlGetText, TempText, , % "ahk_id" ControlHwndId[a_index] ;"ControlGetText" prevents EOL "End of line translation", no "`r`n" is translated to "`n"
else
GuiControlGet, TempText, LVAddEditRow:, % ControlHwndId[a_index]
if (CtrlType[a_index] = "DateTime")
{
if (TempText != "")
FormatTime, TempText, % TempText, yyyy-MM-dd/HH:mm:ss ;"HH" 24-hour format (00 – 23)
}
else if (CtrlType[a_index] = "MonthCal")
{
if (TempText != "")
{
Loop, Parse, TempText, -
{
TempText := a_index = 1 ? "" : TempText
FormatTime, TempTime, % A_LoopField, yyyy/MM/dd ;"MonthCal" does not retrieve "HH24MISS" time portion , retrieves only "YYYYMMDD" Date
TempText .= TempTime "-"
}
TempText := RegExReplace(TempText, "-$") ;remove the last "-" character at the end of the string
}
}
LV_Modify(FocusedRow, "Col" a_index, TempText)
}
}
LV_Modify(0, "-Select") ;Deselect all rows
LV_Modify(FocusedRow, "Focus Select Vis")
;"vis", Ensures that the specified row is completely visible by scrolling the ListView, if necessary.
;"Vis", has an effect only for "LV_Modify()" function! (does not work with "LV_Add()" function!)
;"Focus", Sets keyboard focus to the row / "Select", highlight the row
LVAddEditRowGuiClose: ;_______ LVAddEditRow Gui Close _______
LVAddEditRowGuiEscape:
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
GuiControl, Focus, % A_DefaultListView ;"A_DefaultListView" supported from [v1.1.23+]
if (Options["GoSub"] != "") ;if not blank/empty
GoSub, % Options["GoSub"] ;"GoTo" is not allowed inside functions, only "GoSub" is!
TempText := "", ControlHwndId := [], CtrlType := [], CtrlHwnd := [], Options := [] ;make variable blank (free memory)
gui, LVAddEditRow:Destroy ;by destroying the gui window, "a_guicontrol" will be made blank\empty!
return
}
Code: Select all
gui, add, listview, w310 vLV1 gLVEvents BackgroundWhite Grid, Id|A|B|C|D
loop, 5
LV_ModifyCol(a_index, 55) ;columns change columns width
loop, 4
LV_Add("", a_index) ;add rows
gui, add, button, xm gAdd1, Add
gui, add, button, x+5 gEdit1, Edit
gui, add, text, x+5, "Alternative: Double-Click rows to edit them!"
LV1Options := []
LV1Options["Cell2Type"] := "ListBox"
LV1Options["Cell2Text"] := "AAA|BBB|CCC||DDD"
;____________
gui, add, listview, xm w310 vLV2 gLVEvents BackgroundWhite Grid, Id|E|F|G|H
loop, 5
LV_ModifyCol(a_index, 55) ;columns change columns width
loop, 4
LV_Add("", a_index) ;add rows
gui, add, button, xm gAdd2, Add
gui, add, button, x+5 gEdit2, Edit
gui, add, text, x+5, "Alternative: Double-Click rows to edit them!"
LV2Options := []
LV2Options["Cell5Type"] := "DropDownList"
LV2Options["Cell5Text"] := "EEE|FFF|GGG||HHH"
gui, show
return
LVEvents: ;_____________ LVEvents (LV1 and Lv2) ________________
if (A_GuiEvent = "DoubleClick")
{
if (a_guicontrol = "LV1")
Options := LV1Options
if (a_guicontrol = "LV2")
Options := LV2Options
LV_AddEditRow(A_Gui, A_GuiControl, "Modify", Options)
}
return
Edit1: ;____________ Edit 1 _______________
LV_AddEditRow(A_Gui, "LV1", "Modify", LV1Options)
return
Add1: ;____________ Add 1 _______________
LV_AddEditRow(A_Gui, "LV1", "Add", LV1Options)
return
Edit2: ;____________ Edit 2 _______________
LV_AddEditRow(A_Gui, "LV2", "Modify", LV2Options)
return
Add2: ;____________ Add 2 _______________
LV_AddEditRow(A_Gui, "LV2", "Add", LV2Options)
return
guiclose: ;_____________ gui close _______________
exitapp
LV_AddEditRow(GuiWnd, LVCtrl, Status, Optns := "") ;_______________ Add/Edit ListView Controls Rows - v1.0 (Function) ___________________
{
;Local ;uncomment this line if you use AutoHotKey v1.1.27+
;Force all variables in this function to be "Local" vars (with no exceptions)
;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
;this function was tested in AutoHotKey 1.1.23.05
;Local TempControlId ;this line was disabled because otherwise it would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)
Static ControlHwndId := [], CtrlType := [], CtrlHwnd := [] ;declare the variable as an object and remember its values between function calls
Static GuiWindow, LVControl, FocusedRow, TotalCols, Options, GuiHwnd ;"Static" variables, remember values between function calls
if (Status = "GetVar")
return, (%LVCtrl%) ;return the values of static variables from this function
if (Status = "GetObject") ;return the values of static Objects from this function
return, %GuiWnd%[LVCtrl]
GuiWindow := GuiWnd
LVControl := LVCtrl
Options := Optns.Clone()
;"Clone()", Returns a shallow (not always a 100% clone???) copy of the object.
;"Clone()" creates a new object from the object referenced by "Optns" variable!
;then, "Options" variable will reference that newly created/cloned object!
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
FocusedRow := LV_GetNext(0, "Focused")
;Search for the focused row ("0", the search starts from row number 1!
;there is never more than one focused row in the entire list, and sometimes there is none at all!
if (Status = "Modify" and FocusedRow = 0)
{
msgbox, 8240, Warning!, No row is selected! Please, select a row to be modified!
;"8240" sum of 8192 and 48 (8192 for "Task Modal" option \ 48 for Icon Exclamation + sound)
;"52" sum of 4 and 48 (4 for "yes - no" options \ 48 for Icon Exclamation + sound)
gui, LVAddEditRow:Destroy
return
}
TotalCols := LV_GetCount("Col") ;the function returns the number of columns in the control
gui, LVAddEditRow:Default
gui, destroy
Gui +HwndGuiHwnd
loop, % TotalCols
{
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
LV_GetText(TempHeader, 0, a_index) ;"0" is the columns header row / "a_index" is the column number
if (Status = "Modify")
LV_GetText(TempText, FocusedRow, a_index) ;"a_index" is the column number
gui, LVAddEditRow:Default
TempIndex := a_index
loop
{
if (Options["BeforeCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
gui, add, % Options["BeforeCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["BeforeCell" TempIndex "Ctrl" a_index "Options"], % Options["BeforeCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["BeforeCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
gui, add, text, % Options["Cell" a_index "HeaderOptions"], % TempHeader
;Ternary operator, ( ? = if ) and ( : = else )
ControlType := ControlOption := ControlText := "" ;blank\empty values
ControlType := CtrlType[a_index] := Options["Cell" a_index "Type"] != "" ? Options["Cell" a_index "Type"] : "Edit"
if (ControlType = "Checkbox")
{
ControlOption := Status = "Add" ? "" : "Checked" TempText
}
else if (ControlType = "DateTime")
{
TempText := TempText = "" ? "None" : RegExReplace(TempText, "\D") ;"\D" means any non-digit (remove any non-digit characters)
ControlOption := Status = "Add" ? "" : "Choose" TempText
}
else if (ControlType = "ListBox" or ControlType = "DropDownList" or ControlType = "DDL")
{
if (Status = "Modify")
{
TempIndex := a_index
TempList := Options["Cell" TempIndex "Text"], Options["Cell" TempIndex "Text"] := ""
loop, parse, TempList, |
{
if (A_LoopField == "") ;if blank\empty (== is case-sensitive)
continue ;Skips the rest of the current loop iteration and begins a new one. Valid inside any kind of loop.
TempString := A_LoopField
loop, parse, TempText, |
{
if ("S" TempString == "S" A_LoopField) ;"==" is case-sensitive, "S" forces "string" comprisons and avoids "number" comparisons!
{
TempString .= "|"
break
}
}
Options["Cell" TempIndex "Text"] .= TempString "|"
}
}
}
else if (ControlType != "Edit" and ControlType != "ComboBox")
{
if (ControlType = "MonthCal")
TempText := RegExReplace(TempText, "\Q/") ;remove any "/" character
if (Status = "Modify")
ControlText := TempText, Options["Cell" a_index "Text"] := ""
}
gui, add, % ControlType, % "+HwndTempControlId " Options["Cell" a_index "Options"] " " ControlOption, % Options["Cell" a_index "Text"] ControlText
if (Status = "Modify")
{
if (ControlType = "Edit" or ControlType = "ComboBox")
ControlSetText, , % TempText, % "ahk_id" TempControlId ;"ControlSetText" prevents "EOL" (End of LIne Translation), no "`n" is translated to "`r`n"
}
ControlHwndId[a_index] := TempControlId ;the variable must be declared as an object first ("ControlHwndId := []")
TempKey := Options["Cell" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
TempIndex := a_index
loop
{
if (Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
if (a_index = "1" and Status = "Modify" and Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "UpDown")
Options["AfterCell" TempIndex "Ctrl" a_index "Text"] := RegExReplace(TempText, "\.|,") ;Regex removes thousands separator (. or ,)
gui, add, % Options["AfterCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["AfterCell" TempIndex "Ctrl" a_index "Options"], % Options["AfterCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["AfterCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
}
TempText := "" ;make variable blank (free memory)
if (Status = "Modify")
GuiCaption := ButtonCaption := "Modify"
else
GuiCaption := ButtonCaption := "Add"
gui, add, button, xm gLVAddEditRowLabel Default, % ButtonCaption
if (Status = "Modify")
{
gui, add, button, x+5 gLVAddEditRowLabel , Add
gui, add, button, x+5 gLVAddEditRowLabel , Delete
}
gui, add, button, x+5 gLVAddEditRowGuiClose, Cancel
gui, show, , % GuiCaption
return
LVAddEditRowLabel: ;_________ Function Label __________
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
if (a_guicontrol = "Delete")
{
LV_Delete(FocusedRow)
FocusedRow := LV_GetNext(0, "Focused") ;Search for the focused row ("0", the search starts from row number 1!
}
if (a_guicontrol = "Add" or a_guicontrol = "Modify")
{
if (a_guicontrol = "Add")
{
FocusedRow := LV_Insert(Options["NewRowIndex"] = "" ? LV_GetCount() + 1 : Options["NewRowIndex"], Options["NewRowOptions"])
;The function adds a new row to the specified index position (if the ListView control does not have the "Sort" or "SortDesc" style)
;The function returns the new row number, which is not necessarily the specified index position if the ListView has the "Sort" or "SortDesc" style.
;Ternary operator, (? = if) and (: = else)
;if Options["NewRowIndex"] is blank\empty, the new row will be inserted to the end of the listview control, "LV_GetCount() + 1"
;for some reason, the Options["NewRowOptions"] prevents Autohotkey from crashing if Options["NewRowIndex"] is blank/empty and the ListView control contains "Sort" or "SortDesc" options
}
if (a_guicontrol = "Modify")
{
LV_Modify(FocusedRow, Options["RowOptions"])
}
loop, % TotalCols
{
if (CtrlType[a_index] = "Edit" or CtrlType[a_index] = "ComboBox")
ControlGetText, TempText, , % "ahk_id" ControlHwndId[a_index] ;"ControlGetText" prevents EOL "End of line translation", no "`r`n" is translated to "`n"
else
GuiControlGet, TempText, LVAddEditRow:, % ControlHwndId[a_index]
if (CtrlType[a_index] = "DateTime")
{
if (TempText != "")
FormatTime, TempText, % TempText, yyyy-MM-dd/HH:mm:ss ;"HH" 24-hour format (00 – 23)
}
else if (CtrlType[a_index] = "MonthCal")
{
if (TempText != "")
{
Loop, Parse, TempText, -
{
TempText := a_index = 1 ? "" : TempText
FormatTime, TempTime, % A_LoopField, yyyy/MM/dd ;"MonthCal" does not retrieve "HH24MISS" time portion , retrieves only "YYYYMMDD" Date
TempText .= TempTime "-"
}
TempText := RegExReplace(TempText, "-$") ;remove the last "-" character at the end of the string
}
}
LV_Modify(FocusedRow, "Col" a_index, TempText)
}
}
LV_Modify(0, "-Select") ;Deselect all rows
LV_Modify(FocusedRow, "Focus Select Vis")
;"vis", Ensures that the specified row is completely visible by scrolling the ListView, if necessary.
;"Vis", has an effect only for "LV_Modify()" function! (does not work with "LV_Add()" function!)
;"Focus", Sets keyboard focus to the row / "Select", highlight the row
LVAddEditRowGuiClose: ;_______ LVAddEditRow Gui Close _______
LVAddEditRowGuiEscape:
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
GuiControl, Focus, % A_DefaultListView ;"A_DefaultListView" supported from [v1.1.23+]
if (Options["GoSub"] != "") ;if not blank/empty
GoSub, % Options["GoSub"] ;"GoTo" is not allowed inside functions, only "GoSub" is!
TempText := "", ControlHwndId := [], CtrlType := [], CtrlHwnd := [], Options := [] ;make variable blank (free memory)
gui, LVAddEditRow:Destroy ;by destroying the gui window, "a_guicontrol" will be made blank\empty!
return
}
Code: Select all
;uncomment the "Local" line inside "LV_AddEditRow" function if you use AutoHotKey v1.1.27+
;Force all variables in the function to be "Local" vars (with no exceptions)
;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
;the function was tested in AutoHotKey 1.1.23.05
Count := 1
LVOptions := [] ;declare the variable as an object
LVOptions["RowOptions"] := "Check"
;just for testing, which means that, every modified row will have its correspondent checkbox checked!
;All the row options from the listview built-in functions can be used here!
LVOptions["NewRowIndex"] := 3
;every newly inserted row will be placed at row position 3
;if LVOptions["NewRowIndex"] is not defined (blank\empty), every newly inserted row will be placed at the bottom of the listview control
;(The above lines are valid only if the listview control does not contain "Sort" or "SortDesc" options)
LVOptions["NewRowOptions"] := "Check"
;just for testing, which means that, every newly inserted row will have its correspondent checkbox checked!
;All the row options from the listview built-in functions can be used here!
;All gui control built-in options can be used below
loop, 2
LVOptions["Cell" a_index "Options"] := "w300 cRed"
LVOptions["Cell1Hwnd"] := "Cell1" ;Use 'LV_AddEditRow("CtrlHwnd", "Cell1", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["Cell2Options"] .= " r3" ;adding an extra option to cell2 (the leading "space" character is necessary!)
LVOptions["Cell2Hwnd"] := "C2" ;Use 'LV_AddEditRow("CtrlHwnd", "C2", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["Cell4Options"] := "w150 cGreen"
LVOptions["Cell4Hwnd"] := "4" ;Use 'LV_AddEditRow("CtrlHwnd", "4", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["Cell3Type"] := "Checkbox"
LVOptions["Cell3Text"] := "Just Test (Check/Uncheck)"
LVOptions["Cell3Hwnd"] := "Check" ;Use 'LV_AddEditRow("CtrlHwnd", "Check", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["Cell5HeaderOptions"] := "Section cPurple"
LVOptions["Cell5Type"] := "ListBox"
LVOptions["Cell5Options"] := "multi h160"
LVOptions["Cell5Text"] := " lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White ||"
LVOptions["Cell6HeaderOptions"] := "x+5 ys cBlue"
LVOptions["Cell6Type"] := "ListBox"
LVOptions["Cell6Options"] := "h160"
LVOptions["Cell6Text"] := " lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White ||"
LVOptions["Cell7HeaderOptions"] := "x+5 ys cAqua"
LVOptions["Cell7Type"] := "DropDownList"
LVOptions["Cell7Text"] := " lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White ||"
LVOptions["Cell8HeaderOptions"] := "cOlive"
LVOptions["Cell8Type"] := "DDL"
LVOptions["Cell8Text"] := " lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White ||"
LVOptions["Cell9HeaderOptions"] := "cMaroon section"
LVOptions["Cell9Type"] := "ComboBox"
LVOptions["Cell9Text"] := " lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White ||"
;___
LVOptions["BeforeCell10Ctrl1Type"] := "Button"
LVOptions["BeforeCell10Ctrl1Options"] := "w100 ym gAction"
LVOptions["BeforeCell10Ctrl1Text"] := "Before Test 1 (Action)"
LVOptions["BeforeCell10Ctrl1Hwnd"] := "BC10C1" ;Use 'LV_AddEditRow("CtrlHwnd", "BC10C1", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["BeforeCell10Ctrl2Type"] := "Button"
LVOptions["BeforeCell10Ctrl2Options"] := "w125"
LVOptions["BeforeCell10Ctrl2Text"] := "Before Test 2"
LVOptions["BeforeCell10Ctrl2Hwnd"] := "Button2" ;Use 'LV_AddEditRow("CtrlHwnd", "Button2", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["BeforeCell10Ctrl3Type"] := "Button"
LVOptions["BeforeCell10Ctrl3Options"] := "w150"
LVOptions["BeforeCell10Ctrl3Text"] := "Before Test 3"
LVOptions["BeforeCell10Ctrl3Hwnd"] := "B3" ;Use 'LV_AddEditRow("CtrlHwnd", "B3", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["Cell10HeaderOptions"] := "cRed"
LVOptions["Cell10Type"] := "DateTime"
LVOptions["Cell10Options"] := "2" ;"2" checkbox inside the control
LVOptions["Cell10Text"] := "LongDate"
;___
LVOptions["Cell11Type"] := "DateTime"
LVOptions["Cell11Options"] := "2 ChooseNone" ;"2" checkbox inside the control, "None" checkbox unchecked
LVOptions["Cell11Text"] := "Time"
;___
LVOptions["Cell12Type"] := "DateTime"
LVOptions["Cell12Options"] := "2 ChooseNone" ;"2" checkbox inside the control, "None" checkbox unchecked
LVOptions["Cell12Text"] := "yyyy-MM-dd/HH:mm:ss" ;"HH" 24-hour format (00 – 23)
LVOptions["AfterCell12Ctrl1Type"] := "Button"
LVOptions["AfterCell12Ctrl1Options"] := "w100 gAction"
LVOptions["AfterCell12Ctrl1Text"] := " After Test 1 (Action) "
LVOptions["AfterCell12Ctrl1Hwnd"] := "AC12C1" ;Use 'LV_AddEditRow("CtrlHwnd", "AC12C1", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell12Ctrl2Type"] := "Button"
LVOptions["AfterCell12Ctrl2Options"] := "w125"
LVOptions["AfterCell12Ctrl2Text"] := "After Test 2"
LVOptions["AfterCell12Ctrl2Hwnd"] := "AButton2" ;Use 'LV_AddEditRow("CtrlHwnd", "AButton2", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell12Ctrl3Type"] := "Button"
LVOptions["AfterCell12Ctrl3Options"] := "w150"
LVOptions["AfterCell12Ctrl3Text"] := "After Test 3"
LVOptions["AfterCell12Ctrl3Hwnd"] := "A3" ;Use 'LV_AddEditRow("CtrlHwnd", "A3", "GetObject")' to get the control Hwnd id in case you need it later!
;___
LVOptions["BeforeCell13Ctrl1Type"] := "Button"
LVOptions["BeforeCell13Ctrl1Options"] := "w150 ym"
LVOptions["BeforeCell13Ctrl1Text"] := "Before Test 4"
LVOptions["BeforeCell13Ctrl2Type"] := "Button"
LVOptions["BeforeCell13Ctrl2Options"] := "w125"
LVOptions["BeforeCell13Ctrl2Text"] := "Before Test 5"
LVOptions["BeforeCell13Ctrl3Type"] := "Button"
LVOptions["BeforeCell13Ctrl3Options"] := "w100"
LVOptions["BeforeCell13Ctrl3Text"] := "Before Test 6"
LVOptions["Cell13HeaderOptions"] := "cRed"
LVOptions["Cell13Type"] := "MonthCal"
LVOptions["Cell13Text"] := "20050525-20050531"
LVOptions["AfterCell13Ctrl1Type"] := "Button"
LVOptions["AfterCell13Ctrl1Options"] := "w150"
LVOptions["AfterCell13Ctrl1Text"] := "After Test 4"
LVOptions["AfterCell13Ctrl2Type"] := "Button"
LVOptions["AfterCell13Ctrl2Options"] := "w125"
LVOptions["AfterCell13Ctrl2Text"] := "After Test 5"
LVOptions["AfterCell13Ctrl3Type"] := "Button"
LVOptions["AfterCell13Ctrl3Options"] := "w100"
LVOptions["AfterCell13Ctrl3Text"] := "After Test 6"
;___
LVOptions["BeforeCell14Ctrl1Type"] := "text"
LVOptions["BeforeCell14Ctrl1Options"] := "xs section"
LVOptions["BeforeCell14Ctrl1Text"] := "Less"
LVOptions["Cell14HeaderOptions"] := "x+50 y+-32"
LVOptions["Cell14Type"] := "slider"
LVOptions["Cell14Options"] := "x+-70 ys h25 ToolTip gUpdateSliderStatus"
LVOptions["Cell14Text"] := "25"
LVOptions["Cell14Hwnd"] := "Slider" ;Use 'LV_AddEditRow("CtrlHwnd", "Slider", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell14Ctrl1Type"] := "Edit"
LVOptions["AfterCell14Ctrl1Options"] := "xp+35 y+-0 w50 center +border gUpdateSlider"
LVOptions["AfterCell14Ctrl1Text"] := ""
LVOptions["AfterCell14Ctrl1Hwnd"] := "SliderStatus" ;Use 'LV_AddEditRow("CtrlHwnd", "SliderStatus", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell14Ctrl2Type"] := "text"
LVOptions["AfterCell14Ctrl2Options"] := "x+35 ys"
LVOptions["AfterCell14Ctrl2Text"] := "More"
;The label "UpdateSliderStatus" must be executed everytime "LVAddEdidRow" gui window is created in order to update the "sliderStatus" control!
;see "gosub, UpdateSliderStatus" examples below!
;___
LVOptions["Cell15HeaderOptions"] := "x+10 y+-32"
LVOptions["Cell15Type"] := "Hotkey"
LVOptions["Cell15Text"] := "^!a"
LVOptions["AfterCell15Ctrl1Type"] := "text"
LVOptions["AfterCell15Ctrl1Options"] := "x+5"
LVOptions["AfterCell15Ctrl1Text"] := ":HotKey"
;___
LVOptions["Cell16HeaderOptions"] := "x+20 section"
LVOptions["Cell16Options"] := "w70 ReadOnly" ;"ReadOnly" is recommended in order to prevent wrong results
LVOptions["AfterCell16Ctrl1Type"] := "UpDown" ;"Cell16" control above is automatically made the Buddy of this control
LVOptions["AfterCell16Ctrl1Options"] := "Range0-2000"
LVOptions["AfterCell16Ctrl1Text"] := "1500"
;___
LVOptions["Cell17HeaderOptions"] := "ys"
LVOptions["Cell17Type"] := "UpDown" ;in this example, "Cell17" will be an "UpDown" control itself!
LVOptions["Cell17Options"] := "h20 -16 gUpdateUpDownBuddy" ;"-16" prevents "UpDown" control to treat the "Cell17Header" control as its "Buddy" control!
LVOptions["Cell17Text"] := "89"
LVOptions["Cell17Hwnd"] := "UpDown" ;Use 'LV_AddEditRow("CtrlHwnd", "UpDown", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell17Ctrl1Type"] := "Edit"
LVOptions["AfterCell17Ctrl1Options"] := "x+0 w50 gUpdateUpDown"
LVOptions["AfterCell17Ctrl1Hwnd"] := "UpDownBuddy" ;Use 'LV_AddEditRow("CtrlHwnd", "UpDownBuddy", "GetObject")' to get the control Hwnd id in case you need it later!
;The label "UpdateUpDownBuddy" must be executed everytime "LVAddEdidRow" gui window is created in order to update the "UpDownBuddy" control!
;see "gosub, UpdateUpDownBuddy" examples below!
;___
LVOptions["Cell18HeaderOptions"] := "ys"
LVOptions["Cell18Type"] := "DDL"
LVOptions["Cell18Options"] := "w50"
LVOptions["Cell18Text"] := "A|B|C|D|E||F|G"
LVOptions["Cell18Hwnd"] := "DDLUPDown" ;Use 'LV_AddEditRow("CtrlHwnd", "DDLUPDown", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell18Ctrl1Type"] := "Button"
LVOptions["AfterCell18Ctrl1Options"] := "x+0 w20 h11 gCustomUPDown"
LVOptions["AfterCell18Ctrl1Text"] := "▴"
LVOptions["AfterCell18Ctrl2Type"] := "Button"
LVOptions["AfterCell18Ctrl2Options"] := "y+-1 w20 h11 gCustomUPDown"
LVOptions["AfterCell18Ctrl2Text"] := "▾"
;___
LVOptions["Cell19HeaderOptions"] := "xm section"
LVOptions["Cell19Options"] := "w400"
LVOptions["Cell19Hwnd"] := "FileBox" ;Use 'LV_AddEditRow("CtrlHwnd", "FileBox", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell19Ctrl1Type"] := "Button"
LVOptions["AfterCell19Ctrl1Text"] := "Browse"
LVOptions["AfterCell19Ctrl1Options"] := "x+0 gBrowse"
;___
LVOptions["Cell20HeaderOptions"] := "ys"
LVOptions["Cell20Options"] := "ReadOnly"
LVOptions["Cell20Hwnd"] := "IconBox" ;Use 'LV_AddEditRow("CtrlHwnd", "IconBox", "GetObject")' to get the control Hwnd id in case you need it later!
LVOptions["AfterCell20Ctrl1Type"] := "Button"
LVOptions["AfterCell20Ctrl1Options"] := "x+0 gChooseIcon"
LVOptions["AfterCell20Ctrl1Text"] := "Choose Icon"
;___
;___
;___
;___
LVOptions["GoSub"] := "ExtraTasks"
;Do extra tasks after Adding\Modifying\Deleting\etc rows!
;"Goto" inside functions is not allowed, so "GoSub" is used instead!
;___
ImageListID := IL_Create(10) ; Create an ImageList to hold 10 small icons.
Loop 10
IL_Add(ImageListID, "shell32.dll", A_Index) ; Load the ImageList with a series of icons from the DLL.
loop, 3
{
gui, %a_index%:default
loop, 3
{
TableHead := "ID" Count++ "|A" Count++ "|B" Count++ "|C" Count++ "|D" Count++ "|E" Count++ "|F" Count++ "|G" Count++ "|H" Count++ "|I" Count++ "|J" Count++ "|K" Count++ "|L" Count++ "|M" Count++ "|N" Count++ "|O" Count++ "|P" Count++ "|Q" Count++ "|R" Count++ "|S" Count++
gui, add, listview, h135 AltSubmit checked BackgroundWhite vMyTable%a_index% gTablesEvents +HwndMyTableId%a_index% Grid, % TableHead
;"AltSubmit" allows detection of mouse "1 left click" or "1 right click" and others "gui events"
;"ID|A|B|C" inicial columns
;"Normal = 1 left click"
;"RightClick = 1 right click"
;"Grid" Provides horizontal and vertical lines to visually indicate the boundaries between rows and columns.
;"BackgroundWhite" Background color is White
;"+HwndMyTableId%a_index%", stores the control Hwnd id number in "MyTableId%a_index%" variable
LV_SetImageList(ImageListID) ; Assign the above ImageList to the current ListView.
loop, 20
LV_ModifyCol(a_index, 55) ;columns change columns width
loop, 4
LV_Add("Icon2", a_index, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++, Count++)
;add 3 rows / "a_index" add number to first fields (for "ID" Column)
}
gui, add, button, gAdd, Add
gui, add, button, x+5 gModify, Modify
if (a_index = 1)
pos := "x" A_ScreenWidth/2 - 370
else if (a_index = 2)
pos := "x" A_ScreenWidth/2 - 100
else
pos := "x" A_ScreenWidth/2 + 170
gui, show, % pos, % "Gui " A_index
}
return
TablesEvents: ;_____________________ ListView controls Events ___________________
if (A_GuiEvent = "F") ;"F", The ListView has received keyboard focus (ListView control must contain "AltSubmit" word in its options)
Gui, ListView, % A_GuiControl ;change the default listview control of the gui windows that the focused control belongs
if (A_GuiEvent = "DoubleClick")
{
LV_AddEditRow(A_Gui, A_GuiControl, "Modify", LVOptions)
gosub, UpdateUpDownBuddy
gosub, UpdateSliderStatus
gosub, ShowWindowHandle
}
return
Add: ;__________________ Add Buttons ________________
LV_AddEditRow(A_Gui, "", "Add", LVOptions)
;a new row will be added to the last focused listview control from the Gui window that started the thread
;keep track of the last focused listview controls through listview G-Label Notifications (see "TablesEvents:" label above)
gosub, UpdateUpDownBuddy
gosub, UpdateSliderStatus
gosub, ShowWindowHandle
return
Modify: ;__________________ Modify Buttons ___________
LV_AddEditRow(A_Gui, "", "Modify", LVOptions)
;the focused row will be modified from the last focused listview control of the Gui window that started the thread
;keep track of the last focused listview controls through listview G-Label Notifications (see "TablesEvents:" label above)
gosub, UpdateUpDownBuddy
gosub, UpdateSliderStatus
gosub, ShowWindowHandle
return
ShowWindowHandle: ;___________ Show Window Handle _________
ToolTipText:= ""
. "Gui Window 'LVAddEditRow' Hwnd = " LV_AddEditRow("", "GuiHwnd", "GetVar") "`n`n"
. "'LVAddEditRow' is the internal name in AHK" "`n`n"
. "Hold 'F12' or 'F11' to flash the window!" "`n`n"
CoordMode, ToolTip, Screen
ToolTip, % ToolTipText, 0, 0
return
f12:: ;_____________ F12 - Flash Window ______________
Gui, % LV_AddEditRow("", "GuiHwnd", "GetVar") ":Flash"
return
f11:: ;_____________ F11 - Flash Window ______________
Gui, LVAddEditRow:Flash
return
ExtraTasks: ;__________________ Extra Tasks ________________
ToolTipText := ""
. "a_gui = " a_gui "`n"
. "a_guicontrol = " a_guicontrol "`n"
. "`n"
. "A_DefaultGui = " A_DefaultGui "`n"
. "A_DefaultListView = " A_DefaultListView "`n"
. "`n"
. "Static Vars values from the function: `n"
. "Gui Window = " LV_AddEditRow("", "GuiWindow", "GetVar") "`n"
. "LV Control = " LV_AddEditRow("", "LVControl", "GetVar") "`n"
. "Focused Row = " LV_AddEditRow("", "FocusedRow", "GetVar") "`n"
CoordMode, ToolTip, Screen
ToolTip, % ToolTipText, 0, 0
if (LV_AddEditRow("", "FocusedRow", "GetVar") > 0)
{
LV_GetText(RowIcon, LV_AddEditRow("", "FocusedRow", "GetVar"), 20)
RowIcon := RegExMatch(RowIcon, "^Icon\d+$") ? RowIcon : ""
LV_Modify(LV_AddEditRow("", "FocusedRow", "GetVar"), "col4 " RowIcon, "@" count++ "@")
;just for test
}
return
Action: ;__________________ Action __________________
ControlSetText, , Action TripleX, % "ahk_id" LV_AddEditRow("CtrlHwnd", "Cell1", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "C2", "GetObject"), Action xXx
ControlSetText, , Bang, % "ahk_id" LV_AddEditRow("CtrlHwnd", "BC10C1", "GetObject")
ControlSetText, , Bang 2, % "ahk_id" LV_AddEditRow("CtrlHwnd", "Button2", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "B3", "GetObject"), Bang 3
ControlSetText, , Skrr, % "ahk_id" LV_AddEditRow("CtrlHwnd", "AC12C1", "GetObject")
ControlSetText, , Skrr 2, % "ahk_id" LV_AddEditRow("CtrlHwnd", "AButton2", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "A3", "GetObject"), Skrr 3
return
UpdateSlider: ;_____________________ Update Slider _____________________
GuiControlGet, TempValue, , % LV_AddEditRow("CtrlHwnd", "SliderStatus", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "Slider", "GetObject"), % TempValue
return
UpdateSliderStatus: ;_____________________ Update Slider Status _____________________
GuiControlGet, TempValue, , % LV_AddEditRow("CtrlHwnd", "Slider", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "SliderStatus", "GetObject"), % TempValue
return
UpdateUpDown: ;____________________ Update UpDown ___________________
GuiControlGet, TempValue, , % LV_AddEditRow("CtrlHwnd", "UpDownBuddy", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "UpDown", "GetObject"), % TempValue
return
UpdateUpDownBuddy: ;____________________ Update UpDown Buddy _______________________
GuiControlGet, TempValue, , % LV_AddEditRow("CtrlHwnd", "UpDown", "GetObject")
guicontrol, , % LV_AddEditRow("CtrlHwnd", "UpDownBuddy", "GetObject"), % TempValue
return
CustomUPDown: ;__________________ Custom UPDown _______________
;"==" is always case-sensitive
if (a_guicontrol == "▴")
ControlSend , , {Up}, % "ahk_id" LV_AddEditRow("CtrlHwnd", "DDLUpDown", "GetObject")
if (a_guicontrol == "▾")
ControlSend , , {Down}, % "ahk_id" LV_AddEditRow("CtrlHwnd", "DDLUpDown", "GetObject")
return
Browse: ;__________________ Browse __________________
Gui, +OwnDialogs ;must close "FileSelectFile" window below in order to use gui window again!
FileSelectFile, SelectedFile
guicontrol, , % LV_AddEditRow("CtrlHwnd", "FileBox", "GetObject"), % SelectedFile
return
ChooseIcon: ;__________________ Choose Icon ______________
gui, Icon:Default
gui, destroy
Gui, %a_gui%: +Disabled ;disable "LVAddEditRow" Gui (in this case, "a_gui = LVAddEditRow")
gui, +owner%a_gui% ;make "LVAddEditRow" Gui the owner of "Icon" Gui (in this case, "a_gui = LVAddEditRow")
Gui, Add, ListView, h200 w180 0x40, Icon ;"0x40" prevents the created ImageList above to be destroyed when this listview control is destroyed!
LV_SetImageList(ImageListID) ; Assign the above ImageList to the current ListView.
Loop 10
LV_Add("Icon" . A_Index, "Icon" A_Index) ; Add rows to the ListView (for demonstration purposes, one for each icon).
LV_ModifyCol("Hdr") ; Auto-adjust the column widths.
gui, add, button, gOkChooseIcon, Ok
gui, show, , Choose Icon
return
OkChooseIcon: ;____
LV_GetText(UserIcon, LV_GetNext(0, "Focused") , 1)
guicontrol, LVAddEditRow: , % LV_AddEditRow("CtrlHwnd", "IconBox", "GetObject"), % UserIcon
IconGuiClose: ;____
gui, LVAddEditRow: -Disabled
gui, destroy
return
guiclose: ;__________________ Gui Close _______________
2guiclose:
3guiclose:
exitapp
LV_AddEditRow(GuiWnd, LVCtrl, Status, Optns := "") ;_______________ Add/Edit ListView Controls Rows - v1.0 (Function) ___________________
{
;Local ;uncomment this line if you use AutoHotKey v1.1.27+
;Force all variables in this function to be "Local" vars (with no exceptions)
;"Force-local" mode (only supported on AutoHotKey v1.1.27+)
;this function was tested in AutoHotKey 1.1.23.05
;Local TempControlId ;this line was disabled because otherwise it would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)
Static ControlHwndId := [], CtrlType := [], CtrlHwnd := [] ;declare the variable as an object and remember its values between function calls
Static GuiWindow, LVControl, FocusedRow, TotalCols, Options, GuiHwnd ;"Static" variables, remember values between function calls
if (Status = "GetVar")
return, (%LVCtrl%) ;return the values of static variables from this function
if (Status = "GetObject") ;return the values of static Objects from this function
return, %GuiWnd%[LVCtrl]
GuiWindow := GuiWnd
LVControl := LVCtrl
Options := Optns.Clone()
;"Clone()", Returns a shallow (not always a 100% clone???) copy of the object.
;"Clone()" creates a new object from the object referenced by "Optns" variable!
;then, "Options" variable will reference that newly created/cloned object!
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
FocusedRow := LV_GetNext(0, "Focused")
;Search for the focused row ("0", the search starts from row number 1!
;there is never more than one focused row in the entire list, and sometimes there is none at all!
if (Status = "Modify" and FocusedRow = 0)
{
msgbox, 8240, Warning!, No row is selected! Please, select a row to be modified!
;"8240" sum of 8192 and 48 (8192 for "Task Modal" option \ 48 for Icon Exclamation + sound)
;"52" sum of 4 and 48 (4 for "yes - no" options \ 48 for Icon Exclamation + sound)
gui, LVAddEditRow:Destroy
return
}
TotalCols := LV_GetCount("Col") ;the function returns the number of columns in the control
gui, LVAddEditRow:Default
gui, destroy
Gui +HwndGuiHwnd
loop, % TotalCols
{
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
LV_GetText(TempHeader, 0, a_index) ;"0" is the columns header row / "a_index" is the column number
if (Status = "Modify")
LV_GetText(TempText, FocusedRow, a_index) ;"a_index" is the column number
gui, LVAddEditRow:Default
TempIndex := a_index
loop
{
if (Options["BeforeCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
gui, add, % Options["BeforeCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["BeforeCell" TempIndex "Ctrl" a_index "Options"], % Options["BeforeCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["BeforeCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
gui, add, text, % Options["Cell" a_index "HeaderOptions"], % TempHeader
;Ternary operator, ( ? = if ) and ( : = else )
ControlType := ControlOption := ControlText := "" ;blank\empty values
ControlType := CtrlType[a_index] := Options["Cell" a_index "Type"] != "" ? Options["Cell" a_index "Type"] : "Edit"
if (ControlType = "Checkbox")
{
ControlOption := Status = "Add" ? "" : "Checked" TempText
}
else if (ControlType = "DateTime")
{
TempText := TempText = "" ? "None" : RegExReplace(TempText, "\D") ;"\D" means any non-digit (remove any non-digit characters)
ControlOption := Status = "Add" ? "" : "Choose" TempText
}
else if (ControlType = "ListBox" or ControlType = "DropDownList" or ControlType = "DDL")
{
if (Status = "Modify")
{
TempIndex := a_index
TempList := Options["Cell" TempIndex "Text"], Options["Cell" TempIndex "Text"] := ""
loop, parse, TempList, |
{
if (A_LoopField == "") ;if blank\empty (== is case-sensitive)
continue ;Skips the rest of the current loop iteration and begins a new one. Valid inside any kind of loop.
TempString := A_LoopField
loop, parse, TempText, |
{
if ("S" TempString == "S" A_LoopField) ;"==" is case-sensitive, "S" forces "string" comprisons and avoids "number" comparisons!
{
TempString .= "|"
break
}
}
Options["Cell" TempIndex "Text"] .= TempString "|"
}
}
}
else if (ControlType != "Edit" and ControlType != "ComboBox")
{
if (ControlType = "MonthCal")
TempText := RegExReplace(TempText, "\Q/") ;remove any "/" character
if (Status = "Modify")
ControlText := TempText, Options["Cell" a_index "Text"] := ""
}
gui, add, % ControlType, % "+HwndTempControlId " Options["Cell" a_index "Options"] " " ControlOption, % Options["Cell" a_index "Text"] ControlText
if (Status = "Modify")
{
if (ControlType = "Edit" or ControlType = "ComboBox")
ControlSetText, , % TempText, % "ahk_id" TempControlId ;"ControlSetText" prevents "EOL" (End of LIne Translation), no "`n" is translated to "`r`n"
}
ControlHwndId[a_index] := TempControlId ;the variable must be declared as an object first ("ControlHwndId := []")
TempKey := Options["Cell" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
TempIndex := a_index
loop
{
if (Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "")
break
else
{
if (a_index = "1" and Status = "Modify" and Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "UpDown")
Options["AfterCell" TempIndex "Ctrl" a_index "Text"] := RegExReplace(TempText, "\.|,") ;Regex removes thousands separator (. or ,)
gui, add, % Options["AfterCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["AfterCell" TempIndex "Ctrl" a_index "Options"], % Options["AfterCell" TempIndex "Ctrl" a_index "Text"]
TempKey := Options["AfterCell" TempIndex "Ctrl" a_index "Hwnd"]
CtrlHwnd[TempKey] := TempControlId
}
}
}
TempText := "" ;make variable blank (free memory)
if (Status = "Modify")
GuiCaption := ButtonCaption := "Modify"
else
GuiCaption := ButtonCaption := "Add"
gui, add, button, xm gLVAddEditRowLabel Default, % ButtonCaption
if (Status = "Modify")
{
gui, add, button, x+5 gLVAddEditRowLabel , Add
gui, add, button, x+5 gLVAddEditRowLabel , Delete
}
gui, add, button, x+5 gLVAddEditRowGuiClose, Cancel
gui, show, , % GuiCaption
return
LVAddEditRowLabel: ;_________ Function Label __________
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
if (a_guicontrol = "Delete")
{
LV_Delete(FocusedRow)
FocusedRow := LV_GetNext(0, "Focused") ;Search for the focused row ("0", the search starts from row number 1!
}
if (a_guicontrol = "Add" or a_guicontrol = "Modify")
{
if (a_guicontrol = "Add")
{
FocusedRow := LV_Insert(Options["NewRowIndex"] = "" ? LV_GetCount() + 1 : Options["NewRowIndex"], Options["NewRowOptions"])
;The function adds a new row to the specified index position (if the ListView control does not have the "Sort" or "SortDesc" style)
;The function returns the new row number, which is not necessarily the specified index position if the ListView has the "Sort" or "SortDesc" style.
;Ternary operator, (? = if) and (: = else)
;if Options["NewRowIndex"] is blank\empty, the new row will be inserted to the end of the listview control, "LV_GetCount() + 1"
;for some reason, the Options["NewRowOptions"] prevents Autohotkey from crashing if Options["NewRowIndex"] is blank/empty and the ListView control contains "Sort" or "SortDesc" options
}
if (a_guicontrol = "Modify")
{
LV_Modify(FocusedRow, Options["RowOptions"])
}
loop, % TotalCols
{
if (CtrlType[a_index] = "Edit" or CtrlType[a_index] = "ComboBox")
ControlGetText, TempText, , % "ahk_id" ControlHwndId[a_index] ;"ControlGetText" prevents EOL "End of line translation", no "`r`n" is translated to "`n"
else
GuiControlGet, TempText, LVAddEditRow:, % ControlHwndId[a_index]
if (CtrlType[a_index] = "DateTime")
{
if (TempText != "")
FormatTime, TempText, % TempText, yyyy-MM-dd/HH:mm:ss ;"HH" 24-hour format (00 – 23)
}
else if (CtrlType[a_index] = "MonthCal")
{
if (TempText != "")
{
Loop, Parse, TempText, -
{
TempText := a_index = 1 ? "" : TempText
FormatTime, TempTime, % A_LoopField, yyyy/MM/dd ;"MonthCal" does not retrieve "HH24MISS" time portion , retrieves only "YYYYMMDD" Date
TempText .= TempTime "-"
}
TempText := RegExReplace(TempText, "-$") ;remove the last "-" character at the end of the string
}
}
LV_Modify(FocusedRow, "Col" a_index, TempText)
}
}
LV_Modify(0, "-Select") ;Deselect all rows
LV_Modify(FocusedRow, "Focus Select Vis")
;"vis", Ensures that the specified row is completely visible by scrolling the ListView, if necessary.
;"Vis", has an effect only for "LV_Modify()" function! (does not work with "LV_Add()" function!)
;"Focus", Sets keyboard focus to the row / "Select", highlight the row
LVAddEditRowGuiClose: ;_______ LVAddEditRow Gui Close _______
LVAddEditRowGuiEscape:
Gui, %GuiWindow%:Default ;forces Built-in ListView Functions to operate upon the indicated gui window
Gui, ListView, % LVControl ;forces built-in ListView functions to operate upon the indicated Listview Control (the control must belong to the indicated gui window above)
GuiControl, Focus, % A_DefaultListView ;"A_DefaultListView" supported from [v1.1.23+]
if (Options["GoSub"] != "") ;if not blank/empty
GoSub, % Options["GoSub"] ;"GoTo" is not allowed inside functions, only "GoSub" is!
TempText := "", ControlHwndId := [], CtrlType := [], CtrlHwnd := [], Options := [] ;make variable blank (free memory)
gui, LVAddEditRow:Destroy ;by destroying the gui window, "a_guicontrol" will be made blank\empty!
return
}