Jump to content
Tuts 4 You

How to show a progressbar as tray icon?


LCF-AT

Recommended Posts

Posted

Hi guys,

does anyone know a example / way how to set a progressbar into tray as icon to show the progress status?So you know like Taskmanager does it.

Thank you

Posted (edited)

dont think thats a progress bar actually, i think its a generated icon, simply as it doesnt obey themes... on mine, the color is blue, on the standard theme, the progressbars are green and animated...and its probably just an icon generated with a fill rect or something

Edited by evlncrn8
  • Like 2
Posted

So you mean I need to use CreateIconIndirect at the end and draw the colors into rect?I tried something and get this...

2017-01-26_210044.png

...left from takmanager and right one from me but dosent look pretty well so far.Do you know how to make it better anyhow?

greetz

Posted

well the 3d effect is just 2 rectangles, so fill white, offset the rect and fill green, and then draw a hatching pattern or whatnot on it or draw rect, draw the white lines for pseudo 3d... tons of variations

Posted

Do you have any short example code for this?Dont know how to make this hatching etc.I would like to make same as taskmanger.

greetz

Posted

if i had, i'd send it, honest.. but you can see from protectionid, im no graphics whizz :) the patching i think is from a patternbrush, so createbrush might be useful for that

  • Like 1
Posted

@LCF-AT :

I see that you are looking for examples : There are TWO ways to achieve what you wanted to do. They are detailed in the attached PDFs.

Please check out the attachments. They should help give you a very idea of the steps needed for you to achieve your goal. They  are from my collection ...

The examples are for C# and C  but the can be very easily adapted for any programming language of your choice.

The PDFs have clickable hyperlinks in case you want to download the actual Source Code examples.

The original links here and here (but the PDFs have everything in them and there i sno need to actually visit the links).

Links to SOURCE CODE EXAMPLES :

For PDF 1 here and for PDF 2 here .

Good Luck ! :thumbsup:

Animation and Text in System tray using C.pdf

Mastering the system tray.pdf

  • Like 3
Posted

@Techlord: both your links deal with C# - which is nice but several abstraction layers away from pure WinAPI and assembly LCF-AT is using.. ;)

 

  • Like 3
Posted (edited)

@Lcf

The Taskmanager use 12 icons to draw this in the tray.

The simply way is load the icons and put it to nid.hIcon

    .IF eax == 0
        m2m   nid.hIcon,hIconOne
    .ELSEIF eax == 1
        m2m   nid.hIcon,hIconTwo
    .ELSEIF eax == 2
        m2m   nid.hIcon,hIconThree
    .ELSEIF eax == 3
        m2m   nid.hIcon,hIconFour
    .ENDIF
    Invoke Shell_NotifyIcon,NIM_MODIFY,ADDR nid

Or you can use a dword array to store / get the icons .

Edited by ragdog
  • Like 3
Posted
39 minutes ago, kao said:

@Techlord: both your links deal with C# - which is nice but several abstraction layers away from pure WinAPI and assembly LCF-AT is using.. ;)

 

Yes, I did mention that point ..

Also, wanted to give a couple of examples jus in case anyone else would be reading this thread in future :)

Posted

A PureBasic example...

;
; ------------------------------------------------------------------
;
;   Dual SysTray, Threaded & "Animated" "imageres.dll" System Icons
;   "imageres.dll" is available on Window 7 & 8 (Vista??)
;
;   By Teddy Rogers / PureBasic 5.22
;
; ------------------------------------------------------------------
;

; Declare our procedures

Declare WinCallback_Icon1(WindowID, uMsg, wParam, lParam)
Declare WinCallback_Icon2(WindowID, uMsg, wParam, lParam)

Declare SetImage(Icon)
Declare ChangeIcon(void)

; Declare some global variables...

