ギャラリーの操作

Windows リボン フレームワークは、さまざまなコレクション ベースのコントロールにわたって動的コンテンツを管理するための堅牢で一貫性のあるモデルを開発者に提供します。 リボン UI を調整および再構成することで、これらの動的コントロールを使用すると、フレームワークはホスト アプリケーションとリボン自体の両方でユーザー操作に応答し、さまざまな実行時環境を柔軟に処理できます。

はじめに

実行時の条件、アプリケーション要件、およびエンド ユーザー入力に動的に適応するリボン フレームワークのこの機能は、フレームワークの豊富な UI 機能を強調し、開発者は幅広い顧客ニーズに対応できる柔軟性を提供します。

このガイドの焦点は、フレームワークでサポートされている動的ギャラリー コントロールについて説明し、その違いを説明し、それらが最適に使用されるタイミングと場所について説明し、リボン アプリケーションに組み込む方法を示します。

ギャラリー

ギャラリーは、機能的かつグラフィカルに豊富なリスト ボックス コントロールです。 ギャラリーのアイテム コレクションは、カテゴリ別に整理でき、柔軟な列および行ベースのレイアウトで表示され、画像とテキストで表され、ギャラリーの種類に応じてライブ プレビューがサポートされます。

ギャラリーは、次の理由により、他の動的リボン コントロールとは機能的に異なります。

  • ギャラリーは、ギャラリー項目コレクションを操作するためのさまざまなメソッドを定義する IUICollection インターフェイスを実装します。
  • ギャラリーは、ユーザーがクイック アクセス ツール バー (QAT) にコマンドを追加したときなど、リボンで直接発生するアクティビティに基づいて、実行時に更新できます。
  • ギャラリーは、プリンター ドライバーが縦ページ レイアウトのみをサポートしている場合など、実行時環境から間接的に発生するアクティビティに基づいて、実行時に更新できます。
  • ユーザーがドキュメント内のアイテムを選択したときなど、ホスト アプリケーションで間接的に発生するアクティビティに基づいて、実行時にギャラリーを更新できます。

リボン フレームワークは、アイテム ギャラリーとコマンド ギャラリーの 2 種類のギャラリーを公開します。

アイテム ギャラリー

アイテム ギャラリーには、各アイテムが画像、文字列、またはその両方で表される、関連アイテムのインデックスベースのコレクションが含まれています。 コントロールは、 UI_PKEY_SelectedItem プロパティによって識別されるインデックス値に依存する単一の Command ハンドラーにバインドされます。

アイテム ギャラリーではライブ プレビューがサポートされています。これは、コマンドにコミットしたり、実際に Command を呼び出したりすることなく、マウスオーバーまたはフォーカスに基づいてコマンドの結果を表示することを意味します。

重要

フレームワークでは、アプリケーション メニューでのアイテム ギャラリーのホストはサポートされていません。

 

コマンド ギャラリー

コマンド ギャラリーには、インデックスのない個別の項目のコレクションが含まれています。 各項目は、Command ID を介して Command ハンドラーにバインドされた 1 つのコントロールによって表されます。 スタンドアロン コントロールと同様に、Command ギャラリー内の各項目は、関連付けられた Command ハンドラーに入力イベントをルーティングします。コマンド ギャラリー自体はイベントをリッスンしません。

コマンド ギャラリーでは、ライブ プレビューはサポートされていません。

リボン フレームワークには、DropDownGallery、SplitButtonGalleryInRibbonGalleryComboBox の 4 つのギャラリー コントロールがあります。 ComboBox を除くすべての項目ギャラリーまたはコマンド ギャラリーとして実装できます。

DropDownGallery は、相互に排他的な項目または Commands のコレクションを含むドロップダウン リストを表示するボタンです。

次のスクリーン ショットは、Windows 7 用のMicrosoft ペイントのリボン ドロップダウン ギャラリー コントロールを示しています。

Windows 7 用 Microsoft Paint のドロップダウン ギャラリー コントロールのスクリーン ショット。

SplitButtonGallery

