Embedding Icons in EXE
From QB64 Wiki
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.
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
- 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
See also:
- Resource Table extraction
- Icons and Cursors, _ICON (cannot use Icons)
- SaveIcon32 (convert any image to icon)
- GIF Images
- Icon Extraction