Mega Code Archive
How to use those Balloon style hints with Tray icons in Win2K
Title: How to use those Balloon-style hints with Tray icons in Win2K
Question: Ever seen Win2K pop balloons over tray icons?
When connecting through the Dial-Up Networking, for example...
Windows pops a balloon over the connection icon that states speed and connection type. This is how to produce those cool balloons in your code.
Answer:
Please note: The author assumes you are familiar with simple operations of inserting and removing your icons to / from the "Tray". If you are not, I suggest studying either, or both, of the following:
1. How to create a TrayIcon ! (ID 1567) by Bernhard Angerer
2. In the end of this article, I provide my own functions for these tasks.
Now, back to the balloons. I found out that the format of the NotifyIconData structure used to operate icons in the Tray (which, by the way, is called by Microsoft "The Taskbar Notification Area" :) changed significantly in Windows 2000. Those changes are NOT reflected in ShellAPI.pas unit of Delphi 5. Therefore I got the original SHELLAPI.H and translated the required declarations. Here they are:
uses Windows;
type
NotifyIconData_50 = record // defined in shellapi.h
cbSize: DWORD;
Wnd: HWND;
uID: UINT;
uFlags: UINT;
uCallbackMessage: UINT;
hIcon: HICON;
szTip: array[0..MAXCHAR] of AnsiChar;
dwState: DWORD;
dwStateMask: DWORD;
szInfo: array[0..MAXBYTE] of AnsiChar;
uTimeout: UINT; // union with uVersion: UINT;
szInfoTitle: array[0..63] of AnsiChar;
dwInfoFlags: DWORD;
end{record};
const
NIF_INFO = $00000010;
NIIF_NONE = $00000000;
NIIF_INFO = $00000001;
NIIF_WARNING = $00000002;
NIIF_ERROR = $00000003;
Here is a couple of types I think to be helpful:
type
TBalloonTimeout = 10..30{seconds};
TBalloonIconType = (bitNone, // no icon
bitInfo, // information icon (blue)
bitWarning, // exclamation icon (yellow)
bitError); // error icon (red)
Now we're ready to BALLOON!
This is the function I use:
uses SysUtils, Windows, ShellAPI;
function DZBalloonTrayIcon(const Window: HWND; const IconID: Byte; const Timeout: TBalloonTimeout; const BalloonText, BalloonTitle: String; const BalloonIconType: TBalloonIconType): Boolean;
const
aBalloonIconTypes : array[TBalloonIconType] of Byte = (NIIF_NONE, NIIF_INFO, NIIF_WARNING, NIIF_ERROR);
var
NID_50 : NotifyIconData_50;
begin
FillChar(NID_50, SizeOf(NotifyIconData_50), 0);
with NID_50 do begin
cbSize := SizeOf(NotifyIconData_50);
Wnd := Window;
uID := IconID;
uFlags := NIF_INFO;
StrPCopy(szInfo, BalloonText);
uTimeout := Timeout * 1000;
StrPCopy(szInfoTitle, BalloonTitle);
dwInfoFlags := aBalloonIconTypes[BalloonIconType];
end{with};
Result := Shell_NotifyIcon(NIM_MODIFY, @NID_50);
end;
And this is how to employ it:
DZBalloonTrayIcon(Form1.Handle, 1, 10, 'this is the balloon text', 'title', bitWarning);
The icon has to be already added, of course, with the same window handle and IconID (in this example, Form1.Handle and 1).
Try all three types of the inside-the-balloon-icons, they are cool!
======THE END OF THE BALLOON ARTICLE======
P.S. Now the functions I promised for adding/removing tray icons:
uses SysUtils, Windows, ShellAPI;
{just adds an icon}
function DZAddTrayIcon(const Window: HWND; const IconID: Byte; const Icon: HICON; const Hint: String = ''): Boolean;
var
NID : NotifyIconData;
begin
FillChar(NID, SizeOf(NotifyIconData), 0);
with NID do begin
cbSize := SizeOf(NotifyIconData);
Wnd := Window;
uID := IconID;
if Hint = '' then begin
uFlags := NIF_ICON;
end{if} else begin
uFlags := NIF_ICON or NIF_TIP;
StrPCopy(szTip, Hint);
end{else};
hIcon := Icon;
end{with};
Result := Shell_NotifyIcon(NIM_ADD, @NID);
end;
{adds an icon with a call-back message}
function DZAddTrayIconMsg(const Window: HWND; const IconID: Byte; const Icon: HICON; const Msg: Cardinal; const Hint: String = ''): Boolean;
var
NID : NotifyIconData;
begin
FillChar(NID, SizeOf(NotifyIconData), 0);
with NID do begin
cbSize := SizeOf(NotifyIconData);
Wnd := Window;
uID := IconID;
if Hint = '' then begin
uFlags := NIF_ICON or NIF_MESSAGE;
end{if} else begin
uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
StrPCopy(szTip, Hint);
end{else};
uCallbackMessage := Msg;
hIcon := Icon;
end{with};
Result := Shell_NotifyIcon(NIM_ADD, @NID);
end;
{removes an icon}
function DZRemoveTrayIcon(const Window: HWND; const IconID: Byte): Boolean;
var
NID : NotifyIconData;
begin
FillChar(NID, SizeOf(NotifyIconData), 0);
with NID do begin
cbSize := SizeOf(NotifyIconData);
Wnd := Window;
uID := IconID;
end{with};
Result := Shell_NotifyIcon(NIM_DELETE, @NID);
end;
A few final notes:
1. There's absolutely no need to use the larger ver.5.0 structure NotifyIconData_50 to add or remove icons, the old smaller structure NotifyIconData is perfect for that, even if you want to balloon them.
2. For the callback message, I suggest using WM_APP + something.
3. Using different IconIDs, it is easy to add many different icons to tray from a single parent window and operate them by their IconIDs.