SplitButtonGallery は、1 つの既定の項目または Command をコレクションからプライマリ ボタンで公開し、その他の項目またはコマンドを相互に排他的なドロップダウン リストに表示する複合コントロールで、セカンダリ ボタンがクリックされたときに表示されます。

次のスクリーン ショットは、Windows 7 用のMicrosoft ペイントのリボン分割ボタン ギャラリー コントロールを示しています。

Windows 7 用 Microsoft Paint の分割ボタン ギャラリー コントロールのスクリーン ショット。

InRibbonGallery

InRibbonGallery は、リボンの関連アイテムまたはコマンドのコレクションを表示するギャラリーです。 ギャラリーにアイテムが多すぎる場合は、展開されたウィンドウにコレクションの残りの部分を表示するための展開矢印が表示されます。

次のスクリーン ショットは、Windows 7 用のMicrosoft ペイントのリボン内ギャラリー コントロールを示しています。

Microsoft ペイント リボンのリボン内ギャラリー コントロールのスクリーン ショット。

ComboBox

ComboBox は、静的コントロールまたは編集コントロールとドロップダウン矢印を含む項目のコレクションを含む 1 列のリスト ボックスです。 ユーザーがドロップダウン矢印をクリックすると、コントロールのリスト ボックス部分が表示されます。

次のスクリーン ショットは、Windows Live ムービー メーカーのリボン コンボ ボックス コントロールを示しています。

Microsoft ペイント リボンのコンボボックス コントロールのスクリーン ショット。

ComboBox は排他的に項目ギャラリーであるため、Command 項目はサポートされていません。 また、コマンド スペースをサポートしない唯一のギャラリー コントロールでもあります。 (Command Space は、マークアップで宣言され、項目ギャラリーまたはコマンド ギャラリーの下部に一覧表示されるコマンドのコレクションです)。

次のコード例は、 DropDownGallery で 3 ボタンの Command Space を宣言するために必要なマークアップを示しています。

<DropDownGallery 
  CommandName="cmdSizeAndColor" 
  TextPosition="Hide" 
  Type="Commands"
  ItemHeight="32"
  ItemWidth="32">
  <DropDownGallery.MenuLayout>
    <FlowMenuLayout Rows="2" Columns="3" Gripper="None"/>
  </DropDownGallery.MenuLayout>
  <Button CommandName="cmdCommandSpace1"/>
  <Button CommandName="cmdCommandSpace2"/>
  <Button CommandName="cmdCommandSpace3"/>
</DropDownGallery>

次のスクリーン ショットは、前のコード例の 3 ボタンの Command Space を示しています。

ドロップダウンギャラリー内の 3 ボタンのコマンド空間のスクリーン ショット。

このセクションでは、リボン ギャラリーの実装の詳細について説明し、リボン アプリケーションに組み込む方法について説明します。

基本的なコンポーネント

このセクションでは、リボン フレームワークの動的コンテンツのバックボーンを形成し、実行時にリボン ギャラリーのコンテンツとビジュアル レイアウトの追加、削除、更新、その他の操作をサポートする一連のプロパティとメソッドについて説明します。

IUICollection

ギャラリーには、コレクション内の個々の項目にアクセスして操作するための基本的なメソッド セットが必要です。

IEnumUnknown インターフェイスはこれらのメソッドを定義し、フレームワークは IUICollection インターフェイスで定義されている追加のメソッドでその機能を補完します。 IUICollection は、リボン マークアップの各ギャラリー宣言のフレームワークによって実装されます。

IUICollection インターフェイスによって提供されない追加の機能が必要な場合は、ホスト アプリケーションによって実装され、IEnumUnknown から派生したカスタム コレクション オブジェクトをフレームワーク コレクションに置き換えることができます。

IUICollectionChangedEvent

アプリケーションがギャラリー コレクションの変更に応答するには、 IUICollectionChangedEvent インターフェイスを実装する必要があります。 アプリケーションは、IUICollectionChangedEvent::OnChanged イベント リスナーを介して IUICollection オブジェクトからの通知をサブスクライブできます。

