提詞器原理分析和技術(shù)實現(xiàn)_第1頁
提詞器原理分析和技術(shù)實現(xiàn)_第2頁
提詞器原理分析和技術(shù)實現(xiàn)_第3頁
提詞器原理分析和技術(shù)實現(xiàn)_第4頁
提詞器原理分析和技術(shù)實現(xiàn)_第5頁
已閱讀5頁,還剩16頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、播音提詞器的原理分析和技術(shù)實現(xiàn)1. 提詞器應(yīng)用概述我開發(fā)的一個產(chǎn)品想實現(xiàn)很多顯示設(shè)備的同屏顯示效果,查閱資料的時候發(fā)現(xiàn)播音提詞器也是其應(yīng)用之一,那就順便一起研究了吧。筆者很長時間沒有開發(fā)程序了,錯誤的地方請廣大碼友多多批評指正。電視提詞器是常用于電視播音、采訪工作中的專用設(shè)備。其使用場景是播音員在播音的時候,需要正視前方,流暢說出待播內(nèi)容。由于播音具有不確定性,播音員很難準(zhǔn)確記住整片文件,因此需要借助外部協(xié)助。外部協(xié)助包括語音導(dǎo)播和圖像導(dǎo)播:語音導(dǎo)播是指導(dǎo)播人員在幕后手持文稿閱讀,聲音傳輸?shù)讲ヒ魡T所用的耳機(jī),播音員根據(jù)導(dǎo)讀聲音播出。圖像導(dǎo)播:是指在播音員前方防止較大屏幕的顯示屏,用于顯示待播文

2、稿,文稿調(diào)整顯示內(nèi)容,播音員閱讀內(nèi)容。語音導(dǎo)播和圖像導(dǎo)播各有弊端,語音導(dǎo)播受人為影響較大,例如導(dǎo)播要控制播音進(jìn)度,并且導(dǎo)播的時候不能出現(xiàn)意外狀況(打噴嚏、注意力不集中等),圖像導(dǎo)播往往需要借助多種設(shè)備,成本較高。高質(zhì)量圖形設(shè)備層出不窮,為了確保播出質(zhì)量,圖形提詞器應(yīng)用越來越廣泛。因此導(dǎo)播系統(tǒng)雖然看似簡單,但是如果要實現(xiàn)高質(zhì)量的導(dǎo)播效果,需要精心設(shè)計。本文主要討論圖像方式的導(dǎo)播,通過需求和技術(shù)分析,提供新技術(shù)廣泛應(yīng)用下的最優(yōu)解決思路。2. 圖像提詞器發(fā)展情況圖像提詞器發(fā)展經(jīng)歷了三個階段:模擬信號提詞器、計算機(jī)信號提詞器和網(wǎng)絡(luò)提詞器。2.1 模擬信號提詞器模擬信號提詞器是最早的圖像提詞器技術(shù),其原

3、理是播音員前方放置待播紙質(zhì)文稿,文稿正上方置攝像儀器,儀器所拍信號通過線路傳輸?shù)讲ヒ魡T正前方約5米的顯示屏,顯示屏所顯示的為鏡像圖像,需要經(jīng)過一個45°的反光玻璃糾正,從而看到正像,播音員閱讀正像圖片播出。其示意圖如下:圖像在上述環(huán)境中顯示的圖像如下:播音員閱讀反向文字非常吃力,需要模擬信號顯示器進(jìn)行像素偏轉(zhuǎn)處理現(xiàn)鏡像顯示其實很簡單,只需要對顯示器電路作簡單的修改,將顯像管的行偏轉(zhuǎn)線圈兩個接線頭調(diào)換一下,即可實現(xiàn)圖像的鏡像顯示。這種方案有如下特點:1、 播放進(jìn)度掌控在播音員手中,控制自如;2、 原理簡單,幾乎全部基于硬件設(shè)備,線路清晰;3、 硬件刷新率較高,但是圖像增強(qiáng)顯示,容易對播

4、音員眼部造成傷害;4、 播音的時候,播音員手部需要換搞,動作需要雅觀;5、 播音的時候需要較大屏幕,對焦比較麻煩;6、 造價較高;2.2 計算機(jī)信號提詞器隨著計算機(jī)辦公普及,電視文稿產(chǎn)生、傳輸實現(xiàn)了無紙化,使用針對電子文檔的提詞器是大勢所趨,模擬信號提詞器也逐步由模擬信號提詞器發(fā)展成計算機(jī)提詞器,播音員只需要通過鼠標(biāo)或控制器就可以靈活控制文稿的顯示。同時由于顯示技術(shù)的發(fā)展和對提詞器輕量化和移動性,便攜性的要求,傳統(tǒng)的CRT提詞器已經(jīng)逐漸被淘汰,轉(zhuǎn)而大量使用液晶顯示器做為顯示單元。新型電腦提詞器的組成如下圖所示:液晶顯示器不再具有偏轉(zhuǎn)線圈掃描單元,市售的液晶顯示器也都無法通過簡單地修改電路實現(xiàn)圖

