VC++でSWFファイルを再生したいです。

http://www.lab.its55.com/?p=60
この方法を参考にいろいろ試しているのですが、コンポーネントを追加する時点でエラーが出ます。
おそらく基本的なことが分かっていないと思いますので、手順を教えてください。
VC++2008ExpressEditionを使ってます。

回答の条件
  • 1人2回まで
  • 登録:
  • 終了:2009/03/25 03:17:07
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:cx20 No.1

回答回数607ベストアンサー獲得回数108

ポイント1000pt

途中目標として、なんでもいいからとりあえずSWF埋め込みをしたい

Windows アプリケーションに ActiveX コントロールを埋め込む方法は色々ありますが、基本的に以下のような図のイメージになります。

ActiveX の通信のイメージ

ActiveX
コントロール
コンテナ

メソッド、プロパティ
───────────→

ActiveX
コントロール

 
←───────────
イベント

Flash コントロールの例

Windows
アプリケーション

Play(メソッド)
Movie(プロパティ)
SetVariable(メソッド)
───────────→

Flash
コントロール

 
←───────────
FSCommand(イベント)
OnProgress(イベント)

コンテナとは、ActiveX コントロールを貼り付けられる側(入れ物)に相当します。

例えば、Word や Excel に ActiveX コントロールを貼り付ければ、Word や Excel がコンテナとなり、HTML に ActiveX コントロールに貼り付けて IE で表示させれば、IE がコンテナとなります。(コンテナのことを「ホストアプリケーション」や「COM クライアント」と呼ぶ場合もあります。)

コンテナから AxtiveX コントロールを操作する場合はメソッドやプロパティを呼び出します。逆に AxtiveX コントロールからコンテナにメッセージを送る場合はイベントを発生させます。


ここでは、VC++ 2008 Express Edition が標準でサポートしているアプリケーションのタイプである「CLR アプリケーション(Windows フォーム アプリケーション)」を例に説明します。

// 1. [ファイル] - [新規作成] - [プロジェクト] にてプロジェクトを新規作成します。
//   プロジェクトの種類:[Visual C++] - [CLR]
//   テンプレート:[Windows フォーム アプリケーション]
//   プロジェクト名:[FlashTest]
// 
// 2. [表示] - [ツールボックス] を選択し「ツールボックス」を表示させます。
// 
// 3. [ツールボックス] - [右クリック] - [アイテムを選択] を選択します。
//   → 「ツールボックス アイテムの選択」ダイアログが表示されます。
// 
// 4. 「ツールボックス アイテムの選択」ダイアログにて「Shockwave Flash Object」を選択します。
//   [COM コンポーネント] のタブに移動し「Shockwave Flash Object」にチェックを入れ [OK] ボタンを押下します。
//   → ツールボックスに「Shockwave Flash Object」が追加されます。
// 
// 5. ツールボックスから「Shockwave Flash Object」を選択しデザイナの画面のフォームに貼り付けます。
//   →「axShockwaveFlash1(※)」 という名称でフォームに貼り付けられます。
//   ※ 実際には ActiveX コントロールのラッパークラス(AxShockwaveFlash)が自動生成され、そのインスタンスとして貼り付けられます。
// 
// 6. 同様に、ツールボックスから「Button」を選択しフォームに貼り付けます。
//   →「button1」という名称でフォームに貼り付けられます。
//    
//    +------------------------------------+
//    |Form1                   [_][□][×]|
//    +------------------------------------+
//    |                                    |
//    |  +-------------------+             |
//    |  |                   |  +-------+  |
//    |  | axShockwaveFlash1 |  |button1|  |
//    |  |                   |  +-------+  |
//    |  +-------------------+             |
//    |                                    |
//    +------------------------------------+
// 
// 7. フォーム上の「button1」をダブルクリックし button1_Click() を実装します。
//   以下のコードを貼り付けます。
   
private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    // ActiveX コントロールの「プロパティ」をセットする
    axShockwaveFlash1->Movie = "http://www.adobe.com/jp/support/flash/ts/documents/images/jv05s01.swf";
    // ActiveX コントロールの「メソッド」を呼び出す
    axShockwaveFlash1->Play();
}

// 8. フォーム上の「axShockwaveFlash1」の「プロパティ」を開き「イベント」ボタンをクリックします。
//   「プロパティ」ウィンドウの上部に「イベント」というアイコン(稲妻マーク)があるのでクリックしてください。
//   → 実装可能なイベントの一覧が表示されます。
// 
// 9. イベントの一覧より「FSCommand」を選択し、右側の空白部分をダブルクリックします。
//   以下のコードを貼り付けます。

private: System::Void axShockwaveFlash1_FSCommand(System::Object^  sender, AxShockwaveFlashObjects::_IShockwaveFlashEvents_FSCommandEvent^  e) {
    // 受信したイベントの引数「command」の内容を取得します。
    String^ strCommand = e->command;
    // 受信したイベントの引数「args」の内容を取得します。
    String^ strArgs = e->args;
    String^ strMessage;
    strMessage = String::Format( "Command = [{0}], Args = [{1}]", strCommand, strArgs );
    // イベントの内容を画面に表示します。
    MessageBox::Show( strMessage, "FSCommand" );
}

他の言語環境でも基本的には上記の考え方となります。

ただ、開発環境や作成するアプリケーションのタイプによっては ActiveX コントロールのラッパークラスを生成してくれない場合があります。

そのような場合は、タイプライブラリを元に手動でラッパークラスを作成する必要があります(このあたりが、面倒なところですが・・・)

タイプライブラリとは COM オブジェクト(ActiveX コントロール等)の型情報を保持したファイルになります。

Flash コンポーネントの場合は、OCX ファイル(例:C:\Windows\System32\Macromed\Flash\Flash10b.ocx)に内包されています。

OCX ファイル内のタイプライブラリ情報は「OLE/COM オブジェクト ビューア」というツールで参照することができます。

ツールは Visual Studio や Windows SDK に付属していますが、下記より単体でダウンロードすることも可能です。

■ Download details: Windows 2000 Resource Kit Tool : OLE/COM Object Viewer (oleview.exe)
http://www.microsoft.com/downloads/details.aspx?familyid=5233b70...
  • id:cx20
    > VC++2008ExpressEditionを使ってます。
    1点、確認ですが、作成されているアプリケーションのタイプは以下のうちどれでしょうか?
    ・MFC アプリケーション
    ・Win32 アプリケーション
    ・CLR アプリケーション(Windows フォーム アプリケーション)

    > ■ its55 lab » WindowsアプリケーションのUIとしてFLASHを使う方法
    > http://www.lab.its55.com/?p=60

    上記サイトの方法は「MFC アプリケーション」での、Flash を使用する方法ですので、
    VC++ 2008 Express Edition では作成することができません。
    (MFC のライブラリやリソースエディタ等のツールが Express Edition には含まれていない為。)

    どうしても「MFC アプリケーション」で作成されたということでしたら、
    マイクロソフトのサイトにて、Visual Studio 2008 Pro の評価版がダウンロード可能ですので、
    こちらで試してみてください。

    ■ ダウンロードの詳細 : Visual Studio 2008 Professional (評価版)
    http://www.microsoft.com/DOWNLOADS/details.aspx?familyid=83C3A1EC-ED72-4A79-8961-25635DB0192B&displaylang=ja

    また、VC++ 2008 Express Edition で「Win32 アプリケーション」を作成する場合でしたら、
    WTL(Windows Template Library)というライブラリを使用することで
    クラスライブラリを利用した Windows アプリケーションの開発が可能です。

    以下は、WTL 環境での Flash コンポーネントの使用方法のサンプルになります。

    ■ タイプライブラリ情報のインポート
    http://home.att.ne.jp/banana/akatsuki/doc/atlwtl2/axhosting08/index.html

    「CLR アプリケーション」でしたら、Express Edition でも、追加ライブラリを使用することなく
    Flash コンポーネントを使用した開発が可能です。
  • id:yuugani
    丁寧なコメントありがとうございます。
    いろいろ自分なりに調べてみました。

    やりたいことをまとめると
    最終目標は、ゲームエンジンで作成されたWinアプリケーションのUIをFlashにしたい。
    http://tkool.jp/products/rpgvx/index.html
    仕様上ウインドウ生成時はたぶんいじれないので、アプリケーション起動後にエンジン付属スクリプト(Ruby)でWin32api.newを使って動的に?Activexコントロールを埋め込んでSwfを再生したい、ということになると思います。
    途中目標として、なんでもいいからとりあえずSWF埋め込みをしたい、と思い質問しました。

    現在はCで作ったDLL併せてウインドウ制御するところまでは自力で出来ました。

    これからのプランとしては、
    http://ilaliart.sourceforge.jp/tips/sdl_flash.html
    この方法を参考に、このWin32api版をDLLにするのが一番有望かと思っています。
    Flashとの通信方法の解説があまりなさそうなのが不安材料。

    他に
    2,RubyとFlashを通信する方法
    http://www.geocities.jp/stacorico/
    コレ単体でFlash再生は出来るが記述が高レベルなので既にあるウインドウhWndを引数にしてActivexコントロール埋め込めこんで操作可能なクラスのインスタンスにする方法?を調べるのに時間かかりそう。

    用語の使い方が変なところはあると思います。
    なにか今後の指針などありましたらアドバイスよろしくお願いします。
    コメント欄の分は後でポイント送信させていただきます。

  • id:cx20
    > 仕様上ウインドウ生成時はたぶんいじれないので、アプリケーション起動後に
    > エンジン付属スクリプト(Ruby)でWin32api.newを使って動的に?
    > Activexコントロールを埋め込んでSwfを再生したい

    イメージとしては以下のような感じでしょうか?

    [RPGツクール(画面)] <--> [Ruby(スクリプト)] <--> [DLL] <--> [Flash(画面)]

    DLL の作りにもよると思いますが、個人的には、EXE 化して独立させた方がよさそう(簡単そう)な気がします。

    [RPGツクール(画面)] <--> [Ruby(スクリプト)] <--> [Windows アプリケーション(画面)]

    それと、

    ■ SDL_mixerでMix_OpenMUS_RWを利用する方法
    http://ilaliart.sourceforge.jp/tips/sdl_flash.html

    のサンプルコードですが、ATL を使用しているようです。

    > #include <atlbase.h>

    残念ながら Express Edition には、ATL や MFC のような
    ネイティブ Windows アプリケーション開発用のライブラリは含まれていませんので、
    (Express Edition 自体が、.NET アプリケーションの開発用のツールである為)
    そのままではコードは使用できません。

    ただ、実際には ATL の機能というより、A2W マクロ(ANSI → UNICODE 変換)の為に使用しているだけのようなので、
    代替手段(_bstr_t 等)を用いて回避することは可能そうですが・・・。

    また、古いバージョンの Platform SDK をインストールすることで、ATL の古いバージョンを入手することは可能なようです。

    ■ Download details: Windows Server 2003 R2 Platform SDK ISO Download
    http://www.microsoft.com/downloads/details.aspx?FamilyId=E15438AC-60BE-41BD-AA14-7F1E0F19CA0D&displaylang=en
  • id:yuugani
    ありがとうございます。質問締め切っておきました。
    まず、CLRアプリケーションの方法で再生は成功しました。

    >個人的には、EXE 化して独立させた方がよさそう
    その通りなんでしょうし、むしろ自分でC#で作った方が早いとは思うんですが、グラフィック素材の規約で制限があるので、今の方法で考えています。

    そして、当初の予定通りWin32api版のサンプルコードをDLL化してゲームウインドウ本体でのSWF再生までは行きました。
    問題は予想通りCとFlashの通信で実装資料が無いということで、
    相当検索しましたが解説はJavascriptとC#ばかりで、英語でも使えるコードは存在しないんじゃないかと思ってるところです。
    まぁこれも基本的な知識がないのが原因なわけですが、、、

    >>
    private: System::Void axShockwaveFlash1_FSCommand(System::Object^ sender, AxShockwaveFlashObjects::_IShockwaveFlashEvents_FSCommandEvent^ e)
    }
    >>
    この部分をどう改変すればFSCommand受け取れるようになるのでしょうか?
    もし良ければ、教えていただけると助かります。
  • id:cx20
    > この部分をどう改変すればFSCommand受け取れるようになるのでしょうか?

    ATL や MFC を使わないで COM イベントを取得するには自前で Event Sink を実装する必要があります。
    「IConnectionPointContainer」「Event Sink」等をキーワードに検索してみてください。

    ちなみに、以下のサイトが参考になりそうです。

    ■ 旧 Life is Real.(~2008年) : COMサーバーへのイベントハンドラ登録
    http://fiber.exblog.jp/10448444/

    上記のサイトの説明は、IE のコンポーネントでの例ですが、基本的には Flash の場合でも同様です。
    以下、簡単に書き換えるポイントについて記述します(検証していないのでそのままでは動かない可能性があります。)

    <手順>
    1. #import ディレクティブにより Flash のタイプライブラリのラッパークラスを生成します。

    #import "C:\Windows\System32\Macromed\Flash\Flash10b.ocx"

    2. イベント受信用のクラスを用意します。

    class CEventSink : public _IShockwaveFlashEvents
    {
    HRESULT STDMETHODCALLTYPE OnReadyStateChange ( long newState );
    HRESULT STDMETHODCALLTYPE OnProgress ( long percentDone );
    HRESULT STDMETHODCALLTYPE FSCommand ( _bstr_t command, _bstr_t args );
    };

    3. CEventSink::FSCommand() を実装します。

    CEventSink::FSCommand ( _bstr_t command, _bstr_t args )

    4. コンポーネントに接続します。

    IShockwaveFlash* pFlash
    IConnectionPointContainer *pCPC;
    IConnectionPoint *pCP;

    hr = pFlash->QueryInterface(IID_IConnectionPointContainer,(void**)&pCPC);
    hr = pCPC->FindConnectionPoint(ShockwaveFlashObjects::DIID__IShockwaveFlashEvents, &pCP);

    5. イベントに接続します。

    DWORD dwCookie = 0L;
    IUnknown *pUnk = NULL;
    CEventSink *pES = new CEventSink();
    pES->QueryInterface(IID_IUnknown,reinterpret_cast<LPVOID*>(&pUnk));
    pCP->Advise(pUnk,&dwCookie);

    <参考情報>
    ■ WIN32でOCXを利用する方法を教えて下さい! - 教えて!goo
    http://oshiete1.goo.ne.jp/qa834419.html
    ■ COMのイベントをVC++で受け取る方法
    http://hpcgi1.nifty.com/MADIA/Vcbbs/wwwlng.cgi?print+200705/07050016.txt
    ■ CodeProject: Transparent Flash Control in plain C++. Free source code and programming help
    http://www.codeproject.com/KB/COM/flashcontrol.aspx
    ■ Visual C++ を使用した Office オートメーション
    http://support.microsoft.com/kb/196776/ja

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません