Whats a better way to get which column was double-clicked in a gui listview? Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
SSpeed
Posts: 25
Joined: 04 Jul 2018, 09:48

Whats a better way to get which column was double-clicked in a gui listview?

Post by SSpeed » 18 Sep 2019, 13:59

Something better than this?

garry
Posts: 3763
Joined: 22 Dec 2013, 12:50

Re: Whats a better way to get which column was double-clicked in a gui listview?  Topic is solved

Post by garry » 18 Sep 2019, 14:45

script from user 'just me'
https://autohotkey.com/board/topic/80265-solved-which-column-is-clicked-in-listview/

Code: Select all

;-------- saved at Mittwoch, 18. September 2019 21:42:50 --------------
;;-------- https://autohotkey.com/board/topic/80265-solved-which-column-is-clicked-in-listview/ ---
#NoEnv
Gui, Margin, 20, 20
Gui, Add, ListView, w400 r9 Grid HwndHLV1 gSubLV AltSubmit, Column 1|Column 2|Column 3
Loop, 9
   LV_Add("", A_Index, A_Index, A_Index)
Loop, 3
   LV_ModifyCol(A_Index, "AutoHdr")
Gui, Show, , ListView
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiCLose:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
SubLV:
   If (A_GuiEvent = "Normal") {
      Row := A_EventInfo
      Column := LV_SubItemHitTest(HLV1)
      ToolTip, You clicked on column %Column% in row %Row%!
      SetTimer, KillToolTip, -1500
   }
Return
; ----------------------------------------------------------------------------------------------------------------------
KillToolTip:
   ToolTip
Return
; ----------------------------------------------------------------------------------------------------------------------
LV_SubitemHitTest(HLV) {
   ; To run this with AHK_Basic change all DllCall types "Ptr" to "UInt", please.
   ; HLV - ListView's HWND
   Static LVM_SUBITEMHITTEST := 0x1039
   VarSetCapacity(POINT, 8, 0)
   ; Get the current cursor position in screen coordinates
   DllCall("User32.dll\GetCursorPos", "Ptr", &POINT)
   ; Convert them to client coordinates related to the ListView
   DllCall("User32.dll\ScreenToClient", "Ptr", HLV, "Ptr", &POINT)
   ; Create a LVHITTESTINFO structure (see below)
   VarSetCapacity(LVHITTESTINFO, 24, 0)
   ; Store the relative mouse coordinates
   NumPut(NumGet(POINT, 0, "Int"), LVHITTESTINFO, 0, "Int")
   NumPut(NumGet(POINT, 4, "Int"), LVHITTESTINFO, 4, "Int")
   ; Send a LVM_SUBITEMHITTEST to the ListView
   SendMessage, LVM_SUBITEMHITTEST, 0, &LVHITTESTINFO, , ahk_id %HLV%
   ; If no item was found on this position, the return value is -1
   If (ErrorLevel = -1)
      Return 0
   ; Get the corresponding subitem (column)
   Subitem := NumGet(LVHITTESTINFO, 16, "Int") + 1
   Return Subitem
}
/*
typedef struct _LVHITTESTINFO {
  POINT pt;
  UINT  flags;
  int   iItem;
  int   iSubItem;
  int   iGroup;
} LVHITTESTINFO, *LPLVHITTESTINFO;
*/

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 18 Sep 2019, 15:20

Code: Select all

Gui, Add, ListView, Grid r5, Col 1|Col 2|Col 3|Col 4
Loop 5
   LV_Add()
Gui, Show
OnMessage(0x4E, "WM_NOTIFY")
Return

GuiClose:
   ExitApp

WM_NOTIFY(wp, lp) {
   static NM_DBLCLK := -3
   if NumGet(lp + A_PtrSize*2, "Int") = NM_DBLCLK
      ToolTip % NumGet(lp + A_PtrSize*3 + 4, "Int") + 1
}

SSpeed
Posts: 25
Joined: 04 Jul 2018, 09:48

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by SSpeed » 18 Sep 2019, 17:19

Thank you for the code.

garry
Posts: 3763
Joined: 22 Dec 2013, 12:50

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by garry » 19 Sep 2019, 09:16

@teadrinker, thank you for the script

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 19 Sep 2019, 11:27

@garry

Code: Select all

Gui, Add, ListView, Grid r5, Col 1|Col 2|Col 3|Col 4
Loop 5
   LV_Add()
Gui, Show
OnMessage(0x4E, "WM_NOTIFY")
Return

GuiClose:
   ExitApp

WM_NOTIFY(wp, lp) {
   static notices := {-2: "NM_CLICK", -3: "NM_DBLCLK"}
   notice := NumGet(lp + A_PtrSize*2, "Int")
   if (notice = -2 || notice = -3)
      ToolTip % "Action: " . notices[notice]                         . "`n"
              . "Row: "    . NumGet(lp + A_PtrSize*3,     "Int") + 1 . "`n"
              . "Column: " . NumGet(lp + A_PtrSize*3 + 4, "Int") + 1
}
:wave:

garry
Posts: 3763
Joined: 22 Dec 2013, 12:50

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by garry » 19 Sep 2019, 14:53

@teadrinker, thank again, now see info : click/doubleclick , row , column
tried this to get row/column

Code: Select all

Gui, Add, ListView, w400 r9 Grid HwndHLV1 gLV1 AltSubmit, Column 1|Column 2|Column 3
global action,notice,rowx,colx
Loop,5
  LV_Add("", "Field 1-" . A_Index, "Field 2-" . A_Index, "Field 3-" . A_Index)
Gui, Show
OnMessage(0x4E, "WM_NOTIFY")
Return
;---------------
GuiClose:
   ExitApp
;---------------   
WM_NOTIFY(wp, lp) 
   {
   static notices := {-2: "NM_CLICK", -3: "NM_DBLCLK"}
   notice := NumGet(lp + A_PtrSize*2, "Int")
   if (notice = -2 || notice = -3)
      Action:= notices[notice] 
   rowx:= NumGet(lp + A_PtrSize*3,     "Int") + 1
   colx:= NumGet(lp + A_PtrSize*3 + 4, "Int") + 1
   }
;---------------
LV1:
Gui,1:ListView,%a_guicontrol%
if a_guievent=Normal
{
LV_GetText(Cx,rowx,colx)
msgbox,%action% - "%cx%"
}
return
;================================================================

Last edited by garry on 24 May 2022, 15:30, edited 1 time in total.

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by BoBo » 23 May 2022, 23:08

teadrinker wrote:
19 Sep 2019, 11:27
@garry

Code: Select all

Gui, Add, ListView, Grid r5, Col 1|Col 2|Col 3|Col 4
Loop 5
   LV_Add()
Gui, Show
OnMessage(0x4E, "WM_NOTIFY")
Return

GuiClose:
   ExitApp

WM_NOTIFY(wp, lp) {
   static notices := {-2: "NM_CLICK", -3: "NM_DBLCLK"}
   notice := NumGet(lp + A_PtrSize*2, "Int")
   if (notice = -2 || notice = -3)
      ToolTip % "Action: " . notices[notice]                         . "`n"
              . "Row: "    . NumGet(lp + A_PtrSize*3,     "Int") + 1 . "`n"
              . "Column: " . NumGet(lp + A_PtrSize*3 + 4, "Int") + 1
}
:wave:
Moin :) (northern German equivalent for: "Hi!")
Is there a chance to select a whole column with clicking its header?

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 24 May 2022, 10:09

Aloha! :)

Code: Select all

LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
LVS_EX_DOUBLEBUFFER := 0x00010000

Gui, Add, ListView, w350 vLV hwndhLV NoSort Grid R15, Col 1|Col 2|Col 3|Col 4
Loop 15
   LV_Add("", "Field " . A_Index, "Field " . A_Index, "Field " . A_Index, "Field " . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 80)
Gui, Show

SendMessage, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER,, ahk_id %hLV%
OnMessage(0x004E, Func("WM_NOTIFY").Bind(hLV))
Return

WM_NOTIFY(hLV, wp, lp) {
   static LVN_COLUMNCLICK := -108, LVM_SETSELECTEDCOLUMN := 0x108C
   hCtrl := NumGet(lp + 0)
   if !(hCtrl = hLV)
      Return
   notify := NumGet(lp + A_PtrSize*2, "Int")
   if (notify = LVN_COLUMNCLICK) {
      col := NumGet(lp + A_PtrSize*3 + 4, "Int")
      SendMessage, LVM_SETSELECTEDCOLUMN, col,,, ahk_id %hLV%
   }
}

GuiClose() {
   ExitApp
}
Do you mean this?

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by BoBo » 24 May 2022, 10:19

@teadrinker - yep! :mrgreen: erm, bear with me if it's kinda obvious but,...
a) allows this as well to extract that selection for further processing? :shifty:
b) how to 'unselect' that selection if needed (ie if a row is clicked afterward, the column is still selected)?

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 24 May 2022, 10:24

What would you like to get, a text array from selected items?

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by BoBo » 24 May 2022, 10:25

teadrinker wrote:
24 May 2022, 10:24
What would you like to get, a text array from selected items?
Sounds perfect! :thumbup:

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 24 May 2022, 10:49

Code: Select all

LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
LVM_GETSELECTEDCOLUMN        := 0x10AE
LVS_EX_DOUBLEBUFFER := 0x010000

Gui, Add, ListView, w350 vLV hwndhLV NoSort Grid R15, Col 1|Col 2|Col 3|Col 4
Loop 15
   LV_Add("", "Field 1-" . A_Index, "Field 2-" . A_Index, "Field 3-" . A_Index, "Field 4-" . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 80)
Gui, Show

SendMessage, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER,, ahk_id %hLV%
OnMessage(0x004E, Func("WM_NOTIFY").Bind(hLV))
Return

$F1::
   SendMessage, LVM_GETSELECTEDCOLUMN,,,, ahk_id %hLV%
   if !col := ErrorLevel + 1
      Return
   textArr := []
   Loop % LV_GetCount() {
      LV_GetText(text, A_Index, col)
      textArr.Push(text)
      MsgBox, % text
   }
   Return

WM_NOTIFY(hLV, wp, lp) {
   static LVN_COLUMNCLICK := -108, LVM_SETSELECTEDCOLUMN := 0x108C, NM_CLICK := -2
   hCtrl := NumGet(lp + 0)
   if !(hCtrl = hLV)
      Return
   notify := NumGet(lp + A_PtrSize*2, "Int")
   if (notify = LVN_COLUMNCLICK) {
      while selectedRow := LV_GetNext()
         LV_Modify(selectedRow, "-Select")
      col := NumGet(lp + A_PtrSize*3 + 4, "Int")
      SendMessage, LVM_SETSELECTEDCOLUMN, col,,, ahk_id %hLV%
   }
   if (notify = NM_CLICK)
      SendMessage, LVM_SETSELECTEDCOLUMN, -1,,, ahk_id %hLV%
}

GuiClose() {
   ExitApp
}

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 24 May 2022, 11:08

Or without OnMessage():

Code: Select all

LVM_SETEXTENDEDLISTVIEWSTYLE := 0x1036
LVM_GETSELECTEDCOLUMN        := 0x10AE
LVS_EX_DOUBLEBUFFER := 0x010000