5、像的鏡像顯示。目前實現(xiàn)液晶顯示器提詞的方法基本有兩種:一種方法是使用專用的硬件VGA鏡像發(fā)生設(shè)備器,實現(xiàn)顯示器信號的鏡向輸出,但這種設(shè)備基于硬件,成本高,一旦損壞,將難以及時修復(fù)。第二種方法是使用雙顯卡或雙頭顯卡,利用軟件實現(xiàn)副顯卡與主顯卡顯示內(nèi)容的鏡向,實現(xiàn)方法是使用專用軟件輔以一種專用的鏡像顯示字庫并通過改變文字的顯示順序來實現(xiàn)文字的鏡向顯示。目前市面基于這種方案的提詞器具有如下特點:1、 使用通用的計算機(jī)硬件,維修更新方便,成本低2、 必須使用專用軟件,文稿兼容性差,不能兼容常見的WORD,WPS,PDF等文稿格式;3、 更無法實現(xiàn)圖文同時顯示;4、 使用專用字庫,僅能實現(xiàn)中文或英文提詞

6、,無法實現(xiàn)中英文混合顯示;5、 少數(shù)民族等需要縱向顯示的文稿,播音臺無法正常使用;為解決上述兩種方案的弊病,需要設(shè)計出一種使用通用硬件,同時又能直接支持各種軟件的提詞器系統(tǒng)。第二套方案的硬件設(shè)計具有很強(qiáng)的通用性,目前主流PC均可安裝雙顯卡或單片雙頭顯卡,普通顯卡由于是民用產(chǎn)品,價格便宜,來源廣泛,數(shù)百元即可購得,因此這將是一種極為廉價的高可靠性電腦提詞器信號輸出方案,值得采用,因此提詞器系統(tǒng)硬件部分應(yīng)該選用這種方法。    關(guān)鍵的難點在于如何用軟件實現(xiàn)副顯示器對主顯示器的鏡像滾屏輸出,同時又要兼容眾多的文檔格式。事實上,各種文檔格式都有成熟的軟件可以打開,并可以在

7、鼠標(biāo)控制下實現(xiàn)自動滾屏和手動滾屏,例如Microsoft Word,只要打開文檔后,點擊鼠標(biāo)滾輪鍵,即可控制滾屏速度和方向,同時顯示字號、字體的大小均可任意調(diào)節(jié)。因此,多文檔格式滾屏的實現(xiàn),完全可以利用各類文稿軟件自身的功能來實現(xiàn)。問題就簡化為如何將主顯示卡上顯示的內(nèi)容實時地水平鏡像復(fù)制到副顯示器上。本文重點講述如何利用簡易設(shè)備,采用合理的軟件技術(shù),解決上述弊端,實現(xiàn)高質(zhì)量的屏幕鏡像復(fù)制效果。2.3 網(wǎng)絡(luò)提詞器隨著互聯(lián)網(wǎng)直播臺、現(xiàn)場錄播、討論式播出的不斷流行,需要播音軟件具有更復(fù)雜的、控制功能,實現(xiàn)多人播出,并在播出的時候插稿、臨時修改播音詞、合理引導(dǎo)播出等。網(wǎng)絡(luò)提詞器方案一般是根據(jù)計算機(jī)提詞

8、器的第二套方案,對提詞器的內(nèi)容同步、顯示控制等進(jìn)行功能改進(jìn),實際上是軟件提供了更加復(fù)雜的網(wǎng)絡(luò)控制功能。網(wǎng)絡(luò)提詞器的原理如下圖所示:上圖所示播音員的的計算機(jī)仍是核心,播音員可以操控播音計算機(jī)的播放進(jìn)度,而編輯員計算機(jī)通過軟件獲取播音員當(dāng)前的播出內(nèi)容,并進(jìn)行編輯,完畢后將新內(nèi)容同步到播音員計算機(jī),達(dá)到插播效果。上述方案中,編輯員獲取播音員當(dāng)前播出內(nèi)容和編輯非常容易,難點在于在播音員正常錄播的情況下如何實現(xiàn)屏幕加載。網(wǎng)絡(luò)軟件技術(shù)要求高,而且需要安全操作,因此軟件造價相對較高,但是其強(qiáng)大的功能對于大型播音臺非常適用。3. 計算機(jī)和網(wǎng)絡(luò)提詞器需求分析通過對提詞器的發(fā)展分析,可以看出目前市場對提詞器的需求

