[Function] LV_AddEditRow - Add\Edit ListView control rows!

Post your working scripts, libraries and tools for AHK v1.1 and older
User
Posts: 407
Joined: 26 Jun 2017, 08:12

[Function] LV_AddEditRow - Add\Edit ListView control rows!

02 Sep 2018, 00:45

Hi,

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
}
Basic - 2 Listview controls

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
}
Objects Test

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
}
A more extensive but yet simple Example

Image
LV_AddEditRow (Function).gif
(1.94 MiB) Not downloaded yet

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
}
Last edited by User on 17 Dec 2018, 21:04, edited 2 times in total.
User avatar
NovaRanger
Posts: 68
Joined: 23 Oct 2014, 02:05

Re: [Function] LV_AddEditRow - Add\Edit ListView control rows!

13 Sep 2018, 08:47

Thanks bro,
I was looking for something like this..
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] LV_AddEditRow - Add\Edit ListView control rows!

13 Sep 2018, 12:26

NovaRanger wrote:Thanks bro,
I was looking for something like this..
You welcome!
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] LV_AddEditRow - Add\Edit ListView control rows!

05 Oct 2018, 00:55

(v1.1)

Fixed an issue with AfterCellxCtrl1 "UpDown" controls!

AfterCellxCtrl1 "UpDown" controls will use "TempText" values only if the "UpDown" controls have "0x10" and "0x2" styles!

0x10 - means that the "UpDown" control makes the previous control its "buddy" control!
0x2 - means that the "UpDown" control can set\modify text from its "buddy" control!


(Example) "UpDown" control with option to change "Increment" value:
48_ zz_ Increment.gif
48_ zz_ Increment.gif (935.77 KiB) Viewed 2450 times


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["Cell21HeaderOptions"] := "ys"
LVOptions["Cell21Options"] := "w75 gLoneUpDown"
LVOptions["Cell21Text"] := 4
LVOptions["Cell21Hwnd"] := "LoneUpDownEditId"		;Use 'LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")' to get the control Hwnd id in case you need it later!

LVOptions["AfterCell21Ctrl1Type"] := "UpDown"
LVOptions["AfterCell21Ctrl1Options"] := "Range-1-1 gLoneUpDown -0x2"	;"-0x2", prevents the UpDown control to set the text of the buddy "Edit" control
LVOptions["AfterCell21Ctrl1Text"] := "0"				;must be\start as "0" (zero) / Range must be "-1 to 1"
LVOptions["AfterCell21Ctrl1Hwnd"] := "LoneUpDownId"			;Use 'LV_AddEditRow("CtrlHwnd", "LoneUpDownId", "GetObject")' to get the control Hwnd id in case you need it later!

LVOptions["AfterCell21Ctrl2Type"] := "text"
LVOptions["AfterCell21Ctrl2Options"] := "x+0"
LVOptions["AfterCell21Ctrl2Text"] := "+"

LVOptions["AfterCell21Ctrl3Type"] := "edit"
LVOptions["AfterCell21Ctrl3Options"] := "x+0 w25 center"
LVOptions["AfterCell21Ctrl3Text"] := "2"
LVOptions["AfterCell21Ctrl3Hwnd"] := "Increment"	;Use 'LV_AddEditRow("CtrlHwnd", "Increment", "GetObject")' to get the control Hwnd id in case you need it later!

;___

;___

;___

;___

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++ "|T" 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, 21
	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++, 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

LoneUpDown:	;__________________ LoneUpDown _________________

GuiControlGet, Increment, , % LV_AddEditRow("CtrlHwnd", "Increment", "GetObject")
GuiControlGet, LoneUpDownEdit, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")

GuiControlGet, LoneUpDown, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownId", "GetObject")		;check if "UpDown" control value is "-1", "0" or "1"
GuiControl, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownId", "GetObject"), 0			;set the "UpDown" control to "0" (zero)

	;msgbox, % LoneUpDown

if (LoneUpDown = 1)
LoneUpDownEdit := LoneUpDownEdit + Increment
else if (LoneUpDown = -1)
LoneUpDownEdit := LoneUpDownEdit - Increment

if LoneUpDownEdit is Number
LoneUpDownEdit := LoneUpDownEdit < -50 ? -50 : LoneUpDownEdit > 100 ? 100 : LoneUpDownEdit
else
LoneUpDownEdit := LoneUpDownEdit = "" ? "" : LoneUpDownEdit = "-" ? "-" : 0

GuiControl, -g, % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")
GuiControl, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject"), % LoneUpDownEdit
ControlSend, , {End}, % "ahk_id" LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")
GuiControl, +gLoneUpDown, % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")

	;tooltip, % count++ 

