[Class] LV_Colors - 1.1.04.01 (2016-05-03)

Post your working scripts, libraries and tools
User avatar
JoeWinograd
Posts: 1249
Joined: 10 Feb 2014, 20:00

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

03 May 2016, 10:45

OK, thanks for the explanation. Good to know that it won't affect my current usage of LV_Colors for my Processing Console, which is an "output-only" LV, i.e., users never select rows on which to perform operations. Thanks again, Joe
hobboy
Posts: 41
Joined: 05 Jan 2016, 09:59

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

10 Jul 2016, 03:13

Thanks for the script just me, it's incredibly helpful

I have a suggested addition, what I wanted to do was toggle the colour of a row between on and off. All I did was change

Code: Select all

This["Rows"].Remove(Row, "")
to

Code: Select all

If (ToggleColor and This["Rows"].HasKey(Row))
{
   This["Rows"].Remove(Row, "")
   return true
}
This["Rows"].Remove(Row, "")
and add an optional parameter ToggleColor

Code: Select all

Row(Row, BkColor := "", TxColor := "", ToggleColor := false) {
      If !(This.HWND)
         Return False
      If This.IsStatic
         Row := This.MapIndexToID(Row)
      If (ToggleColor and This["Rows"].HasKey(Row))
      {
         This["Rows"].Remove(Row, "")
         return true
      }
      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
   }

Edit: changed code to use your function rather than a separate one.
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

10 Jul 2016, 03:47

Hi hobboy,

first of all, I cannot see the advantage of a separate method or an additional parameter. Are you using variadic method calls?
hobboy
Posts: 41
Joined: 05 Jan 2016, 09:59

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

10 Jul 2016, 03:56

just me wrote:first of all, I cannot see the advantage of a separate method or an additional parameter. Are you using variadic method calls?
No, I'm not using variadic method calls (not too familiar with them). Is there a way to do this toggle with the current version of your code that I missed? I use the toggle so the user can highlight important fields.
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

10 Jul 2016, 04:13

As far as I understand you want to remove the row even if you are passing colors. I think you can easily use an own function like this:

Code: Select all

ToggleRowColors(LVInstance, Row, BkColor, TxColor) {
   If LVInstance["Rows"].HasKey(Row)
      Return LVInstance.Row(Row)
   Return LV_Instance.Row(Row, BkColor, TxColor)
}
*Not tested!*
hobboy
Posts: 41
Joined: 05 Jan 2016, 09:59

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

10 Jul 2016, 04:35

That works great! Thanks again :)
hobboy
Posts: 41
Joined: 05 Jan 2016, 09:59

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

07 Aug 2016, 05:48

I've run into a weird problem. Whenever I activate a window before creating a gui with a listview, the gui doesn't seem to draw the highlighted rows (until selected).
Using

Code: Select all

GuiControl, +Redraw, %_lv_hwnd%
after showing the gui fixes the problem, but I'd like to know if I'm missing something here or it's a bug. if I don't activate a window then the rows are highlighted when the gui is shown.

Here's code which reproduces my problem, it requires notepad to be open.

Code: Select all

; requires notepad to be open

#Include ../../LibExt/Class_LVColors.ahk

WinActivate, ahk_class Notepad
WinWaitActive, ahk_class Notepad,,5

Gui, New, +Hwndgui_hwnd -SysMenu
Gui %gui_hwnd%: Add, ListView, w100 r15 Count500 Hwnd_lv_hwnd, index

_lv_colours := new LV_Colors(_lv_hwnd)

Loop 5
{
	LV_Add("", A_Index)
	_lv_colours.Row(A_Index, 0xFF0000)
}

Gui %gui_hwnd%: Show, % "x0 y0 autosize"
; this command correctly draws listview even after window activated
;~ GuiControl, +Redraw, %_lv_hwnd%

return

Esc::ExitApp 5
I'm using Win7 x64
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

07 Aug 2016, 08:58

It's a known problem. The GuiControl, +Redraw, ... is even part of the sample script on GitHub:

Code: Select all

...
Gui, Show, , ListView & Colors
; Redraw the ListView after the first Gui, Show command to show the colors, if any.
WinSet, Redraw, , ahk_id %HLV%
Prior to 1.1.22.05 (at least I think the changes belong to this version) it was needed almost always.
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

01 Sep 2016, 14:10

Should we be able to draw a border around the selected item using GDI+ within the NM_CUSTOMDRAW() when we are in the CDDS_ITEMPREPAINT part of the drawing? I'd think we could get the HDC and RECT to position a border rectangle or simply use DllCall("FrameRect",...). Does that sound right?

EDIT:
I was able to add this in your Class_OD_Colors code but I suppose that is a totally different mechanism...

Code: Select all

         If (State & ODS_SELECTED) {
            ; DllCall("User32.dll\DrawFocusRect", "Ptr", HDC, "Ptr", RECT)
		  FrameRect( hdc, RECT, 0xEE000000 )
	    }
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

02 Sep 2016, 01:55

Yes, they are different concepts.

In case of owner drawing you are expected to draw everything on your own. The control will draw nothing by itself.

LV_Colors() is using custom drawing by overwriting the default colors and lets the control do the drawing.
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

02 Sep 2016, 07:07

I'm wondering how they do it here then on a treeview... Quick Cliq ***Link downloads the source for the most recent version in a zip**

If you take a look in MenuTVBuilding.ahk in the GUI_Main_TV_CustomDraw() function, it seems they are using the similar message for treeviews (meaning not owner drawn) and are successfully drawing a border and arrow on the item.

https://msdn.microsoft.com/en-us/librar ... s.85).aspx

It may be that I'm just not drawing the border at the appropriate time though.
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

02 Sep 2016, 09:24

Well, I'm going to keep looking at this more but I think its just a matter of understanding the order of the different drawstages. But excluding any of the coloring and just looking at selected rows, I was able to mimic what Quick Cliq did for a treeview.

I could not get GDIP_GraphicsFromHDC() to work though. Just FrameRect().

Adjusted Class_LV_Colors:

Code: Select all

; ======================================================================================================================
; Namespace:      LV_Colors
; Function:       Individual row and cell coloring for AHK ListView controls.
; Tested with:    AHK 1.1.23.05 (A32/U32/U64)
; Tested on:      Win 10 (x64)
; Changelog:
;     1.1.04.01/2016-05-03/just me - added change to remove the focus rectangle from focused rows
;     1.1.04.00/2016-05-03/just me - added SelectionColors method
;     1.1.03.00/2015-04-11/just me - bugfix for StaticMode
;     1.1.02.00/2015-04-07/just me - bugfixes for StaticMode, NoSort, and NoSizing
;     1.1.01.00/2015-03-31/just me - removed option OnMessage from __New(), restructured code
;     1.1.00.00/2015-03-27/just me - added AlternateRows and AlternateCols, revised code.
;     1.0.00.00/2015-03-23/just me - new version using new AHK 1.1.20+ features
;     0.5.00.00/2014-08-13/just me - changed 'static mode' handling
;     0.4.01.00/2013-12-30/just me - minor bug fix
;     0.4.00.00/2013-12-30/just me - added static mode
;     0.3.00.00/2013-06-15/just me - added "Critical, 100" to avoid drawing issues
;     0.2.00.00/2013-01-12/just me - bugfixes and minor changes
;     0.1.00.00/2012-10-27/just me - initial release
; ======================================================================================================================
; CLASS LV_Colors
;
; The class provides six public methods to set individual colors for rows and/or cells, to clear all colors, to
; prevent/allow sorting and rezising of columns dynamically, and to deactivate/activate the message handler for
; WM_NOTIFY messages (see below).
;
; The message handler for WM_NOTIFY messages will be activated for the specified ListView whenever a new instance is
; created. If you want to temporarily disable coloring call MyInstance.OnMessage(False). This must be done also before
; you try to destroy the instance. To enable it again, call MyInstance.OnMessage().
;
; To avoid the loss of Gui events and messages the message handler might need to be set 'critical'. This can be
; achieved by setting the instance property 'Critical' ti the required value (e.g. MyInstance.Critical := 100).
; New instances default to 'Critical, Off'. Though sometimes needed, ListViews or the whole Gui may become
; unresponsive under certain circumstances if Critical is set and the ListView has a g-label.
; ======================================================================================================================
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)
	 
	 static CDDS_PREPAINT := 0x00000001
        ,CDRF_NOTIFYITEMDRAW := 0x00000020
        ,CDDS_ITEMPREPAINT := 0x00010001
        ,CDRF_NOTIFYPOSTPAINT := 0x00000010
        ,CDRF_DODEFAULT := 0
        ,CDRF_SKIPDEFAULT := 0x00000004
        ,CDDS_ITEMPOSTPAINT := 0x00010002
	   
      ; ----------------------------------------------------------------------------------------------------------------
      DrawStage := NumGet(L + SizeNMHDR, 0, "UInt")
      If This.IsStatic
         Row := This.MapIndexToID(Row)
	    
	 if (drawstage = CDDS_PREPAINT)
		return CDRF_NOTIFYITEMDRAW
		
     Row := NumGet(L + OffItem, "UPtr") + 1
     Col := NumGet(L + OffSubItem, "Int") + 1
     Item := Row - 1
	hdc := NumGet(L+0, 4*A_PtrSize, "UPtr")
	pRECT := L + 5*A_PtrSize
	left := NumGet( pRECT + 0, 0, "UInt" )
	top := NumGet( pRECT + 0, 4, "UInt" )
	right := NumGet( pRECT + 0, 8, "UInt" )
	bottom := NumGet( pRECT + 0, 12, "UInt" )
	  if ( drawstage = CDDS_ITEMPREPAINT ) {
		; If row is selected.
		if (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 CDRF_NOTIFYPOSTPAINT
	  }
		if ( drawstage == CDDS_ITEMPOSTPAINT )
		{
			if (DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt"))
			{
				; Adjust the left and bottom edges of the bounding rectangle to frame.
				NumPut(left + 3, pRECT+0, "UInt")
				NumPut(bottom - 1, pRECT+12, "UInt")
				FrameRect( hdc, pRECT, 0xFFD199 )
				; G := gdip_GraphicsFromHDC(hdc)
				; pPen := Gdip_CreatePen(0x000000, 2)
				; Gdip_DrawRectangle(G, pPen, left + 2, top, right-left-2, bottom-top)
				arrHeight := round((bottom-top)*0.8)
				arrY := top+(bottom-top-arrHeight)/2
				Gdip_DrawArrow( hdc, right-15,arrY, 15, arrHeight, 0x000000, "right" )
			}
		}
	return CDRF_DODEFAULT
      ; 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) ? 0x220 : 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)
   }
}