9、大致如下:3.1 文稿引入文稿引入是指提詞器軟件應(yīng)具備自建內(nèi)容和從外部獲取內(nèi)容的能力。由于提詞器的展示樣式是其運行前可以設(shè)置的,因此軟件所管理的內(nèi)容應(yīng)當(dāng)是文本內(nèi)容,文稿引入要求可以打開常用格式的稿件,并提取其文本內(nèi)容。常用的文稿樣式有TXT、Microsoft Word、WPS、PDF、HTML等。自建文稿是指用戶可以在軟件新建一篇文稿,由于軟件管理文本內(nèi)容,因此建議新建文稿的格式為TXT文檔。3.2 二次編輯二次編輯是指播音人員在播音前的閱稿過程中如果發(fā)現(xiàn)稿件有錯誤或已經(jīng)裝入的稿件需要臨時調(diào)整,可以通過軟件及時調(diào)整,不影響播出。3.3 題詞效果設(shè)置播音的時候,需要對題詞文本進(jìn)行展示樣式的設(shè)置

10、和字幕展示方式設(shè)置,以達(dá)到最好的提示效果。樣式的設(shè)置包括對字體、字號、文字顏色、文字背景顏色、行間距、字間距、段落間距等;字幕展示方式是指對不同的播音習(xí)慣進(jìn)行文字橫排和縱排展示,橫向滾動和縱向滾動展示,文字排版方向和字幕滾動方向互相配合使用,一般當(dāng)字幕自下向上縱向滾動的時候文字橫向自上向下排版,字幕自上向下滾動的時候文字自下向上排版,字幕自左向右滾動的時候文字自右向左排版,字幕自左向右排版的時候文字自左向右排版。以下列出部分效果示意:橫向字幕水平鏡像的示意效果橫向字幕垂直鏡像的示意效果橫向字幕的自上向下滾動示意效果縱向字幕的水平鏡像效果示意縱向字幕的垂直鏡像效果示意3.4 鏡像支持兩個顯示器鏡

11、像顯示,包括屏幕復(fù)制、水平鏡像和垂直鏡像。3.5 進(jìn)度控制進(jìn)度控制是指字幕在運行過程中,應(yīng)當(dāng)可以展示出字幕開始的時間、已經(jīng)運行的時間、剩余時間、進(jìn)度百分比等信息,便于播音員了解當(dāng)前進(jìn)度情況。播音員可以根據(jù)當(dāng)前進(jìn)度情況使用多種方式進(jìn)行進(jìn)度調(diào)整,包括可以鼠標(biāo)滾輪、游戲手柄、腳踏開關(guān)等調(diào)整滾動速度和當(dāng)前進(jìn)度,并可以隨時控制暫停、回復(fù)滾動等操作。3.6 插播插播是指字幕已經(jīng)裝載內(nèi)容并且正在滾動的時候,其它程序可以增加、刪除正要播出的內(nèi)容,并將最新的內(nèi)容更新到正在播放的屏幕,更新的時候屏幕不會閃爍。3.7 語言播音軟件要應(yīng)對不同語種的播音需要,例如英語、漢語、日語、韓語、哈薩克等等,要求軟件界面、提示信

12、息和字幕內(nèi)容支持多語種,便于播音員順利操作軟件和播音。4. 技術(shù)實現(xiàn)方法了解上述需求后,可以想象最好的實現(xiàn)效果好比玩游戲一樣,在進(jìn)行內(nèi)容的檢查后進(jìn)行樣式設(shè)定,然后開始執(zhí)行字幕,執(zhí)行過程中播音員就像游戲中的線路跑動一樣,調(diào)整跑動速度,如果已經(jīng)連接了擴(kuò)展顯示器,擴(kuò)展顯示器可以隨時鏡像顯示。實現(xiàn)上述效果看似簡單,要達(dá)到游戲效果絕非易事,有很多難點:ü 字幕排版靈活,如對較大篇幅的文字根據(jù)設(shè)置進(jìn)行橫向和縱向排版;ü 鏡像屏幕需要恒定的速度,而在Windows操作系統(tǒng)下很難得到;ü 字幕滾動過程中持續(xù)占用處理器資源,避免字幕滾動過程中出現(xiàn)閃爍;ü 支持更多的外部驅(qū)

