File: n_icontray.sru
Size: 18937
Date: Mon, 31 Dec 2018 21:14:38 +0100
$PBExportHeader$n_icontray.sru
$PBExportComments$Icon System Tray functions
forward
global type n_icontray from nonvisualobject
end type
type guid from structure within n_icontray
end type
type notifyicondata from structure within n_icontray
end type
type dllversioninfo from structure within n_icontray
end type
end forward

type guid from structure
   unsignedlong      data1
   integer     data2
   integer     data3
   character      data4[8]
end type

type notifyicondata from structure
   unsignedlong      cbsize
   long     hwnd
   unsignedlong      uid
   unsignedlong      uflags
   unsignedlong      ucallbackmessage
   long     hicon
   character      sztip[128]
   unsignedlong      dwstate
   unsignedlong      dwstatemask
   character      szinfo[256]
   unsignedlong      utimeout
   character      szinfotitle[64]
   unsignedlong      dwinfoflags
   guid     guiditem
   long     hballoonicon
end type

type dllversioninfo from structure
   unsignedlong      cbsize
   unsignedlong      dwmajorversion
   unsignedlong      dwminorversion
   unsignedlong      dwbuildnumber
   unsignedlong      dwplatformid
end type

global type n_icontray from nonvisualobject autoinstantiate
end type

type prototypes
Function boolean Shell_NotifyIcon ( &
   ulong dwMessage, &
   Ref NOTIFYICONDATA lpData &
   ) Library "shell32.dll" alias for "Shell_NotifyIcon"

Function boolean SetForegroundWindow ( &
   ulong hWnd &
   ) Library "user32.dll"

Function long LoadImage ( &
   long hInst, &
   string lpszName, &
   uint uType, &
   int cxDesired, &
   int cyDesired, &
   uint fuLoad &
   ) Library "user32.dll" Alias For "LoadImage"

Function long ExtractIcon ( &
   long hInst, &
   string lpszExeFileName, &
   uint nIconIndex &
   ) Library "shell32.dll" Alias For "ExtractIcon"

Function boolean DestroyIcon ( &
   long hIcon &
   ) Library "user32.dll"

Function boolean RegisterHotKey ( &
   ulong hWnd, &
   int id, &
   uint fsModifiers, &
   uint vk &
   ) Library "user32.dll"

Function boolean UnregisterHotKey ( &
   ulong hWnd, &
   int id &
   ) Library "user32.dll"

Function long DllGetVersion ( &
   Ref DLLVERSIONINFO pdvi &
   ) Library "comctl32.dll" alias for "DllGetVersion"

Function long LoadLibrary ( &
   string lpFileName &
   ) Library "kernel32.dll" Alias For "LoadLibraryA"

Function boolean FreeLibrary ( &
   long hModule &
   ) Library "kernel32.dll"

Function long GetProcAddress ( &
   long hModule, &
   string lpProcName &
   ) Library "kernel32.dll" alias for "GetProcAddress"

Subroutine DebugMsg( &
   String lpOutputString &
   ) Library "kernel32.dll" Alias For "OutputDebugStringA"

end prototypes

type variables
Long il_iconhandles[]

// actual values set in constructor event
Long NOTIFYICONDATA_SIZE = 88
Long NOTIFYICON_VERSION = 1

// function Constants

Constant long NIF_MESSAGE     = 1
Constant long NIF_ICON        = 2
Constant long NIF_TIP         = 4
Constant long NIF_STATE       = 8
Constant long NIF_INFO        = 16
Constant long NIF_GUID        = 32
Constant long NIF_REALTIME    = 64
Constant long NIF_SHOWTIP     = 128

Constant long NIM_ADD         = 0
Constant long NIM_MODIFY      = 1
Constant long NIM_DELETE      = 2
Constant long NIM_SETFOCUS    = 3
Constant long NIM_SETVERSION  = 4
Constant long NIM_VERSION     = 5

Constant long NIS_HIDDEN      = 1
Constant long NIS_SHAREDICON  = 2

Constant long NIIF_NONE       = 0
Constant long NIIF_INFO       = 1
Constant long NIIF_WARNING    = 2
Constant long NIIF_ERROR      = 3
Constant long NIIF_USER       = 4
Constant long NIIF_ICON_MASK  = 15
Constant long NIIF_NOSOUND    = 16
Constant long NIIF_LARGE_ICON = 32
Constant long NIIF_RESPECT_QUIET_TIME = 64