#Include gdip.ahk
GDIP:

Code: Select all

Gdip_Startup()
{
	static hmodule
	if ( !hmodule || !DllCall( "GetModuleHandleW", "Wstr", "gdiplus", "UPtr" ) )
        hmodule := DllCall( "LoadLibraryW", "Wstr", "gdiplus", "UPtr" )
	
	VarSetCapacity(GdiplusStartupInput , 3*A_PtrSize, 0), NumPut(1,GdiplusStartupInput ,0,"UInt") ; GdiplusVersion = 1
	DllCall("gdiplus\GdiplusStartup", "Ptr*", pToken, "Ptr", &GdiplusStartupInput, "Ptr", 0)
	return pToken
}

Gdip_Shutdown(pToken)
{
	DllCall("gdiplus\GdiplusShutdown", "Ptr", pToken)
	return 0
}

Gdip_CreateBitmap(Width, Height, Format=0x26200A)
{
    DllCall("gdiplus\GdipCreateBitmapFromScan0", "int", Width, "int", Height, "int", 0, "int", Format, "Ptr", 0, "Ptr*", pBitmap)
    Return pBitmap
}

Gdip_GraphicsFromImage(pBitmap)
{
    DllCall("gdiplus\GdipGetImageGraphicsContext", "Ptr", pBitmap, "Ptr*", pGraphics)
    return pGraphics
}

Gdip_SetSmoothingMode(pGraphics, SmoothingMode)
{
   return DllCall("gdiplus\GdipSetSmoothingMode", "Ptr", pGraphics, "int", SmoothingMode)
}

Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
{
   return DllCall("gdiplus\GdipFillRectangle", "Ptr", pGraphics, "Ptr", pBrush
   , "float", x, "float", y, "float", w, "float", h)
}

Gdip_FillRoundedRectangle(pGraphics, pBrush, x, y, w, h, r)
{
	Region := Gdip_GetClipRegion(pGraphics)
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_FillRectangle(pGraphics, pBrush, x, y, w, h)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_FillEllipse(pGraphics, pBrush, x, y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y, 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x, y+h-(2*r), 2*r, 2*r)
	Gdip_FillEllipse(pGraphics, pBrush, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_SetClipRegion(pGraphics, Region, 0)
	Gdip_DeleteRegion(Region)
	return E
}

Gdip_SetClipRegion(pGraphics, Region, CombineMode=0)
{
	return DllCall("gdiplus\GdipSetClipRegion", "Ptr", pGraphics, "Ptr", Region, "uint", CombineMode)
}

Gdip_CreateRegion()
{
	DllCall("gdiplus\GdipCreateRegion", "Ptr*", Region)
	return Region
}

Gdip_GetClipRegion(pGraphics)
{
	Region := Gdip_CreateRegion()
	DllCall("gdiplus\GdipGetClip", "Ptr" pGraphics, "Ptr*", Region)
	return Region
}

Gdip_SetClipRect(pGraphics, x, y, w, h, CombineMode=0)
{
   return DllCall("gdiplus\GdipSetClipRect", "Ptr", pGraphics, "float", x, "float", y, "float", w, "float", h, "int", CombineMode)
}

Gdip_FillEllipse(pGraphics, pBrush, x, y, w, h)
{
	return DllCall("gdiplus\GdipFillEllipse", "Ptr", pGraphics, "Ptr", pBrush, "float", x, "float", y, "float", w, "float", h)
}

Gdip_DeleteRegion(Region)
{
	return DllCall("gdiplus\GdipDeleteRegion", "Ptr", Region)
}

Gdip_TextToGraphics(pGraphics, Text, Options, Font="Arial", Width="", Height="", Measure=0)
{
	IWidth := Width, IHeight:= Height
	
	RegExMatch(Options, "i)X([\-\d\.]+)(p*)", xpos)
	RegExMatch(Options, "i)Y([\-\d\.]+)(p*)", ypos)
	RegExMatch(Options, "i)W([\-\d\.]+)(p*)", Width)
	RegExMatch(Options, "i)H([\-\d\.]+)(p*)", Height)
	RegExMatch(Options, "i)C(?!(entre|enter))([a-f\d]+)", Colour)
	RegExMatch(Options, "i)Top|Up|Bottom|Down|vCentre|vCenter", vPos)
	RegExMatch(Options, "i)NoWrap", NoWrap)
	RegExMatch(Options, "i)R(\d)", Rendering)
	RegExMatch(Options, "i)S(\d+)(p*)", Size)

	if !Gdip_DeleteBrush(Gdip_CloneBrush(Colour2))
		PassBrush := 1, pBrush := Colour2
	
	if !(IWidth && IHeight) && (xpos2 || ypos2 || Width2 || Height2 || Size2)
		return -1

	Style := 0, Styles := "Regular|Bold|Italic|BoldItalic|Underline|Strikeout"
	Loop, Parse, Styles, |
	{
		if RegExMatch(Options, "\b" A_loopField)
		Style |= (A_LoopField != "StrikeOut") ? (A_Index-1) : 8
	}
  
	Align := 0, Alignments := "Near|Left|Centre|Center|Far|Right"
	Loop, Parse, Alignments, |
	{
		if RegExMatch(Options, "\b" A_loopField)
			Align |= A_Index//2.1      ; 0|0|1|1|2|2
	}

	xpos := (xpos1 != "") ? xpos2 ? IWidth*(xpos1/100) : xpos1 : 0
	ypos := (ypos1 != "") ? ypos2 ? IHeight*(ypos1/100) : ypos1 : 0
	Width := Width1 ? Width2 ? IWidth*(Width1/100) : Width1 : IWidth
	Height := Height1 ? Height2 ? IHeight*(Height1/100) : Height1 : IHeight
	if !PassBrush
		Colour := "0x" (Colour2 ? Colour2 : "ff000000")
	Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
	Size := (Size1 > 0) ? Size2 ? IHeight*(Size1/100) : Size1 : 12

	hFamily := Gdip_FontFamilyCreate(Font)
	hFont := Gdip_FontCreate(hFamily, Size, Style)
	FormatStyle := NoWrap ? 0x4000 | 0x1000 : 0x4000
	hFormat := Gdip_StringFormatCreate(FormatStyle)
	pBrush := PassBrush ? pBrush : Gdip_BrushCreateSolid(Colour)
	if !(hFamily && hFont && hFormat && pBrush && pGraphics)
		return !pGraphics ? -2 : !hFamily ? -3 : !hFont ? -4 : !hFormat ? -5 : !pBrush ? -6 : 0
   
	CreateRectF(RC, xpos, ypos, Width, Height)
	Gdip_SetStringFormatAlign(hFormat, Align)
	Gdip_SetTextRenderingHint(pGraphics, Rendering)
	ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)

	if vPos
	{
		StringSplit, ReturnRC, ReturnRC, |
		
		if (vPos = "vCentre") || (vPos = "vCenter")
			ypos += (Height-ReturnRC4)//2
		else if (vPos = "Top") || (vPos = "Up")
			ypos := 0
		else if (vPos = "Bottom") || (vPos = "Down")
			ypos := Height-ReturnRC4
		
		CreateRectF(RC, xpos, ypos, Width, ReturnRC4)
		ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
	}

	if !Measure
		E := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)

	if !PassBrush
		Gdip_DeleteBrush(pBrush)
	Gdip_DeleteStringFormat(hFormat)   
	Gdip_DeleteFont(hFont)
	Gdip_DeleteFontFamily(hFamily)
	return E ? E : ReturnRC
}

Gdip_DrawString(pGraphics, sString, hFont, hFormat, pBrush, ByRef RectF)
{
	if !A_IsUnicode
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "Ptr", &sString, "int", -1, "Ptr", 0, "int", 0)
		VarSetCapacity(wString, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "Ptr", &sString, "int", -1, "Ptr", &wString, "int", nSize)
		return DllCall("gdiplus\GdipDrawString", "Ptr", pGraphics
		, "Ptr", &wString, "int", -1, "Ptr", hFont, "Ptr", &RectF, "Ptr", hFormat, "Ptr", pBrush)
	}
	else
	{
		return DllCall("gdiplus\GdipDrawString", "Ptr", pGraphics
		, "Ptr", &sString, "int", -1, "Ptr", hFont, "Ptr", &RectF, "Ptr", hFormat, "Ptr", pBrush)
	}	
}

Gdip_MeasureString(pGraphics, sString, hFont, hFormat, ByRef RectF)
{
	VarSetCapacity(RC, 16)
	if !A_IsUnicode
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "Ptr", &sString, "int", -1, "Ptr", 0, "int", 0)
		VarSetCapacity(wString, nSize*2)   
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "Ptr", &sString, "int", -1, "Ptr", &wString, "int", nSize)
		DllCall("gdiplus\GdipMeasureString", "Ptr", pGraphics
		, "Ptr", &wString, "int", -1, "Ptr", hFont, "Ptr", &RectF, "Ptr", hFormat, "Ptr", &RC, "uint*", Chars, "uint*", Lines)
	}
	else
	{
		DllCall("gdiplus\GdipMeasureString", "Ptr", pGraphics
		, "Ptr", &sString, "int", -1, "Ptr", hFont, "Ptr", &RectF, "Ptr", hFormat, "Ptr", &RC, "uint*", Chars, "uint*", Lines)
	}
	return &RC ? NumGet(RC, 0, "float") "|" NumGet(RC, 4, "float") "|" NumGet(RC, 8, "float") "|" NumGet(RC, 12, "float") "|" Chars "|" Lines : 0
}

Gdip_SetTextRenderingHint(pGraphics, RenderingHint)
{
	return DllCall("gdiplus\GdipSetTextRenderingHint", "Ptr", pGraphics, "int", RenderingHint)
}

Gdip_SetStringFormatAlign(hFormat, Align)
{
   return DllCall("gdiplus\GdipSetStringFormatAlign", "Ptr", hFormat, "int", Align)
}

CreateRectF(ByRef RectF, x, y, w, h)
{
   VarSetCapacity(RectF, 16)
   NumPut(x, RectF, 0, "float"), NumPut(y, RectF, 4, "float"), NumPut(w, RectF, 8, "float"), NumPut(h, RectF, 12, "float")
}

/* StringFormatFlagsDirectionRightToLeft    = 0x00000001,
StringFormatFlagsDirectionVertical       = 0x00000002,
StringFormatFlagsNoFitBlackBox           = 0x00000004,
StringFormatFlagsDisplayFormatControl    = 0x00000020,
StringFormatFlagsNoFontFallback          = 0x00000400,
StringFormatFlagsMeasureTrailingSpaces   = 0x00000800,
StringFormatFlagsNoWrap                  = 0x00001000,
StringFormatFlagsLineLimit               = 0x00002000,
StringFormatFlagsNoClip                  = 0x00004000 
 */
Gdip_StringFormatCreate(Format=0, Lang=0)
{
   DllCall("gdiplus\GdipCreateStringFormat", "int", Format, "int", Lang, "Ptr*", hFormat)
   return hFormat
}

Gdip_FontCreate(hFamily, Size, Style=0)
{
   DllCall("gdiplus\GdipCreateFont", "Ptr", hFamily, "float", Size, "int", Style, "int", 0, "Ptr*", hFont)
   return hFont
}

Gdip_FontFamilyCreate(Font)
{
	if !A_IsUnicode
	{
		nSize := DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "Ptr", &Font, "int", -1, "Ptr", 0, "int", 0)
		VarSetCapacity(wFont, nSize*2)
		DllCall("MultiByteToWideChar", "uint", 0, "uint", 0, "Ptr", &Font, "int", -1, "Ptr", &wFont, "int", nSize)
		DllCall("gdiplus\GdipCreateFontFamilyFromName", "Ptr", &wFont, "Ptr", 0, "Ptr*", hFamily)
	}
	else
		DllCall("gdiplus\GdipCreateFontFamilyFromName", "Ptr", &Font, "Ptr", 0, "Ptr*", hFamily)
	return hFamily
}

Gdip_CreateHBITMAPFromBitmap(pBitmap, Background=0xffffffff)
{
	DllCall("gdiplus\GdipCreateHBITMAPFromBitmap", "Ptr", pBitmap, "Ptr*", hbm, "int", Background)
	return hbm
}

SetImage(hwnd, hBitmap)
{
	SendMessage, 0x172, 0x0, hBitmap,, ahk_id %hwnd%
	E := ErrorLevel
	DeleteObject(E)
	return E
}

DeleteObject( hObj )
{
  return DllCall( "DeleteObject", "Ptr", hObj )
}

SelectObject( hDC, hObj )
{
  return DllCall( "SelectObject", "Ptr", hDC, "Ptr", hObj )
}

GetDC( hwnd = 0 )
{
  return DllCall( "GetDC", "Ptr", hwnd )
}

GetTextExtentPoint32( hDC, string )
{
  VarSetCapacity( pSize, 8, 0 )
  DllCall( "GetTextExtentPoint32W", "Ptr", hDC, "Ptr", &string, "UInt", StrLen( string ), "Ptr", &pSize )
  size := object()
  size[ "cx" ] := NumGet( &pSize, 0, "UInt" )
  size[ "cy" ] := NumGet( &pSize, 4, "UInt" )
  return size
}

ExcludeClipRect( hDC, left, top, right, bottom )
{
  return DllCall( "ExcludeClipRect"
          , "Ptr", hDC
          , "Int", left
          , "Int", top
          , "Int", right
          , "Int", bottom )
}

SetBkColor( hDC, clr )
{
  return DllCall( "SetBkColor", "Ptr", hDC, "UInt", clr )
}

FrameRect( hDC, pRect, clr )
{
  ret := DllCall( "FrameRect"
                , "Ptr", hDC
                , "Ptr", pRECT
                , "Ptr", hBrush := CreateSolidBrush( clr ) )
  DeleteObject( hBrush )
  return ret
}

InflateRect( pRECT, x, y )
{
  return DllCall( "InflateRect", "Ptr", pRECT, "int", x, "int", y )
}

DrawEdge( hDC, pRECT )
{
  return DllCall( "DrawEdge"
                , "Ptr", hDC
                , "Ptr", pRECT
                , "UInt", (0x0002 | 0x0004)
                , "UInt", 0x0002 )
}

SetTextColor( hDC, clr )
{
  return DllCall( "SetTextColor", "Ptr", hDC, "UInt", clr )
}

DeleteDC( hDC )
{
  return DllCall( "DeleteDC", "Ptr", hDC )
}

ReleaseDC( hDC, hWnd = 0 )
{
  return DllCall( "ReleaseDC", "Ptr", hWnd, "Ptr", hDC )
}

BitBlt( hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, dwRop )
{
  return DllCall( "BitBlt"
                , "Ptr", hdcDest
                , "UInt",nXDest
        , "UInt",nYDest
        , "UInt",nWidth
        , "UInt",nHeight
        , "Ptr", hdcSrc
        , "UInt",nXSrc
        , "UInt",nYSrc
        , "UInt",dwRop )
}

FillRect( hDC, pRECT, Clr )
{
  ret := DllCall( "FillRect", "Ptr", hDC, "Ptr", pRECT, "Ptr", hBrush := CreateSolidBrush( Clr ) )
  DeleteObject( hBrush )
  return ret
}

CreateCompatibleDC( hDC )
{
  return DllCall( "CreateCompatibleDC", "Ptr", hDC )
}

CreateCompatibleBitmap( hDC, w, h )
{
  return DllCall( "CreateCompatibleBitmap", "Ptr", hDC, "UInt", w, "Uint", h )
}

SetRect( ByRef rect, left, top, right, bottom )
{
  VarSetCapacity( rect, 16, 0 )
  return DllCall( "SetRect", "Ptr", &rect, "UInt", left, "UInt", top, "UInt", right, "UInt", bottom )
}

DrawFrameControl( hDC, pRECT, uType, uState )
{
  return DllCall( "DrawFrameControl", "Ptr", hDC, "Ptr", pRECT, "UInt", uType, "UInt", uState )
}

GetSysColorBrush( nIndex )
{
  return DllCall( "GetSysColorBrush", "UInt", nIndex )
}

CreateSolidBrush( clr )
{
  return DllCall( "CreateSolidBrush", "Uint", clr )
}

CreatePen( width, color, style=0 )  ;0 means solid
{
  return DllCall( "CreatePen", "int", style, "int", width, "UInt", color, "UPtr" )
}

GetObject( hObj,ByRef buf )
{
  if bufSize := DllCall( "GetObject", "Ptr", hObj, "UInt", 0, "Ptr", 0 )
  {
    VarSetCapacity( buf, bufSize, 0 )
    DllCall( "GetObject", "Ptr", hObj, "UInt", bufSize, "Ptr", &buf )
  }
  else
    return 0
  return 1
}

PatBlt( hDC, clr, rect )
{
  hBrush := CreateSolidBrush( clr )
  hOldBrush := SelectObject( hDC, hBrush )
  if IsObject( rect )
    x := rect.left, y := rect.top, w := rect.right - rect.left, h := rect.bottom - rect.top
  else if IsInteger( rect )
  {
    x := NumGet( rect+0, 0, "UInt" )
    y := NumGet( rect+0, 4, "UInt" )
    w := NumGet( rect+0, 8, "UInt" ) - x
    h := NumGet( rect+0, 12, "UInt" ) - y
  }
  else
    return 0
  ret := DllCall( "PatBlt", "Ptr", hDC, "int", x, "int", y, "int", w, "int", h, "Uint", 0x005A0049 )
  SelectObject( hDC, hOldBrush )
  DeleteObject( hBrush )
  return ret
}

Polyline( hDC, arrPOINT )
{
  if !IsObject( arrPOINT )
    return 0
  points_num := arrPOINT.MaxIndex()
  VarSetCapacity( sPOINTS, 8*points_num, 0 )
  for i,point in arrPOINT
  {
    NumPut( point.x, sPOINTS, 4*( A_Index*2 - 2 ), "UInt" )
    NumPut( point.y, sPOINTS, 4*( A_Index*2 - 1 ), "UInt" )
  }
  return DllCall( "Polyline", "Ptr", hDC, "Ptr", &sPOINTS, "Int", points_num )
}

