Loading icon from kit using twapi
I have a tcl script named main.tcl
in a folder called App
. One of the lines in the script uses a command from the twapi module (that line is actually in a proc and I'm trying to minimize the app to system tray when a user closes the app through the 'X' window button):
package require twapi
# ... code here
set hand [twapi::load_icon_from_file tclkit.ico]
# ... code here
The file tclkit.ico
is in the same directory as the script (ie in the folder App
).
When main.tcl
is run through wish
, the script works without any issues, but after wrapping it into an executable through command line,
> tclkit sdx.kit wrap App -runtime tclsh863.exe
the executable raises an error, notably that the icon file could not be found:
The system cannot find the file specified.
The system cannot find the file specified.
while executing
"LoadImage $hmod $path $type $opts(width) $opts(height) $flags"
(procedure "twapi::_load_image" line 18)
invoked from within
"twapi::load_icon_from_file tclkit.ico"
(procedure "min_to_tray" line 2)
invoked from within
"min_to_tray"
(command for "WM_DELETE_WINDOW" window manager protocol)
The current workaround right now is to have a copy of the tclkit.ico
file in the same directory as the .exe but I want to avoid that as much as possible and only have the standalone .exe file. I tried using the full path with:
set hand [twapi::load_icon_from_file [file join [pwd] App.exe tclkit.ico]]
which normally works when I want to read a file (.txt, .png files, etc.) within the .exe, without success.
So basically, is there a way to enable the .exe to load the .ico file from within itself or another workaround that will not require some dependence on a file outside the .exe app?
The core issue is that the relevant Windows API actually takes a filename, and not something that it's more easy to wrap loading-from-archive around (such as a buffer). This means that you have to copy the file out of the archive somewhere and then pass that name to the system call. This is in fact what Tcl does internally for load
when it's pulling the DLL from a source that isn't directly visible to the OS; it doesn't do it automatically for TWAPI though, as that library takes the philosophical position of being just a thin wrapper and letting the caller handle the consequences (which does mean you can easily do more tricks, provided you're inventive).
I suggest copying the file to a temporary file somewhere (ie, the standard location for these things; Tcl 8.6 has file tempfile
to help with this sort of trick) and then passing the full filename into the TWAPI call. I think everywhere in the Windows API that you could pass a simple filename in, you can also pass a full filename. (That's actually very convenient…)
上一篇: 相对而言,Windows 10上的TCL应该多快?
下一篇: 使用twapi从工具包加载图标