Class TransparentListBox

Post your working scripts, libraries and tools for AHK v1.1 and older
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: Class TransparentListBox

16 May 2016, 08:15

The update did not fix it. But, wow! After further research, I've discovered this is a "bug" with the native AHK ListBox and not your class :) I also noticed this behavior with non-AutoHotKey applications, so apparently it's a normal Windows thing.

Here's what happening: After launching an explorer.exe process (such as launching a folder) apparently explorer.exe sends the WM_Paint message. The Listbox (both AHK's and yours) repaints when this happens. I've provided a script below which should make this pretty clear.

So it's perfectly defensible for your script to keep doing what it is doing. For what it's worth, I would like a way to opt out of the redrawing procedure upon launching explorer.exe because I've never used a ListBox which is dependent upon anything that happens within explorer.exe. But I can easily do this on my own and then post the code in case you want to add it to the class.

Code: Select all

#NoEnv
Loop, %A_WinDir%\Web\Wallpaper\*.jpg, 0, 1
{
   PicFile := A_LoopFileLongPath
   Break
}
; PicFile := A_WinDir . "\Web\Wallpaper\Blaues Fenster.jpg"   ; German Win XP
; PicFile := A_WinDir . "\Web\Wallpaper\Landscapes\img7.jpg"  ; Win 7
; PicFile := A_WinDir . "\Web\Wallpaper\theme2\img10.jpg"     ; Win 8.1
Content := "One|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|Eleven|Twelve|Thirteen|Fourteen|Fifteen|Sixteen"
; ----------------------------------------------------------------------------------------------------------------------
Global hMain
Gui, New, hwndhMain
Gui, Font, s12
Gui, Add, Picture, x0 y0 w600 h400 hwndhPic, %PicFile%
Gui, Add, ListBox, x50 y50 w200 r8 vLB1 gSel1 Choose1, %Content%
Gui, Add, ListBox, x+100 yp wp hp hwndhLB vLB Choose1 gSelection -VScroll -E0x0200, %Content%
TLB := New TransparentListBox(hLB, hPic, 0xFFFFFF, 0x000000, 0xFFFFFF, 128)
Gui, Show, w600 h400, Transparent ListBox
Return
; ----------------------------------------------------------------------------------------------------------------------
GuiClose:
ExitApp
; ----------------------------------------------------------------------------------------------------------------------
#If WinActive("ahk_id " . hMain)
!x::
   Random, R, 0, % TLB.ItemCount
   GuiControl, %hMain%:Choose, LB, %R%
Return
#If
; ----------------------------------------------------------------------------------------------------------------------
Selection:
   GuiControlGet, LB
   ToolTip, Selected: %LB%`nA_GuiEvent: %A_GuiEvent%`nA_EventInfo: %A_EventInfo%
   SetTimer, KillTT, -750
Return
Sel1:
   GuiControlGet, LB1
   ToolTip, Selected: %LB1%`nA_GuiEvent: %A_GuiEvent%`nA_EventInfo: %A_EventInfo%
   Msgbox Move your mouse off the listbox and then keep your eyes on the corners of the listbox
		Run, %A_WinDir%
   SetTimer, KillTT, -750
Return
KillTT:
   ToolTip
Return
; ----------------------------------------------------------------------------------------------------------------------
#Include Class_TransparentListBox.ahk
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

16 May 2016, 10:04

Thanks for testing.

Maybe it's due to my old eyes, but I cannot see any abnormal when running your test script.
Verdlin
Posts: 63
Joined: 04 Oct 2013, 08:55
Contact:

Re: Class TransparentListBox

17 May 2016, 06:50

Interesting. I just noticed your signature says you run Win 10 Pro. I typically use Win 7 pro. I'm guessing that's the difference. I suppose it's not an issue in newer versions of windows.
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Class TransparentListBox

30 Oct 2016, 12:15

Hello.

I'm using this class and I have two questions:
1.- Is it possible to center the text of each item in the listbox?
2.- I have three items (Notepad, Mala and HyperSpin) in my listbox. If I press la n key in my keyboard, Notepad item is selected or if I press the m key then Mala is selected. Is it possible to disable this option in the class?

