第 9 章: Hilo Annotator の概要

Hilo は写真や画像の閲覧、コメントの追加、および共有などの機能を備えたサンプル アプリケーションのコレクションです。このシリーズの以前の記事では、Hilo Browser アプリケーションの設計および実装について説明しました。このアプリケーションでは、タッチ対応のユーザー インターフェイスで画像を閲覧および選択することができます。この記事では、選択した写真のトリミング、回転、描画を行うための Hilo Annotator アプリケーションについて説明します。Hilo Annotator では Windows リボン コントロールを使用してさまざまな注釈機能へのアクセスを提供しています。また、Windows Imaging Component にアクセスして、画像とそのメタデータの読み込みや操作を行うこともできます。

Browser と Annotator の統合

Hilo Annotator は独立したアプリケーションであり、デスクトップやコマンド ラインから直接起動することも、Hilo Browser アプリケーション内から起動することもできます。Browser アプリケーションは、Annotator の統合をサポートするように更新されています。ユーザーは、写真を指でダブルタップするか、マウスでダブルクリックすることによって、Browser 内から Annotator を起動できます。このアクションによって、WM_LBUTTONDBLCLK メッセージが生成されます。このメッセージは、メディア ウィンドウで MediaPaneMessageHandler::LaunchAnnotator メソッドによって処理され、選択した写真の名前が渡されます。リスト 1 に、この LaunchAnnotator メソッドのコードを示します。

リスト 1 Annotator プロセスを起動する Hilo Browser のコード

void MediaPaneMessageHandler::LaunchAnnotator(std::wstring fileName)
{
// 最初にターゲットの exe のパスを取得する
    wchar_t currentFileName[FILENAME_MAX];

    if ( !GetModuleFileName(nullptr, currentFileName, FILENAME_MAX) )
    {
        return;
    }

// Annotator はこのバイナリと同じディレクトリにある必要がある
    std::wstring currentDirectory = std::wstring(currentFileName);
    std::wstring externalFileName = currentDirectory.substr(
                                 0, currentDirectory.find_last_of(L"\\") + 1);
    externalFileName += L"annotator.exe";

    STARTUPINFO startInfo;
    PROCESS_INFORMATION processInfo;

// スタートアップ情報およびプロセス情報を格納する構造体を初期化する
    ZeroMemory(&startInfo, sizeof(startInfo));
    startInfo.cb = sizeof(startInfo);
    ZeroMemory(&processInfo, sizeof(processInfo));

// コマンド ライン パラメーター リストを作成する
    wchar_t buffer[FILENAME_MAX];
    swprintf_s(buffer, FILENAME_MAX, L"\"%s\" \"%s\"", externalFileName.c_str(),  
               fileName.c_str());

    ::CreateProcess(nullptr, buffer, nullptr, nullptr, false, 0, nullptr, nullptr,
                    &startInfo, &processInfo);

// メモリを解放する
    ::CloseHandle(processInfo.hProcess);
    ::CloseHandle(processInfo.hThread);

    return;
}

Browser では、Annotator の実行可能ファイルが Browser と同じフォルダーにあることを前提としています。LaunchAnnotator メソッドの最初の部分では、GetModuleFileName 関数を呼び出して Browser アプリケーションへの完全なパスを取得し、フォルダーのパスを抽出します。このフォルダー パスは、Annotator アプリケーションへのパスとして使用されます。

次に、Browser は CreateProcess 関数を使用して Annotator を起動し、編集する写真の名前をコマンド ラインで指定します。Annotator プロセスは、最初の起動時に、AnnotatorApplication::Initialize メソッドでコマンド ラインにアクセスします。リスト 2 に、この処理を行うコードを示します。このコードは、最初に GetCommandLineW メソッドを呼び出し、次に CommandLineToArgvW 関数を呼び出して、コマンド ラインを個々のコマンド ライン引数へのポインターの配列に分割します。コマンド ラインはプロセス環境の一部であるため、プロセスは文字列用の記憶域を提供する必要がなく、文字列バッファーの割り当てを解除するコードを提供する必要もありません。GetCommandLineW 関数を使用する理由は以下の通りです。すなわち、プロセス エントリ ポイント関数 WinMainlpCmdLine パラメーターでは、Hilo の場合のようにプロセスが Unicode 用にコンパイルされていても、コマンド ラインは ANSI 文字列としてのみ**提供されるためです。

リスト 2 コマンド ライン パラメーターにアクセスするための Annotator のコード

int argumentCount = 0;
ComPtr<IShellItem> currentBrowseLocationItem;
if (SUCCEEDED(hr))
{
// コマンド ラインを処理する
   wchar_t ** commandArgumentList = CommandLineToArgvW(
                                        GetCommandLineW(), &argumentCount);

   if (argumentCount > 1)
   {
      hr = ::SHCreateItemFromParsingName(
                       commandArgumentList[1],
            nullptr,
            IID_PPV_ARGS(&currentBrowseLocationItem));
   }
   else
   {
// 既定としてピクチャ ライブラリを設定する
      hr = ::SHCreateItemInKnownFolder(
         FOLDERID_PicturesLibrary, 0, nullptr,
         IID_PPV_ARGS(&currentBrowseLocationItem));

      if (FAILED(hr))
      {
// 最上位レベルのコンピューター フォルダーに設定する
         hr = ::SHGetKnownFolderItem(
                 FOLDERID_ComputerFolder, static_cast<KNOWN_FOLDER_FLAG>(0), 
                 nullptr, IID_PPV_ARGS(&currentBrowseLocationItem));
      }
   }
}

リスト 2 には、コマンド ライン パラメーターを指定してプロセスが起動された場合に、SHCreateItemFromParsingName 関数を呼び出すことによって、コマンド ライン パラメーターを使用してシェル アイテム オブジェクトを作成する処理も示されています。コマンド ライン パラメーターを指定せずに Annotator が呼び出された場合、Annotator はまずピクチャ ライブラリを取得し、これに失敗した場合はコンピューター フォルダーを取得します。シェル アイテム オブジェクトは、ファイル (Browser から渡された写真) とフォルダー (ピクチャ ライブラリまたはコンピューター フォルダー) のいずれかになることに注意してください。Annotator は、このシェル アイテムを使用してエディター ウィンドウ (Browser のメディア ウィンドウに相当) に、指定されたフォルダー内のすべての写真を表示します。シェル アイテム オブジェクトがファイルである場合は、選択した写真を表示します。

Browser と Annotator の間では、コマンド ライン以外の通信は行われません。Annotator は独立したプロセスであるため、ユーザーは Browser にタスクを切り替えて、引き続き Browser を使用することができます。また、Annotator の別のインスタンスを作成することもできます。Browser アプリケーションとの直接的な通信は行われないので、Annotator で写真を変更した場合、Browser でキャッシュされている写真の画像が、Annotator で行われた変更を反映して自動的に更新されることはありません。

Annotator のデバッグ

Browser アプリケーションと Annotator アプリケーションの並列処理アーキテクチャは、ソリューション全体のデバッグ方法と深いかかわりがあります。Annotator は独立したプロセスであるため、Browser をデバッグしているときに Annotator を起動しても、Annotator のコードにステップ インすることはできません。同様に、Browser をデバッグしているときに、Annotator でブレークポイントを設定することはできません。Annotator をデバッグするには、次の 3 つの方法があります。

最初の方法は、ソリューション エクスプローラーで [スタートアップ プロジェクトに設定] をクリックして、Annotator プロセスをデバッグ用に起動することを指定する方法です (図 1)。この方法を使用すると、WinMain 関数を含め、プロセス内の任意の場所にブレークポイントを配置でき、便利です。

図 1 Annotator をスタートアップ プロジェクトとして設定

Ff951239.470cadde-a3e6-42fb-bb43-62991d8a93d4-thumb(ja-jp,MSDN.10).png

Annotator プロセスは、デバッガーによって起動され、デバッガーの下で実行されます。すなわち、Annotator は Browser によって起動されないため、ファイル パスが Browser から渡されなくなるということです。Annotator でコマンド ライン パラメーターがどのように処理されるかをテストする場合は、図 2 に示すように、Annotator の [デバッグ] プロパティ ページを開き、[コマンド引数] プロパティとして、写真の完全なパスを指定する必要があります。

