現在我們要開始說明動作視窗了!不過在這之前,要先補講一段設定的視窗,這個視窗就是用
來將這個螢幕保護程式設為預設的螢幕保護程式以及這個螢幕保護程式所使用的設定檔為何?
你可以打開frmAdvSetUP的視窗看一下。
不過這個設定視窗功能有點不足,只能設定這個螢幕保護程式,不能取消或設定其它的螢幕保
護程式,下一版會加強它的功能的。這個視窗還有一個測試螢幕保護程式的功能,不過這牽涉
到動作視窗,等會再回頭看,這裡要看的只有兩個地方,首先是Form_Load
Private Sub Form_Load()
Dim dx%, dy%
'Set From Position, Check ADVSET.INI , Get ADVSET.INI's Data
dx% = (Screen.Width - Me.Width) / 2
dy% = (Screen.Height - Me.Height) / 2
Me.Move dx%, dy%
If Dir$(workPath$ & "ADVSET.INI") <> "" Then
If GetIntFromIni("START", "ACTION", -1, workPath$ & "ADVSET.INI") <> -1 Then
chkScrSet.Value = GetIntFromIni("START", "ACTION", 0, workPath$ & "ADVSET.INI")
txtDelayTime.Text = GetStringFromIni("START", "DELAYTIME", "1", workPath$ & "ADVSET.INI")
txtProFileName.Text = GetStringFromIni("START", "PROFILE", "", workPath$ & "ADVSET.INI")
End If
End If
End Sub
在這裡,我是將設定放在ADVSET.INI這個檔案裡,先Check一下有沒有資料,有的話就將資料讀出
來,接者就是等使用者設定完畢按下確定的時候了
Private Sub cmdOK_Click()
Dim rBuf$, ShortName$, rc&
'1.Check Set Value Error,If Error Flase Then Write Data To ADVSET.INI
'2.If Scr File Not Find then Copy Scr File
'3.Set Screen Saver TimeOut,Check OS ver,Set Screen Saver Active
If CInt(Val(txtDelayTime.Text)) <= 0 Then
MsgBox "等候時間不可為零值", vbOKOnly Or vbInformation
Exit Sub
End If
If Trim$(txtProFileName) = "" Then
MsgBox "必須指定使用的設定檔", vbOKOnly Or vbInformation
Exit Sub
End If
If Dir$(txtProFileName) = "" Then
MsgBox "找不到您指定的設定檔", vbOKOnly Or vbInformation
Exit Sub
End If
If Dir$(workPath$ & "ScrMaker.Exe") = "" Then
MsgBox "找不到預設的執行檔名!請確定目前執行的檔案名稱為 ScrMaker.Exe,否則無法正常的設定螢幕保護程式", vbOKOnly Or vbInformation
Exit Sub
End If
rBuf$ = workPath
WriteStringToIni "START", "ACTION", Trim$(Str$(chkScrSet.Value)), workPath & "ADVSET.INI"
WriteStringToIni "START", "DELAYTIME", txtDelayTime.Text, workPath & "ADVSET.INI"
WriteStringToIni "START", "PROFILE", txtProFileName.Text, workPath & "ADVSET.INI"
If Dir$(workPath$ & "ScrMaker.Scr") = "" Then
FileCopy workPath$ & "ScrMaker.Exe", workPath & "ScrMaker.Scr"
End If
SystemParametersInfo SPI_SETSCREENSAVETIMEOUT, CLng(Val(txtDelayTime.Text)) * 60, 0&, SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE
Dim ver As OSVERSIONINFO, hkey As Long, Length As Long
ver.dwOSVersionInfoSize = Len(ver)
GetVersionEx ver
ShortName = String(LenB(workPath & "ScrMaker.Scr"), Chr$(0))
rc = GetShortPathName(workPath & "ScrMaker.Scr", ShortName, Len(ShortName))
If ver.dwPlatformId = VER_PLATFORM_WIN32_NT Then 'Windows NT
RegOpenKey HKEY_CURRENT_USER, "Control Panel\Desktop", hkey
RegSetValueEx hkey, "SCRNSAVE.EXE", 0, REG_SZ, ByVal (winPath$ & "ScrMaker.Scr"), Length
RegCloseKey hkey
Else 'Windows95 / 98
WriteStringToIni "boot", "SCRNSAVE.EXE", ShortName$, winPath$ & "system.ini"
End If
SystemParametersInfo SPI_SETSCREENSAVEACTIVE, CLng(True), 0&, SPIF_UPDATEINIFILE Or SPIF_SENDWININICHANGE
MsgBox "設定成功!", vbOKOnly Or vbInformation
Unload Me
End Sub
首先要Check等待時間和設定檔的欄位的資料是否正確,再Check指定的設定檔是否存在(
如果使用者不存心搗蛋其實是不可能不存在的,欄位的KeyIn我都限制住了),最後在Check執
行檔在不在,因為等一下需要知道檔名才能指定啟動的螢幕保護程式,我又懶得去試怎麼得到
自己的執行檔名(app.ExeName的檔名似乎不對...?),所以乾脆限制使用者不能變更這個執行
檔的名稱比較快囉... :p ,確定沒有問題後,我們再將設定值寫入檔案中,再將目前的執行檔
Copy成.Scr的螢幕保護程式,接者使用SystemParametersInfo這個API來改變螢幕保護程式的啟
動時間,這個API裡所傳遞的時間單位為秒,所以請將時間再乘上60才是正確的值。
接下來再將ScrMaker.Scr設為預設的螢幕保護程式,但是,在Windows NT和Windows95/98裡,
設定螢幕保護程式的方式並不一樣,所以我們再使用GetVersionEx這個API來取得Windows的版本,
再依其版本將ScrMaker.Scr指定為預設的螢幕保護程式,這裡要注意的是,傳入的螢幕保護程式
檔名必須為短檔名的格式,請轉成短檔名之後再執行,最後再呼叫一次SystemParametersInfo
,將螢幕保護程式啟動就行了。
Ver1.0 Update:
Ver0.9的螢幕保護程式稍嫌粗燥,功能方面並不完備,因此,在Ver1.0 Beta作了不少修改,
加入了完整的管理功能,變動的幅度不小,但整體來說,其實還是一樣,多了一些較細微的設定而已,
先講講功能上有那些變動,首先,我將整個設定視窗劃分為兩大區,一區是Screen Saver Maker的管理區,
另一區則是既有的螢幕保護程式的管理區,而Screen Saver Maker則又劃為SPM,SPC兩個部份,另外,
還加入了Esc鍵跳出的功能及密碼管理。現在讓我們重頭看整個程式,我們一樣從Form_Load來看起
Private Sub Form_Load()
Dim dx%, dy%, rBuf$, i%, ShortName$, rc&, hkey&
'Set From Position, Check ADVSET.INI , Get ADVSET.INI's Data,Get All Screen Saver Data
'略
GetScrData這一段副程式是用來找出我們的電腦裡有那些.Scr的螢幕保護程式,
並將其List在lstListSCR裡,這一段比較簡單,我就省略不講了,不過,我搜尋的
範圍僅限於Windows及System的目錄,這一點請注意
Call GetScrData
If Dir$(workPath$ & "ADVSET.INI") <> "" Then
i = GetIntFromIni("START", "ACTION", -1, workPath$ & "ADVSET.INI")
首先,因為設定劃分為兩大區的緣故,我們必須Check ADVSET.INI的內容,
以確定要載入的資料及控制項Enabled的控制,先確定是否是將Screen Saver Maker設定為啟動
如果是啟動的話,在讀取出各項資料,去設定各控制項,在讀取及設定時有幾點要注意的,
第一點是check box這個控制項,在你改變check box的value時,也會引起Click的事件
所以,如果你在Click如果有做任何事的話,就要想辦法把這一段避過去,我是使用chkSkip的變數,
藉此來判斷到底要不要執行Click事件的程式,接者,我們要判斷目前有沒有設定密碼,如果有
就必須為chkSetPwd的控制項打勾(value=vbChecked),判斷的方法很簡單,從登錄檔的資料下手,
HKEY_CURRENT_USER\Control Panel\Desktop\ScreenSaveUsePassword
只要讀取這個Key的值就可以了,如果等於1就是有設定密碼
另外將setPasswdFlag設為WN_SUCCESS,這個變數是用來設定有沒有設定密碼的
後面會做詳細一點的說明
最後,我們再從載入的專案檔副檔名判斷要將那些控制項Enabled
並呼叫EnabledControl()來執行,並設定setLoadType,讓我們知道目前載入的設定為何
LOAD_SPM SPM專案檔
LOAD_SPC SPC專案檔
LOAD_NONE 一般的螢幕保護程式
If i <> 0 And i <> -1 Then
chkSkip = 1
chkScrSet.Value = GetIntFromIni("START", "ACTION", 0, workPath$ & "ADVSET.INI")
chkSkip = 0
chkEscQuit.Value = GetIntFromIni("START", "ESC_QUIT", 0, workPath$ & "ADVSET.INI")
txtDelayTime.Text = GetStringFromIni("START", "DELAYTIME", "1", workPath$ & "ADVSET.INI")
rBuf$ = GetStringFromIni("START", "PROFILE", "", workPath$ & "ADVSET.INI")
chkSetPwd.Enabled = True
RegOpenKey HKEY_CURRENT_USER, "Control Panel\Desktop", hkey
RegQueryValueEx hkey, "ScreenSaveUsePassword", 0, REG_DWORD, rc, 4
RegCloseKey hkey
If rc = 1 Then
chkSetPwd.Value = vbChecked
setPasswdFlag = WN_SUCCESS
Else
chkSetPwd.Value = vbUnchecked
setPasswdFlag = 1
End If
If UCase$(Right$(rBuf$, 3)) = "SPC" Then
Call EnabledControl(SCRMAKER, LOAD_SPC)
Call GetSPCData(rBuf$)
txtSPCFileName.Text = rBuf$
Else
Call EnabledControl(SCRMAKER, LOAD_SPM)
txtProFileName.Text = rBuf$
End If
Else
Call EnabledControl(NORMAL_SCR, LOAD_NONE)
End If
Else
Call EnabledControl(NORMAL_SCR, LOAD_NONE)
End If
接下來,如果是載入Screen Saver Maker的專案檔,就可以離開這一段程式了
如果是載入一般的螢幕保護程式的話,則必須利用API找出ScreenSaver的名稱
及等待的時間,再設定到相對應的控制項即可
SPCUpdate = False
If setLoadType <> LOAD_NONE Then
tmpScrFileName = ""
Else
RegOpenKey HKEY_CURRENT_USER, "Control Panel\Desktop", hkey
RegQueryValueEx hkey, "ScreenSaveUsePassword", 0, REG_DWORD, rc, 4
RegCloseKey hkey
If rc = 1 Then
chkSetPasswd.Value = vbChecked
setPasswdFlag = WN_SUCCESS
Else
chkSetPasswd.Value = vbUnchecked
setPasswdFlag = 1
End If
tmpScrFileName = GetStringFromIni("boot", "SCRNSAVE.EXE", "", winPath$ & "system.ini")
If tmpScrFileName = "" Then
lstSCRList.Selected(0) = True
txtDelayTime.Text = "1"
Else
For i = 0 To UBound(ScrFileName)
ShortName = String(LenB(ScrFileName(i)), Chr$(0))
rc = GetShortPathName(ScrFileName(i), ShortName, Len(ShortName))
ShortName = Left$(ShortName, InStr(1, ShortName, Chr(0)) - 1)
If tmpScrFileName = ShortName Then
lstSCRList.Selected(i + 1) = True
Exit For
End If
Next i
If i = UBound(ScrFileName) + 1 Then
lstSCRList.Selected(0) = True
txtDelayTime.Text = "1"
Else
SystemParametersInfoByRef SPI_GETSCREENSAVETIMEOUT, 0, rc, 0
txtDelayTime.Text = rc \ 60
End If
End If
End If
End Sub
接下來程式的其它部份我不打算詳細解釋,只要稍微研究一下,應該就沒有問題了,
但有兩點還是要說明一下
第一個是SPC的檔案格式,SPC - Screen saver maker Program file Colletcion
顧名思義,所謂SPC的檔案,就是SPM專案檔的集合,也就是說,一個SPM檔雖然有者100張
的設定限制,但使用SPC檔,就可以設定播放100,200甚至上千張的螢幕保護程式,
可以讓你更自由的設定。不過我好像忘記公佈它的檔案格式了,所以這邊補講一下
'[This is Screen saver maker Program file Colletcion]
'[Please Don't Modify This File]
'[請不要任意變更此檔案的內容,否則可能造成系統錯誤]
SUM=002
C:\MYWORK\Screen Saver Maker\Di Gi Charat.SPM
C:\WALL\OrangeRoad\Orange Road.SPM
前三行是慣例的檔頭宣告,沒什麼用....
接者是SUM,代表這個SPC檔包含幾個SPM檔,這樣才知道要宣告多大的陣列,
接者便是SPM檔的完整檔名,但是要注意一點,SPM檔不可以超過999個,不然會
發生錯誤的
第二點是密碼的設定,在Windows的螢幕保護程式管理中,你可以試試以下的動作,
先隨便選取一個螢幕保護程式,然後將密碼設定勾選起來,什麼都不要做,按下確定,
那麼,你會發覺,當螢幕保護程式Run起來時,密碼保護也會跟者啟動的,但這裡就有
一點不大好的地方了,User雖然勾選了密碼保護,但卻沒有設定密碼(如果你勾選了
密碼保護,也叫出設定視窗,但沒有設定密碼按下取消也會有同樣情形),那我們還是
應該設定嗎?我就發生過這種情形,當密碼輸入框跑出來時,我壓根忘了我那800年前
設定的密碼為何了!所以我在這裡有加一些判斷,只有當你確實有設定過密碼時,我才會
為你設定密碼保護的
接下來要講解動作視窗了,關於圖型的一些處理呢,你的數學最好要好一點,才可以寫
出一段有效率又精緻的畫面處理程式,因為我自己的數學很菜,對於圖型處理實在想不
出什麼比較炫又有效率的處理方法,所以本程式的變化也只有少少的七種而已囉
(Ver1.0增加到15種囉 ^_^)!如果有那一位網友對這一方面有心得的話,歡迎一起討論交流!
首先要作的是最基本的處理,請將你的frmActive打開,當使用者對鍵盤或滑鼠有所動作的
時候,我們必需將視窗于以關閉,所以我們在Form_KeyDown、Form_MouseDown做Unload Me
的處理,唯一的例外是MouseMove,當你的Form啟動時,同時也會觸發到MouseMove的事件,
因此我們設定一個MouseX,MouseY的變數,在Form_Load時將值設為-9999當第一次觸發事件
時,再將mouseX、mouseY設為目前的位置,在下一次觸發事件時就可以知道Mouse移動了,我
們就可以將Form Unload了。
Private Sub Form_MouseMove
If mouseX = -9999 Then
mouseX = X
mouseY = y
Else
If mouseX <> X Or mouseY <> y Then Unload Me
End If
End Sub
接下來看一下Form_Activate的部份
Private Sub Form_Activate()
Dim rc As Long
'Hide Mouse Cursor,Set Window TopMost,Reset Midi and Wave Flag
rc = ShowCursor(False)
rc = SetWindowPos(Me.hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE)
ReplayMidiFlag = 0
ReplayWavFlag = 0
frmActive.cmdStart.Value = True
End Sub
首先我們先用ShowCursor這個API來將滑鼠游標隱藏起來Form_Activate,ShowCursor的使用很簡
單,傳入False就會隱藏滑鼠游標,傳入True就會將游標顯示。接者我們呼叫ShowWindowPos來將
螢幕保護程式的動作視窗設定為最上層顯示,第一個參數是Window的hWnd,第二個參數是指定
Window的階層,這裡傳入的是HWND_TOPMOST,代表永遠在最上層,接下來四個參數分別指定
Window的X、Y座標及長寬,不過在這裡我們不準備作任何變動,所以傳入0即可,最後一個參
數則傳入你所要對Window作的動作,我們不打算作任何動作,所以傳入SWP_NOMOVE(不移動)
、SWP_NOSIZE(不改變大小),最後將參數初始化後,將cmdStart.Value設為True(相當於按
下cmdStart這個按鍵),接者來看這一段程式
Private Sub cmdStart_Click()
'Check ActiveType
'1.PreView -> Load Picture File then GetEffectTime then Show Picture
'2.Start -> Get Default Screen Saver's SPM File,Goto tmrActive
'3.Program Test -> Get Define SPM File, Check SPM Error,Goto tmrActive
If ActiveType = Active_PicPreview Then
Call LoadImagePicture(frmScrSetUP.chkFullPic.Value)
ElseIf ActiveType = Active_Start Then
Call LoadSPMData("")
tmrActive.Interval = 250
tmrActive.Enabled = True
Exit Sub
ElseIf ActiveType = ProgramTest Then
Call LoadSPMData(ProFileTemp$)
If ActiveType <> DefaultAction Then ActiveType = Active_Start
tmrActive.Interval = 250
tmrActive.Enabled = True
Exit Sub
End If
picPreView.AutoRedraw = True
Call GetEffectTime
tmrShow.Enabled = True
End Sub
在執行動作視窗時,我把它劃分為四種情況
1.預覽圖片時
2.螢幕保護程式啟動時
3.預覽螢幕保護程式時
4.當執行發生錯誤時(例如設定檔有問題時)
針對這四種狀況再作不同的處理,在這裡我設定了一個全域變數ActiveType來儲存目前的狀態,
現在我們先從第一種情形,預覽圖片開始看起,如果是預覽圖片的話(這個功能在設定視窗中,
用來查看目前設定圖檔的顯示效果),要做的只有將圖片依指定的顯示方式顯示出來就可以了,
(這裡我沒有將音樂播放和文字顯示的功能加入,純粹是個人感覺而已,如果你認為加入這些功
能比較好的話,在後面介紹過音樂播放和文字顯示功能的作法後,你可以自己加入看看),首先
我們要先呼叫LoadImagePicture這段副程式(看Active_PicPreview),這個副程式要傳入一個參
數,代表是否要將圖型自動縮放到與螢幕同長寬,先來看程式碼
Private Sub LoadImagePicture(FullType As Integer)
Dim i As Integer
'1.Load Picture File Set the prePicture Width & Height
'2.Check Picture's ShowType (Full or Normal) , Get Source & Target's Width,Height,Left,Top
'3.If Error Then Set loopNo = 0
On Error GoTo ImageError_Handle
picPreView.Picture = LoadPicture(picName)
preWidth = DestWidth
preHeight = DestHeight
If FullType = vbChecked Or (picPreView.ScaleWidth = screenWidth And picPreView.ScaleHeight = screenHeight) Then
SrcTop = 0
SrcLeft = 0
SrcWidth = picPreView.ScaleWidth
SrcHeight = picPreView.ScaleHeight
DestTop = 0
DestLeft = 0
DestWidth = screenWidth
DestHeight = screenHeight
picCut = False
Else
If picPreView.ScaleWidth > screenWidth Then
If picPreView.ScaleWidth - screenWidth > 1 Then
SrcLeft = (picPreView.ScaleWidth - screenWidth) / 2
Else
SrcLeft = 0
End If
SrcWidth = screenWidth
DestLeft = 0
DestWidth = screenWidth
Else
SrcLeft = 0
SrcWidth = picPreView.ScaleWidth
If screenWidth - picPreView.ScaleWidth > 1 Then
DestLeft = (screenWidth - picPreView.Width) / 2
Else
DestLeft = 0
End If
DestWidth = picPreView.ScaleWidth
End If
If picPreView.ScaleHeight > screenHeight Then
If picPreView.ScaleHeight - screenHeight > 1 Then
SrcTop = (picPreView.ScaleHeight - screenHeight) / 2
Else
SrcTop = 0
End If
SrcHeight = screenHeight
DestTop = 0
DestHeight = screenHeight
Else
SrcTop = 0
SrcHeight = picPreView.ScaleHeight
If screenHeight - picPreView.ScaleHeight > 1 Then
DestTop = (screenHeight - picPreView.ScaleHeight) / 2
Else
DestTop = 0
End If
DestHeight = picPreView.ScaleHeight
End If
picCut = True
End If
loopNo = 1
Exit Sub
ImageError_Handle:
loopNo = 0
Resume QuitImageError
QuitImageError:
Exit Sub
End Sub
首先我們將User指定的圖檔載入picpreView這個Picture Box中,picName是個全域變
數,當你在設定視窗預視縮圖時便會載入,因此在這個情況下是不會有問題的,不過
,由於我在Run螢幕保護程式時也會用到這段程式來作圖檔的處理,所以有可能發生要
載入的圖檔錯誤的問題,因此我在這還是作了一段錯誤處理,萬一有任何錯誤,我會
將loopNo這個值傳回0,在後段秀圖的處理時我就會Show出錯誤訊息讓User知道。
接下來我們來Check一下圖檔的情況,因為我們不是直接將圖Show在螢幕上而已,
還要做一些特效的處理,所以我會用到StretchBlt這個API來作顯示圖片的動作,
因此這裡我們要算出圖檔實際要Show在螢幕上的長寬,以及X、Y座標值,還有我們實際
上在這個圖檔所要顯示的範圍及相對座標的X、Y值來作為StretchBlt的參數,
如果圖檔是指定縮放成與螢幕同長寬的話,那麼一切都很簡單,要取用的圖型範圍就是
整張圖,顯示範圍就是整個螢幕,X、Y座標則為0。如果使用者沒有選取圖型縮放功能
的話,情形就稍微麻煩一點了,我們要判對出整張圖在螢幕中的中央位置,將顯示的圖
型做上下左右的置中處理,當然,你可以啥都不管,將圖往0,0的位置一丟,有沒有對齊
是他家的事,不過...還是稍微花點功夫吧!計算的原理稍微說明一下,首先我們先比對
一下圖檔的width與Screen.Width(別忘了要轉成相同的單位計算),如果圖檔比螢幕大
,我們就算出它在螢幕的中央位置X座標(兩者寬度相減除二即可),它的顯示寬度則與
螢幕同寬,圖檔要截取的圖檔範圍亦與螢幕同寬。如果圖檔比螢幕小呢?只要將算式反
過來,就可以取得顯示的X座標位置了。顯示的寬度則與圖檔同寬,接者Y座標及顯示高度
等也就可以求出來了,接者我們將loopNo這個變數設為1,代表載入圖檔成功(loopNo
也被我用來作一個計算次數的變數,不要搞錯了,這裡相當於在作歸零的動作),
如果我們顯示的不是圖檔的全圖的話,我們就將picCut設為True,這在後面顯示圖片時會用到,
接者再回到cmdStart_Click這段程式,載入圖檔完畢後,我們將picPreView.AutoRedraw
設為True,這個是為了StretchBlt的使用,picPreView的Visible屬性我們是設為False的
,但是這樣一來StretchBlt也就讀不到picPreView實際載入的圖檔了,將AutoRedraw設為
True後,它就會將目前顯示的圖存入記憶體中,使用StretchBlt時就會讀取到我們載入的
圖型了。接者再呼叫GetEffectTime,GetEffectTime非常單純,它只是根據你指定的特效
來指定你執行完這段特效所需的執行次數等相關資料,大略來看一下這段程式
Private Sub GetEffectTime()
'Select Effect Type , Set EffectTime & tmrShow's Interval
If EffectBuffer = RANDOM_SELECT Then
EffectBuffer = GetRandomNo(EFFECT_SUM) - 1
If ActiveType = Active_PicPreview Then RandomSelectFlag = True
ElseIf EffectBuffer > EFFECT_SUM Then
EffectBuffer = GetRandomNo(EFFECT_SUM) - 1
If ActiveType = Active_PicPreview Then RandomSelectFlag = True
End If
Select Case EffectBuffer
Case LEFT_TO_RIGHT, RIGHT_TO_LEFT
'略
End Select
End Sub
這一段程式就如剛才所說的,只是設定一些執行時的相關資料而已,至於這些值,都是我自己
經過數次執行之後而得出的值,並沒有什麼理論依據,覺得表現不如你意的,可以再更改看看
,應該還可以有更好的表現的。這一段有一點要注意一下的是,圖形的表現方法中,有一個選
擇叫作亂數選擇,因此在設定資料之前,我們如果檢查出EffectBuffer(我用來儲存目前這張
圖檔特效的變數)等於亂數選擇特效的話,就利用GetRandomNo這個副程式亂數選出一個表現的
特效方法,但是這個變數(EffectBuffer)同時也用來儲存設定視窗的設定檔的特效變數,
因此,如果目前的表現方式是預覽圖片的話(Active_PicPreview),我們就設定一個變數
RandomSelectFlag為True,在Unload Form時將EffectBuffer設回RANDOM_SELECT,這樣設定視窗
的設定值才不會變。
到此為止,顯示圖片的準備工作算告一段落了,下次我們再來講顯示圖片的處理過程!
Ver1.0 Update:
在Ver1.0程式做了一些小小的修改,一個是EscQuit的功能,讓使用者決定是否按下Esc鍵才
跳開程式,這一點沒有什麼技巧,設一個變數,讀取設定值再做一些檢查就可以了,
另一個則是密碼保護的功能,在離開Form之前,如果有設定密碼的話就要輸入正確密碼才可以離開,
當然,請記得Call API(ScreenSaverRunning....)讓Ctrl+Alt+Del無法使用才可以,不然就沒有任何意義了^_^,
程式如下,
Dim rc As Long
If ActiveType = Active_Start And isPassword = 1 Then
If VerifyScreenSavePwd(Me.hwnd) = False Then
Cancel = True
Exit Sub
End If
End If
isPassword是一開始時檢查登錄檔時取得的,如果是在Run螢幕保護程式,又有設定密碼的話,
我們就呼叫VerifyScreenSavePwd()來檢查密碼輸入,如果輸入正確就會傳回True,(這個函數
參考自
培基語言的璉璉,這是他辛苦找出來的函數,節省了我很多時間,在這邊謝謝他)
另外還有一個變化比較多的地方,就是圖型的展示方式,在前一版,當圖型大於螢幕範圍時,
你只有兩種選擇,第一個就是暴力式的把圖型設成與螢幕同長寬,再不然就是置中顯示,
但是這樣的功能顯然有點不夠用,如果圖型的長寬跟螢幕根本不成比例,如果圖型中央部份剛好
看不到圖型的精華部份,那~~~還能玩嗎...?所以我新增了幾種圖型的展示方法
圖型等比例縮放 - 以螢幕為邊界,將圖型等比例放大或縮小
將小圖型等比例放大顯示 - 以螢幕為邊界,只將比螢幕長寬小的圖型放大,其它圖型則置中顯示
將大圖型等比例縮小顯示 - 以螢幕為邊界,只將比螢幕長寬大的圖型縮小,其它圖型則置中顯示
Left-Top顯示,Right-Top顯示......這裡用圖示來說明,這幾種顯示方法其實和置中顯示並沒有什麼
不同,只不過我將圖型畫分為九個區域,讓使用者去指定要顯示的範圍而已,看看下面的圖示應該就可
以瞭解了