13、動,包括游戲手柄等;筆者訪查市面上絕大多數(shù)提詞器,其使用的技術(shù)分為以下幾種:方案1: 創(chuàng)建兩個窗口,一個全屏運行在主屏幕,另一個全屏運行在副屏幕。主屏幕運行正像顯示的字幕,副屏幕鏡像顯示主屏幕的內(nèi)容。主屏幕字幕排版采用文本控件實現(xiàn),然后將文本控件圖像貼圖到副屏幕,建立一個定時器,定時調(diào)整文本控件滾動條的位置,并將所產(chǎn)生的最新圖像貼圖到副屏幕的窗口。在實現(xiàn)的時候有很多問題要考慮,例如大文件的快速裝載,文本控件的滾動條隱藏等,需要主屏幕的軟件隱藏文本控件,并將文本控件的顯示圖像拷貝出來,根據(jù)當(dāng)前位置粘貼到預(yù)置好的3個圖片框。該方法使用VB或者VC開發(fā)比較適合,VB開發(fā)技術(shù)門檻低,比較適合工具類軟件

14、開發(fā),同時可以調(diào)用Windows API實現(xiàn)強(qiáng)大的功能,并且具有很高的運行效率,當(dāng)然如果做到更優(yōu)秀的功能,需要采用VC,VC在文本處理、圖像處理、硬件控制等方面都具有非常優(yōu)秀的能力,但是VC開發(fā)往往需要更高的成本。方案2:同樣是創(chuàng)建兩個窗口,文字排版依靠系統(tǒng)API函數(shù),API函數(shù)根據(jù)設(shè)置的效果將文字打印在主窗口屏幕,主窗口屏幕打印完畢后,將主窗口所有內(nèi)容鏡像顯示到擴(kuò)展屏幕的窗口。該方案的排版功能很難實現(xiàn),例如繪制某一時刻的字幕效果,需要先知道整體高度,當(dāng)前運行的位置,下一刻速度等。方案3:如同方案2,不同的是副屏幕不再是鏡像顯示主屏幕的圖像,而是文字依靠可鏡像的字體,直接鏡像顯示。其優(yōu)點是運行

15、效率比方案2高一些,缺點是對字體的控制相當(dāng)麻煩,投入非常大而收獲很小,只能使用很少量的字體。以上方案有很多缺陷:1. 方案1和方案2依靠全屏貼圖實現(xiàn)屏幕鏡像,肉眼的舒適切換頻率在100毫秒,而雙屏整屏幕繪制(StretchBlt),往往會超出(目前市場的中配顯示器,整平刷新需要40-70毫秒,如果加上軟件處理的損耗,往往會達(dá)到120毫秒以上),頓挫感很強(qiáng);2. 較大文件的字幕需要動態(tài)將文字轉(zhuǎn)化為圖片,如果要實現(xiàn)無刷新效果,必須使用內(nèi)存雙緩沖繪圖技術(shù),該技術(shù)比較復(fù)雜,即使使用了該技術(shù),若使用了較低配置的顯示器或主機(jī),仍無法達(dá)到效果;3. 實現(xiàn)縱向字幕是非常艱巨的工程;4. 若要實現(xiàn)多角色播音(加

16、背景顏色),性能會大幅降低;5. Timer控件有很多缺陷,其主要作用是定時觸發(fā),如果處理時間超出timer的設(shè)定頻率,屏幕滾動時快時慢,影響播出;6. 主屏幕和擴(kuò)展屏幕尺寸不一致的時候,即放大和縮小顯示,出現(xiàn)排版混亂;為了解決上述問題,筆者決定嘗試采用較新的技術(shù):使用C#開發(fā),運行在Windows7+IE10及以上版本。為什么必須要采用C#開發(fā)呢?因為C#運行在.net CLR上面,已經(jīng)提供了性能較好的繪圖技術(shù),而且獲取外部文檔的技術(shù)相對簡單,而運行在IE10是因為IE10的超文本渲染效果是最好的,滑動非常細(xì)膩,而且支持超大文件,而且我想使用CSS3實現(xiàn)部分排版功能??傊甀E的技術(shù)投入是非常

17、大的,人家是超文本展示的高手,仔細(xì)發(fā)掘肯定能滿足我們的需求。眾所周知,現(xiàn)在的筆記本通常是Windows7操作系統(tǒng),IE10通常運行在Windows7上,筆記本通??梢灾苯舆B另一個擴(kuò)展屏幕,無需額外的硬件投入。當(dāng)然如果要運行更流暢,建議擴(kuò)展顯示器采用刷新率較高的,而且內(nèi)存4G以上,CPU 2GHZ以上,現(xiàn)在主流筆記本都可以達(dá)到。說了這么多,該技術(shù)環(huán)節(jié)登場,針對需求,列出主要實現(xiàn)辦法。本文的代碼主要是測試代碼,有些是從往上拷來的,是我都運行過,是可用的。4.1 打開外部文件并提取文本打開外部文本包括提取Word、WPS、PDF的文本內(nèi)容,按照原有的段落組織。C#獲取Word內(nèi)容需要引用Micros