Gui, Add, ListView, w350 hwndhLV NoSort Grid R15 AltSubmit, Col 1|Col 2|Col 3|Col 4
handler := Func("OnNotify").Bind(hLV)
GuiControl, +g, % hLV, % handler
Loop 15
   LV_Add("", "Field 1-" . A_Index, "Field 2-" . A_Index, "Field 3-" . A_Index, "Field 4-" . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 80)
Gui, Show

SendMessage, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_DOUBLEBUFFER, LVS_EX_DOUBLEBUFFER,, ahk_id %hLV%
Return

$F1::
   SendMessage, LVM_GETSELECTEDCOLUMN,,,, ahk_id %hLV%
   if !col := ErrorLevel + 1
      Return
   textArr := []
   Loop % LV_GetCount() {
      LV_GetText(text, A_Index, col)
      textArr.Push(text)
      MsgBox, % text
   }
   Return

OnNotify(hLV) {
   static LVM_SETSELECTEDCOLUMN := 0x108C
   if (A_GuiEvent = "Normal")
      SendMessage, LVM_SETSELECTEDCOLUMN, -1,,, ahk_id %hLV%
   if (A_GuiEvent = "ColClick") {
      while selectedRow := LV_GetNext()
         LV_Modify(selectedRow, "-Select")
      SendMessage, LVM_SETSELECTEDCOLUMN, A_EventInfo - 1,,, ahk_id %hLV%
   }
}

GuiClose() {
   ExitApp
}

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by BoBo » 24 May 2022, 11:14

@teadrinker - Perfetto Signore :clap: :thumbup: Mille Gracie :)
If you're OK with it I'd transfer a copy of that code on your behalf to the forum "Scripts&Funtions"-section?!? 8-)


teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 25 May 2022, 14:51

BoBo wrote: Is there a chance to select a whole column with clicking its header?
BoBo wrote: Btw, ich sehe im screencast von Nussbeisser sehr wohl das die Spalte optisch selektiert wird (in Farbe des GUI-Rahmens, NICHT in Blau wie bei Auswahl einer Reihe!!), wenn auch (auf meinem tablet) nur schwach erkenntlich.
With some effort, I managed to apply the @just me's LV_Colors class to get a more contrasty selection:

Code: Select all

SetBatchLines, -1

selectionTextColor := 0xFFFFFF
selectionBackColor := 0x3399FF

Gui, Add, ListView, w350 hwndhLV NoSort Grid R15, Col 1|Col 2|Col 3|Col 4
Info := {hLV: hLV, selTextColor: selectionTextColor, selBackColor: selectionBackColor}
Loop 15
   LV_Add("", "Field 1-" . A_Index, "Field 2-" . A_Index, "Field 3-" . A_Index, "Field 4-" . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 80)
Gui, Show

OnMessage(0x004E, Func("WM_NOTIFY").Bind(Info))
Info.LV := new LV_Colors(hLV)
Return

#If Info.col
$F1::
   textArr := []
   Loop % LV_GetCount() {
      LV_GetText(text, A_Index, Info.col)
      textArr.Push(text)
      MsgBox, % text
   }
   Return
#If

WM_NOTIFY(Info, wp, lp) {
   static LVN_COLUMNCLICK := -108, NM_CLICK := -2
   hCtrl := NumGet(lp + 0)
   if !(hCtrl = Info.hLV)
      Return
   notify := NumGet(lp + A_PtrSize*2, "Int")
   if (notify = LVN_COLUMNCLICK) {
      Info.col := NumGet(lp + A_PtrSize*3 + 4, "Int") + 1
      while selectedRow := LV_GetNext()
         LV_Modify(selectedRow, "-Select")
      Info.LV.Clear()
      Loop % LV_GetCount()
         Info.LV.Cell(A_Index, Info.col, Info.selBackColor, Info.selTextColor)
      WinSet, Redraw,, % "ahk_id" . Info.hLV
   }
   if (notify = NM_CLICK && Info.col) {
      Info.col := 0
      Info.LV.Clear()
      WinSet, Redraw,, % "ahk_id" . Info.hLV
   }
}

GuiClose() {
   ExitApp
}

