Embedding Icons in EXE - QB64 Wiki

Embedding Icons in EXE

From QB64 Wiki

Jump to: navigation, search

This page is maintained for historic purposes. The functionality of the code below can now be achieved through the $EXEICON metacommand.

The following procedure supplied by Michael Calkins can be used to embed icons into QB64 EXE program files visible in MS Explorer. The information and code provided has no warranty and the user accepts all responsibility for damages incurred!

I will demonstrate using TheBOB's minigolf sample. Warning: doing this will overwrite "mgi.ico", "mgi.o", and "mgi.exe" in your qb64 folder.

samples\thebob\minigolf\mg.ico is not actually an ICO file, it is a BMP. First convert it to an ICO. The following program strips the BMP header, adds an ICO header, doubles the height in the DIB header, and adds an AND bitmask of all nulls.

Run this program from your qb64 folder to create an icon from the bitmap:

CONST dat = 14~& DIM dw AS _UNSIGNED LONG DIM siz AS _UNSIGNED LONG DIM wid AS _UNSIGNED LONG DIM hei AS _UNSIGNED LONG DIM w AS _UNSIGNED INTEGER DIM b AS _UNSIGNED _BYTE OPEN "samples\thebob\minigolf\mg.ico" FOR BINARY ACCESS READ AS 1 OPEN "mgi.ico" FOR OUTPUT AS 2 'truncates file CLOSE 2 OPEN "mgi.ico" FOR BINARY AS 2 GET 1, 1 + 2, siz siz = siz - 14 w = 0 PUT 2, 1, w 'reserved w = 1 PUT 2, , w 'resource id PUT 2, , w 'icon count GET 1, 1 + dat + 4, wid SELECT CASE wid CASE IS < &H100: b = wid CASE &H100: b = 0 CASE ELSE: PRINT "bitmap is larger than 256 pixels.": END END SELECT PUT 2, , b 'width GET 1, , hei SELECT CASE hei CASE IS < &H100: b = hei CASE &H100: b = 0 CASE ELSE: PRINT "bitmap is larger than 256 pixels.": END END SELECT PUT 2, , b 'height GET 1, 1 + dat + 14, w IF w < 8 THEN b = 2 ^ w ELSE b = 0 PUT 2, , b 'num of colors b = 0 dw = 0 PUT 2, , b 'reserved PUT 2, , dw 'reserved dw = siz + (((wid * hei) + 7) \ 8) PUT 2, , dw 'size of data dw = 22 PUT 2, , dw 'copy, but double height SEEK 1, 1 + dat FOR dw = 1 TO siz GET 1, , b IF dw = 1 + 8 THEN w = hei * 2 PUT 2, , w dw = dw + 1 GET 1, , b ELSE PUT 2, , b END IF NEXT 'add AND bitmask b = 0 FOR dw = 1 TO ((hei * wid) + 7) \ 8 PUT 2, , b NEXT CLOSE SYSTEM

Public domain, November 2011, Michael Calkins
Now, we need to compile the resource into a COFF object file. Save this as "mgi.rc" in your qb64 folder:

0 ICON mgi.ico

Open a cmd prompt and CD to your qb64 folder. Then type:

internal\c\bin\windres -i mgi.rc -o mgi.o

We need to include it when we link the various object modules together to form the executable. First, get qb64 to compile mg.bas into a .cpp file:

qb64 -c samples\thebob\minigolf\mg.bas

Wait for qb64 to finish compiling and type the following commands and hit enter each line:

cd internal\c dir qbx*.cpp /O:D

That should tell you which number qbxn.cpp file is most recent hopefully. Try qbx.cpp when in doubt. Insert the number in command line below where the n is or skip it altogether if using qbx.cpp:
.\bin\g -w -Wall -I.\i -I..\..\ -L.\l ..\\tempn\\data.o qbxn.cpp libqbx.o ..\..\mgi.o -mwindows .\i686-w64-mingw32\lib\libimm32.a -lwinspool -lmingw32 -ln -lmix -limg -lttf -lmn -lSDL -s -o ..\..\mgi.exe
Where n is the number of the most recent qbxn.cpp file. Remember to replace n on both the tempn and qbxn.cpp parts.
Doing this will create mgi.exe in your qb64 folder, containing the icon resource. The icon should show up in Explorer.

cd ..\.. explorer .

Regards, Michael

QB64 Version

The following code creates a resource file, object file and compiles the most recent QB64 EXE file with the embedded icon selected.

_TITLE "QB64 Icon Embedding Program" DO LINE INPUT "Enter name of icon to embed without .ICO extension: ", icon$ LOOP UNTIL _FILEEXISTS(icon$ + ".ico") Q$ = CHR$(34) IF _FILEEXISTS(icon$ + "A.rc") = 0 THEN PRINT "Creating RC resource file " + icon$ + "A.rc..." OPEN icon$ + "A.rc" FOR OUTPUT AS #1 PRINT #1, "0 ICON " + Q$ + icon$ + ".ico" + Q$ CLOSE #1 DO: _LIMIT 100: LOOP UNTIL _FILEEXISTS(icon$ + "A.rc") ELSE PRINT "Resource file already created!": END IF IF _FILEEXISTS(icon$ + "A.o") = 0 THEN PRINT "Creating Object file " + icon$ + "A.o..." SHELL _HIDE "internal\c\bin\windres -i " + icon$ + "A.rc -o " + icon$ + "A.o" DO: _LIMIT 100: LOOP UNTIL _FILEEXISTS(icon$ + "A.o") PRINT icon$ + "A.o Object file created in QB64 folder!" ELSE PRINT "Object file already created!" END IF qbx$ = "QBX64.LST" PRINT PRINT "List of all QB64 QBX files created by access time:" CHDIR "internal\c" SHELL _HIDE "dir qbx*.cpp /O /T:A > " + qbx$ OPEN qbx$ FOR INPUT AS #2 DO UNTIL EOF(2) LINE INPUT #2, text$ PRINT text$ LOOP CLOSE #2 DO LINE INPUT "Select the most recent QBX file number to use(Hit Enter if QBX.cpp!): ", qbxnum$ LOOP UNTIL _FILEEXISTS("QBX" + qbxnum$ + ".cpp") PRINT DO LINE INPUT "Enter a name for the most recent program EXE file(program adds .EXE): ", exefile$ IF _FILEEXISTS(exefile$ + ".EXE") THEN PRINT "EXE file already exists! Use another name!" LOOP UNTIL _FILEEXISTS(exefile$ + ".EXE") = 0 SHELL _HIDE ".\bin\g -w -Wall -I.\i -I..\..\ -L.\l ..\\temp" + qbxnum$ + "\\data.o qbx" + qbxnum$ + ".cpp libqbx.o ..\..\" + icon$ + "A.o -mwindows .\i686-w64-mingw32\lib\libimm32.a -lwinspool -lmingw32 -ln -lmix -limg -lttf -lmn -lSDL -s -o ..\..\" + exefile$ + ".exe" SYSTEM

Code by Ted Weissgerber
Make sure that the long SHELL line of code at the end is copied fully and ends with + ".exe"

See also:

Go to Keyword Reference - Alphabetical
Go to Keyword Reference - By usage
Go to Main WIKI Page
Personal tools
  • Talk for this IP
  • Log in