Win7: タスクバープログラミング(AppIDs)

ようやくタスクバープログラミングを書きます…。
Windows 7 のタスクバーに関する前置きは、過去の記事を参考にしてください。

今回は、”Application Identity による管理” ということで、Application Identity(AppIDs とします)に関する
プログラミングのネタです。
Windows のタスクバーですが、プログラムを起動すると、プログラムアイコンがタスクバーに表示されます。
同じプログラムを複数起動した際にはグルーピングされるわけですが、このグルーピングの際、プロセス(exe)名で
管理しているのではなく、Windows は Application Identity という単位で管理しています。
つまり、別の言い方をすると、同じ Application Identity であればグルーピングするという仕様になっているわけです。
そして、Windows 7 では、この Application Identity を任意で変更できるようになりました。

AppIDs は、プロセスのメインウィンドウを生成する際にプロセス名をベースにして OS によって割り当てられます。
(↓セミナーで使っているスライドからの抜粋です)

 
この AppIDs によるグルーピングですが、例えば

  1. 異なるプロセスだが、ひとつのグループにまとめたい
  2. 同じプロセスだが、起動引数によって意味が異なるので、グルーピングしたくない

などのようなシナリオの場合には、AppIDs をカスタマイズすることで、今までの Windows にはできなかった動きを
実装することができます。

わかりやすくするために、画面を使います。
まずは、グルーピングされているイメージです。この 2 つのプロセス名は異なっていますが、Application Identity を
”MyDemo2009Apps” と同じにすることで、アプリケーションアイコンをひとつだけ表示するようにしています。

次に、片方の Application Identity を “MyDemo2009Apps2“ に変更してみます。

するとアプリケーションアイコンが 2 つに分離します。これで動きがわかってもらえるかなと思います。

AppIDs については、次の 2 つの API が用意されています。(かなり長い名前の API デス)

使い方は非常に簡単です。

[Application Identity を設定する]

ネイティブコードで書くなら、WinMain の直後や メインウィンドウを生成する(WM_CREATE 内)が適切です。
.NET Windows フォームであれば、フォームのコンストラクタや Load イベント内が適切です。

int WINAPI _tWinMain(
  HINSTANCE hInstance,
  HINSTANCE /*hPrevInstance*/,
  LPTSTR lpstrCmdLine,
  int nCmdShow)
{
  // アプリケーション ID 名称
  PCWSTR pcwstrAppID = TEXT(“MyDemoApps2009“);
  // アプリケーションに AppID をカスタム設定
  SetCurrentProcessExplicitAppUserModelID(pcwstrAppID);

・・・

[Application Identity を取得する]

任意のタイミングで取得できます。

WCHAR szAppId[129];
WCHAR * psz = szAppId;
HRESULT hRes = GetCurrentProcessExplicitAppUserModelID(&psz);
if (SUCCEEDED(hRes))
{
    m_edAppId.SetWindowText(psz);
}
else
{
    m_edAppId.SetWindowText(TEXT("Unknown Application ID"));
}

ただし、Application Identity には、次の注意点があります。

  • OS が割り当てた既定の Application Identity は取得できない
  • Application Identity の最大文字列長は 128 byte
  • Windows Vista モードでも有効
  • 必ず、タスクバーにアイコンが表示される前に設定する必要がある

では、任意のタイミングで Application Identity を設定/変更することができるのかというと、一応できます。
ただし、あまり推奨されていません。
実は、SetCurrentProcessExplicitAppUserModelID() を任意のタイミングで発行しても Application Identity は変わらないのです。
この API が有効なのは、タスクバーにアイコンが表示される前だけなのです。
では、どうするのかというと、Shell のプロパティストアに格納されている ID を強制的に変更してあげることになります。

[任意のタイミングで Application Identity を変更する]

コードを簡単にするために、ATL を使っています。

HRESULT SetWindowAppId(WCHAR *pszAppId)
{
    CComPtr<IPropertyStore> propStore;
    HRESULT hRes = SHGetPropertyStoreForWindow(m_hWnd, IID_PPV_ARGS(&propStore));
    if (SUCCEEDED(hRes))
    {
        CPropVariant propvar;
        InitPropVariantFromString(pszAppId, &propvar);
        hRes = propStore->SetValue(PKEY_AppUserModel_ID, propvar);
        if (FAILED(hRes))
        {
            // エラー
        }
    }
    else
    {
        // エラー
    }

    return hRes;
}

なお、Application Identity の推奨されるフォーマットは

CompanyName.ProductName.SubProduct.VersionInformation

になっています。
Application Identity をカスタマイズすることによって、Windows 7 に ”より対応” したアプリケーションができると思います。

参考情報

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。