図 2 Annotator のコマンド ラインでの画像の指定

Ff951239.ad517dfc-ae0b-44ff-b73e-1210474478af-thumb(ja-jp,MSDN.10).png

2 つ目の方法は、Browser から Annotator プロセスを起動することを許可し、Annotator プロセスに対して Visual Studio デバッガーをアタッチする方法です。そのためには、[デバッグ] メニューの [プロセスにアタッチ] をクリックします。[プロセスにアタッチ] ダイアログ ボックスに、コンピューターで実行中のすべてのプロセスの一覧が表示されます。デバッガーをアタッチするには、Annotator.exe の行をダブルクリックします (図 3)。この方法は、既存のプロセスにアタッチする場合に便利ですが、デバッグを実行できるのはアタッチした時点以降になります。このため、通常、WinMain 関数や、ウィンドウを作成して初期化するコードをデバッグすることはできません。

図 3 デバッガーを Annotator プロセスにアタッチ

Ff951239.236c6e80-efdd-4b56-abb1-74e6b3eab098-thumb(ja-jp,MSDN.10).png

3 つ目の方法は Just In Time (JIT) デバッグを使用する方法で、Visual C++ Express では実行できませんが、Visual Studio Professional 以上のエディションで実行できます。これを実行するには、プログラム内のデバッグを開始する位置に、DebugBreak 関数 (または __debugbreak 組み込み関数) の呼び出しを挿入します。ただし、これらの関数を使用するには、関数呼び出しでデバッガーを起動できるように Windows 7 で設定しておく必要があります。これらの関数はソフトウェア例外 (int 3 割り込み) を発生させます。既定では Windows 7 のセキュリティ機能はすべての例外をプログラム内のエラーと見なし、オンラインで解決策を検索してこれを処理しようとします。このため、Annotator プロセスについてはこのアクションを無効にしておく必要があります。assert C ランタイム ライブラリ (CRT) 関数が false 状態で呼び出されると、__debugbreak 組み込み関数が呼び出されます。したがって、コード内にアサートがあり、そのアサートを JIT デバッグで処理する場合は、これから説明するように、Windows 7 の問題解決機能を無効にする必要があります。

問題解決機能を無効にするには、[コントロール パネル] の [アクション センター] を開き、[メンテナンス] セクション (図 4) を展開して [設定] をクリックします。

図 4 アクション センターの使用

Ff951239.d7f4e01e-8446-439b-b7af-6787e894943f-thumb(ja-jp,MSDN.10).png

[問題レポートの設定] ページが表示され、コンピューター上で実行されているすべてのプロセスについて使用される設定が示されます (図 5)。このダイアログ ボックスで、問題レポートから除外するプログラムを指定することもできます。[レポートから除外するプログラムを選択] をクリックし、[追加] をクリックして Annotator プロセスのデバッグ ビルドを指定します (図 5 および 図 6)。

図 5 [問題レポートの設定] ダイアログ ボックスの使用

Ff951239.db53702a-6a1d-4c15-a3f8-2501bb12d580-thumb(ja-jp,MSDN.10).png

図 6 Annotator プロセスを問題レポートから除外

Ff951239.87fc704c-7842-4a8b-b816-3294b5eb76ab-thumb(ja-jp,MSDN.10).png

これにより、Annotator の実行中に DebugBreak 関数への呼び出しがあると、Windows 7 で図 7 のようなダイアログ ボックスが表示されます。次に、Visual Studio JIT デバッガーが呼び出され、Visual Studio の新しいインスタンスを起動するか、実行中のインスタンスからデバッガーにアタッチするかを選択できます。

図 7 Windows 7 の問題レポートでプロセスのデバッグを許可

Ff951239.4874a6d2-6a58-42bf-a275-216197dab03b-thumb(ja-jp,MSDN.10).png