return

guiclose:	;__________________ Gui Close _______________
2guiclose:
3guiclose:
exitapp


LV_AddEditRow(GuiWnd, LVCtrl, Status, Optns := "")	;_______________ Add/Edit ListView Controls Rows - v1.1 (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
			{
			gui, add, % Options["AfterCell" TempIndex "Ctrl" a_index "Type"], % "+HwndTempControlId " Options["AfterCell" TempIndex "Ctrl" a_index "Options"], % Options["AfterCell" TempIndex "Ctrl" a_index "Text"]

				if (a_index = "1" and Status = "Modify" and Options["AfterCell" TempIndex "Ctrl" a_index "Type"] = "UpDown")
				{
				ControlGet, TempStyle, Style, , , % "ahk_id" TempControlId

					;0x10 = 16 (means that the "UpDown" control treats the previous control as its buddy control)
					;0x2 = 2 (means that the "UpDown" control can set\modify text of its buddy control)

					;https://autohotkey.com/docs/commands/WinGet.htm#Style
					;https://autohotkey.com/docs/misc/Styles.htm#UpDown

				if (TempStyle & 0x10) and (TempStyle & 0x2)				;if style "0x10" and "0x2" are found in "TempStyle" variable
				guicontrol, , % TempControlId , % RegExReplace(TempText, "\.|,")	;Regex removes thousands separator (. or ,)
				}

			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
}
User
Posts: 407
Joined: 26 Jun 2017, 08:12

Re: [Function] LV_AddEditRow - Add\Edit ListView control rows!

17 Dec 2018, 20:47

(v2.0)

V2 uses SimpleObject "o()" function instead AHK Built-in Object!

v2.png
v2.png (45.12 KiB) Viewed 2445 times

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

o(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!

o(LVOptions, "NewRowIndex", , "=", 3)
;every newly inserted row will be placed at row position 3
;if o(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)

o(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
o(LVOptions, "Options", "Col_" a_index, "=", "w300 cRed")

o(LVOptions, "Hwnd", "Col_1", "=", "Cell1")	;Use 'LV_AddEditRow("CtrlHwnd", "Cell1", "GetObject")' to get the control Hwnd id in case you need it later! 

o(LVOptions, "Options", "Col_2", "=", o(LVOptions, "Options", "Col_2") " r3")	;adding an extra option to "Col_2" (" r3", the leading "space" character is necessary before "r3" !)
o(LVOptions, "Hwnd", "Col_2", "=", "C2")					;Use 'LV_AddEditRow("CtrlHwnd", "C2", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Options", "Col_4", "=", "w150 cGreen")
o(LVOptions, "Hwnd", "Col_4", "=", "4")			;Use 'LV_AddEditRow("CtrlHwnd", "4", "GetObject")' to get the control Hwnd id in case you need it later!


o(LVOptions, "Type", "Col_3", "=", "Checkbox")
o(LVOptions, "Text", "Col_3", "=", "Just Test (Check/Uncheck)")
o(LVOptions, "Hwnd", "Col_3", "=", "Check")		;Use 'LV_AddEditRow("CtrlHwnd", "Check", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Header_Options", "Col_5", "=", "Section cPurple")
o(LVOptions, "Type", "Col_5", "=", "ListBox")
o(LVOptions, "Options", "Col_5", "=", "multi h160")
o(LVOptions, "Text", "Col_5", "=", "          lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White          ||")

o(LVOptions, "Header_Options", "Col_6", "=", "x+5 ys cBlue")
o(LVOptions, "Type", "Col_6", "=", "ListBox")
o(LVOptions, "Options", "Col_6", "=", "h160")
o(LVOptions, "Text", "Col_6", "=", "          lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White          ||")

o(LVOptions, "Header_Options", "Col_7", "=", "x+5 ys cAqua")
o(LVOptions, "Type", "Col_7", "=", "DropDownList")
o(LVOptions, "Text", "Col_7", "=", "          lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White          ||")

o(LVOptions, "Header_Options", "Col_8", "=", "cOlive")
o(LVOptions, "Type", "Col_8", "=", "DDL")
o(LVOptions, "Text", "Col_8", "=", "          lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White          ||")

o(LVOptions, "Header_Options", "Col_9", "=", "cMaroon section")
o(LVOptions, "Type", "Col_9", "=", "ComboBox")
o(LVOptions, "Text", "Col_9", "=", "          lot||green life|Red|red|green|soft-Green||Green|White life|\E|\e|White          ||")

;___

o(LVOptions, "Ctrl_1_Type_Before",    "Col_10", "=", "Button")
o(LVOptions, "Ctrl_1_Options_Before", "Col_10", "=", "w100 ym gAction")
o(LVOptions, "Ctrl_1_Text_Before",    "Col_10", "=", "Before Test 1 (Action)")
o(LVOptions, "Ctrl_1_Hwnd_Before",    "Col_10", "=", "BC10C1")		;Use 'LV_AddEditRow("CtrlHwnd", "BC10C1", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_2_Type_Before",    "Col_10", "=", "Button")
o(LVOptions, "Ctrl_2_Options_Before", "Col_10", "=", "w125")
o(LVOptions, "Ctrl_2_Text_Before",    "Col_10", "=", "Before Test 2")
o(LVOptions, "Ctrl_2_Hwnd_Before",    "Col_10", "=", "Button2")		;Use 'LV_AddEditRow("CtrlHwnd", "Button2", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_3_Type_Before",    "Col_10", "=", "Button")
o(LVOptions, "Ctrl_3_Options_Before", "Col_10", "=", "w150")
o(LVOptions, "Ctrl_3_Text_Before",    "Col_10", "=", "Before Test 3")
o(LVOptions, "Ctrl_3_Hwnd_Before",    "Col_10", "=", "B3")		;Use 'LV_AddEditRow("CtrlHwnd", "B3", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Header_Options", "Col_10", "=", "cRed")
o(LVOptions, "Type", "Col_10", "=", "DateTime")
o(LVOptions, "Options", "Col_10", "=", "2")		;"2" checkbox inside the control
o(LVOptions, "Text", "Col_10", "=", "LongDate")

;___

o(LVOptions, "Type", "Col_11", "=", "DateTime")
o(LVOptions, "Options", "Col_11", "=", "2 ChooseNone")	;"2" checkbox inside the control, "None" checkbox unchecked
o(LVOptions, "Text", "Col_11", "=", "Time")

;___

o(LVOptions, "Type", "Col_12", "=", "DateTime")
o(LVOptions, "Options", "Col_12", "=", "2 ChooseNone")		;"2" checkbox inside the control, "None" checkbox unchecked
o(LVOptions, "Text", "Col_12", "=", "yyyy-MM-dd/HH:mm:ss")	;"HH" 24-hour format (00 – 23)

o(LVOptions, "Ctrl_1_Type_After",    "Col_12", "=", "Button")
o(LVOptions, "Ctrl_1_Options_After", "Col_12", "=", "w100 gAction")
o(LVOptions, "Ctrl_1_Text_After",    "Col_12", "=", "  After Test 1 (Action)  ")
o(LVOptions, "Ctrl_1_Hwnd_After",    "Col_12", "=", "AC12C1")		;Use 'LV_AddEditRow("CtrlHwnd", "AC12C1", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_2_Type_After",    "Col_12", "=", "Button")
o(LVOptions, "Ctrl_2_Options_After", "Col_12", "=", "w125")
o(LVOptions, "Ctrl_2_Text_After",    "Col_12", "=", "After Test 2")
o(LVOptions, "Ctrl_2_Hwnd_After",    "Col_12", "=", "AButton2")		;Use 'LV_AddEditRow("CtrlHwnd", "AButton2", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_3_Type_After",    "Col_12", "=", "Button")
o(LVOptions, "Ctrl_3_Options_After", "Col_12", "=", "w150")
o(LVOptions, "Ctrl_3_Text_After",    "Col_12", "=", "After Test 3")
o(LVOptions, "Ctrl_3_Hwnd_After",    "Col_12", "=", "A3")	;Use 'LV_AddEditRow("CtrlHwnd", "A3", "GetObject")' to get the control Hwnd id in case you need it later!

;___

o(LVOptions, "Ctrl_1_Type_Before",    "Col_13", "=", "Button")
o(LVOptions, "Ctrl_1_Options_Before", "Col_13", "=", "w150 ym")
o(LVOptions, "Ctrl_1_Text_Before",    "Col_13", "=", "Before Test 4")

o(LVOptions, "Ctrl_2_Type_Before",    "Col_13", "=", "Button")
o(LVOptions, "Ctrl_2_Options_Before", "Col_13", "=", "w125")
o(LVOptions, "Ctrl_2_Text_Before",    "Col_13", "=", "Before Test 5")

o(LVOptions, "Ctrl_3_Type_Before",    "Col_13", "=", "Button")
o(LVOptions, "Ctrl_3_Options_Before", "Col_13", "=", "w100")
o(LVOptions, "Ctrl_3_Text_Before",    "Col_13", "=", "Before Test 6")

o(LVOptions, "Header_Options", "Col_13", "=", "cRed")
o(LVOptions, "Type", "Col_13", "=", "MonthCal")
o(LVOptions, "Text", "Col_13", "=", "20050525-20050531")

o(LVOptions, "Ctrl_1_Type_After",    "Col_13", "=", "Button")
o(LVOptions, "Ctrl_1_Options_After", "Col_13", "=", "w150")
o(LVOptions, "Ctrl_1_Text_After",    "Col_13", "=", "After Test 4")

o(LVOptions, "Ctrl_2_Type_After",    "Col_13", "=", "Button")
o(LVOptions, "Ctrl_2_Options_After", "Col_13", "=", "w125")
o(LVOptions, "Ctrl_2_Text_After",    "Col_13", "=", "After Test 5")

o(LVOptions, "Ctrl_3_Type_After",    "Col_13", "=", "Button")
o(LVOptions, "Ctrl_3_Options_After", "Col_13", "=", "w100")
o(LVOptions, "Ctrl_3_Text_After",    "Col_13", "=", "After Test 6")

;___

o(LVOptions, "Ctrl_1_Type_Before",    "Col_14", "=", "text")
o(LVOptions, "Ctrl_1_Options_Before", "Col_14", "=", "xs section")
o(LVOptions, "Ctrl_1_Text_Before",    "Col_14", "=", "Less")

o(LVOptions, "Header_Options", "Col_14", "=", "x+50 y+-32")
o(LVOptions, "Type", "Col_14", "=", "slider")
o(LVOptions, "Options", "Col_14", "=", "x+-70 ys h25  ToolTip gUpdateSliderStatus")
o(LVOptions, "Text", "Col_14", "=", "25")
o(LVOptions, "Hwnd", "Col_14", "=", "Slider")		;Use 'LV_AddEditRow("CtrlHwnd", "Slider", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_1_Type_After",    "Col_14", "=", "Edit")
o(LVOptions, "Ctrl_1_Options_After", "Col_14", "=", "xp+35 y+-0 w50 center +border gUpdateSlider")
o(LVOptions, "Ctrl_1_Text_After",    "Col_14", "=", "")
o(LVOptions, "Ctrl_1_Hwnd_After",    "Col_14", "=", "SliderStatus")	;Use 'LV_AddEditRow("CtrlHwnd", "SliderStatus", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_2_Type_After",    "Col_14", "=", "text")
o(LVOptions, "Ctrl_2_Options_After", "Col_14", "=", "x+35 ys")
o(LVOptions, "Ctrl_2_Text_After",    "Col_14", "=", "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!

;___

o(LVOptions, "Header_Options", "Col_15", "=", "x+10 y+-32")
o(LVOptions, "Type", "Col_15", "=", "Hotkey")
o(LVOptions, "Text", "Col_15", "=", "^!a")

o(LVOptions, "Ctrl_1_Type_After",    "Col_15", "=", "text")
o(LVOptions, "Ctrl_1_Options_After", "Col_15", "=", "x+5")
o(LVOptions, "Ctrl_1_Text_After",    "Col_15", "=", ":HotKey")

;___

o(LVOptions, "Header_Options", "Col_16", "=", "x+20 section")
o(LVOptions, "Options", "Col_16", "=", "w70 ReadOnly")		;"ReadOnly" is recommended in order to prevent wrong results

o(LVOptions, "Ctrl_1_Type_After",    "Col_16", "=", "UpDown")		;"Col_16" control above is automatically made the Buddy of this control
o(LVOptions, "Ctrl_1_Options_After", "Col_16", "=", "Range0-2000")
o(LVOptions, "Ctrl_1_Text_After",    "Col_16", "=", "1500")

;___

o(LVOptions, "Header_Options", "Col_17", "=", "ys")
o(LVOptions, "Type", "Col_17", "=", "UpDown")				;in this example, "Col_17" will be an "UpDown" control itself!
o(LVOptions, "Options", "Col_17", "=", "h20 -16 gUpdateUpDownBuddy")	;"-16" prevents "UpDown" control to treat the "Col_17" Header control as its "Buddy" control!
o(LVOptions, "Text", "Col_17", "=", "89")
o(LVOptions, "Hwnd", "Col_17", "=", "UpDown")		;Use 'LV_AddEditRow("CtrlHwnd", "UpDown", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_1_Type_After",    "Col_17", "=", "Edit")
o(LVOptions, "Ctrl_1_Options_After", "Col_17", "=", "x+0 w50 gUpdateUpDown")
o(LVOptions, "Ctrl_1_Hwnd_After",    "Col_17", "=", "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!
;___

o(LVOptions, "Header_Options", "Col_18", "=", "ys")
o(LVOptions, "Type", "Col_18", "=", "DDL")
o(LVOptions, "Options", "Col_18", "=", "w50")
o(LVOptions, "Text", "Col_18", "=", "A|B|C|D|E||F|G")
o(LVOptions, "Hwnd", "Col_18", "=", "DDLUPDown")	;Use 'LV_AddEditRow("CtrlHwnd", "DDLUPDown", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_1_Type_After",    "Col_18", "=", "Button")
o(LVOptions, "Ctrl_1_Options_After", "Col_18", "=", "x+0 w20 h11 gCustomUPDown")
o(LVOptions, "Ctrl_1_Text_After",    "Col_18", "=", "▴")

o(LVOptions, "Ctrl_2_Type_After",    "Col_18", "=", "Button")
o(LVOptions, "Ctrl_2_Options_After", "Col_18", "=", "y+-1 w20 h11 gCustomUPDown")
o(LVOptions, "Ctrl_2_Text_After",    "Col_18", "=", "▾")

;___

o(LVOptions, "Header_Options", "Col_19", "=", "xm section")
o(LVOptions, "Options", "Col_19", "=", "w400")
o(LVOptions, "Hwnd", "Col_19", "=", "FileBox")	;Use 'LV_AddEditRow("CtrlHwnd", "FileBox", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_1_Type_After",    "Col_19", "=", "Button")
o(LVOptions, "Ctrl_1_Text_After",    "Col_19", "=", "Browse")
o(LVOptions, "Ctrl_1_Options_After", "Col_19", "=", "x+0 gBrowse")

;___

o(LVOptions, "Header_Options", "Col_20", "=", "ys")
o(LVOptions, "Options", "Col_20", "=", "ReadOnly")
o(LVOptions, "Hwnd", "Col_20", "=", "IconBox")		;Use 'LV_AddEditRow("CtrlHwnd", "IconBox", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_1_Type_After",    "Col_20", "=", "Button")
o(LVOptions, "Ctrl_1_Options_After", "Col_20", "=", "x+0 gChooseIcon")
o(LVOptions, "Ctrl_1_Text_After",    "Col_20", "=", "Choose Icon")

;___

o(LVOptions, "Header_Options", "Col_21", "=", "ys")
o(LVOptions, "Options", "Col_21", "=", "w75 gLoneUpDown")
o(LVOptions, "Text", "Col_21", "=", 4)
o(LVOptions, "Hwnd", "Col_21", "=", "LoneUpDownEditId")		;Use 'LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_1_Type_After",    "Col_21", "=", "UpDown")
o(LVOptions, "Ctrl_1_Options_After", "Col_21", "=", "Range-1-1 gLoneUpDown -0x2")	;"-0x2", prevents the UpDown control to set the text of the buddy "Edit" control
o(LVOptions, "Ctrl_1_Text_After",    "Col_21", "=", "0")				;must be\start as "0" (zero) / Range must be "-1 to 1"
o(LVOptions, "Ctrl_1_Hwnd_After",    "Col_21", "=", "LoneUpDownId")	;Use 'LV_AddEditRow("CtrlHwnd", "LoneUpDownId", "GetObject")' to get the control Hwnd id in case you need it later!

o(LVOptions, "Ctrl_2_Type_After",    "Col_21", "=", "text")
o(LVOptions, "Ctrl_2_Options_After", "Col_21", "=", "x+0")
o(LVOptions, "Ctrl_2_Text_After",    "Col_21", "=", "+-")

o(LVOptions, "Ctrl_3_Type_After",    "Col_21", "=", "edit")
o(LVOptions, "Ctrl_3_Options_After", "Col_21", "=", "x+0 w25 center")
o(LVOptions, "Ctrl_3_Text_After",    "Col_21", "=", "2")
o(LVOptions, "Ctrl_3_Hwnd_After",    "Col_21", "=", "Increment")	;Use 'LV_AddEditRow("CtrlHwnd", "Increment", "GetObject")' to get the control Hwnd id in case you need it later!

;___

;___

;___

;___

o(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++ "|T" 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, 21
	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++, 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
gui, add, button, x+70 gShowLVOptions, Show LVOptions

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

LoneUpDown:	;__________________ LoneUpDown _________________

GuiControlGet, Increment, , % LV_AddEditRow("CtrlHwnd", "Increment", "GetObject")
GuiControlGet, LoneUpDownEdit, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")

GuiControlGet, LoneUpDown, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownId", "GetObject")		;check if "UpDown" control value is "-1", "0" or "1"
GuiControl, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownId", "GetObject"), 0			;set the "UpDown" control to "0" (zero)

	;msgbox, % LoneUpDown

if (LoneUpDown = 1)
LoneUpDownEdit := LoneUpDownEdit + Increment
else if (LoneUpDown = -1)
LoneUpDownEdit := LoneUpDownEdit - Increment

if LoneUpDownEdit is Number
LoneUpDownEdit := LoneUpDownEdit < -50 ? -50 : LoneUpDownEdit > 100 ? 100 : LoneUpDownEdit
else
LoneUpDownEdit := LoneUpDownEdit = "" ? "" : LoneUpDownEdit = "-" ? "-" : 0

GuiControl, -g, % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")
GuiControl, , % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject"), % LoneUpDownEdit
ControlSend, , {End}, % "ahk_id" LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")
GuiControl, +gLoneUpDown, % LV_AddEditRow("CtrlHwnd", "LoneUpDownEditId", "GetObject")

	;tooltip, % count++ 

return

ShowLVOptions:		;___________________ Show LVOptions __________________

gui, LVOptions:Default

gui, destroy

gui, add, edit, w600 h400 +HScroll, % LVOptions

gui, show

return

guiclose:	;__________________ Gui Close _______________
2guiclose:
3guiclose:
exitapp


LV_AddEditRow(GuiWnd, LVCtrl, Status, Optns := "")	;_______________ Add/Edit ListView Controls Rows - v2.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

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 (o(Options, "Ctrl_" a_index "_Type_Before", "Col_" TempIndex) == "")
			break
			else
			{
			gui, add, % o(Options, "Ctrl_" a_index "_Type_Before", "Col_" TempIndex), % "+HwndTempControlId " o(Options, "Ctrl_" a_index "_Options_Before", "Col_" TempIndex), % o(Options, "Ctrl_" a_index "_Text_Before", "Col_" TempIndex)

			TempKey := o(Options, "Ctrl_" a_index "_Hwnd_Before", "Col_" TempIndex)
			CtrlHwnd[TempKey] := TempControlId
			}
		}

	gui, add, text, % o(Options, "Header_Options", "Col_" a_index), % TempHeader

		;Ternary operator, ( ? = if ) and ( : = else )

	ControlType := ControlOption := ControlText := ""	;blank\empty values

	ControlType := CtrlType[a_index] := o(Options, "Type", "Col_" a_index) != "" ? o(Options, "Type", "Col_" a_index) : "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 := o(Options, "Text", "Col_" TempIndex), o(Options, "Text", "Col_" TempIndex, "=", "")

				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
						}

					}

				o(Options, "Text", "Col_" TempIndex, "=", o(Options, "Text", "Col_" TempIndex) TempString "|")
				}
			}
		}
		else if (ControlType != "Edit" and ControlType != "ComboBox")
		{
		if (ControlType = "MonthCal")
		TempText := RegExReplace(TempText, "\Q/")	;remove any "/" character

		if (Status = "Modify")
		ControlText := TempText, o(Options, "Text", "Col_" a_index, "=", "")
		}

	gui, add, % ControlType, % "+HwndTempControlId " o(Options, "Options", "Col_" a_index) " " ControlOption, % o(Options, "Text", "Col_" a_index) 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 := o(Options, "Hwnd", "Col_" a_index)
	CtrlHwnd[TempKey] := TempControlId

		TempIndex := a_index
		loop
		{
			if (o(Options, "Ctrl_" a_index "_Type_After", "Col_" TempIndex) = "")
			break
			else
			{
			gui, add, % o(Options, "Ctrl_" a_index "_Type_After", "Col_" TempIndex), % "+HwndTempControlId " o(Options, "Ctrl_" a_index "_Options_After", "Col_" TempIndex), % o(Options, "Ctrl_" a_index "_Text_After", "Col_" TempIndex)

				if (a_index = "1" and Status = "Modify" and o(Options, "Ctrl_" a_index "_Type_After", "Col_" TempIndex) = "UpDown")
				{
				ControlGet, TempStyle, Style, , , % "ahk_id" TempControlId

					;0x10 = 16 (means that the "UpDown" control treats the previous control as its buddy control)
					;0x2 = 2 (means that the "UpDown" control can set\modify text of its buddy control)

					;https://autohotkey.com/docs/commands/WinGet.htm#Style
					;https://autohotkey.com/docs/misc/Styles.htm#UpDown

				if (TempStyle & 0x10) and (TempStyle & 0x2)				;if style "0x10" and "0x2" are found in "TempStyle" variable
				guicontrol, , % TempControlId , % RegExReplace(TempText, "\.|,")	;Regex removes thousands separator (. or ,)
				}

			TempKey := o(Options, "Ctrl_" a_index "_Hwnd_After", "Col_" TempIndex)
			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(o(Options, "NewRowIndex") = "" ? LV_GetCount() + 1 : o(Options, "NewRowIndex"), o(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 o(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 o(Options, "NewRowOptions") prevents Autohotkey from crashing if o(Options, "NewRowIndex") is blank/empty and the ListView control contains "Sort" or "SortDesc" options
		}

		if (a_guicontrol = "Modify")
		{
		LV_Modify(FocusedRow, o(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 (o(Options, "GoSub") != "")	;if not blank/empty
GoSub, % o(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
}


o(ByRef Var, Key := "", Section := "", Task := "", Value := "", Options := "")	;__________________ SimpleObject o(Function) - v1.4 _________________________ 
{

;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 AnyVariable	;(Not Recommended) this line would switch the function mode from "assume-Local" to "assume-Global" (makes all variables global by default)


Static FindAnySection := "s)#(.*?)#@(.*?)#End#!"

Static FindAnyKey := "s)#(.*?)#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if (key = "<=Get")
return, (%Var%)		;returns the values of static variables of this function! (Mainly for "FindAnyKey" var)

	if (Key = "<=CountSections")
	{
	RegExReplace(Var, "#End#!", , TotalReplace)
	return, TotalReplace
	}

	if RegExMatch(Key, "i)^<=(S|C)(\d+)$", Found)
	{
	GetWhat := Found1, GetX := Found2

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(Var, FindAnySection, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "S" ? RegExReplace(Match1, "#_", "#") : Match2
			}
		}
	}

if (Key = "" and Section = "" and Task = "" and Value = "" and Options = "")
return, "#" RegExReplace(Var, "#", "#_") "#"

if (Key = "Get=>")
key := "", Task := "GetSection"

if (Key = "GetIndex=>")
key := "", Task := "GetSectionIndex"

if RegExMatch(Key, "i)^(k|v)(\d+)=>$", Found)
key := "", GetWhat := Found1, GetX := Found2

	if RegExMatch(Key, "=>$")	;if "key" var value ends with an "=>" (Add\Modify keys-Values from existing "Sections!"! Create "Section" if doesn't exist!)
	{
	if RegExMatch(Key, "-=>$")		;if "key" var value ends with an "-=>" (delete content of the "Section" and add new keys-values)
	o(Var, , Section, "DelSectionContent")

	if RegExMatch(Key, "\+=>$")	;if "key" var value ends with an "+=>" (Creat new "section" at specified index!)
	Task := "<="
	else
	Task := "="

		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(key, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (a_index = 2)
			Task := "="

			if o(Var, Match1, Section, Task, Match4, "Skip#Esc") = "InvalidSectionIndex"
			return
			}
		}
	}

	if !RegExMatch(Options, "i)Skip#Esc")		;"i" enable regex Case-insensitive
	{
	Key := RegExReplace(Key, "#", "#_")
	Value := RegExReplace(Value, "#", "#_")
	}

Section := RegExReplace(Section, "#", "#_")

KeyEsc2 := "\Q" RegExReplace(Key, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
KeyEsc3 := RegExReplace(Key, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

ValueEsc2 := "\Q" RegExReplace(Value, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
ValueEsc3 := RegExReplace(Value, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

SectionEsc2 := "\Q" RegExReplace(Section, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionEsc3 := RegExReplace(Section, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

;_

FindSection := "s)#" SectionEsc2 "#@(.*?)#End#!"

if RegExMatch(Var, FindSection, Match)
SectionExist := "1"

if (Task = "CheckSection")
return, SectionExist

SectionContent := Match1

;_

FindKey := "s)#" KeyEsc2 "#( |	)*?=( |	)*?#(.*?)#(?!_)"
;#(?!_), match an "#" without "_" at its right!
;( |	), Space or Tab

if RegExMatch(SectionContent, FindKey, Match)
KeyExist := "1"

if (Task = "CheckKey")
return, KeyExist

KeyValue := Match3

;_

SectionName := RegExReplace(Section, "\d+$")	;if exist, remove the sequence of numbers at the end

RegExMatch(Section, "\d+$", Match)		;if exist, match the sequence of numbers at the end
if !RegExMatch(Match, "^0")			;"Match" var must not start by a "0" digit (zero digit)
SectionIndex := Match

SectionNameEsc2 := "\Q" RegExReplace(SectionName, "\\E", "\E\\E\Q") "\E"	;Escaped Var to be used with "RegExMatch" and "RegExReplace" second parameters! ("\\" represents one literal "\")
SectionNameEsc3 := RegExReplace(SectionName, "\$", "$$$$")			;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	if (GetWhat != "")
	{
		FoundPos := 1
		MatchLenght := 0
		loop
		{
		FoundPos := RegExMatch(SectionContent, FindAnyKey, Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			return
			else
			{
			MatchLenght := StrLen(Match)

			if (GetX = a_index)
			return, GetWhat = "k" ? RegExReplace(Match1, "#_", "#") : RegExReplace(Match4, "#_", "#")
			}
		}
	}

	if (Task = "<=")
	{
	if (SectionIndex == "" or SectionIndex == 0)
	return, "InvalidSectionIndex"
	}

	if (Task = "<=" and SectionIndex != "" and SectionIndex > 0)    ;"<=" means "Insert at" Section Index (Example: Insert at "Col1" section, the previous "Col1" section is moved to "col2", the previous "Col2" is moved to "col3", and so on ...!)
	{
		if (SectionExist != "1")	;means that insertion Section Index point does not exist
		Task := "="			;Forces the new section to be created anyway
		else
		{
		Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#" KeyEsc3 "# = #" ValueEsc3  "#`r`n#End#!`r`n`r`n$0")

		UpdateSectionIndex := "1"
		} 
		

	}

	if (Task = "DelSection")
	{
	Var := RegExReplace(Var, FindSection "`r`n`r`n")		;Delete section

	if (SectionIndex != "" and SectionIndex > 0)
	UpdateSectionIndex := "1"
	}

	if (Task = "DelSectionContent")
	{
	Var := RegExReplace(Var, FindSection, "#" SectionEsc3 "#@`r`n#End#!")		;Delete section content
	}

	if (Task = "GetSection")
	{
	return, SectionContent
	}

	if (Task = "DelKey")
	{
	SectionContent := RegExReplace(SectionContent, FindKey "`r`n")		;Delete "Key" from "section"

	EditedSection := "#" Section "#@" SectionContent "#End#!"

	EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

	Var := RegExReplace(Var, FindSection, EditedSection)
	}

	if (Task = "GetSectionIndex")
	{
	RegExReplace(SectionContent, FindAnyKey,, TotalReplace)
	return, TotalReplace
	}

	if (UpdateSectionIndex = "1")
	{
		FoundPos := 1
		MatchLenght := 0
		Count := 1
		loop
		{
		FoundPos := RegExMatch(Var, "#" SectionNameEsc2 "(\d+)#@", Match, FoundPos + MatchLenght)

			if (FoundPos = 0 or FoundPos = "")
			break
			else
			{
			MatchLenght := StrLen(Match)

			IndexFound := Match1
			if RegExMatch(IndexFound, "^0")
			Continue			;"Continue", Skips the rest of the current loop iteration and begins a new one.

			Var := RegExReplace(Var, "#" SectionNameEsc2 "(\d+)#@", "#" SectionNameEsc3 Count "#@", , 1, FoundPos)

			MatchLenght := StrLen(SectionName) + StrLen(Count) + 3		;the "+ 3" is for "##@" 

			Count++
			}
		}
	}

	if (Task == "")		;if blank, "Get" key's value 
	{
		;return, SectionContent

	KeyValue := RegExReplace(KeyValue, "#_", "#")

	return, KeyValue
	}
	else if (Task = "=")
	{
		if (SectionExist = "1")
		{
			if (KeyExist = "1")
			{
			SectionContent := RegExReplace(SectionContent, FindKey, "#" KeyEsc3 "# = #" ValueEsc3 "#")
			}
			else
			{
			SectionContent .= "#" Key "# = #" Value "#`r`n"
			}

		EditedSection := "#" Section "#@" SectionContent "#End#!"

		EditedSection := RegExReplace(EditedSection, "\$", "$$$$")	;Escaped Var to be used with "RegExReplace" third parameter! ("$$" represents one literal "$")

		Var := RegExReplace(Var, FindSection, EditedSection)
		}
		else
		{
			if (SectionIndex != "" and SectionIndex > 1)
			{
			if !RegExMatch(Var, "s)#" SectionNameEsc2 "1#@(.*?)#End#!")
			var .= "#" SectionName "1#@`r`n#End#!`r`n`r`n"
			
				loop, % SectionIndex
				{
				if (a_index = SectionIndex)
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#" KeyEsc3 "# = #" ValueEsc3 "#`r`n#End#!")
				else if !RegExMatch(Var, "s)#" SectionNameEsc2 a_index "#@(.*?)#End#!")
				Var := RegExReplace(Var, "s)#" SectionNameEsc2 a_index - 1 "#@(.*?)#End#!", "$0`r`n`r`n#" SectionNameEsc3 a_index "#@`r`n#End#!")
				}


				;msgbox, % SectionName " - " SectionIndex
			}
			else
			{
			Var.= "#" Section "#@`r`n#" Key "# = #" Value "#`r`n#End#!`r`n`r`n"
			}
		}
	}

}

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 74 guests