著作權聲明
請尊重原創作品。轉載請保持文章完整性,並以超連結形式註明原始作者“tingsking18”和主要站台地址,方便其他朋友提問和指正。
以前是用的事件機制來調用JavaScript,事件和回調本來就是一回事。但是由於沒有解決線程同步問題,所以就一直沒有調通。JavaScript中死活也不響應非同步發送過來的事件。前天用Idispatch介面調通了JavaScript。但是始終覺得不是那麼回事,這樣會麻煩死的。
於是回過頭來思考,用事件是不是只要線程同步一下就可以了?今天早上試了一下,果然沒有問題。
下面介紹一下具體的步驟:
1. 建立MFC ActiveX Control(方法略)
2. 在ClassWizard automation頁添加方法invoke。Invoke函數代碼如下:
void CForthCtrl::invoke(short a)
{
m_a = a;
_beginthread(f, 0, (void*)(this));
}
3. 在上面的invoke方法中調用了線程函數f,在f函數中要調用介面控制項CforthCtrl,所以必須進行線程同步,我們使用了PostMessage方法同步 (以前就是忽略了這裡,所以才調不通JavaScript的) 。f函數的代碼如下:
void f(void * r)
{
CForthCtrl* p = (CForthCtrl*)r;
Sleep(5000);
p->m_a +=10;
PostMessage(p->m_hWnd,WM_THREADFIREEVENT,(WPARAM)NULL,(LPARAM)NULL);
return;
}
4. 在ClassWizard ActiveX Events頁添加事件calljs,事件的參數為short類型的參數,用於將結果傳遞到JavaScript中去。
5. 添加WM_THREADFIREEVENT訊息的訊息映射函數。代碼如下:
LRESULT CForthCtrl::OnFireEventForThread(WPARAM wParam, LPARAM lParam)
{
this->FireCalljs(m_a);
return TRUE;
}
6. 用ActiveX Control Test Container測試一下。看看調用invoke的時候會不會觸發calljs事件。
7. 開啟Microsoft ActiveX Control Pad,插入我們剛剛編寫的控制項。然後添加調用invoke的按鈕,並且添加響應Calljs函數的代碼。
<HTML>
<HEAD>
<TITLE>New Page</TITLE>
</HEAD>
<BODY>
<SCRIPT LANGUAGE="JavaScript" FOR="Forth1" EVENT="calljs(param)">
alert(param);
</SCRIPT>
<script LANGUAGE="JavaScript">
function test()
{
Forth1.invoke(1);
}
</script>
<OBJECT ID="Forth1" WIDTH=100 HEIGHT=51
CLASSID="CLSID:52510A20-E949-4213-89FD-8A2AE5A7F6D4">
<PARAM NAME="_Version" VALUE="65536">
<PARAM NAME="_ExtentX" VALUE="2646">
<PARAM NAME="_ExtentY" VALUE="1323">
<PARAM NAME="_StockProps" VALUE="0">
</OBJECT>
<input type ="button" value="test" onclick="test();">
</BODY>
</HTML>
總結:
1. 使用事件機制比前面的方法省老鼻子勁了,少寫多少代碼啊。
2. 使用Idispatch介面還是很容易出錯的,並且不容易尋找錯誤。
3. 使用事件方式,只要用ActiveX Control Test Container調試成功了,放到web頁面中去就沒問題了。
4. 事件方式不用傳函數名進去,直接在JavaScript中掛接事件就可以了。
5. 線程操作介面一定記得要同步啊!!!!!!