JIT デバッグの利点は、DebugBreak 関数の呼び出しを配置できるすべてのコードのデバッグが可能ということですが、アプリケーションのテストが完了したら、このコードを削除する必要があります。

Annotator の UI の確認

Annotator プロセスは、Browser のメディア ウィンドウに表示されている写真を指でダブルタップするか、マウスでダブルクリックすると起動されます。Hilo Annotator のユーザー インターフェイスを図 8 に示します。画像エディター、リボン、およびタイトル バーの 3 つの主な領域があります。

図 8 Hilo Annotator のユーザー インターフェイス

Ff951239.efab4d8e-8eec-4fe9-89fc-487046b60c6d-thumb(ja-jp,MSDN.10).png

画像エディターは、アプリケーション ウィンドウの最も大きな領域を占めています。画像エディターは、Browser のメディア ウィンドウと同様に動作します。マウスまたは左右の矢印キーを使用するか、タッチ スクリーン上で写真を指でドラッグすると、左右にスクロールすることができます。既定のズーム レベルで、1 つの写真全体と、左右の写真のプレビューが表示されます。Annotator は左右の写真をフェードするために、まず画像をレンダリングした後、その画像上で白の線形グラデーション ブラシ (グラデーションは完全な不透明から透明に変化するアルファ チャンネル) を使用して描画します。

画像エディターの上には、Windows リボン コントロールがあります。このリボンには、2 つのタブ、メニュー、およびクイック アクセス ツール バーがあります。[Home] タブは 2 つのグループに分かれており、画像一覧に表示されている写真に対するトリミング、回転、書き込みを行うためのコントロールが用意されています。[Pencil] ボタンまたは [Crop] ボタンをクリックすると、適切なアクションが選択され、鉛筆で書き込みをしたり、画像をトリミングしたりできます。[Rotate] ボタンをクリックすると、写真が時計回りに回転します。[Rotate] コントロールのドロップダウン メニューからは、反時計回りに回転、水平方向に反転、垂直方向に反転など、その他の変形オプションを表示できます。[Color] コントロールは、ドロップダウン カラー ピッカーと呼ばれる標準コントロールです。.このコントロールをクリックすると、色の見本が表示されます。[Size] コントロールは、使用可能な 4 種類の鉛筆の線幅を示すドロップダウン リストです。[View] タブには、ズーム イン、ズーム アウト、および 100% にリセットという 3 種類の操作を示すプッシュ ボタン コントロールがあります。

このリボンには、2 つのメニューがあります。メイン メニューは、リボンの [Home] タブの左側にあるドロップダウン メニュー コントロールです。このメニューには、[Open]、[Save]、[Save A Copy As]、[Exit] という項目があります。もう 1 つのメニューはクイック アクセス ツール バーで、既定ではタイトル バー上に表示されます。クイック アクセス ツール バーには、4 つのコントロールがあります。最初の 3 つは、写真を保存する、アクションを元に戻す、またはアクションをやり直すコマンドを生成するボタンです。4 つ目のコントロールは、ツール バーをカスタマイズするためのドロップダウン メニューで、他のボタンの表示と非表示の切り替え、ツール バーの位置の変更、リボンの最小化を行うことができます。

クイック アクセス ツール バーの既定の位置はタイトル バー上ですが、カスタマイズ メニューには [Show below the Ribbon] というメニュー項目があり、この項目をクリックするとツール バーはリボン コントロールの下に移動し、これに合わせて画像一覧のサイズも変更されます。ツール バーをリボンの下に移動すると、写真を表示する領域が小さくなります。画像エディターの領域を広げるために、クイック アクセス ツール バーの [Minimize the Ribbon] を選択することもできます。リボンを最小化すると、タブの見出しのみが表示されます。これらの見出しのいずれかをクリックすると、タブが、写真の上ではなく、写真の手前に表示されます。

Annotator の使用

Annotator を [スタート] メニューからスタンドアロン プロセスとして起動した場合は、[Open] メニュー項目から編集する写真を選択できます。Browser で写真をダブルタップした場合は、Annotator が起動されると同時に Browser で選択した写真が開かれ、編集可能になります。鉛筆ツールを使用すると、写真に書き込みすることができます。使用する鉛筆の種類は、[Color] および [Size] コントロールで変更できます。[Pencil] ボタンをクリックすると、図 9 のように、カーソルが鉛筆の形に変化し、写真に書き込みができるようになります。

