Euphoria
Ticket #197:
-icon binding option broken?
-
Reported by
ryanj
Sep 02, 2010
The -icon binding option used to work with an older build, but now my exe has the windows default icon when i run this:
euiw %EUDIR%\source\bind.ex -icon aaa.ico bbb.ex
Details
1. Comment by DerekParnell
Oct 03, 2010
Works for me. What is the size of your icon file? Are you getting any error messages?
2. Comment by mattlewis
Oct 22, 2010
Other users have confirmed that it works.
3. Comment by DerekParnell
Oct 27, 2010
Seems to work for everyone else. No change is needed.
4. Comment by jimcbrown
Dec 05, 2010
Reopening, as it was duplicated in ticket:502
5. Comment by jimcbrown
Dec 05, 2010
The information in this thread should at least provide a workaround: http://openeuphoria.org/forum/112480.wc
6. Comment by jimcbrown
Dec 06, 2010
Jeremy just tried it and said it's working. Perhaps if someone could upload an icon that is failing, we might be able to make progress on this?
7. Comment by jeremy
Dec 06, 2010
I said it was not working, however I just read the limitations. Wow! That's a pretty small Icon. Any modern Icon is much larger than our spec. Is this limitation based on the size of icon we put into the exe ourselves (the euphoria icon) or some other limitation?
8. Comment by jeremy
Dec 06, 2010
I was finally able to create an icon this small from existing Icons I found. Most of the Icons I found for use were ~200-300k, not 2.2k. I had to covert to PNG, then resize to 32x32, then to 256 colors, then export as png, and use an online png2ico converter. In the end I have a 32x32 icon that is 2,238, same size as euphoria.ico. eubind -icon paper2.ico test.ex did not work. No errors.
I've placed my icon online at: http://jeremy.cowgar.com/files/paper2.ico
Really what needs to happen is eubind needs to accept a more modern Icon. This should probably be done after we select a new logo. I wonder if this ticket should move to 4.0.0 milestone as we are not going to have a new logo before RC2.
9. Comment by jimcbrown
Dec 06, 2010
Uh... can we at least document it before RC2 and final go out?
10. Comment by jeremy
Dec 07, 2010
Resource handling was added to euc and eubind is not going to be the simplest problem to fix correctly. Thus it has been moved to 4.1. Those on Windows wishing to use an icon can use euc as a work around to this issue. An example is:
C:\proj> echo myproj ICON SRCDIR\myicon.ico > myproj.rc
C:\proj> euc -rc-file myproj.rc myproj.ex
With this new ability, you may wish to use euc all the time for distribution as resource files can contain product and version information as well. With eubind you cannot.
11. Comment by jimcbrown
Dec 07, 2010
Well, I came up with the following code for eubind (untested). It doesn't actually look that difficult.
include std/dll.e
include std/io.e
include std/filesys.e
include std/machine.e
function slice(sequence s, integer i)
if i < 1 or i > length(s) then
return ""
else
return s[i]
end if
end function
function get_file_size(sequence s)
object o = dir(s)
if sequence(o) and length(o) = 1 then
return o[1][D_SIZE]
end if
return 0
end function
integer fn = open(slice(command_line(), 4), "rb")
sequence icon = get_bytes(fn, get_file_size(slice(command_line(), 4)))
close(fn)
-- winnt.h
--#define LANG_NEUTRAL 0x00
--#define SUBLANG_DEFAULT 0x01
constant LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1
function MAKELANGID(atom p, atom s)
-- #define MAKELANGID(p,s) ((((WORD)(s))<<10)|(WORD)(p))
return or_bits(s*power(2,10), p)
end function
-- winuser.h
function MAKEINTRESOURCE(atom a)
-- #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))
return a
end function
-- #define RT_ICON MAKEINTRESOURCE(3)
constant RT_ICON = MAKEINTRESOURCE(3)
constant kernel = open_dll("kernel32.dll"),
beginupdateresource = define_c_func(kernel, "BeginUpdateResourceA",
{C_POINTER, C_INT}, C_POINTER),
endupdateresource = define_c_func(kernel, "EndUpdateResourceA",
{C_POINTER, C_INT}, C_INT),
updateresource = define_c_func(kernel, "UpdateResourceA",
{C_POINTER, C_POINTER, C_POINTER, C_USHORT, C_POINTER, C_ULONG}, C_INT)
function BeginUpdateResource(sequence filename, integer b)
atom ptr = allocate_string(filename)
atom ret = c_func(beginupdateresource, {ptr, b})
free(ptr)
return ret
end function
function EndUpdateResource(atom h, integer b)
return c_func(endupdateresource, {h, b})
end function
function UpdateResource(atom h, atom t, sequence f, integer w, sequence b, integer n)
atom ret, ptr, fptr
ptr = allocate_string(b)
fptr = allocate_string(f)
ret = c_func(updateresource, {h, t, fptr, w, ptr, n})
free(ptr)
free(fptr)
return ret
end function
atom res
res = BeginUpdateResource(slice(command_line(), 3), 0)
if res = 0 then
puts(1, "BeginUpdateResource failed\n")
abort(0)
end if
--if UpdateResource(res, RT_ICON, MAKERESOURCEID(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then
if UpdateResource(res, RT_ICON, "eui", MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then
-- update worked
? EndUpdateResource(res, 0)
else
-- update failed
puts(1, "UpdateResource failed\n")
? EndUpdateResource(res, 1)
end if
12. Comment by jimcbrown
Feb 04, 2011
This is what I have. This seemed to work, but corrupted the .exe
This is most of what you need to do, minus the processing and handling of .ico files.
That is described here, but is more involved than I wanted to do.
http://www.codeguru.com/cpp/w-p/win32/tutorials/print.php/c12873__1
Although it can be done using Euphoria code, the complexity is approaching that of an independent project.
(Incidently, it turns out to be a lot easier to simply copy the icon resource from another, preexisting .exe)
include std/dll.e
include std/io.e
include std/filesys.e
include std/machine.e
include std/console.e
function slice(sequence s, integer i)
if i < 1 or i > length(s) then
return ""
else
return s[i]
end if
end function
function get_file_size(sequence s)
object o = dir(s)
if sequence(o) and length(o) = 1 then
return o[1][D_SIZE]
end if
return 0
end function
integer fn = open(slice(command_line(), 4), "rb")
sequence icon = get_bytes(fn, get_file_size(slice(command_line(), 4)))
close(fn)
-- winnt.h
--#define LANG_NEUTRAL 0x00
--#define SUBLANG_DEFAULT 0x01
constant LANG_NEUTRAL = 0, SUBLANG_DEFAULT = 1
function MAKELANGID(atom p, atom s)
-- #define MAKELANGID(p,s) ((((WORD)(s))<<10)|(WORD)(p))
return or_bits(s*power(2,10), p)
end function
-- winuser.h
function MAKEINTRESOURCE(atom a)
-- #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))
return a
end function
-- #define RT_ICON MAKEINTRESOURCE(3)
constant RT_ICON = MAKEINTRESOURCE(3)
-- #define RT_GROUP_ICON MAKEINTRESOURCE( 11 + R_ICON )
constant RT_GROUP_ICON = MAKEINTRESOURCE(14)
function IS_INTRESOURCE(atom a)
-- #define IS_INTRESOURCE(x) (((ULONG_PTR)(x) >> 16) == 0)
-- TODO handle signed negative values
return (a <= 65536)
end function
-- i don't know, maybe winbase.h
constant LOAD_LIBRARY_AS_DATAFILE = 2
constant kernel = open_dll("kernel32.dll"),
loadlibrary = define_c_func(kernel, "LoadLibraryExA",
{C_POINTER, C_POINTER, C_ULONG}, C_POINTER),
freelibrary = define_c_func(kernel, "FreeLibrary", {C_POINTER}, C_INT),
enumresourcetypes = define_c_func(kernel, "EnumResourceTypesA",
{C_POINTER, C_POINTER, C_POINTER}, C_INT),
enumresourcenames = define_c_func(kernel, "EnumResourceNamesA",
{C_POINTER, C_POINTER, C_POINTER, C_POINTER}, C_INT),
enumresourcelangs = define_c_func(kernel, "EnumResourceLanguagesA",
{C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER}, C_INT),
beginupdateresource = define_c_func(kernel, "BeginUpdateResourceA",
{C_POINTER, C_INT}, C_POINTER),
endupdateresource = define_c_func(kernel, "EndUpdateResourceA",
{C_POINTER, C_INT}, C_INT),
updateresource = define_c_func(kernel, "UpdateResourceA",
{C_POINTER, C_POINTER, C_POINTER, C_USHORT, C_POINTER, C_ULONG}, C_INT)
sequence all_types = {}, all_resources = {}, all_langs = {}
sequence theicon = {0,0}, theiconlangs = {"", ""}
constant ICON_HWDEP = 1, ICON_INDEP = 2
function make_str(atom type_ptr)
sequence type_str
if IS_INTRESOURCE(type_ptr) then
type_str = sprintf("#%d", {type_ptr})
else
type_str = peek_string(type_ptr)
end if
return type_str
end function
function enumrestypescb(atom open_dll_ret, atom type_ptr, atom p)
--printf(2, "|%s|\n", {make_str(type_ptr)})
if not find(type_ptr, all_types) then
all_types &= type_ptr
all_resources &= {""}
end if
return 1
end function
constant enumrestypes_cb = call_back(routine_id("enumrestypescb"))
function enumresnamescb(atom open_dll_ret, atom type_ptr, atom name_ptr, atom p)
--printf(2, "|%s| & |%s|\n", {make_str(name_ptr), make_str(type_ptr)})
all_resources[find(type_ptr, all_types)] &= {make_str(name_ptr)}
if type_ptr = RT_GROUP_ICON then
--theicon = {open_dll_ret, make_str(name_ptr)}
theicon[ICON_INDEP] = make_str(name_ptr)
elsif type_ptr = RT_ICON then
theicon[ICON_HWDEP] = make_str(name_ptr)
end if
return 1
end function
constant enumresnames_cb = call_back(routine_id("enumresnamescb"))
function enumreslangscb(atom open_dll_ret, atom type_ptr, atom name_ptr, atom lang, atom p)
--printf(2, "|%s| & |%s| & |%d|\n", {make_str(name_ptr), make_str(type_ptr), lang})
all_langs &= lang
if type_ptr = RT_GROUP_ICON then
if not find(lang, theiconlangs) then
theiconlangs[ICON_INDEP] &= lang
end if
elsif type_ptr = RT_ICON then
if not find(lang, theiconlangs) then
theiconlangs[ICON_HWDEP] &= lang
end if
end if
return 1
end function
constant enumreslangs_cb = call_back(routine_id("enumreslangscb"))
function LoadLibraryEx(sequence filename, atom reserved, atom flags)
atom ptr = allocate_string(filename)
atom ret = c_func(loadlibrary, {ptr, reserved, flags})
free(ptr)
return ret
end function
function FreeLibrary(atom handle)
return c_func(freelibrary, {handle})
end function
function EnumResourceTypes(atom open_dll_ret, atom cb, atom p)
return c_func(enumresourcetypes, {open_dll_ret, cb, p})
end function
function EnumResourceNames(atom open_dll_ret, object t, atom cb, atom p)
atom ptr
if sequence(t) then
ptr = allocate_string(t)
else
ptr = t
end if
atom ret = c_func(enumresourcenames, {open_dll_ret, ptr, cb, p})
if sequence(t) then
free(ptr)
end if
return ret
end function
function EnumResourceLanguages(atom open_dll_ret, object t, object n, atom cb, atom p)
atom tptr
if sequence(t) then
tptr = allocate_string(n)
else
tptr = t
end if
atom nptr
if sequence(n) then
nptr = allocate_string(n)
else
nptr = n
end if
atom ret = c_func(enumresourcelangs, {open_dll_ret, tptr, nptr, cb, p})
if sequence(t) then
free(tptr)
end if
if sequence(n) then
free(nptr)
end if
return ret
end function
function BeginUpdateResource(sequence filename, integer b)
atom ptr = allocate_string(filename)
atom ret = c_func(beginupdateresource, {ptr, b})
free(ptr)
return ret
end function
function EndUpdateResource(atom h, integer b)
return c_func(endupdateresource, {h, b})
end function
function UpdateResource(atom h, atom t, sequence f, integer w, sequence b, integer n)
atom ret, ptr, fptr
ptr = allocate_string(b)
fptr = allocate_string(f)
ret = c_func(updateresource, {h, t, fptr, w, ptr, n})
free(ptr)
free(fptr)
return ret
end function
atom res
res = LoadLibraryEx(slice(command_line(), 3), 0, LOAD_LIBRARY_AS_DATAFILE)
if res = 0 then
puts(1, "OpenHandle failed\n")
abort(0)
end if
if not EnumResourceTypes(res, enumrestypes_cb, 0) then
puts(1, "EnumResourceTypes failed\n")
end if
for i = 1 to length(all_types) do
if not EnumResourceNames(res, all_types[i], enumresnames_cb, 0) then
printf(1, "EnumResourceNames failed for type %d, i = %d\n",
{all_types[i], i})
end if
end for
for i = 1 to length(all_resources) do
for j = 1 to length(all_resources[i]) do
if not EnumResourceLanguages(res, all_types[i], all_resources[i][j], enumreslangs_cb, 0) then
printf(1, "EnumResourceLanguagess failed for type %d, name %s, i = %d, j = %d\n",
{all_types[i], all_resources[i][j], i, j})
end if
end for
end for
--? c_func(define_c_func(kernel, "GetLastError", {}, C_ULONG), {})
if not FreeLibrary(res) then
puts(1, "CloseHandle failed\n")
abort(0)
end if
res = BeginUpdateResource(slice(command_line(), 3), 0)
if res = 0 then
puts(1, "BeginUpdateResource failed\n")
abort(0)
end if
--if UpdateResource(res, RT_ICON, MAKERESOURCEID(1), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then
--if UpdateResource(res, RT_ICON, "eui", MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), icon, length(icon)) then
for i = 1 to length(theiconlangs[ICON_INDEP]) do
--if theiconlangs[ICON_INDEP][i] != 0 and UpdateResource(res, RT_GROUP_ICON, theicon[ICON_INDEP], theiconlangs[ICON_INDEP][i], icon, length(icon)) then
-- update worked
--elsif theiconlangs[ICON_INDEP][i] = 0 then
if UpdateResource(res, RT_GROUP_ICON, theicon[ICON_INDEP], theiconlangs[ICON_INDEP][i], icon, length(icon)) then
else
-- update failed
printf(1, "UpdateResource GROUP_ICON failed for lang %d, i = %d\n", {theiconlangs[ICON_INDEP][i], i})
? EndUpdateResource(res, 1)
abort(0)
end if
end for
for i = 1 to length(theiconlangs[ICON_HWDEP]) do
--if theiconlangs[ICON_HWDEP][i] != 0 and UpdateResource(res, RT_ICON, theicon[ICON_HWDEP], theiconlangs[ICON_HWDEP][i], icon, length(icon)) then
-- update worked
--elsif theiconlangs[ICON_HWDEP][i] = 0 then
if UpdateResource(res, RT_ICON, theicon[ICON_HWDEP], theiconlangs[ICON_HWDEP][i], icon, length(icon)) then
else
-- update failed
printf(1, "UpdateResource ICON failed for lang %d, i = %d\n", {theiconlangs[ICON_HWDEP][i], i})
? EndUpdateResource(res, 1)
end if
end for
? EndUpdateResource(res, 0)