大家好,今天我們要開始講解Screen Saver Maker最關鍵(也是我最頭痛)的圖形特效部分,
圖形特效主要是由Bitblt這個API的加強版StretchBlt來製作的,它與Bitblt唯一的不同點
在於對目標圖像的控制,使用Bitblt的時候,你所能選擇的是要貼上的圖形來源大小及位置和
目標的座標位置,在使用StretchBlt時,你則可以連貼上的大小一起控制,並且利用正負號的轉
換作出翻轉的效果,不過作者的功夫還不到家,尤其是一些數學概念也不好,導至Ver0.9的運算
上有許多無效的結果,不過在Ver0.91已經做了修正,現在我會分別對Ver0.9及Ver0.91做說明,
希望你們能從我的錯誤中得到一些啟示,不要再犯我這種烏龍錯誤了! 首先要從由左至右、由右至左、由上至下、由下至上四種表現方式做起,這四種方式的原理其 實沒有什麼不同,只要推出一種,其它的也就知道怎麼做了,我們就挑由右至左來說明,首先我 要考慮的是貼圖方式,最簡單的方式如下 以For迴圈,將貼上的圖形範圍遞增,像這樣 這種方法理論上雖然沒有錯...但是!!當作者使用較大的圖檔測試時卻發生了嚴重的閃爍, 因此,這個方式-不可行!! 作者因此換了一種方式,作者猜想,可能是因為圖檔處理的範圍越來越大,清除重繪的地方也 跟者變大,程式更換畫面的速度又快,程式不及處理才會造成這種情形,所以作者換了下面這種方法 依然使用For迴圈處理,但把圖形分成n等份,每次只貼n分之一的圖 如此一來,程式的負擔就應該可以減輕很多了,一試之下,效果還差強人意,至少還在可接受的 範圍內,因此就用這個方法來做了,但是....在作者又多試幾個檔案後發覺,當某些圖檔( 選擇了自動縮放圖形時)載入時,在拼湊圖形時,中間的接縫會有明顯的紋路產生,至於會產生紋 路的原因在於座標值捨去小數點之後的進位問題,這一點,老實講,作者學藝不精,試的出來怎 麼做結果正確,但是原理實在不知道該怎麼解釋才對...為了不誤人子弟,只好讓你們自己來看了 ,(所以說我最討厭這一段了!!每次都要想半天....)總而言之,貼圖的原理如上面所說, 接下來就看你們自己去融會貫通了,接者來看程式 |
Sub tmrShow_Timer()
這裡做的就是貼圖的動作,StretchBlt的用法和BitBlt的用法差不多,只是多了兩個參數指定目標 貼圖的大小,其餘的使用方式沒有不同。由左至右的表現方法是把來源圖型分為(來源圖形寬度/5) +1等份(就是將圖型切成一張張5Pixel大小的圖),得到的就是EffectTime特效需執行的次數,而圖型 貼圖的座標及寬度則在LoadImagePicture時就算出來了,忘記的再回頭看看,因此每次貼圖時的 寬度就可以推出來為(DestWidth / EffectTime),為什麼不是和來源圖形一樣是5Pixel呢?因為 使用者如果點選了圖型自動縮放,那麼貼在目標圖型的寬度就可能要放大或縮小了,因此我們要 再計算一次才會得到正確的值。X座標的位置則是(DestLeft(X座標的原點) + (DestWidth / EffectTime) * (loopNo - 1)(目前貼圖的最後位置)) 其中loopNo就是執行的次數,例如圖型為100*100,假設分為十等份,不考慮原點問題,每次的計算結果如下 Step1.(0)+(100/10)*(1-1) --> 0 貼圖範圍1-10 Step2.(0)+(100/10)*(2-1) --> 10 貼圖範圍11-20 Step3.(0)+(100/10)*(3-1) --> 20 貼圖範圍21-30 Step4.(0)+(100/10)*(4-1) --> 30 貼圖範圍31-40 Step5.(0)+(100/10)*(5-1) --> 40 貼圖範圍41-50 Step6.(0)+(100/10)*(6-1) --> 50 貼圖範圍51-60 Step7.(0)+(100/10)*(7-1) --> 60 貼圖範圍61-70 Step8.(0)+(100/10)*(8-1) --> 70 貼圖範圍71-80 Step9.(0)+(100/10)*(9-1) --> 80 貼圖範圍81-90 Step10.(0)+(100/10)*(10-1) --> 90 貼圖範圍91-100 高度和Y位置則可以不用計算了,因為它是固定貼在DestTop及取DestHeight的高度, 不會有變化的,相信有人看到這裡一定會有疑惑,為什麼上面是這樣計算,但是程式裡 實際的算式卻有+2或-1等額外的計算呢?這就是為了解決上面所說的紋路的問題,在程 式上所做的計算補償,如此一來,顯示出來的圖型才不會有我所說的紋路產生, 但是問題不是這樣就解決了,依圖形的寬度,你可能會發生最後一次貼圖的範圍超出螢幕的 計算結果(例如螢幕寬度為800,X座標為798,貼圖範圍為799-808),但是StretchBlt不接受 這一種參數,會使得最後一次貼圖無效,在畫面上留下一片空白的地方,於是在最後,我會 將整張圖型重新貼上,這樣才會貼滿整個該顯示的畫面,程式才算完成,在這裡可能會有人 注意到,我把Form的AutoRedraw設為True才貼圖上去,這一點則是為了文字顯示時的透空顯示 ,Label是把物件蓋上去後再重會底層的圖形,如果沒有將AutoRedraw設為True,那麼它就會 取原來的黑色背景做為底層的圖案,就會變成黑黑的一塊很難看囉!
-_- 好吧!好吧!你們手上都拿到Ver0.91的版本了吧?這種方法的確還是有許多缺點,
首先就是最後一次貼圖可能發生失敗的問題,雖然我使用了原圖重貼的方式解決了,但是你
應該會注意到,有些圖型會發現明顯的閃動,這是因為補償計算所引發的問題,......我的天
啊!我到底該怎麼解釋..........總之呢!在Ver0.91版我改變了計算的方式,讓最後一次執行
仍然可以順利的貼圖成功,這樣我就沒有必要在將原圖重新貼上去,圖形也就不會發生奇怪的
閃爍了!另外,基於這個原因,我把Form的AutoRedraw直接設為True了,這樣顯示文字才不會
出錯,想更進一步了解的可以把Ver0.91 Print寫檔動作的註解拿掉,宣告一個檔名,將貼圖的
變化記錄下來,Ver0.9也做相同的動作,兩個值比較一下,應該可以比較容易了解,Ver0.91的
程式碼如下,你們可以參考一下,只要弄懂了這一部份,其它三個由左至右、上至下、下至上,
也就可以輕鬆帶過了,這一次的講解就到此為止囉,下一次為你解釋其它三種特效的原理....
頭好痛啊!!!
後記:
回到VB教學教室
| |