winico

winico is a Tk extension for Windows that manages icons for use in the Windows desktop taskbar and for setting an application icon. Part of this extensions functionality has been merged into the Tk core so for Tk 8.4+ this extension is really only useful for managing the taskbar (see wm iconbitmap). The extension works on both Windows 98/ME and Windows NT/2K/XP varieties of windows. Since version 0.5 Tcl 8.4 is required.

See Also

System Tray Icon???? , comp.lang.tcl ,2001-09-22
Tom Wilkason describes how to work with an icon in the system tray in

Attributes

repository
https://chiselapp.com/user/pooryorick/repository/winico
file distributions
https://sourceforge.net/projects/tktable/files/winico/
issue tracker
https://sourceforge.net/p/tktable/bugs/

Documentation

man page

Description

The winico package release also contains a demonstration application of a system tray-based application. Another example of an application using winico is the tkchat application found in tclapps.


MG 2004-04-01: I use this for getting menus in the system tray. Works on Win 98, and (I'm told) Win XP.

winico taskbar add $winico -callback {winicoCallback %m %x %y} -text $yourAppName
proc winicoCallback {t {x 0} {y 0}} {
    if { $t == "WM_LBUTTONUP" } {
        wm deiconify .
        raise .
        focus .
    } elseif { $t == "WM_RBUTTONUP" } {
        .winicoPopup post $x $y
        .winicoPopup activate 0
    }
}

where .winicoPopup is a menu I've already created, and . is the main GUI window of my application. That causes a left-click of the icon to bring the application up to the front, and a right-click to post the menu.

Along with the winico.html documentation referenced immediately above, also be aware of these remarks from KBK and DRH:

"to look 'normal' you need a .ico file with all the sizes. The Windows standards recommend including: 48x48 32bpp, 32x32 32bpp, 16x16 32bpp, 48x48 8bpp, 32x32 8bpp, 16x16 8bpp, (plus same sizes at 4bpp and monochrome). Nowadays, typically only 32bpp and possibly monochrome are relevant because few users use 4- or 8-bit depth color settings.

Windows sometimes reduces the size to 16x16 automatically, but I think you have to give winico a 32x32. The stylized 'Tk' that appears in the upper left is at 16x16. You are also limited to 16 colors, if memory serves."


MG 2007-10-07: Just plugged winico 0.6 into an app (I'd used winico 0.3 before with past apps, I think) and went to test it, and found what seemed to be a bug: whenever I clicked the icon in the system tray when I had a -callback set, the main window (.) was raised and given focus, even though I hadn't told it to be. Had a look in the source to see if I could see the cause for it, and it seems it's deliberate, to work around a Windows bug that occurs when you post a menu from the system tray icon without giving the main window focus first (the menu doesn't disappear if you click another app without first clicking the menu).

Anyone know if it's still totally necessary to do that? I'm using Win XP SP2, and don't see the problem with some other apps (like the latest Windows Live Messenger), so I'm wondering if there's a newer/better/different solution to the problem out there somewhere.


JMN 2007-12-07:

Using winico 0.6, I can't seem to get 'winico taskbar add ..' to behave properly on Vista x64. It adds the icon to the systemtray ok at first, but then it just starts displaying one of the other icons in the panel.

Also 'winico setwindow' only seems to affect the window when maximized. The minimized window on the taskbar shows the default red Tk icon. The same code worked ok on win2k.

2008-03-06: Using png files, Tk 8.5+ and Img - the desired effect for the window and taskbar can be acheived without winico. This displays correctly both minimized & maximized (tested on vista x64)

package require Img
image create photo mylabel -file ./ico16.png
wm iconphoto . pcm

- Using Winico for the systemtray; it seems it might be important to make sure

  you're using a 32x32 version.

e.g if your .ico file contains both a 16x16 & 32x32, you may need to set the -pos argument to 1


SES_home 2010-05-30 11:23:20:

Thanks to package winico and a smart wrapper around it and on top of this a nice & simple GUI to customize the menu, will lead you to more consistent and fast results. To see what I mean, please have a look at : tG2 v1.05.02

Misc

HaO 2010-12-21: If an icon file has multiple sizes and color depth, one could search for 16x16 and a colordepth bigger or equal to the current colordepth:

package require Winico
set hTaskbarIcon [winico createfrom $iconFile]
# > Search for 16x16 and maximum or current colordepth
set indexCur 0
set bppMax 0
foreach dPars [winico info $hTaskbarIcon] {
    if { [dict get $dPars -geometry] eq "16x16" } {
        set bppCur [dict get $dPars -bpp]
        if {$bppCur == [winfo depth .]} {
            set indexCur [dict get $dPars -pos]
            break
        }
        if {$bppCur > $bppMax} {
            set indexCur [dict get $dPars -pos]
            set bppMax $bppCur
        }
    }
}
winico taskbar add $hTaskbarIcon -pos $indexCur -text [wm title .]\
        -callback [list [namespace code WinicoCallback] %m %x %y]

For starpacks, it is possible to load the starpack icon resource (called TK). For me, this did only load the size 32x32 in 4 bit resolution. This was scaled to 16x16 32bit and looked not so nice.

set hTaskbarIcon [winico load TK [info nameofexecutable]]

If the auto-icon-customization with a tclkit.ico file is used, it is also present in the starpack (why ?). So it might be loaded and you get all sizes and resolutions.

set hTaskbarIcon [winico createfrom [file join $starkit::topdir tclkit.ico]]

MJ 2017-03-28: A 64 bit build for Tcl 8.7 and the MinGW64 build script can be found at: https://fossil.mpcjanssen.nl/winico

Tray Icons using TWAPI

HaO 2017-09-26: Magic TWAPI also features tray icon support.

package require twapi_resource
package require twapi_shell
package require twapi_ui
# Create with X
set ID [twapi::systemtray addicon [twapi::load_icon_from_system hand] cb]
# Change to Triangle
twapi::systemtray modifyicon $ID -hicon [twapi::load_icon_from_system bang]
# Set tooltip help
twapi::systemtray modifyicon $ID -tip "New Tooltip"
# Balloon notification (very Windows 10'ish ;-) )
twapi::systemtray modifyicon $ID -balloon "Balloon Text" -balloontitle "Balloon title" -balloonicon error

proc cb {ID Message lPos TimeStamp} {
    lassign $lPos xPos yPos
    switch $Message {
        select - keyselect {
            # click action here
        }
        contextmenu {
            if {![winfo exists .guiWinicoPopup]} {
                menu .guiWinicoPopup -tearoff 0
                .guiWinicoPopup add command -label "CMD1" -command {puts CMD1}
            }
            set hWinNotify [::twapi::Twapi_GetNotificationWindow]
            ::twapi::set_foreground_window $hWinNotify
            .guiWinicoPopup post $xPos $yPos
            .guiWinicoPopup activate 0
            ::twapi::PostMessage $hWinNotify 0 0 0
        }
    }
}

MHo 2020-11-15: Where does ::twapi::Twapi_GetNotificationWindow come from?

Microsoft now calls the tray "Notification area" [L1 ].

Winico is able to handle icon files within a starpack. This does not work with twapi. A copy mechanism is required (the copying is not required for the program icon in "[info nameofexecutable]/tclkit.ico"):

proc GetTrayIcon {FileIn} {
    if {    [info exists starkit::topdir]
            && [string equal -nocase\
                -length [string length $starkit::topdir]\
                $starkit::topdir $FileIn]
            && "[string equal -nocase $FileIn [file normalize [file join $starkit::topdir [info nameofexecutable] tclkit.ico]]]
    } {
        set DestName [file join $::tmpFolder [file tail $FileIn]]
        file copy -force -- $FileIn $DestName
        set ID [::twapi::load_icon_from_file $DestName]
        file delete -force -- $DestName
        return $ID
    }
    return [::twapi::load_icon_from_file $FileIn]
}

MHo 2020-11-14: The above code contains syntax errors...

MHo 2020-11-14: I think we can use this to use the icon of the current executable:

set ID [twapi::systemtray addicon [load_icon_from_module [get_module_handle] "TK"] cb]

Twapi does not need any code to choose the right resolution index.

With Winico, the context menu did not work with Windows 10. The windows menu was shown instead. This works with twapi.

Remove taskbar icon and free icon resources

The following commands clear the taskbar icon. If the icon is loaded from a file.the icon resource may be freed. In the following example, the icon handle (returned by ::twapi::load_icon_from_file) was saved in the variable IconHandle.

Remark that the freeing is catched. The author observed shared resource errors and could not find the reason.

::twapi::systemtray removeicon $ID
catch {::twapi::free_icon $IconHandle}