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); |