18、oft Word 12.0 Object Library類庫,實現(xiàn)方法如下:Word.ApplicationClass wordApp=new ApplicationClass(); object file=path;/表示W(wǎng)ord的路徑object nullobj=System.Reflection.Missing.Value; Word.Document doc = wordApp.Documents.Open(5.ref file, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj,

19、ref nullobj, ref nullobj, ref nullobj, ref nullobj, ref nullobj); doc.ActiveWindow.Selection.WholeStory(); doc.ActiveWindow.Selection.Copy(); IDataObject data=Clipboard.GetDataObject(); String doctext=data.GetData(DataFormats.Text).ToString(); doc.Close();打開WPS文檔的代碼如下:object WpsApp;object 

20、args = new object1;Type wpsAppName;string progID = "Wps.Application"wpsAppName = Type.GetTypeFromProgID(progID); /創(chuàng)建一個WPS實例WpsApp = Activator.CreateInstance(wpsAppName);args0 = true; /設(shè)置為可見wpsAppName.InvokeMember(&q

21、uot;Visible", BindingFlags.SetProperty, null, WpsApp, args); /得到Documents對象Object wpsDocs = wpsAppName.InvokeMember("Documents", BindingFlags.GetProperty, null, WpsApp, null);  /設(shè)置關(guān)鍵參數(shù)即可,例如: 在打開的方法中,只要指定打開的文件名與

22、是否可見args = new object15;args0 = "C:/Demo.wps"args11 = true; /打開C盤下的Demo.wpsObject wpsDoc = wpsAppName.InvokeMember("Open", BindingFlags.InvokeMethod, null, wpsDocs, args);args = new object3;

23、/下面就可以從doc對象獲取文本了打開pdf請注意,pdf分為單層pdf和雙層pdf,單層pdf是由圖片組成的每一頁,雙層pdf是每一頁的圖片上面覆蓋有文字,軟件只能打開雙層pdf,實際是讀取所覆蓋的文字部分,如果想從圖片獲取文字,只能用OCR技術(shù)了,對這個軟件來說沒有必要。打開雙層pdf的代碼如下:添加一個iTextSharp的引用,iTextSharp是一個開源的PDF操作類庫。string xieyi = ""FileInfo fi = new FileInfo(FilePath);StreamReader sr = fi.OpenText();xieyi = sr.

24、ReadToEnd();sr.Close();return xieyi; 文本讀取以后要寫入到一個新的txt文件里面,以備后面編輯的時候用。4.2 展示、編輯文本展示文本是指從讀取后生成的txt文件中按照段落取出來數(shù)據(jù),并呈現(xiàn)給播音人員檢查。從txt文件中讀取內(nèi)容比較簡單,不再粘貼代碼了。從txt文件中讀取的文本按照段落存儲在String數(shù)組當(dāng)中,數(shù)組作為DataGridView的數(shù)據(jù)源呈現(xiàn)。在這里我們需要新建一個List< CaptionItem >對象作為DataGridView的自定義數(shù)據(jù)源。其中CaptionItem是每一個數(shù)據(jù)項,其字段包括。Text(文本內(nèi)容 ,即每一個

25、段落)、FontName、FontSize、FontColor、SectionPadding、RowPadding、BackGroundColor、Alignment等。這個對象建立以后,就將我們讀取的String數(shù)組封裝為List<CaptionItem>對象。將該數(shù)據(jù)綁定到DataGridView即可顯示。綁定代碼如下:/綁定GW.DataSource = null;BindingList<CaptionItem> bindsource = new BindingList <CaptionItem>(DataFactory.getDataSource()

26、;GW.DataSource = bindsource;綁定以后我們每一行就可以取出來內(nèi)容展示了:然后我們完善雙擊事件,實現(xiàn)快速修改內(nèi)容、文字樣式、背景顏色、間距等參數(shù)設(shè)置,難度相當(dāng)于農(nóng)民種菜。下一步我們繼續(xù)完善其它編輯功能,例如刪除行、增加行、復(fù)制剪切粘貼行、格式刷等等,代碼較多就不帖了,放上編輯的撤銷和恢復(fù)操作代碼吧:public void UnDo() SerRow undoRow = un.Undo(); if (undoRow = null) return; /當(dāng)Ì¡À前¡ã值¦Ì壓1入¨?REDO堆?棧

27、? CaptionItem catchedRow = new CaptionItem(DataFactory.getDataSource()undoRow.RowIndex); un.setRedo(new SerRow(undoRow.RowIndex,0,catchedRow); /執(zhí)¡ä行DUNDO exeUndoRedo(undoRow); /定¡§位?到Ì?被À?恢?復(fù)¡ä的Ì?行D if (undoRow.Tag = 0) gridView.CurrentCell = gridView.Row

28、sundoRow.RowIndex.Cells0; else if (undoRow.Tag = 1) gridView.CurrentCell = gridView.RowsundoRow.RowIndex-1.Cells0; else if (undoRow.Tag = -1) gridView.CurrentCell = gridView.RowsundoRow.RowIndex + 1.Cells0; undoControl.Enabled = un.IsUndoPossible(); redoControl.Enabled = un.IsRedoPossible(); public

29、void ReDo() SerRow redoRow = un.Redo(); if (redoRow = null) return; CaptionItem catchedRow = new CaptionItem(DataFactory.getDataSource()redoRow.RowIndex); un.setUndo(new SerRow(redoRow.RowIndex, 0, catchedRow); exeUndoRedo(redoRow); /定¡§位?到Ì?被À?恢?復(fù)¡ä的Ì?行D gridView.

30、CurrentCell = gridView.RowsredoRow.RowIndex.Cells0; undoControl.Enabled = un.IsUndoPossible(); redoControl.Enabled = un.IsRedoPossible(); 最后交代一下,如果用戶希望我們的單元格能夠換行顯示,而且根據(jù)我們設(shè)定的文字大小換行顯示,我建議不要使用DataGridView的AutoHeight等屬性,交給重繪事CellPaint件來做。BS微軟的開發(fā),AutoHeight屬性用了以后,加載叫個超級慢。if (e != null) if (e.ColumnIndex

31、= 0) && (e.RowIndex >= 0) AppTools.updateRowStyleByData(GW, e.RowIndex); if (WarpDToolStripMenuItem.Checked) / Size size = e.ClipBounds.Size; string Value = "" if (e.Value = null) return; Value = e.Value.ToString(); if (String.IsNullOrEmpty(Value) Value = "無" Captions.

32、AppTools.hhString str = new Captions.AppTools.MrString(Value, titleColumnWidth, size.Height, e.CellStyle.Font, e.Graphics); GW.Rowse.RowIndex.Height = (int)str.height; else GW.Rowse.RowIndex.Height = (int)e.Graphics.MeasureString("幕", e.CellStyle.Font).Height; 至此內(nèi)容編輯的功能實現(xiàn)的差不多了,不過最后建議增加一項功能

33、,就是能夠?qū)?dāng)前編輯的文字、樣式保存為我們自己的文件,下次可以直接調(diào)出來這個文件,不用再編輯文字和設(shè)置樣式了,夠人性化吧?我們自己去規(guī)定文件樣式把,編碼采用Unicode,先生成文件內(nèi)容:IList<String> styledStringList = new List<String>();List<CaptionItem> dataSource = DataFactory.getDataSource();foreach (CaptionItem dataItem in dataSource) String styedRow = "" F

34、ont font = dataItem.getFFont(); styedRow = dataItem.文?本À? + "t" styedRow = styedRow + "" styedRow = styedRow + "fontName:" + dataItem.SFont + "," styedRow = styedRow + "fontSize:" + font.Size + "," styedRow = styedRow + "fontColor

35、:" + dataItem.getFontColor() + "," styedRow = styedRow + "fontBold:" + font.Bold.ToString().ToLower() + "," styedRow = styedRow + "fontItalic:" + font.Italic.ToString().ToLower() + "," styedRow = styedRow + "fontStrikethru:" + font.Str

36、ikeout.ToString().ToLower() + "," styedRow = styedRow + "fontUnderLine:" + font.Underline.ToString().ToLower() + "," styedRow = styedRow + "aligns:" + dataItem.對齊 + "," styedRow = styedRow + "bgColor:" + dataItem.getBgColor_HTML() + ",

37、" styedRow = styedRow + "margin:" + dataItem.間距¨¤ + "" styledStringList.Add(styedRow);return styledStringList;寫入文件的代碼:if (System.IO.File.Exists(fName) File.Delete(fName);using (StreamWriter sw = new StreamWriter(fName, false, Encoding.Unicode) oreach (String strIte

38、m in styledDataArray) sw.WriteLine(strItem);4.3 字幕排版設(shè)置字幕排版是字幕軟件的重點了,我們既然決定讓IE來幫我們實現(xiàn)排版,那排版后的文件格式就應(yīng)該是HTML了,字幕排版的重點是生成合適的HTML文件,并借助WebBrowser控件展示出來,達(dá)到用戶想要的字幕效果。有童鞋問了,既然我們要生成HTML,為什么剛才要保存成我們自己設(shè)定的文件格式呢?因為我們可以繼續(xù)寫功能,讓該軟件可以打開這個帶有格式的文件,而采用HTML格式保存,我們下次解析里面的內(nèi)容和格式相對困難。字幕排版設(shè)置是指告訴系統(tǒng),以后運行字母的時候,默認(rèn)生成哪種樣式的字幕。樣式包括水平字

39、幕自上向下滾動、水平字幕自下向上滾動、垂直字幕自左向右滾動、垂直字幕自右項左滾動。設(shè)置部分代碼簡單就不列出了。4.4 字幕預(yù)處理該功能是指用戶在運行字幕前,需要根據(jù)字幕排版設(shè)置的參數(shù),生成相應(yīng)的HTML文件。生成的HTML有如下關(guān)鍵部分:按照我們之前設(shè)定的內(nèi)容、內(nèi)容樣式,段落樣式生成基本段落HTML代碼,給段落HTML代碼附加樣式生成適合字幕方向的代碼。生成基本的HTML段落代碼比較簡單:StringBuilder sb = new StringBuilder();sb.Append("<div style="width:" + screenSize.Wid

40、th.ToString() + "" > rn");sb.Append("<div style="height:" + (screenSize.Height).ToString() + "px" ></div>rn");if (direction = 0) foreach (CaptionItem item in DataFactory.getDataSource() String css = getCss_H(item, direction); sb.Append(&quo

41、t;<div " + css + ">" + item.文本 + "</div>" + "rn"); else if (direction = 4) for (int i = DataFactory.getDataSource().Count - 1; i >= 0; i-) CaptionItem item = DataFactory.getRow(i); String css = getCss_H(item, direction); sb.Append("<div "

42、; + css + ">" + item. 文本 + "</div>" + "rn"); sb.Append("<div style="height:" + (screenSize.Height).ToString() + "px" ></div>rn");sb.Append("</div> rn");return sb;段落樣式代碼如下:/獲?得Ì?橫¨¢向¨&

43、#176;排?版ã?的Ì?CSS樣¨´式º?private String getCss_H(CaptionItem item, int direction) StringBuilder sb = new StringBuilder(); String dirStr = "" if (direction = 4)dirStr = "writing-mode:lr-bt;text-align:left; " sb.Append("style="" + dirStr); Font

44、font = item.getFFont(); if (!String.IsNullOrEmpty(font.Name) sb.Append("font-family:'" + font.Name + "'");sb.Append("font-size:" + font.Size.ToString() + "pt;");if (font.Bold) sb.Append("font-weight:bold;");if (font.Italic) sb.Append("fo

45、nt-style:italic;");if (font.Strikeout) if (font.Underline)sb.Append("text-decoration:line-through underline;"); elsesb.Append("text-decoration:line-through;");else if (font.Underline)sb.Append("text-decoration:underline;"); String alignStr = "" if (item.對

46、齊.Equals("")alignStr = "left" else if (item. 對齊.Equals("")alignStr = "right" elsealignStr = "center" sb.Append("text-align:" + alignStr + ""); sb.Append("color:" + item.getFontColor() + ""); sb.Append("bac

47、kground:" + item.getBgColor_HTML() + ""); sb.Append("padding-top:" + item.間距/2+ "px;padding-left:0px;padding-right:0px;padding-bottom:" + item. item.間距/2+ "px; margin:0px;"); sb.Append("""); return sb.ToString();需要留意的是writing-mode:lr-bt屬性,它

48、用來決定我們的Div里面的文字排版方向,只有高版本的IE才能夠支持。另外需要留意的是字幕開始的時候,是總最邊緣慢慢移入相對方向的,需要生成一個滿屏的空DIV先占位。以上是橫向排版的部分生成代碼,縱向排版字幕以此類推,主要是修改writing-mode:lr-bt屬性。當(dāng)然入到反向滾動的字幕,生成HTML的時候,對List< CaptionItem>按照自底部向頂部依次輸出。4.5 字幕窗口字幕窗口主要實現(xiàn)的是加載HTML代碼,加載控件是WebBroswer。WebBroswer的Navigate方法用于接在HTML代碼。有同學(xué)要問了,為什么不將生成的HTML代碼直接傳遞給WebBr

49、oswer而是生成HTML文件讓W(xué)ebBroswer加載呢?因為筆者經(jīng)過測試,WebBroswer直接加載HTML代碼,不太好觸發(fā)DocumentCompleted事件,我們需要對DocumentCompleted進(jìn)行監(jiān)控,等待WebBroswer全部加載完畢再滾動字幕,有一個暫短的停留。if (WB.ReadyState < WebBrowserReadyStateaaaplete) return;timerScroll.Interval = (DataFactory.getDataSource().Count+1)/2+1000;/加¨®入¨?鼠

50、6;¨®標(biāo)À¨º點Ì?擊¡Â事º?件tthis.WB.Document.MouseDown += new HtmlElementEventHandler(WB_mouseclik);WB.Document.Focusing += new HtmlElementEventHandler(WB_Focus );timerScroll.Enabled = true;這里面用到了Timer,實際上將來Timer只執(zhí)行一次,之所以用它,是想程序不假死的等待,當(dāng)然你可以有別的實現(xiàn)辦法。那么Timer是做什么的呢?pr

51、ivate void timerScroll_Tick(object sender, EventArgs e) timerScroll.Enabled = false; panelLodding.Visible = false; WB.Visible = true; Rectangle wbScrollRectangle = this.WB.Document.Body.ScrollRectangle; /如¨?果?沒?有®D鏡¦Ì像?顯?示º?器¡Â,ê?鏡¦Ì像?按ã¡&#

52、228;鈕£¤無T法¤¡§使º1用®? if (Contants.MONITOR_DIR != 3) showMirrorWindow(); Thread.Sleep(100); /初?始º?化¡¥屏¨¢幕?滾?動¡¥參?數(shù)ºy captionThread = new CaptionThread(); captionThread.setCaptionArgs(this, wbScrollRectangle, panelCenter.ClientR

53、ectangle, new ScrollBackHandler(RefreshBK), new ScrollBackHandler2(scrollBackInvok), new ScrollBackHandlerMirror(RefreshBKMirror); theThread = new Thread(new ThreadStart(captionThread.startScrolling); theThread.Name = "字Á?幕?線?程¨¬" + DateTime.Now.ToShortTimeString() + "

54、創(chuàng)ä¡ä建¡§" theThread.Start(); startScrollTime = DateTime.Now; 它的作用是啟動一個字幕線程,專門用來處理滾動的事情。有同學(xué)會問,為什么要啟動另一個線程?因為我想獲得更穩(wěn)定的速率。while (!blnScrollingStop) && (H < sourceWidth) if (!Contants.PAUSE) | (blnScrollingPause) Application.DoEvents(); continue; DateTime t = DateT

55、ime.Now; /監(jiān)¨¤聽¬y主¡Â線?程¨¬是º?否¤?讓¨?關(guān)?閉À?該?線?程¨¬ if (H = 0) Thread.Sleep(1000); Point speedPoint = AppTools.getSpeed(Contants.CAP_SCRLLSPEED); AppTools.AccurateSleep(speedPoint.X ); H = H + speedPoint.Y; /主¡Â繪?圖ª?事º?件t

56、 int offset = (sourceWidth - H - parentRectangle.Width); /橫¨¢向¨°偏?移°?的Ì?數(shù)ºy值¦Ì if (offset < 0) offset = 0; if (H >= sourceWidth - parentRectangle.Width) H = 0; /通ª¡§知a主¡Â線?程¨¬刷¡é新? if (!(frmParent.IsDispo

57、sed) try frmParent.Invoke(scrollBackHandler, new Point(offset, 0); frmParent.BeginInvoke(scrollBackHandler2, new Point(offset, 0), t); if (Contants.MONITOR_DIR < 3) frmParent.Invoke(scrollBackHandlerMirror, new Point(offset, 0); catch(Exception) /DateTime t2 = DateTime.Now; /TimeSpan ts = t2 - t;

58、 /Console.WriteLine(ts.Milliseconds); 該現(xiàn)成的主要作用是提供一個穩(wěn)定的速率,到了指定的時間讓W(xué)ebBroswer控件的滾動條改變位置,從而達(dá)到滾動效果。需要留意的是我使用了While循環(huán),如果不釋放控制權(quán),程序很可能假死,如果采用DoEvents釋放,操作系統(tǒng)的忙碌程度對程序?qū)斐珊艽笥绊?,從而造成閃爍,那么我就寫一個非模態(tài)等待函數(shù),函數(shù)的主要功能是扔程序消息,即讓程序不假死(響應(yīng)鼠標(biāo)鍵盤操作,還能高效執(zhí)行滾動)。/非¤?模¡ê態(tài)¬?延¨®遲¨´ public static void AccurateSleep(int a_i4MSec) Int64 t_i8Frequency

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論