2007. február 24., szombat

How to run an application in systray mode


Problem/Question/Abstract:

How to run an application in systray mode

Answer:

Solve 1:

Nothing special. It's just a normal application hiding all of its forms and displaying an icon in the systray. The shell takes care of displaying the icon. Just send a message with all info to the shell. Here is an example:

var
  Nid: TNOTIFYICONDATA;

  prodecure ShowTrayIcon();
begin
  nid.cbSize := sizeof(TNOTIFYICONDATA);
  nid.Wnd := Form1.Handle;
  nid.uID := 1;
  nid.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
  nid.uCallbackMessage := WM_MYMESSAGE; {or make it Nil if you don't need it}
  nid.hIcon := LoadIcon(0, IDI_EXCLAMATION); {replace this by your icon}
  lstrcpy(nid.szTip, 'This is my hint');
  Shell_NotifyIcon(NIM_ADD, @nid);
end;

Only have Win32 code for the callback:

function WndProc(hwnd: HWND; msg: integer; wParam: WPARAM;
  lParam: LPARAM): LRESULT; stdcall;
begin
  case msg of
    WM_MYMESSAGE:
      begin
        case (LOWORD(lParam)) of
          WM_LBUTTONDOWN:
            begin
              MessageBox(hwnd, 'You pressed the left mouse button', 'Caption',
                                                                         MB_YESNO or MB_SETFOREGROUND or MB_SYSTEMMODAL);
            end;
          WM_RBUTTONDOWN:
            begin
              PostQuitMessage(0);
              result := 0;
            end
        else
          begin
            result := 0;
          end;
        end;
        result := 1; {true}
      end;
    WM_CLOSE:
      begin
        PostQuitMessage(0);
        result := 0;
        {Exit;}
      end;
    WM_DESTROY:
      begin
        PostQuitMessage(0);
        result := 0;
        {Exit;}
      end;
  end;
  result := DefWindowProc(hwnd, msg, wParam, lParam);
end;


Solve 2:

Try this and don't forget the TImageList holding your icon:

unit Main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Shellapi, ImgList, VersionMonitor;

type
  TForm1 = class(TForm)
    ImageList1: TImageList;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private Declarations }
    Data: PNotifyIconData;
    wm_notifyicon: Cardinal;
    notifyHandle: THandle;
    procedure MyOnClose(var Message: TMessage); message WM_CLOSE;
  public
    { Public Declarations }
    procedure NotifyIconEvnt(var Param: TMessage);
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  aIcon: TIcon;
begin
  wm_notifyicon := RegisterWindowMessage('wm_notifyicon');
  notifyHandle := AllocateHWnd(NotifyIconEvnt);
  aIcon := TIcon.Create;
  ImageList1.GetIcon(0, aIcon);
  new(Data);
  Data.cbSize := sizeof(TNotifyIconData);
  Data.Wnd := notifyHandle;
  Data.uFlags := NIF_ICON or NIF_MESSAGE or NIF_TIP;
  Data.uCallbackMessage := WM_NOTIFYICON;
  Data.hIcon := aIcon.handle;
  StrCopy(Data.szTip, 'Tooltip hint');
  Shell_NotifyIcon(NIM_ADD, Data);
  SetWindowLong(Application.Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
  Form1.Visible := False;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Shell_NotifyIcon(NIM_DELETE, Data);
  DeallocateHWnd(notifyHandle);
  dispose(Data);
end;

procedure TForm1.MyOnClose(var Message: TMessage);
begin
  Beep;
  Close;
end;

procedure TForm1.NotifyIconEvnt(var Param: TMessage);
begin
  case Param.LParam of
    WM_LBUTTONDOWN:
      begin
        Form1.Visible := True;
      end;
    WM_RBUTTONDOWN:
      begin
        Form1.Visible := False;
      end;
    WM_CLOSE:
      begin
        DeallocateHWnd(notifyHandle);
        Close;
      end;
  end;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  DeallocateHWnd(notifyHandle);
  CanClose := True;
end;

end.

Nincsenek megjegyzések:

Megjegyzés küldése