許多軟體都有自動關機功能,特別是在長時間下載的時候,這個功能可是使你不用以守候在電腦前面,而電腦卻能按照您事先的設定自動關閉。現在我們用visual C#來編寫一個多功能的關機程式。該程式具有:定時關機、倒計時關機、關機提醒、系統資訊擷取等四項功能, 可設定關機時間精確到秒。並且讓你很快掌握Visual C#中對API的操作程式。 一. 設計關閉Windows表單 1. 介面的設計 建立一個標準工程,向工程中增加一個Windows表單並向表單中添加如下控制項,並分別設定其屬性:
| 控制項名 |
類別 |
Text |
控制項名 |
類別 |
Text |
| CheckBox1 |
CheckBox |
自動關機 |
GroupBox1 |
GroupBox |
當前系統時間 |
| CheckBox1 |
CheckBox |
倒計時執行操作 |
GroupBox2 |
GroupBox |
設定時間 |
| CheckBox1 |
CheckBox |
定時警示 |
TxtTime |
TextBox |
|
| ButCancle |
Button |
取消 |
SetupTime |
DateTimePicker |
|
| ButReOpen |
Button |
重新啟動 |
SetupDate |
DateTimePicker |
|
| ButClose |
Button |
關機 |
Timer1 |
Timer |
100 |
| ButSysInto |
Button |
系統資訊 |
ButReLogin |
Button |
注消 |
Windows表單介面: 將表單內容中的caption設定為"關閉windows",名稱設定為"frmmain"。 2. 在表單類中引用API函數 API函數是構築Windows應用程式的基石,是Windows編程的必備利器。每一種Windows應用程式開發工具都提供了間接或直接調用了Windows API函數的方法,或者是調用Windows API函數的介面,也就是說具備調用動態串連庫的能力。Visual C#和其它開發工具一樣也能夠調用動態連結程式庫的API函數。 在Visual C#中調用API的基本過程: 首先,在調用API之前,你必須先匯入System.Runtime.InteropServices這個名稱空間。該名稱空間包含了在Visual C#中調用API的一些必要集合,具體的方法如下: using System.Runtime.InteropServices ; using System.Text ; 在匯入了名稱空間後,我們要聲明在程式中所要用到的API函數。我們的程式主要是擷取系統的相關資訊,所以用到的API函數都是返回系統資訊的。先給出在Visual C#中聲明API的方法: [ DllImport("user32") ] public static extern long SetWindowPos(long hwnd , long hWndInsertAfter, long X , long y , long cx, long cy, long wFlagslong) ; 其中,"DllImport"屬性用來從不可控代碼中調用一個方法,它指定了DLL的位置,該DLL中包含調用的外部方法;"kernel32"設定了類庫名;"public"指明函數的訪問類型為公有的;"static"修飾符聲明一個靜態元素,而該元素屬於類型本身而不是指定的對象;"extern"表示該方法將在工程外部執行,同時使用DllImport匯入的方法必須使用"extern"修飾符;最後GetWindowsDirectory函數包含了兩個參數,一個為StringBuilder類型的,另一個為int類型的,該方法返回的內容存在於StringBuilder類型的參數中。同時,因為我們在這裡使用到了StringBuilder類,所以在程式的開始處,我們還得添加System.Text這個名稱空間,方法同上。 聲明其它的在程式中所要用到的API函數: [ DllImport("user32") ] public static extern long ExitWindowsEx(long uFlags, long dwReserved ) ; [ DllImport("shell32") ] public static extern long ShellAbout(long uFlags, long dwReserved ) ; 3. 增加表單類的變數 long dwReserved ; const int SHUTDOWN = 1 ; const int REBOOT = 2 ; const int LOGOFF = 0 ; long sh ; int counter , n ; 4. 編寫表單類的方法 在表單的Load(事件程序中編寫如下代碼: private void frmmain1_Load(object sender, System.EventArgs e ) { file://用系統時間初始化組件 Time.Text = System.DateTime.Today.ToShortDateString( ) + " "+ System.DateTime.Today.ToLongTimeString( ) ; } 在組件Timer1的OnTimer事件程序中編寫如下代碼: / / 在組件Timer1的OnTimer事件程序中編寫如下代碼: private void Timer1_Timer(object sender, System.EventArgs e ) { file://接收當前日期和時間,用於即時顯示 string CurrDate=System.DateTime.Today.ToShortDateString( ) ; string CurrTime=System.DateTime.Today.ToShortTimeString( ) ; file://隨時檢測設定的關機日期和時間是否有效 if( this.CheckBox1.Checked == true ) { if(CurrDate== SetupDate.ToString( ) && CurrTime==SetupTime.ToString( ) ) ColseComputer( ) ; } } private void ColseComputer( ) { sh = ExitWindowsEx(SHUTDOWN, dwReserved) ; } private void button1_Click(object sender, System.EventArgs e ) { Form2 frm=new Form2( ) ; frm.Show( ) ; } private void ButReOpen_Click(object sender, System.EventArgs e ) { sh = ExitWindowsEx(REBOOT, dwReserved) ; } private void ButReLogin_Click(object sender, System.EventArgs e ) { sh = ExitWindowsEx(LOGOFF, dwReserved) ; } private void ButCancle_Click(object sender, System.EventArgs e ) { this.Close( ) ; } private void ButClose_Click_1(object sender, System.EventArgs e ) { sh = ExitWindowsEx(REBOOT, dwReserved) ; } 二. 設計擷取系統資訊的Windows表單 1. 介面的設計 向工程中增加一個Windows表單並向表單中添加如下控制項: 2. 在表單類中引用API函數 using System.Runtime.InteropServices ; using System.Text ; [ DllImport("kernel32") ] public static extern void GetWindowsDirectory(StringBuilder WinDir,int count) ; [ DllImport("kernel32") ] public static extern void GetSystemDirectory(StringBuilder SysDir,int count) ; [ DllImport("kernel32") ] public static extern void GetSystemInfo(ref CPU_INFO cpuinfo) ; [ DllImport("kernel32") ] public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo) ; [ DllImport("kernel32") ] public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo) ; 以上幾個API的作用分別是擷取系統路徑,獲得CPU相關資訊,獲得記憶體的相關資訊,獲得系統時間等。 3. 定義以下各結構 在聲明完所有的API函數後,我們發現後三個函數分別用到了CPU_INFO、MEMORY_INFO、SYSTEMTIME_INFO等結構,這些結構並非是.Net內部的,它們從何而來?其實,我們在用到以上API調用時均需用到以上結構,我們將函數調用獲得的資訊存放在以上的結構體中,最後返回給程式輸出。這些結構體比較複雜,但是如果開發人員能夠熟練運用,那麼整個API世界將盡在開發人員的掌握之中。以下就是上述結構體的聲明: //定義CPU的資訊結構 [StructLayout(LayoutKind.Sequential) ] public struct CPU_INFO { public uint dwOemId ; public uint dwPageSize ; public uint lpMinimumApplicationAddress ; public uint lpMaximumApplicationAddress ; public uint dwActiveProcessorMask ; public uint dwNumberOfProcessors ; public uint dwProcessorType ; public uint dwAllocationGranularity ; public uint dwProcessorLevel ; public uint dwProcessorRevision ; } file://定義記憶體的資訊結構 [StructLayout(LayoutKind.Sequential) ] public struct MEMORY_INFO { public uint dwLength ; public uint dwMemoryLoad ; public uint dwTotalPhys ; public uint dwAvailPhys ; public uint dwTotalPageFile ; public uint dwAvailPageFile ; public uint dwTotalVirtual ; public uint dwAvailVirtual ; } file://定義系統時間的資訊結構 [StructLayout(LayoutKind.Sequential) ] public struct SYSTEMTIME_INFO { public ushort wYear ; public ushort wMonth ; public ushort wDayOfWeek ; public ushort wDay ; public ushort wHour ; public ushort wMinute ; public ushort wSecond ; public ushort wMilliseconds ; } 5. 編寫表單類的方法 private void button1_Click(object sender, System.EventArgs e ) { file://調用GetWindowsDirectory和GetSystemDirectory函數分別取得Windows路徑和系統路徑 const int nChars = 128 ; StringBuilder Buff = new StringBuilder(nChars) ; GetWindowsDirectory(Buff,nChars) ; WindowsDirectory.Text = "Windows路徑:"+Buff.ToString( ) ; GetSystemDirectory(Buff,nChars) ; SystemDirectory.Text = " 系統路徑:"+Buff.ToString( ) ; file://調用GetSystemInfo函數擷取CPU的相關資訊 CPU_INFO CpuInfo ; CpuInfo = new CPU_INFO( ) ; GetSystemInfo(ref CpuInfo) ; NumberOfProcessors.Text = "本電腦中有"+CpuInfo.dwNumberOfProcessors.ToString( ) +"個CPU"; ProcessorType.Text = "CPU的類型為"+CpuInfo.dwProcessorType.ToString( ) ; ProcessorLevel.Text = "CPU等級為"+CpuInfo.dwProcessorLevel.ToString( ) ; OemId.Text = "CPU的OEM ID為"+CpuInfo.dwOemId.ToString( ) ; PageSize.Text = "CPU中的頁面大小為"+CpuInfo.dwPageSize.ToString( ) ; file://調用GlobalMemoryStatus函數擷取記憶體的相關資訊 MEMORY_INFO MemInfo ; MemInfo = new MEMORY_INFO( ) ; GlobalMemoryStatus(ref MemInfo) ; MemoryLoad.Text = MemInfo.dwMemoryLoad.ToString( ) +"%的記憶體正在使用" ; TotalPhys.Text = "實體記憶體共有"+MemInfo.dwTotalPhys.ToString( ) +"位元組" ; AvailPhys.Text = "可使用的實體記憶體有"+MemInfo.dwAvailPhys.ToString( ) +"位元組" ; TotalPageFile.Text = "分頁檔總大小為"+MemInfo.dwTotalPageFile.ToString( ) +"位元組" ; AvailPageFile.Text = "尚可分頁檔大小為"+MemInfo.dwAvailPageFile.ToString( ) +"位元組" ; TotalVirtual.Text = "總虛擬記憶體有"+MemInfo.dwTotalVirtual.ToString( ) +"位元組" ; AvailVirtual.Text = "未用虛擬記憶體有"+MemInfo.dwAvailVirtual.ToString( ) +"位元組" ; file://調用GetSystemTime函數擷取系統時間資訊 SYSTEMTIME_INFO StInfo ; StInfo = new SYSTEMTIME_INFO( ) ; GetSystemTime(ref StInfo) ; Date.Text = StInfo.wYear.ToString( ) +"年"+StInfo.wMonth.ToString( ) +"月"+StInfo.wDay.ToString( ) +"日" ; Time.Text = (StInfo.wHour+8).ToString( ) +"點"+StInfo.wMinute.ToString( ) +"分"+StInfo.wSecond.ToString( ) +"秒" ; } 三. 結束語。 上面介紹了Visual C#開發多功能關機程式的整個過程,該程式有一定的實用價值。通過本文的學習,我相信稍有API使用基礎的開發人員可以馬上觸類旁通,很快掌握Visual C#中對API的操作。上面給出的執行個體僅僅是一個簡單的程式,不過有興趣的讀者可以進一步完善其功能,做出更完美的系統應用程式。 |