- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have a console application and I change its icon at runtime. It has been working well so far, in Windows 7, 8 and 10. However, it stopped working after one of the recent updates of Windows 10 (I do not know which was it was and I do not have any possibility to use an older version of Windows 10).
This is how I change the icon in the code:
subroutine changeConsoleWindowIcon ( ) use ifwin interface function SetConsoleIcon ( hIcon ) use ifwinty integer(BOOL) :: SetConsoleIcon integer(DWORD) :: hIcon !dec$ attributes default, stdcall :: SetConsoleIcon end function end interface integer,parameter :: IDI_ICON_MYAPP=101 integer(kind=HANDLE) :: hModule, hLib integer :: hMainIcon, lRet pointer ( SetConsoleF1, SetConsoleIcon ) hLib = LoadLibrary ( 'Kernel32.dll'C ) SetConsoleF1 = GetProcAddress ( hLib, 'SetConsoleIcon'C ) hModule = GetModuleHandle(0) hMainIcon = LoadIcon ( hModule, MAKEINTRESOURCE(IDI_ICON_MYAPP) ) lRet = SetConsoleIcon ( hMainIcon ) lRet = FreeLibrary ( hLib ) return end subroutine changeConsoleWindowIcon
This works well in Windows 7. In Windows 10, it also works, in cases when I run the executable by double clicking it in the Windows Explorer or any file manager. If I run the command line and run my application from it, or if I run my application as a new process from another (dialog-based, C++) application, the console icon is not changed.
I checked the return value from the call to SetConsoleIcon (by writing its value to the console window) and it is 0 in all above mentioned cases.
I apologize this is not much of a Fortran question; I wonder if anyone here could at least point me in a direction leading to resolving this problem. Goggling this found one note that SetConsoleIcon might have been removed from Kernel32.dll...
Thank you in advance for any tips.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is the code:
PROGRAM cd USE IFWIN, ONLY : LRESULT, fWPARAM, HANDLE , NULL, GetModuleHandle, LoadIcon, & GetConsoleWindow, SendMessage, WM_SETICON, ICON_BIG, ICON_SMALL IMPLICIT none ! INTEGER(KIND=HANDLE) :: hInstance, hConsole, hIcon INTEGER(KIND=LRESULT) :: result ! hInstance = GetModuleHandle(NULL) hIcon = LoadIcon(hInstance, "MY_ICON"//CHAR(0)) ! hConsole = GetConsoleWindow() result = SendMessage(hConsole, WM_SETICON, INT(ICON_SMALL,KIND=fWPARAM), hIcon) result = SendMessage(hConsole, WM_SETICON, INT(ICON_BIG,KIND=fWPARAM), hIcon) ! END PROGRAM cd
Be sure you have a resource file where you define the name of the icon resource, i.e. "MY_ICON". Note that the ICOM_SMALL is for the icon in the console itself and ICON_BIG for the icon in the task bar. The latter, however, does not work in this example. In a window applications where a console is created, it works fine.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Irina,
I met the same problem. In the mean time I found another, much more simple, solution. Try as follows:
hConsole = GetConsoleWindow()
iResult = SendMessage(hConsole, WM_SETICON, ICON_BIG, hMainIcon)
iResult = SendMessage(hConsole, WM_SETICON, ICON_SMALL, hMainIcon)
For me it works fine!
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Could you please post the complete code? I appreciate your idea, but I am not able to finish your snippet to make things work. :-[
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Here is the code:
PROGRAM cd USE IFWIN, ONLY : LRESULT, fWPARAM, HANDLE , NULL, GetModuleHandle, LoadIcon, & GetConsoleWindow, SendMessage, WM_SETICON, ICON_BIG, ICON_SMALL IMPLICIT none ! INTEGER(KIND=HANDLE) :: hInstance, hConsole, hIcon INTEGER(KIND=LRESULT) :: result ! hInstance = GetModuleHandle(NULL) hIcon = LoadIcon(hInstance, "MY_ICON"//CHAR(0)) ! hConsole = GetConsoleWindow() result = SendMessage(hConsole, WM_SETICON, INT(ICON_SMALL,KIND=fWPARAM), hIcon) result = SendMessage(hConsole, WM_SETICON, INT(ICON_BIG,KIND=fWPARAM), hIcon) ! END PROGRAM cd
Be sure you have a resource file where you define the name of the icon resource, i.e. "MY_ICON". Note that the ICOM_SMALL is for the icon in the console itself and ICON_BIG for the icon in the task bar. The latter, however, does not work in this example. In a window applications where a console is created, it works fine.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Robert, thank you for posting the complete code. While testing it, I encountered several interesting things and difficulties:
- In IPS 2016, Update 4, "GetConsoleWindow" is an unresolved external.
- In IPS 2017, Update 2, "GetConsoleWindow" compiles well, but I had to change the call to LoadIcon to MAKEINTRESOURCE(MY_ICON) instead of "MY_ICON"//CHAR(0) to work as required.
Icon is now changed even in Windows 10; thank you very much again!
Finally, it is interesting to see that SendMessage returns 0 in Windows 7, while it return a nonzero value in Windows 10.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
@robert, thanks for the useful tip.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Jirina,
thanks for letting me know. I cannot comment on the unresolved external referewnce. According to MS GetConsoleWindow is valid since Windows XP. Maybe Intel added it somewhat later??
On the icon resource: you have a choice: if the resource is known by its name only, so not by a numerical value, you can use the LoadIcon function call only with a nul-terminated string as the second argument. If you have a resource known by a numerical value, you MUST use that value by calling LoadIcon with a 32 bit integer as the second argument of which the high order word must be zero. I presume you used the second method. I assumed a resource with name so used the first method.
The return value of the Sendmessage is, according to the specs, the handle to the previous console icon. If there was not such an icon, it will retrurn NULL.
Robert
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
GetConsoleWindow is defined by kernel32.lib which comes from Microsoft. Intel doesn't touch this. It could be that you declared it incorrectly. What was the exact error message?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Robert, thank you for your kind and detailed explanation.
Steve, this is what I have in my code:
use ifwin integer(kind=HANDLE) :: hInstance hInstance = GetModuleHandle ( NULL )
Compiling this in IPS XE 2016, Update 4 issues warning #6717: This name has not been given an explicit type. [GETCONSOLEWINDOW]
Linking then issues error LNK2019: unresolved external symbol GETCONSOLEWINDOW referenced in function CONSOLEWINDOW_mp_CHANGECONSOLEWINDOWICON window.obj
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I don't want to sound like I'm making a silly statement, but that code snippet doesn't even have the string "getconsolewindow" in it (lowercase, uppercase, or mixed case)
In your real code, make sure that you "use kernel32" as well as "ifwinty". That will add the declaration and make sure the correct library is linked against.
--Lorri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
IFWIN includes KERNEL32 and IFWINTY. Most likely the declaration of that routine was missing from module KERNEL32 (looking at the current source I see it is one I added with BIND(C), but I am not sure when it was added.) If it was missing when you compiled, you get the Intel Fortran defaults which are not correct for this routine and hence the link error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Lorri, I am very sorry for the mistake I made when posting the code snippet. It contained GetModuleHandle instead of GetConsoleWindow. The right snippet is
use ifwin integer(kind=HANDLE) :: hInstance hInstance = GetConsoleWindow( NULL )
I think using IFWIN should be sufficient, as Steve explained, because the code snippet works well in IPS XE 2017 Update 2, but not in IPS XE 2016 Update 4. I think the declaration of the routine has been added recently, making it work in IPS XE 2017 Update 2.
Thank you for your quick and kind support.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page