I was looking into simple code around net to find is there a way
to change icon of compiled executable file .exe
and found one on PureBasic forum ...
this program use few win api functions and some specific from pureBasic
Now i am wondering how translate this to o2 code ...
ps ..should be great to have simple mini program which can open FileDialog and
that user can itself add his own icon (.ico) to already created exe.
I tested pb program and work well on my win7_64bit
here is PureBasic code :
;Changing icon resources in executables (the NT-API way)
;
;
; NOTE: Needs NT, 2000 or XP to work
;
;
;
; WARNING: the following code is known to fail in certain cases
; be sure to backup your data before using this!
;
;
;
; (:t)raumatic - february 2005
;
#RT_GROUP_ICON = #RT_ICON + 11
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp
Structure ICONDIRENTRYCOMMON
bWidth.b ; Width, in pixels, of the image
bHeight.b ; Height, in pixels, of the image
bColorCount.b ; Number of colors in image (0 if >=8bpp)
bReserved.b ; Reserved ( must be 0)
wPlanes.w ; Color Planes
wBitCount.w ; Bits per pixel
dwBytesInRes.l ; How many bytes in this resource?
EndStructure
;
Structure ICONDIRENTRY
common.ICONDIRENTRYCOMMON
dwImageOffset.l ; Where in the file is this image?
EndStructure
Structure ICONDIR
idReserved.w ; Reserved (must be 0)
idType.w ; Resource Type (1 for icons)
idCount.w ; How many images?
idEntries.ICONDIRENTRY[0] ; An entry for each image (idCount of 'em)
EndStructure
;
Structure GRPICONDIR1ENTRY1
common.ICONDIRENTRYCOMMON
nId.w ; the ID
EndStructure
Structure GRPICONDIR1
idReserved.w ; Reserved (must be 0)
idType.w ; Resource type (1 for icons)
idCount.w ; How many images?
idEntries.GRPICONDIR1ENTRY1[0] ; The entries for each image
EndStructure
;
; Change Icon-Resource in "exeFilename.s" with "iconFileName.s"
;ChangeIcon("window.exe","myicon.ico")
;
Procedure.l ChangeIcon(iconFileName.s, exeFileName.s)
*icon.ICONDIR = AllocateMemory(SizeOf(ICONDIR))
If ReadFile(0, iconFileName.s)
ReadData(0, *icon, SizeOf(ICONDIR))
*icon = ReAllocateMemory(*icon, SizeOf(ICONDIR) + (*icon\idCount*2) *SizeOf(ICONDIRENTRY))
For i=0 To *icon\idCount-1
FileSeek(0, 6+SizeOf(ICONDIRENTRY) * i) ; SizeOf(ICONDIR) - SizeOf(ICONDIRENTRY) = 6
ReadData(0, *icon\idEntries[i], SizeOf(ICONDIRENTRY) * (i+1))
Next
;
hInst.l = BeginUpdateResource_(exeFileName, #False)
If hInst = 0
retVal.l = #False
Else
; CHANGE #RT_GROUP_ICON
*iconGroup.GRPICONDIR1 = AllocateMemory(SizeOf(GRPICONDIR1) + 6 + SizeOf(GRPICONDIR1ENTRY1) * *icon\idCount)
For i=0 To *icon\idCount-1
CopyMemory(*icon\idEntries[i]\common, *iconGroup\idEntries[i]\common, SizeOf(ICONDIRENTRYCOMMON))
*iconGroup\idEntries[i]\nId = (i+1)
Next
*iconGroup\idReserved = 0
*iconGroup\idType = 1
*iconGroup\idCount = *icon\idCount
;
; TODO: Error with bColorCount
; Written value is always wrong!? (e.g. 1 instead of 16)
;
retVal = UpdateResource_(hInst, #RT_GROUP_ICON, 1, #LANG_NEUTRAL, *iconGroup, 6+SizeOf(GRPICONDIR1ENTRY1)* *iconGroup\idCount)
FreeMemory(*iconGroup) : *iconGroup = #Null
; CHANGE #RT_ICON
For i = 0 To *icon\idCount-1
; get the desired icon from .ico file
*resData = AllocateMemory(*icon\idEntries[i]\common\dwBytesInRes)
FileSeek(0, *icon\idEntries[i]\dwImageOffset)
ReadData(0, *resData, *icon\idEntries[i]\common\dwBytesInRes)
retVal = UpdateResource_(hInst, #RT_ICON, (i+1), #LANG_NEUTRAL, *resData, *icon\idEntries[i]\common\dwBytesInRes)
Next
retVal = EndUpdateResource_(hInst, #False)
FreeMemory(*resData) : *resData = #Null
EndIf
FreeMemory(*icon) : *icon = #Null
CloseFile(0)
Else
retVal = #False
EndIf
ProcedureReturn retVal
EndProcedure
ChangeIcon("myIcon.ico","window.exe")
Thanks Aurel, I'm working on it! The procedure is not as complex as first appears, especially when loading the whole ico file into one string.
Charles
GUI part is not problematic but code inself kind a is
This program olnly change exe icon in explorer (folder) view not window icon or
application icon...
i found few things on stackover :
HGLOBAL hResLoad; // handle to loaded resource
HMODULE hExe; // handle to existing .EXE file
HRSRC hRes; // handle/ptr. to res. info. in hExe
HANDLE hUpdateRes; // update resource handle
LPVOID lpResLock; // pointer to resource data
BOOL result;
hExe = LoadLibrary(TEXT("app.exe"));
if (hExe == NULL)
{
return;
}
// Locate the icon resource in the .EXE file.
hRes = FindResource(hExe, MAKEINTRESOURCE(IDI_TB_SAVE), RT_GROUP_ICON);
if (hRes == NULL)
{
return;
}
// Load the resource into global memory.
hResLoad = LoadResource(hExe, hRes);
if (hResLoad == NULL)
{
return;
}
// Lock the resourcex into global memory.
lpResLock = LockResource(hResLoad);
if (lpResLock == NULL)
{
return;
}
// Open the file to which you want to add the icon resource.
hUpdateRes = BeginUpdateResource(TEXT("app_updated.exe"), FALSE);
if (hUpdateRes == NULL)
{
return;
}
result = UpdateResource(hUpdateRes, // update resource handle
RT_GROUP_ICON, // change icon resource
MAKEINTRESOURCE(IDR_MAINFRAME), // resource id
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), // english
lpResLock, // ptr to resource info
SizeofResource(hExe, hRes)); // size of resource info
if (result == FALSE)
{
return;
}
// Write changes to app_updated.exe and then close it.
if (!EndUpdateResource(hUpdateRes, FALSE))
{
return;
}
// Clean up.
if (!FreeLibrary(hExe))
{
return;
}
but :
-------------------------------------------------
MAKEINTRESOURCE
The MAKEINTRESOURCE macro converts an integer value to a resource type compatible with Win32 resource-management functions. This macro is used in place of a string containing the name of the resource.
LPTSTR MAKEINTRESOURCE(
WORD wInteger
// integer to convert
);
Parameters
wInteger
Specifies the integer value to be converted.
Return Values
The return value is the specified value in the low-order word and zero in the high-order word.
Remarks
The return value should be passed only to the Win32 resource-management functions, as the lpType parameter.
The MAKEINTRESOURCE macro is defined as follows:
#define MAKEINTRESOURCE(i) (LPTSTR) ((DWORD) ((WORD) (i)))
so how translate this macro to o2?
such a simple tool should be great to have to change program icon
without resource editor or something complex
do you agree ?
Hi Aurel,
MAKEINTRESOURCE turns an integer into a string representation of the value
For instance, integer 31 becomes "#31"
as a macro in o2:
def MAKEINTRESOURCE "#%1"
print MAKEINTRESOURCE(31)
to convert to a unicode string, store the result in a wstring
wstring s=MAKEINTRESOURCE(31)
PS I don't think the # is necessary
Hi Charles
It looks strange to me ..i never work with resources before
if i mix up something about icons i will post it .
I see that UpdateResourceW accepts numbers directly for params ResType and ResName. It is smart enough to distinguish between string pointers and direct equate values.
Here is my loose translation to o2, including some diagnostics:
/*
;Changing icon resources in executables (the NT-API way)
;
;
; NOTE: Needs NT, 2000 or XP to work
;
;
;
; WARNING: the following code is known to fail in certain cases
; be sure to backup your data before using this!
;
;
;
; (:t)raumatic - february 2005
;
;
translated to OxygenBasic Charles E V Pegge 06/07/2022
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp
*/
uses corewin
% RT_ICON 3
% RT_GROUP_ICON 14
% LANG_NEUTRAL 0x000 '0xc00
type ICONDIRENTRYCOMMON
byte bWidth ' Width, in pixels, of the image
byte bHeight ' Height, in pixels, of the image
byte bColorCount ' Number of colors in image (0 if >=8bpp)
byte bReserved ' Reserved ( must be 0)
word wPlanes ' Color Planes
word wBitCount ' Bits per pixel
dword dwBytesInRes ' How many bytes in this resource?
end type
'12 bytes
type ICONDIRENTRY_A
has ICONDIRENTRYCOMMON
dword dwImageOffset ' Where in the file is this image?
end type
'16 bytes
type ICONDIRENTRY_B
has ICONDIRENTRYCOMMON
'word nId ' the ID
'word padding
dword nId 'dword to ensure upper word is zero
end type
'16 bytes
type ICONDIR
word idReserved ' Reserved (must be 0)
word idType ' Resource Type (1 for icons)
word idCount ' How many images?
end type
'6 bytes + ENTRYS FOLLOW IMMEDIATELY
function ViewIconData(string buf) as string
===========================================
indexbase 0
int i 'iterator
string pr 'return info
ICONDIR *id
ICONDIRENTRY_A *ie
@id = strptr(buf)
@ie = @id+6
pr="
Icon group header
Reserved: " id.idReserved "
Type: " id.idType "
Count: " id.idCount "
Entry 1:
pixel width: " ie.bWidth "
pixel height: " ie.bHeight "
color count: " ie.bColorCount "
reserved : " ie.bReserved "
planes: " ie.wPlanes "
bits per pixel: " ie.wBitCount "
byte count: " ie.dwBytesInRes "
file loc/ordinal: " ie.dwImageOffset "
"
return pr
end function
function ViewIconFileData(string iconFileName) as string
========================================================
string buf = getfile(iconFileName)
string pr 'return info
if not buf
pr="Icon file not found: " iconFileName
else
pr=ViewIconData(buf)
endif
return pr
end function
'print ViewIconFileData "oxicon.ico"
'print ViewIconFileData "oxideicon.ico"
function ChangeIcon(string iconFileName, exeFileName) as int
============================================================
indexbase 0
int lang = 0x0 '0x409 LANG_US, 0x0 LANG_NEUTRAL
int i 'iterator
string buf = getfile(iconFileName)
if len(buf)=0
return 0
endif
'
sys hRes = BeginUpdateResource(exeFileName, 0)
If hRes = 0
return 0
endif
'
ICONDIR *icon
@icon = strptr(buf)
int count = icon.idCount
'
'CHANGE RT_GROUP_ICON (14)
'-------------------------
'
'copy of icon directory to be modified for group
string gbuf
gbuf=buf
ICONDIR *ig
@ig = strptr(gbuf)
ig.idReserved = 0
ig.idType = 1
ig.idCount = count
'
ICONDIRENTRY_B *ie
@ie=strptr(gbuf)+6
for i=0 to count-1
ie[i].nId = i+1 'replacing ImageOffset
next
'
int lg = 6 + SizeOf(ie) * count
function = UpdateResource( hRes, 14, 1, lang , ig, lg )
gbuf=""
'
' CHANGE EACH RT_ICON (3)
'------------------------
'
sys pbuf=strptr(buf)
sys pdat ' pointer to icon data
int ldat ' length of icon data
ICONDIRENTRY_A *ie
@ie=pbuf+6
for i = 0 to count-1
' get each icon from .ico file
ldat = ie[i].dwBytesInRes
pdat = pbuf + ie[i].dwImageOffset
function = UpdateResource( hRes , 3, i+1 , lang , pdat, ldat )
next
'
return EndUpdateResource(hRes, 0)
end function
'ChangeIcon("OxIcon.ico","co2.exe")
Thanks Charles
I will try ..hope that work for me