図 9 鉛筆ツールによる写真への書き込み

Ff951239.f2fa0718-97c0-48da-8c1c-ce3147046d6b-thumb(ja-jp,MSDN.10).png

写真に変更を加えると、[Undo] ボタンが有効になります (図 9 のタイトル バー上の左から 3 番目のアイコン)。Annotator では、写真に対して行ったすべての変更の履歴が保持され、[Undo] ボタンによってこれらの手順を 1 つずつ元に戻すことができます ([Redo] ボタンを使用すると、元に戻した手順をやり直すことができます)。

[Pencil] ボタンを選択するとカーソルが鉛筆の形になり、タッチ スクリーンでスタイラスを使用するか、左ボタンを押したままマウスを動かすと、写真に書き込むことができます。[Pencil] ボタンの選択を解除するとカーソルは矢印に戻り、スタイラスを使用するか、左ボタンを押したままマウスを動かすと、写真を移動できます。これは、写真がズーム インされ、エディターに一部しか表示されていない場合、別の部分に移動するのに便利です。

写真のトリミングが必要な場合は、トリミング ツールを使用します。[Crop] ボタンをクリックすると、カーソルが十字に変化し、写真全体が淡色表示されます。この状態で、スタイラスまたはマウスを使用して、写真の新しい境界線を描画することができます (図 10)。

図 10 写真のトリミング

Ff951239.b0a54034-7d2d-4f2a-8730-df36c1179acc-thumb(ja-jp,MSDN.10).png

Annotator では、写真を回転または反転させることもできます。そのためには、[Rotate] ドロップダウン メニューの項目を使用します。図 11 は、時計回りの 90° の回転を示しています。これらの操作のいずれかを実行すると、Annotator では操作のアニメーションが表示され、最終的な結果だけではなく、回転や反転の過程を確認できます。さらに、画像は、使用可能な領域に完全に収まるようにズームして表示されます。図 11 では、トリミングされた画像を回転させると高さが幅よりも大きくなるため、写真の高さがエディター ウィンドウの高さに収まるように写真がズーム アウトされ、見た目が小さくなっています。写真をもう 1 度、90° 回転させると、画像の幅が高さよりも大きくなるので、画像の新しい高さがエディターの高さに合うようにズーム インされます。

図 11 写真の回転

Ff951239.516b9835-8b6f-4ca5-b2d0-e411e56cfc9e-thumb(ja-jp,MSDN.10).png

写真の詳細を確認したい場合は、さまざまな方法でズーム インまたはズーム アウトすることができます。1 つ目は Ctrl キーを押しながらマウスのホイールを使用する方法で、2 つ目は正符号と負符号のキーを使用する方法です。3 つ目は、図 12 のように、[View] タブの [Zoom In] ボタンと [Zoom Out] ボタンを使用する方法です。ズームを 100% に戻すには、Esc キーを押すか、[100%] ボタンをクリックします。

図 12 写真のズーム

Ff951239.cbeed7c5-a235-4938-b0e0-74cb2221f281-thumb(ja-jp,MSDN.10).png

Annotator を終了する際、行った変更は自動的に保存されますが、[Save] または [Save A Copy As] メニュー項目を使用すると、いつでも変更内容を保存できます。写真を保存すると、Annotator によって、AnnotatorBackup という名前のサブフォルダーに元の写真のバックアップ コピーが作成されます。

まとめ

Hilo Annotator は、Hilo アプリケーション スイートの 2 つ目のアプリケーションであり、さまざまな方法で写真を編集することができます。Annotator には、写真への書き込み、写真のトリミングや回転を行うためのツールが用意されており、これらのツールへのアクセスは Windows リボン コントロールのインスタンスによって提供されます。Windows リボン コントロールのプログラミングについては、このシリーズの次の章で説明します。

前へ | 次へ | ホーム