DrawText( hDC, text, pRect, flags )
{
  return DllCall( "DrawTextExW"
                  ,"Ptr", hDC
                  , "wstr", text
                  , "Uint", -1
                  , "Ptr", pRect
                  , "Uint", flags
                  , "Ptr", 0 )
}

;#####################################################################################

; Function				CreateDIBSection
; Description			The CreateDIBSection function creates a DIB (Device Independent Bitmap) that applications can write to directly
;
; w						width of the bitmap to create
; h						height of the bitmap to create
; hdc					a handle to the device context to use the palette from
; bpp					bits per pixel (32 = ARGB)
; ppvBits				A pointer to a variable that receives a pointer to the location of the DIB bit values
;
; return				returns a DIB. A gdi bitmap
;
; notes					ppvBits will receive the location of the pixels in the DIB

CreateDIBSection(w, h, hdc="", bpp=32, ByRef ppvBits=0)
{
	hdc2 := hdc ? hdc : GetDC()
	VarSetCapacity(bi, 40, 0)
	NumPut(w, bi, 4, "UInt" ), NumPut(h, bi, 8, "UInt" ), NumPut(40, bi, 0, "UInt" ), NumPut(1, bi, 12, "ushort"), NumPut(0, bi, 16, "UInt" ), NumPut(bpp, bi, 14, "ushort")
	hbm := DllCall("CreateDIBSection", "Ptr" , hdc2, "Ptr" , &bi, "uint" , 0, "Ptr*", ppvBits, "Ptr" , 0, "uint" , 0)

	if !hdc
		ReleaseDC(hdc2)
	return hbm
}

;#####################################################################################

; Function				Gdip_GraphicsFromHDC
; Description			This function gets the graphics from the handle to a device context
;
; hdc					This is the handle to the device context
;
; return				returns a pointer to the graphics of a bitmap
;
; notes					You can draw a bitmap into the graphics of another bitmap

Gdip_GraphicsFromHDC( hdc )
{
    DllCall("gdiplus\GdipCreateFromHDC", "Ptr", hdc, "Ptr*", pGraphics)
    return pGraphics
}

GdipCreateFontFromLogfont( hdc, logfont )
{
	DllCall( "gdiplus\GdipCreateFontFromLogfont", "ptr", hdc, "ptr", &logfont, "ptr*", hFont )
	return hFont
}

GdipCreateFontFromDC( hdc )
{
	DllCall( "gdiplus\GdipCreateFontFromDC", "ptr", hdc, "ptr*", hFont )
	return hFont
}

CreatePointF(ByRef PointF, x, y)
{
   VarSetCapacity(PointF, 8)
   NumPut(x, PointF, 0, "float"), NumPut(y, PointF, 4, "float")     
}

/*   
DashStyleSolid        = 0,
DashStyleDash         = 1,
DashStyleDot          = 2,
DashStyleDashDot      = 3,
DashStyleDashDotDot   = 4,
DashStyleCustom       = 5  
*/
GdipSetPenDashStyle( pPen, dashstyle )
{
	return DllCall( "gdiplus\GdipSetPenDashStyle", "ptr", pPen, "UInt", dashstyle )
}

;#####################################################################################

; Function				Gdip_DrawRectangle
; Description			This function uses a pen to draw the outline of a rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle
; y						y-coordinate of the top left of the rectangle
; w						width of the rectanlge
; h						height of the rectangle
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
{
   return DllCall("gdiplus\GdipDrawRectangle", "ptr", pGraphics, "ptr", pPen, "float", x, "float", y, "float", w, "float", h)
}

;#####################################################################################

; Function				Gdip_DrawRoundedRectangle
; Description			This function uses a pen to draw the outline of a rounded rectangle into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rounded rectangle
; y						y-coordinate of the top left of the rounded rectangle
; w						width of the rectanlge
; h						height of the rectangle
; r						radius of the rounded corners
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawRoundedRectangle(pGraphics, pPen, x, y, w, h, r)
{
	Gdip_SetClipRect(pGraphics, x-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x-r, y+h-r, 2*r, 2*r, 4)
	Gdip_SetClipRect(pGraphics, x+w-r, y+h-r, 2*r, 2*r, 4)
	E := Gdip_DrawRectangle(pGraphics, pPen, x, y, w, h)
	Gdip_ResetClip(pGraphics)
	Gdip_SetClipRect(pGraphics, x-(2*r), y+r, w+(4*r), h-(2*r), 4)
	Gdip_SetClipRect(pGraphics, x+r, y-(2*r), w-(2*r), h+(4*r), 4)
	Gdip_DrawEllipse(pGraphics, pPen, x, y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y, 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x, y+h-(2*r), 2*r, 2*r)
	Gdip_DrawEllipse(pGraphics, pPen, x+w-(2*r), y+h-(2*r), 2*r, 2*r)
	Gdip_ResetClip(pGraphics)
	return E
}

;#####################################################################################

; Function				Gdip_DrawEllipse
; Description			This function uses a pen to draw the outline of an ellipse into the Graphics of a bitmap
;
; pGraphics				Pointer to the Graphics of a bitmap
; pPen					Pointer to a pen
; x						x-coordinate of the top left of the rectangle the ellipse will be drawn into
; y						y-coordinate of the top left of the rectangle the ellipse will be drawn into
; w						width of the ellipse
; h						height of the ellipse
;
; return				status enumeration. 0 = success
;
; notes					as all coordinates are taken from the top left of each pixel, then the entire width/height should be specified as subtracting the pen width

Gdip_DrawEllipse(pGraphics, pPen, x, y, w, h)
{
   return DllCall("gdiplus\GdipDrawEllipse", "ptr", pGraphics, "ptr", pPen, "float", x, "float", y, "float", w, "float", h)
}

Gdip_ResetClip(pGraphics)
{
   return DllCall("gdiplus\GdipResetClip", "ptr", pGraphics)
}

;#####################################################################################
; Create resources
;#####################################################################################

Gdip_CreatePen(ARGB, w)
{
   DllCall("gdiplus\GdipCreatePen1", "int", ARGB, "float", w, "int", 2, "Ptr*", pPen)
   return pPen
}

;#####################################################################################

Gdip_CreatePenFromBrush(pBrush, w)
{
	DllCall("gdiplus\GdipCreatePen2", "Ptr", pBrush, "float", w, "int", 2, "Ptr*", pPen)
	return pPen
}

;#####################################################################################

Gdip_BrushCreateSolid(ARGB=0xff000000)
{
	DllCall("gdiplus\GdipCreateSolidFill", "int", ARGB, "Ptr*", pBrush)
	return pBrush
}

;#####################################################################################

; HatchStyleHorizontal = 0
; HatchStyleVertical = 1
; HatchStyleForwardDiagonal = 2
; HatchStyleBackwardDiagonal = 3
; HatchStyleCross = 4
; HatchStyleDiagonalCross = 5
; HatchStyle05Percent = 6
; HatchStyle10Percent = 7
; HatchStyle20Percent = 8
; HatchStyle25Percent = 9
; HatchStyle30Percent = 10
; HatchStyle40Percent = 11
; HatchStyle50Percent = 12
; HatchStyle60Percent = 13
; HatchStyle70Percent = 14
; HatchStyle75Percent = 15
; HatchStyle80Percent = 16
; HatchStyle90Percent = 17
; HatchStyleLightDownwardDiagonal = 18
; HatchStyleLightUpwardDiagonal = 19
; HatchStyleDarkDownwardDiagonal = 20
; HatchStyleDarkUpwardDiagonal = 21
; HatchStyleWideDownwardDiagonal = 22
; HatchStyleWideUpwardDiagonal = 23
; HatchStyleLightVertical = 24
; HatchStyleLightHorizontal = 25
; HatchStyleNarrowVertical = 26
; HatchStyleNarrowHorizontal = 27
; HatchStyleDarkVertical = 28
; HatchStyleDarkHorizontal = 29
; HatchStyleDashedDownwardDiagonal = 30
; HatchStyleDashedUpwardDiagonal = 31
; HatchStyleDashedHorizontal = 32
; HatchStyleDashedVertical = 33
; HatchStyleSmallConfetti = 34
; HatchStyleLargeConfetti = 35
; HatchStyleZigZag = 36
; HatchStyleWave = 37
; HatchStyleDiagonalBrick = 38
; HatchStyleHorizontalBrick = 39
; HatchStyleWeave = 40
; HatchStylePlaid = 41
; HatchStyleDivot = 42
; HatchStyleDottedGrid = 43
; HatchStyleDottedDiamond = 44
; HatchStyleShingle = 45
; HatchStyleTrellis = 46
; HatchStyleSphere = 47
; HatchStyleSmallGrid = 48
; HatchStyleSmallCheckerBoard = 49
; HatchStyleLargeCheckerBoard = 50
; HatchStyleOutlinedDiamond = 51
; HatchStyleSolidDiamond = 52
; HatchStyleTotal = 53
Gdip_BrushCreateHatch(ARGBfront, ARGBback, HatchStyle=0)
{
	DllCall("gdiplus\GdipCreateHatchBrush", "int", HatchStyle, "int", ARGBfront, "int", ARGBback, "Ptr*", pBrush)
	return pBrush
}

;#####################################################################################

Gdip_CreateTextureBrush(pBitmap, WrapMode=1, x=0, y=0, w="", h="")
{
	if !(w && h)
		DllCall("gdiplus\GdipCreateTexture", "Ptr", pBitmap, "int", WrapMode, "Ptr*", pBrush)
	else
		DllCall("gdiplus\GdipCreateTexture2", "Ptr", pBitmap, "int", WrapMode, "float", x, "float", y, "float", w, "float", h, "Ptr*", pBrush)
	return pBrush
}

;#####################################################################################

; WrapModeTile = 0
; WrapModeTileFlipX = 1
; WrapModeTileFlipY = 2
; WrapModeTileFlipXY = 3
; WrapModeClamp = 4
Gdip_CreateLineBrush(x1, y1, x2, y2, ARGB1, ARGB2, WrapMode=1)
{
	CreatePointF(PointF1, x1, y1), CreatePointF(PointF2, x2, y2)
	DllCall("gdiplus\GdipCreateLineBrush", "Ptr", &PointF1, "Ptr", &PointF2, "int", ARGB1, "int", ARGB2, "int", WrapMode, "Ptr*", LGpBrush)
	return LGpBrush
}

;#####################################################################################

; LinearGradientModeHorizontal = 0
; LinearGradientModeVertical = 1
; LinearGradientModeForwardDiagonal = 2
; LinearGradientModeBackwardDiagonal = 3
Gdip_CreateLineBrushFromRect(x, y, w, h, ARGB1, ARGB2, LinearGradientMode=1, WrapMode=1)
{
	CreateRectF(RectF, x, y, w, h)
	DllCall("gdiplus\GdipCreateLineBrushFromRect", "Ptr", &RectF, "int", ARGB1, "int", ARGB2, "int", LinearGradientMode, "int", WrapMode, "Ptr*", LGpBrush)
	return LGpBrush
}

;#####################################################################################

Gdip_CloneBrush(pBrush)
{
	DllCall("gdiplus\GdipCloneBrush", "Ptr", pBrush, "Ptr*", pBrushClone)
	return pBrushClone
}

;#####################################################################################
; Delete resources
;#####################################################################################

Gdip_DeletePen(pPen)
{
   return DllCall("gdiplus\GdipDeletePen", "Ptr", pPen)
}

;#####################################################################################

Gdip_DeleteBrush(pBrush)
{
   return DllCall("gdiplus\GdipDeleteBrush", "Ptr", pBrush)
}

;#####################################################################################

Gdip_DisposeImage(pBitmap)
{
   return DllCall("gdiplus\GdipDisposeImage", "Ptr", pBitmap)
}

;#####################################################################################

Gdip_DeleteGraphics(pGraphics)
{
   return DllCall("gdiplus\GdipDeleteGraphics", "Ptr", pGraphics)
}

;#####################################################################################

Gdip_DisposeImageAttributes(ImageAttr)
{
	return DllCall("gdiplus\GdipDisposeImageAttributes", "Ptr", ImageAttr)
}

;#####################################################################################

Gdip_DeleteFont(hFont)
{
   return DllCall("gdiplus\GdipDeleteFont", "Ptr", hFont)
}

;#####################################################################################

Gdip_DeleteStringFormat(hFormat)
{
   return DllCall("gdiplus\GdipDeleteStringFormat", "Ptr", hFormat)
}

;#####################################################################################

Gdip_DeleteFontFamily(hFamily)
{
   return DllCall("gdiplus\GdipDeleteFontFamily", "Ptr", hFamily)
}

;#####################################################################################

Gdip_DeleteMatrix(Matrix)
{
   return DllCall("gdiplus\GdipDeleteMatrix", "Ptr", Matrix)
}

;~ https://msdn.microsoft.com/en-us/library/windows/desktop/dd162480%28v=vs.85%29.aspx
Gdip_DrawArrow( hDC, x,y, width, height, clr, type = "left" )
{
	bmWidth := width
	bmHeight := height
	bmY := y
	bmX := x
	
	;drawing arrow in the colors we need
	arrowDC := CreateCompatibleDC( hDC )
	fillDC := CreateCompatibleDC( hDC )
	arrowBM := CreateCompatibleBitmap( hDC, bmWidth, bmHeight )
	fillBM := CreateCompatibleBitmap( hDC, bmWidth, bmHeight )
	oldArrowBitmap := SelectObject( arrowDC, arrowBM )
	oldFillBitmap := SelectObject( fillDC, fillBM )
	;Set the offscreen arrow rect
	SetRect( tmpArrowR, 0, 0, bmWidth, bmHeight )
	;Draw the frame control arrow (The OS draws this as a black on
	;                            white bitmap mask)
	DrawFrameControl( arrowDC, &tmpArrowR, 2, type == "left" ? 0 : 4 )
	FillRect( fillDC, &tmpArrowR, clr )
	;Blit the items in a masking fashion
	BitBlt( hDC, bmX, bmY, bmWidth, bmHeight, fillDC, 0, 0, 0x00660046 )
	BitBlt( hDC, bmX, bmY, bmWidth, bmHeight, arrowDC, 0, 0, 0x008800C6 )
	BitBlt( hDC, bmX, bmY, bmWidth, bmHeight, fillDC, 0, 0, 0x00660046 )
	
	SelectObject( arrowDC, oldArrowBitmap )
	SelectObject( fillDC, oldFillBitmap )
	DeleteObject( arrowBM )
	DeleteObject( fillBM )
	DeleteDC( arrowDC )
	DeleteDC( fillDC )
	return 0
}

  IsInteger( var ) {
    if var is integer
      return True
    else 
      return False
  }
Sample:

Code: Select all

#NoEnv
#Include Class_LV_Colors.ahk
SetBatchLines, -1
Gui, Margin, 20, 20
Gui, Add, ListView, w600 r15 Grid -ReadOnly vVLV hwndHLV
   , Column 1|Column 2|Column 3|Column 4|Column 5|Column6
Loop, 256
   LV_Add("", "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value "
        . A_Index, "Value " . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 95)
; Create a new instance of LV_Colors
CLV := New LV_Colors(HLV)
CLV.Critical := 1000
; Set the colors for selected rows
CLV.SelectionColors(0xCCE8FF, 0x000000)
If !IsObject(CLV) {
   MsgBox, 0, ERROR, Couldn't create a new LV_Colors object!
   ExitApp
}
Gui, Add, CheckBox, w120 vColorsOn gSubShowColors Checked, Colors On
Gui, Add, Radio, x+120 yp wp vColors gSubColors, Colors
Gui, Add, Radio, x+0 yp wp vAltRows gSubColors, Alternate Rows
Gui, Add, Radio, x+0 yp wp vAltCols gSubColors, Alternate Columns
Gui, Show, , ListView & Colors
; Redraw the ListView after the first Gui, Show command to show the colors, if any.
WinSet, Redraw, , ahk_id %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
GuiEscape:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
SubShowColors:
Gui, Submit, NoHide
If (ColorsOn)
   CLV.OnMessage()
Else
   CLV.OnMessage(False)
GuiControl, Focus, %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
SubColors:
Gui, Submit, NoHide
GuiControl, -Redraw, %HLV%
CLV.Clear(1, 1)
If (Colors)
   GoSub, SetColors
If (AltRows)
   CLV.AlternateRows(0x808080, 0xFFFFFF)
If (AltCols)
   CLV.AlternateCols(0x808080, 0xFFFFFF)
GuiControl, +Redraw, %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
SetColors:
Loop, % LV_GetCount() {
   If (A_Index & 1) {
      CLV.Cell(A_Index, 1, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 3, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 5, 0x808080, 0xFFFFFF)
   }
   Else {
      CLV.Cell(A_Index, 2, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 4, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 6, 0x808080, 0xFFFFFF)
   }
}
Return
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

26 Mar 2017, 15:56

I added a new method to this and wanted to share. I made just enough changes to enable hot-track color customization. New method is HotColors(). You can pass it background, foreground, and a border color (this is only applied if the selected item is hovered over). Included below is the updated library. Only tested on Win10 x64 and AHK 1.1.25.01 U64.

Code: Select all