アプリケーションがフレームワークによって提供されるギャラリー コレクションをカスタム コレクションに置き換える場合、アプリケーションは IConnectionPointContainer インターフェイスを実装する必要があります。 IConnectionPointContainer が実装されていない場合、アプリケーションは、ギャラリー コントロールの動的更新を必要とするカスタム コレクション内の変更をフレームワークに通知できません。

IConnectionPointContainer が実装されていない場合、ギャラリー コントロールは、IUIFramework::InvalidateUICommand および IUICommandHandler::UpdateProperty を使用するか、または IUIFramework::SetUICommandProperty を呼び出すことによってのみ更新できます。

IUISimplePropertySet

アプリケーションは、ギャラリー コレクション内の各項目または Command に IUISimplePropertySet を実装する必要があります。 ただし、 IUISimplePropertySet::GetValue で要求できるプロパティは異なります。

アイテムは、 UI_PKEY_ItemsSource プロパティ キーを使用してギャラリーに定義およびバインドされ、 IUICollection オブジェクトを使用してプロパティを公開します。

アイテム ギャラリー (UI_COMMANDTYPE_COLLECTION) 内のアイテムの有効なプロパティを次の表に示します。

注意

UI_PKEY_Labelなどの一部の項目プロパティは、マークアップで定義できます。 詳細については、 プロパティ キー のリファレンス ドキュメントを参照してください。

 

コントロール

Properties

ComboBox

UI_PKEY_LabelUI_PKEY_CategoryId

DropDownGallery

UI_PKEY_LabelUI_PKEY_ItemImageUI_PKEY_CategoryId

InRibbonGallery

UI_PKEY_LabelUI_PKEY_ItemImageUI_PKEY_CategoryId

SplitButtonGallery

UI_PKEY_LabelUI_PKEY_ItemImageUI_PKEY_CategoryId

UI_PKEY_SelectedItem はアイテム ギャラリーのプロパティです。

 

コマンド ギャラリー (UI_COMMANDTYPE_COMMANDCOLLECTION) の有効な項目プロパティを次の表に示します。

コントロール Properties
DropDownGallery UI_PKEY_CommandIdUI_PKEY_CommandTypeUI_PKEY_CategoryId
InRibbonGallery UI_PKEY_CommandIdUI_PKEY_CommandTypeUI_PKEY_CategoryId
SplitButtonGallery UI_PKEY_CommandIdUI_PKEY_CommandTypeUI_PKEY_CategoryId

 

カテゴリは、ギャラリー内のアイテムとコマンドを整理するために使用されます。 カテゴリは、 UI_PKEY_Categories プロパティ キーを使用してギャラリーに定義およびバインドされ、カテゴリ固有の IUICollection オブジェクトを使用してプロパティを公開します。

カテゴリには CommandType がないため、ユーザー操作はサポートされていません。 たとえば、項目ギャラリーでカテゴリを SelectedItem にすることはできません。また、コマンド ギャラリーの Command にバインドされません。 他のギャラリー 項目プロパティと同様に、IUISimplePropertySet::GetValue を呼び出すことで、UI_PKEY_LabelやUI_PKEY_CategoryIdなどのカテゴリ プロパティを取得できます。

重要

IUISimplePropertySet::GetValue は、関連付けられたカテゴリを持たないアイテムに対してUI_PKEY_CategoryIdが要求されたときに、UI_COLLECTION_INVALIDINDEXを返す必要があります。

 

マークアップでコントロールを宣言する

ギャラリーは、すべてのリボン コントロールと同様に、マークアップで宣言する必要があります。 ギャラリーは、マークアップで項目ギャラリーまたはコマンド ギャラリーとして識別され、さまざまなプレゼンテーションの詳細が宣言されます。 他のコントロールとは異なり、ギャラリーでは、基本コントロール (コレクション コンテナー) のみをマークアップで宣言する必要があります。 実際のコレクションは実行時に設定されます。 ギャラリーがマークアップで宣言されている場合、ギャラリーが Command ギャラリーのアイテム ギャラリーであるかどうかを指定するために Type 属性が使用されます。

