#NoEnv
PicFile := A_WinDir . "\Web\Wallpaper\Blaues Fenster.jpg" ; German Win XP
Content := "One|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|Eleven|Twelve|Thirteen"
; PicFile := A_WinDir . "\Web\Wallpaper\HP1.jpg" ; HP Win 7
; LBS_OWNERDRAWFIXED = 0x0010
; LBS_HASSTRINGS = 0x0040
Gui, New, hwndhMain
Gui, Add, Picture, x0 y0 w600 h400 hwndhPic, %PicFile%
Gui, Add, ListBox, x50 y50 w200 r6 Choose1, %Content%
Gui, Add, ListBox, x+100 yp wp hp hwndhLB vLB Choose1, %Content%
Gui, Add, Button, x350 y+20 gSelection, Selected?
TLB := New TransparentListBox(hLB, hPic, 0xFFFFFF, 0xFFFF00) ; Colors have to be BGR
Gui, Show, w600 h400, Transparent ListBox
Return
GuiClose:
ExitApp
Selection:
GuiControlGet, LB
MsgBox, 0, You selected:, %LB%
Return
Class TransparentListBox {
; -------------------------------------------------------------------------------------------------------------------
; Constructor
; -------------------------------------------------------------------------------------------------------------------
__New(HLB, HBG, TxtColor, SelColor) {
; ----------------------------------------------------------------------------------------------------------------
; HLB : HWND of the ListBox
; HBG : HWND of the control containing the background
; TxtColor : text color (BGR integer value, e.g. 0xBBGGRR)
; SelColor : selected text color (BGR integer value, e.g. 0xBBGGRR)
; ----------------------------------------------------------------------------------------------------------------
Static LB_GETITEMHEIGHT := 0x01A1
Static WM_GETFONT := 0x0031
Static SRCCOPY := 0x00CC0020
This.HLB := HLB
This.HBG := HBG
This.TxtColor := TxtColor
This.SelColor := SelColor
SendMessage, %LB_GETITEMHEIGHT%, 0, 0, , ahk_id %HLB%
This.ItemHeight := ErrorLevel
SendMessage, %WM_GETFONT%, 0, 0, , ahk_id %HLB%
This.Font := ErrorLevel
This.HasBackground := False
This.TopIndex := -1
This.CurSel := -1
; LBS_OWNERDRAWFIXED = 0x0010, LBS_HASSTRINGS = 0x0040, LBS_NOSEL = 0x4000
WinSet, Style, +0x4050, ahk_id %HLB%
SCCB := RegisterCallback("TransparentListBox.SubClassCallback")
DllCall("Comctl32.dll\SetWindowSubclass", "Ptr", HLB, "Ptr", SCCB, "Ptr", HLB, "Ptr", Object(This))
This.SCCB := SCCB
}
; -------------------------------------------------------------------------------------------------------------------
; Destructor
; -------------------------------------------------------------------------------------------------------------------
__Delete() {
If (This.Font) {
DllCall("Gdi32.dll\DeleteObject", "Ptr", This.FONT)
This.Font := 0
}
If (This.BMPDC) {
DllCall("Gdi32.dll\DeleteDC", "Ptr", This.BMPDC)
DllCall("Gdi32.dll\DeleteObject", "Ptr", This.HBMP)
This.BMPDC := This.HBMP := 0
}
If (This.MEMDC) {
DllCall("Gdi32.dll\DeleteDC", "Ptr", This.MEMDC)
DllCall("Gdi32.dll\DeleteObject", "Ptr", This.HMEM)
This.MEMDC := This.HMEM := 0
}
If (This.HLB) {
DllCall("Comctl32.dll\RemoveWindowSubclass", "Ptr", This.HLB, "Ptr", This.SCCB, "Ptr", This.HLB)
This.HLB := 0
}
}
; -------------------------------------------------------------------------------------------------------------------
; Subclass callback function
; -------------------------------------------------------------------------------------------------------------------
SubClassCallback(uMsg, wParam, lParam, IdSubclass, RefData) {
Critical 50
hWnd := This ; first parameter 'hWnd' is passed as 'This'
Return Object(RefData).SubClassProc(hWnd, uMsg, wParam, lParam)
}
; -------------------------------------------------------------------------------------------------------------------
; Subclassproc
; -------------------------------------------------------------------------------------------------------------------
SubClassProc(hWnd, uMsg, wParam, lParam) {
Static LB := {GETCOUNT: 0x018B, GETCURSEL: 0x0188, GETITEMRECT: 0x0198, GETTEXT: 0x0189,GETTEXTLEN: 0x018A
, GETTOPINDEX: 0x018E, ITEMFROMPOINT: 0x01A9, SETCURSEL: 0x0186}
Static WM := {DESTROY: 0x0002, DRAWITEM: 0x002B, LBUTTONDBLCLK: 0x0203, ERASEBKGND: 0x0014, KEYDOWN: 0x0100
, KILLFOCUS: 0x0008, LBUTTONDOWN: 0x0201, LBUTTONUP: 0x0202, MOUSEWHEEL: 0x020A, PAINT: 0x000F
, SETFOCUS: 0x0007, SETREDRAW: 0x000B, VSCROLL: 0x0115}
Static SRCCOPY := 0x00CC0020
; WM_PAINT message -----------------------------------------------------------------------------------------------
If (uMsg = WM.PAINT) { ; fully processed
VarSetCapacity(PAINTSTRUCT, A_PtrSize + (4 * 7) + 32 + (A_PtrSize - 4), 0)
LBDC := DllCall("USer32.dll\BeginPaint", "Ptr", This.HLB, "Ptr", &PAINTSTRUCT, "UPtr")
SendMessage, % LB.GETCOUNT, 0, 0, , ahk_id %hWnd%
IC := ErrorLevel ; item count
SendMessage, % LB.GETCURSEL, 0, 0, , ahk_id %hWnd%
CS := ErrorLevel ; current selection
SendMessage, % LB.GETTOPINDEX, 0, 0, , ahk_id %hWnd%
TI := ErrorLevel ; top index
If (TI <> This.TopIndex) || (CS <> This.CurSel) {
This.TopIndex := TI
This.CurSel := CS
DllCall("Gdi32.dll\BitBlt", "Ptr", This.MEMDC, "Int", 0, "Int", 0, "Int", This.Width, "Int", This.Height
, "Ptr", This.BMPDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
OFONT := DllCall("Gdi32.dll\SelectObject", "Ptr", This.MEMDC, "Ptr", This.Font, "UPtr")
DllCall("Gdi32.dll\SetBkMode", "Ptr", This.MEMDC, "Int", 1) ; TRANSPARENT
VarSetCapacity(RECT, 16, 0)
SendMessage, % LB.GETITEMRECT, %TI%, &RECT, , ahk_id %hWnd%
NumPut(NumGet(RECT, 0, "Int") + 3, RECT, 0, "Int")
While (TI < IC) && (NumGet(RECT, 12, "Int") <= This.Height) {
SendMessage, % LB.GETTEXTLEN, %TI%, 0, , ahk_id %hWnd%
TL := ErrorLevel
VarSetCapacity(TXT, TL << !!A_IsUnicode, 0)
SendMessage, % LB.GETTEXT, %TI%, &TXT, , ahk_id %hWnd%
TextColor := (TI = CS ? This.SelColor : This.TxtColor)
DllCall("Gdi32.dll\SetTextColor", "Ptr", This.MEMDC, "UInt", TextColor)
DllCall("User32.dll\DrawText", "Ptr", This.MEMDC, "Ptr", &TXT, "Int", TL, "Ptr", &RECT, "UInt", 0)
DllCall("User32.dll\OffsetRect", "Ptr", &RECT, "Int", 0, "Int", This.ItemHeight)
TI++
}
DllCall("Gdi32.dll\SelectObject", "Ptr", MEMDC, "Ptr", OFONT, "UPtr")
}
DllCall("Gdi32.dll\BitBlt", "Ptr", LBDC, "Int", 0, "Int", 0, "Int", This.Width, "Int", This.Height
, "Ptr", This.MEMDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
DllCall("User32.dll\EndPaint", "Ptr", &PAINTSTRUCT)
Return 0
}
; WM_DRAWITEM message --------------------------------------------------------------------------------------------
If (uMsg = WM.DRAWITEM) ; not processed
Return True
; WM_LBUTTONDOWN and WM_LBUTTONDBLCLK messages -------------------------------------------------------------------
If (uMsg = WM.LBUTTONDOWN) Or (uMsg = WM.LBUTTONDBLCLK) { ; partially processed
ControlFocus, , ahk_id %hWnd%
Return 0
}
; WM_MOUSEWHEEL message ------------------------------------------------------------------------------------------
If (uMsg = WM.MOUSEWHEEL) { ; partially processed
PostMessage, % WM.VSCROLL, % ((wParam >> 16) > 0x7FFF ? 1 : 0), 0, , ahk_id %hWnd%
Return 0
}
; WM_KILLFOCUS and WM_SETFOCUS messages --------------------------------------------------------------------------
If (uMsg = WM.KILLFOCUS) Or (uMsg = WM.SETFOCUS) ; not processed
Return 0
; WM_KEYDOWN message --------------------------------------------------------------------------------------------
If (uMsg = WM.KEYDOWN) ; not processed
Return 0
; WM_LBUTTONUP message -------------------------------------------------------------------------------------------
If (uMsg = WM.LBUTTONUP) { ; partially processed
SendMessage, % LB.ITEMFROMPOINT, 0, %lParam%, , ahk_id %hWnd%
Item := ErrorLevel
If !(Item & 0xFFFF0000) {
SendMessage, % WM.SETREDRAW, 0, 0, , ahk_id %hWnd%
SendMessage, % LB.SETCURSEL, %Item%, 0, , ahk_id %hWnd%
SendMessage, % WM.SETREDRAW, 1, 0, , ahk_id %hWnd%
DllCall("User32.dll\RedrawWindow", "Ptr", hWnd, "Ptr", 0, "Ptr", 0, "UInt", 0x0501)
}
Return 0
}
; WM_VSCROLL message ---------------------------------------------------------------------------------------------
If (uMsg = WM.VSCROLL) { ; partially processed
SendMessage, % WM.SETREDRAW, 0, 0, , ahk_id %hWnd%
DllCall("Comctl32.dll\DefSubclassProc", "Ptr", hWnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam)
SendMessage, % WM.SETREDRAW, 1, 0, , ahk_id %hWnd%
SendMessage, % LB.GETTOPINDEX, 0, 0, , ahk_id %hWnd%
DllCall("User32.dll\RedrawWindow", "Ptr", hWnd, "Ptr", 0, "Ptr", 0, "UInt", 0x0501)
Return 0
}
; WM_ERASEBKGND message ------------------------------------------------------------------------------------------
If (uMsg = WM.ERASEBKGND) {
If (!This.HasBackground) { ; processed for first message
VarSetCapacity(RECT, 16, 0)
DllCall("User32.dll\GetClientRect", "Ptr", This.HLB, "Ptr", &RECT)
This.Width := W := NumGet(RECT, 8, "Int")
This.Height := H := NumGet(RECT, 12, "Int")
DllCall("User32.dll\ClientToScreen", "Ptr", This.HLB, "Ptr", &RECT)
DllCall("User32.dll\ScreenToClient", "Ptr", This.HBG, "Ptr", &RECT)
This.Left := NumGet(RECT, 0, "Int")
This.Top := NumGet(RECT, 4, "Int")
BGDC := DllCall("User32.dll\GetDC", "Ptr", This.HBG, "UPtr")
BMPDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr", BGDC, "UPtr")
HBMP := DllCAll("Gdi32.dll\CreateCompatibleBitmap", "Ptr", BGDC, "Int", W, "Int", H, "UPtr")
DllCall("Gdi32.dll\SelectObject", "Ptr", BMPDC, "Ptr", HBMP)
MEMDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr", BGDC, "UPtr")
HMEM := DllCAll("Gdi32.dll\CreateCompatibleBitmap", "Ptr", BGDC, "Int", W, "Int", H, "UPtr")
DllCall("Gdi32.dll\SelectObject", "Ptr", MEMDC, "Ptr", HMEM)
DllCall("Gdi32.dll\BitBlt", "Ptr", BMPDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", BGDC, "Int", This.Left, "Int", This.Top, "UInt", SRCCOPY)
DllCall("User32.dll\ReleaseDC", "Ptr", This.HBG, "Ptr", BGDC)
This.BMPDC := BMPDC
This.HBMP := HBMP
This.MEMDC := MEMDC
This.HMEM := HMEM
LBDC := DllCall("User32.dll\GetDC", "Ptr", hWnd, "UPtr")
DllCall("Gdi32.dll\BitBlt", "Ptr", LBDC, "Int", 0, "Int", 0, "Int", W, "Int", H
, "Ptr", This.BMPDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)
DllCall("User32.dll\ReleaseDC", "Ptr", hWnd, "Ptr", LBDC)
This.HasBackground := True
}
Return True
}
; WM_DESTROY message ---------------------------------------------------------------------------------------------
If (uMsg = WM.DESTROY) { ; fully processed
This.__Delete()
}
Return DllCall("Comctl32.dll\DefSubclassProc", "Ptr", hWnd, "UInt", uMsg, "Ptr", wParam, "Ptr", lParam)
}
}