; ======================================================================================================================
; Namespace:      LV_Colors
; Function:       Individual row and cell coloring for AHK ListView controls.
; Tested with:    AHK 1.1.23.05 (A32/U32/U64)
; Tested on:      Win 10 (x64)
; Changelog:
;     1.1.04.01/2016-05-03/just me - added change to remove the focus rectangle from focused rows
;     1.1.04.00/2016-05-03/just me - added SelectionColors method
;     1.1.03.00/2015-04-11/just me - bugfix for StaticMode
;     1.1.02.00/2015-04-07/just me - bugfixes for StaticMode, NoSort, and NoSizing
;     1.1.01.00/2015-03-31/just me - removed option OnMessage from __New(), restructured code
;     1.1.00.00/2015-03-27/just me - added AlternateRows and AlternateCols, revised code.
;     1.0.00.00/2015-03-23/just me - new version using new AHK 1.1.20+ features
;     0.5.00.00/2014-08-13/just me - changed 'static mode' handling
;     0.4.01.00/2013-12-30/just me - minor bug fix
;     0.4.00.00/2013-12-30/just me - added static mode
;     0.3.00.00/2013-06-15/just me - added "Critical, 100" to avoid drawing issues
;     0.2.00.00/2013-01-12/just me - bugfixes and minor changes
;     0.1.00.00/2012-10-27/just me - initial release
; ======================================================================================================================
; CLASS LV_Colors
;
; The class provides six public methods to set individual colors for rows and/or cells, to clear all colors, to
; prevent/allow sorting and rezising of columns dynamically, and to deactivate/activate the message handler for
; WM_NOTIFY messages (see below).
;
; The message handler for WM_NOTIFY messages will be activated for the specified ListView whenever a new instance is
; created. If you want to temporarily disable coloring call MyInstance.OnMessage(False). This must be done also before
; you try to destroy the instance. To enable it again, call MyInstance.OnMessage().
;
; To avoid the loss of Gui events and messages the message handler might need to be set 'critical'. This can be
; achieved by setting the instance property 'Critical' ti the required value (e.g. MyInstance.Critical := 100).
; New instances default to 'Critical, Off'. Though sometimes needed, ListViews or the whole Gui may become
; unresponsive under certain circumstances if Critical is set and the ListView has a g-label.
; ======================================================================================================================
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
   }
   ; ===================================================================================================================
   ; HotColors() Sets background and/or text color for hovered 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.
   ; ===================================================================================================================
   HotColors(BkColor := "", TxColor := "", borderColor := "") {
      If !(This.HWND)
         Return False
      This.HotColors := False
      If (BkColor = "") && (TxColor = "") && (borderColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      borderColorBGR := This.BGR(borderColor)
      If (BkBGR = "") && (TxBGR = "") && (borderColorBGR = "")
         Return False
      This["HOTB"] := BkBGR
      This["HOTT"] := TxBGR
      This["BORDER"] := borderColorBGR
      This.HotColors := True
	  if (hArrow := DllCall("LoadCursor", "Ptr", 0, "Ptr", 32512))
		 DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x103E, "Int", 0, "Ptr", hArrow, "Ptr")
	  If !(DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x1037 "UInt", 0, "UInt", 0, "UInt") && 0x40)
		 DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x1036, "UInt", 0x40, "UInt", 0x40, "UInt")
      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), 0x10 (CDRF_NOTIFYPOSTPAINT)
      Static SizeNMHDR := A_PtrSize * 3                  ; Size of NMHDR structure
	  Static OffHDC := SizeNMHDR + 8                     ; Offset of HDC (NMCUSTOMDRAW)
	  Static OffRECT := OffHDC + 8                       ; Offset of RECT (NMCUSTOMDRAW)
      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")
	  , HDC := NumGet(L + OffHDC, "Ptr")
	  , RECT := L + OffRECT
	  , X := NumGet(L + OffRECT, 0, "UInt")
      , Row := NumGet(L + OffItem, "UPtr") + 1
      , Col := NumGet(L + OffSubItem, "Int") + 1
      , Item := Row - 1
	  , hotItem := DllCall("SendMessage", "Ptr", H, "UInt", 0x103D, "UInt", 0, "UInt", 0, "UInt")
      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
		 If (This.HotColors) && (Item = hotItem)
			NumPut(This.HOTT, L + OffCT, "UInt"), NumPut(This.HOTB, L + OffCB, "UInt")
		Else
			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 0x12 ; CDRF_NEWFONT | CDRF_NOTIFYPOSTPAINT
         }
         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 0x30
		If (This.HotColors) && (Item = hotItem)
			NumPut(This.HOTT, L + OffCT, "UInt"), NumPut(This.HOTB, L + OffCB, "UInt")
		Else
			NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt")
         Return 0x10 ; CDRF_NOTIFYPOSTPAINT
      }
	  ; CDDS_ITEMPOSTPAINT = 0x010002 -----------------------------------------------------------------------------------
	  If (DrawStage = 0x010002 && This.BORDER) {
			If (This.HotColors) && (Item = hotItem) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt") {
				; NumPut(X + 3, L + OffRECT, 0, "UInt")  ;<<<<<<<< Uncomment this to adjust the rectangle to fit around just the row's background. Not sure how we could color that space (belongs to state image or icon?)
				hBrush := DllCall("CreateSolidBrush", "Uint", This.BORDER)
				DllCall("FrameRect", "Ptr", HDC, "Ptr", RECT, "Ptr", hBrush)
				DllCall("DeleteObject", "Ptr", hBrush)
			}
	  }
      ; 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)
   }
}
Below is an updated version of the test script provided by just me featured at LV_Colors GitHub page. I added another ListView with the Explorer theme set for comparison. The first example is mimicing that theme. There are issues with the "padding" to the left of the row not being colored. This is evident because of the selection/hot rectangle. It is exaggerated if you add an icon to the rows. I'm not sure how the Explorer theme colors the background of the icons, but I assume we would have to draw the icons ourselves and account for the indent then. Maybe someone else has ideas.

Code: Select all

#NoEnv
#Include Class_LV_Colors.ahk
SetBatchLines, -1
Gui, Margin, 20, 20
Gui, Font, s9
Gui, Add, ListView, w600 r15 -ReadOnly vVLV hwndHLV
   , Column 1|Column 2|Column 3|Column 4|Column 5|Column6
Loop, 255
   LV_Add("", "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value "
        . A_Index, "Value " . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 95)
; Create a new instance of LV_Colors
CLV := New LV_Colors(HLV)
; CLV.Critical := 1000
; Set the colors for selected rows
CLV.SelectionColors(0xCCE8FF, 0x000000)
CLV.HotColors(0xE5F3FF, 0x000000, 0x99D1FF)
If !IsObject(CLV) {
   MsgBox, 0, ERROR, Couldn't create a new LV_Colors object!
   ExitApp
}
Gui, Add, ListView, w600 r15 -ReadOnly hwndHLV2
   , Column 1|Column 2|Column 3|Column 4|Column 5|Column6
Loop, 255
   LV_Add("", "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value "
        . A_Index, "Value " . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 95)
SetExplorerTheme(HLV2)
Gui, Add, CheckBox, w120 vColorsOn gSubShowColors Checked, Colors On
Gui, Add, Radio, x+120 yp wp vColors gSubColors, Colors
Gui, Add, Radio, x+0 yp wp vAltRows gSubColors, Alternate Rows
Gui, Add, Radio, x+0 yp wp vAltCols gSubColors, Alternate Columns
Gui, Show, , ListView & Colors
; Redraw the ListView after the first Gui, Show command to show the colors, if any.
WinSet, Redraw, , ahk_id %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
GuiEscape:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
SubShowColors:
Gui, Submit, NoHide
If (ColorsOn)
   CLV.OnMessage()
Else
   CLV.OnMessage(False)
GuiControl, Focus, %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
SubColors:
Gui, Submit, NoHide
GuiControl, -Redraw, %HLV%
CLV.Clear(1, 1)
If (Colors)
   GoSub, SetColors
If (AltRows)
   CLV.AlternateRows(0x808080, 0xFFFFFF)
If (AltCols)
   CLV.AlternateCols(0x808080, 0xFFFFFF)
GuiControl, +Redraw, %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
SetColors:
Loop, % LV_GetCount() {
   If (A_Index & 1) {
      CLV.Cell(A_Index, 1, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 3, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 5, 0x808080, 0xFFFFFF)
   }
   Else {
      CLV.Cell(A_Index, 2, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 4, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 6, 0x808080, 0xFFFFFF)
   }
}
Return

SetExplorerTheme(HCTL) { ; HCTL : handle of a ListView or TreeView control
   If (DllCall("GetVersion", "UChar") > 5) {
      VarSetCapacity(ClassName, 1024, 0)
      If DllCall("GetClassName", "Ptr", HCTL, "Str", ClassName, "Int", 512, "Int")
         If (ClassName = "SysListView32") || (ClassName = "SysTreeView32")
            Return !DllCall("UxTheme.dll\SetWindowTheme", "Ptr", HCTL, "WStr", "Explorer", "Ptr", 0)
   }
   Return False
}
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

27 Mar 2017, 03:34

Hi kczx3,

nice addition, thanks for sharing. IMO, hot item colors are related to items, not subitems. That's why I suggest the following changes:

Code: Select all

   ; ===================================================================================================================
   ; HotColors() Sets background and/or text color for hovered 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.
   ; ===================================================================================================================
   HotColors(BkColor := "", TxColor := "", borderColor := "") {
      If !(This.HWND)
         Return False
      This.HotColors := False
      If (This.BORDER) {
         DllCall("DeleteObject", "Ptr", This.BORDER)
         This.BORDER := ""
      }
      If (BkColor = "") && (TxColor = "") && (borderColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      borderColorBGR := This.BGR(borderColor)
      If (BkBGR = "") && (TxBGR = "") && (borderColorBGR = "")
         Return False
      This["HOTB"] := BkBGR
      This["HOTT"] := TxBGR
      This["BORDER"] := borderColorBGR <> "" ? DllCall("CreateSolidBrush", "UInt", borderColorBGR, "UPtr") : 0
      This.HotColors := True
      If (hArrow := DllCall("LoadCursor", "Ptr", 0, "Ptr", 32512))
         DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x103E, "Int", 0, "Ptr", hArrow, "Ptr")
      If !(DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x1037 "UInt", 0, "UInt", 0, "UInt") && 0x40)
         DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x1036, "UInt", 0x40, "UInt", 0x40, "UInt")
      Return True
   }
