Mouse Image

Mouse Image

Windows10 で Mouse と連動して Image を動かします。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. 今回のプロジェクトは Windows8 を Windows8.1 に再ターゲットしたものを Windows10 & Visual Studio Community 2015 の環境で動かします。
    C++ や DirectX では Windows8 のプロジェクトは動かなかったのですが、幸いにして Direct2D tutorial は動くようです。
    そこで Lesson1 Image をベースにして Mouse と連動して Image を動かすプロジェクトをステップアップで開発します。
    PointerEvent 関係の API は仕様が固まっておらず、バージョンが変わると動かなくなるかも知れません。
  2. Step1 Windows8 のプロジェクトを Windows8.1 に再ターゲットします。
    1. Lesson1.DrawImage のプロジェクトから Lesson1.DrawImage.sln をダブルクリックで起動します。
      次のメッセージが表示されます。
      Windows8 プロジェクトは Windows8.1 に再ターゲットが必要です。
      
    2. ソリューションエクスプローラから[プロジェクト名(Windows8.1 に再ターゲットが必要)]を右クリックして実行します。
      Windows8.1 に再ターゲットされます。
    3. 一般のプロジェクトはコンパイルエラーが表示されて動きませんが Direct2D tutorial は動くようです。
      メニューから[ビルド/ソリューションのビルド]を実行してから、緑色の右三角アイコンをクリックして下さい。
      "mammoth.jpg" の画像が描画されます。
    4. 画像を L"mammoth.jpg" から L"Enemi1.gif" に変更します。
      リビルドして Enemi1.gif が左上に小さく描画されるのを確認して下さい。
    5. 修正するファイルは PhotoRenderer.cpp(.h) です。
  3. Step2 ビルドで表示される警告を無くします。
    1. Windows8 のプロジェクトは、仕様が古くなって使われなくなった非推薦のソースコードが使われています。
      まず最初に [DisplayProperties::LogicalDpi] に警告が出ます。
      この値を OutputDebugString() などで確認して、定数に置き換えます。
      私の場合は 172.8f なので [DisplayProperties::LogicalDpi] を [172.8f] に置き換えました。
    2. 次に DisplayProperties:: に警告が出ます。
      デスクトップの環境では無くても支障が無いようなので削除して下さい。
          /*
          DisplayProperties::LogicalDpiChanged +=
              ref new DisplayPropertiesEventHandler(
                  this, &PhotoRenderer::OnLogicalDpiChanged);
          DisplayProperties::DisplayContentsInvalidated +=
              ref new DisplayPropertiesEventHandler(
                  this, &PhotoRenderer::OnDisplayContentsInvalidated);
          */
      
      /*
      void PhotoRenderer::OnLogicalDpiChanged(
          _In_ Platform::Object^ sender
          )
      {
          SetDpi(DisplayProperties::LogicalDpi);
          Render();
      }
      
      void PhotoRenderer::OnDisplayContentsInvalidated(
          _In_ Platform::Object^ sender
          )
      {
          // Ensure the D3D Device is available for rendering.
          ValidateDevice();
      
          Render();
      }
      */
      
    3. PhotoRenderer.h から関数の宣言も削除します。
        OnLogicalDpiChanged
        OnDisplayContentsInvalidated
      
      これで警告が消えてすっきりします。
  4. Step3 マウスの移動を検出します。
    1. SetWindow() 関数に PointerMoved EventHandler を設定します。
          window->PointerMoved +=
              ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(
                  this, &PhotoRenderer::OnPointerMoved);
      
    2. OnPointerMoved() ではマウスの移動を検出して出力ウインドウに印字します。
      void PhotoRenderer::OnPointerMoved(CoreWindow^ window, PointerEventArgs^ args)
      {   Windows::UI::Input::PointerPoint^ point = args->CurrentPoint;
          Point pos = point->Position;
          m_pos.x = pos.X;
          m_pos.y = pos.Y;
          wchar_t str[80];
          swprintf(str, 80, L"Posion x:%f  Posion y:%f\n\n", m_pos.x, m_pos.y);
          OutputDebugString(str);
      }
      
    3. Constructor で m_pos を初期化します。
      PhotoRenderer::PhotoRenderer() :
          // Initialize defaults for the transformation variables.
          m_pos()
      
    4. PhotoRenderer.h で OnPointerMoved() を宣言して、m_pos を定義します。
          void OnPointerMoved(
              _In_ Windows::UI::Core::CoreWindow^ window,
              _In_ Windows::UI::Core::PointerEventArgs^ args
              );
      
          D2D1_POINT_2F       m_pos;
      
    5. マウスを移動すると、出力ウインドウに座標が印字されます。
  5. Step4 マウスの座標に画像を描画します。
    1. Render() では m_pos の座標に Image を描画します。
      void PhotoRenderer::Render()
      {   m_d2dContext->BeginDraw();
      
          m_d2dContext->DrawImage(
              m_bitmapSourceEffect.Get(), m_pos,
              D2D1_INTERPOLATION_MODE_LINEAR,
              D2D1_COMPOSITE_MODE_SOURCE_COPY );
      
          HRESULT hr = m_d2dContext->EndDraw();
          if (hr != D2DERR_RECREATE_TARGET)
          {   DX::ThrowIfFailed(hr);  }
      
          m_sampleOverlay->Render();
          Present();
      }
      
    2. Run() 関数でメッセージループを組み込みます。
      m_isWindowClosed はウインドウが閉じられたフラグです。
      void PhotoRenderer::Run()
      {   Render();
          while (!m_isWindowClosed)
          {   m_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
              Render();
          }
      }
      
    3. Constructor で m_isWindowClosed を初期化します。
      PhotoRenderer::PhotoRenderer() :
          // Initialize defaults for the transformation variables.
          m_isWindowClosed(false),
          m_pos()
      
    4. SetWindow() 関数に OnWindowClosed の EventHandler を設定します。
          window->Closed +=
              ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>
                  (this, &PhotoRenderer::OnWindowClosed);
      
    5. OnWindowClosed() では、ウインドウが閉じられると m_isWindowClosed に true を設定します。
      void PhotoRenderer::OnWindowClosed(
          _In_ CoreWindow^ window,
          _In_ CoreWindowEventArgs^ args
          )
      {   m_isWindowClosed = true;  }
      
    6. PhotoRenderer.h に OnWindowClosed と m_isWindowClosed を定義します。
          void OnWindowClosed(
              _In_ Windows::UI::Core::CoreWindow^ window,
              _In_ Windows::UI::Core::CoreWindowEventArgs^ args
              );
          bool        m_isWindowClosed;
      
    7. これでマウスの動きに従って Image が動くようになります。
  6. Mouse(PointerEvent) の基礎は C++ のページから Win10 Mouse を参照して下さい。
    Windows10 Direct3D の Mouse(PointerEvent) は Win10 MouseMove を参照して下さい。
    Lesson2 PanZoom は PointerEvent を使ったより高度なプロジェクトです。
    リンク出来ない時は私のトップページからたどって下さい。

超初心者のプログラム入門(DirectX Store)