实现一个带有复选框的多列 ListView 控件,支持对单元格的复选框进行点击切换和状态读取。

 

; https://www.autohotkey.com/boards/viewtopic.php?p=311203&sid=0781c8c9cac0e8d478419974e92b94d2#p311203
#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")
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。