...
...
   ; -------------------------------------------------------------------------------------------------------------------
   NM_CUSTOMDRAW(H, L) {
      ; Return values: 0x00 (CDRF_DODEFAULT), 0x02 (CDRF_NEWFONT), 0x04 (CDRF_SKIPDEFAULT), 0x10 (CDRF_NOTIFYPOSTPAINT),
      ;                0x20 (CDRF_NOTIFYITEMDRAW / CDRF_NOTIFYSUBITEMDRAW)
      Static SizeNMHDR := A_PtrSize * 3                  ; Size of NMHDR structure
      Static OffHDC := SizeNMHDR + 8                     ; Offset of HDC (NMCUSTOMDRAW)
      Static OffRECT := OffHDC + 8                       ; Offset of RECT (NMCUSTOMDRAW)
      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
         }
         If (This.HotColors) && (Item = DllCall("SendMessage", "Ptr", H, "UInt", 0x103D, "UInt", 0, "UInt", 0, "UInt")) {
            NumPut(This.HOTT, L + OffCT, "UInt"), NumPut(This.HOTB, L + OffCB, "UInt"), This.HotItem := This.BORDER ? Item : 0
            Return (This.BORDER ? 0x10 : 0x02) ; CDRF_NOTIFYPOSTPAINT : CDRF_NEWFONT
         }
         UseAltRow := (Item & 1) && (This.AltRows)
         , This.HotItem := 0
         , 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_ITEMPOSTPAINT = 0x010002 -----------------------------------------------------------------------------------
      If (DrawStage = 0x010002) {
         If ((Item = This.HotItem) && This.BORDER) {
            ; NumPut(NumGet(L + OffRECT, 0, "UInt") + 3, L + OffRECT, 0, "UInt")  ;<<<<<<<< Uncomment this to adjust the rectangle to fit around just the row's background. Not sure how we could color that space (belongs to state image or icon?)
            DllCall("FrameRect", "Ptr", NumGet(L + OffHDC, "UPtr"), "Ptr", L + OffRECT, "Ptr", This.BORDER)
            This.Hotitem := 0
         }
         Return 0x04 ; CDRF_SKIPDEFAULT
      }
      ; CDDS_PREPAINT = 0x000001 ---------------------------------------------------------------------------------------
      Return (DrawStage = 0x000001) ? 0x20 : 0x00
   }
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

27 Mar 2017, 10:04

Yours actually isn't working how I had designed it. The item border was supposed to only be applied when the hot item was also selected. Yours is outlining the row all the time except for when the highlighted row is also selected. I changed the if criteria for the CDDS_ITEMPOSTPAINT to also check if the current item is selected. This also requires us to return 0x12 (CDRF_NOTIFYPOSTPAINT | CDRF_NEWFONT) from the first IF in the CDDS_ITEMPREPAINT stage if This.BORDER is set. Here is my updated function. I am still trying to figure out how to apply the background color to the left margin where an icon would live.

EDIT: Actually, this isn't quite working either. I kept some of your code and it seems that once you leave an item after it is selected that the border rectangle will not get applied again until you select a new row. I'm looking into it.

Code: Select all

   ; -------------------------------------------------------------------------------------------------------------------
   NM_CUSTOMDRAW(H, L) {
      ; Return values: 0x00 (CDRF_DODEFAULT), 0x20 (CDRF_NOTIFYITEMDRAW / CDRF_NOTIFYSUBITEMDRAW), 0x10 (CDRF_NOTIFYPOSTPAINT)
      Static SizeNMHDR := A_PtrSize * 3                  ; Size of NMHDR structure
	  Static OffHDC := SizeNMHDR + 8                     ; Offset of HDC (NMCUSTOMDRAW)
	  Static OffRECT := OffHDC + 8                       ; Offset of RECT (NMCUSTOMDRAW)
      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 (This.BORDER ? 0x12 : 0x02) ; CDRF_NOTIFYPOSTPAINT | CDRF_NEWFONT : CDRF_NEWFONT
         }
		 If (This.HotColors) && (Item = DllCall("SendMessage", "Ptr", H, "UInt", 0x103D, "UInt", 0, "UInt", 0, "UInt")) {
            NumPut(This.HOTT, L + OffCT, "UInt"), NumPut(This.HOTB, L + OffCB, "UInt"), This.HotItem := This.BORDER ? Item : 0
            Return (This.BORDER ? 0x10 : 0x02) ; CDRF_NOTIFYPOSTPAINT : 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 0x30
			NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt")
         Return 0x00 ; CDRF_NOTIFYPOSTPAINT
      }
	  ; CDDS_ITEMPOSTPAINT = 0x010002 -----------------------------------------------------------------------------------
	  If (DrawStage = 0x010002) {
			If (This.BORDER) && (Item = This.HotItem) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt") {
				; NumPut(X + 3, L + OffRECT, 0, "UInt")  ;<<<<<<<< Uncomment this to adjust the rectangle to fit around just the row's background. Not sure how we could color that space (belongs to state image or icon?)
				DllCall("FrameRect", "Ptr", NumGet(L + OffHDC, "Ptr"), "Ptr", L + OffRECT, "Ptr", This.BORDER)
			}
	  }
      ; CDDS_PREPAINT = 0x000001 ---------------------------------------------------------------------------------------
      Return (DrawStage = 0x000001) ? 0x20 : 0x00
   }
just me
Posts: 6464
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

27 Mar 2017, 10:13

The item border was supposed to only be applied when the hot item was also selected.
You should mention it in the method description:

Code: Select all

   ; ===================================================================================================================
   ; HotColors() Sets background and/or text color for hovered 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.
   ; ===================================================================================================================
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

27 Mar 2017, 10:25

Code: Select all

   ; ===================================================================================================================
   ; HotColors() Sets background and/or text color for hovered 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
   ;                 borderColor -  Border color for selected item when hot 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.
   ; ===================================================================================================================
User avatar
kczx3
Posts: 872
Joined: 06 Oct 2015, 21:39

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

27 Mar 2017, 12:39

Surely, there is a better way to do this. But I have it functioning how I had intended now. By using FillRect in CDDS_ITEMPREPAINT, we can fill the remaining left margin with the same background color as either the selection or the hot color. As for the icons, I tried sending ImageList_SetBkColor to the hwnd(I think that's what is returned) from IL_Create and setting the color to CLR_NONE but that didn't seem to work. The next best thing I could think of rather quickly was to simply set the ImageList on the ListView and set an icon to a number that is higher than the max index of the ImageList. This allows the ListView to create the proper space for the icon. Then, I get the hwnd of the ListView's ImageList in __New and in CDDS_ITEMPOSTPAINT, I manually draw the icon (with a messy way of getting the coords) using ILD_TRANSPARENT for the last parameter of ImageList_Draw.

Code: Select all

; ======================================================================================================================
; Namespace:      LV_Colors
; Function:       Individual row and cell coloring for AHK ListView controls.
; Tested with:    AHK 1.1.23.05 (A32/U32/U64)
; Tested on:      Win 10 (x64)
; Changelog:
;     1.1.04.01/2016-05-03/just me - added change to remove the focus rectangle from focused rows
;     1.1.04.00/2016-05-03/just me - added SelectionColors method
;     1.1.03.00/2015-04-11/just me - bugfix for StaticMode
;     1.1.02.00/2015-04-07/just me - bugfixes for StaticMode, NoSort, and NoSizing
;     1.1.01.00/2015-03-31/just me - removed option OnMessage from __New(), restructured code
;     1.1.00.00/2015-03-27/just me - added AlternateRows and AlternateCols, revised code.
;     1.0.00.00/2015-03-23/just me - new version using new AHK 1.1.20+ features
;     0.5.00.00/2014-08-13/just me - changed 'static mode' handling
;     0.4.01.00/2013-12-30/just me - minor bug fix
;     0.4.00.00/2013-12-30/just me - added static mode
;     0.3.00.00/2013-06-15/just me - added "Critical, 100" to avoid drawing issues
;     0.2.00.00/2013-01-12/just me - bugfixes and minor changes
;     0.1.00.00/2012-10-27/just me - initial release
; ======================================================================================================================
; CLASS LV_Colors
;
; The class provides six public methods to set individual colors for rows and/or cells, to clear all colors, to
; prevent/allow sorting and rezising of columns dynamically, and to deactivate/activate the message handler for
; WM_NOTIFY messages (see below).
;
; The message handler for WM_NOTIFY messages will be activated for the specified ListView whenever a new instance is
; created. If you want to temporarily disable coloring call MyInstance.OnMessage(False). This must be done also before
; you try to destroy the instance. To enable it again, call MyInstance.OnMessage().
;
; To avoid the loss of Gui events and messages the message handler might need to be set 'critical'. This can be
; achieved by setting the instance property 'Critical' ti the required value (e.g. MyInstance.Critical := 100).
; New instances default to 'Critical, Off'. Though sometimes needed, ListViews or the whole Gui may become
; unresponsive under certain circumstances if Critical is set and the ListView has a g-label.
; ======================================================================================================================
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
	  ; Get ImageList of control
	  SendMessage, 0x1002, 1, 0, , % "ahk_id " . HWND ; LVM_GETIMAGELIST
	  This.IL := 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 (This.SELBrush) {
         DllCall("DeleteObject", "Ptr", This.SELBrush)
         This.SELBrush := ""
      }
      If (BkColor = "") && (TxColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
	  This.SELBrush := BkBGR <> "" ? DllCall("CreateSolidBrush", "UInt", BkBGR, "UPtr") : 0
      If (BkBGR = "") && (TxBGR = "")
         Return False
      This["SELB"] := BkBGR
      This["SELT"] := TxBGR
      This.SelColors := True
      Return True
   }
   ; ===================================================================================================================
   ; HotColors() Sets background and/or text color for hovered 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
   ;                 borderColor -  Border color for selected item when hot 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.
   ; ===================================================================================================================
   HotColors(BkColor := "", TxColor := "", borderColor := "") {
      If !(This.HWND)
         Return False
      This.HotColors := False
      If (This.BORDER) {
         DllCall("DeleteObject", "Ptr", This.BORDER)
         This.BORDER := ""
      }
      If (This.HOTBrush) {
         DllCall("DeleteObject", "Ptr", This.HOTBrush)
         This.HOTBrush := ""
      }
      If (BkColor = "") && (TxColor = "") && (borderColor = "")
         Return True
      BkBGR := This.BGR(BkColor)
      TxBGR := This.BGR(TxColor)
      borderColorBGR := This.BGR(borderColor)
      If (BkBGR = "") && (TxBGR = "") && (borderColorBGR = "")
         Return False
      This["HOTB"] := BkBGR
	  This.HOTBrush := BkBGR <> "" ? DllCall("CreateSolidBrush", "UInt", BkBGR, "UPtr") : 0
      This["HOTT"] := TxBGR
      This["BORDER"] := borderColorBGR <> "" ? DllCall("CreateSolidBrush", "UInt", borderColorBGR, "UPtr") : 0
      This.HotColors := True
      If (hArrow := DllCall("LoadCursor", "Ptr", 0, "Ptr", 32512))
         DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x103E, "Int", 0, "Ptr", hArrow, "Ptr")
	  ; LVS_EX_ONECLICKACTIVATE := 0x40 is a required extended style to enable hot-tracking.
      If !(DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x1037 "UInt", 0, "UInt", 0, "UInt") && 0x40)
         DllCall("SendMessage", "Ptr", This.HWND, "UInt", 0x1036, "UInt", 0x40, "UInt", 0x40, "UInt")
      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), 0x10 (CDRF_NOTIFYPOSTPAINT)
      Static SizeNMHDR := A_PtrSize * 3                   ; Size of NMHDR structure
	  Static OffHDC := SizeNMHDR + 8                      ; Offset of HDC (NMCUSTOMDRAW)
	  Static OffRECT := OffHDC + 8                        ; Offset of RECT (NMCUSTOMDRAW)
      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)
	  Static OffRECT2 := OffSubItem + 28      ; Offset of clrFace (NMLVCUSTOMDRAW)
	  ; ----------------------------------------------------------------------------------------------------------------
      DrawStage := NumGet(L + SizeNMHDR, 0, "UInt")
	  , HDC := NumGet(L + OffHDC, "Ptr")
      , 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) {
		 This.hotItem := DllCall("SendMessage", "Ptr", H, "UInt", 0x103D, "UInt", 0, "UInt", 0, "UInt")
         ; 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 <> "") {
				DllCall("FillRect", "Ptr", NumGet(L + OffHDC, "UPtr"), "Ptr", L + OffRECT, "Ptr", This.SELBrush) ; Fill rectangle with same color to extend to left edge of control.
               NumPut(This.SELB, L + OffCB, "UInt")
			}
            If (This.SELT <> "")
               NumPut(This.SELT, L + OffCT, "UInt")
            Return 0x12 ; CDRF_NOTIFYPOSTPAINT
         }
		If (This.HotColors) && (Item = This.hotItem) {
			DllCall("FillRect", "Ptr", NumGet(L + OffHDC, "UPtr"), "Ptr", L + OffRECT, "Ptr", This.HOTBrush) ; Fill rectangle with same color to extend to left edge of control. Hot Color
			NumPut(This.HOTT, L + OffCT, "UInt"), NumPut(This.HOTB, L + OffCB, "UInt")
			Return 0x12 ; CDRF_NOTIFYPOSTPAINT
		}
         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 0x30
		 NumPut(This.RowT, L + OffCT, "UInt"), NumPut(This.RowB, L + OffCB, "UInt")
         Return 0x10 ; CDRF_DODEFAULT
      }
	  ; CDDS_ITEMPOSTPAINT = 0x010002 -----------------------------------------------------------------------------------
	  If (DrawStage = 0x010002 && This.BORDER) {
		If(This.IL) {
			VarSetCapacity(iconRECT, 16)
			NumPut(2, iconRECT, 0, "UInt")
			DllCall("SendMessage", "Ptr", H, "UInt", 0x100E, "UInt", Item, "Ptr", &iconRECT, "UInt")
			DllCall("comctl32.dll\ImageList_Draw", "Ptr", This.IL, "UInt", 0, "Ptr", NumGet(L + OffHDC, "UPtr"), "UInt", NumGet(iconRECT, 0, "UInt") - 17, "UInt", NumGet(iconRECT, 4, "UInt"), "UInt", 0x1)
		}
		If (This.HotColors) && (Item = This.hotItem) && DllCall("SendMessage", "Ptr", H, "UInt", 0x102C, "Ptr", Item, "Ptr", 0x0002, "UInt")
			DllCall("FrameRect", "Ptr", NumGet(L + OffHDC, "UPtr"), "Ptr", L + OffRECT, "Ptr", This.BORDER)
	  }
      ; 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)
   }
}

