就Windows的螢幕保護裝置的設定功能來看,
一個螢幕保護程式簡單來說可以分成兩個部份,第一個是設定功能(設定值),
第二個則是實際執行時的畫面(預覽或實際執行)。
Window在設定或執行螢幕保護程式時其實就是直接叫出該程式執行而已
(螢幕保護程式其實就是副檔名為scr的執行檔)
而我們所寫的程式再依據這些參數作不同的對應。 Window傳遞的參數有下列幾種 /C 代表的是設定 /S 代表預覽或執行 /A 代表密碼設定 /P 代表小螢幕的預覽(就是顯示器-螢幕保護程式上方的小視窗) 那麼先看一下Screen Saver Maker的API.Bas程式碼 其中的Sub Main()註解為Check Command Word這一段
這個Sub Main()就是整個程式的起始點,這一段就是在分析所接收到的參數 再分別設定合適的變數,最後再Show出指定的From,其中密碼設定和小螢幕預覽的功能被我 取消了,密碼功能是我懶的作,小螢幕預覽則是嫌麻煩所以就不作了, 有興趣的人可以自己加上這些功能,小螢幕預覽的方法可以到王國榮老師的網站- 學VB找王國榮找尋。 最後的Case Else則是在對SPM檔Double Click和拖曳至程式時的處理,不過有些在Uninstall時的 處理我還沒想好,暫時算是試驗性質的功能而已 回頭再看一下整段程式
在Check Program Run Again裡所做的就是防止程式重覆執行的工作, 在一般的情況下,我們只要用App.PrevInstance就可以知道程式已執行,再將程式結束就可以了,而在這裡比較特殊的情況是-當我們已經叫出設定視窗時 使用者又執行一次設定的功能,我們當然也可以同樣的擋掉他的要求將程式關閉,不過比較好的方法是將設定視窗Show到 Desktop的最上層讓使用者直接使用,這樣才有User Friendly的感覺,程式是使用FindWindow和SetForegroundWindow 兩個API來作的,也許有人會用App.PrevInstance和AppActivate來作,不過當程式最小化時AppActivate不會把 程式自動最大化,所以我們還是稍微辛苦一點,用API來做囉。 這一段檢查的程序我把它寫成一段CheckUnique Function,以後要套到別的程式也方便使用, 讓我們來看一下這段程式
首先,先用FindWindow查看目前有沒有已執行中的程式視窗
在程式裡我是用lpWindowName來搜尋的,至於lpClassName則可以用vbNullString帶過, WindowName就是指視窗的Title,如果有找到指定的視窗,會傳回該視窗的hWnd, 否則傳回0,這邊有一點要注意的是,我們是用Title來搜尋視窗的,所以如果假設程式是 由frmScrSetUP起始的話,要記得將Form Caption設為空白,搜尋完畢後再設為原值, 否則會有錯誤。 如果傳回值為程式已執行,我們就呼叫ShowWindow顯示視窗,再呼叫SetForegroundWindow 將視窗置於Desktop的最上層,最後程式再依據CheckUnique的傳回值作對應的處理就可以囉! Sub Main()後面還有一小段程式 Get WorkPath和Get Window Directory 則是利用App.Path及GetWindowDirectory的API來取得目前工作目錄及Windows的路徑代入全域變數中, 方便以後程式利用。 在這裡要提一下,螢幕保護程式是不應該可以重覆執行的 (有兩個以上的執行體),看了10月號的PC HOME我才猛然想起來這個問題,他們也用VB6.0做了螢幕保護程式製作軟體, 但是有一個問題,程式會不斷的執行,到當掉為止,我當初也發生了類似的問題,後來才發覺有兩個Screen Saver Maker在執行, 這大概是因為,即使螢幕保護程式已開始執行,但Windows仍在偵測及計算KeyBoard和Mouse沒有觸發的時間,每隔N分鐘,又會呼叫一次螢幕 保護程式的原因吧!所以我後來才加寫這一段Check的,因此當執行設定視窗時,即使你N分鐘沒有動,螢幕保護程式仍然不會執行的(當你從控制台-顯示器-螢幕保護程式執行設定時), 不過,寫到這裡,我才又發現了一個問題,由於我製作這個程式,是將之作成Exe的執行檔,然後再自行Copy成另一個Scr檔,當你使用Exe檔執行設定時, 螢幕保護程式依舊會執行的,這又會引發另一個問題,當螢幕保護程式在設定視窗還存在的時候執行,O.K,這個問題還不大,但是當你在測試 螢幕保護程式呢?那就會發生兩個螢幕保護程式同時RUN的問題了,這樣雖然不會讓程式當掉,但是也是會對使用者造成困擾的, 那這要怎麼解決呢?嘿嘿,賣個關子,自己動動腦想一想喔!給點提示,在執行的時候,如果是啟動 螢幕保護程式的話,就用FindWindow...... Ver1.0 Update: 這裡其實還有一個小問題沒有解決,那就是,當有一個視窗剛好也叫做"ScreenSaver Maker"(例如目錄), 那~怎麼辦?根據上面檢查程式重覆的邏輯,我們會認為程式已經Run起來了,因此就會將Focus設定到 "ScreenSaver Maker"的目錄視窗上,再將程式結束。沒錯,這樣就有問題了~~~只要同名稱的目錄視窗開者 ,我們就永遠別想開啟程式了,那這個問題要怎麼解決呢? 我們可以這樣想,FindWindow是用視窗Title來檢查有沒有相同的視窗存在,但是VB的App.PrevInstance 則是判斷有沒有這個程式在跑,因此我們可以改成
也就是先判斷程式有沒有重覆執行,再把視窗找出來。但是,這樣就完全解決了嗎?
其實沒有,為什麼呢?問題仍然發生在FindWindow,我們可以來做個實驗,將程式修改後放在
名稱為"ScreenSaver Maker"的資料夾裡,執行Screen Saver Maker,第一次Screen Saver Maker會
很順利的開啟,再執行一次呢?嘿嘿~~問題就來了~~Screen Saver Maker並沒有跑到最上層,
也沒有最大化,為什麼呢?這是因為FindWindow在有兩個以上同名的視窗存在時,只會傳回它第一個
找到的hwnd,因此才會有上面所說的問題,至於解決方法也不是沒有,但是就麻煩多了,我還沒有加進程式
有興趣的人參考看看,可以自己試試,方法如下1.將所有執行中的視窗列舉出來,取得視窗Title及hwnd 2.將與Screen Saver Maker同名的視窗刪選出來 3.這是我個人嘗試的方法,利用得到的hwnd,我們可以用GetClassName這個API取得該視窗的ClassName, 然後在與frmScrSetUP的ClassName比對,如果一樣,那這就是我們要找的程式視窗了 不過這一部分我沒有加上去,因為這其實還是會錯的 為什麼?如何解決?這一點我有想過,不過解決的方法麻煩了點, 我並沒有實際嘗試,其實大概的提示都跟你們講了~~所以就交給你們自己試試吧~~ 至於還是會有錯誤的原因?給你們一個提示-ScrMaker.Exe、ScrMaker.Scr,想一想吧~~~ 另外Ver1.0判斷重覆執行的部份,多加了一些判斷,是為了別人雙擊專案檔時的處理,在後面說明專案檔的處理時 會再回來說明 接者還有一點,密碼保護 在這裡要先說明的是,我提供的,只是一個可以做的到的方法,並不一定就是最正確的做法, 我找到的資料並不夠詳細,只能做得到這個地步而已,因此,並不能說是正確的做法,各位還 是試試能不能找到更正確的資料才比較好。另外,作者的英文能力也不怎麼樣,所以最好依作者提過的 幾份資料自己去看看MSDN的說明會比較好 首先就我所了解的部份為各位說明一下, Windows本身有一個密碼保護的管理機制,而這個密碼管理, 會將其資料登錄在Register裡,在MSDN裡你可以查到這個說明,"Password Provider Registeation", 而螢幕保護程式的密碼也是屬於這個部份,因此,如果我們想要為我們的螢幕保護程式套上Windows的密碼保護 ,就必須將之設定登錄在登錄檔裡。我找出來的API函數是這一個 - PwdChangePassword,我是這樣用的
這樣子就能順利叫出密碼設定的視窗了,第一個是要傳入密碼供應者(??我也不知道怎麼翻比較好),範例上
大多是以ScreenSaver做範例,所以我就一樣採用SCRSAVE這個名稱了,至於可不可以用其它的名稱,有沒有
什麼其它的限制,很抱歉,作者還沒有去研究....至於第二個值傳入的則是密碼供應者的hwnd,但是...
這個我也弄不清楚有什麼分別,我傳入Form的hwnd和傳入0都一樣可以,我還是搞不懂要做什麼,
第三個參數則可以傳入0(忽略)或者是CHANGEPWD_OLDPWDONLY(大概可能也許是,修改密碼的意思吧,我沒有試),
第四個參數則是傳入一個使用者的資料,做什麼用?.......不好意思,不知道,我被這一點搞的一蹋胡塗....,
我也只瞭解這麼一點點而已,詳情可以看一看ScrMaker補完計劃報告書,其它的...我也無能為力了....>_<....
後記: |
回到VB教學教室 |