| A trayicon allows your users to access your program without
having to view an actual form. Imagine writing a file-packer, it's okay to
keep seeing the form if you're using it for 5 minutes. But now there's
someone that wants to pack a couple of DVD's. That'll take a long time,
possibly days depending on your programs speed. Running the program for a
few days isn't a problem for most users, but it'll get killed along the
way if you keep it on the taskbar. An explorer error, a miss-click,
friends or colleagues that close it and on top of that, most people find
not used windows highly annoying. For all these reasons and more, we're going to implement a trayicon.
This is easier then it looks, let's fire up a new project.
First add the shellapi to your 'uses': uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, shellapi; This one's obvious, you'll need the shellapi if you
want to use it ^_^. Now add a constant below your uses: const
WM_ICONTRAY = WM_USER + 1; and insert 'TrayIconData: TNotifyIconData;'
under the form type. Now for the hardest part we'll have to get the
icon up and running in the traybar. This is (for now) done in our oncreate
event of the form and goes as follows: with TrayIconData do
begin
cbSize := SizeOf(TrayIconData);
Wnd := Handle;
uID := 0;
uFlags := NIF_MESSAGE + NIF_ICON + NIF_TIP;
uCallbackMessage := WM_ICONTRAY;
hIcon := Application.Icon.Handle;
StrPCopy(szTip, Application.Title);
end;
if Shell_NotifyIcon(NIM_ADD, @TrayIconData) then
else
showmessage('failed'); It sets the properties of our tryicon. There
are 2 interesting things in this though, the uFlags and the hIcon. Flags
are used to indicate what kind of extra's our trayicon will have, here it
'adds' a message, an icon and a tip to our trayicon. There's more
information about this below. The hIcon is an easy one, it sets the
icon (in this case to the icon of the application). Finally the
trayicon is actually added to the tray by using shell_notifyIcon. The
NIM_ADD basically 'adds' a new trayicon to the traybar with properties
TrayIconData (do not forget the @ it's the pointer sign, see below as
well). You can already run the above, though when closing the program
you'll notice that the trayicon stays until the mouse goes over it. So we
have to make sure that the icon is remove when our program stops, put the
following line in the ondestroy event of our form: Shell_NotifyIcon(NIM_DELETE, @TrayIconData); This
should look familiar. It does the same as the one above, but it deletes it
instead. It looks nice and all, but you'll want to use the trayicon for
something. Returning a state, menu or just a simple message that your
program is still running, so lets add a message when the icon is clicked. Add
the following function to the form.. procedure TrayMsg(var Msg: TMessage); message WM_ICONTRAY; The
following code should be in this function: case Msg.lParam of
WM_LBUTTONDOWN:
begin
ShowMessage('Left button clicked!');
end;
WM_RBUTTONDOWN:
begin
ShowMessage('Right button clicked!');
end;
end; The TrayMsg function receives a WM_ICONTRAY message when your icon
is clicked with the left or right mouse button. You can put anything you
want in here, though this should make the difference between mouse buttons
very clear. WM_LBUTTONDOWN representing the actual downclick (a click
consist of a down and a up, like your finger when clicking the mouse) of
the left mouse button. WM_RBUTTONDOWN does the same but then for the right
button. Run the program and click your trayicon, handy isn't it?
Now (yes as you can see it does matter to us what ppl want) for using
different icons and animating. It can be done really easy, create an TIcon
and load a icon file and reload the trayicon; var icon1 :
TIcon; icon2 : TIcon; icon3 : TIcon;
begin icon1 := TIcon.create; icon2 := TIcon.create;
icon3 := TIcon.create; Shell_NotifyIcon(NIM_DELETE, @TrayIconData); icon1.loadfromfile('place and name of
your icon'); icon2.loadfromfile('place and name of your
icon'); icon3.loadfromfile('place and name of your icon'); TrayIconData.hIcon
:= icon1.handle; //Or whichever you want to load Shell_NotifyIcon(NIM_ADD, @TrayIconData);
end; The difference with the code at the top of the page is that here
we're setting the icon to our own and not that of our application. It
unloads the icon (shell_notifyicon(nim_delete[...]) then sets the icon to
icon1 and reloads (shell_notifyicon(nim_add[...]) it again, changing the
icon on your traybar. A little side-note here; hIcon is not the actual
icon file, it's the handle of the icon file.
|