Code: Select all

#NoEnv
#Include Class_LV_Colors.ahk

LV_IL := IL_Create(1)
IL_Add(LV_IL, "shell32", 2)
SetBatchLines, -1
Gui, Margin, 20, 20
Gui, Font, s9
Gui, Add, ListView, w600 r15 BackgroundSilver -ReadOnly vVLV hwndHLV
   , Column 1|Column 2|Column 3|Column 4|Column 5|Column6
LV_SetImagelist(LV_IL)
Loop, 255
   LV_Add("Icon9999", "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value "
        . A_Index, "Value " . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 95)
; Create a new instance of LV_Colors
CLV := New LV_Colors(HLV)
CLV.Critical := 1000
; Set the colors for selected rows
CLV.SelectionColors(0xCCE8FF, 0x000000)
CLV.HotColors(0xE5F3FF, 0x000000, 0x99D1FF)
If !IsObject(CLV) {
   MsgBox, 0, ERROR, Couldn't create a new LV_Colors object!
   ExitApp
}
Gui, Add, ListView, w600 r15 -ReadOnly hwndHLV2
   , Column 1|Column 2|Column 3|Column 4|Column 5|Column 6
LV_SetImagelist(LV_IL)
Loop, 255
   LV_Add("Icon1", "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value " . A_Index, "Value "
        . A_Index, "Value " . A_Index)
Loop, % LV_GetCount("Column")
   LV_ModifyCol(A_Index, 95)
SetExplorerTheme(HLV2)
Gui, Add, CheckBox, w120 vColorsOn gSubShowColors Checked, Colors On
Gui, Add, Radio, x+120 yp wp vColors gSubColors, Colors
Gui, Add, Radio, x+0 yp wp vAltRows gSubColors, Alternate Rows
Gui, Add, Radio, x+0 yp wp vAltCols gSubColors, Alternate Columns
Gui, Show, , ListView & Colors
; Redraw the ListView after the first Gui, Show command to show the colors, if any.
WinSet, Redraw, , ahk_id %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
GuiEscape:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
SubShowColors:
Gui, Submit, NoHide
If (ColorsOn)
   CLV.OnMessage()
Else
   CLV.OnMessage(False)
GuiControl, Focus, %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
SubColors:
Gui, Submit, NoHide
GuiControl, -Redraw, %HLV%
CLV.Clear(1, 1)
If (Colors)
   GoSub, SetColors
If (AltRows)
   CLV.AlternateRows(0x808080, 0xFFFFFF)
If (AltCols)
   CLV.AlternateCols(0x808080, 0xFFFFFF)
GuiControl, +Redraw, %HLV%
Return
; ----------------------------------------------------------------------------------------------------------------------
SetColors:
Loop, % LV_GetCount() {
   If (A_Index & 1) {
      CLV.Cell(A_Index, 1, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 3, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 5, 0x808080, 0xFFFFFF)
   }
   Else {
      CLV.Cell(A_Index, 2, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 4, 0x808080, 0xFFFFFF)
      CLV.Cell(A_Index, 6, 0x808080, 0xFFFFFF)
   }
}
Return

SetExplorerTheme(HCTL) { ; HCTL : handle of a ListView or TreeView control
   If (DllCall("GetVersion", "UChar") > 5) {
      VarSetCapacity(ClassName, 1024, 0)
      If DllCall("GetClassName", "Ptr", HCTL, "Str", ClassName, "Int", 512, "Int")
         If (ClassName = "SysListView32") || (ClassName = "SysTreeView32")
            Return !DllCall("UxTheme.dll\SetWindowTheme", "Ptr", HCTL, "WStr", "Explorer", "Ptr", 0)
   }
   Return False
}
User avatar
RUNIE
Posts: 283
Joined: 03 May 2014, 14:50
GitHub: Run1e

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

04 May 2017, 18:58

Hey.

Firstly thanks for the class, it really does bring some well needed flavour to GUIs.

I have an issue where the selection colors disappear:
Image

Here is the code that produces that:

Code: Select all

#SingleInstance force
#NoEnv

Menu, Tray, NoStandard
Menu, Tray, DeleteAll
Menu, Tray, Add, Open, Open
Menu, Tray, Add, Exit, Exit
Menu, Tray, Default, Open

Gui Add, ListView, hwndhwnd, Header

for Index, Text in ["Hello there", "This is some lines", "for the listview!"]
	LV_Add(, Text)

CLV := new LV_Colors(hwnd)
CLV.Critical := 200
CLV.SelectionColors(0x60BB60, 0xFFFFFF)

Open:
Gui Show
return

Exit:
ExitApp
return
The same happens in one of my bigger projects:
Image

The critical options does not seem to have an effect.
Any idea why this might be happening?

o/
RUNIE

Edit: did some more testing.

The coloration seems to dissapear when the window gets activated.
Rows colored with .Row() does not lose coloration.

Here's the parameters being sent to the message handler when the window is activated and the colors dissapear:
W: 3
L: 9264528
M: 78
H: 6030580
Last edited by RUNIE on 05 May 2017, 08:26, edited 1 time in total.
User avatar
jNizM
Posts: 2450
Joined: 30 Sep 2013, 01:33
GitHub: jNizM
Contact:

Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)

05 May 2017, 01:50

@Run1e add Winset, Redraw after Gui, Show

Code: Select all

Open:
Gui Show
WinSet, Redraw,, % "ahk_id " hwnd
return
[AHK] 1.1.30.03 x64 Unicode | [WIN] 10 Pro (Version 1903) x64 | [GitHub] Profile
Donations are appreciated if I could help you

Return to “Scripts and Functions”

Who is online

Users browsing this forum: andylysm and 39 guests