關(guān)于Qt Webkit嵌入Flash總結(jié)(Mac平臺(tái))
Qt Webkit嵌入Flash總結(jié)是本文呢要介紹的內(nèi)容,我們都知道Flash是adobe公司的閉源產(chǎn)品,在各平臺(tái)的渲染都是通過(guò)插件來(lái)進(jìn)行的(如windows下的flash.ocx,linux下的libflashplugin.so和mac下的Flash_Plugin),插件可以在adobe的網(wǎng)站上獲取。
當(dāng)然也有開(kāi)源(如gnash)或商業(yè)項(xiàng)目(如scaleform)來(lái)自行對(duì)flash進(jìn)行解碼渲染。我使用qtwebkit嵌入flash主要是因?yàn)樗鄬?duì)簡(jiǎn)單。如果要在游戲中嵌入一個(gè)網(wǎng)頁(yè)(當(dāng)然也包括flash)除了昂貴的scaleform外,還可選擇其他flash gui,不過(guò)因?yàn)樾试驅(qū)嵱眯圆桓撸湓砭褪峭ㄟ^(guò)adobe的插件獲取要渲染的每一幀圖片,然后將其渲染到一張紋理上,通過(guò)引擎來(lái)渲染。說(shuō)白了就是用游戲引擎來(lái)代替如windows或qt來(lái)對(duì)其進(jìn)行渲染。
1、具體實(shí)現(xiàn)(相關(guān)資料網(wǎng)上有很多,這里只說(shuō)原理和關(guān)鍵性的東東)
要加載flash進(jìn)行顯示(當(dāng)然也包括網(wǎng)頁(yè)),其實(shí)只需要建立一個(gè)QWebView然后調(diào)用其setUrl接口傳進(jìn)去要顯示的文件的路徑(最好是絕對(duì)路徑,并且路徑前加 file:///,當(dāng)然,這應(yīng)該不是必須的)。QWebView還有一個(gè)重要的接口是setHtml,它是傳一個(gè)字符串參數(shù),改字符串是html網(wǎng)頁(yè)源代碼形式,如"<html></html>"。
如果要進(jìn)行交互,需要通過(guò)javascript進(jìn)行中轉(zhuǎn)(其實(shí)從原理上來(lái)說(shuō),是可以通過(guò)NP Api來(lái)直接與adobe提供的flash插件進(jìn)行交互的,不過(guò)相關(guān)資料太少,俺又沒(méi)有寫過(guò)插件,所以選擇了簡(jiǎn)單的方法)。
這里我選擇的是在一個(gè)網(wǎng)頁(yè)中嵌入flash,然后在網(wǎng)頁(yè)的<head></head>中添加js腳本,相關(guān)資料也很多,直接google即可。
這里有一些需要注意的地方:
(1)用addToJavaScriptWindowObject的時(shí)機(jī)很關(guān)鍵,必須要dom什么的加載完畢,官方推薦的做法是,用一個(gè)函數(shù)來(lái)調(diào)用addToJavaScriptWindowObject,將javaScriptWindowObjectCleared的信號(hào)和改函數(shù)connect。具體可以看QWebFrame中的addToJavaScriptWindowObject函數(shù)注釋。
(2)c++調(diào)用js函數(shù):page()->mainFrame()->evaluateJavaScript("Test(1, 2)"),這樣就可以直接調(diào)用js中的Test函數(shù),其中1和2是參數(shù)。
(3)js調(diào)用c++函數(shù):確保a步驟已經(jīng)操作,然后js中就可以直接通過(guò)addToJavaScriptWindowObject傳進(jìn)去對(duì)象名來(lái)調(diào)用相應(yīng)QObject對(duì)象的函數(shù)。
(4)js調(diào)用flash的函數(shù):在as2.0以后可以直接使用ExternalCallback來(lái)進(jìn)行,這里為了兼容以前的flash,使用了老的方法。假設(shè)網(wǎng)頁(yè)中已經(jīng)插入了一個(gè)flash,其id為flashname,使用flashname.SetVariable來(lái)修改flash中的變量。而flash的腳本中,則通過(guò)watch()方法來(lái)監(jiān)視這個(gè)變量的改變,從而調(diào)用相應(yīng)函數(shù)。
(5)flash調(diào)用js的函數(shù):flash中使用fscommand函數(shù),js中只要實(shí)現(xiàn)flashname_DoFSCommand(cmd, args)即可自動(dòng)被調(diào)用。
(6)傳給flash的參數(shù)(尤其是中文字符串)要是unicode編碼的,否則會(huì)亂碼。
最后說(shuō)明一下,這些交互步驟的尤其是js調(diào)用flash函數(shù)的時(shí)機(jī)也很重要,比較早的話會(huì)出現(xiàn)無(wú)法響應(yīng)的情況(可能要等f(wàn)lash完全加載完),或許新的調(diào)用方法會(huì)好些。這里我用了非常惡心的實(shí)現(xiàn)。建立一個(gè)定時(shí)器,當(dāng)過(guò)了1秒鐘(確認(rèn)flash已經(jīng)加載完了),才允許調(diào)用該函數(shù)。
2、qt webkit的bug:
其實(shí)也有可能是adobe的flash插件的bug,不過(guò)反正出現(xiàn)問(wèn)題了,而幸好webkit是開(kāi)源的,俺就只好修改它了。(當(dāng)然,最終也沒(méi)有完美修正改bug,不過(guò)滿足了俺的需要,那就夠了,希望諾基亞的精英們能在下次出版本的時(shí)候解決該問(wèn)題)
bug描述:在mac操作系統(tǒng)下,使用qtwebkit加載flash,在文本框進(jìn)行輸入時(shí),按下一個(gè)鍵,響應(yīng)兩個(gè)字符。
原因:猜想是在adobe的10.1的插件自己實(shí)現(xiàn)了輸入響應(yīng)(即便我把按鍵消息都過(guò)濾掉,flash依然可以正常進(jìn)行輸入,包括中文輸入),而qtwebkit又傳給它一次按鍵信息,那就會(huì)出現(xiàn)該問(wèn)題了。
解決辦法:在pluginViewMac.mm(qt使用的就是這個(gè)文件),的dispatchNPevent函數(shù)中過(guò)濾掉按鍵消息
- if (event.what == keyDown) {
- return ;
- }
這樣flash的輸入就正常了,當(dāng)然,其他任何插件都無(wú)法進(jìn)行正常輸入了,不過(guò)俺做的是游戲,又不是瀏覽器,只要伺候好一個(gè)flash插件就足夠了。
還有一個(gè)bug是,如果我在網(wǎng)頁(yè)的空白地方點(diǎn)一下,再回到flash的文本框就無(wú)法正常輸入了,即便光標(biāo)什么的都在里面,除非我找到一個(gè)flash中的文本框點(diǎn)擊一下。初步判斷原因是點(diǎn)擊到空白的地方,整個(gè)webkit的page就無(wú)法獲取按鍵信息了,因?yàn)橐粋€(gè)page是無(wú)法進(jìn)行編輯的,除非點(diǎn)到一個(gè)文本框,這樣又重新可獲取輸入信息。如果整個(gè)page都接收不到按鍵信息,那其中的flash插件自然也就無(wú)法進(jìn)行輸入了。不過(guò)悲催的是,如果我們之前咩有屏蔽掉的PluginView的keyDown信息,這個(gè)時(shí)候反而會(huì)正常的輸入一個(gè)字符,當(dāng)然中文依然不能正常輸入。
這兩個(gè)bug繼續(xù)查兩天看看,說(shuō)不定會(huì)有新的發(fā)現(xiàn)。
小結(jié):關(guān)于Qt Webkit嵌入Flash總結(jié)(Mac平臺(tái))的內(nèi)容介紹完了,希望通過(guò)本文的學(xué)習(xí)能對(duì)你有所幫助!