4.スライドショーを作ろう!!



 相変らず更新の遅いページですが、細かいことは気にしないで行きましょう。更新が遅いことが細かいことかどうかは問題ですが・・・
 さて、前回のプログラムではリソースファイルを手書きで書いていました。VCでは強力なリソースエディタがついています。それを使って、前回のプログラムを少し改良しましょう。


 先ずは[ファイル→新規作成]より、空のワークスペースを作り、前回作ったdx03.cppをワークスペースに追加しましょう。その際、区別をつけるためにファイル名はdx04.cppにしてくれると嬉しいんですが、其の辺の細かいことは皆さんにお任せします。勝手にやれ。(暴言)
 ごほっ、ごほっ、大変失礼しました。さて、リソースの続きを作りましょう。[挿入→リソース]または、[Ctrl + R]を押してリソースの選択画面を出してください。下のような画面が出ましたか?


 先ずは前回とほぼ同じ物を作りましょう。リソース選択から[Menu]を選び、新規作成してください。メニューバーに何も入ってないものが出ましたか?メニューバーはこの状態から作っていきます。

 メニューバーに本来文字が入っているところが、黒い点線で囲まれています。ここをダブルクリックすると、「メニューアイテムプロパテ」なる物が表示されます。まずは、メニューバーの[ファイル]を作るので、「キャプション」の欄に、以下の文章を書き込んでみて下さい。

   ファイル(&F) 

 これでOKです。後は、VCが自動でやってくれます。いつも使用者にヒーヒー言わせてるんだから、これぐらいVCがやってくれないとコッチとしてはやってられるかってんだよ!!こん畜生があ!!!
 げほっ、げほっ、失礼しました・・・。余計なことは抜きにして、さっさと先に進みましょう。[ファイル]の作製が出来たら、[ファイル]の下に、新たな黒い点線で囲まれた部分が出来ます。それでは、先程と同様の操作を行います。キャプションの欄に、以下の文章をコピー&ペースト又は手で書き込んでください。モニターに鉛筆で書き込んだ人は・・・そんな奴いるか!!

   終了(&X) 

これでメニューバーが完成しました。完成結果はだいたい下のような画面になっている筈ですが。



 それでは、[Ctrl + S]を押してリソースファイルを保存してください。保存したリソースファイルと[resource.h]をプロジェクトに追加して下さい。リソースファイルを作ると、VCは自動的にヘッダファイルを作ってくれるんですね〜。こういう時だけ、「VCすげー!!」って思うのは、私だけでしょうか。
 前回のプログラムと[resource.h]の内容が違うので、メッセージループを書き換えなければいけません。具体的には、前回「IDR_EXIT」としていた部分を「IDR_MENUITEM40002」に書き換えます。リソースをVCが自動的に作ると、それに合わせて自分で作ったソースファイルを書き直さなければならないんです。うーん、便利なのか、不便なのか・・・


 さて、ここからが本番です。今回のタイトルは、「スライドショーを作ろう!!」なのです。今回作るアプリケーションの主な使用は、次のようになります。

  ・640x480のフルスクリーン表示
  ・表示させるファイルは[sample01.bmp]〜[sample04.bmp]の4つのみ


・・・とまあ、簡単なものですが、ここで聡明な皆さんなら気づいたことがあると思います。そう、「フルスクリーン表示だとメニューバーが表示されない」のです!!なんとまあ、先程作ったリソースファイルが全くの無駄になってしまいました。あらあら・・・


 仕方ないので、先程作ったリソースファイルは破棄してしまいましょう。まあ、こういう物でも作っておけば後で役に立つはずです。多分。言い訳だけど。
 ということで、このままではスライドの切り替えが出来ません。ここは一つ、キーボードで制御するようにしましょう。その結果、先程の使用に次のものを加えることが決定しました。

  ・矢印キーの右を押すと次のスライド、左を押すと前のスライドに移る
  ・Escキーでプログラム終了


 主な使用が決まったので、それでは早速プログラムの作成に入ろうと思います。先ずはフルスクリーンの制御から。

