[Class] LV_Colors - 1.1.05.00 (2024-03-16)
- JoeWinograd
- Posts: 2200
- Joined: 10 Feb 2014, 20:00
- Location: U.S. Central Time Zone
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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 changeto
and add an optional parameter ToggleColor
Edit: changed code to use your function rather than a separate one.
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, "")
Code: Select all
If (ToggleColor and This["Rows"].HasKey(Row))
{
This["Rows"].Remove(Row, "")
return true
}
This["Rows"].Remove(Row, "")
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.
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
Hi hobboy,
first of all, I cannot see the advantage of a separate method or an additional parameter. Are you using variadic method calls?
first of all, I cannot see the advantage of a separate method or an additional parameter. Are you using variadic method calls?
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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 wrote:first of all, I cannot see the advantage of a separate method or an additional parameter. Are you using variadic method calls?
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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:
*Not tested!*
Code: Select all
ToggleRowColors(LVInstance, Row, BkColor, TxColor) {
If LVInstance["Rows"].HasKey(Row)
Return LVInstance.Row(Row)
Return LV_Instance.Row(Row, BkColor, TxColor)
}
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
That works great! Thanks again
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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 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.
I'm using Win7 x64
Using
Code: Select all
GuiControl, +Redraw, %_lv_hwnd%
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
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
It's a known problem. The GuiControl, +Redraw, ... is even part of the sample script on GitHub:
Prior to 1.1.22.05 (at least I think the changes belong to this version) it was needed almost always.
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%
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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...
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 )
}
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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.
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.
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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.
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.
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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:
GDIP:
Sample:
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
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
}
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
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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.
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
; ======================================================================================================================
; 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)
}
}
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
}
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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:
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
}
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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.
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
}
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
You should mention it in the method description:The item border was supposed to only be applied when the hot item was also selected.
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.
; ===================================================================================================================
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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.
; ===================================================================================================================
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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
}
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
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:
Here is the code that produces that:
The same happens in one of my bigger projects:
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
Firstly thanks for the class, it really does bring some well needed flavour to GUIs.
I have an issue where the selection colors disappear:
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 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.
Re: [Class] LV_Colors - 1.1.04.01 (2016-05-03)
@Run1e add Winset, Redraw after Gui, Show
Code: Select all
Open:
Gui Show
WinSet, Redraw,, % "ahk_id " hwnd
return
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Return to “Scripts and Functions (v1)”
Who is online
Users browsing this forum: fiendhunter and 55 guests