Jump to content
Tuts 4 You

PureBasic Adventures - Dual SysTray


Teddy Rogers

Recommended Posts

Teddy Rogers

This is a repostĀ from the "PureBasic Adventures" blog...

Last year a friend of mine was talking about PureBasic and how easy and good it was for coding and how much he liked working with it. I didn't really take much notice of it - it was just another Basic language, right?! Earlier this year he started showing off some of his remade old school crack intro's and demos from way back in the early 80's and 90's from the Amiga scene including some general effects so I decided to download a copy of PureBasic and tried out some of the features of the language. I liked it so much that I ended up purchasing a licence for PureBasic and have been using it ever since when I've needed to quickly code some tool or another. Why do I like it? Simply because of the ease in which I can get something done with minimal fuss and time. I can access all Windows API's and code can be natively compiled (and switched) between 32 and 64 bit with a couple of mouse clicks and PureBasics own command set is extensive. It's a very good basic language.

I don't normally do blogs, it's not my thing. I certainly don't have the time but I want to help spread the language. I'm likely not going to be posting amazing demo effects as I don't have the time to be spending on such things but I will post some snippets of code I needed to come up with in PureBasic for applications or tools. I can't promise you will be wowed or amazed by any of the samples I'm really just going to be posting things I've worked on and included in some programs or just code snippets to better understand how PureBasic works.

The first PureBasic sample I am going to post is some test code for a tool I coded where I needed multiple animated tray icons to be displayed to provide various information to the user. I hadn't found any similar code in PureBasic either in the example or archived code libraries or in the PureBasic forums.

This example creates two tray icons that cycles through imageres.dll via threads. Imageres.dll is basically an image library that comes with Windows, I believe its on Vista and later and its similar to shell32.dll but with nicer icons and a larger library. The example also listens out for the TaskbarCreated Windows message, if the taskbar crashes and has to reload and your application does not listen for the TaskbarCreated message your trayicon will not reappear. Cycling through the icons was a cheap way to get some "animation" to show up in the example. A callback is created to listen for events happening over the tray icons such as mouse clicks and mouse hover. Normally if you have only one icon in your program you don't have to use callbacks, I needed the callbacks because it was the only way I could get multiple icons working effectively in PureBasic. The threads are used to stop the tray icons locking up once the cycling of the icons is started.

I have added some comments but if you have any particular questions about the example please ask...

;
; ------------------------------------------------------------------
;
;   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.

Animated Tray Icon.zip

Link to comment

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...