Thanks very much for your class.

Greetings
Everything is possible!
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

06 Nov 2016, 03:50

  1. You might try to add the DT_CENTER (0x01) flag to the DrawText uFormat parameter:

    Code: Select all

                DllCall("User32.dll\DrawText", "Ptr", LBDC, "Ptr", &Txt, "Int", Len, "Ptr", &RECT, "UInt", 0x0841)
  2. You might try to add the following to SubClassProc:

    Code: Select all

          ; ----------------------------------------------------------------------------------------------------------------
          ; Keyboard
          ; ----------------------------------------------------------------------------------------------------------------
          ; WM_CHAR message
          If (uMsg = 0x0102)
             Return 0
I didn't test both.
User avatar
empardopo
Posts: 336
Joined: 06 Oct 2013, 12:50
Location: Spain
Contact:

Re: Class TransparentListBox

06 Nov 2016, 15:01

I've just take a look changing the class and my first impression is that it works fine!!!! Thanks very much!
Everything is possible!
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: Class TransparentListBox

27 May 2021, 17:30

@just me
When a listbox using the Class TransparentListBox, is above a gif the cpu keeps increasing the entire time.

If you could test, comment this line and compare cpu before/after

Code: Select all

TLB := New TransparentListBox(hLB, hMain, TxtColor:=0xFFFFFF, SelColor:=0x000000, SelBkGnd:=0x8a11e0, SelBkTrans:=255)
Im trying to figure out the source of the problem :think:

Code: Select all

SetBatchLines, -1
pToken := Gdip_Startup()

Content := "One|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|Eleven|Twelve|Thirteen|Fourteen|Fifteen|Sixteen"

Gui, New, hwndhMain +E0x02000000 +E0x00080000
Gui, Font, s12

Gui, Add, ListBox, x70 y50 w100 r8 vLB1 Choose1, %Content%

Gui, Add, ListBox, x200 y50 w100 r8 hwndhLB vLB Choose1 -VScroll -E0x0200 , %Content%

Gui, Add, Picture, xp y0 0xE hwndhGif1 vGif1

Gui, Show, w600 h400, Transparent ListBox

Global TLB
TLB := New TransparentListBox(hLB, hMain, TxtColor:=0xFFFFFF, SelColor:=0x000000, SelBkGnd:=0x8a11e0, SelBkTrans:=255)

Return



F2::
   Gif_1 := New Gif("tenor.gif", hGif1 )
   Gif_1.Play(50)
return



Class Gif {

   __New(File, Hwnd, Width:=0, Height:=0) {

      this.File := File	
      this.Hwnd := Hwnd

      ;FileAppend, File:%File% `n,*

      this.pBitmap := Gdip_CreateBitmapFromFile(File)
      ;this.pBitmap := pBitmapFromResource(file)

      Gdip_GetImageDimensions(this.pBitmap, pWidth, pHeight)

      if (Width != 0) {
         this.Width := Width
         this.Height := Height
      } else {
         this.Width := pWidth
         this.Height := pHeight
      }

      this.isPlaying := false

      DllCall("Gdiplus\GdipImageGetFrameDimensionsCount", "ptr", this.pBitmap, "uptr*", frameDimensions)
      this.SetCapacity("dimensionIDs", 32)

      DllCall("Gdiplus\GdipImageGetFrameDimensionsList", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int", frameDimensions)

      DllCall("Gdiplus\GdipImageGetFrameCount", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int*", count)

      this.frameCount := count
      this.frameCurrent := -1

   }



   Play(interval:=100) {
      this.isPlaying := true
      fn := this._Play.Bind(this)
      this._fn := fn
      SetTimer, % fn, % interval
   }



   Pause(){
      this.isPlaying := false
      fn := this._fn
      SetTimer, % fn, Delete

   }



   ; Remember to add 0xE flag in the picture control

   _Play()
   {

      this.frameCurrent := (this.frameCurrent = this.frameCount-1) ? 0 : this.frameCurrent + 1		

      CurrentFrame := this.frameCurrent
      FrameCount := this.frameCount
      ;FileAppend CurrentFrame: %CurrentFrame%    FrameCount: %FrameCount% `n, *	

      DllCall("Gdiplus\GdipImageSelectActiveFrame", "ptr", this.pBitmap, "uptr", this.GetAddress("dimensionIDs"), "int", this.frameCurrent)

      
      hBitmap := Gdip_CreateHBITMAPFromBitmap(this.pBitmap)

      SetImage(this.hwnd, hBitmap)
      DeleteObject(hBitmap)
      
      TLB.Update()


   }



   __Delete() {
      Gdip_DisposeImage(this.pBitmap)
      Object.Delete("dimensionIDs")
   }

}

