在WP8的時候,關於如何關閉屏幕,國內外都有不少文章了,大家有興趣地可以搜搜,很多,我就不給鏈接了,因為稍后我的例子中會有。
其實,關閉屏幕是調用了未開放的API,正因為這個API未開放的,不敢保證所有機型都能用。
這是一個Win32的API,用C語言寫的,在托管代碼中可以dll import,再調用,和在桌面的.NET程序的互操作是一樣的。在WP 8中是要先創建一個Windows運行時組件項目,並在項目中dll import,然后在主項目中引用組件才能調用,前不久,我在MSDN的社區中看到有位仁兄說,在8.1上是不用建運行時組件的,你喜歡在哪引入dll函數都能調用。於是,昨晚我試了一下,果然,在8.1上是不用建Windows運行時組件項目就能調用。
不過,在新建項目時一定要選括號中有“Windows Phone”的模板,即移植的RT應用,不要選Silverlight的,記清楚了。

這個API函數叫Shell_TurnScreenOn,它有一個參數,bool類型,如果參數是true就是打開屏幕,false則是關閉屏幕。我們知道在手機上只要屏幕關了就會鎖屏幕(默認),因此,只要調用Shell_TurnScreenOn(false)就可以達到一鍵鎖屏幕的效果。
為了方便操作,我封裝了一個類:
public static class LockScreen { [DllImport("ShellChromeAPI.dll")] static extern void Shell_TurnScreenOn ( bool value ); public static void TurnOffScreen () { Shell_TurnScreenOn(false); } public static void TurnOnScreen () { //Shell_TurnScreenOn(true); throw new NotImplementedException("暫時不實現。"); } }
TurnOnScreen是打開屏幕,這里用不上,所以我讓它拋了異常,一鍵鎖屏,調用TurnOffScreen方法就可以了。
好了,基本原理說完了,接下來就可以任意發揮了。本文中,我給大家准備了兩個示例,一柔一剛。柔者,有界面有按鈕,可以創建輔助磁貼來一鍵鎖屏;剛者,非常狠,無界面無初始屏幕,只要一啟動就關閉屏幕。很簡單,就是調用上面那個TurnOffScreen方法即可。
兩個示例是差不多的,我先說柔的。單擊按鈕后鎖屏。
private void OnLock ( object sender, RoutedEventArgs e ) { LockScreen.TurnOffScreen(); if (this.ckbExit.IsChecked == true) { App.Current.Exit(); } }
這里用到Application類的一個Exit方法,如果想在鎖屏后退出程序,可以調用它,調用后程序就會退出。
接着是為一鍵鎖屏創建輔助磁貼的代碼。
private async void OnPin ( object sender, RoutedEventArgs e ) { if (!SecondaryTile.Exists(TILE_ID)) { SecondaryTile t = new SecondaryTile(TILE_ID); t.VisualElements.Square150x150Logo = new Uri("ms-appx:///Assets/Logo.png", UriKind.Absolute); t.DisplayName = "一鍵鎖屏"; t.Arguments = "lock"; t.VisualElements.ShowNameOnSquare150x150Logo = true; await t.RequestCreateAsync(); } else { var tiles = await SecondaryTile.FindAllAsync(); if (tiles.Count > 0) { SecondaryTile theTile = tiles.FirstOrDefault(st => st.TileId == TILE_ID); if (theTile != null) { await theTile.RequestDeleteAsync(); } } } UpdatePinButton(); }
這個我不詳說了,就是通過SecondaryTile類來創建或刪除輔助磁貼,要注意的是必須為Arguments屬性賦值,不然沒法創建磁帖,而且不能為null,如果沒有參數就用空字符串(""),我這里用了個參數lock。還有一點就是磁貼的ID必須唯一,這個就不用解釋了,用腳丫子就能想明白的事。
當用戶點擊輔助磁貼啟動應用程序,會進入OnLaunch方法,此時一定要先作判斷再決定是否鎖屏。為啥呢? 別忘了,用戶從應用列表中啟動應用程序時也會進入OnLaunch方法的,所以,要通過方法參數的磁貼ID和剛才創建輔助磁貼時賦值的Arguments來判斷用戶是不是通過輔助磁貼來啟動程序的,如果是,不用顯示界面,直接Lock屏,然后Exit。
protected override void OnLaunched(LaunchActivatedEventArgs e) { // 如果是通過快捷磁貼啟動的 // 則先關閉屏幕,再退出應用程序 if (e.TileId == MainPage.TILE_ID && e.Arguments == "lock") { LockScreen.TurnOffScreen(); this.Exit(); } ……
如何? 上面那個太柔了,沒事,下面咱們來個更猛的,連界面都沒有的,一啟動就Lock。
在創建項目后,直接把項目生成的App.xaml、MainPage.xaml都X掉,都說沒有界面了嘛,所以頁面也不用了。
然后自己新建一個類,同樣名為App,從Application類派生,注意必須有這個類,不然沒法運行。並且,這個類的名字必須與清單文件中“入口點”中配置的名字相匹配,否則你等着倒霉吧。

App類的代碼如下:
public sealed class App : Application { public App () { // 先關屏幕再退出 LockScreen.TurnOffScreen(); Exit(); } }
還是那個思路,先Lock后退出。
各位要嚴重注意,光是完成以上動作,程序也是無法運行的,其實app是有Main入口點的,和一般的.net程序一樣,但通常這個Main是由VS自動生成的,我們很少招惹它,因為你招惹也沒用,重新生成應用程序后,這些由VS生成的文件會被覆蓋,你修改了等於沒改。但是,本例不一樣,上面的步驟已經把項目模板生成的App.xaml干掉了,這個App類是我自己寫的,因此在沒有App.xaml文件的條件下VS是不會自動生成Main的,所以必須自己手動來創建一個Main方法。
/// <summary> /// 必須通過此類聲明Main,否則不能運行 /// </summary> public static class AppStart { public static void Main ( string[] args ) { Application.Start(ps => new App()); } }
最后,打開清單文件,切換到所有可見資產選項卡,把初始屏幕的圖片清除,程序都沒有界面了,初始屏幕也是多余的,但是磁貼還是要的。

好了,這兩個示例的源碼我已上傳,下載地址:http://files.cnblogs.com/tcjiaan/onekeyLockscreenApps.zip
時間不早了,88。
