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