Page 1 of 1

Balloon tip in systray

Posted: Sat Aug 07, 2004 2:40 pm
by MarkH
I couldn't find a working example on how to use the the Windows 2000/XP balloontip. So I took all the information I could find in the purebasic forum and a simular application I once wrote in VB 6. This is the result. Let me know if it doesn't work for you. It's tested on NT, W2000, XP and 98. NT and 98 off course don't have the balloontips, but the add/remove trayicon procedures still works without problems.

Mark.

Code: Select all


  #TRAY_ID = 999
  #NIM_ADD = $0
  #NIM_MODIFY = $1
  #NIM_DELETE = $2
  #NIF_MESSAGE = $1
  #NIF_ICON = $2
  #NIF_TIP = $4
  #NIF_STATE = $8
  #NIF_INFO = $10
  #NIS_SHAREDICON = $2
  #NIFF_NONE = $0
  #NIIF_INFO = $1
  #NIIF_WARNING = $2
  #NIIF_ERROR = $3
  #NIIF_NOSOUND = $10
  #NIN_BALLOONSHOW=$402
  #NIN_BALLOONHIDE=$403
  #NIN_BALLOONTIMEOUT =$404
  #NIN_BALLOONUSERCLICK=$405
  #NOTIFYICON_VERSION = $3
  #NOTIFYICONDATA_V1_SIZE = 88
  #NOTIFYICONDATA_V2_SIZE = 488
  #NOTIFYICONDATA_V3_SIZE = 504
  
Enumeration  
  #Window_0
  #TRAYICON_0
  #image_0
EndEnumeration

Structure IconData
  cbSize.l
  hwnd.l
  uID.l
  uFlags.l
  uCallbackMessage.l
  hIcon.l
  szTip.b[128]
  dwState.l
  dwStateMask.l
  szInfo.b[256]
  StructureUnion
    uTimeout.l
    uVersion.l
  EndStructureUnion
  szInfoTitle.b[64]
  dwInfoFlags.l
EndStructure 

Procedure MyWindowCallback(WindowID, Message, wParam, lParam) 
  Result = #PB_ProcessPureBasicEvents 
  Select Message
    Case #WM_USER
      Select lParam
        Case #WM_LBUTTONDOWN
          Debug "Left mousebutton click on Icon"
          
        Case #WM_RBUTTONDOWN
          Debug "Right mousebutton click on Icon"

        Case #WM_LBUTTONDBLCLK 
          Debug "Left button doublecklick on Icon"
          
        Case #WM_MOUSEMOVE
          ;Debug "Mouse moved over TrayIcon"
          
        Case #NIN_BALLOONSHOW
          Debug "SHow balloon"
          
        Case #NIN_BALLOONTIMEOUT
          Debug "Timeout or X pressed" ; The 'X' doesn't seem to be available in W2K?!
        Case #NIN_BALLOONUSERCLICK
          Debug "Balloon user click"
          
        Case #NIN_BALLOONHIDE
          Debug "Balloon closed"
          
      EndSelect
EndSelect
  
  ProcedureReturn Result 
EndProcedure 

Procedure.w GetDataSize()
  
