2013-03-26 93 views
2

我認爲this article與我有同樣的問題。但是,我的情況沒有可行的解決方案。如何將事件附加到動態對象或COM對象

我在我的程序中使用Windows Media Player ActiveX。

出於某種原因,我不想添加它的引用並由IDE自動轉換爲AxHost。

我通過ActivatorProgID

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); 
} 

不幸的是,當我要附上事件像the article I indicated in the top,它有沒有工作。

我這樣的代碼:

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.DynamicObjectSystem.EventHandler

即使有一個例外,但就像我說的,編譯通過後,一切仍然工作 - - 除了我不聽事件。

那麼,如何在動態對象_wmp中成功附加事件?

任何可能的解決方案(如Reflection)對我很有用。

此外,在上述情況下,處理器類型StatusChangeEventHandler

但是,如果我想處理PlayStateChange事件,如果我不添加wmp.dll的引用,它是一個「未知的句柄」。

我希望解決方案也適用於這種情況。

非常感謝大家的支持,請原諒我的英文不好。

+0

您如何確保WMPlayer狀態發生變化? – 2013-03-26 06:28:55

+0

@SrikanthVenugopalan:accroding [MSDN](http://msdn.microsoft.com/en-us/library/windows/desktop/dd564082.aspx),當我的_wmp.Status改變時引發這個事件。我檢查了狀態字符串,並且它發生了變化,所以我認爲事件也應該提高。 – 2013-03-26 06:41:25

+0

同意 - 想知道您是否知道狀態屬性被更改,並且由於它是隻讀屬性,您將如何更改狀態? – 2013-03-26 06:43:01

回答

1

將一個使用COM對象的程序從早期綁定到晚期綁定調用的通用策略是第一個寫入早期綁定。智能感知將幫助您陷入成功的困境,確保您使用正確命名的方法,傳遞正確的參數,特別有用,可以幫助您找出事件處理程序簽名的外觀。

將會產生該位的測試代碼:

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

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

隨着StatusChange事件處理程序的分配方法和身體完全自動生成由智能感知。注意事件處理程序的簽名,它是而不是的一個EventHandler。只是一個返回void且不帶參數的方法,它與Action委託類型相匹配。現在,您在寫入遲到版本時沒有出現無法識別的運行時異常,這是一個很好的選擇:

void testLateBound() { 
     dynamic wmp = Activator.CreateInstance(Type.GetTypeFromProgID("WMPlayer.OCX")); 
     wmp.StatusChange += new Action(wmp_StatusChange); 
    } 
+0

我從Trad中的MVP得到了相同的提示/回答。中文[MDSN Social](http://social.msdn.microsoft.com/Forums/zh-TW/233/thread/90328268-1c50-4278-a226-cb2e9bfb8bfc)。我實現了'StatusChange'和'PlayStateChange',它非常好。但是,我無法附加到'wmp.Error',並且異常描述是「無法將運算符'+ ='應用於'System .__ ComObject'和'Action'」。我現在仍然試圖解決這個問題。我會盡力按照您的提示解決這個問題。謝謝。 – 2013-03-28 01:51:05

+0

根據[MSDN文檔](http://msdn.microsoft.com/zh-tw/library/windows/desktop/dd564051(v = vs.85).aspx),似乎有一個錯誤事件。但是當我使用'WMPLib.WindowsMediaPlayer'類型時,標記'Error'是一個屬性。我正在尋找一些方法來附加錯誤事件。 – 2013-03-28 02:22:29

+0

假設事件處理程序具有像這樣的參數public void wmp_StatusChange(object sender,MyCustomArgument e){}在這種情況下,事件註冊碼是什麼? – Aneesh 2014-05-09 05:58:57