Lesson2

Lesson2 PanZoom

マウスで画像を拡大/縮小/描画範囲を操作します。

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

プログラムの説明

  1. フォルダには Lesson1 ~ Lesson5 の5本のプロジェクトが格納されています。
    PhotoAdjustment.sln から起動して、Lesson2.PanZoom を右クリックします。
    メニューから「スタートアップ プロジェクトに設定」を選びます。
    そのまま右三角アイコンでコンパイル&実行して下さい。
    大きな画像がウインドウサイズに合わせて、縮小して描画されています。
    マウスの中ボタンを回転すると画像が拡大します。
    マウスのドラッグで描画範囲を操作することが出来ます。
  2. PhotoRenderer.cpp をダブルクリックして、ソースコードを表示して下さい。
    PhotoRenderer の Constructor からメンバーオブジェクトの Constructor を呼び出しています。
    これを見れば、処理内容の「おおよその見当」が付くのではないでしょうか。
    PhotoRenderer::PhotoRenderer() :
        m_viewPosition(),
        m_zoom(1.0f),
        m_minZoom(1.0f), // Min zoom is dynamically calculated
        m_bitmapPixelSize(),
        m_imageSize(),
        m_contextSize(),
        m_isWindowClosed(false),
        m_renderingMode(RenderingMode::WaitForEvents),
        m_recenterStartZoom(),
        m_recenterStartPosition()
    {
        m_timer = ref new BasicTimer();
    }
    
    ちなみに、Lesson1 では何も記述されていません。
    PhotoRenderer::PhotoRenderer()
    {
    }
    
  3. Run() メソッドには、レンダリングループが設定されています。
    void PhotoRenderer::Run()
    {
        Render();
    
        while (!m_isWindowClosed)
        {
            switch (m_renderingMode)
            {
                case RenderingMode::WaitForEvents:
                    m_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
                    break;
    
                case RenderingMode::RunRecenterAnimation:
                    m_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
                    UpdateRecenterAnimation();
                    Render();
                    break;
            }
        }
    }
    
  4. Run() メソッドで使われている m_window は DirectXBase.h で宣言されています。
    DirectXBase.cpp で m_window に CoreWindow がセットされています。
        Platform::Agile  m_window;
    
    void DirectXBase::Initialize(CoreWindow^ window, float dpi)
    {
        m_window = window;
    
        CreateDeviceIndependentResources();
        CreateDeviceResources();
        SetDpi(dpi);
    }
    
  5. UpdateRecenterAnimation() メソッドです。
    m_viewPosition が画像の左上座標で、m_zoom が画像の大きさのようです。
    void PhotoRenderer::UpdateRecenterAnimation()
    {
        m_timer->Update();
        float delta = m_timer->Total / sc_recenterAnimationDuration;
        delta = Clamp(delta, 0.0f, 1.0f);
    
        m_viewPosition.x = LinearInterpolate(m_recenterStartPosition.x, 0, delta);
        m_viewPosition.y = LinearInterpolate(m_recenterStartPosition.y, 0, delta);
        m_zoom = LinearInterpolate(m_recenterStartZoom, m_minZoom, delta);
    
        ClampViewPosition(&m_viewPosition, m_contextSize, m_imageSize, m_zoom);
    
        UpdatePanZoomEffectValues();
    
        if (delta >= 1.0f)
        {
            m_renderingMode = RenderingMode::WaitForEvents;
        }
    }
    
  6. Image を描画する Render() メソッドです。
    void PhotoRenderer::Render()
    {
        m_d2dContext->BeginDraw();
    
        m_d2dContext->DrawImage(
            m_2dTransformEffect.Get(),
            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();
    }
    

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