Grid of Checkboxes Topic is solved

Get help with using AutoHotkey and its commands and hotkeys
aromero
Posts: 51
Joined: 01 Aug 2016, 11:53

Grid of Checkboxes

21 Jan 2020, 13:03

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
User avatar
Chunjee
Posts: 787
Joined: 18 Apr 2014, 19:05
GitHub: Chunjee

Re: Grid of Checkboxes

21 Jan 2020, 15:50

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.
FanaticGuru
Posts: 1497
Joined: 30 Sep 2013, 22:25

Re: Grid of Checkboxes

21 Jan 2020, 16:13

aromero wrote:
21 Jan 2020, 13:03
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?

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")
}
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
User avatar
kczx3
Posts: 1254
Joined: 06 Oct 2015, 21:39

Re: Grid of Checkboxes

22 Jan 2020, 21:37

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
just me
Posts: 7747
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Grid of Checkboxes  Topic is solved

24 Jan 2020, 15:18

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")
}
User avatar
kczx3
Posts: 1254
Joined: 06 Oct 2015, 21:39

Re: Grid of Checkboxes

24 Jan 2020, 20:08

@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.
FanaticGuru
Posts: 1497
Joined: 30 Sep 2013, 22:25

Re: Grid of Checkboxes

24 Jan 2020, 21:36

just me wrote:
24 Jan 2020, 15:18
Just a proof of concept:

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
just me
Posts: 7747
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Grid of Checkboxes

26 Jan 2020, 06:04

@kczx3,
1. Why call if Trim(txt)? You're PoC has text in every cell...
Just to show that I wouldn't add checkboxes to empty cells. ;)
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.
This might show better results. It's using the original state image list returned from the dummy control.

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
}
There's another option if you use a ListView with the Checked option and a hidden first colum.
aromero
Posts: 51
Joined: 01 Aug 2016, 11:53

Re: Grid of Checkboxes

28 Jan 2020, 09:27

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
User avatar
hasantr
Posts: 780
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Grid of Checkboxes

17 Dec 2020, 16:19

@just me . This awesome script has been very useful to me. Thank you.

Image

But if the guides are open, such a cosmetic problem occurs on the left. Is there a way to fix it?
Thanks again.
User avatar
kczx3
Posts: 1254
Joined: 06 Oct 2015, 21:39

Re: Grid of Checkboxes

17 Dec 2020, 17:26

Do you mean grid lines when you say “guides”?
User avatar
hasantr
Posts: 780
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Grid of Checkboxes

17 Dec 2020, 17:47

kczx3 wrote:
17 Dec 2020, 17:26
Do you mean grid lines when you say “guides”?
Oh yes. My English is not good at all.
Thanks for the fix.
User avatar
kczx3
Posts: 1254
Joined: 06 Oct 2015, 21:39

Re: Grid of Checkboxes

17 Dec 2020, 19:43

None of the concept code does any manual drawing so I’m not sure what you could do to fix that
User avatar
kczx3
Posts: 1254
Joined: 06 Oct 2015, 21:39

Re: Grid of Checkboxes

18 Dec 2020, 10:24

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.
User avatar
hasantr
Posts: 780
Joined: 05 Apr 2016, 14:18
Location: İstanbul

Re: Grid of Checkboxes

19 Dec 2020, 07:38

kczx3 wrote:
18 Dec 2020, 10:24
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.
Yes I could not do either. Maybe I shouldn't use lines.

Return to “Ask For Help”

Who is online

Users browsing this forum: Bing [Bot], Google [Bot], mikeyww, Nixcalo, paul1965, roysubs, XMCQCX and 50 guests