As long it keeps running the computer starts to freeze :? :shock:

Some conclusions:

- CPU keeps increasing even if you remove the line TLB.Update() inside Class Gif, but this happens only if the gif is under the listbox, if you move it away, the CPU doesn't increase.

- Deleting and making a new does no impact when there's already a high CPU usage and there's the option TLB.Update() inside Class Gif

Code: Select all

F3::
TLB.__Delete()
TLB := New TransparentListBox(hLB, hGif1, TxtColor:=0xFFFFFF, SelColor:=0x000000, SelBkGnd:=0x8a11e0, SelBkTrans:=255)
return
- Deleting while there's no TLB.Update() inside Class Gif does "free" the high CPU usage, but without the option TLB.Update() the background doesn't get redraw.
TLB.__Delete()



-------------------
Ok after the entire day debugging the script i think i have isolated the source of the problem, its something inside:

Code: Select all

If (uMsg = WM.PAINT)
That is causing the high CPU. Maybe an object that needs to be deleted?

Comparing cpu usage with and without transparency activated:
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

28 May 2021, 05:20

; After you've changed the content or size of the ListBox, or if you want to change the text or selection color, you
; have to call 'TLB.Update()' once, passing the new color values if desired. The whole action should be enclosed by
; two calls of 'TLB.SetRedraw(False/True)' to avoid flickering as far as possible.
TLB.UpDate() is not designed to update a background changing at a 'high' frequency. Also, the current version possibly does not free the GDI resources used for the previous background:
This.BMPDC / This.HBMP / This.SELDC / This.HSEL[/code]
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: Class TransparentListBox

28 May 2021, 08:45

There’s any other version ?
I was reading the source of your other lib CtlColors, and see it also support transparency:

Code: Select all

If (CTL.BkColor = "Trans")
         DllCall("Gdi32.dll\SetBkMode", "Ptr", HDC, "UInt", 1)
I tested the same script with the GIF and looks like its don't cause high CPU usage over time :clap:

But there's no option in CtlColors to colorize the current selection in the ListBox like does have in the TransparentListBox lib:
image.png
image.png (150.82 KiB) Viewed 1911 times
I tried to port the code to change the selection background from Class TransparentListBox lib:

Code: Select all

If (This.SelBkGnd <> "") {
	.....
}
But i could not get it working, my attempt:

Code: Select all