當然當我們劃分區域時不見得就會剛好劃的這麼好看,通常有些區域會有重疊的部份,這幾種顯示方法
和置中顯示比較起來,主要只是差在X,Y座標的算法而已,這一點就交由你們自己看了,比較需要說明
的是圖型放大縮小的部份,我們先想一想,為了能讓圖型放大縮小,所以我們必須將新的顯示範圍
換算出來,算出SrcWidth和SrcHeight、SrcLeft、SrcTop等,要算出這個其實並沒有太大的麻煩、比照設定
視窗,用For迴圈遞增或遞減長寬,一直到不超過螢幕的最大值即可推算出SrcWidth及SrcHeight了,
不過後來我不單純使用這個方法,為什麼呢?有興趣的可以自己修改試試,其實,主要是我的運算方法中,
有幾種特效的運算式並不適合套用到放大或縮小的情況,會產生很嚴重的鋸齒現像,所以我只好稍為
繞個遠路,先以最不會影響圖型的方式將圖型放大或縮小複製到另一個PictureBox,然後為了把程式碼
的變動減到最小,再把放大縮小後的圖型複製回原picPreView中,這過程裡面有兩點要注意
第一點是picture box的長寬,當你放大圖型時,你必須記得把picture box的長寬設成放大後的長寬,
如果你沒有設定,到時候執行特效時呼叫的API是沒有辦法順利複製picture box範圍以外的圖型的
第二點要注意的是,當我將圖型放大或縮小複製到另一個Picture Box時,為什麼我不直接將全圖複製過去?
而要以亂數顯示的特效方式複製?這一點我不曉得是不是Bug,當我將全圖以放大或縮小的方式複製時,
有些圖常常莫明其妙的出現條紋,屢試不爽,考量之下,只好以這種方法代替,這一點你最好也可以試試,
也有可能只是單純我的電腦有什麼問題,也可能是某種Bug
|