winico

Difference between version 58 and 59 - Previous - Next
'''[http://tktable.sourceforge.net/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 **

   [http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&frame=right&th=9aa47598b4aba9a9&seekm=j5br7.31096%24ar5.1911394%40news1.rdc1.ga.home.com#link4%|%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 **

   [http://tktable.sourceforge.net/winico/winico.html%|%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 :
http://www.youtube.com/watch?v=JafI4y_egqk%|%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.

======tcl
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" [https://msdn.microsoft.com/en-us/library/windows/desktop/ee330740(v=vs.85).aspx].

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"):
======tcl
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}
======

<<categories>> Package