ここで説明するコントロールごとに、さまざまなオプションのレイアウト属性を使用できます。 これらの属性は、コントロールの設定方法とリボンへの表示方法に直接影響を与えるフレームワークの開発者設定を提供します。 マークアップに適用できる基本設定は、「 サイズ定義とスケーリング ポリシーによるリボンのカスタマイズ」で説明されている表示とレイアウトのテンプレートと動作に関連しています。

特定のコントロールがマークアップでレイアウト設定を直接許可しない場合、またはレイアウトの基本設定が指定されていない場合、フレームワークは、使用可能な画面領域の量に基づいてコントロール固有の表示規則を定義します。

次の例では、一連のギャラリーをリボンに組み込む方法を示します。

コマンド宣言

コマンドは、コントロールまたはコントロールのセットを Command に関連付けるために使用される CommandName 属性を使用して宣言する必要があります。

マークアップのコンパイル時に Command を Command ハンドラーにバインドするために使用される CommandId 属性も、ここで指定できます。 ID が指定されていない場合は、フレームワークによって ID が生成されます。

<!-- ComboBox -->
<Command Name="cmdComboBoxGroup"
         Symbol="cmdComboBoxGroup"
         Comment="ComboBox Group"
         LabelTitle="ComboBox"/>
<Command Name="cmdComboBox"
         Symbol="cmdComboBox"
         Comment="ComboBox"
         LabelTitle="ComboBox"/>

<!-- DropDownGallery -->
<Command Name="cmdDropDownGalleryGroup"
         Symbol="cmdDropDownGalleryGroup"
         Comment="DropDownGallery Group"
         LabelTitle="DropDownGallery"/>
<Command Name="cmdDropDownGallery"
         Symbol="cmdDropDownGallery"
         Comment="DropDownGallery"
         LabelTitle="DropDownGallery"/>

<!-- InRibbonGallery -->
<Command Name="cmdInRibbonGalleryGroup"
         Symbol="cmdInRibbonGalleryGroup"
         Comment="InRibbonGallery Group"
         LabelTitle="InRibbonGallery"/>
<Command Name="cmdInRibbonGallery"
         Symbol="cmdInRibbonGallery"
         Comment="InRibbonGallery"
         LabelTitle="InRibbonGallery"

<!-- SplitButtonGallery -->
<Command Name="cmdSplitButtonGalleryGroup"
         Symbol="cmdSplitButtonGalleryGroup"
         Comment="SplitButtonGallery Group"
         LabelTitle="SplitButtonGallery"/>
<Command Name="cmdSplitButtonGallery"
         Symbol="cmdSplitButtonGallery"
         Comment="SplitButtonGallery"
         LabelTitle="SplitButtonGallery"

コントロール宣言

このセクションには、さまざまなギャラリーの種類に必要な基本的なコントロール マークアップを示す例が含まれています。 ギャラリー コントロールを宣言し、 CommandName 属性を使用して Command に関連付ける方法を示します。

次の例は、Type 属性を使用してこれがコマンド ギャラリーであることを指定する DropDownGallery のコントロール宣言を示しています。

<!-- DropDownGallery -->
<Group CommandName="cmdDropDownGalleryGroup">
  <DropDownGallery CommandName="cmdDropDownGallery"
                   TextPosition="Hide"
                   Type="Commands"
                   ItemHeight="32"
                   ItemWidth="32">
    <DropDownGallery.MenuLayout>
      <FlowMenuLayout Rows="2"
                      Columns="3"
                      Gripper="None"/>
    </DropDownGallery.MenuLayout>
    <DropDownGallery.MenuGroups>
      <MenuGroup>
        <Button CommandName="cmdButton1"></Button>
        <Button CommandName="cmdButton2"></Button>
       </MenuGroup>
       <MenuGroup>
        <Button CommandName="cmdButton3"></Button>
      </MenuGroup>
    </DropDownGallery.MenuGroups>
  </DropDownGallery>
</Group>

次の例は、 SplitButtonGallery のコントロール宣言を示しています。

