Page 1 of 2

ProgressBarGadget on Vista bug?

Posted: Thu Aug 28, 2008 10:35 am
by whertz
It seems the progressbargadget does not get updated properly on Windows Vista. The following code works properly on XP with or without the XP skins mode selected, but on Vista the bar only goes about a quarter of the way up. On XP the bar goes all the way to the top. If you compile without XP skins support, it does work on Vista. Anyone know of a solution? I think the problem lies with adding items to the listicongadget, if you comment it out, the bar works properly. Here's the code:

Code: Select all

Procedure addtolist()
  For n2=0 To 150
    AddGadgetItem(1,-1,Str(Random(10000)))
  Next n2
EndProcedure

If OpenWindow(0, 0, 0, 600, 100, "ProgressBarGadget Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  ListIconGadget(1,10,10,580,80,"",100)
  ProgressBarGadget(0,  10, 40, 580,  20, 0, 200)  
  HideGadget(1,1)
  For n=0 To 200
    addtolist()
    SetGadgetState(0,n)
    While WindowEvent():Wend
  Next n
  HideGadget(0,1)
  HideGadget(1,0)
  
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow
EndIf

Posted: Thu Aug 28, 2008 10:47 am
by srod
Take away the HideGadget(0,1) and it works fine here on Vista with xp themes enabled or not. I did have to move the progress bar because it does sit atop the listicon!

Posted: Thu Aug 28, 2008 10:56 am
by whertz
srod wrote:Take away the HideGadget(0,1) and it works fine here on Vista with xp themes enabled or not. I did have to move the progress bar because it does sit atop the listicon!
Thanks srod, but I want the listicongadget hidden while I add items to it, so your solution does not work for me.

Posted: Thu Aug 28, 2008 11:02 am
by srod
Sorry, I see what you're after.

Yes, not a PB bug as such; a Vista peculiarity. The fact is that the progress bar is being updated faster than the system can redraw. Stick in a sizeable delay and all works fine. There must be a better way though...

Posted: Thu Aug 28, 2008 11:09 am
by whertz
Yes, adding a delay works to an extent. The bar still doesn't go all the way to the top, there's still a bit to go! But this way is bad anyway, because I'm adding a lot of items and doing other stuff when adding to the listicongadget, so any delay is not good.

Posted: Thu Aug 28, 2008 12:00 pm
by srod
Right, after much poking and prodding I can see what is happening. Because of the visual style applied to the progress bar under Vista (the marquee type effect), the rendering of the actual bar can lag behind the actual position of the slider etc. What Windows does is 'buffer' the drawing and sets up a timer in order to complete the drawing in stages.

Now, your code has no way of knowing when this timer completes and so is issuing the HideGadget() command too early. What we need is some way of determining when this damn timer ends and that is a problem! (Of course a nice message sent from the progress bar to inform us of the completion of this buffered drawing would be nice!)

I have confirmed this by a manual count of the number of times the timer is called etc. and then hidden the progress bar. This works fine, but we cannot rely upon a manual count. Let me try something else...

Posted: Thu Aug 28, 2008 12:11 pm
by srod
Okay, a complete and total utter hack in which I set up a timer to monitor the timer created by Windows in order to complete the painting of the progressbar! :wink: We are snooping upon the snooper!

If this doesn't run in other versions of Windows then you'll need some conditional code to take account of this.

Code: Select all

Global oldProc, progressFlag

Procedure progressCallback(hWnd, uMsg, wParam, lParam)
  Protected result = CallWindowProc_(oldProc, hWnd, uMsg, wParam, lParam)
  Static count
  Select uMsg
    Case #WM_PAINT
      If GetGadgetState(0) = 200
        ;Create a timer to monitor the 'other' timer!
          SetTimer_(hWnd, 100, 10, 0)
      EndIf
    Case #WM_TIMER
      If wParam = 100 ;This is our timer.
        count+1  ;A count of the number of times this timer is called consecutively.
      Else
        count=0
      EndIf
      If count = 10 ;Should be enough to determine that the 'other' timer has completed.  Increase this value if you get problems.
        KillTimer_(hWnd, 100)
        count = 0
        HideGadget(0,1) 
        HideGadget(1,0) 
      EndIf
  EndSelect

  ProcedureReturn result
EndProcedure

Procedure addtolist() 
  For n2=0 To 150 
    AddGadgetItem(1,-1,Str(Random(10000))) 
  Next n2 
EndProcedure 

If OpenWindow(0, 0, 0, 600, 100, "ProgressBarGadget Test", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
  ListIconGadget(1,10,10,580,80,"",100) 
  ProgressBarGadget(0,  10, 40, 580,  20, 0, 200)  
  oldProc = SetWindowLong_(GadgetID(0), #GWL_WNDPROC, @progressCallback()) 
  HideGadget(1,1) 
  For n=0 To 200 
    addtolist() 
    SetGadgetState(0,n) 
  Next n 
  
  Repeat : Until WaitWindowEvent()=#PB_Event_CloseWindow 
EndIf

Posted: Thu Aug 28, 2008 1:34 pm
by Sparkie
Another option might be to remove the theme from the ProgressBarGadget...

Code: Select all

If OSVersion() >= #PB_OS_Windows_Vista
    SetWindowTheme_(GadgetID(0), @null.w, @null.w)
  EndIf

Posted: Thu Aug 28, 2008 1:37 pm
by srod
Yes, I was thinking about that; but to have all that lovely Vista gloss, ...and then remove it! :wink:

Posted: Thu Aug 28, 2008 1:41 pm
by Sparkie
gloss, schmoss....I'll take quick and clean everytime :P

Posted: Thu Aug 28, 2008 1:52 pm
by srod
What, even if it looks like something which fell from fangbeast's left nostril? :twisted:

Posted: Thu Aug 28, 2008 2:01 pm
by Derek
Without the gloss and slowness we might as well be using XP. :lol:

Posted: Thu Aug 28, 2008 2:05 pm
by srod
You don't think XP is faster than Vista then?

Posted: Thu Aug 28, 2008 3:40 pm
by Derek
Yeah, I was trying to say that xp + gloss + slowness (is that a word) = vista. :lol: :lol:

Posted: Thu Aug 28, 2008 3:41 pm
by srod
Oops, sorry; I think you said it clearly enough! srod = daft twit! :)