この記事は旧ブログ(amuns:blog)の記事です。

常駐アプリでスタートアップから起動された時、場合によってはタスクトレイにアイコンが表示されない場合があります。
これはアプリが起動時処理に時間がかかり、タイムアウトになった場合起こるようです。

以下Microsoftの技術情報です。
通知領域にアイコンが登録されないことがある

Clibor1.0.3でこの問題に対応しました。
その時のDelphiのソースです。

環境

  • 開発ツール : Turbo Delphi
  • OS : Windows XP

ソース

Turbo DelphiにはTTrayIconというコンポーネントが標準でありますが、Cliborは自前でタスクトレイに格納する処理を書いています。

今回は全てのソースを紹介しませんが、問題の箇所だけ書きたいと思います。
機会があれば別の記事でタスクトレイに格納するソース(クラス)を、すべて紹介したいと思います。

通常タスクトレイに格納する際、以下のようにAPIを呼び出します。
Shell_NotifyIcon(NIM_ADD, @NotifyIcon);

そこで次のように、タイムアウトに対応したメソッドを用意します。

// privateに宣言
NotifyIcon : TNotifyIconData;

// タスクトレイに格納する
procedure TTaskTray.NotifyIconEx(Message: Integer);
var
  i : Integer;
begin
  try

    // リトライする
    for i := 0 to 100 do begin
      if (Shell_NotifyIcon(Message, @NotifyIcon)) then begin
        // 正常終了
        Break;
      end else begin
        if GetLastError() <> ERROR_TIMEOUT then begin
          // タイムアウトじゃない場合は登録失敗
        end;

        if Shell_NotifyIcon(NIM_MODIFY, @NotifyIcon) then begin
          // 正常終了
          Break;
        end else begin
          // タイムアウトなので待ち処理
          Sleep(500);
        end;

      end;
    end;

    // 失敗
    if i > 100 then begin
      // リトライ失敗
    end;

  except
    on E:Exception do begin
      // 例外処理
    end;
  end;
end;

使用する際は、以下のようにします。
NotifyIconEx(NIM_ADD);

これでタイムアウト時にリトライし、アイコンが表示されるようになります。