<!-- SplitButtonGallery -->
<Group CommandName="cmdSplitButtonGalleryGroup">
  <SplitButtonGallery CommandName="cmdSplitButtonGallery">
    <SplitButtonGallery.MenuLayout>
      <FlowMenuLayout Rows="2"
                      Columns="3"
                      Gripper="None"/>
    </SplitButtonGallery.MenuLayout>
    <SplitButtonGallery.MenuGroups>
      <MenuGroup>
        <Button CommandName="cmdButton1"></Button>
        <Button CommandName="cmdButton2"></Button>
      </MenuGroup>
      <MenuGroup>
        <Button CommandName="cmdButton3"></Button>
      </MenuGroup>
    </SplitButtonGallery.MenuGroups>
  </SplitButtonGallery>
</Group>

次の例は、 InRibbonGallery のコントロール宣言を示しています。

注意

InRibbonGallery は、ドロップダウン メニューをアクティブ化せずにリボンに項目コレクションのサブセットを表示するように設計されているため、リボンの初期化時にサイズと項目のレイアウトを制御するオプションの属性が多数用意されています。 これらの属性は InRibbonGallery に固有であり、他の動的コントロールからは使用できません。

 

<!-- InRibbonGallery -->
<Group CommandName="cmdInRibbonGalleryGroup" SizeDefinition="OneInRibbonGallery">
  <InRibbonGallery CommandName="cmdInRibbonGallery"
                   MaxColumns="10"
                   MaxColumnsMedium="5"
                   MinColumnsLarge="5"
                   MinColumnsMedium="3"
                   Type="Items">
    <InRibbonGallery.MenuLayout>
      <VerticalMenuLayout Rows="2"
                          Gripper="Vertical"/>
    </InRibbonGallery.MenuLayout>
    <InRibbonGallery.MenuGroups>
      <MenuGroup>
        <Button CommandName="cmdButton1"></Button>
        <Button CommandName="cmdButton2"></Button>
      </MenuGroup>
      <MenuGroup>
        <Button CommandName="cmdButton3"></Button>
      </MenuGroup>
    </InRibbonGallery.MenuGroups>            
  </InRibbonGallery>
</Group>

次の例は、 ComboBox のコントロール宣言を示しています。

<!-- ComboBox -->
<Group CommandName="cmdComboBoxGroup">
  <ComboBox CommandName="cmdComboBox">              
  </ComboBox>
</Group>

コマンド ハンドラーを作成する

コマンドごとに、リボン フレームワークには、ホスト アプリケーションで対応する Command ハンドラーが必要です。 コマンド ハンドラーはリボン ホスト アプリケーションによって実装され、 IUICommandHandler インターフェイスから派生します。

注意

複数のコマンドを 1 つのコマンド ハンドラーにバインドできます。

 

コマンド ハンドラーは、次の 2 つの目的を果たします。

  • IUICommandHandler::UpdateProperty は 、プロパティの更新要求に応答します。 UI_PKEY_EnabledUI_PKEY_Labelなどの Command プロパティの値は、IUIFramework::SetUICommandProperty または IUIFramework::InvalidateUICommand の呼び出しによって設定されます。
  • IUICommandHandler::Execute は 実行イベントに応答します。 このメソッドは、 UI_EXECUTIONVERB パラメーターで指定される次の 3 つの実行状態をサポートしています。
    • Execute 状態は、ハンドラーがバインドされているコマンドを実行またはコミットします。
    • プレビュー状態では、ハンドラーがバインドされているコマンドがプレビューされます。 これは基本的に、結果にコミットせずにコマンドを実行します。
    • CancelPreview 状態では、プレビューされたコマンドが取り消されます。 これは、メニューまたはリストを介したトラバーサルをサポートし、必要に応じて結果を順番にプレビューして元に戻すために必要です。

次の例では、ギャラリー コマンド ハンドラーを示します。

/*
 * GALLERY COMMAND HANDLER IMPLEMENTATION
 */
