« 復活のいせや本店(仮) | トップページ | かけこみ乗車はキケンです! »

2006年10月 9日 (月)

なんとなくMCIウインドウ

昔、ウインドウズプログラミングを始めた頃
マルチメディア関連の処理を検討した時に
MCIだけでプレイヤーが作れるかなとやってみたが
上手くいかなかった…。

MCIWndCreate(NULL,hInstance,MCIWNDF_SHOWALL,NULL)
で、「NULL」にするとMCIが自前でウインドウを作成する。
そのメニューも実際に動作するのだが…。
ファイルをロードする項目が動作しない。
当時、動作させる方法が分からなかった。

最近そのコードを発掘したので再度挑戦!

で、ボケ的には、満足できる出来になった。

チョットは、進歩した俺を確認。
チョット嬉しい。
で、チョット公開。

MCIは、たったこれだけでマルチメディアが
再生できる便利なルーチンなのだ。
手軽に再生するのなら結構使えると思うのだが…。

VC++6のWin32アプリケーションで作成。

//------------------------------------------------------------------------------
//    MCIウインドウのもっとも簡単な使い方
//------------------------------------------------------------------------------
#pragma comment(lib,"vfw32.lib")
//--------------------------------------
#include<windows.h>
#include<vfw.h>
//--------------------------------------
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)
{
    MSG msg={0,};
    HWND hWnd=NULL;
    LPSTR FileName="Test.avi";
//    HWND OwnerWnd=NULL;// MCIウインドウを作成。
    HWND OwnerWnd=GetDesktopWindow();// ディスクトップに映像を貼り付けます。
    if((hWnd=MCIWndCreate(OwnerWnd,hInstance,MCIWNDF_NOMENU|MCIWNDF_NOPLAYBAR|MCIWNDF_SHOWNAME|MCIWNDF_NOTIFYALL|0,FileName))!=NULL){
        if(OwnerWnd!=NULL){
            // ディストップなら大きさに合わせます。
            RECT OwnerRect,Rect;
            int Zoom;
            GetClientRect(OwnerWnd,&OwnerRect);
            MCIWndGetSource(hWnd,&Rect);
            Zoom=OwnerRect.right*100/Rect.right;
            MCIWndSetZoom(hWnd,Zoom);
            SetWindowPos(hWnd,0,0,(OwnerRect.bottom-Rect.bottom*Zoom/100)/2,0,0,SWP_NOSIZE|SWP_NOZORDER);
        }
        MCIWndPlay(hWnd);
        while(IsWindow(hWnd)&&(GetMessage(&msg,NULL,0,0)>0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
            // メディアの停止を検出します。
            // 「MCIWNDF_NOTIFYALL」を指定すると「WM_TIMER」が
            // 実行されるので定期的にチェック可能になります。
            if(MCIWndGetMode(hWnd,NULL,0)==MCI_MODE_STOP)
                break;
        }
    }
    MCIWndStop(hWnd);
    MCIWndClose(hWnd);
    MCIWndDestroy(hWnd);
    return msg.wParam;
}
//------------------------------------------------------------------------------

で、こちらが本命。

//------------------------------------------------------------------------------
//    MCIウインドウを利用したムービー&サウンドプレイヤー
//------------------------------------------------------------------------------
#pragma comment(lib,"vfw32.lib")
//--------------------------------------
#include<windows.h>
#include<vfw.h>
//--------------------------------------
LRESULT (CALLBACK*OriginalMicWndProc)(HWND,UINT,WPARAM,LPARAM);
char Directory[MAX_PATH];
//------------------------------------------------------------------------------
LRESULT CALLBACK MicWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
    switch(uMsg)
    {
    case WM_COMMAND:
        // 開く
        if(wParam==0x68){
            char FileName[MAX_PATH];
            OPENFILENAME OpenFileName;

            *FileName=0;
            ZeroMemory(&OpenFileName,sizeof(OpenFileName));
            OpenFileName.lStructSize=sizeof(OpenFileName);
            OpenFileName.hwndOwner=hWnd;
            OpenFileName.lpstrFilter="マルチメディア(*.avi;*.wav;*.aif;*.mid;*.mp3)\0*.avi;*.wav;*.aif;*.mid;*.mp3\0";
            OpenFileName.lpstrFile=FileName;
            OpenFileName.nMaxFile=MAX_PATH;
            OpenFileName.lpstrInitialDir=Directory;
            OpenFileName.Flags=OFN_HIDEREADONLY|OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;
            if(!GetOpenFileName(&OpenFileName))
                return 0;

            // ディレクトリの更新
            strcpy(Directory,FileName);

            // MCIへ登録し再生します。
            MCIWndClose(hWnd);
            if(MCIWndOpen(hWnd,FileName,0)==0)
                MCIWndPlay(hWnd);
            return 0;
        }
        break;

    case WM_INITMENU:
        // 正しく処理されないメニュー項目
        // 「構成(0x6E)」と「コマンド(0x6F)」を削除します。
        {
            HMENU Menu=(HMENU)wParam;
            DeleteMenu(Menu,0x6E,MF_BYCOMMAND);
            DeleteMenu(Menu,0x6F,MF_BYCOMMAND);
        }
        break;

    case WM_CLOSE:
        // ムービーの再生中にウインドウを閉じると
        // 別のウインドウフレームが左上に表示されます。
        // ここで、停止しする事で表示されなくなります。
        MCIWndStop(hWnd);
        MCIWndClose(hWnd);
        break;
    }
    return CallWindowProc(OriginalMicWndProc,hWnd,uMsg,wParam,lParam);
}
//--------------------------------------
// 使用しない引数名を削除したのはレベル4のエラーチェックに対応するため。
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE,LPSTR,int)
{
    MSG msg={0,};
    HWND hWnd=NULL;

    if(GetCurrentDirectory(MAX_PATH,Directory)==0)
        goto EXIT;

    // MCIバージョンを調べます。
    if(HIWORD(VideoForWindowsVersion())<ICVERSION)
        goto EXIT;

    // MCIウインドウを作成します。
    if((hWnd=MCIWndCreate(NULL,hInstance,MCIWNDF_SHOWALL,NULL))==NULL)
        goto EXIT;

    // プロシージャを差し替えます。
    // ファイルのロード部分のみ実装されていません。
    // サブクラス化しロード等の処理を追加します。
     OriginalMicWndProc=(WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC);
    SetWindowLong(hWnd,GWL_WNDPROC,(DWORD)MicWndProc);

    // 「TranslateMessage/DispatchMessage」の
    // 後でないと「IsWindow」は、正常に動作しません。
    // 「while((GetMessage(&msg,NULL,0,0) > 0) && IsWindow(hWnd))」
    // では、希望した通りに動作しません。
    while(IsWindow(hWnd)&&(GetMessage(&msg,NULL,0,0)>0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;

    // エラー時の処理
    EXIT:
    MessageBox(hWnd,"エラーが発生しました。\n強制的に終了します。","MCI Window - ERROR",MB_OK|MB_ICONSTOP);
    MCIWndClose(hWnd);
    MCIWndDestroy(hWnd);
    return 0;
}
//------------------------------------------------------------------------------

何で、こんなのを公開したかと言うと…
無かったから。

自分と同じ所で詰まっている人が居るかもしれない!
…居ないかもしれない。

まあ、ボケもいろいろ貰っているので
たまには、還元。

でな所。

|

« 復活のいせや本店(仮) | トップページ | かけこみ乗車はキケンです! »

コメント

コメントどうも♪
ちょっと還元されたのを確認できたので
ちょっと幸せ♪
アリガトね♪

投稿: kouyou | 2007年10月23日 (火) 23時45分

WinMainでMCIウインドウを作成する方法をずっと探してた。
参考になったよ。
このブログ内容がね。
ありがとう。

投稿: MCI初心者 | 2007年10月23日 (火) 06時55分

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: なんとなくMCIウインドウ:

« 復活のいせや本店(仮) | トップページ | かけこみ乗車はキケンです! »