If OpenLibrary(1,"VERSION.DLL")
  BuffSize.l= CallFunction(1,"GetFileVersionInfoSizeA","shell32.dll",0)
  If BuffSize>0 
    databuf.s=Space(BuffSize-1)
    ;Dim databuf.b(BuffSize-1)
    Result=CallFunction(1,"GetFileVersionInfoA","shell32.dll",0,BuffSize,@databuf)
    Result=CallFunction(1,"VerQueryValueA",@databuf,"\",@lpBuffer,@puLen)
    CopyMemory(lpBuffer+10,@nVerMajor,2)
  EndIf
  CloseLibrary(1)
  Select nVerMajor
    Case 6
      ProcedureReturn #NOTIFYICONDATA_V3_SIZE
      
    Case 5
      ProcedureReturn #NOTIFYICONDATA_V2_SIZE
      
    Default
      ProcedureReturn #NOTIFYICONDATA_V1_SIZE
  EndSelect
EndIf

EndProcedure

Procedure StatusAreaAddIcon(tooltiptext.s)
  Balloon.IconData\cbSize=GetDataSize()
  
  Balloon\hwnd = WindowID(#Window_0)
  Balloon\uID = #TRAY_ID
  Balloon\uFlags = #NIF_MESSAGE | #NIF_ICON | #NIF_TIP 
  Balloon\hIcon = UseImage(#image_0)
  Balloon\dwState = #NIS_SHAREDICON
  Balloon\uCallbackMessage=#WM_USER
  If OSVersion() < #PB_OS_Windows_2000
    Balloon\uVersion = 0
  Else
    Balloon\uVersion = #NOTIFYICON_VERSION
  EndIf
  Balloon\uTimeout = 11000 ; The balloon will not disappear if you don't move the mouse!
  Balloon\dwInfoFlags = #NIIF_INFO
  If Balloon.IconData\cbSize=#NOTIFYICONDATA_V1_SIZE
    PokeS(@Balloon\szTip, tooltiptext,64)
  Else
    PokeS(@Balloon\szTip, tooltiptext,128)
  EndIf
  
  Result= CallFunction(0,"Shell_NotifyIcon",#NIM_ADD,@Balloon)
EndProcedure 

Procedure StatusAreaRemoveIcon()
  Balloon.IconData\cbSize=GetDataSize()
  
  Balloon\hwnd = WindowID(#Window_0)
  Balloon\uID = #TRAY_ID
  Result= CallFunction(0,"Shell_NotifyIcon",#NIM_DELETE,@Balloon)
EndProcedure 

Procedure ShowBalloonTip(title.s,maintext.s,tooltiptext.s,IconType.l)
  Balloon.IconData\cbSize=GetDataSize()
  
  Balloon\hwnd = WindowID(#Window_0)
  Balloon\uID = #TRAY_ID
  Balloon\uFlags =  #NIF_INFO | #NIF_MESSAGE | #NIF_ICON | #NIF_TIP 
  Balloon\hIcon = UseImage(#image_0)
  Balloon\dwState = #NIS_SHAREDICON
  Balloon\uCallbackMessage=#WM_USER
  Balloon\uTimeout = 10000
  If OSVersion() < #PB_OS_Windows_2000
    Balloon\uVersion = 0
  Else
    Balloon\uVersion = #NOTIFYICON_VERSION
  EndIf
  Balloon\dwInfoFlags = IconType
  
  If Balloon.IconData\cbSize=#NOTIFYICONDATA_V1_SIZE
    PokeS(@Balloon\szTip, tooltiptext,64)
  Else
    PokeS(@Balloon\szTip, tooltiptext,128)
    PokeS(@Balloon\szInfo,maintext.s,255)
    PokeS(@Balloon\szInfoTitle,title.s,63)
  EndIf
  Result= CallFunction(0,"Shell_NotifyIcon",#NIM_MODIFY,@Balloon)
EndProcedure 


OpenLibrary(0,"shell32.dll")

If OpenWindow(#Window_0,0,0,300,90,#PB_Window_SystemMenu|#PB_Window_ScreenCentered,"Status Area(Systray) Balloon tip example") And CreateGadgetList(WindowID()) 
    ButtonGadget  (1, 50, 10,200, 20, "Add Status area icon") 
    ButtonGadget  (2, 50, 30,200, 20, "Show Balloon tip") 
    ButtonGadget  (3, 50, 50,200, 20, "Remove Icon") 
    CatchImage(#image_0,?Icon)
    SetWindowCallback(@MyWindowCallback())
  
  Repeat 
    EventID = WaitWindowEvent() 
    
    Select EventID 
      
      Case #PB_Event_Gadget 
        Select EventGadgetID() 
          Case 1
            StatusAreaAddIcon("Tool tip text")
          Case 2
            ShowBalloonTip("Status Area Balloon Tip demo","This is the first line"+Chr(13)+"This should be the second line","Tool tip text",#NIIF_INFO)
          Case 3
            StatusAreaRemoveIcon()
        EndSelect 
    EndSelect 
  Until EventID = #PB_Event_CloseWindow 
  StatusAreaRemoveIcon()
  CloseLibrary(0)
EndIf 
End

DataSection
Icon:
IncludeBinary "d:\PureBasic\Examples\Sources\Data\CdPlayer.ico"
EndDataSection 

Posted: Sat Aug 07, 2004 3:02 pm
by thefool
it works fine here.

using xp pro (dk)

Posted: Sat Aug 07, 2004 3:30 pm
by GreenGiant
Yep, working here too. (XP Home)

Posted: Thu Aug 12, 2004 10:28 pm
by deMattin
On Win2k (SP4) manually setting the balloon works but the #NIN-messages don't come up.
So it's not possible to substitute the default tooltip with the balloon-tip in your app.
Because if you use the mouseover-message (#WM_MOUSEMOVE) to generate the balloon, you get many messages in queue if you move the mouse over the icon (eg. move mouse over icon - 20 move-messages: ballontip stays visible for 20 x timeout time if you use this message to bring up the balloon - it's called 20 times in queue)
It would be easy to supress this by setting a block variable within the "#NIN_BALLOONSHOW" message but this message doesn't come up with win2k. I think the "#NIN_BALLOONSHOW" message under WinXP comes up when the balloon comes up?!

So you are only able to use this as a message balloon and not as a real tooltip balloon, I think.

It would be great if someone has an idea to solve this to use this balloonstyle as a real tooltip (under win2k) that comes up with the mouse over the trayicon and goes away after the timout time.

greets,
Martin

Posted: Thu Jun 05, 2008 9:04 pm
by Ollivier
Updated (V4.10 B2) ! Nice code !

Code: Select all

#TRAY_ID = 999 
  #NIM_ADD = $0 
  #NIM_MODIFY = $1 
  #NIM_DELETE = $2 
  #NIF_MESSAGE = $1 
  #NIF_ICON = $2 
  #NIF_TIP = $4 
  #NIF_STATE = $8 
  #NIF_INFO = $10 
  #NIS_SHAREDICON = $2 
  #NIFF_NONE = $0 
  #NIIF_INFO = $1 
  #NIIF_WARNING = $2 
  #NIIF_ERROR = $3 
  #NIIF_NOSOUND = $10 
  #NIN_BALLOONSHOW=$402 
  #NIN_BALLOONHIDE=$403 
  #NIN_BALLOONTIMEOUT =$404 
  #NIN_BALLOONUSERCLICK=$405 
  #NOTIFYICON_VERSION = $3 
  #NOTIFYICONDATA_V1_SIZE = 88 
  #NOTIFYICONDATA_V2_SIZE = 488 
  #NOTIFYICONDATA_V3_SIZE = 504 
  
Enumeration  
  #Window_0 
  #TRAYICON_0 
  #image_0 
EndEnumeration 

Structure IconData 
  cbSize.l 
  hwnd.l 
  uID.l 
  uFlags.l 
  uCallbackMessage.l 
  hIcon.l 
  szTip.b[128] 
  dwState.l 
  dwStateMask.l 
  szInfo.b[256] 
  StructureUnion 
    uTimeout.l 
    uVersion.l 
  EndStructureUnion 
  szInfoTitle.b[64] 
  dwInfoFlags.l 
EndStructure 

Procedure MyWindowCallback(WindowID, Message, wParam, lParam) 
  Result = #PB_ProcessPureBasicEvents 
  Select Message 
    Case #WM_USER 
      Select lParam 
        Case #WM_LBUTTONDOWN 
          Debug "Left mousebutton click on Icon" 
          
        Case #WM_RBUTTONDOWN 
          Debug "Right mousebutton click on Icon" 

        Case #WM_LBUTTONDBLCLK 
          Debug "Left button doublecklick on Icon" 
          
        Case #WM_MOUSEMOVE 
          ;Debug "Mouse moved over TrayIcon" 
          
        Case #NIN_BALLOONSHOW 
          Debug "SHow balloon" 
          
        Case #NIN_BALLOONTIMEOUT 
          Debug "Timeout or X pressed" ; The 'X' doesn't seem to be available in W2K?! 
        Case #NIN_BALLOONUSERCLICK 
          Debug "Balloon user click" 
          
        Case #NIN_BALLOONHIDE 
          Debug "Balloon closed" 
          
      EndSelect 
EndSelect 
  
  ProcedureReturn Result 
EndProcedure 

Procedure.w GetDataSize() 
  
If OpenLibrary(1,"VERSION.DLL") 
  BuffSize.l= CallFunction(1,"GetFileVersionInfoSizeA","shell32.dll",0) 
  If BuffSize>0 
    databuf.s=Space(BuffSize-1) 
    ;Dim databuf.b(BuffSize-1) 
    Result=CallFunction(1,"GetFileVersionInfoA","shell32.dll",0,BuffSize,@databuf) 
    Result=CallFunction(1,"VerQueryValueA",@databuf,"\",@lpBuffer,@puLen) 
    CopyMemory(lpBuffer+10,@nVerMajor,2) 
  EndIf 
  CloseLibrary(1) 
  Select nVerMajor 
    Case 6 
      ProcedureReturn #NOTIFYICONDATA_V3_SIZE 
      
    Case 5 
      ProcedureReturn #NOTIFYICONDATA_V2_SIZE 
      
    Default 
      ProcedureReturn #NOTIFYICONDATA_V1_SIZE 
  EndSelect 
EndIf 

EndProcedure 

Procedure StatusAreaAddIcon(tooltiptext.s) 
  Balloon.IconData\cbSize=GetDataSize() 
  
  Balloon\hwnd = WindowID(#Window_0) 
  Balloon\uID = #TRAY_ID 
  Balloon\uFlags = #NIF_MESSAGE | #NIF_ICON | #NIF_TIP 
  Balloon\hIcon = ImageID(#image_0) 
  Balloon\dwState = #NIS_SHAREDICON 
  Balloon\uCallbackMessage=#WM_USER 
  If OSVersion() < #PB_OS_Windows_2000 
    Balloon\uVersion = 0 
  Else 
    Balloon\uVersion = #NOTIFYICON_VERSION 
  EndIf 
  Balloon\uTimeout = 11000 ; The balloon will not disappear if you don't move the mouse! 
  Balloon\dwInfoFlags = #NIIF_INFO 
  If Balloon.IconData\cbSize=#NOTIFYICONDATA_V1_SIZE 
    PokeS(@Balloon\szTip, tooltiptext,64) 
  Else 
    PokeS(@Balloon\szTip, tooltiptext,128) 
  EndIf 
  
  Result= CallFunction(0,"Shell_NotifyIcon",#NIM_ADD,@Balloon) 
EndProcedure 

Procedure StatusAreaRemoveIcon() 
  Balloon.IconData\cbSize=GetDataSize() 
  
  Balloon\hwnd = WindowID(#Window_0) 
  Balloon\uID = #TRAY_ID 
  Result= CallFunction(0,"Shell_NotifyIcon",#NIM_DELETE,@Balloon) 
EndProcedure 

Procedure ShowBalloonTip(title.s,maintext.s,tooltiptext.s,IconType.l) 
  Balloon.IconData\cbSize=GetDataSize() 
  
  Balloon\hwnd = WindowID(#Window_0) 
  Balloon\uID = #TRAY_ID 
  Balloon\uFlags =  #NIF_INFO | #NIF_MESSAGE | #NIF_ICON | #NIF_TIP 
  Balloon\hIcon = ImageID(#image_0) 
  Balloon\dwState = #NIS_SHAREDICON 
  Balloon\uCallbackMessage=#WM_USER 
  Balloon\uTimeout = 10000 
  If OSVersion() < #PB_OS_Windows_2000 
    Balloon\uVersion = 0 
  Else 
    Balloon\uVersion = #NOTIFYICON_VERSION 
  EndIf 
  Balloon\dwInfoFlags = IconType 
  
  If Balloon.IconData\cbSize=#NOTIFYICONDATA_V1_SIZE 
    PokeS(@Balloon\szTip, tooltiptext,64) 
  Else 
    PokeS(@Balloon\szTip, tooltiptext,128) 
    PokeS(@Balloon\szInfo,maintext.s,255) 
    PokeS(@Balloon\szInfoTitle,title.s,63) 
  EndIf 
  Result= CallFunction(0,"Shell_NotifyIcon",#NIM_MODIFY,@Balloon) 
EndProcedure 


OpenLibrary(0,"shell32.dll") 

If OpenWindow(#Window_0,0,0,300,90,"Status Area(Systray) Balloon tip example",#PB_Window_SystemMenu|#PB_Window_ScreenCentered)
  If CreateGadgetList(WindowID(#Window_0))
    ButtonGadget  (1, 50, 10,200, 20, "Add Status area icon") 
    ButtonGadget  (2, 50, 30,200, 20, "Show Balloon tip") 
    ButtonGadget  (3, 50, 50,200, 20, "Remove Icon") 
    CatchImage(#image_0,?Icon) 
    SetWindowCallback(@MyWindowCallback()) 
  
  Repeat 
    EventID = WaitWindowEvent() 
    
    Select EventID 
      
      Case #PB_Event_Gadget 
        Select EventGadget() 
          Case 1 
            StatusAreaAddIcon("Tool tip text") 
          Case 2 
            ShowBalloonTip("Status Area Balloon Tip demo","This is the first line"+Chr(13)+"This should be the second line","Tool tip text",#NIIF_INFO) 
          Case 3 
            StatusAreaRemoveIcon() 
        EndSelect 
    EndSelect 
  Until EventID = #PB_Event_CloseWindow 
  StatusAreaRemoveIcon() 
  CloseLibrary(0) 
  EndIf
EndIf 
End 

DataSection 
Icon: 
IncludeBinary "h:\PureBasic\Examples\Sources\Data\CdPlayer.ico" 
EndDataSection 

Posted: Thu Jun 05, 2008 10:31 pm
by AND51
Just tested and this does not work with Vista; it's only showing "T" as normal tooltip. The second button seems to have no effect, because nothing happens.

Posted: Thu Jun 05, 2008 11:21 pm
by rsts
Works fine here with Vista64 ultimate.

(have to have an icon to get the tooltip) :)

cheers

also - very nice :D

Posted: Fri Jun 06, 2008 1:03 am
by AND51
Well, I'm using the same OS with SP1 and I use #PB_Compiler_Home to get the CD-icon, but the code does not work.
I tried it 2 times: First, I updated the code myself to 4.x and prior then I took the code of Ollivier.

Posted: Sat Jun 07, 2008 2:31 am
by NoahPhense
Very nice. Like it a lot.

- np

Posted: Sat Jun 07, 2008 2:45 am
by NSaneBMX
Works so good (xp pro, sp2)