[delphi][練習]タスクトレイに表示、アイコンを右クリックでメニュー表示 2010/02/07

Delphiです。環境はDelphi2010です。

やりたいこと

タスクトレイにアイコンを表示して、右クリックでメニュー表示させる。

です。

グーグルさんで検索していろいろコードを集めてためしてみています。

今回の調べもの中心は、
  • タスクトレイに表示
  • ポップアップメニュー
  • アプリケーションの終了
です。

タスクトレイ関連のコードはここをメインに調べました。
コンポーネントを使わないコードが紹介されています。役に立つ方法だと思います。


ポップアップメニュー関連


アプリケーションの終了


以下コードです。
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ShellApi, Menus;

type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
test1: TMenuItem;
test21: TMenuItem;
test31: TMenuItem;
exit1: TMenuItem;
procedure TaskTrayWndProc(var Msg: TMessage);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure CreateTaskBarIcon();
procedure DeleteTaskBarIcon();
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure MenuItemExitClick(Sender: TObject);

const
WM_MY_TRAYICON = WM_APP + $300; // 適当です

private
{ Private 宣言 }

public
{ Public 宣言 }
end;

var
Form1: TForm1;
hWndTrayIcon: HWND;
uTaskBarRecreate: UINT;

implementation

{$R *.dfm}
(*
以下のコードは、
http://big2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=0&refresh=1#0207.txt
をいろいろ参考にしています。
*)

(*
タスクトレイに来るWM_MY_TRAYICONメッセージを受信
*)
procedure TForm1.TaskTrayWndProc(var Msg: TMessage);
var
ps: TPoint;
begin
Case Msg.LParam of
WM_LBUTTONDBLCLK:
begin

(*
// 左クリックでフォームを表示する場合
Visible := true;
ShowWindow(Application.Handle, SW_SHOW);
ShowWindow(Application.Handle,SW_RESTORE);
*)
end;
WM_RBUTTONUP:
begin
{ 左クリックと同じコード }
GetCursorPos(ps);
SetForegroundWindow(Handle);
// フォームにポップアップメニューがあるとする
PopupMenu1.Popup(ps.x, ps.y);
PostMessage(Handle, WM_NULL, 0, 0);
end;
else
// タスクバーが移動・再構築された場合に消えたアイコンを再生成
if (Msg.LParam = LongInt(uTaskBarRecreate)) then
CreateTaskBarIcon;
end;
end;

(*
このプログラムではフォームを表示させてないので、つかわれないはず。
*)
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
// WM_QUIT メッセージを受け取る時
if Application.Terminated then
begin
ShowWindow(Application.Handle, SW_HIDE);
Visible := False;
Action := caNone;
end;
end;

(*
フォームが作られるとき
このコード意味がわかってないので、あとで調べるべし
*)
procedure TForm1.FormCreate(Sender: TObject);
begin
// uTaskBarRecrate は TForm1 の private に UINT 型で宣言
// 新しい UtilWindow を作成し、ブロードキャストメッセージのみを受け取らせる
uTaskBarRecreate := RegisterWindowMessage('TaskbarCreated');
// hWndTrayIcon は TForm1 の private に HWND 型で宣言
// メッセージ送信先を指定
hWndTrayIcon := AllocateHWnd(TaskTrayWndProc);


CreateTaskBarIcon;
// フォームを表示させないようにする
ShowWindow(Application.Handle, SW_HIDE);
Application.ShowMainForm := False;
end;

(*
アイコンをトレイに登録−−ここではメインアイコンを使用
*)
procedure TForm1.CreateTaskBarIcon;
var
NotifyData: TNotifyIconData;
begin
with NotifyData do
begin
cbSize := SizeOf(TNotifyIconData);
Wnd := hWndTrayIcon;
uID := 0;
uFlags := NIF_MESSAGE or NIF_ICON or NIF_TIP;
szTip := '右クリックでメニュー表示';
hIcon := Application.Icon.Handle;
uCallbackMessage := WM_MY_TRAYICON; // 独自に定義
end;
Shell_NotifyIcon(NIM_ADD, @NotifyData);
end;

(*
アイコンを削除
*)
procedure TForm1.DeleteTaskBarIcon;
var
NotifyData: TNotifyIconData;
begin
with NotifyData do
begin
cbSize := SizeOf(TNotifyIconData);
Wnd := hWndTrayIcon;
uID := 0;
end;
Shell_NotifyIcon(NIM_DELETE, @NotifyData);
end;

(*
ポップアップメニューのexitでアプリケーションを終了
*)
procedure TForm1.MenuItemExitClick(Sender: TObject);
var
Control: TControl;
begin

(*
//クリックされたメニュー項目のタグにより対応するコントロールのEnableを切り替え
Control := (FindComponent
(Components[(Sender as TMenuItem).Tag].Name) as TControl);
Control.Enabled := not Control.Enabled;
*)
FormDestroy(Sender);
Application.Terminate;
end;

(*
終了した時にトレイのアイコンを削除
この処理を行わないとアイコンが残ってるようにみえる
*)
procedure TForm1.FormDestroy(Sender: TObject);
begin
DeleteTaskBarIcon;
DeallocateHWnd(hWndTrayIcon);
end;

end.

: