Another program icon via command line
-
- Posts: 117
- Joined: Jun 21, 2018 11:14
Re: Another program icon via command line
And the truth is, we're a bunch of weird nerds. Not true?!
Re: Another program icon via command line
Back to op's question:
Here a working version for Windows OS:
Compile it and start from command line: ThisExe.exe /icon:"path to the ico file" . You can load also GDI+ supported image files.
Tested on Windows 10 x64.
Here a working version for Windows OS:
Code: Select all
'coded by UEZ
'Usage _WinAPI_SetWindowTitleIcon.exe /icon:email-logo.ico
#include "file.bi"
#Ifdef __Fb_64bit__
#Inclib "gdiplus"
#Include Once "win/gdiplus-c.bi"
#Else
#Include Once "win/gdiplus.bi"
Using gdiplus
#Endif
Declare Function WndProc(hWnd As HWND, uMsg As UINT, wParam As WPARAM, lParam As LPARAM) As Integer
Declare Function _WinAPI_SetWindowTitleIcon(sFile As String, hHWND As Any Ptr) As Byte
'check command line paramter
Dim As String CmdLineParameter
Dim As Ubyte iPos, bFile = False
iPos = Instr(Command(1), "/icon:")
If iPos = 1 Then
CmdLineParameter = Mid(Command(1), 7)
If FileExists(CmdLineParameter) <> 0 Then bFile = TRUE
EndIf
'create a test GUI
Dim wc As WNDCLASSEX
Dim msg As MSG
Dim hHWND As HWND
Dim As Integer sW, sH
ScreenInfo(sW, sH)
Dim szAppName As ZString * 30 => "FB GUI"
Dim As String sTitle = "<- Icon ;-)"
Dim Shared As ULong iW, iH
iW = 300
iH = 200
With wc
.style = CS_HREDRAW Or CS_VREDRAW
.lpfnWndProc = @WndProc
.cbClsExtra = NULL
.cbWndExtra = NULL
.hInstance = GetModuleHandle(NULL)
.hIcon = LoadIcon(NULL, IDI_APPLICATION )
.hCursor = LoadCursor(NULL, IDC_ARROW )
.hbrBackground = GetStockObject(WHITE_BRUSH )
.lpszMenuName = NULL
.lpszClassName = @szAppName
.cbSize = SizeOf(WNDCLASSEX)
End With
RegisterClassEx(@wc)
hHWND = CreateWindowEx(0, wc.lpszClassName, sTitle, _
WS_OVERLAPPEDWINDOW Or WS_VISIBLE, _
(sW - iW) / 2, (sH - iH) / 2, _
iW, iH, _
NULL, NULL, wc.hInstance, NULL)
'set icon to GUI
If bFile Then _WinAPI_SetWindowTitleIcon(CmdLineParameter, hHWND)
While GetMessage(@Msg, 0, 0, 0)
TranslateMessage(@Msg)
DispatchMessage(@Msg)
Wend
Function WndProc(hWnd As HWND,uMsg As UINT,wParam As WPARAM,lParam As LPARAM) As Integer
Select Case uMsg
Case WM_CLOSE
PostQuitMessage(0)
Case WM_CREATE
Case Else
Return DefWindowProc(hWnd, uMsg, wParam, lParam)
End Select
End Function
Function _WinAPI_SetWindowTitleIcon(sFile As String, hHWND As Any Ptr) As Byte
Dim gdipToken As ULONG_PTR
Dim GDIp As GdiplusStartupInput
GDIp.GdiplusVersion = 1
If GdiplusStartup(@gdipToken, @GDIp, NULL) <> 0 Then Return -1
Dim As any Ptr hImage, hImageScaled, hIcon
If GdipLoadImageFromFile(Wstr(sFile), @hImage) <> 0 Then
GdiplusShutdown(gdipToken)
Return -2
End If
GdipCreateHICONFromBitmap(hImage, @hIcon)
SendMessageW(hHWND, WM_SETICON, 1, Cast(LParam, hIcon))
GdipDisposeImage(hImage)
DestroyIcon(hIcon)
GdiplusShutdown(gdipToken)
Return 1
End Function
Tested on Windows 10 x64.
Last edited by UEZ on Jul 07, 2018 21:05, edited 1 time in total.
Re: Another program icon via command line
The font joke is getting oldnewbieforever wrote:And the truth is, we're a bunch of weird nerds. Not true?!
Re: Another program icon via command line
Hello UEZ
Works perfectly on Win 10.
My icon size 128 X 128, which always works well with a freebasic rc file.
I bsaved a little image and re saved it as .ico.
The force awakens.
Works perfectly on Win 10.
My icon size 128 X 128, which always works well with a freebasic rc file.
I bsaved a little image and re saved it as .ico.
The force awakens.
Re: Another program icon via command line
You can load your little image directly. ;-)dodicat wrote:Hello UEZ
Works perfectly on Win 10.
My icon size 128 X 128, which always works well with a freebasic rc file.
I bsaved a little image and re saved it as .ico.
The force awakens.
May the force be with you...
Re: Another program icon via command line
This one is out of fashion now.
Code: Select all
Sub EURO(x As Integer,y As Integer,s As Single,im As Any Pointer=0)
#macro pentagon(starx,stary,size,col)
Scope
Var count=0,rad=0.0,_px=0.0,_py=0.0
For z As Single=0+.28 To 2*pi+.1+.28 Step 2*pi/10
count=count+1
If count Mod 2=0 Then rad=size Else rad=.4*size
_px=starx+rad*Cos(z)
_py=stary+rad*Sin(z)
If count=1 Then Pset im,(_px,_py)Else Line im,-(_px,_py),col
Next z
Paint im,(starx,stary),col,col
End Scope
#endmacro
Dim As Double pi=4*Atn(1)
Dim As Integer lx=60*s,ly=1*lx
Line im,(x,y)-(x+lx,y+ly),Rgb(2,3,192),bf
Dim As Integer cntx=(x+x+lx)/2,cnty=(y+Y+ly)/2
For z As Double=0 To 2*pi Step 2*pi/12
Var px=cntx+.7*(lx/2)*Cos(z)
Var py=cnty+.7*(lx/2)*Sin(z)
pentagon(px,py,3*s,Rgb(243,236,24))
Next z
End Sub
screen 19,32
dim as any ptr i=imagecreate(128,128)
euro(00,00,2.2,i)
put(50,50),i
print "Euro.ico is the icon"
bsave "euro.bmp",i
sleep 50
shell "rename euro.bmp euro.ico"
sleep
Re: Another program icon via command line
The OP is not being very clear about what he's trying to accomplish but it seems he wants to change the embedded icon in a third-party EXE using FB code. In other words, open the EXE, modify the icon, and save it back out. For example, take a binary and make it look to the uninitiated like a jpeg image file when viewed in Explorer. Of course hacking an EXE's embedded icon will not necessarily change the icon that's displayed in the window corner or the task bar, as those can be set programmatically by the EXE to anything it wants, regardless of the embedded default icon.UEZ wrote:Back to op's question:
In any event, there are programs that will do this out there. I found at least one (with VB source code) with a simple Google search.
There are perhaps legitimate reasons why you'd want to hack the default icon of a third-party binary. newbieforever has never been very forthcoming with his goals here, and doesn't appear to have done much research before coming to the forum. It's unknown whether his projects are just for personal edification purposes (like most of us on the forum), or something else.
Or have I completely misread what newbieforever was trying to do?
Re: Another program icon via command line
caseih wrote:it seems he wants to change the embedded icon in a third-party EXE using FB code.
A Windows GUI application loads the icon with LoadIcon(GetModuleHandle(0), IDI_APPLICATION)newbieforever wrote:How a FB program (MyProgram.exe) could be enabled (by its code) to change its icon via command line:
MyProgram.exe /icon:AnotherIcon.ico
The Hello World proggie in examples\GUI\win32\hello.bas does it with .hIcon = LoadIcon( NULL, IDI_APPLICATION ) - and consequently, the exe shows no icon (to be corrected...).
Back to OP's objective: If you want a different icon via the commandline, the easiest way would be to include a choice of icons in the resource file, and to use the ID passed via the commandline to pick the right one. Using IDI_APPLICATION is just a convention, any other ID will do.
If, however, you don't mind shipping the icon file with the application, you may use this:
Code: Select all
#include once "win\shellapi.bi"
dim lpiIcon as WORD = 0
.hIcon = ExtractAssociatedIcon(GetModuleHandle(0), "another.ico", @lpiIcon)
In contrast to the LoadIcon bug in the hello world proggie, .hIcon = ExtractAssociatedIcon(0, "some.ico", @lpiIcon) works, too (no GetModuleHandle needed), but this is not documented by Microsoft.
There is more documentation at MSDN.
-
- Posts: 1002
- Joined: Jul 14, 2005 23:41
Re: Another program icon via command line
The use of Null as the hInstance parameter in LoadIcon is not a bug. IDI_APPLICATION is a predefined standard icon that must use Null as the hInstance parameter. There are many other standard predefined icons that could be used other than IDI_APPLICATION. Take a look at the documentation for LoadIcon https://docs.microsoft.com/en-us/window ... -loadiconajj2007 wrote:A Windows GUI application loads the icon with LoadIcon(GetModuleHandle(0), IDI_APPLICATION)
The Hello World proggie in examples\GUI\win32\hello.bas does it with .hIcon = LoadIcon( NULL, IDI_APPLICATION ) - and consequently, the exe shows no icon (to be corrected...).
...
Using IDI_APPLICATION is just a convention, any other ID will do.
...
In contrast to the LoadIcon bug in the hello world proggie,
Re: Another program icon via command line
And he probably wants to do it using the program that is edited. That's harder. Probably have to take a copy of the exe, rename the old exe, rename the copy to the "main" name. Now the "alternate" filename is executing. Now modify the exe with the "main" name and exit.caseih wrote: The OP is not being very clear about what he's trying to accomplish but it seems he wants to change the embedded icon in a third-party EXE using FB code.
The problem is now that the user must restart the new "main" exe which can then delete the old "alternate" exe.
Usually this (and other self-update scenarios) is done with a little loader app.
Of course a resource editor doesn't have this problem. It isn't running from the binary being edited.
It can be quite benign, like setting the icon to match the configured binary after a setup/configuration stage. Still modifying exes is frowned upon, and the binary doing can expect extra attention (and thus trouble) from antiviruses.There are perhaps legitimate reasons why you'd want to hack the default icon of a third-party binary. newbieforever has never been very forthcoming with his goals here, and doesn't appear to have done much research before coming to the forum. It's unknown whether his projects are just for personal edification purposes (like most of us on the forum), or something else.
Or have I completely misread what newbieforever was trying to do?
It might be possible (especially without the auto-update problem), but it isn't easy. If it is worth it, is something only OP can tell.
Re: Another program icon via command line
Using jj2007's shellapi idea.
This is the examples hello world tweaked so it creates and loads an icon during compile.
I am not sure if newbieforever wants an icon in the window titlebar (as this code), or the whole .exe given an icon which is seen when the .exe is not running .
so I have skipped parameter passing .
This is the examples hello world tweaked so it creates and loads an icon during compile.
Code: Select all
#include once "windows.bi"
#include once "win\shellapi.bi"
dim shared as string Myicon :Myicon ="Euro.ico"
declare Sub EURO(x As Integer,y As Integer,s As Single,im As Any Pointer=0) 'creates Myicon
declare function WinMain ( byval hInstance as HINSTANCE, _
byval hPrevInstance as HINSTANCE, _
byval szCmdLine as zstring ptr, _
byval iCmdShow as integer ) as integer
end WinMain( GetModuleHandle( null ), null, Command( ), SW_NORMAL )
'':::::
function WndProc ( byval hWnd as HWND, _
byval wMsg as UINT, _
byval wParam as WPARAM, _
byval lParam as LPARAM ) as LRESULT
function = 0
select case( wMsg )
case WM_CREATE
exit function
case WM_PAINT
dim rct as RECT
dim pnt as PAINTSTRUCT
dim hDC as HDC
hDC = BeginPaint( hWnd, @pnt )
GetClientRect( hWnd, @rct )
DrawText( hDC, _
"Hello, World!", _
-1, _
@rct, _
DT_SINGLELINE or DT_CENTER or DT_VCENTER )
EndPaint( hWnd, @pnt )
exit function
case WM_KEYDOWN
if( lobyte( wParam ) = 27 ) then
PostMessage( hWnd, WM_CLOSE, 0, 0 )
end if
case WM_DESTROY
PostQuitMessage( 0 )
exit function
end select
function = DefWindowProc( hWnd, wMsg, wParam, lParam )
end function
'':::::
function WinMain ( byval hInstance as HINSTANCE, _
byval hPrevInstance as HINSTANCE, _
byval szCmdLine as zstring ptr, _
byval iCmdShow as integer ) as integer
'=========== added ========
screen 19,32
dim as any ptr i=imagecreate(128,128)
euro(00,00,2.2,i)
bsave "euro.bmp",i
sleep 50
shell "rename euro.bmp, " + Myicon
imagedestroy (i)
screen 0
'===================
dim wMsg as MSG
dim wcls as WNDCLASS
dim hWnd as HWND
function = 0
dim as string iconpath=curdir + "\" + Myicon
dim as integer lpiIcon
with wcls
.style = CS_HREDRAW or CS_VREDRAW
.lpfnWndProc = @WndProc
.cbClsExtra = 0
.cbWndExtra = 0
.hInstance = hInstance
.hIcon = ExtractAssociatedIcon(GetModuleHandle(0), iconpath, @lpiIcon)
.hCursor = LoadCursor( NULL, IDC_ARROW )
.hbrBackground = GetStockObject( WHITE_BRUSH )
.lpszMenuName = NULL
.lpszClassName = @"HelloWin"
end with
if( RegisterClass( @wcls ) = FALSE ) then
MessageBox( null, "Failed to register wcls", "Error", MB_ICONERROR )
exit function
end if
hWnd = CreateWindowEx( 0, _
@"HelloWin", _
"The Hello Program", _
WS_OVERLAPPEDWINDOW, _
CW_USEDEFAULT, _
CW_USEDEFAULT, _
CW_USEDEFAULT, _
CW_USEDEFAULT, _
NULL, _
NULL, _
hInstance, _
NULL )
ShowWindow( hWnd, iCmdShow )
UpdateWindow( hWnd )
while( GetMessage( @wMsg, NULL, 0, 0 ) <> FALSE )
TranslateMessage( @wMsg )
DispatchMessage( @wMsg )
wend
kill rtrim(Myicon,".ico")+".bmp"'"euro.bmp"
function = wMsg.wParam
end function
'added
Sub EURO(x As Integer,y As Integer,s As Single,im As Any Pointer=0)
#macro pentagon(starx,stary,size,col)
Scope
Var count=0,rad=0.0,_px=0.0,_py=0.0
For z As Single=0+.28 To 2*pi+.1+.28 Step 2*pi/10
count=count+1
If count Mod 2=0 Then rad=size Else rad=.4*size
_px=starx+rad*Cos(z)
_py=stary+rad*Sin(z)
If count=1 Then Pset im,(_px,_py)Else Line im,-(_px,_py),col
Next z
Paint im,(starx,stary),col,col
End Scope
#endmacro
Dim As Double pi=4*Atn(1)
Dim As Integer lx=60*s,ly=1*lx
Line im,(x,y)-(x+lx,y+ly),Rgb(2,3,192),bf
Dim As Integer cntx=(x+x+lx)/2,cnty=(y+Y+ly)/2
For z As Double=0 To 2*pi Step 2*pi/12
Var px=cntx+.7*(lx/2)*Cos(z)
Var py=cnty+.7*(lx/2)*Sin(z)
pentagon(px,py,3*s,Rgb(243,236,24))
Next z
End Sub
sleep
so I have skipped parameter passing .
-
- Posts: 117
- Joined: Jun 21, 2018 11:14
Re: Another program icon via command line
UEZ, dodicat & others:
I am overhelmed by your help!
Unfortunately at the moment I am unable to study the codes in detail and to evaluate what can be used for my project (other commitments)...
PS: In case my question was not clear enough: The basic program icon as shown in Windows Explorer should be changed (not the icons displayed directly when 'MyProgram.exe /icon:AnotherIcon.ico' is applied).
I am overhelmed by your help!
Unfortunately at the moment I am unable to study the codes in detail and to evaluate what can be used for my project (other commitments)...
PS: In case my question was not clear enough: The basic program icon as shown in Windows Explorer should be changed (not the icons displayed directly when 'MyProgram.exe /icon:AnotherIcon.ico' is applied).
Re: Another program icon via command line
Right, so the icon a program displays while running is irrelevant to your purposes, thus playing around with the windows API likely isn't going to solve your problem. Like I said if you do a google search you will find at least one VB program that can change the EXE's icon (which shows up in explorer).
Re: Another program icon via command line
Right, that's what the docs say. Fact is that .hIcon = LoadIcon(0, IDI_APPLICATION) has the same effect as leaving .hIcon zeroed; so you may as well omit that line in hello.bas. If, however, you have something like IDI_APPLICATION ICON "Smiley.ico" in your resource file, you absolutely need GetModuleHandle(0) to see that icon in action.PaulSquires wrote:IDI_APPLICATION is a predefined standard icon that must use Null as the hInstance parameter.
No, it's not hard, it's a one-liner, as explained above. In the unlikely case that with "using the program that is edited" you mean modifying the exe before running it: see below.marcov wrote:he probably wants to do it using the program that is edited. That's harder.
The question was indeed misleading. Explorer uses the icon that is embedded as a resource, but you had explicitly asked to pass a filename in the commandline. There is a logical flaw in that, because passing a commandline implies running the file. Explorer just sees a non-running executable file. So you want to modify the executable, right? Very simple: Rebuild it with a different resource file. Takes half a second...newbieforever wrote:PS: In case my question was not clear enough: The basic program icon as shown in Windows Explorer should be changed (not the icons displayed directly when 'MyProgram.exe /icon:AnotherIcon.ico' is applied).
Re: Another program icon via command line
Well. You picked it as the unlikely case. I picked it as the likely case. So the chance is 50-50 :-)jj2007 wrote:No, it's not hard, it's a one-liner, as explained above. In the unlikely case that with "using the program that is edited" you mean modifying the exe before running it: see below.marcov wrote:he probably wants to do it using the program that is edited. That's harder.