悉windows的使用者對作業系統的關機程式一定了解,您是不是覺得它的功能不是很多。許多軟體都有自動關機功能,比如一些下載下傳軟體,這一功能能讓您半夜踏踏實實地睡個好覺,而電腦卻能按照您事先的設定自動關閉 , 您在使用電腦聽音樂、看電影、或是下載下傳等一些自動功能的時候,是不是經常為忘記關機而心痛不已。現在我們用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 )
{
//用系統時間初始化元件
Time.Text = System.DateTime.Today.ToShortDateString( ) + " "+ System.DateTime.Today.ToLongTimeString( ) ;
}
在元件Timer1的OnTimer事件過程中編寫如下代碼:
/ / 在元件Timer1的OnTimer事件過程中編寫如下代碼:
private void Timer1_Timer(object sender, System.EventArgs e )
{
//接收目前日期和時間,用于即時顯示
string CurrDate=System.DateTime.Today.ToShortDateString( ) ;
string CurrTime=System.DateTime.Today.ToShortTimeString( ) ;
//随時檢測設定的關機日期和時間是否有效
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 ;
}
//定義記憶體的資訊結構
[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 ;
}
//定義系統時間的資訊結構
[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 ;
}
4.編寫窗體類的方法
private void button1_Click(object sender, System.EventArgs e )
{
//調用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( ) ;
//調用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( ) ;
//調用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( ) +"位元組" ;
//調用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的操作。上面給出的執行個體僅僅是一個簡單的程式,不過有興趣的讀者可以進一步完善其功能,做出更完美的系統應用程式。