Constant long WM_USER = 1024
Constant long PBM_CUSTOMEVENT       = (WM_USER - 1) + 1
Constant long NIN_SELECT            = WM_USER + 0
Constant long NIN_BALLOONSHOW       = WM_USER + 2
Constant long NIN_BALLOONHIDE       = WM_USER + 3
Constant long NIN_BALLOONTIMEOUT    = WM_USER + 4
Constant long NIN_BALLOONUSERCLICK  = WM_USER + 5
Constant long NIN_POPUPOPEN         = WM_USER + 6
Constant long NIN_POPUPCLOSE        = WM_USER + 7

Constant ulong NOTIFYICONDATA_V1_SIZE = 88  // pre-5.0 structure size
Constant ulong NOTIFYICONDATA_V2_SIZE = 488 // pre-6.0 structure size
Constant ulong NOTIFYICONDATA_V3_SIZE = 504 // 6.0 structure size
Constant ulong NOTIFYICONDATA_V4_SIZE = 508 // Vista and newer structure size

Constant long ICON_SMALL   = 0
Constant long ICON_BIG     = 1

Constant uint IMAGE_BITMAP = 0
Constant uint IMAGE_ICON   = 1
Constant uint IMAGE_CURSOR = 2

Constant uint LR_LOADFROMFILE    = 16
Constant uint LR_DEFAULTSIZE     = 64

// windows messages
Constant long WM_GETICON         = 127
Constant long WM_MOUSEMOVE       = 512
Constant long WM_LBUTTONDOWN     = 513
Constant long WM_LBUTTONUP       = 514
Constant long WM_LBUTTONDBLCLK   = 515
Constant long WM_RBUTTONDOWN     = 516
Constant long WM_RBUTTONUP       = 517
Constant long WM_RBUTTONDBLCLK   = 518

// hotkey values
Constant uint MOD_NONE     = 0
Constant uint MOD_ALT      = 1
Constant uint MOD_CONTROL  = 2
Constant uint MOD_SHIFT    = 4
Constant uint MOD_WIN      = 8
uint iui_keycode = 0
uint iui_modifier = 0

// virtual keycodes
Constant uint KeyBack         = 8
Constant uint KeyTab          = 9
Constant uint KeyEnter        = 13
Constant uint KeyShift        = 16
Constant uint KeyControl      = 17
Constant uint KeyAlt          = 18
Constant uint KeyPause        = 19
Constant uint KeyCapsLock     = 20
Constant uint KeyEscape       = 27
Constant uint KeySpaceBar     = 32
Constant uint KeyPageUp       = 33
Constant uint KeyPageDown     = 34
Constant uint KeyEnd          = 35
Constant uint KeyHome         = 36
Constant uint KeyLeftArrow    = 37
Constant uint KeyUpArrow      = 38
Constant uint KeyRightArrow   = 39
Constant uint KeyDownArrow    = 40
Constant uint KeyPrintScreen  = 44
Constant uint KeyInsert       = 45
Constant uint KeyDelete       = 46
Constant uint Key0            = 48
Constant uint Key1            = 49
Constant uint Key2            = 50
Constant uint Key3            = 51
Constant uint Key4            = 52
Constant uint Key5            = 53
Constant uint Key6            = 54
Constant uint Key7            = 55
Constant uint Key8            = 56
Constant uint Key9            = 57
Constant uint KeyA            = 65
Constant uint KeyB            = 66
Constant uint KeyC            = 67
Constant uint KeyD            = 68
Constant uint KeyE            = 69
Constant uint KeyF            = 70
Constant uint KeyG            = 71
Constant uint KeyH            = 72
Constant uint KeyI            = 73
Constant uint KeyJ            = 74
Constant uint KeyK            = 75
Constant uint KeyL            = 76
Constant uint KeyM            = 77
Constant uint KeyN            = 78
Constant uint KeyO            = 79
Constant uint KeyP            = 80
Constant uint KeyQ            = 81
Constant uint KeyR            = 82
Constant uint KeyS            = 83
Constant uint KeyT            = 84
Constant uint KeyU            = 85
Constant uint KeyV            = 86
Constant uint KeyW            = 87
Constant uint KeyX            = 88
Constant uint KeyY            = 89
Constant uint KeyZ            = 90
Constant uint KeyLeftWindows  = 91
Constant uint KeyRightWindows = 92
Constant uint KeyApps         = 93
Constant uint KeyNumPad0      = 96
Constant uint KeyNumPad1      = 97
Constant uint KeyNumPad2      = 98
Constant uint KeyNumPad3      = 99
Constant uint KeyNumPad4      = 100
Constant uint KeyNumPad5      = 101
Constant uint KeyNumPad6      = 102
Constant uint KeyNumPad7      = 103
Constant uint KeyNumPad8      = 104
Constant uint KeyNumPad9      = 105
Constant uint KeyMultiply     = 106
Constant uint KeyAdd          = 107
Constant uint KeySubtract     = 109
Constant uint KeyDecimal      = 110
Constant uint KeyDivide       = 111
Constant uint KeyF1           = 112
Constant uint KeyF2           = 113
Constant uint KeyF3           = 114
Constant uint KeyF4           = 115
Constant uint KeyF5           = 116
Constant uint KeyF6           = 117
Constant uint KeyF7           = 118
Constant uint KeyF8           = 119
Constant uint KeyF9           = 120
Constant uint KeyF10          = 121
Constant uint KeyF11          = 122
Constant uint KeyF12          = 123
Constant uint KeyNumLock      = 144
Constant uint KeyScrollLock   = 145
Constant uint KeySemiColon    = 186
Constant uint KeyEqual        = 187
Constant uint KeyComma        = 188
Constant uint KeyDash         = 189
Constant uint KeyPeriod       = 190
Constant uint KeySlash        = 191
Constant uint KeyBackQuote    = 192
Constant uint KeyLeftBracket  = 219
Constant uint KeyBackSlash    = 220
Constant uint KeyRightBracket = 221
Constant uint KeyQuote        = 222

