Visual C#是微軟公司推出的下一代程序開發語言,是微軟.Net框架中的的一個重要組成部分。微軟的.Net平台堪稱為新一代的互聯網平台。對於技術開發人員來說,.Net平台的兩大特性是非常卓越的,首先是其所提供的公共語言運行時,也就是公用語言運行平台,另一方面就是其龐大而全面的統一編程類。Visual C#就是通過調用這些類、對象來實現許多比較強大的功能。
在互聯網應用中,電子郵件一直占據著重要的位置。互聯網上每天都有大量的電子郵件,我們每天都要花時間去收發郵件,而有時卻收不到一封郵件,有時卻很多。要是我們能做一個郵件通知程序就好了。本文就向大家介紹用C#做個郵件通知程序,同時也向大家展示一下C#編程的一些特性。
一. 簡介:
這個郵件通知程序是一個用來通知用戶的郵件服務器中是否有新郵件的TCP/IP程序。程序還帶有一個精靈來通知用戶具體的新郵件數,所以用戶界面比較新奇。程序每隔5分鐘就自動連接到郵件服務器進行新郵件的檢查。用戶還可以對程序進行配置:設置時間間隔,設置郵件服務器地址以及端口號,設置用戶名以及密碼。此程序還是居於系統托盤的,所以是在後台運行的。
二. 工程步驟:
1. 在VS.net下新建一個C#的Windows應用程序的工程,不妨命名為“EmailNotifier”。
圖1
2. 設計主界面和精靈界面:
先將主窗體的ShowInTaskbar屬性設置為false,FormBorderStyle屬性設置為FixedDialog,Text屬性設置為“配置參數”。
再在主窗體上添加五個標簽控件(Label Control)、五個文本框控件(TextBox Control)、兩個按鈕控件(Button Control)、一個系統托盤控件(NotifyIcon Control)、一個上下文菜單控件(ContextMenu Control)以及一個時鐘控件(Timer Control)。
對各個控件進行屬性設置:將五個標簽的Text屬性分別設置為“郵件服務器地址:”、“服務器端口:”、“用戶名:”、“密碼:”、“時間間隔(毫秒):”;將五個文本框的Name屬性分別設置為:“ServerAdd”、“ServerPort”、“Username”、“Password”、“TimeSpan”;將前四個文本框的Text屬性均設置為空,將最後一個的設置為300000(因為我們默認的時間間隔為5分鐘);還有把第四個文本框的PasswordChar屬性設置為“*”,這樣輸入的時候就隱藏了密碼;把按鈕控件的Text屬性設置為“隱藏”和“檢查郵件”;將系統托盤的Icon屬性設置為一個圖標文件;在上下文菜單下添加三個子項“配置參數”、“檢查郵件”、“退出”。
這樣主界面已經設計完畢,圖示如下:
圖2
接著設計精靈界面。
我們用到的精靈是用Microsoft Agent創建的,它是完全居於COM的,所以我們可以很方便的利用它。有關它的詳細信息,可以參考微軟網站上的資料,網址為:http://www.microsoft.com/msagent/downloads.htm。先從那裡下載以下一些東西:
(1)Microsoft Agent核心組建
(2) Microsoft Agent的精靈:吉尼(Genie)、麼林(Merlin)、羅比(Robby)和皮蒂(Peedy)
(3)至少有一個英語的Text-to-Speech引擎(現在還找不到中文的)
(4)微軟運行時發音API4.0a
有了這些,我們就可以在我們的任何程序中應用了,只要在程序中添加此ActiveX控件即可。
我們先添加一個新的窗體Form2,圖示如下:
圖3
在新添加的窗體上我們要用到Microsoft Agent這個控件,於是就導入它到該工程中,圖示如下:
圖4
現在,我們的工具箱裡已經有了相應的控件,我們就可以直接使用了。(在程序運行時這個控件是不可見的)
(如果讀者有興趣的話,可以到我的另一篇有關Microsoft Agent控件的文章:http://www.computerworld.com.cn/htm/app/aprog/01_12_29_2.asp看看)
3. 重要的代碼部分:
在主窗體的代碼部分,因為我們要用到網絡以及網絡流等類的對象,所以首先得添加以下幾個重要的名字空間(Namespace):
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;
接著,給我們的類添加一個NetworkStream對象來控制網絡中的流。
private NetworkStream netStream;
給該類的構造函數添加如下代碼,設置時鐘的時間間隔以及使程序一開始就不可見而只有系統托盤。
timer1.Interval=Int32.Parse(TimeSpan.Text);//設定時間間隔
this.Opacity=0;//使窗體不可見
我們用到一個重要的函數EmailCheck()。這個函數先新建一個TcpClient對象進行網絡連接,用一個try-catch設法連接到用戶輸入的郵件服務器。如果連接成功,則用netStream對象取得網絡流:netStream = tcpClient.GetStream();最後完成信息的發送和獲取。函數如下:
private void EmailCheck()
{
file://新建一個TcpClient對象來建立連接
TcpClient tcpClient = new TcpClient();
try
{
tcpClient.Connect(ServerAdd.Text,Int32.Parse(ServerPort.Text));
}
catch
{
MessageBox.Show("不能連接到主機:"+ServerAdd.Text+"和端口:"+ServerPort.Text);
}
file://從郵件服務器獲得相應
netStream = tcpClient.GetStream();
if(netStream == null)
{
throw new Exception("獲得的網絡流為空值。");
}
string returnMsg=ReadFromNetStream(ref netStream);
checkForError(returnMsg);
file://發送用戶名信息
WriteToNetStream(ref netStream, "USER " + this.Username.Text);
returnMsg=ReadFromNetStream(ref netStream);
checkForError(returnMsg);
file://發送密碼信息
WriteToNetStream(ref netStream, "PASS " + this.Password.Text);
returnMsg=ReadFromNetStream(ref netStream);
checkForError(returnMsg);
Stat();
netStream.Close();
tcpClient.Close();
}
上面的函數中用到了ReadFromNetStream()、WriteToNetStream()、Stat()、checkForError()等函數。ReadFromNetStream()是用來從網絡流中讀取信息的,帶一個類型為ref NetworkStream的參數;WriteToNetStream()是向網絡流中寫入信息的,帶兩個類型為ref NetworkStream,string的參數;Stat()是當檢查到新郵件後用來向用戶報告信息的函數;checkForError()是進行查錯的,帶一個String類型的參數。四個函數如下:
///
/// 這個函數用來顯示新郵件數信息
///
public void Stat()
{
WriteToNetStream(ref netStream, "STAT");
string returnMsg=ReadFromNetStream(ref netStream);
checkForError(returnMsg);
file://將總郵件數和郵件大小分離
string[] TotalStat= returnMsg.Split(new char[] { });
int count =Int32.Parse(TotalStat[1]);
int totalSize=Int32.Parse(TotalStat[2]);
file://調用精靈,告知用戶新郵件數
Form2 agent= new Form2(count);
}
///
/// 這個函數用來向網絡流寫入數據
///
///
///
private void WriteToNetStream(ref NetworkStream NetStream, string Command)
{
string stringToSend = Command + " ";
Byte[] arrayToSend = Encoding.ASCII.GetBytes(stringToSend.ToCharArray());
NetStream.Write(arrayToSend, 0, arrayToSend.Length);
}
///
/// 這個函數用來從網絡流中讀取數據
///
///
///
private String ReadFromNetStream(ref NetworkStream NetStream)
{
StringBuilder strReceived= new StringBuilder();
StreamReader sr= new StreamReader(NetStream);
String strLine = sr.ReadLine();
while(strLine==null || strLine.Length==0)
{
strLine = sr.ReadLine();
}
strReceived.Append(strLine);
if(sr.Peek()!=-1)
{
while ((strLine=sr.ReadLine())!=null)