3

この記事にも同じ問題があると思います。しかし、私の場合、実行可能な解決策はありません。

プログラムでWindowsMediaPlayerActiveXを使用しています。

何らかの理由で、その参照を追加して、IDEによって自動的にAxHostに変換したくありません。

Activatorとによってインスタンスを作成しますProgID

protected const string WMP_PROG_ID = "WMPlayer.OCX.7";

private dynamic _wmp;

protected virtual bool init(){
    try{
        _wmp = Activator.CreateInstance(Type.GetTypeFromProgID(WMP_PROG_ID));
    }
    catch{ return false; }
    return true;
}

私はこれをしようとしましたが、それが私の場合に適しているReflectionことがわかりました。dynamic

次のように、すべてのプロパティとメソッドは正常に機能します。

protected override bool setSpeed(float speed){
    try{
        _wmp.settings.rate = speed;
    }
    catch { return false; }
    return true;
}

protected override int getLength(){
    double res;
    try{
        res = _wmp.currentMedia.duration;
    }
    catch { return 0; }
    return (int)(res * 1000);
}

残念ながら、上に示した記事のようなイベントを添付したいのですが、うまくいきませんでした。

このような私のコード:

protected bool connectEvent(){
_wmp.StatusChange += new EventHandler(_wmp_StatusChange);
    return true;
}

protected void _wmp_StatusChange(object sender, EventArgs e){
    Console.WriteLine(_wmp.Status);
}

のイベントハンドラーのタイプを確認しました。StatusChangeそれはEventHandlerです。

これらのコードはうまくコンパイルされており、音楽をロードしたり、再生したり、一時停止したり、...好きなことをすることができます。

しかし、StatusChangeイベントはトリガーされませんでした。

ブレークポイントをに設定しようとしましたconnectEvent

で実行する_wmp.StatusChange += new EventHandler(...)と、IntelliTraceからいくつかの情報が得られます。

それらの情報はTradで書かれていました。中国語、私はそれが意味すると思います:

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:演算子「+=」をタイプSystem.Dynamic.DynamicObjectとに適用できませんでしたSystem.EventHandler

例外はありますが、私が言ったように、コンパイルは渡されましたが、イベントをリッスンできなかったことを除いて、すべてが引き続き機能します。

では、どうすれば動的オブジェクトにイベントを正常にアタッチできます_wmpか?

(のような)可能な解決策Reflectionは私にとって有用です。

また、上記の場合、のハンドラタイプはStatusChangeですEventHandler

しかし、イベントを処理したい場合PlayStateChange、wmp.dllの参照を追加しないと、「不明なハンドル」になります。

このソリューションがこの場合にも適していることを願っています。

皆様のご支援に心より感謝申し上げますとともに、英語力の低さをお許しください。

4

1 に答える 1

1

COMオブジェクトを使用するプログラムをアーリーバウンドからレイトバウンドの呼び出しに変える一般的な戦略は、最初にアーリーバウンドでプログラムを作成することです。IntelliSenseは、成功の落とし穴に陥るのに役立ち、正しい名前のメソッドを使用し、正しい種類の引数を渡すことを保証し、イベントハンドラーのシグネチャがどのように見えるかを見つけるのに特に役立ちます。

これにより、次のテストコードが生成されます。

    void testEarlyBound() {
        var wmp = new WMPLib.WindowsMediaPlayer();
        wmp.StatusChange += new WMPLib._WMPOCXEvents_StatusChangeEventHandler(wmp_StatusChange);
    }

    void wmp_StatusChange() {
        throw new NotImplementedException();
    }

StatusChangeイベントハンドラーの割り当てとメソッド本体を使用して、IntelliSenseによって完全に自動生成されます。イベントハンドラの署名に注意してください。これはEventHandlerではありません。voidを返し、引数をとらないメソッドであり、Actionデリゲートタイプと一致します。これで、診断できないランタイム例外なしで、レイトバウンドバージョンを作成することができます。

    void testLateBound() {
        dynamic wmp = Activator.CreateInstance(Type.GetTypeFromProgID("WMPlayer.OCX"));
        wmp.StatusChange += new Action(wmp_StatusChange);
    }
于 2013-03-26T10:44:39.697 に答える