class CGalleryCommandHandler
      : public CComObjectRootEx<CComMultiThreadModel>
      , public IUICommandHandler
{
public:
  BEGIN_COM_MAP(CGalleryCommandHandler)
    COM_INTERFACE_ENTRY(IUICommandHandler)
  END_COM_MAP()

  // Gallery command handler's Execute method
  STDMETHODIMP Execute(UINT nCmdID,
                       UI_EXECUTIONVERB verb, 
                       const PROPERTYKEY* key,
                       const PROPVARIANT* ppropvarValue,
                       IUISimplePropertySet* pCommandExecutionProperties)
  {
    HRESULT hr = S_OK;
        
    // Switch on manner of execution (Execute/Preview/CancelPreview)
    switch (verb)
    {
      case UI_EXECUTIONVERB_EXECUTE:
        if(nCmdID == cmdTextSizeGallery || 
           nCmdID == cmdTextSizeGallery2 || 
           nCmdID == cmdTextSizeGallery3)
        {
          if (pCommandExecutionProperties != NULL)
          {
            CItemProperties *pItem = 
              static_cast<CItemProperties *>(pCommandExecutionProperties);
            g_prevSelection = g_index = pItem->GetIndex();
            UpdateGallerySelectedItems();
            ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
          }
          else
          {
            g_prevSelection = g_index = 0;
            UpdateGallerySelectedItems();
            ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
          }
        }           
        break;
      case UI_EXECUTIONVERB_PREVIEW:
        CItemProperties *pItem = 
          static_cast<CItemProperties *>(pCommandExecutionProperties);
        g_index = pItem->GetIndex();
        ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
        break;
      case UI_EXECUTIONVERB_CANCELPREVIEW:
        g_index = g_prevSelection;
        ::InvalidateRect(g_hWindowFrame, NULL, TRUE);
        break;
    }   
    return hr;
  }

  // Gallery command handler's UpdateProperty method
  STDMETHODIMP UpdateProperty(UINT nCmdID,
                              REFPROPERTYKEY key,
                              const PROPVARIANT* ppropvarCurrentValue,
                              PROPVARIANT* ppropvarNewValue)
  {
    UNREFERENCED_PARAMETER(ppropvarCurrentValue);

    HRESULT hr = E_NOTIMPL;         

    if (key == UI_PKEY_ItemsSource) // Gallery items requested
    {
      if (nCmdID == cmdTextSizeGallery || 
          nCmdID == cmdTextSizeGallery2 || 
          nCmdID == cmdTextSizeGallery3)
      {
        CComQIPtr<IUICollection> spCollection(ppropvarCurrentValue->punkVal);

        int count = _countof(g_labels);

        for (int i = 0; i < count; i++)
        {
          CComObject<CItemProperties> * pItem;
          CComObject<CItemProperties>::CreateInstance(&pItem);
                    
          pItem->AddRef();
          pItem->Initialize(i);

          spCollection->Add(pItem);
        }
        return S_OK;
      }
      if (nCmdID == cmdCommandGallery1)
      {
        CComQIPtr<IUICollection> spCollection(ppropvarCurrentValue->punkVal);

        int count = 12;
        int commands[] = {cmdButton1, 
                          cmdButton2, 
                          cmdBoolean1, 
                          cmdBoolean2, 
                          cmdButton1, 
                          cmdButton2, 
                          cmdBoolean1, 
                          cmdBoolean2, 
                          cmdButton1, 
                          cmdButton2, 
                          cmdBoolean1, 
                          cmdBoolean2};

        for (int i = 0; i < count; i++)
        {
          CComObject<CItemProperties> * pItem;
          CComObject<CItemProperties>::CreateInstance(&pItem);
                    
          pItem->AddRef();
          pItem->InitializeAsCommand(commands[i]);

          spCollection->Add(pItem);
        }
        return S_OK;
      }
    }        
    else if (key == UI_PKEY_SelectedItem) // Selected item requested
    {           
      hr = UIInitPropertyFromUInt32(UI_PKEY_SelectedItem, g_index, ppropvarNewValue);           
    }
    return hr;
  }
};

コマンド ハンドラーをバインドする

Command ハンドラーを定義した後、Command をハンドラーにバインドする必要があります。

次の例では、ギャラリー Command を特定の Command ハンドラーにバインドする方法を示します。 この場合、 ComboBox コントロールとギャラリー コントロールの両方がそれぞれの Command ハンドラーにバインドされます。

// Called for each Command in markup. 
// Application will return a Command handler for each Command.
STDMETHOD(OnCreateUICommand)(UINT32 nCmdID,
                             UI_COMMANDTYPE typeID,
                             IUICommandHandler** ppCommandHandler) 
{   
  // CommandType for ComboBox and galleries
  if (typeID == UI_COMMANDTYPE_COLLECTION || typeID == UI_COMMANDTYPE_COMMANDCOLLECTION) 
  {
    switch (nCmdID)
    {
      case cmdComboBox:
        CComObject<CComboBoxCommandHandler> * pComboBoxCommandHandler;
        CComObject<CComboBoxCommandHandler>::CreateInstance(&pComboBoxCommandHandler);
        return pComboBoxCommandHandler->QueryInterface(IID_PPV_ARGS(ppCommandHandler));
      default:
        CComObject<CGalleryCommandHandler> * pGalleryCommandHandler;
        CComObject<CGalleryCommandHandler>::CreateInstance(&pGalleryCommandHandler);
        return pGalleryCommandHandler->QueryInterface(IID_PPV_ARGS(ppCommandHandler));
    }
    return E_NOTIMPL; // Command is not implemented, so do not pass a handler back.
  }
}

コレクションを初期化する

次の例では、アイテム ギャラリーとコマンド ギャラリーの両方に対する IUISimplePropertySet のカスタム実装を示します。

この例の CItemProperties クラスは、 IUISimplePropertySet から派生しています。 必要なメソッド IUISimplePropertySet::GetValue に加えて、CItemProperties クラスは、初期化とインデックスの追跡のためのヘルパー関数のセットを実装します。

//
//  PURPOSE:    Implementation of IUISimplePropertySet.
//
//  COMMENTS:
//              Three gallery-specific helper functions included. 
//

class CItemProperties
  : public CComObjectRootEx<CComMultiThreadModel>
  , public IUISimplePropertySet
{
  public:

  // COM map for QueryInterface of IUISimplePropertySet.
  BEGIN_COM_MAP(CItemProperties)
    COM_INTERFACE_ENTRY(IUISimplePropertySet)
  END_COM_MAP()

  // Required method that enables property key values to be 
  // retrieved on gallery collection items.
  STDMETHOD(GetValue)(REFPROPERTYKEY key, PROPVARIANT *ppropvar)
  {
    HRESULT hr;

    // No category is associated with this item.
    if (key == UI_PKEY_CategoryId)
    {
      return UIInitiPropertyFromUInt32(UI_PKEY_CategoryId, 
                                       UI_COLLECTION_INVALIDINDEX, 
                                       pprovar);
    }

    // A Command gallery.
    // _isCommandGallery is set on initialization.
    if (_isCommandGallery)
    {           
      if(key == UI_PKEY_CommandId && _isCommandGallery)
      {
        // Return a pointer to the CommandId of the item.
        return InitPropVariantFromUInt32(_cmdID, ppropvar);
      }         
    }
    // An item gallery.
    else
    {
      if (key == UI_PKEY_Label)
      {
        // Return a pointer to the item label string.
        return UIInitPropertyFromString(UI_PKEY_Label, ppropvar);
      }
      else if(key == UI_PKEY_ItemImage)
      {
        // Return a pointer to the item image.
        return UIInitPropertyFromImage(UI_PKEY_ItemImage, ppropvar);
      }         
    }
    return E_NOTIMPL;
  }

  // Initialize an item in an item gallery collection at the specified index.
  void Initialize(int index)
  {
    _index = index;
    _cmdID = 0;
    _isCommandGallery = false;
  }

  // Initialize a Command in a Command gallery.
  void InitializeAsCommand(__in UINT cmdID)
  {
    _index = 0;
    _cmdID = cmdID;
    _isCommandGallery = true;
  }

  // Gets the index of the selected item in an item gallery.
  int GetIndex()
  {
    return _index;
  }

private:
  int _index;
  int _cmdID;
  bool _isCommandGallery;   
};