end variables

forward prototypes
public subroutine of_setfocus (window aw_window)
public function boolean of_modify_icon (window aw_window, string as_imagename, unsignedinteger aui_index)
public function boolean of_modify_icon (window aw_window, string as_imagename)
public function boolean of_add_icon (window aw_window)
public function boolean of_add_icon (window aw_window, string as_imagename)
public function boolean of_add_icon (window aw_window, string as_imagename, unsignedinteger aui_index)
private function long of_loadimage (string as_filename, unsignedinteger aui_iconindex)
private function long of_loadimage (string as_imagename)
public function boolean of_modify_tip (window aw_window, string as_newtip)
public function boolean of_registerhotkey (window aw_window, integer ai_hotkeyid, unsignedinteger aui_modifier, unsignedinteger aui_keycode)
public function boolean of_unregisterhotkey (window aw_window, integer ai_hotkeyid)
public function boolean of_ishotkey (unsignedlong wparam, long lparam)
public function boolean of_delete_icon (window aw_window, boolean ab_show)
public function integer of_dllversion ()
public function boolean of_trayfocus ()
public function boolean of_balloon_tip (window aw_window, string as_title, string as_info)
public function boolean of_balloon_tip (window aw_window, string as_title, string as_info, integer ai_timeout, icon dwinfoflag)
public function boolean of_balloon_tip (window aw_window, string as_title, string as_info, icon dwinfoflag)
end prototypes

public subroutine of_setfocus (window aw_window);// give window proper focus
SetForegroundWindow(Handle(aw_window))

end subroutine

public function boolean of_modify_icon (window aw_window, string as_imagename, unsignedinteger aui_index);// modify icon in the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1
lstr_NID.uFlags   = NIF_ICON
lstr_NID.hIcon = this.of_LoadImage(as_imagename, aui_index)

If lstr_NID.hIcon = 0 Then Return False

// modify icon in system tray
Return Shell_NotifyIcon(NIM_MODIFY, lstr_NID)

end function

public function boolean of_modify_icon (window aw_window, string as_imagename);// modify icon in the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1
lstr_NID.uFlags   = NIF_ICON
lstr_NID.hIcon = this.of_LoadImage(as_imagename)

// modify icon in system tray
Return Shell_NotifyIcon(NIM_MODIFY, lstr_NID)

end function

public function boolean of_add_icon (window aw_window);// add window icon to the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1
lstr_NID.uFlags   = NIF_ICON + NIF_TIP + NIF_MESSAGE + NIF_SHOWTIP
lstr_NID.uCallBackMessage = PBM_CUSTOMEVENT
lstr_NID.hIcon    = Send(lstr_NID.hWnd, WM_GETICON, ICON_SMALL, 0)
lstr_NID.szTip    = aw_window.title

// add icon to system tray
If Shell_NotifyIcon(NIM_ADD, lstr_NID) Then
   // make window invisible
   aw_window.Hide()
   Return True
Else
   Return False
End If

end function

public function boolean of_add_icon (window aw_window, string as_imagename);// add loaded icon to the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1
lstr_NID.uFlags   = NIF_ICON + NIF_TIP + NIF_MESSAGE + NIF_SHOWTIP
lstr_NID.uCallBackMessage = PBM_CUSTOMEVENT
lstr_NID.hIcon    = this.of_LoadImage(as_imagename)
lstr_NID.szTip    = aw_window.title

// add icon to system tray
If Shell_NotifyIcon(NIM_ADD, lstr_NID) Then
   // make window invisible
   aw_window.Hide()
   Return True
Else
   Return False
End If

end function

public function boolean of_add_icon (window aw_window, string as_imagename, unsignedinteger aui_index);// add loaded icon to the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1
lstr_NID.uFlags   = NIF_ICON + NIF_TIP + NIF_MESSAGE + NIF_SHOWTIP
lstr_NID.uCallBackMessage = PBM_CUSTOMEVENT
lstr_NID.hIcon    = this.of_LoadImage(as_imagename, aui_index)
lstr_NID.szTip    = aw_window.title

// add icon to system tray
If Shell_NotifyIcon(NIM_ADD, lstr_NID) Then
   // make window invisible
   aw_window.Hide()
   Return True
Else
   Return False
End If

end function

private function long of_loadimage (string as_filename, unsignedinteger aui_iconindex);// load icon into memory from .exe or .dll file
// aui_iconindex is zero based (first icon is 0, second is 1)

Long ll_handle

// load icon
ll_handle = ExtractIcon(Handle(GetApplication()), as_filename, aui_iconindex)

// save handle for destroy in destructor event
If ll_handle > 0 Then
   il_iconhandles[UpperBound(il_iconhandles) + 1] = ll_handle
End If

Return ll_handle

end function

private function long of_loadimage (string as_imagename);// load image into memory from .ico, .cur or .ani file

Long ll_handle

CHOOSE CASE Lower(Right(as_imagename, 4))
   CASE ".ico"
      ll_handle = LoadImage(0, as_imagename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE + LR_DEFAULTSIZE)
   CASE ".cur", ".ani"
      ll_handle = LoadImage(0, as_imagename, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE + LR_DEFAULTSIZE)
   CASE ELSE
END CHOOSE

Return ll_handle

end function

public function boolean of_modify_tip (window aw_window, string as_newtip);// modify window icon tip in the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1
lstr_NID.uFlags   = NIF_TIP + NIF_SHOWTIP
lstr_NID.szTip = as_newtip

// modify icon tip
Return Shell_NotifyIcon(NIM_MODIFY, lstr_NID)

end function

public function boolean of_registerhotkey (window aw_window, integer ai_hotkeyid, unsignedinteger aui_modifier, unsignedinteger aui_keycode);// remember hotkey info
iui_keycode  = aui_keycode
iui_modifier = aui_modifier

// register a system wide hotkey
Return RegisterHotKey(Handle(aw_window), ai_hotkeyid, aui_modifier, aui_keycode)

end function

public function boolean of_unregisterhotkey (window aw_window, integer ai_hotkeyid);// unregister a system wide hotkey
Return UnregisterHotKey(Handle(aw_window), ai_hotkeyid)

end function

public function boolean of_ishotkey (unsignedlong wparam, long lparam);// return whether this is a WM_HOTKEY event
// called from window 'Other' event

If wparam = 1 Then
   If IntHigh(lparam) = iui_keycode Then
      If IntLow(lparam)  = iui_modifier Then
         Return True
      End If
   End If
End If

Return False

end function

public function boolean of_delete_icon (window aw_window, boolean ab_show);// delete window icon from the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize   = NOTIFYICONDATA_SIZE
lstr_NID.hWnd     = Handle(aw_window)
lstr_NID.uID      = 1

If ab_show Then
   // make window visible
   aw_window.Show()
   // give the window primary focus
   this.of_SetFocus(aw_window)
End If

// remove icon from system tray
Return Shell_NotifyIcon(NIM_DELETE, lstr_NID)

end function

public function integer of_dllversion ();// determine NOTIFYICONDATA version to use

DLLVERSIONINFO lstr_dvi
String ls_libname, ls_function
Integer li_version
Long ll_module, ll_rc

// default to original
li_version = 1

ls_libname  = "comctl32.dll"
ls_function = "DllGetVersion"

ll_module = LoadLibrary(ls_libname)
If ll_module > 0 Then
   ll_rc = GetProcAddress(ll_module, ls_function)
   If ll_rc > 0 Then
      lstr_dvi.cbSize = 20
      ll_rc = DllGetVersion(lstr_dvi)
      CHOOSE CASE lstr_dvi.dwMajorVersion
         CASE 6
            If lstr_dvi.dwMinorVersion = 0 Then
               li_version = 3
            Else
               li_version = 4
            End If
         CASE 5
            li_version = 2
         CASE ELSE
            li_version = 1
      END CHOOSE
   End If
   FreeLibrary(ll_module)
End If

Return li_version

end function

public function boolean of_trayfocus ();// give focus to the system tray

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize = NOTIFYICONDATA_SIZE

// give focus to the system tray
Return Shell_NotifyIcon(NIM_SETFOCUS, lstr_NID)

end function

public function boolean of_balloon_tip (window aw_window, string as_title, string as_info);// create balloon tip in the system tray
// Note: to close a balloon tip, call with as_info an empty string

Return of_Balloon_Tip(aw_window, as_title, as_info, 0, None!)

end function

public function boolean of_balloon_tip (window aw_window, string as_title, string as_info, integer ai_timeout, icon dwinfoflag);// create balloon tip in the system tray using a messagebox icon
// Note: to close a balloon tip, call with as_info an empty string

NOTIFYICONDATA lstr_NID

// populate structure
lstr_NID.cbSize      = NOTIFYICONDATA_SIZE
lstr_NID.hWnd        = Handle(aw_window)
lstr_NID.uID         = 1
lstr_NID.uTimeout    = ai_timeout
lstr_NID.uFlags      = NIF_INFO + NIF_SHOWTIP
lstr_NID.szInfoTitle = as_title
lstr_NID.szInfo      = as_info

Choose Case dwinfoflag
   Case StopSign!
      lstr_NID.dwInfoFlags = NIIF_ERROR
   Case Information!
      lstr_NID.dwInfoFlags = NIIF_INFO
   Case None!
      lstr_NID.dwInfoFlags = NIIF_NONE
   Case Exclamation!
      lstr_NID.dwInfoFlags = NIIF_WARNING
   Case Else
      lstr_NID.dwInfoFlags = NIIF_NONE
      lstr_NID.hIcon = Send(lstr_NID.hWnd, WM_GETICON, ICON_SMALL, 0)
End Choose

// create balloon tip
Return Shell_NotifyIcon(NIM_MODIFY, lstr_NID)

end function

public function boolean of_balloon_tip (window aw_window, string as_title, string as_info, icon dwinfoflag);// create balloon tip in the system tray using a messagebox icon
// Note: to close a balloon tip, call with as_info an empty string

Return of_Balloon_Tip(aw_window, as_title, as_info, 0, dwInfoFlag)

end function

on n_icontray.create
call super::create
TriggerEvent( this, "constructor" )
end on

on n_icontray.destroy
TriggerEvent( this, "destructor" )
call super::destroy
end on

event destructor;Integer li_cnt, li_max

// destroy icon handles created by ExtractIcon function
li_max = UpperBound(il_iconhandles)
FOR li_cnt = 1 TO li_max
   DestroyIcon(il_iconhandles[li_cnt])
NEXT

end event

event constructor;// determine version of NOTIFYICONDATA to use

NOTIFYICON_VERSION = this.of_DllVersion()

CHOOSE CASE NOTIFYICON_VERSION
   CASE 4
      NOTIFYICONDATA_SIZE = NOTIFYICONDATA_V4_SIZE
   CASE 3
      NOTIFYICONDATA_SIZE = NOTIFYICONDATA_V3_SIZE
   CASE 2
      NOTIFYICONDATA_SIZE = NOTIFYICONDATA_V2_SIZE
   CASE ELSE
      NOTIFYICONDATA_SIZE = NOTIFYICONDATA_V1_SIZE
END CHOOSE

end event