Page 1 of 1

Windows: use the shell progress dialog in your apps.

Posted: Sat Jan 22, 2005 1:42 pm
by El_Choni
Code updated for 5.20+

Hi,

The subject says it all:

Code: Select all

; Tested on Windows XP Pro SP1

Procedure Ansi2Uni(st$)
  CompilerIf #PB_Compiler_Unicode ; Already in correct format, just copy it
    blen = (Len(st$)+1)*SizeOf(Character)
    wbuf = AllocateMemory(blen)
    CopyMemory(@st$, wbuf, blen)
  CompilerElse
    blen = (Len(st$)*2)+2
    wbuf = AllocateMemory(blen)
    MultiByteToWideChar_(#CP_ACP, 0, st$, -1, wbuf, blen)
  CompilerEndIf
  ProcedureReturn wbuf
EndProcedure

#CLSCTX_INPROC_SERVER = 1

#PROGDLG_NORMAL = 0
#PROGDLG_AUTOTIME = 2

#PDTIMER_RESET = 1

#IDA_COPY_ANIMATION = 160 ; AVI file resource ID (I use an arbitrary constant name)
; This one is from shell32.dll.
; You can use any AVI file resource as long as it's
; uncompressed or RLE8 compressed, silent and
; smaller or equal to 272 by 60 pixels in size.

ProgressLimit = 1000

CoInitialize_(0)
hr = CoCreateInstance_(?CLSID_ProgressDialog, #Null, #CLSCTX_INPROC_SERVER, ?IID_IProgressDialog, @ppv.IProgressDialog)
If hr=#S_OK
  *Title = Ansi2Uni("System progress dialog box")
  ppv\SetTitle(*Title)
  hShell = OpenLibrary(0, "shell32.dll")
  If hShell
    ppv\SetAnimation(hShell, #IDA_COPY_ANIMATION)
  EndIf
  *Cancel = Ansi2Uni("Cancel")
  ppv\SetCancelMsg(*Cancel, 0)
  *Line1 = Ansi2Uni("System progress dialog test in PureBasic")
  ppv\SetLine(1, *Line1, #True, 0)
  ppv\StartProgressDialog(#Null, 0, #PROGDLG_AUTOTIME|#PROGDLG_NORMAL, 0)
  ppv\Timer(#PDTIMER_RESET, 0)
  Repeat
    If ppv\HasUserCancelled()
      MessageRequester("Messsage", "Progress cancelled")
      Break
    Else
      ppv\SetProgress(dwCompleted, ProgressLimit)
      If dwCompleted>=ProgressLimit
        MessageRequester("Messsage", "Progress completed")
        Break
      Else
        dwCompleted+1
        *Line2 = Ansi2Uni("We are at progress point number "+Str(dwCompleted))
        ppv\SetLine(2, *Line2, #True, 0)
        FreeMemory(*Line2)
      EndIf
    EndIf
    Delay(100)
  ForEver
  ppv\StopProgressDialog()
  ppv\Release()
  FreeMemory(*Title)
  FreeMemory(*Cancel)
  FreeMemory(*Line1)
  If hShell:CloseLibrary(0):EndIf
Else
  Debug Hex(hr)
EndIf
CoUninitialize_()

DataSection
  CLSID_ProgressDialog:
  Data.l $f8383852
  Data.w $fcd3, $11d1
  Data.b $a6, $b9, 0, $60, $97, $df, $5b, $d4
  IID_IProgressDialog:
  Data.l $ebbc7c04
  Data.w $315e, $11d2
  Data.b $b6, $2f, 0, $60, $97, $df, $5b, $d4
EndDataSection
Regards,

Posted: Sat Jan 29, 2005 1:31 am
by GeoTrail
Abit over my head, but the result is really cool.
Great work El_Choni :)

Posted: Mon Jan 31, 2005 10:31 pm
by TerryHough
Thanks El_Choni, I have wondered how to do this.

Two questions.

1) How to make the progress bar smooth (like PB flag)

2) How is the time determined. Sorry, I don't recogninze that in the code.


Terry

Posted: Mon Jan 31, 2005 11:16 pm
by Le Soldat Inconnu
very nice :D

Posted: Tue Feb 01, 2005 6:55 pm
by eriansa
very handy! thanks.

Re: Windows: use the shell progress dialog in your apps.

Posted: Wed Feb 02, 2005 2:34 am
by NoahPhense
That's purty.. nice work

- np

Posted: Wed Feb 02, 2005 10:45 am
by El_Choni
TerryHough wrote: Two questions.
1) How to make the progress bar smooth (like PB flag)
2) How is the time determined. Sorry, I don't recogninze that in the code.
1) I think you can't, this is a system-predefined dialog box, good to avoid doing the job yourself. If you want to modify it, better do your own dialog.
2) Windows estimates the remaining time. The more 'progress intermediate points' you use, the more accurate will be the result.

I've edited the snippet, now it uses 1000 instead of 100, and Windows estimates the remaining time much better.

You can change that value here:

Code: Select all

ProgressLimit = 1000
Anyway, in real life you would probably put the update stuff in a timer proc while you're, for example, copying a file. The timer proc would check for the amount of bytes copied (using a critical section, for example), and update the progress dialog according to that.

Regards,

Posted: Thu Feb 03, 2005 2:46 am
by sverson
Great work! :wink:

Tested on WIN NT4 SP6 - running fine!

Posted: Thu Feb 03, 2005 11:26 am
by Le Soldat Inconnu
Time estimation is only calculate with the progresslimit ??

when I change the delay, I always obtain the same time estimation.

ProgressLimit is the time in second * 10

example :
ProgressLimit = 10 * 60 gives 60s time remaining
ProgressLimit = 10 * 60 * 5 gives 5min time remaining