用Delphi在區域網中實現網上影院 (轉)

worldblog發表於2007-12-13
用Delphi在區域網中實現網上影院 (轉)[@more@] microsoft FrontPage 4.0">
<>稿件   用在中實現網上影院
  陳經韜
  相信用過<>的人都知道里面有個"接收DVB廣播",可以在區域性網中實現一臺影片而另一臺接收.因為DVB設計的知識面太廣,下面我們用另外一個巧妙的思路來實現區域性網中的"網路播放".因為涉及到多檔案的播放,所以我們在中使用了一個 Mediaplay,但是很多使用過這個控制元件做的人都遇到過這樣一個問題:就是在播放MPG等副檔名的檔案時出現"MCI初始化錯誤",如果了Win後又沒有問題了,怎麼回事呢?現在市面上所有的有關DELPHI多媒體的書都沒有講到這個問題和如何解決.原來,我們要自己修改win.ini裡面[mci extensions]小節,另外還要修改一下system.ini裡面的[mci]小節.舉例說,你想讓Mediaplay可以播放MPG為副檔名的檔案時,可以按照如下格式修改:
[mci extensions]
mpeg=MPEGVo
mpg=MPEGVideo
...
  在這裡,我們寫了個自定義WriteMciConfig來達到這一目的,詳細程式碼請看源程式.
  解霸的左右聲道設定好像也沒有什麼書籍介紹如何實現,實際上我們可以底層函式mciSendString,不過好像只對Wav,Mid等檔案有效.比如說左聲道設定:
mciSendString('set all audio all off',nil,0,Handle);
mciSendString('set all audio left on',nil,0,Handle);
  先把所有聲道關閉,然後開啟左聲道.如果你設計過,會發現有些防火牆也是這樣的:先關上所有埠,然後開啟常用的埠.注意:因為這裡呼叫了多媒體方面的API,所以程式必須加上MMsystem這個單元,否則將無法編譯.
  還有一個難點就是如何實現全螢幕播放.可能讀者會說:先把Form的BorderStyle動態設定為BsNone,再把Form的tate:=wsMaximized不就行了嗎?呵呵,是嗎?你試試看.結果播放螢幕的影片不見了.只看到一個光禿禿的面版.解決的方法是用API函式:
SetWindowLong(Handle,GWL_STYLE,GetWindowLong(Handle,GWL_STYLE) and (not WS_CAPTION));
  動態把視窗標題欄隱藏起來,再最大化.另外,為了保持視窗最大化後播放的尺寸仍然保持跟視窗大小融合,必須在視窗的OnResize事件中寫上MediaPlayer1.DisplayRect:=Panel1.ClientRect;另外,程式中還有"彈出CD-ROM",檔案拖放,音量控制等功能,讀者可自行參考程式碼,均附了註釋.
  實際上,我們上面的程式已經是一個功能比較完善的"多媒體播放器"了,下面我們就來新增我們的"網路播放"功能.
  先來熱熱身.
  大家知道,區域性網中大家互相訪問對方共享的資料夾時,可以直接在IE的位址列輸入如"機器名共享名"形式來開啟.比如說電腦Boy的共享資料夾mpgfile下有一個MPG檔案Andy.mpg,則平時我們就可以用"BoympegfileAndy.mpg"來開啟它.聰明的讀者可能已經想到,把這個名稱傳給播放器不就可以播放了嗎?對!我們的程式原理是這樣的:甲機播放影片檔案時,動態把檔案所在目錄"隱形"共享,並開啟一個Socket服務進行,當客戶Socket連線時把檔案完整的路徑和名稱傳送過去,客戶機取得名稱後賦給Mediaplay控制元件的Filename即可進行播放.
  但是現在問題又來了:
  一:如何實現"動態共享"?你總不能叫自己去擊滑鼠共享吧?
  二:如何實現"隱形共享"?這裡的"隱形"包括兩方面:比如說Boy共享了一個資料夾,那麼必須做到同一個區域性網的使用者開啟"網路上的芳鄰"時看不見該資料夾.另外,使用者在Boy上共享的資料夾擊滑鼠右鍵的"共享"一項裡看不到該資料夾共享.
  共享資料夾可以透過修改登錄檔,而且在DELPHI中操作登錄檔也很簡單.但是透過修改登錄檔實現共享必須在電腦重新啟動後才生效,即使你用API向廣播登錄檔內容已經改變的訊息也無效.但是為什麼Windows系統本身可以實現動態共享?它肯定呼叫了什麼東西.是什麼呢?原來在下它呼叫了SVRAPI.DLL中的一個函式ShareAdd,在NT/2000下則是NETAPI32.DLL.其實有很多所謂的"系統",比如說在Win9x下動態隱藏自己的功能就是系統自己本身用的用來執行某些系統程式的功能,而不是什麼漏洞.只不過是不公佈,後來有人發現了才叫"漏洞".跟蹤系統和分析系統可以讓你跟系統更加靠近.因為網路共享這個不是我們的主題,所以下面只給出實現的單元My_Share(見),感興趣的朋友可自行翻閱相關資料.呼叫規則如下:
刪除一個共享:DeleteShare(nil, Pchar(共享名稱));
新增一個只讀共享:
ShareRe(nil, pchar(路徑), Pchar(共享名稱), Pchar(共享說明),STYPE_DISKTREE,SHI50F_RDONLY,'','');
新增一個完全共享:
ShareResource(nil, pchar(路徑), Pchar(共享名稱), Pchar(共享說明),STYPE_DISKTREE,SSHI50F_FULL,'','');
  好,第一個問題解決了,下面來解決第二個.我也不想浪費納稅人的金錢了.具體方法如下:
一:新增一個引數SHI50F_SYSTEM,這樣一來在共享的資料夾擊右鍵的"共享"裡面就看不到自己的資料夾共享了.
如:ShareResource(nil, pchar(路徑), Pchar(共享名稱), Pchar(共享說明), STYPE_DISKTREE, SHI50F_RDONLY or SHI50F_SYSTEM, '', '');
二:共享資料夾時在共享名稱後面加上一個$符號,這樣一來開啟"網路上的芳鄰"就看不見共享的資料夾了,但是還是可以訪問.
如:BoyMyfile$
  好,到這裡我們的具有"網路播放"功能的播放器就完成了.程式程式碼很粗糙,沒有作過多容錯檢查,請讀者自行完善.另外,在程式中檔案進度的拖放我們用的是Delphi自身帶的TrackBar控制元件,所以在播放時有時會出現稍微短暫的停頓,建議讀者改用其它控制元件比如說Trackbar95.為了功能的完整性和照顧沒有第三方控制元件的讀者,我們這裡保留了該控制元件.
補充:
1:本程式在P第二版+100M區域性網上透過.
2:本程式可以改進的地方:不用Socket控制元件改用UDP來廣播,實現不用輸入對方完全"傻瓜式"網路播放.或者用一臺電腦做,共享多個檔案供客戶端有選擇的播放.實驗證明:在100M區域性網上一個檔案可以同時供7-8個使用者同時播放而速度無停滯.
3:真正的"網路播放"一般是採用傳輸流來實現,具體程式碼可到我站點.

★作者:

陳經韜

430074湖北省武漢市武昌民院路湖北經濟管理大學計算機系(本)9801班
Home:
E-: Lovejingtao@21.cn.com  

     ©CopyRight 2000-2001


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-992506/,如需轉載,請註明出處,否則將追究法律責任。

相關文章