コレクション イベントの処理

次の例は、IUICollectionChangedEvent 実装を示しています。

class CQATChangedEvent
  : public CComObjectRootEx<CComSingleThreadModel>
  , public IUICollectionChangedEvent
{
  public:

  HRESULT FinalConstruct()
  {
    _pSite = NULL;
    return S_OK;
  }

  void Initialize(__in CQATSite* pSite)
  {
    if (pSite != NULL)
    {
      _pSite = pSite;
    }
  }

  void Uninitialize()
  {
    _pSite = NULL;
  }

  BEGIN_COM_MAP(CQATChangedEvent)
    COM_INTERFACE_ENTRY(IUICollectionChangedEvent)
  END_COM_MAP()

  // IUICollectionChangedEvent interface
  STDMETHOD(OnChanged)(UI_COLLECTIONCHANGE action, 
                       UINT32 oldIndex, 
                       IUnknown *pOldItem, 
                       UINT32 newIndex, 
                       IUnknown *pNewItem)
  {
    if (_pSite)
    {
      _pSite->OnCollectionChanged(action, oldIndex, pOldItem, newIndex, pNewItem);
    }
    return S_OK;
  }

  protected:
  virtual ~CQATChangedEvent(){}

  private:
  CQATSite* _pSite; // Weak ref to avoid circular refcounts
};

HRESULT CQATHandler::EnsureCollectionEventListener(__in IUICollection* pUICollection)
{
  // Check if listener already exists.
  if (_spQATChangedEvent)
  {
    return S_OK;
  }

  HRESULT hr = E_FAIL;

  // Create an IUICollectionChangedEvent listener.
  hr = CreateInstanceWithRefCountOne(&_spQATChangedEvent);
    
  if (SUCCEEDED(hr))
  {
    CComPtr<IUnknown> spUnknown;
    _spQATChangedEvent->QueryInterface(IID_PPV_ARGS(&spUnknown));

    // Create a connection between the collection connection point and the sink.
    AtlAdvise(pUICollection, spUnknown, __uuidof(IUICollectionChangedEvent), &_dwCookie);
    _spQATChangedEvent->Initialize(this);
  }
  return hr;
}

HRESULT CQATHandler::OnCollectionChanged(
             UI_COLLECTIONCHANGE action, 
          UINT32 oldIndex, 
             IUnknown *pOldItem, 
          UINT32 newIndex, 
          IUnknown *pNewItem)
{
    UNREFERENCED_PARAMETER(oldIndex);
    UNREFERENCED_PARAMETER(newIndex);

    switch (action)
    {
      case UI_COLLECTIONCHANGE_INSERT:
      {
        CComQIPtr<IUISimplePropertySet> spProperties(pNewItem);
                
        PROPVARIANT var;
        if (SUCCEEDED(spProperties->GetValue(UI_PKEY_CommandId, &var)))
        {
          UINT tcid;
          if (SUCCEEDED(UIPropertyToUInt32(UI_PKEY_CommandId, var, &tcid)))
          {
            FireETWEvent(tcid, L"Added to QAT");
            PropVariantClear(&var);
          }
        }
      }
      break;
      case UI_COLLECTIONCHANGE_REMOVE:
      {
        CComQIPtr<IUISimplePropertySet> spProperties(pOldItem);
                
        PROPVARIANT var;
        if (SUCCEEDED(spProperties->GetValue(UI_PKEY_CommandId, &var)))
        {
          UINT tcid;
          if (SUCCEEDED(UIPropertyToUInt32(UI_PKEY_CommandId, var, &tcid)))
          {
            FireETWEvent(tcid, L"Removed from QAT");
            PropVariantClear(&var);
          }
        }
      }
      break;
    default:
  }
  return S_OK;
}

コレクションのプロパティ

リボン アプリケーションの作成

コマンドとコントロールについて

リボン ユーザー エクスペリエンスのガイドライン

リボンのデザイン プロセス

ギャラリーのサンプル