Global Num1 = 100   ; Set our default "imageres.dll" tray icon 1
Global Num2 = 101   ; Set our default "imageres.dll" tray icon 2
Global ThreadID     ; This is used to end the thread
Global IconNum = ExtractIconEx_("imageres.dll", -1, #Null, #Null, #Null)

; Register a message with the "TaskbarCreated" string

Global TaskbarRestart = RegisterWindowMessage_("TaskbarCreated")  

; Define two windows for seperate icons/menu's and callbacks

If OpenWindow(1, 0, 0, 0, 0, "", #PB_Window_Invisible)
  If OpenWindow(2, 0, 0, 0, 0, "", #PB_Window_Invisible)
    
    ; These are the callbacks to watch for events on each of the icons
    
    SetWindowCallback(@WinCallback_Icon1(), 1)
    SetWindowCallback(@WinCallback_Icon2(), 2)
    
    ; Add the system tray icons using icons from "imageres.dll"
    
    AddSysTrayIcon(1, WindowID(1), SetImage(Num1))
    AddSysTrayIcon(2, WindowID(2), SetImage(Num2))
    
    ; Setup some tooltips...
    
    SysTrayIconToolTip(1, "You are hovering over icon 1")     
    SysTrayIconToolTip(2, "You are hovering over icon 2")
    
    ; Create icon 1 menu with PureBasic modern look (we use "imageres.dll" for menu icons)
    
    If CreatePopupImageMenu(1, #PB_Menu_ModernLook)       
      MenuItem(01, "Open", SetImage(174))
      MenuItem(02, "Save", SetImage(39))
      MenuItem(03, "Save as", SetImage(23))
      MenuItem(04, "Quit", SetImage(84))
      MenuBar()
      OpenSubMenu("Recent files")
      MenuItem(05, "PureBasic.exe")
      MenuItem(06, "Test.txt")
      CloseSubMenu()
    EndIf
    
    ; Create icon 2 menu with standard look (we use "imageres.dll" for menu icons)
    
    If CreatePopupImageMenu(2, 0)
      MenuItem(07, "Open", SetImage(174))
      MenuItem(08, "Save", SetImage(39))
      MenuItem(09, "Save as", SetImage(23))
      MenuItem(10, "Quit", SetImage(84))
      MenuBar()
      OpenSubMenu("Recent files")
      MenuItem(11, "PureBasic.exe")
      MenuItem(12, "Test.txt")
      CloseSubMenu()
    EndIf
   
    ; Wait for a MenuItem to be selected... then do some stuff...
   
    Repeat
      Event = WaitWindowEvent()
      Select Event
        Case #PB_Event_Menu
          Select EventMenu()
             
            ; Icon 1 menu actions...
             
            Case 01 : Debug "Menu: Open (Icon 1)"
            Case 02 : Debug "Menu: Save (Icon 1)"
            Case 03 : Debug "Menu: Save as (Icon 1)"
            Case 04 : End
            Case 05 : Debug "Menu: PureBasic.exe (Icon 1)"
            Case 06 : Debug "Menu: Text.txt (Icon 1)"
             
            ; Icon 2 menu actions...
           
            Case 07 : Debug "Menu: Open (Icon 2)"
            Case 08 : Debug "Menu: Save (Icon 2)"
            Case 09 : Debug "Menu: Save as (Icon 2)"
            Case 10 : End
            Case 11 : Debug "Menu: PureBasic.exe (Icon 2)"
            Case 12 : Debug "Menu: Text.txt (Icon 2)"
              
          EndSelect
      EndSelect
    Until Event = #PB_Event_CloseWindow
  EndIf
EndIf

; We will use the Windows default system icons for our own the menu options

Procedure SetImage(Icon)
  
  ExtractIconEx_("imageres.dll", Icon, 0, @iIcon, 1)
  
  If CreateImage(MyImage, 16, 16 ,32)
    StartDrawing(ImageOutput(MyImage))
    Box(0, 0, 16, 16, GetSysColor_(#COLOR_MENU))
    DrawingMode(#PB_2DDrawing_AllChannels)
    DrawImage(iIcon, 0, 0, 16, 16)
    StopDrawing()
  EndIf
  
  DestroyIcon_(iIcon)
  
  ProcedureReturn ImageID(MyImage)
EndProcedure

; Icon Number 1 (clicking left mouse button starts automatic cycling through the icons, clicking left again end the thread)

Procedure WinCallback_Icon1(WindowID, uMsg, wParam, lParam)

  ; End the thread if it is already running or start it...
  
  Select lParam
    Case #WM_LBUTTONDOWN
      If ThreadID
        ThreadID = #Null
      Else
        ThreadID = CreateThread(@ChangeIcon(), 0)
      EndIf
      
      ; Display popup-menu 1
      
    Case #WM_RBUTTONDOWN
      DisplayPopupMenu(1, WindowID(1))  
  EndSelect
  
  ; Listen for "TaskbarCreated" broadcast to be sent to all windows if the taskbar is recreated then...
  ; Recreate our tray icon including the tool tip...
  
  Select uMsg
    Case TaskbarRestart
      AddSysTrayIcon(1, WindowID(1), SetImage(Num1))
      SysTrayIconToolTip(1, "You are hovering over icon 1")
  EndSelect
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

; Icon Number 2 (clicking left mouse button manually cycles through the icons one at a time)

Procedure WinCallback_Icon2(WindowID, uMsg, wParam, lParam)
  
  ; Cycle through "imageres.dll" icons. Windows 7 has 218 and Window 8 has 384!!!
  
  Select lParam    
    Case #WM_LBUTTONDOWN
      Num2 = Num2 + 1
      
      If Num2 > IconNum
        Num2 = 0
      EndIf
      
      ChangeSysTrayIcon(2, SetImage(Num2))
      
      ; Display popup-menu 2
      
    Case #WM_RBUTTONDOWN
      DisplayPopupMenu(2, WindowID(1))
  EndSelect    
  
  ; Listen for "TaskbarCreated" broadcast to be sent to all windows if the taskbar is recreated then...
  ; Recreate our tray icon including the tool tip...  
  
  Select uMsg
    Case TaskbarRestart
      AddSysTrayIcon(2, WindowID(2), SetImage(Num2))
      SysTrayIconToolTip(2, "You are hovering over icon 2")
  EndSelect
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

; Create a thread to cycle through the icons, creating a thread allows us to continue using tray menu(s)

Procedure ChangeIcon(void)
  
  ; Cycle through "imageres.dll" icons. Windows 7 has 218 and Window 8 has 384!!!
  
  Repeat
    Num1 = Num1 + 1
    
    If Num1 > IconNum
      Num1 = 0
    EndIf
    
    Sleep_(500)
    ChangeSysTrayIcon(1, SetImage(Num1))
    
  Until ThreadID = #Null
  
EndProcedure

Ted.

  • Like 1
Posted

Hi guys,

first thank you all for posting some answers. :)

So I thought yesterday also about it to just use diffrent icons to show the progress in system tray.Didnt thought that the taskmanager does it so but now I see the icon set in resources.Hehe. :) I think this would also be the easiest soltuiton.So I will try this first now.

Thanks again so far guys and greetz

Posted

I created an example for you using a library i created for tray menus and icons. The example uses a RadASM 2 project

https://dl.dropboxusercontent.com/u/17077376/ASM_Projects/Traymenu/TaskTray.zip

Example1 button shows using the Task Manager icons to update the tray menu icon randomly. Example2 button shows setting text based icons in the tray, again set randomly (10-100)

To compile the project requires the TrayMenu library i created, which can be downloaded here: https://dl.dropboxusercontent.com/u/17077376/ASM_Projects/Traymenu/traymenu.zip

Or from the project homepage: http://www.letthelight.in/projects/released-controls/traymenu-control

Includes a TrayMenu.chm file, TrayMenu.inc, TrayMenu.lib, (and a few other files for use in RadASM for its auto api help type thing)

Anyhow hope that helps

  • Like 2
Posted

Hi fearless,

thank you for your example files / lib.

So do you have another created libs which could be interesting?

Maybe you can help with another thing.So before a while I tried to work with baloontips but had the problem that I coulnt set any custom or system icons into hBalloonIcon.I just always get the blue info icon to see in the baloon.Maybe you have any short example / code for this too.

PS: Do you also have any latest windows.inc file?So it seems they dont get updated anymore or everyone has to do this by himself.

greetz

Posted

I've a few other older projects on my site (www.LetTheLight.in) that might be of use/interest

http://www.letthelight.in/index.php/projects/released-controls/spinner-control

http://www.letthelight.in/index.php/projects/released-controls/circlebar-control

http://www.letthelight.in/index.php/projects/released-controls/smartanchor-control

 

Plus some stuff i started working on a while ago on Github

A framework and some controls written in asm x86 and x64 to give a modern UI look to assembler programs, influenced by the window MDL and Metro apps etc: https://github.com/mrfearless/ModernUI  /  https://github.com/mrfearless/ModernUI64

The releases page has some screenshots to show how some of the controls look: https://github.com/mrfearless/ModernUI/releases  /  https://github.com/mrfearless/ModernUI64/releases

 

The windows.inc and most other .inc files I use from the MASM32 SDK package, which can be downloaded here: http://masm32.com/download.htm

Shouldn't be too much an issue to use that one, and it should have most stuff you will likely need. Of course you might have to manually include a few things now and then, but that's just the way of it I'm afraid.

 

For the balloon notification, the TrayMenu library has a function called TrayMenuShowNotification that helps show a balloon tooltip, specifying TMNI_INFO for the blue info icon, TMNI_WARNING for a warning icon, and TMNI_ERROR for an error icon. I didnt add in support for custom icon as i felt it would rarely be needed, and if it was then i would just do a function call manually to invoke Shell_NotifyIcon, NIM_MODIFY and set NIIF_USER in the dwInfoFlags of NOTIFYICONDATA and set hBalloonIcon to the handle of the icon.

But something like this will call the balloon notification for your app:

Invoke TrayMenuShowNotification, hTM, Addr szNotifyMsg, Addr szNotifyTitle, 5000d, TMNI_INFO

 

  • 4 years later...
Posted

Hi guys,

@fearless

just a info, so I'am using your ModernUI_TrayMenu / MUITrayMenuCreate function only which works good so far but I found out that in some cases if my Windows Explorer just exits (rarly happens) and does restart by itself that right after that my app icon from task is gone (no chance to get it back anyhow) and the process is still running in taskmanager and I just can do a kill process operation from taskmanager.This is pretty bad of course.Other apps I have running (not from me) are still showing the icon after Windows Explorer did restart after exit only yours not.Just wanna ask whether you could  maybe check this out if you like to find the bug / reason if possible.

.data
szTrayMenuTooltip       DB 'Some App',0
MUITRAYMENU TrayMenu1
; nothing
MUITRAYMENU_END


Invoke MUITrayMenuCreate, hWnd, hIcoMain, Addr szTrayMenuTooltip, MUITMT_MENUITEMS, Addr TrayMenu1,MUITMS_HIDEIFMIN or MUITMS_MINONCLOSE , NULL

or just so

Invoke MUITrayMenuCreate, hWnd, hIcoMain, Addr szTrayMenuTooltip, MUITMT_NOMENUEVER or MUITMT_MENUDEFER, FALSE,MUITMS_HIDEIFMIN or MUITMS_MINONCLOSE , NULL 

I am using no try menu items etc just a TrayMenuTooltip text and rest is empty.Not sure why the icon dosent come back in taskbar after Explorer did restart.You can reproduce that issue manually if you kill & start the explorer manually.Just the tray Icon disapears only.I also tried to changed the Tray Menu Styles but I get same problem.As I said, maybe you can check that out later etc.Thanks.

greetz

Teddy Rogers
Posted
11 hours ago, LCF-AT said:

my app icon from task is gone

Listen for the "TaskbarCreated" window message then add it back to the taskbar. Taskbar Creation Notification.

You can find an example here...

Ted.

  • Like 2
Posted

Hi again,

ok seems I got it now.I tried to create same code like on MSDN from  your link Ted.

WM_INITDIALOG
		invoke RegisterWindowMessage,chr$("TaskbarCreated")
		mov s_uTaskbarRestart, eax
		invoke MyTaskBarAddIcon,hWin,uID_TRAY,hIcoMain,chr$("Some Info!")

; eax = MSG
	.elseif eax == MYWM_NOTIFYICON
		invoke On_MYWM_NOTIFYICON,wParam,lParam
	.elseif eax == s_uTaskbarRestart
		invoke MyTaskBarAddIcon,hWin,uID_TRAY,hIcoMain,chr$("Some Info!")

; functions
MyTaskBarAddIcon proc hwnd:DWORD,uID:DWORD,hicon:DWORD,lpszTip:DWORD


.const
uID_TRAY			equ 8887
MYWM_NOTIFYICON	equ 8888
.data?
tnid	N_NOTIFYICONDATA <>
res		dd ?
.code
	lea edi, tnid
	assume edi:ptr N_NOTIFYICONDATA
		mov [edi].cbSize,			sizeof tnid
		m2m [edi].hwnd,				hwnd
		m2m [edi].uID,				uID
		mov [edi].uFlags,			NIF_MESSAGE+NIF_ICON+NIF_TIP
		mov [edi].uCallbackMessage,	MYWM_NOTIFYICON
		m2m [edi].hIcon,			hicon
	.if lpszTip
		invoke lstrcpy,addr [edi].szTip, lpszTip
	.else
		mov [edi].szTip,			FALSE
	.endif
	invoke Shell_NotifyIcon,NIM_ADD,edi
	assume edi:nothing
	.if hicon
		invoke DestroyIcon,hicon
	.endif
	
	ret
MyTaskBarAddIcon endp

MyTaskBarDeleteIcon proc hwnd:DWORD,uID:DWORD

	lea edi, tnid
	assume edi:ptr N_NOTIFYICONDATA
	mov [edi].cbSize,			sizeof tnid
	m2m [edi].hwnd,				hwnd
	m2m [edi].uID,				uID
	assume edi:nothing
	invoke Shell_NotifyIcon,NIM_DELETE,edi
	Ret
MyTaskBarDeleteIcon endp

On_MYWM_NOTIFYICON proc wparam:DWORD,lparam:DWORD

local uID:DWORD
local uMouseMsg:DWORD

	push wparam
	pop uID
	push lparam
	pop uMouseMsg
	.if 	uMouseMsg == WM_LBUTTONDOWN
		invoke ShowWindow,hWnd,SW_HIDE
	.elseif uMouseMsg == WM_LBUTTONDBLCLK
		invoke ShowWindow,hWnd,SW_RESTORE
	.elseif uMouseMsg == WM_CREATE
		invoke RegisterWindowMessage,chr$("TaskbarCreated")
		mov s_uTaskbarRestart, eax
	.endif
	Ret
On_MYWM_NOTIFYICON endp

I did tested my  example app on VM Win10 and did kill the explorer & restart it and my app icon comes back. :) Coolio!Not sure whether I did correctly for 100% but its working so far = good.Thanks again.

greetz

Posted
13 hours ago, Teddy Rogers said:

Listen for the "TaskbarCreated" window message then add it back to the taskbar. Taskbar Creation Notification.

Thats good to know, I think the shell has a bug that causes the icon to stop responding sometimes, I found various mentions to that issue online but no solution, the TaskbarCreated option looks like a winner, I will try to update MUITrayMenu control to include this automatically so that the user doesnt have to do anything. Cheers.

  • Like 1
Posted

Hi,

sounds good if you could update your Tray stuff (ModernUI). :) Just tell us if you did to check it out.

I have another small but important question about Window Procederes (WindowProc).So normaly I'am just using one Main Window Proc to handle all inside of it or creating subclasses.The disadvantage is that I have to write the whole code into that WindowProc = Not so good.Now I'am looking for a method to create another WindowProcs to write my code on that location but how to do that?

Example: I wanna create OwnerDraw handling at WM_DRAWITTEM message but not in my main WindowProc so I wanna handle it on a custom WindowProc_2 on other location / ASM file.How to manage that?So the goal is to get the WM_DRAWITTEM message also into my WindowProc_2 so that I can handle my ODraw from there.Is that doable and if yes how without to call RegisterClassEx & CreateWindowEx functions.In this case I dont have to create anything and just wanna register an other WindowProc XY to get all message there too.Maybe you guy have some hints for me about that.

Example: Something like that = 2 WindowProcs and in the 2. one (extern ASM file / wanna put all there later) I wanna handle it all and not in the first WndProc you know.How to do that without to create any another window / class.

WndProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

	mov eax, uMsg
	.if 	eax == WM_INITDIALOG
			....here doing some install call of WndProc 2 / 3 etc
	.elseif eax == WM_DRAWITEM
	
	.elseif eax == WM_MEASUREITEM
	
	.else
		Invoke DefWindowProc,hWin,uMsg,wParam,lParam
		ret
	.endif
	xor    eax,eax
	ret
WndProc endp

WndProc2 proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

	mov eax, uMsg

	.if	eax == WM_DRAWITEM
			....manage all OD here....
	.elseif eax == WM_MEASUREITEM
			....manage all OD here....
	.endif
	Invoke DefWindowProc, hWin, uMsg, wParam, lParam
	Ret
WndProc2 endp

greetz

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...