名は[bitmap_surface]とでもしておきましょう。下にプログラムの詳細を表示します。

    HRESULT         ddrval;

    //協調レベルを設定
    ddrval = lpDD->SetCooperativeLevel (hWnd , DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
    if (ddrval != DD_OK){
        ErrStr = Err_Coop;
        return FALSE;
    }

    //ディスプレイモードを設定
    ddrval = lpDD->SetDisplayMode (640 , 480 , 16 , 0 , 0);
    if (ddrval != DD_OK){
        ErrStr = Err_DispMode;
        return FALSE;
    }

 こんな感じですか。下のSetDisplayModeで、ディスプレイの解像度を640x480x16bitに変更しています。あ、これは前回作製したウィンドウ作成用Init関数内の記述です。これの実行前に、ウィンドウの作製とDirectDrawオブジェクトの作成を行っていますので、詳しくはソースファイルのほうを見てください。


 次に、スライド表示の部分を作ります。そこで、前回と同様サーフェスを用いるんですが、これが少々面倒です。画像を複数呼び出すため、サーフェスが1つだと画面のリフレッシュに対して画像データ読み込みが間に合わない可能性があります。これを解決するために、プライマリサーフェスの他にビデオメモリ内にバックバッファとして2つ目のサーフェスを用意します。そのバックバッファのサーフェス内に次の画像を読み込んでおきます。画面のリフレッシュ中に2つのサーフェスをスワップすることで、画面のちらつきを抑えることが出来ます。この手法をダブルバッファリング、サーフェスの集合のことをフリッピングチェーンと呼びます。
 さて、用語の説明が済んだところで、早速プログラムの説明です。次のプログラムは、Init関数内に、上のディスプレイモード設定の部分を書いたあとに書き加えます。

    //バックバッファを1個持つプライマリサーフェスを作成
    DDSURFACEDESC2 ddsd;
    DDSCAPS2 ddscaps;
    ZeroMemory (&ddsd , sizeof (ddsd) );
    ddsd.dwSize = sizeof (ddsd);
    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
    ddsd.dwBackBufferCount = 1;
    ddrval = lpDD->CreateSurface (&ddsd , &lpDDSPrimary , NULL);
    if (ddrval != DD_OK){
        ErrStr = Err_CreateSurf;
        return FALSE;
    }

    //バックバッファインターフェースを取得
    ZeroMemory (&ddscaps , sizeof ( ddscaps ) );
    ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
    ddrval = lpDDSPrimary -> GetAttachedSurface (&ddscaps , &lpDDSBack);
    if (ddrval != DD_OK){
        ErrStr = Err_CreateSurf;
        return FALSE;
    }

 ここでは、バックバッファが1つのため、"ddsd.dwBackBufferCount = 1"に設定されています。また、"GetAttachedSurface ( )"で、バックバッファへのポインタが指定されています。
 実際にバックバッファとプライマリサーフェスの交換は、次に示す"Flip ( )"で行います。これは、スライド描画関数のほうに書くものです。先程と同様にInit関数のほうに書かないように気をつけてください。

    //オブジェクトを画面に描画
    lpDDSBack->BltFast (0 , 0 , lpSlides[cur_image] , NULL , DDBLTFAST_WAIT);

    //プライマリサーフェスにフリップ
    lpDDSPrimary->Flip (0 , DDFLIP_WAIT);

 注意して欲しいのは、最初にデータを転送するのはプライマリサーフェスではなくバックバッファだということです。フリップは次のリフレッシュを待って実行されます。


 さて、最後にキー入力によるスライド制御ですが、WM_KEYDOWNメッセージを使います。面倒なので、WindowProcを全部載せちゃいます。ちょっと見難いのは、我慢してください。

//--------------------メッセージループの組み立て--------------------//
LRESULT CALLBACK
WindowProc (HWND hWnd , unsigned uMsg , WPARAM wParam , LPARAM lParam)
{
    switch (uMsg){
        case WM_DESTROY:        //DDrawサーフェスとインターフェイスの解放
            Cleanup ( );
            PostQuitMessage (0);
            break;
        case WM_KEYDOWN:
            switch (wParam){
                case VK_ESCAPE:     //Escキーでプログラム[終了]
                    DestroyWindow (hWnd);
                    break;
                case VK_RIGHT:      //右向き矢印キーで[次のスライド]
                    cur_image++;
                    if (cur_image > IMAGE_COUNT - 1)
                        cur_image = 0;
                    DrawSlide ( );
                    break;
                case VK_LEFT:       //左向き矢印キーで[前のスライド]
                    cur_image--;
                    if (cur_image < 0)
                        cur_image = IMAGE_COUNT - 1;
                    DrawSlide ( );
                    break;
                default:            //文字以外のその他のキーを押した場合
                    break;
            }
        default:
            return DefWindowProc (hWnd , uMsg , wParam , lParam);
    }
    return 0;
}

 以上で主な変更は終了です。その他の部分は前回作成したプログラムを流用しているので、実際にそれほど多くの手間はかかっていないと思います。
 その他に、クリーンアップ関数も少し変更が加えられているんですが、ここでは割愛します。取りあえず、サーフェスとインターフェイスを"Release ( )"によって解放すれば終了です。主な変更点は、ソースファイルのほうを参考に。


 それでは早速実行してみましょう。気になる画像の内容は・・・



 最後の一つは、プログラムを実行して自分で確認してください。くすくすっ。


まとめ
・リソースエディタを使いこなす
・複数の画像を使うプログラムには、ダブルバッファリングを使う
・フルスクリーンだとメニューバーが見えない(反省)

ファイル
dx04.lzh
 ├ readme.txt
 ├ dx04.cpp
 ├ slide01.bmp
 ├ slide02.bmp
 ├ slide03.bmp
 └ slide04.bmp
dx04_exe.lzh
 ├ readme.txt
 ├ dx04.exe
 ├ slide01.bmp
 ├ slide02.bmp
 ├ slide03.bmp
 └ slide04.bmp


電脳館
written by みや
First Write : 2001.03.06
Last Update : 2001.03.08



戻る


Gポイントポイ活 Amazon Yahoo 楽天

無料ホームページ 楽天モバイル[UNLIMITが今なら1円] 海外格安航空券 海外旅行保険が無料!