Skip to content

Instantly share code, notes, and snippets.

@maul-esel
Created July 10, 2012 15:21
Show Gist options
  • Save maul-esel/3084017 to your computer and use it in GitHub Desktop.
Save maul-esel/3084017 to your computer and use it in GitHub Desktop.
LVX 1.05.0
/*
Title: LVX Library
Row colouring and cell editing functions for ListView controls.
Remarks:
Cell editing code adapted from Michas <http://www.autohotkey.com/forum/viewtopic.php?t=19929>;
row colouring by evl <http://www.autohotkey.com/forum/viewtopic.php?t=9266>.
Many thanks to them for providing the code base of these functions!
License:
- Version 1.04 by Titan <http://www.autohotkey.net/~Titan/#lvx>
- zlib License <http://www.autohotkey.net/~Titan/zlib.txt>
- Version 1.05.0-alpha by maul.esel (Unicode and 64bit corrections)
*/
/*
Function: LVX_Setup
Initalization function for the LVX library. Must be called before all other functions.
Parameters:
name - associated variable name (or Hwnd) of ListView control to setup for colouring and cell editing.
*/
LVX_Setup(name) {
global lvx ; data storage
PtrSize := A_PtrSize ? A_PtrSize : 4, PtrType := A_PtrSize ? "Ptr" : "UInt"
If name is xdigit
h = %name%
Else GuiControlGet, h, Hwnd, %name%
VarSetCapacity(lvx, PtrSize + 255 * 9, 0) ; TODO (?)
NumPut(h + 0, lvx, 0, PtrType) ; store HWND in data storage
OnMessage(0x4e, "WM_NOTIFY")
LVX_SetEditHotkeys() ; initialize default hotkeys
}
/*
Function: LVX_CellEdit
Makes the specified cell editable with an Edit control overlay.
Parameters:
r - (optional) row number (default: 1)
c - (optional) column (default: 1)
set - (optional) true to automatically set the cell to the new user-input value (default: true)
Remarks:
The Edit control may be slightly larger than its corresponding row,
depending on the current font setting.
*/
LVX_CellEdit(set = true) {
global lvx, lvxb
static i := 1, e, h, k := "Enter|Esc|NumpadEnter", LVIR_LABEL := 2
PtrSize := A_PtrSize ? A_PtrSize : 4, PtrType := A_PtrSize ? "Ptr" : "UInt"
If i
{
Gui, %A_Gui%:Add, Edit, Hwndh ve Hide r1
;make row resize to fit this height.. then back
h += i := 0
}
If r < 1
r = %A_EventInfo%
If !LV_GetNext()
Return
If !(A_Gui or r)
Return
l := NumGet(lvx) ; TODO
SendMessage, 4135, , , , ahk_id %l% ; LVM_GETTOPINDEX
vti = %ErrorLevel%
bw := 0, by := 0, bpw := 0
VarSetCapacity(xy, 16, 0)
ControlGetPos, bx, t, , , , ahk_id %l%
SendMessage, 4136, , , , ahk_id %l% ; LVM_GETCOUNTPERPAGE
Loop, %ErrorLevel% {
cr = %A_Index%
NumPut(cr - 1, xy, 4, "UInt"), NumPut(LVIR_LABEL, xy, 0, "UInt")
SendMessage, 4152, vti + cr - 1, &xy, , ahk_id %l% ; LVM_GETSUBITEMRECT
by := NumGet(xy, 4, "UInt")
If (LV_GetNext() - vti == cr)
Break
}
by += t + 1
cr--
VarSetCapacity(xy, 16, 0)
CoordMode, Mouse, Relative
MouseGetPos, mx
Loop, % LV_GetCount("Col") {
cc = %A_Index%
NumPut(cc - 1, xy, 4, "UInt"), NumPut(LVIR_LABEL, xy, 0, "UInt")
SendMessage, 4152, cr, &xy, , ahk_id %l% ; LVM_GETSUBITEMRECT
bx += bw := NumGet(xy, 8, "UInt") - NumGet(xy, 0, "UInt")
If !bpw
bpw := NumGet(xy, 0, "UInt")
If (mx <= bx)
Break
}
bx -= bw - bpw - 2
LV_GetText(t, cr + 1, cc)
GuiControl, , e, %t%
ControlMove, , bx, by, bw, , ahk_id %h%
GuiControl, Show, e
GuiControl, Focus, e
sizeof_GUITHREADINFO := 6 * PtrSize + 24
VarSetCapacity(g, sizeof_GUITHREADINFO, 0)
NumPut(sizeof_GUITHREADINFO, g, 0, "UInt") ; GUITHREADINFO::cbSize
LVX_SetEditHotkeys(~1, h)
Loop {
DllCall("GetGUIThreadInfo", "UInt", 0, PtrType, &g)
If (lvxb or NumGet(g, 8 + PtrSize, PtrType) != h)
Break
Sleep, 100
}
GuiControlGet, t, , e
If (set and lvxb != 2)
LVX_SetText(t, cr + 1, cc)
GuiControl, Hide, e
Return, lvxb == 2 ? "" : t
}
/*
Function: LVX_SetText
Set the text of a specified cell.
Parameters:
text - new text content of cell
row - (optional) row number
col - (optional) column number
*/
LVX_SetText(text, row = 1, col = 1) {
global lvx
PtrSize := A_PtrSize ? A_PtrSize : 4, PtrType := A_PtrSize ? "Ptr" : "UInt", sizeof_LVITEM := 52 + 2 * PtrSize
LVM_GETITEMTEXT := 0x1000 + (A_IsUnicode ? 115 : 45), LVM_SETITEMTEXT := 0x1000 + (A_IsUnicode ? 116 : 46)
l := NumGet(lvx, 0, PtrType) ; get HWND from data storage
row-- ; zero-based index
VarSetCapacity(d, sizeof_LVITEM, 0)
SendMessage, LVM_GETITEMTEXT, row, &d, , ahk_id %l% ; initialize item structure (first item in the row)
NumPut(col - 1, d, 8, "Int") ; adjust column index
NumPut(&text, d, 20, PtrType) ; set text
SendMessage, LVM_SETITEMTEXT, row, &d, , ahk_id %l%
}
/*
Function: LVX_SetEditHotkeys
Change accept/cancel hotkeys in cell editing mode.
Parameters:
enter - comma seperated list of hotkey names/modifiers that will save
the current input text and close editing mode
esc - same as above but will ignore text entry (i.e. to cancel)
Remarks:
The default hotkeys are Enter and Esc (Escape) respectively,
and such will be used if either parameter is blank or omitted.
*/
LVX_SetEditHotkeys(enter = "Enter,NumpadEnter", esc = "Esc") {
global lvx, lvxb
static h1, h0
If (enter == ~1) {
If esc > 0
{
lvxb = 0
Hotkey, IfWinNotActive, ahk_id %esc%
}
Loop, Parse, h1, `,
Hotkey, %A_LoopField%, _lvxb
Loop, Parse, h0, `,
Hotkey, %A_LoopField%, _lvxc
Hotkey, IfWinActive
Return
}
If enter !=
h1 = %enter%
If esc !=
h0 = %esc%
}
_lvxc: ; these labels are for internal use:
lvxb++
_lvxb:
lvxb++
LVX_SetEditHotkeys(~1, -1)
Return
/*
Function: LVX_SetColour
Set the background and/or text colour of a specific row on a ListView control.
Parameters:
index - row index (1-based)
back - (optional) background row colour, must be hex code in RGB format (default: 0xffffff)
text - (optional) similar to above, except for font colour (default: 0x000000)
Remarks:
Sorting will not affect coloured rows.
*/
LVX_SetColour(index, back = 0xffffff, text = 0x000000) {
global lvx
PtrType := A_PtrSize ? "Ptr" : "UInt"
a := (index - 1) * 9 + 5 ; TODO
NumPut(LVX_RevBGR(text) + 0, lvx, a) ; TODO
If !back
back = 0x010101 ; since we can't use null
NumPut(LVX_RevBGR(back) + 0, lvx, a + 4) ; TODO
h := NumGet(lvx, 0, PtrType) ; get HWND from data storage
WinSet, Redraw, , ahk_id %h%
}
/*
Function: LVX_RevBGR
Helper function for internal use. Converts RGB to BGR.
Parameters:
i - BGR hex code
*/
LVX_RevBGR(i) {
Return, (i & 0xff) << 16 | (i & 0xffff) >> 8 << 8 | i >> 16
}
/*
Function: LVX_Notify
Handler for WM_NOTIFY events on ListView controls. Do not use this function.
*/
LVX_Notify(wParam, lParam, msg) {
global lvx
PtrSize := A_PtrSize ? A_PtrSize : 4, PtrType := A_PtrSize ? "Ptr" : "UInt"
, LVIF_TEXT := 1
If (NumGet(lParam + 0, 0, PtrType) == NumGet(lvx, 0, PtrType) and NumGet(lParam + 0, 2 * PtrSize, "Int") == -12) { ; TODO: adjust -12 for unicode
st := NumGet(lParam + 0, 4 + 2 * PtrSize, "UInt") ; get mask item from NMLVDISPINFO->LVITEM structure
If (st == LVIF_TEXT)
Return, 0x20 ;?
Else If (st == 0x10001) { ; TODO: ?
a := NumGet(lParam + 36) * 9 + 9 ; get length of item text + 1 and multiply by 9 (?) TODO (36)
If NumGet(lvx, a)
NumPut(NumGet(lvx, a - 4), lParam + 48), NumPut(NumGet(lvx, a), lParam + 52)
}
}
}
WM_NOTIFY(wParam, lParam, msg, hwnd) {
; if you have your own WM_NOTIFY function you will need to merge the following four lines:
global lvx
PtrType := A_PtrSize ? "Ptr" : "UInt"
If (NumGet(lParam + 0, 0, PtrType) == NumGet(lvx, 0, PtrType))
Return, LVX_Notify(wParam, lParam, msg)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment