This example just shows the taskbar button progressbar,
I leave it to others to toy around with taskbar thumbnail toolbar controls. (mini play/pause at bottom of thumb preview for example),
or changing the thumb tooltip and whatnot.
There is also a ITaskbarList4 but it only ads one method so it's not used in this code...
If anyone see any mistakes (I'm green when it comes to interfaces and COM!) by all means post corrections.
Introducing The Taskbar APIs
ITaskbarList3
Code: Select all
;Public Domain
EnableExplicit
#PB_Compiler_Exe=#True ;This does not exist (yet?)
;http://msdn.microsoft.com/en-us/library/dd464660%28VS.85%29.aspx
Global _ScaleDPI_X_.f=1.0,_ScaleDPI_Y_.f=1.0,_ScaleDPI_font_$
#DefaultDPIX=96.0 ;Different platforms might have different default DPI, Windows is 96 DPI.
#DefaultDPIY=96.0
Procedure InitScaleDPI() ;Windows 5.0 or higher needed for minimum functionality of this procedure.
Protected dpiaware.l=#False,dc.i,lpx.i,lpy.i,dll.i,*SetProcessDPIAware,*IsProcessDPIAware,ncm.NONCLIENTMETRICS,font.i
;This part is Windows 6.x+ only (Vista etc.) and must be done before we use devcaps.
;http://msdn.microsoft.com/en-us/library/dd464660%28VS.85%29.aspx#declaring_dpi_awareness
;You really should use the DPI aware manifest instead of SetProcessDPIAware() when possible.
;On Windows 2000 and XP the manifest has no effect and set dpi aware is not available,
;however Devicecaps still returns usefull info that can be used.
;Note! If the dpi aware manifest is missing on Vista and Win7 then the OS will lie on devicecaps and will autoscale the entire app window.
CompilerIf #PB_Compiler_Exe ;Only use this in exes, as dlls inherit DPI from the calling process.
;If the exe or the calling exe in case of this being a dll is allready dpi aware (like through a manifest),
;then we skip using the the set dpi aware function, a dll should never use the set function, but it should check if the process id dpi aware
;and apply the proper modifiers where appropriate obviously.
dll=OpenLibrary(#PB_Any,"user32.dll")
If dll
*IsProcessDPIAware=GetFunction(dll,"IsProcessDPIAware")
If *IsProcessDPIAware
dpiaware=CallFunctionFast(*IsProcessDPIAware)
EndIf
If Not dpiaware
*SetProcessDPIAware=GetFunction(dll,"SetProcessDPIAware")
If *SetProcessDPIAware
CallFunctionFast(*SetProcessDPIAware)
EndIf
EndIf
EndIf
CompilerEndIf
dc=GetDC_(#Null)
If dc
lpx=GetDeviceCaps_(dc,#LOGPIXELSX)
lpy=GetDeviceCaps_(dc,#LOGPIXELSY)
If lpx>0
_ScaleDPI_X_=lpx/#DefaultDPIX
EndIf
If lpy>0
_ScaleDPI_Y_=lpy/#DefaultDPIY
EndIf
ReleaseDC_(#Null,dc)
EndIf
;Get the system font for message boxes etc.
;We default to a size of 9, which is also the Vista and Win7 default size.
;The OS will automatically (Vista and Win7 at least) scale the font per the current user's DPI setting.
ncm\cbSize=SizeOf(NONCLIENTMETRICS)
If SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS,SizeOf(NONCLIENTMETRICS),ncm,#Null)
_ScaleDPI_font_$=PeekS(@ncm\lfMessageFont\lfFaceName)
font=LoadFont(#PB_Any,_ScaleDPI_font_$,9,#PB_Font_HighQuality)
If font
SetGadgetFont(#PB_Default,FontID(font))
EndIf
EndIf
EndProcedure
InitScaleDPI()
Macro ScaleDPIx(x)
(x)*_ScaleDPI_X_
EndMacro
Macro ScaleDPIy(y)
(y)*_ScaleDPI_Y_
EndMacro
Macro ScaleDPIfont()
_ScaleDPI_font_$
EndMacro
#CLSCTX_ALL = 0
#TBPF_NOPROGRESS = $0
#TBPF_INDETERMINATE = $1
#TBPF_NORMAL = $2
#TBPF_ERROR = $4
#TBPF_PAUSED = $8
#TBATF_USEMDITHUMBNAIL = $1
#TBATF_USEMDILIVEPREVIEW = $2
#THB_BITMAP = $1
#THB_ICON = $2
#THB_TOOLTIP = $4
#THB_FLAGS = $8
#STPF_NONE = $00000000
#STPF_USEAPPTHUMBNAILALWAYS = $00000001
#STPF_USEAPPTHUMBNAILWHENACTIVE = $00000002
#STPF_USEAPPPEEKALWAYS = $00000004
#STPF_USEAPPPEEKWHENACTIVE = $00000008
Structure THUMBBUTTON
dwMask.l
iId.l
iBitmap.l
hIcon.i
szTip.u[260]
dwFlags.l
EndStructure
Interface ITaskbarList3 Extends ITaskbarList2
SetProgressValue.i(hWnd.i,ullCompleted.q,ullTotal.q)
SetProgressState.i(hWnd.i,tbpFlags.l)
RegisterTab.i(hWndTab.i,hWndMDI.i)
UnregisterTab.i(hWndTab.i)
SetTabOrder.i(hWndTab.i,hWndInsertBefore.i)
SetTabActive.i(hWndTab.i,hWndMDI.i,tbatFlags.l)
ThumbBarAddButtons.i(hWnd.i,cButtons.l,*pButton)
ThumbBarUpdateButtons.i(hWnd.i,cButtons.l,*pButton)
ThumbBarSetImageList.i(hWnd.i,himl.i)
SetOverlayIcon.i(hWnd.i,hIcon.i,pszDescription$)
SetThumbnailTooltip.i(hWnd.i,pszTip$)
SetThumbnailClip.i(hWnd.i,*prcClip)
EndInterface
Interface ITaskbarList4 Extends ITaskbarList3
SetTabProperties.i(hwndTab.i,stpFlags.l)
EndInterface
DataSection
CLSID_TaskBarList:
Data.l $56FDF344
Data.w $FD6D, $11D0
Data.b $95, $8A, $00, $60, $97, $C9, $A0, $90
IID_ITaskBarList3:
Data.l $ea1afb91
Data.w $9e28,$4b86
Data.b $90,$E9,$9e,$9f,$8a,$5e,$ef,$af
EndDataSection
Enumeration 1
#Window_Main
EndEnumeration
Enumeration 1
#Gadget_Main_Text
#Gadget_Main_Progress
EndEnumeration
Enumeration 1
#Timer_Progress
EndEnumeration
InitScaleDPI()
Define ptl.ITaskbarList3,event,progress,progressmax,pp.ITaskbarList3
;Note1: It seems that CoInitialize, HrInit and CoUninitialize are not needed (does PB apply these?)
;Note2: Only tried this on Windows 7, does Vista display the taskbutton progress?
;Note3: You should wait to use the taskbar stuff until the taskbar button has been created.
; DWORD g_wmTBC = (DWORD)-1;
;
; //In the window Procedure:
; switch (msg) {
; Case WM_CREATE:
; g_wmTBC = RegisterWindowMessage(L"TaskbarButtonCreated");
; //Proceed To create the window
; Case g_wmTBC:
; //The taskbar button has been created
; }
If OpenWindow(#Window_Main,0,0,ScaleDPIx(320),ScaleDPIy(160),"ProgressBar",#PB_Window_ScreenCentered|#PB_Window_MinimizeGadget)
progress=0
progressmax=100
TextGadget(#Gadget_Main_Text,ScaleDPIx(10),ScaleDPIy(10),ScaleDPIx(250),ScaleDPIy(20),"Progress ("+Str(progress)+"/"+Str(progressmax)+")",#PB_Text_Center)
ProgressBarGadget(#Gadget_Main_Progress,ScaleDPIx(10),ScaleDPIy(30),ScaleDPIx(250),ScaleDPIy(30),0,100)
SetGadgetState(#Gadget_Main_Progress,progress)
CoInitialize_(#Null)
CoCreateInstance_(?CLSID_TaskBarList,#Null,1,?IID_ITaskBarList3,@ptl)
If ptl
ptl\HrInit()
ptl\SetProgressValue(WindowID(#Window_Main),progressmax,progressmax)
ptl\SetProgressState(WindowID(#Window_Main),#TBPF_INDETERMINATE)
EndIf
AddWindowTimer(#Window_Main,#Timer_Progress,1000)
Repeat
event=WaitWindowEvent()
If event=#PB_Event_Timer
progress+1;Random(progressmax)
SetGadgetState(#Gadget_Main_Progress,progress)
SetGadgetText(#Gadget_Main_Text,"Progress ("+Str(progress)+"/"+Str(progressmax)+")")
If ptl
If progress=5
ptl\SetProgressState(WindowID(#Window_Main),#TBPF_NORMAL)
RemoveWindowTimer(#Window_Main,#Timer_Progress)
AddWindowTimer(#Window_Main,#Timer_Progress,100)
ElseIf progress>5
ptl\SetProgressValue(WindowID(#Window_Main),progress,progressmax)
EndIf
EndIf
If progress=101
RemoveWindowTimer(#Window_Main,#Timer_Progress)
AddWindowTimer(#Window_Main,#Timer_Progress,1000)
ptl\SetProgressState(WindowID(#Window_Main),#TBPF_PAUSED)
ElseIf progress=102
ptl\SetProgressState(WindowID(#Window_Main),#TBPF_NORMAL)
ElseIf progress=103
ptl\SetProgressState(WindowID(#Window_Main),#TBPF_ERROR)
ElseIf progress=104
ptl\SetProgressState(WindowID(#Window_Main),#TBPF_INDETERMINATE)
progress=0
EndIf
EndIf
Until event=#PB_Event_CloseWindow
EndIf
RemoveWindowTimer(#Window_Main,#Timer_Progress)
If ptl
ptl\Release()
EndIf
CloseWindow(#Window_Main)
CoUninitialize_()