However, the Delphi 5 help on TIcon is wrong!! (actually, incomplete) This page clarifies the error and explains how to load and display any available icon size from the program's resources.
While Windows applications use icons for many purposes, this page focuses on the application's icon - MAINICON.
Also see- Creating icons using GIMP and wikipedia page on the ICO file_format.
Why the help is wrong
All icons in an application have the same width, which is determined by Windows. Read Width to determine this common width.
Attempting to set the Width property raises an exception. |
procedure TIcon.SetWidth(Value: Integer); begin if FImage.FHandle = 0 then FRequestedSize.X := Value else InvalidOperation(@SChangeIconSize); end; function TIcon.GetWidth: Integer; begin Result := FImage.FSize.X; if Result = 0 then Result := GetSystemMetrics(SM_CXICON); end; |
This argument applies equally to TIcon.Height which has similar help and code.
Why this matters
As a result of reverse engineering the code, a better (and more correct) help entry might read.
Windows icons have various sizes - 16x16, 32x32, 48x48, 64x64.
By default, the various methods used to load an icon use the Windows default size -
typically 32x32.
To create an icon with a specific size, create a TIcon object and set the width and height before requesting a windows handle .. which creates a blank icon of the specified size. To load an icon with the windows default size, use the Windows LoadIcon function. To load an icon of a specific size, use the Windows LoadImage function. Once an icon is either created or loaded, read Width to determine the size. Once loaded, icons can not be resized. As a result, attempting to set the Width property after an icon is loaded raises an exception. The icon associated with the application is identified as MAINICON. |
LoadIcon | Returns the default size |
---|---|
LoadImage | You specify the size |
Image1.Picture.Icon := Application.Icon; // gets the 32x32 icon |
How Delphi 5 handles this
IconSize.X := Width; // This gets the component's value IconSize.Y := Height; // or Windows defaults if nothing is set Icon := CreateIcon(HInstance, IconSize.X, IconSize.Y, XorInfo.bmPlanes, XorInfo.bmBitsPixel, AndMem, XorMem); |
{$EXTERNALSYM CreateIcon} function CreateIcon(hInstance: HINST; nWidth, nHeight: Integer; cPlanes, cBitsPixel: Byte; lpbANDbits, lpbXORbits: Pointer): HICON; stdcall; |
Application.Icon
Application.Icon returns the default Windows icon size - 32x32.
To run an experiment, I tried setting the icon size before accessing Application.Icon. However, that failed
Application.Icon.Width := 64; // produces an error Application.Icon.Height := 64; Image1.Picture.Icon := Application.Icon; // never gets here |
constructor TApplication.Create(AOwner: TComponent); begin inherited Create(AOwner); // other code here FIcon := TIcon.Create; FIcon.Handle := LoadIcon(MainInstance, 'MAINICON'); FIcon.OnChange := IconChanged; // other code here end; |
LoadIcon can only load an icon whose size conforms to the SM_CXICON and SM_CYICON system metric values. Use the LoadImage function to load icons of other sizes. |
What works
The LoadImage function loads an icon, cursor, or bitmap. HANDLE LoadImage( HINSTANCE hinst, // handle of the instance that contains the image LPCTSTR lpszName, // name or identifier of image UINT uType, // type of image int cxDesired, // desired width int cyDesired, // desired height UINT fuLoad // load flags ); |
var cur_handle : HWND; begin cur_handle := LoadImage(MainInstance, 'MAINICON', IMAGE_ICON, 64, 64, 0); Image1.Picture.Icon.Handle := cur_handle; // gets the 64x64 icon end; |
cur_handle := LoadImage(MainInstance, 'MAINICON', IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); // 32x32 cur_handle := LoadImage(MainInstance, 'MAINICON', IMAGE_ICON, 0, 0, 0); // first icon |
Note that TApplication.Handle points to the main form (which does not have an associated resource section) and that MainInstance points to the executable (which does). Instead of MainInstance, HInstance also works.
// This will access the resources in the module that has the code cur_handle := LoadImage(HInstance, 'MAINICON', IMAGE_ICON, 64, 64, 0); // This will access the resources in the exe that started the program cur_handle := LoadImage(MainInstance, 'MAINICON', IMAGE_ICON, 64, 64, 0); |