Class LV_Colors {
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; META FUNCTIONS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; ===================================================================================================================
   ; __New()         Create a new LV_Colors instance for the given ListView
   ; Parameters:     HWND        -  ListView's HWND.
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 StaticMode  -  Static color assignment, i.e. the colors will be assigned permanently to the row
   ;                                contents rather than to the row number.
   ;                                Values:  True/False
   ;                                Default: False
   ;                 NoSort      -  Prevent sorting by click on a header item.
   ;                                Values:  True/False
   ;                                Default: True
   ;                 NoSizing    -  Prevent resizing of columns.
   ;                                Values:  True/False
   ;                                Default: True
   ; ===================================================================================================================
   __New(HWND, StaticMode := False, NoSort := True, NoSizing := True) {
      If (This.Base.Base.__Class) ; do not instantiate instances
         Return False
      If This.Attached[HWND] ; HWND is already attached
         Return False
      If !DllCall("IsWindow", "Ptr", HWND) ; invalid HWND
         Return False
      VarSetCapacity(Class, 512, 0)
      DllCall("GetClassName", "Ptr", HWND, "Str", Class, "Int", 256)
      If (Class <> "SysListView32") ; HWND doesn't belong to a ListView
         Return False
      ; ----------------------------------------------------------------------------------------------------------------
      ; Set LVS_EX_DOUBLEBUFFER (0x010000) style to avoid drawing issues.
      SendMessage, 0x1036, 0x010000, 0x010000, , % "ahk_id " . HWND ; LVM_SETEXTENDEDLISTVIEWSTYLE
      ; Get the default colors
      SendMessage, 0x1025, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTBKCOLOR
      This.BkClr := ErrorLevel
      SendMessage, 0x1023, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTCOLOR
      This.TxClr := ErrorLevel
      ; Get the header control
      SendMessage, 0x101F, 0, 0, , % "ahk_id " . HWND ; LVM_GETHEADER
      This.Header := ErrorLevel
      ; Set other properties
      This.HWND := HWND
      This.IsStatic := !!StaticMode
      This.AltCols := False
      This.AltRows := False
      This.NoSort(!!NoSort)
      This.NoSizing(!!NoSizing)
      This.OnMessage()
      This.Critical := "Off"
      This.Attached[HWND] := True
   }
   ; ===================================================================================================================
   __Delete() {
      This.Attached.Remove(HWND, "")
      This.OnMessage(False)
      WinSet, Redraw, , % "ahk_id " . This.HWND
   }
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PUBLIC METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; ===================================================================================================================
   ; Clear()         Clears all row and cell colors.
   ; Parameters:     AltRows     -  Reset alternate row coloring (True / False)
   ;                                Default: False
   ;                 AltCols     -  Reset alternate column coloring (True / False)
   ;                                Default: False
   ; Return Value:   Always True.
   ; ===================================================================================================================
   Clear(AltRows := False, AltCols := False) {
      If (AltCols)
         This.AltCols := False
      If (AltRows)
         This.AltRows := False
      This.Remove("Rows")
      This.Remove("Cells")
      Return True
   }
   ; ===================================================================================================================
   ; AlternateRows() Sets background and/or text color for even row numbers.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   AlternateRows(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.AltRows := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["ARB"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["ART"] := (TxBGR <> "") ? TxBGR : This.TxClr
      This.AltRows := True
      Return True
   }
   ; ===================================================================================================================
   ; AlternateCols() Sets background and/or text color for even column numbers.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   AlternateCols(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.AltCols := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["ACB"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["ACT"] := (TxBGR <> "") ? TxBGR : This.TxClr
      This.AltCols := True
      Return True
   }
   ; ===================================================================================================================
   ; SelectionColors() Sets background and/or text color for selected rows.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default selected background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default selected text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   SelectionColors(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.SelColors := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["SELB"] := BkBGR
      This["SELT"] := TxBGR
      This.SelColors := True
      Return True
   }
   ; ===================================================================================================================
   ; Row()           Sets background and/or text color for the specified row.
   ; Parameters:     Row         -  Row number
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   Row(Row, BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      This["Rows"].Remove(Row, "")
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["Rows", Row, "B"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["Rows", Row, "T"] := (TxBGR <> "") ? TxBGR : This.TxClr
      Return True
   }
   ; ===================================================================================================================
   ; Cell()          Sets background and/or text color for the specified cell.
   ; Parameters:     Row         -  Row number
   ;                 Col         -  Column number
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> row's background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> row's text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   Cell(Row, Col, BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      This["Cells", Row].Remove(Col, "")
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      If (BkBGR <> "")
         This["Cells", Row, Col, "B"] := BkBGR
      If (TxBGR <> "")
         This["Cells", Row, Col, "T"] := TxBGR
      Return True
   }
   ; ===================================================================================================================
   ; NoSort()        Prevents/allows sorting by click on a header item for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   NoSort(Apply := True) {
      If !(This.HWND)
         Return False
      If (Apply)
         This.SortColumns := False
      Else
         This.SortColumns := True
      Return True
   }
   ; ===================================================================================================================
   ; NoSizing()      Prevents/allows resizing of columns for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   NoSizing(Apply := True) {
      Static OSVersion := DllCall("GetVersion", "UChar")
      If !(This.Header)
         Return False
      If (Apply) {
         If (OSVersion > 5)
            Control, Style, +0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING = 0x0800
         This.ResizeColumns := False
      }
      Else {
         If (OSVersion > 5)
            Control, Style, -0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING
         This.ResizeColumns := True
      }
      Return True
   }
   ; ===================================================================================================================
   ; OnMessage()     Adds/removes a message handler for WM_NOTIFY messages for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   Always True
   ; ===================================================================================================================
   OnMessage(Apply := True) {
      If (Apply) && !This.HasKey("OnMessageFunc") {
         This.OnMessageFunc := ObjBindMethod(This, "On_WM_Notify")
         OnMessage(0x004E, This.OnMessageFunc) ; add the WM_NOTIFY message handler
      }
      Else If !(Apply) && This.HasKey("OnMessageFunc") {
         OnMessage(0x004E, This.OnMessageFunc, 0) ; remove the WM_NOTIFY message handler
         This.OnMessageFunc := ""
         This.Remove("OnMessageFunc")
      }
      WinSet, Redraw, , % "ahk_id " . This.HWND
      Return True
   }
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PRIVATE PROPERTIES  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Static Attached := {}
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PRIVATE METHODS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   On_WM_NOTIFY(W, L, M, H) {
      ; Notifications: NM_CUSTOMDRAW = -12, LVN_COLUMNCLICK = -108, HDN_BEGINTRACKA = -306, HDN_BEGINTRACKW = -326
      Critical, % This.Critical
      If ((HCTL := NumGet(L + 0, 0, "UPtr")) = This.HWND) || (HCTL = This.Header) {
         Code := NumGet(L + (A_PtrSize * 2), 0, "Int")
         If (Code = -12)
            Return This.NM_CUSTOMDRAW(This.HWND, L)
         If !This.SortColumns && (Code = -108)
            Return 0
         If !This.ResizeColumns && ((Code = -306) || (Code = -326))
            Return True
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   NM_CUSTOMDRAW(H, L) {
      ; Return values: 0x00 (CDRF_DODEFAULT), 0x20 (CDRF_NOTIFYITEMDRAW / CDRF_NOTIFYSUBITEMDRAW)
      Static SizeNMHDR := A_PtrSize * 3                  ; Size of NMHDR structure
      Static SizeNCD := SizeNMHDR + 16 + (A_PtrSize * 5) ; Size of NMCUSTOMDRAW structure
      Static OffItem := SizeNMHDR + 16 + (A_PtrSize * 2) ; Offset of dwItemSpec (NMCUSTOMDRAW)
      Static OffItemState := OffItem + A_PtrSize         ; Offset of uItemState  (NMCUSTOMDRAW)
      Static OffCT :=  SizeNCD                           ; Offset of clrText (NMLVCUSTOMDRAW)
      Static OffCB := OffCT + 4                          ; Offset of clrTextBk (NMLVCUSTOMDRAW)
      Static OffSubItem := OffCB + 4                     ; Offset of iSubItem (NMLVCUSTOMDRAW)
      ; ----------------------------------------------------------------------------------------------------------------
      DrawStage := NumGet(L + SizeNMHDR, 0, "UInt")
      , Row := NumGet(L + OffItem, "UPtr") + 1
      , Col := NumGet(L + OffSubItem, "Int") + 1
      , Item := Row - 1
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      ; CDDS_SUBITEMPREPAINT = 0x030001 --------------------------------------------------------------------------------
      If (DrawStage = 0x030001) {
         UseAltCol := !(Col & 1) && (This.AltCols)
         , ColColors := This["Cells", Row, Col]
         , ColB := (ColColors.B <> "") ? ColColors.B : UseAltCol ? This.ACB : This.RowB
         , ColT := (ColColors.T <> "") ? ColColors.T : UseAltCol ? This.ACT : This.RowT
         , NumPut(ColT, L + OffCT, "UInt"), NumPut(ColB, L + OffCB, "UInt")
         Return (!This.AltCols && !This.HasKey(Row) && (Col > This["Cells", Row].MaxIndex())) ? 0x00 : 0x20
      }
      ; CDDS_ITEMPREPAINT = 0x010001 -----------------------------------------------------------------------------------
      If (DrawStage = 0x010001) {
         ; LVM_GETITEMSTATE = 0x102C, LVIS_SELECTED = 0x0002
         If (This.SelColors) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt") {
            ; Remove the CDIS_SELECTED (0x0001) and CDIS_FOCUS (0x0010) states from uItemState and set the colors.
            NumPut(NumGet(L + OffItemState, "UInt") & ~0x0011, L + OffItemState, "UInt")
            If (This.SELB <> "")
               NumPut(This.SELB, L + OffCB, "UInt")
            If (This.SELT <> "")
               NumPut(This.SELT, L + OffCT, "UInt")
            Return 0x02 ; CDRF_NEWFONT
         }
         UseAltRow := (Item & 1) && (This.AltRows)
         , RowColors := This["Rows", Row]
         , This.RowB := RowColors ? RowColors.B : UseAltRow ? This.ARB : This.BkClr
         , This.RowT := RowColors ? RowColors.T : UseAltRow ? This.ART : This.TxClr
         If (This.AltCols || This["Cells"].HasKey(Row))
            Return 0x20
         NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt")
         Return 0x00
      }
      ; CDDS_PREPAINT = 0x000001 ---------------------------------------------------------------------------------------
      Return (DrawStage = 0x000001) ? 0x20 : 0x00
   }
   ; -------------------------------------------------------------------------------------------------------------------
   MapIndexToID(Row) { ; provides the unique internal ID of the given row number
      SendMessage, 0x10B4, % (Row - 1), 0, , % "ahk_id " . This.HWND ; LVM_MAPINDEXTOID
      Return ErrorLevel
   }
   ; -------------------------------------------------------------------------------------------------------------------
   BGR(Color, Default := "") { ; converts colors to BGR
      Static Integer := "Integer" ; v2
      ; HTML Colors (BGR)
      Static HTML := {AQUA: 0xFFFF00, BLACK: 0x000000, BLUE: 0xFF0000, FUCHSIA: 0xFF00FF, GRAY: 0x808080, GREEN: 0x008000
                    , LIME: 0x00FF00, MAROON: 0x000080, NAVY: 0x800000, OLIVE: 0x008080, PURPLE: 0x800080, RED: 0x0000FF
                    , SILVER: 0xC0C0C0, TEAL: 0x808000, WHITE: 0xFFFFFF, YELLOW: 0x00FFFF}
      If Color Is Integer
         Return ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16)
      Return (HTML.HasKey(Color) ? HTML[Color] : Default)
   }
}

Loop
Posts: 167
Joined: 07 Jan 2019, 14:51

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by Loop » 25 May 2022, 16:47

Hi,
Is it possible to select more than one column while holding down the ctrl key?

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by BoBo » 26 May 2022, 04:56

With some effort, I managed to apply the @just me's LV_Colors class to get a more contrasty selection:
So cool! :mrgreen: (well, I can't test/use it ATM bc iOS doesn’t support AHK :cry:) Thx a lot anyway 8-)

teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: Whats a better way to get which column was double-clicked in a gui listview?

Post by teadrinker » 26 May 2022, 05:15

Loop wrote: Is it possible to select more than one column while holding down the ctrl key?
Yep, try this:

Code: Select all

SetBatchLines, -1
Gui, Add, ListView, w350 hwndhLV NoSort Grid R15, Col 1|Col 2|Col 3|Col 4
SelCol := new LV_SelectColumn(hLV)
Loop 15
   LV_Add("", "Field 1-" . A_Index, "Field 2-" . A_Index, "Field 3-" . A_Index, "Field 4-" . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 80)
Gui, Show,, Press F1 to get selected columns
Return

$F1:: ; get selected columns
   selected := ""
   selArr := SelCol.GetSelectedColumns()
   for k, v in selArr
      selected .= (selected ? ", " : "") . v
   MsgBox, % "selected columns: " . selected
Return

; select first column
$F2:: SelCol.SelectColumn(1)

; deselect first column
$F3:: SelCol.SelectColumn(1, false)

; toggle first column state
$F4:: SelCol.SelectColumn(1, !SelCol.GetColumnState(1))

GuiClose() {
   ExitApp
}

class LV_SelectColumn
{
   __New(hLV, selBackColor := 0x3399FF, selTextColor := 0xFFFFFF) {
      this.Info := {hLV: hLV, backColor: selBackColor, textColor: selTextColor, selColoumns: {}}
      this.OnNotify := ObjBindMethod(this.Events, "WM_NOTIFY", this.Info)
      OnMessage(0x004E, this.OnNotify)
      this.Info.LV := new LV_Colors(hLV,, false, false)
   }
   
   SelectColumn(n, select := true) {
      this.Info.selColoumns[n] := !select
      this.Events.ToggleColumnSelState(this.Info, n)
      WinSet, Redraw,, % "ahk_id" . this.Info.hLV
   }
   
   GetColumnState(n) {
      Return !!this.Info.selColoumns[n]
   }
   
   GetSelectedColumns() {
      selected := []
      for k, v in this.Info.selColoumns
         (v && selected.Push(k))
      Return selected
   }
   
   class Events
   {
      WM_NOTIFY(Info, wp, lp) {
         static LVN_COLUMNCLICK := -108, NM_CLICK := -2
         hCtrl := NumGet(lp + 0)
         if !(hCtrl = Info.hLV)
            Return
         notify := NumGet(lp + A_PtrSize*2, "Int")
         Switch notify {
            case NM_CLICK        : this.OnRowClick(Info)
            case LVN_COLUMNCLICK : this.OnColumnClick(Info, lp)
         }
      }
      OnRowClick(Info) {
         isSelected := false
         for k, v in Info.selColoumns {
            if v {
               isSelected := true
               Info.selColoumns[k] := false
            }
         }
         if isSelected {
            Info.LV.Clear()
            WinSet, Redraw,, % "ahk_id" . Info.hLV
         }
      }
      OnColumnClick(Info, lp) {
         Gui, %A_Gui%: ListView, % Info.hLV
         clickedColumn := NumGet(lp + A_PtrSize*3 + 4, "Int") + 1
         
         while selectedRow := LV_GetNext()
            LV_Modify(selectedRow, "-Select")
         
         this[ GetKeyState("Ctrl", "P") ? "ToggleColumnSelState" : "SelectSingleColumn" ](Info, clickedColumn)
         WinSet, Redraw,, % "ahk_id" . Info.hLV
      }
      SelectSingleColumn(Info, column) {
         Info.LV.Clear()
         for k in Info.selColoumns
            Info.selColoumns[k] := false
         this.ToggleColumnSelState(Info, column)
      }
      ToggleColumnSelState(Info, column) {
         static LVM_GETITEMCOUNT := 0x1004
         isSelected := Info.selColoumns[column]
         Info.selColoumns[column] := !isSelected
         SendMessage, LVM_GETITEMCOUNT,,,, % "ahk_id" . Info.hLV
         Loop % ErrorLevel
            Info.LV.Cell(A_Index, column, isSelected ? "" : Info.backColor, isSelected ? "" : Info.textColor)
      }
   }
   
   __Delete() {
      this.Info.LV.Clear()
      OnMessage(0x004E, this.OnNotify, 0)
      WinSet, RedRaw,, % "ahk_id" . this.Info.hLV
      this.Info := ""
   }
}

Class LV_Colors {
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; META FUNCTIONS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; ===================================================================================================================
   ; __New()         Create a new LV_Colors instance for the given ListView
   ; Parameters:     HWND        -  ListView's HWND.
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 StaticMode  -  Static color assignment, i.e. the colors will be assigned permanently to the row
   ;                                contents rather than to the row number.
   ;                                Values:  True/False
   ;                                Default: False
   ;                 NoSort      -  Prevent sorting by click on a header item.
   ;                                Values:  True/False
   ;                                Default: True
   ;                 NoSizing    -  Prevent resizing of columns.
   ;                                Values:  True/False
   ;                                Default: True
   ; ===================================================================================================================
   __New(HWND, StaticMode := False, NoSort := True, NoSizing := True) {
      If (This.Base.Base.__Class) ; do not instantiate instances
         Return False
      If This.Attached[HWND] ; HWND is already attached
         Return False
      If !DllCall("IsWindow", "Ptr", HWND) ; invalid HWND
         Return False
      VarSetCapacity(Class, 512, 0)
      DllCall("GetClassName", "Ptr", HWND, "Str", Class, "Int", 256)
      If (Class <> "SysListView32") ; HWND doesn't belong to a ListView
         Return False
      ; ----------------------------------------------------------------------------------------------------------------
      ; Set LVS_EX_DOUBLEBUFFER (0x010000) style to avoid drawing issues.
      SendMessage, 0x1036, 0x010000, 0x010000, , % "ahk_id " . HWND ; LVM_SETEXTENDEDLISTVIEWSTYLE
      ; Get the default colors
      SendMessage, 0x1025, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTBKCOLOR
      This.BkClr := ErrorLevel
      SendMessage, 0x1023, 0, 0, , % "ahk_id " . HWND ; LVM_GETTEXTCOLOR
      This.TxClr := ErrorLevel
      ; Get the header control
      SendMessage, 0x101F, 0, 0, , % "ahk_id " . HWND ; LVM_GETHEADER
      This.Header := ErrorLevel
      ; Set other properties
      This.HWND := HWND
      This.IsStatic := !!StaticMode
      This.AltCols := False
      This.AltRows := False
      This.NoSort(!!NoSort)
      This.NoSizing(!!NoSizing)
      This.OnMessage()
      This.Critical := "Off"
      This.Attached[HWND] := True
   }
   ; ===================================================================================================================
   __Delete() {
      This.Attached.Remove(HWND, "")
      This.OnMessage(False)
      WinSet, Redraw, , % "ahk_id " . This.HWND
   }
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PUBLIC METHODS ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; ===================================================================================================================
   ; Clear()         Clears all row and cell colors.
   ; Parameters:     AltRows     -  Reset alternate row coloring (True / False)
   ;                                Default: False
   ;                 AltCols     -  Reset alternate column coloring (True / False)
   ;                                Default: False
   ; Return Value:   Always True.
   ; ===================================================================================================================
   Clear(AltRows := False, AltCols := False) {
      If (AltCols)
         This.AltCols := False
      If (AltRows)
         This.AltRows := False
      This.Remove("Rows")
      This.Remove("Cells")
      Return True
   }
   ; ===================================================================================================================
   ; AlternateRows() Sets background and/or text color for even row numbers.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   AlternateRows(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.AltRows := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["ARB"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["ART"] := (TxBGR <> "") ? TxBGR : This.TxClr
      This.AltRows := True
      Return True
   }
   ; ===================================================================================================================
   ; AlternateCols() Sets background and/or text color for even column numbers.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   AlternateCols(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.AltCols := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["ACB"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["ACT"] := (TxBGR <> "") ? TxBGR : This.TxClr
      This.AltCols := True
      Return True
   }
   ; ===================================================================================================================
   ; SelectionColors() Sets background and/or text color for selected rows.
   ; Parameters:     BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default selected background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default selected text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   SelectionColors(BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      This.SelColors := False
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["SELB"] := BkBGR
      This["SELT"] := TxBGR
      This.SelColors := True
      Return True
   }
   ; ===================================================================================================================
   ; Row()           Sets background and/or text color for the specified row.
   ; Parameters:     Row         -  Row number
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> default text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   Row(Row, BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      This["Rows"].Remove(Row, "")
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["Rows", Row, "B"] := (BkBGR <> "") ? BkBGR : This.BkClr
      This["Rows", Row, "T"] := (TxBGR <> "") ? TxBGR : This.TxClr
      Return True
   }
   ; ===================================================================================================================
   ; Cell()          Sets background and/or text color for the specified cell.
   ; Parameters:     Row         -  Row number
   ;                 Col         -  Column number
   ;                 Optional ------------------------------------------------------------------------------------------
   ;                 BkColor     -  Background color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> row's background color
   ;                 TxColor     -  Text color as RGB color integer (e.g. 0xFF0000 = red) or HTML color name.
   ;                                Default: Empty -> row's text color
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   Cell(Row, Col, BkColor := "", TxColor := "") {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      This["Cells", Row].Remove(Col, "")
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      If (BkBGR = "") && (TxBGR = "")
         Return False
      If (BkBGR <> "")
         This["Cells", Row, Col, "B"] := BkBGR
      If (TxBGR <> "")
         This["Cells", Row, Col, "T"] := TxBGR
      Return True
   }
   ; ===================================================================================================================
   ; NoSort()        Prevents/allows sorting by click on a header item for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   NoSort(Apply := True) {
      If !(This.HWND)
         Return False
      If (Apply)
         This.SortColumns := False
      Else
         This.SortColumns := True
      Return True
   }
   ; ===================================================================================================================
   ; NoSizing()      Prevents/allows resizing of columns for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   True on success, otherwise false.
   ; ===================================================================================================================
   NoSizing(Apply := True) {
      Static OSVersion := DllCall("GetVersion", "UChar")
      If !(This.Header)
         Return False
      If (Apply) {
         If (OSVersion > 5)
            Control, Style, +0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING = 0x0800
         This.ResizeColumns := False
      }
      Else {
         If (OSVersion > 5)
            Control, Style, -0x0800, , % "ahk_id " . This.Header ; HDS_NOSIZING
         This.ResizeColumns := True
      }
      Return True
   }
   ; ===================================================================================================================
   ; OnMessage()     Adds/removes a message handler for WM_NOTIFY messages for this ListView.
   ; Parameters:     Apply       -  True/False
   ;                                Default: True
   ; Return Value:   Always True
   ; ===================================================================================================================
   OnMessage(Apply := True) {
      If (Apply) && !This.HasKey("OnMessageFunc") {
         This.OnMessageFunc := ObjBindMethod(This, "On_WM_Notify")
         OnMessage(0x004E, This.OnMessageFunc) ; add the WM_NOTIFY message handler
      }
      Else If !(Apply) && This.HasKey("OnMessageFunc") {
         OnMessage(0x004E, This.OnMessageFunc, 0) ; remove the WM_NOTIFY message handler
         This.OnMessageFunc := ""
         This.Remove("OnMessageFunc")
      }
      WinSet, Redraw, , % "ahk_id " . This.HWND
      Return True
   }
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PRIVATE PROPERTIES  +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   Static Attached := {}
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; PRIVATE METHODS +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   ; +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   On_WM_NOTIFY(W, L, M, H) {
      ; Notifications: NM_CUSTOMDRAW = -12, LVN_COLUMNCLICK = -108, HDN_BEGINTRACKA = -306, HDN_BEGINTRACKW = -326
      Critical, % This.Critical
      If ((HCTL := NumGet(L + 0, 0, "UPtr")) = This.HWND) || (HCTL = This.Header) {
         Code := NumGet(L + (A_PtrSize * 2), 0, "Int")
         If (Code = -12)
            Return This.NM_CUSTOMDRAW(This.HWND, L)
         If !This.SortColumns && (Code = -108)
            Return 0
         If !This.ResizeColumns && ((Code = -306) || (Code = -326))
            Return True
      }
   }
   ; -------------------------------------------------------------------------------------------------------------------
   NM_CUSTOMDRAW(H, L) {
      ; Return values: 0x00 (CDRF_DODEFAULT), 0x20 (CDRF_NOTIFYITEMDRAW / CDRF_NOTIFYSUBITEMDRAW)
      Static SizeNMHDR := A_PtrSize * 3                  ; Size of NMHDR structure
      Static SizeNCD := SizeNMHDR + 16 + (A_PtrSize * 5) ; Size of NMCUSTOMDRAW structure
      Static OffItem := SizeNMHDR + 16 + (A_PtrSize * 2) ; Offset of dwItemSpec (NMCUSTOMDRAW)
      Static OffItemState := OffItem + A_PtrSize         ; Offset of uItemState  (NMCUSTOMDRAW)
      Static OffCT :=  SizeNCD                           ; Offset of clrText (NMLVCUSTOMDRAW)
      Static OffCB := OffCT + 4                          ; Offset of clrTextBk (NMLVCUSTOMDRAW)
      Static OffSubItem := OffCB + 4                     ; Offset of iSubItem (NMLVCUSTOMDRAW)
      ; ----------------------------------------------------------------------------------------------------------------
      DrawStage := NumGet(L + SizeNMHDR, 0, "UInt")
      , Row := NumGet(L + OffItem, "UPtr") + 1
      , Col := NumGet(L + OffSubItem, "Int") + 1
      , Item := Row - 1
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      ; CDDS_SUBITEMPREPAINT = 0x030001 --------------------------------------------------------------------------------
      If (DrawStage = 0x030001) {
         UseAltCol := !(Col & 1) && (This.AltCols)
         , ColColors := This["Cells", Row, Col]
         , ColB := (ColColors.B <> "") ? ColColors.B : UseAltCol ? This.ACB : This.RowB
         , ColT := (ColColors.T <> "") ? ColColors.T : UseAltCol ? This.ACT : This.RowT
         , NumPut(ColT, L + OffCT, "UInt"), NumPut(ColB, L + OffCB, "UInt")
         Return (!This.AltCols && !This.HasKey(Row) && (Col > This["Cells", Row].MaxIndex())) ? 0x00 : 0x20
      }
      ; CDDS_ITEMPREPAINT = 0x010001 -----------------------------------------------------------------------------------
      If (DrawStage = 0x010001) {
         ; LVM_GETITEMSTATE = 0x102C, LVIS_SELECTED = 0x0002
         If (This.SelColors) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt") {
            ; Remove the CDIS_SELECTED (0x0001) and CDIS_FOCUS (0x0010) states from uItemState and set the colors.
            NumPut(NumGet(L + OffItemState, "UInt") & ~0x0011, L + OffItemState, "UInt")
            If (This.SELB <> "")
               NumPut(This.SELB, L + OffCB, "UInt")
            If (This.SELT <> "")
               NumPut(This.SELT, L + OffCT, "UInt")
            Return 0x02 ; CDRF_NEWFONT
         }
         UseAltRow := (Item & 1) && (This.AltRows)
         , RowColors := This["Rows", Row]
         , This.RowB := RowColors ? RowColors.B : UseAltRow ? This.ARB : This.BkClr
         , This.RowT := RowColors ? RowColors.T : UseAltRow ? This.ART : This.TxClr
         If (This.AltCols || This["Cells"].HasKey(Row))
            Return 0x20
         NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt")
         Return 0x00
      }
      ; CDDS_PREPAINT = 0x000001 ---------------------------------------------------------------------------------------
      Return (DrawStage = 0x000001) ? 0x20 : 0x00
   }
   ; -------------------------------------------------------------------------------------------------------------------
   MapIndexToID(Row) { ; provides the unique internal ID of the given row number
      SendMessage, 0x10B4, % (Row - 1), 0, , % "ahk_id " . This.HWND ; LVM_MAPINDEXTOID
      Return ErrorLevel
   }
   ; -------------------------------------------------------------------------------------------------------------------
   BGR(Color, Default := "") { ; converts colors to BGR
      Static Integer := "Integer" ; v2
      ; HTML Colors (BGR)
      Static HTML := {AQUA: 0xFFFF00, BLACK: 0x000000, BLUE: 0xFF0000, FUCHSIA: 0xFF00FF, GRAY: 0x808080, GREEN: 0x008000
                    , LIME: 0x00FF00, MAROON: 0x000080, NAVY: 0x800000, OLIVE: 0x008080, PURPLE: 0x800080, RED: 0x0000FF
                    , SILVER: 0xC0C0C0, TEAL: 0x808000, WHITE: 0xFFFFFF, YELLOW: 0x00FFFF}
      If Color Is Integer
         Return ((Color >> 16) & 0xFF) | (Color & 0x00FF00) | ((Color & 0xFF) << 16)
      Return (HTML.HasKey(Color) ? HTML[Color] : Default)
   }
}
Last edited by teadrinker on 26 May 2022, 06:53, edited 2 times in total.

Post Reply

Return to “Ask for Help (v1)”