Delphi 2010 is gaining traction again, and many Delphi programmers that moved away to Java and .NET in the dark era of late Borland, are looking at Delphi again, because it continues to be the relevant choice for your just another new project and it combines native performance with the the power of visual RAD programming. You get the best of two worlds: native, high performance code and elegant Visual Component Library. Delphi also means great, very responsive IDE and standalone executables with no dependencies that will run on just any version of Windows, does not matter which version of .NET is installed or not:-)
I was just reading through recent Dr.Bob's excellent article on using new Windows 7 TaskBar in Delphi code (good stuff!) and though it would be cool to revisit just another area also covered by Windows API Code Pack: Windows Stock Icons.
Delphi 2010 comes with "ShellAPI" unit that simplifies Windows Shell programming. It is not a new unit, but it works great with new Windows 7 APIs! In order to retrieve Windows Stock Icons in your Delphi code, you need to call "SHGetStockIconInfo" function defined in "ShellAPI" exported from shell32 Windows DLL. The "SHGetStockIconInfo" function takes an integer "id" of the icon we want to retrieve, "flags" argument that can be used to specify if we want normal or large size icons, and returns HResult and "TSHStockIconInfo" record as "out" parameter.
I have put together a small utility class named "TStockIcon" that wraps calls to "SHGetStockIconInfo" and simplifies access to Windows Stock Icons.
unit StockIconUtil;
interface
uses
Windows, Graphics;
type
TStockIconSize = (sisLarge, sisSmall, sisShellSize);
TStockIcon = class
class function GetIcon(id: integer): HICON; overload
class function GetIcon(id: integer; size: TStockIconSize;
overlay, selected: boolean): HICON; overload
class function GetBmp(id: integer): Graphics.TBitmap; overload// conflicts with "Windows" unit
class function GetBmp(id: integer; size: TStockIconSize;
overlay, selected: boolean): Graphics.TBitmap; overload
end
implementation
uses
SysUtils, ShellAPI;
{ TStockIcon }
class function TStockIcon.GetIcon(id: integer; size: TStockIconSize;
overlay, selected: boolean): HICON;
var
flags: cardinal;
SSII: TSHStockIconInfo;
ResCode: HResult;
begin
// you always want to get an icon so SHGSI_ICON is here in all choices
case size of
sisLarge: flags := SHGSI_ICON or SHGSI_LARGEICON;
sisSmall: flags := SHGSI_ICON or SHGSI_SMALLICON;
sisShellSize: flags := SHGSI_ICON or SHGSI_SHELLICONSIZE;
end
if selected then
flags := flags OR SHGSI_SELECTED;
if overlay then
flags := flags OR SHGSI_LINKOVERLAY;
SSII.cbSize := SizeOf(SSII);
ResCode := SHGetStockIconInfo(id, flags, SSII);
if ResCode <> S_OK then
begin
if ResCode = E_INVALIDARG then
raise Exception.Create(
'The stock icon identifier [' + IntToStr(id) + '] is invalid')
else
Result := 0;
end
else
Result := SSII.hIcon;
end
class function TStockIcon.GetIcon(id: integer): HICON;
begin
Result := GetIcon(id, sisLarge, false, false);
end
class function TStockIcon.GetBmp(id: integer): TBitmap;
begin
Result := GetBmp(id, sisLarge, false, false);
end
class function TStockIcon.GetBmp(id: integer; size: TStockIconSize; overlay,
selected: boolean): TBitmap;
var aIcon: HICON; tempIcon: TIcon;
begin
aIcon := GetIcon(id, size, overlay, selected);
tempIcon := TIcon.Create;
try
tempIcon.Handle := aIcon;
Result := Graphics.TBitmap.Create;
tempIcon.AssignTo(Result);
finally
tempIcon.Free;
end
end
end.
What is new to Delphi 2010 is the possibility to easily convert icons to bitmaps with new: "TIcon.AssignTo(Dest: TPersistent); override;" method that can take a TBitmap param as "Dest".
Here is the output of my test Delphi 2010 application running on Windows 7 and displaying all Stock Icons as bitmaps in a Delphi VCL Form:
The source code for "StockIconUtil" Delphi unit and a test application can be downloaded from the EDN Code Central.