CtlColors_OnMessage(HDC, HWND) {
   Critical
   If CtlColors.IsAttached(HWND) {
      CTL := CtlColors.Attached[HWND]
      If (CTL.TxColor != "")
         DllCall("Gdi32.dll\SetTextColor", "Ptr", HDC, "UInt", CTL.TxColor)
      If (CTL.BkColor = "Trans")
         DllCall("Gdi32.dll\SetBkMode", "Ptr", HDC, "UInt", 1) ; TRANSPARENT = 1
      Else
         DllCall("Gdi32.dll\SetBkColor", "Ptr", HDC, "UInt", CTL.BkColor)

      SelBkGnd = 0x8a11e0

      ;SelBkGnd := ((SelBkGnd >> 16) & 0xFF) | (SelBkGnd & 0x00FF00) | ((SelBkGnd & 0xFF) << 16)

      If (SelBkGnd <> "") {
         
         FileAppend, SelBkGnd: %SelBkGnd% hMain: %hMain% `n,*
         
         Static SRCCOPY := 0x00CC0020

         VarSetCapacity(RECT, 16, 0)
         DllCall("User32.dll\GetClientRect", "Ptr", HWND, "Ptr", &RECT)
         Width := W := NumGet(RECT, 8, "Int")
         Height := H := NumGet(RECT, 12, "Int")

         DllCall("User32.dll\ClientToScreen", "Ptr", HWND, "Ptr", &RECT)
         DllCall("User32.dll\ScreenToClient", "Ptr", hMain, "Ptr", &RECT)
         Left := L := NumGet(RECT, 0, "Int")
         Top := T := NumGet(RECT, 4, "Int")
         BGDC := DllCall("User32.dll\GetDC", "Ptr", hMain, "UPtr")

         ; ----------------------------------------

         SELDC := DllCall("Gdi32.dll\CreateCompatibleDC", "Ptr", BGDC, "UPtr")

         HSEL := DllCall("Gdi32.dll\CreateCompatibleBitmap", "Ptr", BGDC, "Int", ItemWidth, "Int", ItemHeight, "UPtr")

         ;FileAppend, -> BGDC: %BGDC% HDC: %HDC% HSEL: %HSEL% `n,*

         DllCall("Gdi32.dll\SelectObject", "Ptr", SELDC, "Ptr", HSEL)

         Brush := DllCall("Gdi32.dll\CreateSolidBrush", "UInt", SelBkGnd, "UPtr")

         VarSetCapacity(RECT, 16, 0)
         NumPut(ItemWidth, RECT, 8, "Int")
         NumPut(ItemHeight, RECT, 12, "Int")

         DllCall("User32.dll\FillRect", "Ptr", SELDC, "Ptr", &RECT, "Ptr", Brush)

         ;DllCall("User32.dll\FillRect", "Ptr", BGDC, "Ptr", &RECT, "Ptr", Brush)

         DllCall("Gdi32.dll\DeleteObject", "Ptr", Brush)

         ; ------------------------------------------

         DllCall("User32.dll\ReleaseDC", "Ptr", HWND, "Ptr", BGDC)

         ;LBDC := DllCall("User32.dll\GetDC", "Ptr", hWnd, "UPtr")

         ;DllCall("Gdi32.dll\BitBlt", "Ptr", LBDC, "Int", 0, "Int", 0, "Int", W, "Int", H
         ;, "Ptr", BMPDC, "Int", 0, "Int", 0, "UInt", SRCCOPY)

         ;DllCall("User32.dll\ReleaseDC", "Ptr", hWnd, "Ptr", LBDC)

      }

      Return CTL.Brush
   }
}

I wonder if you could help me which it
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

29 May 2021, 06:26

The whole control will be redrawn after the message handler returns. There's no chance to redraw only parts of the list within the message handler.
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: Class TransparentListBox

29 May 2021, 06:40

@just me could you point where the code needs to go then ?
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

29 May 2021, 08:49

@c7aesa7r, exactly there where you copied it from.
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: Class TransparentListBox

29 May 2021, 11:01

But the code there does not change the current listbox selection color, could you provide an example? Im using the CTLColor lib now as it doesn't cause high cpu usage
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: Class TransparentListBox

05 Jun 2021, 03:44

@just me can you help add support to when the listbox has the option -multi?
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

05 Jun 2021, 04:30

-Multi -> single select.
Which script do you use to obtain transparency?
c7aesa7r
Posts: 209
Joined: 02 Jun 2016, 21:09

Re: Class TransparentListBox

05 Jun 2021, 05:08

Im current using this one where are now, Class TransparentListBox
When you add the option -Multi, it does not select anything
just me
Posts: 9457
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Class TransparentListBox

05 Jun 2021, 09:26

I cannot see any problem for -Multi here, but for +Multi.
It's documented:

Code: Select all

; Due to the complex way ListBoxes do their scrolling not all options of a common ListBox are supported.
; You have to keep in mind the following restrictions:
; - The new object instance has to be created before the Gui is shown.
; - The ListBox must not have a horizontal scroll bar (because I haven't a clue how to do the scrolling).
; - The Multi(select) option is not supported as yet (but it may be feasible).
; - Scrolling is not 'smooth'.
Support for multi-selection would still be rather complicated. Perhaps someone else will do it.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 140 guests