Is there a way to setup a listview so that there is a checkbox in each cell, not just at the beginning of each row?
I have a project where I am copying Excel data to the clipboard, sending it into my AHK project where it will add a checkbox and the excel text to a grid layout. The user will be able to check the cells they want AHK to act on. I haven't found a way to setup a gui where check boxes can be added in a grid layout such as a listview.
Thoughts on what I should look into?
-Andrew V. Romero
Grid of Checkboxes Topic is solved
Re: Grid of Checkboxes
The way I've done it is to loop through your data, creating each gui element. I couldn't tell if your checkboxes have labels but if they don't it would be easier.
You will generally know that your gui has {{x}} pixels horizontally to work with, which you cross that threshhold move the y down and reset the x position.
You will generally know that your gui has {{x}} pixels horizontally to work with, which you cross that threshhold move the y down and reset the x position.
-
- Posts: 1497
- Joined: 30 Sep 2013, 22:25
Re: Grid of Checkboxes
Not exactly what you asked for. It is not a listview but I already had it so here is an example of a bunch of checkboxes in a GUI.
Code: Select all
Day_Names :=["Su","Mo","Tu","We","Th","Fr","Sa"]
for Day, Name in Day_Names
{
Gui, Add, text, % "x10 y" Day * 60 + 55, % Name ":"
Loop, 24
{
GUI, Add, Text, % "x" A_Index * 30 " y" Day * 60 + 25, % ConvertTimeSlotToTime(A_Index)
GUI, Add, Checkbox, % "v" Name A_Index " x" A_Index * 30 + 5 " y" Day * 60 + 40
GUI, Add, Text, % "x" A_Index * 30 " y" Day * 60 + 55, % ConvertTimeSlotToTime(A_Index+24)
GUI, Add, Checkbox, % "v" Name A_Index + 24 " x" A_Index * 30 + 5 " y" Day * 60 + 70
}
}
Gui, add, Button, Default gSubmit x30 y600 w180, OK
Gui, show
return
Submit:
Gui, Submit, NoHide
Display := "=== Boxes Checked ==="
for Day, Name in Day_Names
{
TimeSlot := 0
while (TimeSlot++ < 48)
{
if (%Name%%TimeSlot% = true)
Display .= "`n" Name "`t" ConvertTimeSlotToTime(TimeSlot)
}
}
MsgBox % Display
return
Esc::ExitApp
ConvertTimeSlotToTime(n)
{
return RegExReplace(Format("{:04u}",(n-1) / 2 * 100), "50$", "30")
}
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
[Function] Timer - Create and Manage Timers
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
[Function] Timer - Create and Manage Timers
Re: Grid of Checkboxes
I think the best you could do with the standard list view is to use icons in each cell to mimic a checkbox.
https://10tec.com/articles/excel-vba-listview-control-examples.aspx
https://10tec.com/articles/excel-vba-listview-control-examples.aspx
Re: Grid of Checkboxes Topic is solved
Just a proof of concept:
Code: Select all
#NoEnv
SetBatchLines, -1
; State image list
HSIL := LV_GetStateImageList()
; LVS_EX_DOUBLEBUFFER = 0x0010000, LVS_EX_SUBITEMIMAGES = 0x02
Gui, Add, ListView, w400 r10 vCBLV hwndHLV +LV0x00010002, Col1|Col2|Col3|Col4|Col5
; Set 'Explorer' theme
DllCall("UxTheme.dll\SetWindowTheme", "Ptr", HLV, "WStr", "Explorer", "Ptr", 0)
ColCnt := LV_GetCount("Col")
LV_SetImageList(HSIL, 1)
Loop, 10 {
Row := LV_Add("", A_Index . "-1", A_Index . "-2", A_Index . "-3", A_Index . "-4", A_Index . "-5")
Col := 2
Loop {
LV_GetText(Txt, Row, Col)
If Trim(Txt)
LV_SetSubItemCB(HLV, Row, Col)
Col++
} Until (Col > ColCnt)
}
LV_ModifyCol()
Gui, Show, , CheckBoxListView
OnMessage(0x0201, "On_WM_LBUTTONDOWN")
Return
GuiClose:
Rows := LV_GetCount()
Cols := LV_GetCount("Col")
Checked := ""
Loop, %Rows% {
Row := A_Index
Loop, %Cols% {
Col := A_Index
If LV_IsChecked(HLV, Row, Col)
Checked .= Row . " - " . Col . "`n"
}
}
MsgBOx, 0, Checked, %Checked%
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
; Left mouse button click handler
; ----------------------------------------------------------------------------------------------------------------------
On_WM_LBUTTONDOWN(W, L, M, H) {
; LVM_GETITEMA = 0x1005, LVM_SETITEMA = 0x1006, LVM_SUBITEMHITTEST = 0x1039
If (A_GuiControl = "CBLV") && LV_IsClickOnIcon(H, L, Row, Col)
LV_ToggleCheck(H, Row, Col)
}
; ----------------------------------------------------------------------------------------------------------------------
; Gets a copy of the state image list of a list view control
; ----------------------------------------------------------------------------------------------------------------------
LV_GetStateImagelist() {
; LVM_GETIMAGELIST = 0x1002, LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036
; LVSIL_STATE = 0x02, LVS_EX_CHECKBOXES = 0x04
HLV := DllCall("CreateWindowEx", "UInt", 0x0200, "Str", "SysListView32", "Ptr", 0, "UInt", 0x01
, "Int", 0, "Int", 0, "Int", 100, "Int", 100, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "UPtr")
DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1036, "Ptr", 0x04, "Ptr", 0x04)
HSIL := DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1002, "Ptr", 2, "Ptr", 0, "UPtr")
DllCall("ImageList_GetIconSize", "Ptr", HSIL, "IntP", W, "IntP", H)
C := DllCall("ImageList_GetImageCount", "Ptr", HSIL, "Ptr", 0, "Ptr", 0, "Int")
HIL := DllCall("ImageList_Create", "Int", W, "Int", H, "UInt", 0x00010001, "Int", C, "Int", C, "UPtr")
Loop, %C% {
HICO := DllCall("ImageList_GetIcon", "Ptr", HSIL, "Int", A_Index - 1, "UInt", 0, "UPtr")
DllCall("ImageList_ReplaceIcon", "Ptr", HIL, "Int", -1, "Ptr", HICO)
}
DllCall("DestroyWindow", "Ptr", HLV)
Return HIL
}
; ----------------------------------------------------------------------------------------------------------------------
; Checks whether an item or subitem shows the 'checked' check box icon
; ----------------------------------------------------------------------------------------------------------------------
LV_IsChecked(HLV, Row, Col) {
; LVM_GETITEMA = 0x1005
Static OffImage := 20 + (A_PtrSize * 2)
LV_CreateLVITEM(LVITEM, 0x00000002, Row, Col)
Return DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1005, "Ptr", 0, "Ptr", &LVITEM, "UInt")
? NumGet(LVITEM, OffImage, "Int")
: False
}
; ----------------------------------------------------------------------------------------------------------------------
; Checks whether the left mouse button was pressed upon a check box icon
; ----------------------------------------------------------------------------------------------------------------------
LV_IsClickOnIcon(HLV, POINTS, ByRef Row, ByRef Col) {
; LVM_SUBITEMHITTEST =0x1039
Col := Row := 0
VarSetCapacity(LVHTI, 24, 0)
VarSetCapacity(PTS, 4, 0)
NumPut(POINTS, PTS, "Int")
NumPut(NumGet(PTS, 0, "Short"), LVHTI, 0, "Int")
NumPut(NumGet(PTS, 2, "Short"), LVHTI, 4, "Int")
If (DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1039, "Ptr", 0, "Ptr", &LVHTI, "Int") <> -1) {
If (NumGet(LVHTI, 8, "UInt") = 2) { ; Flags: LVHT_ONITEMICON = 2
Row := NumGet(LVHTI, 12, "Int") + 1 ; Item
Col := NumGet(LVHTI, 16, "Int") + 1 ; SubItem
Return True
}
}
Return False
}
; ----------------------------------------------------------------------------------------------------------------------
; Toggles the check box icon (unchecked <> checked)
; ----------------------------------------------------------------------------------------------------------------------
LV_ToggleCheck(HLV, Row, Col) {
; LVM_GETITEMA = 0x1005, LVM_SETITEMA = 0x1006
Static OffImage := 20 + (A_PtrSize * 2)
LV_CreateLVITEM(LVITEM, 0x00000002, Row, Col)
If DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1005, "Ptr", 0, "Ptr", &LVITEM, "UInt") {
NumPut(NumGet(LVITEM, OffImage, "Int") ? 0 : 1, LVITEM, OffImage, "Int")
Return DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1006, "Ptr", 0, "Ptr", &LVITEM, "Int")
}
Return False
}
; ----------------------------------------------------------------------------------------------------------------------
; Sets the check box icon for subitems
; ----------------------------------------------------------------------------------------------------------------------
LV_SetSubItemCB(HLV, Row, Col, Index := 1) {
; LVM_SETITEMA = 0x1006 -> http://msdn.microsoft.com/en-us/library/bb761186(v=vs.85).aspx
Static OffImage := 20 + (A_PtrSize * 2)
LV_CreateLVITEM(LVITEM, 0x00000002, Row, Col) ; LVIF_IMAGE
NumPut(Index - 1, LVITEM, OffImage, "Int")
Return DllCall("SendMessage", "Ptr", HLV, "UInt", 0x1006, "Ptr", 0, "Ptr", &LVITEM, "Int")
}
; ----------------------------------------------------------------------------------------------------------------------
; Creates a LVITEM structure filling some fields
; ----------------------------------------------------------------------------------------------------------------------
LV_CreateLVITEM(ByRef LVITEM, Mask := 0, Row := 1, Col := 1) {
Static LVITEMSize := 40 + (A_PtrSize * 5)
VarSetCapacity(LVITEM, LVITEMSize, 0)
NumPut(Mask, LVITEM, 0, "UInt"), NumPut(Row - 1, LVITEM, 4, "Int"), NumPut(Col - 1, LVITEM, 8, "Int")
}
Re: Grid of Checkboxes
@just me well done. Nifty how you create a control with the LVS_EX_CHECKBOXES extended style to grab the state image list.
I don't want to hijack this thread but I have a few questions.
1. Why call if Trim(txt)? You're PoC has text in every cell...
2. Oddly, it seems that the checkmark is grey and not black. Add 0x4 to the GUI's listview styles and you can see the slight color difference.
Great code as usual from you.
I don't want to hijack this thread but I have a few questions.
1. Why call if Trim(txt)? You're PoC has text in every cell...
2. Oddly, it seems that the checkmark is grey and not black. Add 0x4 to the GUI's listview styles and you can see the slight color difference.
Great code as usual from you.
-
- Posts: 1497
- Joined: 30 Sep 2013, 22:25
Re: Grid of Checkboxes
This is pretty nifty.
I like the effect of how rows are highlighted. It looks like it would be pretty easy to modify so that you can only pick one item from each row which makes for a nice multiple choice questionnaire type effect.
I am squirreling this code away for a rain day when I need it.
FG
Hotkey Help - Help Dialog for Currently Running AHK Scripts
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
[Function] Timer - Create and Manage Timers
AHK Startup - Consolidate Multiply AHK Scripts with one Tray Icon
[Function] Timer - Create and Manage Timers
Re: Grid of Checkboxes
@kczx3,
There's another option if you use a ListView with the Checked option and a hidden first colum.
Just to show that I wouldn't add checkboxes to empty cells.1. Why call if Trim(txt)? You're PoC has text in every cell...

This might show better results. It's using the original state image list returned from the dummy control.2. Oddly, it seems that the checkmark is grey and not black. Add 0x4 to the GUI's listview styles and you can see the slight color difference.
Code: Select all
; ----------------------------------------------------------------------------------------------------------------------
; Gets the state image list of a list view control.
; If you need to assign the returned image list to multiple list views,
; consider to set the LVS_SHAREIMAGELISTS (0x40) style.
; ----------------------------------------------------------------------------------------------------------------------
LV_GetStateImagelist() {
; LVM_GETIMAGELIST = 0x1002, LVM_SETEXTENDEDLISTVIEWSTYLE = 0x1036
; LVSIL_STATE = 0x02, LVS_EX_CHECKBOXES = 0x04
Static HSIL := 0
If (HSIL = 0) {
HWND := DllCall("CreateWindowEx", "UInt", 0x0200, "Str", "SysListView32", "Ptr", 0, "UInt", 0x01
, "Int", 0, "Int", 0, "Int", 0, "Int", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "Ptr", 0, "UPtr")
DllCall("SendMessage", "Ptr", HWND, "UInt", 0x1036, "Ptr", 0x04, "Ptr", 0x04)
HSIL := DllCall("SendMessage", "Ptr", HWND, "UInt", 0x1002, "Ptr", 2, "Ptr", 0, "UPtr")
}
Return HSIL
}
Re: Grid of Checkboxes
Thanks everyone. These are all great ideas. JustMe's looks the best although is the most complicated. I'll have to see if I can figure out the code well enough to use it for my project. I appreciate everyone's help.
-Andrew V. Romero
-Andrew V. Romero
Re: Grid of Checkboxes
@just me . This awesome script has been very useful to me. Thank you.

But if the guides are open, such a cosmetic problem occurs on the left. Is there a way to fix it?
Thanks again.

But if the guides are open, such a cosmetic problem occurs on the left. Is there a way to fix it?
Thanks again.
Re: Grid of Checkboxes
Do you mean grid lines when you say “guides”?
Re: Grid of Checkboxes
None of the concept code does any manual drawing so I’m not sure what you could do to fix that
Re: Grid of Checkboxes
I see no way to handle this other than custom drawing the listview to draw the icon to the right by a couple pixels. It happens with images besides the checkboxes and also happens if you don't enable the Explorer style for the control. I also tried applying the Grid option after the addition of the subitem images.
Re: Grid of Checkboxes
Yes I could not do either. Maybe I shouldn't use lines.kczx3 wrote: ↑18 Dec 2020, 10:24I see no way to handle this other than custom drawing the listview to draw the icon to the right by a couple pixels. It happens with images besides the checkboxes and also happens if you don't enable the Explorer style for the control. I also tried applying the Grid option after the addition of the subitem images.