一共470多例winform 界面特效的源碼。算法
窗體與界面設計... 9數據庫
實例001 帶歷史信息的菜單 10編程
實例002 菜單動態合併 12windows
實例003 像開始菜單同樣漂亮的菜單... 14api
實例004 任務欄托盤菜單 15數組
實例005 能夠拉伸的菜單界面 16瀏覽器
實例006 菜級聯菜單 18安全
1.2 工具欄設計... 19網絡
實例007 帶帶背景的工具欄 19框架
實例008 帶浮動工具欄 20
實例009 在帶下拉菜單的工具欄... 21
實例010 在具備提示功能的工具欄... 22
實例011 在狀態欄中顯示檢查框... 23
實例012 帶進度條的狀態欄 25
實例013 狀態欄中加入圖標 26
實例014 OutLook界面 27
實例015 帶帶導航菜單的主界面... 29
實例016 圖形化的導航界面 32
實例017 菜類QQ的程序界面 35
實例018 相似windows xp的程序界面... 38
實例019 以圖形按鈕顯示的界面... 42
實例020 以樹形顯示的程序界面... 44
實例021 動態按鈕的窗體界面 46
實例022 非矩形窗體 50
實例023 創建字體形狀窗體 52
實例024 控件隨窗體自動調整 54
實例025 帶分隔欄的窗體 55
實例026 隨機更換主界面背景 56
實例027 自動啓動的多媒體光盤程序... 57
實例028 爲觸摸屏程序添加虛擬鍵盤... 59
實例029 半透明漸顯窗體 61
實例030 窗口顏色的漸變 63
實例031 窗體中的滾動字幕 65
實例032 動畫顯示窗體 67
實例033 製做閃爍的窗體 69
實例034 直接在窗體上繪圖 70
實例035 動畫形式的程序界面 73
實例036 使窗體標題欄文字右對齊... 75
實例037 沒有標題欄可義改變大小的窗口... 76
實例038 設置窗體在屏幕中的位置... 77
實例039 始終在最上面的窗體 78
實例040 限制窗體大小 79
實例041 獲取桌面大小 81
實例042 在窗口間移動按扭 82
實例043 如何實現Office助手 84
實例044 在關閉窗口前加入確認對話框... 85
實例045 使用任意組件拖動窗體... 88
實例046 修改提示字體及顏色 89
實例047 如何爲MDI類型窗體設置背景圖片... 91
實例048 向提示框中添加圖標 93
實例418 經過串口發送數據 95
實例419 經過串口關閉對方計算機... 98
實例420 密碼寫入與讀出加密狗... 101
實例421 使用加密狗進行身份驗證... 105
實例422 向IC卡中寫入數據 107
實例423 讀取IC卡中的數據 113
實例424 利用IC卡製做考勤程序... 116
實例425 簡易視頻程序 119
實例426 攝像頭監控錄像 125
實例427 超市攝像頭定時監控系統... 127
實例428 語音卡電話呼叫系統 132
實例429 客戶來電查詢系統 141
實例430 語音卡實現電話錄音 144
實例431 利用短信貓收發短信息... 147
實例432 利用短信遠程關閉計算機... 155
實例433 短信息採集菸草銷售數據... 159
實例434 「春晚」節目評比短信息互動平臺... 164
實例435 條形碼掃描器銷售商品... 167
實例436 利用神龍卡製做練歌房程序... 169
實例463 數據加密技術 174
實例464 文本文件加密與解密 177
實例465 利用圖片加密文件 188
實例466 如何編程修復Access數據庫... 194
實例467 訪問帶驗證模式的Sqlserver 2000數據庫... 197
實例468 利用INI文件對軟件進行註冊... 201
實例469 利用註冊表設計軟件註冊程序... 204
實例470 利用網卡序列號設計軟件註冊程序... 208
實例471 根據cpu序列號、磁盤序列號設計軟件註冊程序... 214
窗體與界面設計
菜單是程序開發中常用的界面元素,合理利用菜單不但可使用戶很是方便的操做程序的功能,更能使效率提升,適應人性化的潮流。下面經過幾個應用實例,介紹菜單設計的方法和技術。
實例001 帶歷史信息的菜單
實例說明
在開發圖紙管理軟件時,要求在菜單上記錄用戶最近打開的檔案或圖紙,以方便下次使用。如圖1.1所示,單擊「文件」菜單下的「打開文件」子菜單,打開須要查閱的圖紙。下次運行該軟件時,上次打開的文件名記錄到「文件」菜單的歷史菜單中,選擇該菜單,便可打開相應的圖紙文件。
技術要點
要實現保存最近打開的文件,能夠將在菜單中最近打開文件的文件名和路徑保存到事先創建的*.ini文件中,系統啓動時讀取*.ini中的數據創建數組菜單,便可實現顯示歷史菜單的功能。
注意:要創建一個帶歷史信息的菜單,必須首先添加一個MenuStrip菜單控件,並將主窗體的IsMdiContainer屬性設爲True。
實現過程
(1)建立一個項目,將其命名爲Ex01_01,默認窗體爲Form1。
(2)從工具箱中向Form1窗體添加MenuStrip控件,同時向窗體添加OpenFileDialog控件。建立一個「文件」主菜單,在其下面建立打開、關閉全部、退出等菜單選項。
(3)主要程序代碼。
將打開文件路徑寫入INI文件的實現代碼以下:
private void 打開ToolStripMenuItem_Click(object sender, EventArgs e)
{
openFileDialog1.FileName = "";
this.openFileDialog1.ShowDialog();
StreamWriter s = new StreamWriter(address + "\\Menu.ini", true);
s.WriteLine(openFileDialog1.FileName);//寫入INI文件
s.Flush();
s.Close();
ShowWindows(openFileDialog1.FileName);
}
讀取INI文件並將信息加入菜單的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
StreamReader sr = new StreamReader(address + "\\Menu.ini");
int i = this.文件ToolStripMenuItem.DropDownItems.Count-2;
while (sr.Peek()>=0)//讀取INI文件
{
ToolStripMenuItem menuitem = new ToolStripMenuItem(sr.ReadLine());
this.文件ToolStripMenuItem.DropDownItems.Insert(i, menuitem);
i++;
menuitem.Click += new EventHandler(menuitem_Click);
}
sr.Close();
}
自定義方法ShowWindows()用來加載背景圖片並顯示窗體,實現代碼以下:
public void ShowWindows(string fileName)
{
Image p = Image.FromFile(fileName);
Form f = new Form();
f.MdiParent = this;
f.BackgroundImage = p;
f.Show();
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
記錄用戶操做菜單日誌的程序。在用戶單擊菜單時,把用戶、菜單命令和菜單對應功能寫入保存菜單日誌的INI文件。若是須要查看日誌,只需打開INI文件。
經過數據庫保存菜單歷史信息的程序。
菜單使用頻率的程序。把用戶使用菜單的數據信息保存到數據庫中,而後統計用戶使用菜單的頻率,並根據此頻率調整菜單的顯示順序。
實例002 菜單動態合併
實例說明
在程序中常用彈出菜單,而且一個窗體中能夠存在多個彈出菜單。開發過MDI窗體的讀者可能都知道,當MDI子窗體最大化時,子窗體和主窗體的菜單可以自動的合併。這是如何實現的呢?本例實現了將兩個彈出菜單動態的合併成一個彈出菜單的功能。實例效果如圖1.2所示。
技術要點
C# 2.0中已經將彈出菜單封裝爲Context MenuStrip控件,利用該控件中的Items對象能夠操做菜單中的菜單項。該對象是ToolStripMenuItem類型,使用Items.AddRange( )方法能夠向彈出菜單中添加菜單項,該方法原型以下。
public void AddRange (
ToolStripItem[] toolStripItems
)
參數說明以下。
l toolStripItems:控件的數組。
實現過程
(1)建立一個項目,將其命名爲Ex01_02,默認窗體爲Form1。
(2)從工具箱中向Form1窗體添加一個MenuStrip控件用來設計菜單;同時向窗體添加ContextMenuStrip控件用來設計右鍵菜單;選中MenuStrip控件建立一個「打開子窗體」主菜單,而後選中ContextMenuStrip控件爲其添加子項。
(3)爲程序添加一個窗體,默認名爲Form2,同時向窗體添加ContextMenuStrip控件用來設計右鍵菜單,而後選中ContextMenuStrip控件爲其添加子項。
(4)主要程序代碼。
private void 打開自窗體ToolStripMenuItem_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.MdiParent = this;
f.Show();//顯示子窗體
f.Resize += new EventHandler(f_Resize);
}
void f_Resize(object sender, EventArgs e)
{
Form2 f = (Form2)sender;
ToolStripMenuItem item = new ToolStripMenuItem();
for (int i = 0; i < f.contextMenuStrip2.Items.Count; )//合併菜單
{
item.DropDownItems.Add(f.contextMenuStrip2.Items[i]);
}
this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
item});
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
讓右鍵菜單在子窗體中顯示。
讓右鍵菜單在主窗體和子窗體中同時顯示。
實例003 像開始菜單同樣漂亮的菜單
實例說明
Windows的開始菜單很是的獨特,在菜單的旁邊有一條豎着的彩條,彩條中還寫着文字。這種獨特的菜單可以使程序的界面看起來更加的漂亮。本例中就實現了這種菜單,運行本例彈出「打開菜單」時,就會看到菜單的左邊有一個紫色的彩條。實例效果如圖1.3所示。
技術要點
在C# 2.0中,MenuStrip控件中的子項ToolStripMenuItem已經包括了左側的彩條,實現像開始菜單同樣的菜單很是容易,不像在其餘計算機語言的開發環境中,須要調用API才能夠實現。若是想改變左側豎着的彩條,只要給對應的菜單項設置相應的圖片便可。
注意:若是要在左側彩條顯示文字,只要在對應的圖片上加入文字便可。
實現過程
(1)建立一個項目,將其命名爲Ex01_03,默認窗體爲Form1。
(2)從工具箱中向Form1窗體添加MenuStrip控件。
(3)爲MenuStrip控件添加相應的子項。
(4)爲子項添加相應的圖片。
觸類旁通
根據本實例,讀者能夠實現如下功能。
將菜單元設置成不一樣的格式(如圖片、文字等)。
在菜單左側播放動畫。
實例004 任務欄托盤菜單
實例說明
有一些軟件一般只是在後臺運行,這些進程大部分時間不顯示用戶界面。可經過單擊任務欄狀態通知區域的圖標來訪問的病毒防禦程序就是一個示例。Windows窗體中的NotifyIcon控件一般用於顯示在後臺運行的進程的圖標,本實例利用該控件製做了一個任務欄托盤菜單。實例效果如圖1.4所示。
技術要點
要實現程序啓動時出如今系統托盤中。必需要爲窗體添加NotifyIcon 控件和ContextMenuStrip控件。
注意:必須爲NotifyIcon 控件的Icon屬性設置圖標。
實現過程
(1)建立一個項目,將其命名爲Ex01_04,默認窗體爲Form1。
(2)向Form1窗體添加NotifyIcon 控件和ContextMenuStrip控件,併爲ContextMenuStrip控件添加子項。
(3)選擇NotifyIcon 控件,在其屬性窗口中將ContextMenuStrip屬性設置爲添加到窗體上的ContextMenuStrip控件,併爲Icon屬性設置圖片。
觸類旁通
根據本實例,讀者能夠開發如下程序。
程序啓動時不出現界面,直接出如今系統托盤中運行的後臺程序。
程序啓動時不出如今任務欄中。
實例005 能夠拉伸的菜單界面
實例說明
若是管理程序功能菜單很是多,而用戶只使用一些經常使用菜單,這時,能夠將主菜單項下的不經常使用菜單隱藏起來。此種顯示方式相似於對菜單進行拉伸。使用時,只需單擊展開菜單,便可顯示相應菜單功能。運行本例,效果如圖1.5所示。
技術要點
要實現能夠拉伸的菜單,關鍵是要使用一個開關變量,同時調用ShowDropDown()方法,顯示操做後的結果。下面詳細介紹一下該方法。
ShowDropDown()方法用來顯示與此ToolStripDrop DownItem關聯的ToolStripDropDownItem控件。其語法結構以下:
public void ShowDropDown ()
另外,用ShowDropDown()方法還能夠顯示已由 DropDown 屬性設置的下拉控件。
注意:必須設置開關變量的初值。
實現過程
(1)建立一個項目,將其命名爲Ex01_05,默認窗體爲Form1。
(2)從工具箱中向Form1窗體添加MenuStrip控件,選中MenuStrip控件爲其添加子項。
(3)雙擊「展開(關閉)子項」爲其雙擊事件添加處理代碼。
(4)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
//初始設置下面的菜單隱藏
this.設置密碼ToolStripMenuItem.Visible = false;
this.添加用戶ToolStripMenuItem.Visible = false;
this.忘記密碼ToolStripMenuItem.Visible = false;
this.修改密碼ToolStripMenuItem.Visible = false;
this.員工錄入ToolStripMenuItem.Visible = false;
}
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
switch (i)
{
case 1:
this.設置密碼ToolStripMenuItem.Visible = false;
this.添加用戶ToolStripMenuItem.Visible = false;
this.忘記密碼ToolStripMenuItem.Visible = false;
this.修改密碼ToolStripMenuItem.Visible = false;
this.員工錄入ToolStripMenuItem.Visible = false;
i = 2;
this.操做ToolStripMenuItem.ShowDropDown();
break;
case 2:
this.設置密碼ToolStripMenuItem.Visible = true;
this.添加用戶ToolStripMenuItem.Visible = true;
this.忘記密碼ToolStripMenuItem.Visible = true;
this.修改密碼ToolStripMenuItem.Visible = true;
this.員工錄入ToolStripMenuItem.Visible = true;
i = 1;
this.操做ToolStripMenuItem.ShowDropDown();
break;
}
}
觸類旁通
根據本實例,讀者能夠開發如下功能。
製做顯示\隱藏工具欄。
合併菜單欄。
實例006 菜級聯菜單
實例說明
若是管理程序功能菜單很是多,一些功能中又包括許多子功能,這時可使用級聯菜單來組織系統的各個功能。實例運行結果如圖1.6所示。
圖1.6 級聯菜單
技術要點
製做級聯菜單須要使用MenuStrip控件。
注意:在使用級聯菜單時最好不要超過5層,不然用戶在使用時會很不方便。
實現過程
(1)建立一個項目,將其命名爲Ex01_06,默認窗體爲Form1。
(2)在Form1窗體添加MenuStrip控件,選中MenuStrip控件爲其添加子項和級聯子項。
觸類旁通
根據本實例,讀者能夠開發如下功能。
大型系統的功能導航。
在窗體四周再增長菜單欄。
在菜單欄中將經常使用的菜單命令以工具欄按鈕的形式顯示,並做爲快速訪問方式。工具欄位於菜單欄的下方,由許多命令按鈕組成,每一個命令按鈕上都有一個形象的小圖標,以標識命令按鈕的功能。因爲工具欄這種直觀易用的特色,使其已成爲Windows應用程序的標準界面。
實例007 帶帶背景的工具欄
實例說明
工具欄是窗體的組成部分之一,工具欄中的按鈕能夠設定完成一些較爲經常使用或重要的功能,本例中設計了一個工具欄,而且爲該工具欄做了一些修飾,使工具欄帶有背景。背景圖案能夠透過按鈕顯示,效果如圖1.7所示。
技術要點
工具欄中的背景是一幅圖片,在運行時應該將該圖片繪製到工具欄上,在.NET 2.0中,只需將工具欄按鈕的BackGroundImage的屬性設置爲對應的圖片便可。
實現過程
(1)建立一個項目,將其命名爲Ex01_07,默認窗體爲Form1。
(2)從工具箱中爲Form1窗體添加ToolStrip控件,併爲工具欄添加相應的按鈕。
(3)爲工具欄的按鈕設置相應的BackGroundImage屬性,相應的的圖片就會變成按鈕的背景。
觸類旁通
根據本實例,讀者能夠開發如下功能。
製做一個帶動畫效果的工具欄。
製做一個自定義樣式的工具欄。
實例008 帶浮動工具欄
實例說明
一般狀況下,窗體顯示在屏幕的中心。對於使用頻率很是高的軟件,一般放在屏幕上端以浮動工具欄形式顯示。下面經過實例介紹浮動工具欄的設計方法。運行程序,程序能夠停在屏幕的任何位置,當窗體失去焦點後,窗體將自動隱藏。效果如圖1.8所示。
技術要點
窗體是否要隱藏,重要的是要判斷在操做中,經過窗體的Focused屬性,是否能夠肯定窗體有焦點。在窗體有焦點時,該窗體正在被操做,這時須要徹底顯示在屏幕當中,若是窗體沒有焦點,經過設置窗體到屏幕的高度,來肯定窗體的隱藏部分。下面詳細介紹一下Focused屬性。
Focused屬性用來獲取一個值,該值指示控件是否有輸入焦點。其語法結構以下:
public virtual bool Focused { get; }
l 屬性值:若是控件有焦點,則爲True;不然爲False。
實現過程
(1)建立一個項目,將其命名爲Ex01_08,默認窗體爲Form1。
(2)從工具箱中爲Form1窗體添加Panel控件,併爲Panel控件添加相應的背景圖片。
(3)在Panel上添加兩個Label控件,並將其Text屬性設置爲「打開」和「關閉」,同時把兩個Label控件的背景顏色設置爲透明。
(4)主要程序代碼。
private void timer1_Tick(object sender, EventArgs e)
{
if (this.Focused == false)
{
this.Top = -30;
}
}
private void label2_Click(object sender, EventArgs e)
{
this.Close();
}
private void panel1_MouseClick(object sender, MouseEventArgs e)
{
this.Top = 60;
}
觸類旁通
根據本實例,讀者能夠開發如下功能。
製做一個帶動畫效果的工具欄。
製做一個飄動的工具欄。
實例009 在帶下拉菜單的工具欄
實例說明
工具欄是窗體的組成部分之一,工具欄中的按鈕能夠完成一些較爲經常使用或重要的功能,本例中設計了一個工具欄,使工具欄帶有下拉菜單,效果如圖1.9所示。
技術要點
帶下拉菜單的工具欄在其餘計算機語言中實現比較複雜,但在.NET 2.0中已經提供了這個功能,只需將工具欄按鈕的類型設置爲DropDownButton便可。
實現過程
(1)建立一個項目,將其命名爲Ex01_09,默認窗體爲Form1。
(2)從工具箱中爲窗體添加ToolStrip控件,併爲工具欄添加相應的按鈕,在按鈕的下拉選項中選擇DropDownButton類型。
(3)爲工具欄DropDownButton類型的按鈕設置相應的下拉菜單,就能夠輕鬆實現帶下拉菜單的工具欄。
觸類旁通
根據本實例,讀者能夠開發如下功能。
製做一個帶右鍵菜單的工具欄。
製做一個帶複選框的工具欄。
實例010 在具備提示功能的工具欄
實例說明
在文檔\視圖結構的應用程序中,默認狀況下,當鼠標在工具欄按鈕上停留片刻,會出現一個工具提示條。本例實現了一個具備提示功能的工具欄,效果如圖1.10所示。
技術要點
具備提示功能的工具欄在其餘計算機語言中實現也許比較複雜,但在.NET 2.0中已經提供了這個功能。只需將工具欄按鈕的ToolTipText設置爲要提示的內容便可。下面詳細介紹一下該屬性。
ToolTipText屬性用來獲取或設置做爲控件的ToolTip顯示的文本。其語法結構以下:
public string ToolTipText { get; set; }
l 屬性值:一個表示工具提示文本的字符串。
實現過程
(1)建立一個項目,將其命名爲Ex01_10,默認窗體爲Form1。
(2)從工具箱中爲Form1窗體添加ToolStrip控件用來設計工具欄,併爲工具欄添加相應的按鈕。
(3)爲相應按鈕的ToolTipTile屬性設置提示內容,就能夠輕鬆實現具備提示功能的工具欄。
觸類旁通
根據本實例,讀者能夠開發如下功能。
具備提示功能的各類控件。
具備提示功能的窗體。
1.3 狀態欄設計
狀態欄是用來顯示當前程序狀態的。狀態欄能夠分爲多個面板,用來顯示不一樣狀態下的內容,本節主要介紹了狀態欄的用法以及如何在狀態欄中添加控件。
實例011 在狀態欄中顯示檢查框
實例說明
在設計程序界面時,爲了規範界面,能夠將一些控件放置在狀態欄中,這樣既能起到控制程序的做用,又能使界面和諧、美觀。運行程序,在窗體的狀態欄中加入了顯示時間檢查框。效果如圖1.11所示。
技術要點
在狀態欄中添加檢查框比較容易,只需先將狀態欄加入窗體,而後將檢查框從工具箱中拖入狀態攔便可。
實現過程
(1)建立一個項目,將其命名爲Ex01_11,默認窗體爲Form1。
(2)從工具箱中爲Form1窗體添加StatusStrip控件,並從工具箱中爲狀態欄添加CheckBox控件。
(3)主要程序代碼。
private void checkBox2_CheckedChanged(object sender, EventArgs e)
{
if (this.checkBox2.Checked)
{
statusStrip1.Items[1].Text = "日期:" + DateTime.Now.ToString();
}
else
{
statusStrip1.Items[1].Text = "";
}
}
觸類旁通
根據本實例,讀者能夠開發如下功能。
運行時設置控件的位置。
動態控制控件的顯示。
實例012 帶進度條的狀態欄
實例說明
上網瀏覽網頁的讀者都用過IE瀏覽器,讀者是否注意到該瀏覽器的狀態欄,在打開網頁的過程當中,瀏覽器下邊的狀態欄中有一個進度條顯示當前網頁的載入進度,這樣的狀態欄使界面顯得更加豐富多彩,而且很是實用。本例將設計一個帶進度條的狀態欄,而且在程序運行當中進度條能夠顯示其進度,該實例運行結果如圖1.12所示。
技術要點
帶進度條的狀態欄在別的開發環境下實現相對比較複雜,但在.NET 2.0中已經提供了這個功能,只需將狀態欄的按鈕類型設置爲ProgressBar便可。經過設置ProgressBar的Step 屬性指定一個特定值用以逐次遞增Value屬性的值,而後調用PerformStep方法來使該值遞增,就能夠實現帶進度條的狀態欄。
實現過程
(1)建立一個項目,將其命名爲Ex01_12,默認窗體爲Form1。
(2)從工具箱中爲Form1窗體添加StatusStrip控件,併爲狀態欄添加相應的按鈕,在按鈕的下拉選項中選擇ProgressBar類型。
(3)設置ToolStripProgressBar1的Value屬性、Maximum屬性和Step屬性。
(4)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
while (toolStripProgressBar1.Value < toolStripProgressBar1.Maximum)
{
this.toolStripProgressBar1.PerformStep();
}
}
觸類旁通
根據本實例,讀者能夠開發如下功能。
在狀態欄中顯示時間。
改變進度條的顏色。
實例013 狀態欄中加入圖標
實例說明
狀態欄已經成爲主界面必不可少的部分,狀態欄通常用於顯示程序狀態、當前日期等,在狀態欄中添加一張圖片會使程序的主界面更有特點。運行本例,效果如圖1.13所示。
技術要點
狀態欄中加入圖標在.NET 2.0中實現很是容易,只要將對應狀態欄面板的Image屬性設置爲要顯示的圖片便可。
實現過程
(1)建立一個項目,將其命名爲Ex01_13,默認窗體爲Form1。
(2)從工具箱中爲Form1窗體添加StatusStrip控件,併爲狀態欄添加相應的按鈕,設置添加的按鈕的Image屬性爲要顯示的圖片。
觸類旁通
根據本實例,讀者能夠實現如下功能。
將其餘控件放置在狀態欄中,如進度條。
將其餘控件放置在狀態欄中,如複選框。
1.4 導航菜單界面
對於一些應用工具軟件,界面不但要求人性化、漂亮,還要突出界面功能、使用方便,這樣才能吸引用戶使用。本節主要介紹了經常使用的幾種菜單界面。
實例014 OutLook界面
實例說明
程序主界面包括菜單欄、工具欄、狀態欄和樹狀視圖。OutLook界面美觀、友好,是一個很實用的程序主界面,而且菜單欄和工具欄是可移動的。運行本例效果如圖1.14所示。
圖1.14 Out Look界面
技術要點
通常程序的菜單欄和工具欄是不可移動的,可是隻要將MenuStrip和ToolStrip控件的AllowItemRecorder屬性設爲True就能夠移動。在本例中使用MenuStrip控件製做菜單欄,使用ToolStrip製做工具欄,使用StatusStrip控件製做狀態欄。下面詳細介紹一下這幾個控件的屬性。
1.ToolStrip. AllowItemReorder屬性
獲取或設置一個值,該值指示是否由ToolStrip類私自處理拖放和項從新排序。其結構以下:
public bool AllowItemReorder { get; set; }
l 屬性值:若是讓ToolStrip類自動處理拖放和項從新排序,爲True;不然爲False。默認值爲False。
2.MenuStrip. AllowItemReorder屬性
獲取或設置一個值,該值指示是否由ToolStrip類私自處理拖放和項從新排序。其結構以下:
public bool AllowItemReorder { get; set; }
l 屬性值:若是讓 MenuStrip類自動處理拖放和項從新排序,爲True;不然爲False。默認值爲False。
3.ToolStripItem.DisplayStyle屬性
獲取或設置是否在ToolStripItem上顯示文本和圖像。
public virtual ToolStripItemDisplayStyle DisplayStyle { get; set; }
l 屬性值:ToolStripItemDisplayStyle值之一。默認爲ImageAndText。
注意:在移動菜單欄和工具欄時,須要按住「Alt」鍵,同時用鼠標進行拖動。
實現過程
(1)建立一個項目,將其命名爲Ex01_14,默認窗體爲Form1。
(2)在Form1窗體上添加MenuStrip控件,用來設計主菜單;添加ToolStrip控件,用來設計工具欄;添加StatusStrip控件,用來設計狀態欄;添加ImageList控件和TreeVew控件,用來設計樹結構。
(3)分別爲MenuStrip控件、ToolStrip控件、ImageList控件和TreeVew控件添加子項,將MenuStrip控件和ToolStrip控件的AllowItemRecorder屬性設爲True,並將ToolStrip控件的每一個子項的DisplayStyle屬性設置爲「ImageAndText」。下面詳細介紹這幾個屬性。
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做一個系統菜單。
製做一個導航界面。
實例015 帶帶導航菜單的主界面
實例說明
在窗體界面中,菜單欄是不可缺乏的重要組成部分。本實例是用其餘的控件來製做一個摸擬菜單欄。運行程序,單擊窗體上面的按鈕,將會在按鈕的下面顯示一個下拉列表。如圖1.15所示。
技術要點
該實例中主要使用Button控件和ListView控件製做導航菜單界面。在對ListView控件添加菜單信息時,必需在前面寫入添加語句,如Listview.Items.Add,不然添加的菜單信息將替換前一條信息。單擊相應的按鈕時,應首先對ListView控件進行清空,不然在ListView控件中將繼續上一次的添加菜單信息。
實現過程
(1)建立一個項目,將其命名爲Ex01_15,默認窗體爲Form1。
(2)在Form1窗體上添加MenuStrip控件設計菜單欄;添加ToolStrip控件設計工具欄;添加SplitContainer控件、ImageList控件、3個Button控件和ListView控件用來製做左側的導航欄。
(3)分別爲MenuStrip控件、ToolStrip控件添加子項,將3個Button按鈕和ListView控件加入SqlitContainer1.panel的左側部分中。
(4)主要程序代碼。
加載窗體時,設置左側導航欄內容的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
listView1.Clear();
listView1.LargeImageList = imageList1;
listView1.Items.Add("設置上下班時間", "設置上下班時間", 0);
listView1.Items.Add("是否啓用短信提醒", "是否啓用短信提醒", 1);
listView1.Items.Add("設置密碼", "設置密碼", 2);
}
添加打開按鈕的ListView控件顯示內容的實現代碼以下:
private void button2_Click_1(object sender, EventArgs e)
{
listView1.Dock = DockStyle.None;
button2.Dock = DockStyle.Top;
button1.SendToBack();
button1.Dock = DockStyle.Top;
button3.Dock = DockStyle.Bottom;
listView1.Dock = DockStyle.Bottom;
listView1.Clear();
listView1.Items.Add("近期工做記錄", "近期工做記錄", 3);
listView1.Items.Add("近期工做計劃", "近期工做計劃", 4);
}
添加編輯按鈕的ListView控件顯示內容的實現代碼以下:
private void button3_Click_1(object sender, EventArgs e)
{
listView1.Dock = DockStyle.None;
button3.SendToBack();
button3.Dock = DockStyle.Top;
button2.SendToBack();
button2.Dock = DockStyle.Top;
button1.SendToBack();
button1.Dock = DockStyle.Top;
listView1.Dock = DockStyle.Bottom;
listView1.Clear();
listView1.Items.Add("編輯工做進度報告", "編輯工做進度報告", 5);
listView1.Items.Add("編輯項目設計圖", "編輯項目設計圖", 6);
}
添加設置按鈕的ListView控件顯示內容的實現代碼以下:
private void button1_Click_1(object sender, EventArgs e)
{
listView1.Dock = DockStyle.None;
button1.Dock = DockStyle.Top;
button2.Dock = DockStyle.Bottom;
button3.SendToBack();
button3.Dock = DockStyle.Bottom;
listView1.BringToFront();
listView1.Dock = DockStyle.Bottom;
listView1.Clear();
listView1.Items.Add("設置上下班時間", "設置上下班時間", 0);
listView1.Items.Add("是否啓用短信提醒", "是否啓用短信提醒",1);
listView1.Items.Add("設置密碼", "設置密碼", 2);
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做一個系統菜單。
製做大型系統的導航界面。
實例016 圖形化的導航界面
實例說明
若是以按鈕來代替菜單的功能,會使界面更具備個性化。使操做者更易於操做。下面介紹按鈕顯示菜單的設計方法。運行本例,效果如圖1.16所示。
圖1.16 圖形化的導航界面
技術要點
本實例主要經過設置Button控件的相應屬性,肯定其按鈕的位置、文字、顯示樣式和要顯示的圖片等。下面對Button控件相應屬性進行詳細介紹。
1.Button. BackColor屬性
獲取或設置控件的背景色,其方法結構以下:
public override Color BackColor { get; set; }
l 屬性值:一個表示背景色的Color值。
2.Button. FlatStyle屬性
獲取或設置按鈕控件的平面樣式外觀。其代碼以下:
public FlatStyle FlatStyle { get; set; }
l 屬性值:FlatStyle 值之一。默認值爲Standard。
3.Button. TextImageRelation屬性
獲取或設置文本和圖像相互之間的相對位置。其代碼以下:
public TextImageRelation TextImageRelation { get; set; }
l 屬性值:TextImageRelation 的值之一。默認爲Overlay。
實現過程
(1)建立一個項目,將其命名爲Ex01_16,默認窗體爲Form1。
(2)在Form1窗體上添加MenuStrip控件用來設計菜單欄,添加ToolStrip控件用來設計工具欄,添加Panel控件、Button控件用來設計圖形化的導航按鈕。
(3)分別爲MenuStrip控件、ToolStrip控件添加子項,併爲Panel控件選擇背景圖片。
(4)將Button控件的BackColor屬性設爲「Transparent」、FlatStyle屬性設置爲「Flat」、TextImageRelation屬性設置爲「ImageBeforeText」。
(5)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
//使子項可見
button5.Visible = true;
button6.Visible = true;
button7.Visible = true;
}
private void button2_Click(object sender, EventArgs e)
{
//使子項可見
button8.Visible = true;
button9.Visible = true;
button10.Visible = true;
}
private void button3_Click(object sender, EventArgs e)
{
//使子項可見
button11.Visible = true;
button12.Visible = true;
button13.Visible = true;
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做動態的按鈕界面。
製做動態的圖片界面。
1.5 特點程序界面
如今有不少開發人員都將界面製做成不一樣類型的樣式,這樣可使界面更加形象化。本節主要介紹瞭如何對程序界面進行特點化設計,如相似QQ、Windows XP的界面等。
實例017 菜類QQ的程序界面
實例說明
通常程序都是以菜單欄和工具欄的形式調用其餘功能模塊,若是以動態的相似QQ的程序界面來調用其餘功能模塊,將會給用戶一種新鮮的感受,使用戶對軟件更感興趣。實例運行結果如圖1.17所示。
技術要點
本例主要使用Button控件來完成佈局,使用ListView控件來顯示有圖標的功能菜單。ListView控件的經常使用屬性及說明以下。
1.ListView.Items屬性
使用該屬性可直接訪問表示列表中項目的ListItem對象。其結構以下:
public ListViewItemCollection Items { get; }
l 屬性值: ListView.ListViewItemCollection包含ListView控件中全部的項。
2.ListView.Dock屬性
獲取或設置哪些控件邊框停靠到其父控件並肯定控件如何隨其父級一塊兒調整大小。其結構以下:
public virtual DockStyle Dock { get; set; }
l 屬性值:DockStyle值之一。默認爲None。
實現過程
(1)建立一個項目,將其命名爲Ex01_17,默認窗體爲Form1。
(2)在窗體上添加Button控件、ListView控件和ImageList控件。設置ListView控件的ImageList屬性爲ImageList控件。
(3)主要程序代碼。
添加「個人好友」選項內容的實現代碼以下:
private void button1_Click(object sender, EventArgs e)
{
listView1.Dock = DockStyle.None;
button1.Dock = DockStyle.Top;
button2.Dock = DockStyle.Bottom;
button3.SendToBack();
button3.Dock = DockStyle.Bottom;
listView1.BringToFront();
listView1.Dock = DockStyle.Bottom;
listView1.Clear();
listView1.Items.Add("小豬", "小豬", 0);
listView1.Items.Add("小狗", "小狗", 1);
listView1.Items.Add("嬌嬌", "嬌嬌", 2);
}
添加默認時選項內容的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
listView1.Clear();
listView1.LargeImageList = imageList1;
listView1.Items.Add("小豬", "小豬", 0);
listView1.Items.Add("小狗", "小狗", 1);
listView1.Items.Add("嬌嬌", "嬌嬌", 2);
}
添加「陌生人」選項內容的實現代碼以下:
private void button2_Click(object sender, EventArgs e)
{
listView1.Dock = DockStyle.None;
button2.Dock = DockStyle.Top;
button1.SendToBack();
button1.Dock = DockStyle.Top;
button3.Dock = DockStyle.Bottom;
listView1.Dock = DockStyle.Bottom;
listView1.Clear();
listView1.Items.Add("北風", "北風", 3);
}
添加「黑名單」選項內容的實現代碼以下:
private void button3_Click(object sender, EventArgs e)
{
listView1.Dock = DockStyle.None;
button3.SendToBack();
button3.Dock = DockStyle.Top;
button2.SendToBack();
button2.Dock = DockStyle.Top;
button1.SendToBack();
button1.Dock = DockStyle.Top;
listView1.Dock = DockStyle.Bottom;
listView1.Clear();
listView1.Items.Add("冰雨", "冰雨", 5);
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
根據數據庫信息造成相應的功能列表。
製做聊天界面。
實例018 相似windows xp的程序界面
實例說明
在Windows XP環境下打開控制面板,會發現左側的導航界面很實用。雙擊展開按鈕,導航欄功能顯示出來,雙擊收縮按鈕,導航按鈕收縮。下面經過實例介紹此種主窗體的設計方法。運行本例,效果如圖1.18所示。
技術要點
PictureBox控件是一個圖像顯示控件,該控件主要以其中的Image屬性存儲圖像數據。其詳細介紹以下。
PictureBox.Image屬性用來獲取或設置 PictureBox 顯示的圖像,其語法格式以下:
public Image Image { get; set; }
圖1.18 相似windows xp的程序界面
l 屬性值:要顯示的Image。
實現過程
(1)建立一個項目,將其命名爲Ex01_18,默認窗體爲Form1。
(2)在Form1窗體上添加Button控件、PictureBox控件和label控件,佈局如圖1.18所示。
(3)主要程序代碼。
雙擊「向下箭頭」的實現代碼以下:
private void pictureBox5_Click(object sender, EventArgs e)
{
//使子項收縮
int i ;
i=80;
pictureBox5.Visible = false;
pictureBox4.Visible = false;
label2.Visible = false;
label3.Visible = false;
pictureBox6.Top -= i;
pictureBox8.Top -= i;
label4.Top -= i;
label5.Top -= i;
label6.Top -= i;
label10.Top -= i;
label7.Top -= i;
label8.Top -= i;
label9.Top -= i;
pictureBox9.Top -= i;
pictureBox11.Top -= i;
}
雙擊「向上箭頭」的實現代碼以下:
private void pictureBox2_Click(object sender, EventArgs e)
{
//展開子項
if (pictureBox5.Visible == false)
{
int i;
i = 80;
pictureBox5.Visible = true;
pictureBox4.Visible = true;
label2.Visible = true;
label3.Visible = true;
pictureBox6.Top += i;
pictureBox8.Top += i;
label4.Top += i;
label5.Top += i;
label6.Top += i;
label10.Top += i;
label7.Top += i;
label8.Top += i;
label9.Top += i;
pictureBox9.Top += i;
pictureBox11.Top += i;
}
}
private void Form1_Load(object sender, EventArgs e)
{
SetStyle(ControlStyles.SupportsTransparentBackColor,true);
}
注意:在對控件的高度進行遞增或遞減的時候,數值不要過小。
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做Windows XP控制面板。
製做Windows XP開始導航菜單。
實例019 以圖形按鈕顯示的界面
實例說明
菜單和工具欄雖然能方便用戶操做程序的相應功能,但各有缺點。若是採用按鈕式功能菜單,不但美觀大方,並且操做靈活。當單擊按鈕時,用戶區將顯示相應的操做按鈕組。下面介紹圖形界面式菜單的設計方法。運行本例,效果如圖1.19所示。
圖1.19 以圖形按鈕顯示的界面
技術要點
本例中用到了Image.FromFile方法和PictureBox.Image屬性,下面詳細介紹一下。
(1)Image.FromFile方法:從指定的文件建立Image。該函數的結構爲:
public static Image FromFile (string filename)
參數說明以下。
l filename:當前目錄的指定路徑字符串,包含要從中建立Image的文件的名稱。
l 返回值:此方法建立的Image。
(2)PictureBox.Image屬性:獲取或設置PictureBox顯示的圖像。其屬性結構爲:
public Image Image { get; set; }
l 屬性值:要顯示的Image。
注意:在本例中不易使窗體最大化。如最大化,會使Label控件不在正確的位置上。
實現過程
(1)建立一個項目,將其命名爲Ex01_19,默認窗體爲Form1。
(2)在Form1窗體上添加MenuStrip控件用來設計菜單;添加Picture控件、Panel控件用來設計圖形顯示的界面。
(3)將panel的背景圖片設置爲圖1.19所示,並在圖片上添加Label控件,同時將Label控件的BackColor屬性設置爲transparency。
(4)主要程序代碼。
private void label1_Click(object sender, EventArgs e)
{
pictureBox3.Image= Image.FromFile("3.jpg");//爲控件加載圖像
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做圖片的動態更新。
製做一個圖片瀏覽器。
實例020 以樹形顯示的程序界面
實例說明
以樹形來顯示程序的菜單,能夠更直觀更快捷的對軟件進行操做。樹形菜單比菜單欄更加美觀實用。下面介紹樹形界面菜單的設計方法。運行本例效果如圖1.20所示。
圖1.20 以樹形顯示的程序界面
技術要點
在對TreeView控件輸入記錄時,雙擊Nodes屬性就能夠對TreeView的節點進行設置。
能夠在窗體的Load事件中輸入下面的一條命令:
treeView1.ExpandAll();
功能:展開TreeView控件中全部的下級菜單。
實現過程
(1)建立一個項目,將其命名爲Ex01_20,默認窗體爲Form1。
(2)在窗體上添加MenuStrip控件用來設計菜單欄,添加PictureBox控件用來顯示圖片,添加TreevVew控件用來設計左側樹形導航界面。
(3)爲PictureBox添加背景圖片,給MenuStrip控件和TreevVew控件添加子項。
(4)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
treeView1.ExpandAll();
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做一個動態的從數據庫中讀取數據的樹型界面。
製做一個帶圖標的樹型界面。
實例021 動態按鈕的窗體界面
實例說明
在窗體界面中,一般以按鈕來代替菜單欄的功能,這種形式雖然給用戶一種直觀,界面風格各異的感黨,但一般按鈕都是以靜止的形式顯示,若是使光標移到按鈕時,可使按鈕上的圖片和文字說明動態化,使用戶快捷地找到所選按鈕。這樣就須要一個動態的按鈕顯示界面。運行本例效果如圖1.21所示。
圖1.21 動態按鈕的窗體界面
技術要點
在編輯過程當中,首先在Button控件中的Image屬性中添加圖片,而後將Button控件的ImageAlign屬性設置爲MiddleCenter,使圖片居中。在設置Button控件的動態圖片時,必須在相應控件的MouseMove事件中設置。
1.Button.Image屬性
獲取或設置顯示在按鈕控件上的圖像,其語法格式以下:
public Image Image { get; set; }
l 屬性值:按鈕控件上顯示的Image。默認值爲空引用。
2.Button. ImageAlign屬性
獲取或設置按鈕控件上的圖像對齊方式,其語法格式以下:
public ContentAlignment ImageAlign { get; set; }
l 屬性值:ContentAlignment值之一。默認值爲MiddleCenter。
注意:當鼠標移開Button控件時,圖片與字應及時恢復原位。
實現過程
(1)建立一個項目,將其命名爲Ex01_21,默認窗體爲Form1。
(2)在Form1窗體上添加PictureBox用來顯示圖片,添加Button、Lable控件用來設計動態按鈕。
(3)爲PictureBox控件設置背景圖片,將Lable控件的Text屬性設置爲「明日科技有限公司」,併爲每一個Button控件設置圖片和文字。
(4)主要程序代碼。
private void button1_MouseMove(object sender, MouseEventArgs e)
{
//鼠標移動時改變圖片位置
button1.ImageAlign = ContentAlignment.MiddleLeft;
}
private void button2_MouseMove(object sender, MouseEventArgs e)
{
button2.ImageAlign = ContentAlignment.MiddleLeft;
}
private void button3_MouseMove(object sender, MouseEventArgs e)
{
button3.ImageAlign = ContentAlignment.MiddleLeft;
}
private void button4_MouseMove(object sender, MouseEventArgs e)
{
button4.ImageAlign = ContentAlignment.MiddleLeft;
}
private void button5_MouseMove(object sender, MouseEventArgs e)
{
button5.ImageAlign = ContentAlignment.MiddleLeft;
}
private void button1_MouseLeave(object sender, EventArgs e)
{
button1.ImageAlign = ContentAlignment.MiddleCenter;
}
//鼠標離開時改變圖片位置
private void button2_MouseLeave(object sender, EventArgs e)
{
button2.ImageAlign = ContentAlignment.MiddleCenter;
}
private void button3_MouseLeave(object sender, EventArgs e)
{
button3.ImageAlign = ContentAlignment.MiddleCenter;
}
private void button4_MouseLeave(object sender, EventArgs e)
{
button4.ImageAlign = ContentAlignment.MiddleCenter;
}
private void button5_MouseLeave(object sender, EventArgs e)
{
button5.ImageAlign = ContentAlignment.MiddleCenter;
}
private void button6_MouseMove(object sender, MouseEventArgs e)
{
button6.ImageAlign = ContentAlignment.MiddleLeft;
}
private void button6_MouseLeave(object sender, EventArgs e)
{
button6.ImageAlign = ContentAlignment.MiddleCenter;
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
根據所給圖片製做相應的窗體界面。
用圖片代替控件製做相應的窗體界面。
1.6 特殊形狀的窗體
將界面以不規則的形狀顯示在桌面上,能夠給用戶一種新鮮的感受。本節主要對窗體以特殊的形狀進行顯示,如非矩形窗體和字體形窗體等。
實例022 非矩形窗體
實例說明
大部分Windows窗體都是一個矩形區域,讀者是否已經厭倦了這種中規中矩的矩形窗體?本例中的窗體是一個打破傳統矩形的異型窗體,運行該例會看到一個很是可愛的窗體,單擊【X】按鈕就會使窗口關閉。實例效果如圖1.22所示。
技術要點
之前,建立非矩形窗體是一個既費時又費人力的過程,其中涉及到 API 調用和大量的編程工做。在.NET 2.0框架中能夠不調用API很是輕鬆的實現這一功能。只要重寫窗體的OnPaint方法,在方法中從新繪製窗體,而後用透明色將窗體設置透明便可。
(1)Form.OnPaint方法:此成員重寫Control.OnPaint。用來從新繪製窗體圖像。其結構以下:
protected override void OnPaint (PaintEventArgs e)
參數說明以下。
l PaintEventArgs:爲Paint事件提供數據。
實現過程
(1)建立一個項目,將其命名爲Ex01_22,默認窗體爲Form1。
(2)在窗口中添加Label控件,並將BackColor屬性設爲透明,將text屬性設爲空。
(3)將窗體的TransparencyKey屬性設爲窗體的背景色。
(4)主要程序代碼。
設置圖片透明顏色的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
bit = new Bitmap("Heart.bmp");
bit.MakeTransparent(Color.Blue);
}
重寫基類方法,具體代碼以下:
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage((Image)bit, new Point(0, 0));//將圖片畫出
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
能夠把窗體制作成各類卡通圖形。
能夠將窗體制作成各類幾何圖形。
能夠將窗體制作成桌面小精靈。
實例023 創建字體形狀窗體
實例說明
你們都見過不規則形狀的窗體吧,那麼如何製做一個文字形的窗體呢?文字形窗體通常應用在屏幕提示中,如收款機屏幕等。運行本例,效果如圖1.23所示。
技術要點
之前,建立字體形窗體是一個既費時又費人力的過程,其中涉及到API調用和大量的編程工做。在.NET 2.0框架中能夠不調用API很是輕鬆的實現這一功能。只要先將字體畫在一幅圖上,而後重寫窗體的OnPaint方法(方法的詳細內容能夠參見實例022),在方法中用圖從新繪製窗體,用背景色將窗體設置透明便可。
實現過程
(1)建立一個項目,將其命名爲Ex01_23,默認窗體爲Form1。
(2)主要程序代碼。
namespace SpecialSharpWindows
{
public partial class Form1 : Form
{
Bitmap bit;
public Form1()
{
InitializeComponent();
}
設置圖片透明顏色的實現。代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
bit = new Bitmap("1.bmp");
bit.MakeTransparent(Color.Blue);
}
重寫基類方法的實現。代碼以下:
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImage((Image)bit, new Point(0, 0));
}
private void label1_Click(object sender, EventArgs e)
{
this.Close();
}
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做圓形的窗體。
製做鋸齒狀的窗體。
實例024 控件隨窗體自動調整
實例說明
在軟件開發中,隨着窗體的大小變化,界面會和設計時出現較大的差別,控件和窗體的大小會不成比例很是不美觀。本例中的控件是一個能夠隨窗體大小變化的控件。運行該例會看到一個控件隨窗體大小變化的窗體。實例效果如圖1.24所示。
技術要點
在.NET 2.0框架中能夠很是輕鬆的實現這一功能。大多數控件都有Anthor屬性,當在窗體上添加控件時設置Anthor屬性便可。Anthor屬性是個錨定屬性,指定了控件距容器邊緣的距離。當窗體大小變化時,控件距窗體邊緣的距離不變,天然大小就隨窗體自動調整。
實現過程
(1)建立一個項目,將其命名爲Ex01_24,默認窗體爲Form1。
(2)在窗體上添加MenuStrip控件、ToolStrip控件和Button控件。並設置Button的Anthor屬性和Text屬性。
觸類旁通
根據本實例,讀者能夠實現如下功能。
圖片大小隨着窗體大小變化的窗體。
菜單欄大小隨着窗體大小變化的窗體。
實例025 帶分隔欄的窗體
實例說明
在軟件開發中,常常須要將界面分紅幾個部分,並且這幾個部分又能夠自由調整大小。運行本例,實例效果如圖1.25所示。
技術要點
在.NET 2.0框架中能夠很是輕鬆的實現這一功能,只要在窗體中加入SplitContainer控件便可。SplitContainer控件帶有一個分隔欄,用來把窗體分紅兩部分。
實現過程
(1)建立一個項目,將其命名爲Ex01_25,默認窗體爲Form1。
(2)在Form1窗體上添加MenuStrip控件用來設計菜單欄,添加ToolStrip控件用來設計工具欄,添加SplitContainer控件用來設計分隔欄。
觸類旁通
根據本實例,讀者能夠實現如下功能。
分紅3部分的窗體。
分紅4部分的窗體。
實例026 隨機更換主界面背景
實例說明
若是開發的軟件用戶使用頻率很是高,能夠爲程序設計隨機更換背景的程序。這樣不但可使用戶心情愉快,也增長了軟件的人性化設計。下面的界面就是一個隨機更換主界面的例子,效果如圖1.26所示。
技術要點
隨機更換主界面背景使用了Random類和ImageList控件。首先爲ImageList控件添加一組圖片,而後實例化一個Random類,再用Next()方法產生一個隨機數以決定將哪一個圖片設爲背景。
Random.Next()方法用來返回一個小於所指定最大值的非負隨機數。其結構以下:
public virtual int Next (int maxValue)
參數說明以下。
l maxValue:要生成的隨機數的上界(隨機數不能取該上界值)。maxValue必須大於或等於零。
l 返回值:大於或等於零且小於maxValue的32位帶符號整數,即返回的值範圍包括零但不包括maxValue。
實現過程
(1)建立一個項目,將其命名爲Ex01_26,默認窗體爲Form1。
(2)在Form1窗體上添加ImageList控件,併爲ImageList控件添加圖片。
(3)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
Random rdn = new Random();
int i = rdn.Next(imageList1.Images.Count);//產生一個隨機數
this.BackgroundImage = imageList1.Images[i];
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
天天更換主程序背景的主界面。
隨機更換菜單欄、工具欄圖標的主程序。
1.7 多媒體光盤
本節主要介紹瞭如何自動啓動多媒體光盤和觸摸屏的相關技術。自動啓動多媒體光盤技術應用十分普遍,如今的光盤大多應用這些技術,節省了用戶單擊進入的時間。
實例027 自動啓動的多媒體光盤程序
實例說明
用戶在安裝軟件時,將光盤放入光驅內,光盤會自動運行,進行安裝操做,該功能是如何實現的呢?本例介紹如何製做「自動安裝的光盤程序」,程序運行效果如圖1.27所示。
技術要點
其實,實現光盤的自動運行很是簡單,當用戶打開自動運行的光盤時,會發現光盤中有幾個特殊的文件,分別爲「autorun.exe」、「run.ico」和「autorun.inf」,其中「autorun.exe」是光盤自動播放時執行的可執行文件,「run.ico」是光盤的圖標,「autorun.inf」是一個INI文件。只要光盤中包含這些文件,那麼在將光盤放入光驅時,就會自動運行。
實現過程
(1)建立一個項目,將其命名爲Ex01_27,默認窗體爲Form1。
(2)爲Form1窗體添加背景圖片Button控件。
(3)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
StreamWriter sw = new StreamWriter("AutoRun.inf",false);
sw.WriteLine("[autorun]");
sw.WriteLine("OPEN=AUTORUN.EXE");
sw.WriteLine("ICON=run.ICO");
sw.Close();
}
(4)運行程序,將可執行文件命名爲「autorun.exe」,該文件就是光盤自動播放時打開的文件。
(5)選擇一個圖標,命名爲「run.ico」,該圖標在光驅讀盤時顯示。
(6)在刻光盤時,將上面的「run.ico」、「autorun.inf」和「autorun.exe」3個文件刻錄到光盤中。
觸類旁通
根據本實例,讀者能夠開發如下程序。
設計多媒體宣傳光盤。
製做後門程序。
實例028 爲觸摸屏程序添加虛擬鍵盤
實例說明
因爲觸摸屏沒有鍵盤,只能利用屏幕操做。若是要輸入數據或查找數據,須要製做一個虛擬鍵盤,以方便用戶輸入。本例介紹如何實現虛擬鍵盤的程序設計。運行本例,效果如圖1.28所示。
技術要點
本例中用到了Lable控件的透明屬性和字符串截取技術。主要是使用Substring()方法。下面詳細介紹一下該方法。
Substring()方法用來今後實例檢索子字符串。子字符串從指定的字符位置開始且具備指定的長度。其語法結構以下:
public string Substring (int startIndex,int length)
參數說明以下。
l startIndex:子字符串起始位置的索引。
l length:子字符串中的字符數。
l 返回值:一個String,等於此實例中從startIndex開始的長度爲length的子字符串,若是startIndex等於此實例的長度且length爲零,則爲Empty。
實現過程
(1)建立一個項目,將其命名爲Ex01_28,默認窗體爲Form1。
(2)在窗體上添加2個Panel控件,1個TextBox控件和許多Label控件,每一個Label控件對應背景圖片上的1個按鈕。
(3)爲Panel控件添加背景圖片,並將Label控件的BackColor設置爲透明。
(4)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
lbl_0.Click += new EventHandler(lbl_Click);
lbl_1.Click += new EventHandler(lbl_Click);
lbl_2.Click += new EventHandler(lbl_Click);
lbl_3.Click += new EventHandler(lbl_Click);
lbl_4.Click += new EventHandler(lbl_Click);
lbl_5.Click += new EventHandler(lbl_Click);
lbl_6.Click += new EventHandler(lbl_Click);
lbl_7.Click += new EventHandler(lbl_Click);
lbl_8.Click += new EventHandler(lbl_Click);
lbl_9.Click += new EventHandler(lbl_Click);
lbl_Q.Click += new EventHandler(lbl_Click);
lbl_W.Click += new EventHandler(lbl_Click);
lbl_R.Click += new EventHandler(lbl_Click);
lbl_E.Click += new EventHandler(lbl_Click);
lbl_T.Click += new EventHandler(lbl_Click);
lbl_Y.Click += new EventHandler(lbl_Click);
lbl_U.Click += new EventHandler(lbl_Click);
lbl_I.Click += new EventHandler(lbl_Click);
lbl_O.Click += new EventHandler(lbl_Click);
lbl_P.Click += new EventHandler(lbl_Click);
lbl_A.Click += new EventHandler(lbl_Click);
lbl_S.Click += new EventHandler(lbl_Click);
lbl_D.Click += new EventHandler(lbl_Click);
lbl_F.Click += new EventHandler(lbl_Click);
lbl_G.Click += new EventHandler(lbl_Click);
lbl_H.Click += new EventHandler(lbl_Click);
lbl_J.Click += new EventHandler(lbl_Click);
lbl_K.Click += new EventHandler(lbl_Click);
lbl_L.Click += new EventHandler(lbl_Click);
lbl_Z.Click += new EventHandler(lbl_Click);
lbl_X.Click += new EventHandler(lbl_Click);
lbl_C.Click += new EventHandler(lbl_Click);
lbl_V.Click += new EventHandler(lbl_Click);
lbl_B.Click += new EventHandler(lbl_Click);
lbl_N.Click += new EventHandler(lbl_Click);
lbl_M.Click += new EventHandler(lbl_Click);
label44.Click += new EventHandler(label44_Click);
}
將選中的數字或字母加入TextBox.Text的實現代碼以下:
void lbl_Click(object sender, EventArgs e)
{
Label l = (Label)sender;
textBox1.Text += l.Name.Substring(4, 1);
textBox1.SelectionStart = textBox1.Text.Length;
}
觸類旁通
根據本實例,讀者能夠實現如下程序。
製做註冊控件的程序。
製做網絡程序複製的程序。
1.8 窗體效果
本節主要是對窗體的透明度、顏色漸變、背景及邊框的相關技術進行講解。在項目開發中窗體的設計會影響用戶對軟件的總體印象,因此窗體的效果要設計的美觀一些。下面將介紹一些經常使用的效果。
實例029 半透明漸顯窗體
實例說明
不少專業軟件在啓動前都會顯示一個說明該軟件信息或用途的窗口,有的則是一個漂亮的啓動界面,如Adobe公司的Acrobat。該窗口使軟件顯得更加專業。本例將實現一個半透明的漸顯窗體,運行本軟件會顯示一個啓動畫面,而且畫面會將徹底透明慢慢到半透明的效果顯示在用戶面前。效果如圖1.29所示。
圖1.29 半透明濺顯窗體
技術要點
在其餘開發環境中,實現窗體的半透明漸顯須要調用API函數,實現很是困難,但在C# 2.0中,窗體提供了Opacit屬性來設置窗體的透明度。
Form.Opacit屬性用來獲取或設置窗體的不透明度級別,其語法格式以下:
public double Opacity { get; set; }
l 屬性值:窗體的不透明度級別。默認值爲1.00。
實現過程
(1)建立一個項目,將其命名爲Ex01_29,默認窗體爲Form1。
(2)在Form1窗體中設置背景圖片,添加Timer控件用來觸發漸變事件。
(3)設置Timer控件的Enable屬性爲True,設置Interval屬性爲1000。
(4)主要程序代碼。
private void timer1_Tick(object sender, EventArgs e)
{
this.Opacity += 0.1;
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
使窗體由透明狀態顯現出來,能夠用Time控件來控制窗體由透明到顯示所需的時間。
可使窗體爲透明狀態,只顯示窗體上的控件。
實例030 窗口顏色的漸變
實例說明
在程序設計時,能夠經過設置窗體的BackColor屬性來改變窗口的背景顏色。可是這個屬性改變後整個窗體的客戶區都會變成這種顏色,而且很是單調。若是窗體的客戶區能夠向標題欄同樣可以體現顏色的漸變效果,那麼窗體風格將會另有一番風味。本例設計了一個顏色漸變的窗體。效果如圖1.30所示。
技術要點
C#中能夠經過Color.FromArgb( )方法返回一種顏色,下面詳細介紹一下該方法。
Color.FromArgb( )方法用來返回Color的顏色值,該方法語法結構以下:
public static Color FromArgb (
int red,
int green,
int blue
)
參數說明以下。
l red:新Color的紅色份量值。有效值爲從0~255。
l green:新Color的綠色份量值。有效值爲從0~255。
l blue:新Color的藍色份量值。有效值爲從0~255。
l 返回值:此方法建立的Color。
該函數就是用3種不一樣的色值來返回一個顏色,而稍微的調整某一種顏色值就可使總體的顏色發生細微的變化,在窗體中至上而下每行填充一種稍微調整後的顏色,這樣總體看來就會產生漸變的效果。能夠利用窗體的Graphics對象對窗體進行繪圖,該對象能夠徹底操控窗體的客戶區。
注意:顏色值在0~255之間。
實現過程
(1)建立一個項目,將其命名爲Ex01_30,默認窗體爲Form1。
(2)在Form1窗體中添加Button用來使顏色漸變;添加TextBox控件用來輸入顏色RGB值。
(3)主要程序代碼。
觸發從新繪製事件的實現代碼以下:
private void button2_Click(object sender, EventArgs e)
{
InvokePaintBackground( );
this.Hide( );
this.Visible=true;
}
從新繪製窗體背景顏色的實現代碼以下:
protected override void OnPaintBackground(PaintEventArgs e)
{
int y, dy;
y = this.ClientRectangle.Location.Y;
dy = this.ClientRectangle.Height / 256;
for (int i = 255; i >= 0; i--)
{
Color c = new Color( );
c = Color.FromArgb(Convert.ToInt32(textBox1.Text.ToString( )), i,Convert.ToInt32(textBox2.Text.ToString( )));
SolidBrush sb = new SolidBrush(c);
Pen p = new Pen(sb, 1);
e.Graphics.DrawRectangle(p,this.ClientRectangle.X, y, this.Width,y+dy);
y = y + dy;
}
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
把窗體設置成單一的顏色。
利用Timer組體,使窗體動態改變顏色。
1.9 窗體動畫
本節主要對窗體進行動畫設置,在窗體上添加一些動畫效果,能夠爲操做者添加一些樂趣,下面的幾個例子將詳細介紹窗體動畫的相關技術。
實例031 窗體中的滾動字幕
實例說明
普通窗體中的文字位置都是固定的,一些窗體中須要讓文字動起來,例如一些廣告性較強的界面中須要作一些滾動的字幕。本例實現了一個具備滾動字幕效果的窗體,運行本例,單擊【演示】按鈕,看到窗口中的文字開始滾動。單擊【暫停】按鈕,可使字幕中止滾動。本例運行效果如圖1.31所示。
技術要點
滾動字幕的效果其實就是改變了文字的位置,在窗體中顯示一串文字最好的辦法就是利用Label控件。將Label控件的位置改變就能夠實現文字的位置變換,若是該控件的位置不斷的向水平方向移動,就會實現文字的滾動效果。改變Label控件的水平位置能夠經過改變Label控件的Left的值來實現。用Timer控件對文字的移動進行時間控制。
實現過程
(1)建立一個項目,將其命名爲Ex01_31,默認窗體爲Form1。
(2)在窗體上添加Label控件用來顯示消息;添加Button控件用來控制消息的運動;添加Timer控件用來控制滾動速度。
(3)主要程序代碼。
private void timer1_Tick(object sender, EventArgs e)//用Timer來控制滾動速度
{
label1.Left -= 2;
if (label1.Right < 0)
{
label1.Left = this.Width;
}
}
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true; //開始滾動
}
private void button2_Click(object sender, EventArgs e)
{
timer1.Enabled = false; //中止滾動
}
注意:要特別注意文字滾動的方向問題,向左則減,向右則加。
觸類旁通
根據本實例,讀者能夠開發如下程序。
能夠在窗體中設置一個滾動的圖片。
能夠在窗體中設置一個滾動的提示信息。
實例032 動畫顯示窗體
實例說明
當用戶啓動程序後,普通的程序窗口都是瞬間顯示到屏幕上,這樣未免有些生硬。若是窗口可以慢慢的展示在用戶面前,將會是什麼樣的效果?本例設計的是一個動畫顯示的窗體,該程序運行後,窗體是慢慢的以拉伸的效果顯示到用戶的面前。當關閉時也是同樣慢慢的消失。本例運行效果如圖1.32所示。
技術要點
Windows提供了一個API函數Animate Window,該函數能夠實現窗體的動畫效果,AnimateWindow函數在C#中的聲明以下。
[DllImportAttribute("user32.dll")]
private static extern bool AnimateWindow(IntPtr hwnd, int dwTime, int dwFlags);
參數說明以下。
l hwnd:目標窗口句柄。
l dwTime:動畫的持續時間,數值越大動畫效果的時間就越長。
l DwFlags:DwFlags參數是動畫效果類型選項,該參數在C#中的聲明以下:
public const Int32 AW_HOR_POSITIVE = 0x00000001;
public const Int32 AW_HOR_NEGATIVE = 0x00000002;
public const Int32 AW_VER_POSITIVE = 0x00000004;
public const Int32 AW_VER_NEGATIVE = 0x00000008;
public const Int32 AW_CENTER = 0x00000010;
public const Int32 AW_HIDE = 0x00010000;
public const Int32 AW_ACTIVATE = 0x00020000;
public const Int32 AW_SLIDE = 0x00040000;
public const Int32 AW_BLEND = 0x00080000;
DwFlags參數可選值含義如表1.1所示
表1.1 參數說明
標 志 |
描 述 |
AW_SLIDE |
使用滑動類型。缺省則爲滾動動畫類型。當使用AW_CENTER標誌時,這個標誌就被忽略 |
AW_ACTIVE |
激活窗口。在使用了AW_HIDE標誌後不要使用這個標誌 |
AW_BLEND |
使用淡入效果。只有當hWnd爲頂層窗口的時候纔可使用此標誌 |
AW_HIDE |
隱藏窗口,缺省則顯示窗口 |
AW_CENTER |
若使用了AW_HIDE標誌,則使窗口向內重疊;若未使用AW_HIDE標誌,則使窗口向外擴展 |
AW_HOR_POSITIVE |
自左向右顯示窗口。該標誌能夠在滾動動畫和滑動動畫中使用。當使用AW_CENTER標誌時,該標誌將被忽略 |
AW_HOR_NEGATIVE |
自右向左顯示窗口。當使用了 AW_CENTER 標誌時該標誌被忽略 |
AW_VER_POSITIVE |
自頂向下顯示窗口。該標誌能夠在滾動動畫和滑動動畫中使用。當使用AW_CENTER標誌時,該標誌將被忽略 |
AW_VER_NEGATIVE |
自下向上顯示窗口。該標誌能夠在滾動動畫和滑動動畫中使用。當使用AW_CENTER標誌時,該標誌將被忽略 |
實現過程
(1)建立一個項目,將其命名爲Ex01_32,默認窗體爲Form1。
(2)在窗體上添加PictureBox控件。
(3)設置PictureBox控件的Image屬性。
(4)主要代碼以下。
public Form1( )
{
InitializeComponent( );
AnimateWindow(this.Handle, 300, AW_SLIDE + AW_VER_NEGATIVE);//開始窗體動畫
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{ //結束窗體動畫
AnimateWindow(this.Handle, 300, AW_SLIDE + AW_VER_NEGATIVE + AW_HIDE);
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
實現窗體的淡入淡出。
實現窗體從中間擴散顯示。
實例033 製做閃爍的窗體
實例說明
Windows系統中,當程序在後臺運行時,若是某個窗口的提示信息須要用戶瀏覽,該窗口就會不停的閃爍,這樣就會吸引用戶的注意。一樣,若是在本身的程序中使某個窗口不停的閃爍就會吸引用戶的注意。本例設計了一個閃爍的窗體,運行程序,單擊【開始閃爍】按鈕,窗體就會不停的閃爍,單擊【中止】按鈕,窗體就會中止閃爍。本例運行效果如圖1.33所示。
技術要點
Windows提供了一個API函數FlashWIndow,該函數可使窗體閃爍一下。FlashWIndow函數在C#中聲明以下:
[System.Runtime.InteropServices.DllImportAttribute("user32.dll")]
public static extern bool FlashWindow(IntPtr handle, bool bInvert);
參數說明以下。
l handle:表示將要閃爍的窗體。
l bInvert:是否恢復狀態。
利用該函數只能使窗體閃爍一下,若是讓窗口不停地閃爍,就須要用一個Timer控件每隔一段時間就調用該函數使窗體閃爍。
實現過程
(1)建立一個項目,將其命名爲Ex01_33,默認窗體爲Form1。
(2)在窗體上添加PictureBox控件用來顯示窗體;添加Button、Timer控件用來開始和中止閃爍。
(3)設置PictureBox控件的Image屬性。
(4)主要程序代碼。
timer1的Tick事件處理代碼以下:
private void timer1_Tick(object sender, EventArgs e)
{
FlashWindow(this.Handle,true);
}
【開始閃爍】按鈕的單擊事件,用來啓動窗體閃爍:
private void button1_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
}
【中止】按鈕的單擊事件,用來中止窗體的閃爍:
private void button2_Click(object sender, EventArgs e)
{
timer1.Enabled = false;
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
利用Visible屬性製做一個閃爍的圖片。
製做一個閃爍的按鈕。
實例034 直接在窗體上繪圖
實例說明
含有Graphics對象的控件都可以在其上進行繪圖,不少軟件就是經過Graphics對象來美化程序的主界面,由於窗體中含有Graphics對象,因此能夠將窗體看做一個大畫板,一個能夠在上面繪圖的特殊控件。本例設計了一個簡單的繪圖軟件,該軟件就利用了在窗體上繪圖的方法,運行本軟件能夠在窗體上進行繪圖。實例效果如圖1.34所示。
技術要點
窗體中含有Graphics對象,使用該對象就可以完成大部分繪圖功能,Graphics對象已經對Windows底層的一些繪圖API進行了封裝,使用起來比較方便。下面介紹Graphics對象的經常使用方法。
Graphics.DrawLine繪圖方法用來繪製一條鏈接由座標對指定的兩個點的線條。其語法結構以下:
public void DrawLine (Pen pen,int x1,int y1,int x2,int y2)
參數說明以下。
l pen:Pen對象,肯定線條的顏色、寬度和樣式。
l x1:第一個點的x座標。
l y1:第一個點的y座標。
l x2:第二個點的x座標。
l y2:第二個點的y座標。
實現過程
(1)建立一個項目,將其命名爲Ex01_34,默認窗體爲Form1。
(2)向Form1窗口中添加GroupBox控件,用做RadioButton控件的容器;添加Button控件用來推出程序。
(3)主要程序代碼。
在窗體單元的private中添加變量以下:
int startX,startY;
Graphics g;
單擊鼠標事件。具體代碼以下:
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
startX=e.X;
startY = e.Y;
}
鼠標在窗體中的移動事件。具體代碼以下:
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
g = this.CreateGraphics( );
Pen p = new Pen(Color.Black, 1);
if(radioButton2.Checked==true)
{
g.DrawRectangle(p, e.X, e.Y, 1, 1);
}
}
鼠標擡起事件。具體代碼以下:
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
g = this.CreateGraphics( );
Pen p = new Pen(Color.Black, 2);
if (radioButton1.Checked == true )
{
g.DrawLine(p, startX, startY, e.X, e.Y);
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
改變畫筆的顏色。
在窗體上繪製矩型。
實例035 動畫形式的程序界面
實例說明
在不少的程序界面中,都是以菜單或工具欄的形式顯示窗體界面,這種顯示方式是以靜止狀態顯示的,界面不夠生動。下面介紹一個以動畫顯示窗體界面的設計方法。運行本例,效果如圖1.35所示。
技術要點
在該實例中用到了Microsoft Animation Control 6.0(SP4)COM組件,因此要從工具箱「選擇項」中將該組件添加到工具箱,而後繼續將該組件從工具箱添加到窗體便可。下面介紹本例中用到的相關方法。
AxAnimation.open方法用來播放動畫文件。其結構以下:
Public void AxAnimation.open(string bstrFilename)
參數說明以下。
l bstrFilename:將要播放的文件名。
注意:由於使用了AxAnimation類,因此要添加對WMPLib命名空間的引用。
實現過程
(1)建立一個項目,將其命名爲Ex01_35,默認窗體爲Form1。
(2)在Form1窗體添加PictureBox控件用來顯示圖片,添加Microsoft Animation Control 6.0 (SP4)COM組件用來播放動畫。
(3)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
axAnimation1.Open("Electron.avi");
axAnimation2.Open("zybiao.avi");
axAnimation3.Open("gd.avi");
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
製做摸擬網頁。
製做動畫播放器。
1.10 標題欄窗體
本節主要是對窗體的標題欄進行設置,標題欄是一個顯著的位置,在這個位置添加按鈕或進行一些個性化的設置,都會給人一種新奇的感受。經過如下實例的學習,讀者將掌握此技術。
實例036 使窗體標題欄文字右對齊
實例說明
窗口標題欄中的文字是窗口的重要說明,該文字能夠標示窗口的功能、狀態或名稱等信息,通常該文字是居左顯示的,在本例中設計一個標題欄文字右對齊的窗口。本實例運行結果如圖1.36所示。
技術要點
在C# 2.0中實現這一功能很是容易,只需將窗體的RightToLeft屬性設置爲Yes便可。
Form. RightToLeft屬性用來獲取或設置一個值,該值指示是否將控件的元素對齊以支持使用從右向左的字體的區域設置,其語法結構以下:
public virtual RightToLeft RightToLeft { get; set; }
l 屬性值:RightToLeft值之一。默認爲Inherit。
實現過程
(1)建立一個項目,將其命名爲Ex01_36,默認窗體爲Form1。
(2)爲Form1窗體添加背景圖片。
(3)設置RightToLeft屬性爲Yes。
觸類旁通
根據本實例,讀者能夠開發如下程序。
利用Timer控件使窗體標題欄的文字進行左右閃動。
製做窗體標題欄滾動播放圖片的窗體。
實例037 沒有標題欄可義改變大小的窗口
實例說明
隱藏Windows窗口的標題欄以後,窗口只剩下一個客戶區域,有點像Panel控件在窗口中的樣子,而這樣的窗口一般是不可以改變大小的。由於屏蔽其標題欄以後,窗口默認將邊框也去除了,本例將用特殊的方法創建一個沒有標題欄可是能夠改變其大小的窗體。實例運行效果如圖1.37所示。
技術要點
窗口的樣式是在窗口創建時肯定的,在C#中實現窗體沒有標題欄可是能夠改變大小的窗口,有一個巧妙的方法就是將窗體的Text屬性設爲空,同時將ControlBox屬性設爲False。下面介紹一下相關的屬性。
ControlBox屬性用來獲取或設置一個值,該值指示在該窗體的標題欄中是否顯示控件框,其語法結構以下:
public bool ControlBox { get; set; }
l 屬性值:若是該窗體在窗體的左上角顯示控件框,則爲True;不然爲False。默認爲True。
實現過程
(1)建立一個項目,將其命名爲Ex01_37,默認窗體爲Form1。
(2)在Form1窗口中添加Label、Button控件,用來設計界面。
(3)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
ControlBox = false;
}
注意:必須將窗體的Text屬性設爲空。
觸類旁通
根據本實例,讀者能夠開發如下程序。
在窗體顯示時最小化。
在許多的軟件中,都會對窗體的大小、位置和移動進行限定。在不一樣分辨率的顯示器中如何正確顯示窗體、如何設置窗體始終在最上面,這些都須要本節的技術。
實例038 設置窗體在屏幕中的位置
實例說明
在窗體中能夠設置窗體居中顯示,本例經過設置窗體的Left屬性和Top屬性能夠準確設置窗體的位置。運行本例,效果如圖1.38所示。
技術要點
設置窗體在屏幕中的位置,能夠經過設置窗體的屬性來實現。窗體的Left屬性表示窗體距屏幕左側的距離,Top屬性表示窗體距屏幕上方的距離。
實現過程
(1)建立一個項目,將其命名爲Ex01_38,默認窗體爲Form1。
(2)在窗體上添加Label控件;添加TextBox控件用來輸入距屏幕的距離;添加Button控件用來設置窗體在屏幕上的位置。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
this.Left = Convert.ToInt32(textBox1.Text);
this.Top = Convert.ToInt32(textBox2.Text);
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
根據分辨率的變化動態設置窗體位置。
用Timer控件實時顯示窗體位置。
實例039 始終在最上面的窗體
實例說明
Windows桌面上容許多個窗體同時顯示,可是隻有一個窗體可以獲得焦點,當一個窗體獲得焦點後在其上面的窗體會被獲得焦點的窗體遮擋,獲得焦點的窗體會顯示在最上層,這樣被覆蓋的窗體就不能徹底的顯示給用戶,若是該窗體中具備實時性和比較重要的信息時,須要該窗口始終在最上層。本例就實現了此功能,運行本例後,主窗體會始終在桌面的最上面。實例效果如圖1.39所示。
技術要點
在其餘開發環境中實現窗體始終在最上面比較複雜,但在C# 2.0中實現很是簡單,只要將TopMost屬性設爲True便可。下面介紹一下TopMost屬性。
Form.TopMost屬性用來獲取或設置一個值,指示該窗體是否應顯示爲最頂層窗體。其結構以下:
public bool TopMost { get; set; }
l 屬性值:若是將窗體顯示爲最頂層窗體,則爲True;不然爲False。默認爲False。
實現過程
(1)建立一個項目,將其命名爲Ex01_39,默認窗體爲Form1。
(2)爲Form1窗體添加背景圖片,並設置窗體TopMost屬性爲True。
觸類旁通
根據本實例,讀者能夠開發如下程序。
能夠將設爲最上層的窗體設置成爲一個電子錶,以便觀看時間。
能夠將設爲最上層的窗體設置成爲一個工做計劃表,以便隨時提醒本身。
1.12 設置窗體大小
用戶打開軟件後首先看到的就是窗體和窗體上的控件,如何設置窗體的大小及合理的設置窗體和控件的關係就變得十分重要,下面的實例將介紹這方面的知識。
實例040 限制窗體大小
實例說明
Windows窗體是能夠隨意改變大小的,然而對於一些要求嚴格的窗體,開發人員不但願用戶隨意的改變其大小,例如,定位準確的地圖和遊戲軟件等。遇到這種狀況必須對窗口的大小進行一些限制。本例設計一個限制了大小的窗體,用戶雖然能夠改變其大小,可是,大小的範圍是受到限制的。實例效果如圖1.40所示。
技術要點
在此C#中實現限制大小很是方便,只要設置窗體的最大和最小範圍便可。下面介紹一下相關屬性。
Form.MinimumSize屬性用來獲取或設置窗體可調整到的最小大小,其語法格式以下:
public override Size MinimumSize { get; set; }
l 屬性值:Size,表示該窗體的最小大小。
Form.MaximumSize屬性用來獲取或設置窗體可調整到的最大大小,其語法格式以下:
public override Size MaximumSize{ get; set; }
l 屬性值:Size,表示該窗體的最大大小。
實現過程
(1)建立一個項目,將其命名爲Ex01_27,默認窗體爲Form1。
(2)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
MinimumSize = new Size(200, 200);
MaximumSize = new Size(400, 400);
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
在窗體顯示時規定其大小。
在窗體運行時規定其大小。
實例041 獲取桌面大小
實例說明
獲取桌面分辨率可使用API函數GetDeviceCaps,但API函數參數較多,使用不方便,如何更方便的獲取桌面分辨率呢?在本例中,經過讀取Screen對象的屬性,來獲取桌面分辨率信息,以像素爲單位。運行本例,效果如圖1.41所示。
技術要點
C#中提供了Screen對象,在該對象中封裝了屏幕相關信息。能夠經過讀取Screen對象的相關屬性,來獲取屏幕的信息,Screen.PrimaryScreen.WorkingArea.Width用於讀取桌面寬度;Screen.PrimaryScreen.WorkingArea.Height能夠讀取桌面的高度。下面介紹一下相關屬性。
Screen.PrimaryScreen.WorkingArea屬性用於獲取顯示器的工做區。工做區是顯示器的桌面區域,不包括任務欄、停靠窗口和停靠工具欄。其結構以下:
public Rectangle WorkingArea { get; }
l 屬性值:一個Rectangle,表示顯示器的工做區。
實現過程
(1)建立一個項目,將其命名爲Ex01_41,默認窗體爲Form1。
(2)在Form1窗體上添加一個Button控件,用來獲取桌面大小;添加兩個TextBox控件,用來輸出所獲取的桌面大小。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
textBox2.Text = Screen.PrimaryScreen.WorkingArea.Height.ToString( );
textBox1.Text = Screen.PrimaryScreen.WorkingArea.Width.ToString( );
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
根據顯示器的分辨率信息設置窗體大小及位置。
根據顯示器的分辨率信息調整窗體界面。
實例042 在窗口間移動按扭
實例說明
窗體中每一個可視控件都有全部者和父對象兩個重要屬性,全部者是控件創建時指定的所屬對象,該對象能夠是不可視控件,而父對象必須是可視控件。所以能夠經過窗體中可視控件的Parent屬性來判斷控件是否在這個窗體中,還能夠用Form.Controls.Add( )方法爲窗體添加控件。本例以一個能夠在窗口間移動的按鈕來演示父對象改變後的運行效果。運行本例,在窗口中單擊按鈕,按鈕就會移動到另一個窗口中。實例效果如圖1.42和圖1.43所示。
圖1.42 在窗口間移動按鈕 圖1.43 在窗口間移動按鈕
技術要點
可視控件包含一個Parent屬性,該屬性表示控件的父對象。通常將此屬性設置爲一個窗口。經過該屬性能夠控制所屬窗體。
實現過程
(1)建立一個項目,將其命名爲Ex01_42,默認窗體爲Form1。
(2)添加一個窗體,默認窗體的Name屬性爲Form2。
(3)在Form1窗口中添加一個Button控件。併爲Form1和Form2設置背景圖片。
(4)主要程序代碼。
單擊按鈕在兩個窗體之間移動,具體代碼以下:
private void button1_Click(object sender, EventArgs e)
{
if (button1.Parent == this)
{
f.Controls.Add(this.button1);
this.button1.Text = "返回原地";
}
else
{
this.Controls.Add(button1);
this.button1.Text = "開始移動";
}
}
Form1窗體加載時同時顯示Form2窗體,具體代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
f = new Form2( );
f.Show( );
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
試作從一個窗體將控件拖到另外一個窗體。
試作用一個窗體控制另外一個窗體。
實例043 如何實現Office助手
實例說明
用過Office的人都知道,Office助手是一個很是漂亮的小工具,有了它,即便對Office不太熟悉的用戶也能夠操做自如。本實例使用C#製做了一個相似Office助手的程序,實例效果如圖1.44所示。
技術要點
要實現Office助手效果,須要使用Microsoft提供的第3方控件。在工具箱中單擊「選擇項」,從彈出的對話框中選擇COM組件選項卡中的Microsoft Agent Control 2.0組件並加入工具箱中,而後再添加到窗體中。
實現過程
(1)建立一個項目,將其命名爲Ex01_43,默認窗體爲Form1。
(2)在Form1窗體上添加一個ListBox控件用來讓用戶選擇人物的動做。
(3)主要程序代碼。
聲明成員變量及字符串數組,具體代碼以下:
IAgentCtlCharacterEx ICCE;
IAgentCtlRequest ICR;
string[] ws = new string[10] { "Acknowledge", "LookDown", "Sad", "Alert", "LookDownBlink", "Search", "Announce", "LookUp", "Think", "Blink"};
爲ListBox添加選項的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
listBox1.Items.Add(ws[i]);
}
ICR = axAgent1.Characters.Load("merlin", "merlin.acs");
ICCE = axAgent1.Characters.Character("merlin");
ICCE.Show(0);
}
隨着選項改變Office表情的實現代碼以下:
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
ICCE.StopAll("");
ICCE.Play(ws[listBox1.SelectedIndex]);
}
觸類旁通
根據本實例,讀者能夠實現如下程序。
瑞星助手。
在本身的程序中加入Office助手。
實例044 在關閉窗口前加入確認對話框
實例說明
用戶對程序進行操做時,不免會有錯誤操做的狀況,例如不當心關閉程序,若是尚有許多資料沒有保存,那麼損失將很是嚴重,因此最好使程序具備靈活的交互性。人機交互過程通常都是經過對話框來實現的,對話框中有提示信息,而且提供按鈕讓用戶選擇,例如【是】或【否】。這樣用戶就可以對所作的動做進行確認。正如前面所說的不當心關閉程序,若是在關閉程序以前提示用戶將要關閉程序,而且提供用戶選擇是否繼續下去,這樣就大大減小了誤操做現象。本例程序中的窗口在關閉時會顯示一個對話框,該對話框中有兩個按鈕【是】與【否】表明是否贊成關閉程序操做。實例運行結果如圖1.45所示。
技術要點
窗口正要關閉可是沒有關閉以前會觸發FormClosing事件,該事件中的參數FormClosingEventArgs e中包含Cancel屬性,若是設置該屬性爲True,窗口將不會被關閉。因此在該事件處理代碼中能夠提示用戶是否關閉程序,若是用戶不想關閉程序,則設置該參數爲True。利用MessageBox參數的返回值能夠知道用戶所選擇的按鈕。下面詳細介紹一下相關屬性。
CancelEventArgs.Cancel屬性用來獲取或設置指示是否應取消事件的值。該屬性結構以下:
public bool Cancel { get; set; }
l 屬性值:若是應取消事件,則爲True;不然爲False。
實現過程
(1)建立一個項目,將其命名爲Ex01_44,默認窗體爲Form1。
(2)主要程序代碼。
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("將要要關閉窗體,是否繼續?", "詢問", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
e.Cancel = false;
}
else
{
e.Cancel = true;
}
}
觸類旁通
根據本實例,讀者能夠實現如下程序。
使窗體的關閉按鈕無效。
使窗體關閉出如今托盤中。
實例045 使用任意組件拖動窗體
實例說明
一般將鼠標按住窗口的標題欄纔可以拖動窗口,可是,在沒有窗口標題欄的狀況下如何拖動窗體呢?本例將會利用窗口中的控件拖動窗口,將鼠標放在按鈕上而後按住鼠標左鍵移動鼠標便可拖動窗體。實例效果如圖1.46所示。
技術要點
經過控件移動窗體時,須要判斷用戶的鼠標動做。用戶準備拖動窗體時必須在控件上按住鼠標左鍵,因此應該在鼠標MouseDown事件處理過程當中來實現窗體的拖動。當用戶在按鈕上將鼠標左鍵按下時,觸發MouseDown事件,在該事件處理代碼中,MouseEventArgs e的Button屬性記錄了當前按下的鼠標按鈕,若是按鍵是鼠標左鍵,則表示能夠移動窗口,鼠標移動時,窗體就能夠跟着移動了。
實現過程
(1)建立一個項目,將其命名爲Ex01_45,默認窗體爲Form1。
(2)在Form1窗體上添加兩個Button控件,分別用來拖動窗體和關閉窗體。而後設置窗體的背景顏色。
(3)主要程序代碼。
聲明記錄鼠標按下時初始位置的變量,具體代碼以下:
private int startX, StartY;
鼠標按下事件處理代碼,具體代碼以下:
private void button1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
startX = e.X;
StartY = e.Y;
}
}
鼠標移動事件處理代碼,具體代碼以下:
private void button1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.Left += e.X - startX;
this.Top += e.Y - StartY;
}
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
能夠用窗體的用戶區拖動窗體。
不能夠拖動的窗體。
實例046 修改提示字體及顏色
實例說明
若是設置了控件的ToolTip屬性,當鼠標移到該控件後,會提示相關的文本,但沒有提供對提示字體及顏色的設置屬性,如何改變提示文本的樣式和字體呢?本例能夠設置提示文本的字體及顏色。運行本例,效果如圖1.47所示。
技術要點
C# 2.0中提供了ToolTip控件,能夠指定關聯控件併爲每一個控件提供提示文本,其中ToolTipTitle屬性指定文本提示盒中的文本。下面介紹相關的屬性和方法。
(1)SetToolTip方法
使工具提示文本與指定的控件相關聯。其語法結構以下:
public void SetToolTip (Control control,string caption)
參數說明以下。
l control:要將工具提示文本與其關聯的Control。
l caption:指針位於控件上方時要顯示的工具提示文本。
(2)ToolTip.ToolTipTitle屬性
獲取或設置工具提示窗口的標題。其語法結構以下:
public string ToolTipTitle { get; set; }
l 屬性值:包含窗口標題的String。該標題在窗口中做爲一行粗體文本顯示在標準的工具提示控件說明文本的上方。一般,標題只用於區分窗體上不一樣類別的控件,或做爲較長控件說明的簡介。
實現過程
(1)建立一個項目,將其命名爲Ex01_46,默認窗體爲Form1。
(2)在Form1窗體上添加Button控件用來在其上方顯示提示文本;添加ToolTip控件用來設計提示文本。
(3)主要程序代碼。
設置提示文本,及提示文本的關聯控件,具體代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
this.toolTip1.OwnerDraw = true;
this.toolTip1.SetToolTip(this.button1,"設置提示的字體及顏色");
this.toolTip1.Draw += new DrawToolTipEventHandler(toolTip1_Draw);
}
設置文本的提示樣式,具體代碼以下:
void toolTip1_Draw(object sender, DrawToolTipEventArgs e)
{
// throw new Exception("The method or operation is not implemented.");
e.DrawBackground( );
e.DrawBorder( );
using (StringFormat sf = new StringFormat( ))
{
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
sf.HotkeyPrefix = System.Drawing.Text.HotkeyPrefix.None;
sf.FormatFlags = StringFormatFlags.NoWrap;
using (Font f = new Font("宋體", 12))
{
e.Graphics.DrawString(e.ToolTipText, f,
SystemBrushes.ActiveCaptionText, e.Bounds, sf);
}
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
修改任意控件提示文本的樣式。
提示時加提示的聲音。
1.14 其他技術
本節主要介紹瞭如何建立和關閉MDI窗體。在大型項目和產品的開發中經常將系統設計爲MDI界面。
實例047 如何爲MDI類型窗體設置背景圖片
實例說明
MDI窗體是一種應用很是普遍的窗體類型,在一個主窗體內包含多個子窗體,子窗體永遠不會顯示在主窗體的外面。當子窗體不能徹底的顯示在主窗體中時,主窗體會顯示滾動條來調整可視範圍,在其餘開發環境中爲MDI窗體添加背景圖片十分困難。但在C# 2.0中實現很是容易。在本例中實現了一個具備背景的MDI窗體。實例效果如圖1.48所示。
技術要點
在C# 2.0中直接提供了BackgroundImage 屬性,該屬性能夠直接設置窗體的背景圖片。設置IsMdiContainer屬性爲True可使窗體成爲MDI主窗體。下面詳細介紹一下相關屬性。
(1)BackgroundImage屬性
獲取或設置在控件中顯示的背景圖像。其語法結構以下:
public virtual Image BackgroundImage { get; set; }
l 屬性值:一個Image,表示在控件的背景中顯示的圖像。
(2)Form.IsMdiContainer屬性
獲取或設置一個值,該值指示窗體是否爲多文檔界面(MDI)子窗體的容器。其語法結構以下:
public bool IsMdiContainer { get; set; }
l 屬性值:若是該窗體是MDI子窗體的容器,則爲True;不然爲False。默認爲False。
此屬性將窗體的顯示和行爲更改成MDI父窗體。當此屬性設置爲True時,該窗體顯示具備凸起邊框的凹陷工做區。全部分配給該父窗體的MDI子窗體都在該父窗體的工做區內顯示。
實現過程
(1)建立一個項目,將其命名爲Ex01_47,默認窗體爲Form1。
(2)添加一個窗體,默認窗體的Name屬性爲Form2。
(3)爲Form1窗體中添加背景圖片。
(4)設置Form1窗體的IsMdiContainer屬性爲True,該窗口做爲MDI主窗體。
(5)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
Form2 f = new Form2( );
f.MdiParent = this;
f.Show( );
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
爲非MDI窗體制做背景。
爲MDI子窗體設定顯示區域。
實例048 向提示框中添加圖標
實例說明
在開發程序時,爲了讓用戶熟悉操做,常用一些提示框,顯示提示信息。默認狀況下,提示信息框只包含提示信息,未免有些單調,若是在提示信息框中顯示一個圖標,程序或許就別具風格了。本實例實現了在提示框中添加圖標的功能,實例運行結果如圖1.49所示。
技術要點
要修改提示信息框的風格,首先須要瞭解C#中提示信息框的設計原理。在C#中,提示信息框是用ToolTip控件來實現的。ToolTip控件的ToolTipIcon屬性能夠設置提示時顯示的圖片,下面詳細介紹一下該屬性。
ToolTip.ToolTipIcon屬性用來獲取或設置一個值,該值定義要在工具提示文本旁顯示的圖標的類型。其語法結構以下:
public ToolTipIcon ToolTipIcon { get; set; }
l 屬性值:System.Windows.Forms.ToolTipIcon枚舉值之一。
實現過程
(1)建立一個項目,將其命名爲Ex01_48,默認窗體爲Form1。
(2)在Form1窗口中添加3個Label控件,用來顯示文字。
(3)在窗體上添加ToolTip控件用來顯示提示內容和提示樣式。
(4)主要程序代碼。
. private void Form1_Load(object sender, EventArgs e)
{
toolTip1.SetToolTip(label1,"人生格言");
toolTip1.SetToolTip(label2, "人生格言");
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
自定義提示信息框。
製做氣泡樣式提示信息框。
|
|
|
|
|
第13章 硬件相關開發技術
13.1 串口控制
串行口是計算機的標準接口,如今的PC機(我的電腦)通常至少有兩個串行口COM1和COM2。串行口應用普遍,在數據通訊、計算機網絡以及分佈式工業控制系統中,常常採用串行通訊來交換數據和信息。本節經過幾個實例,介紹串口應用的技術和方法。
實例418 經過串口發送數據
實例說明
如今大多數硬件設備均採用串口技術與計算機相連,所以串口的應用程序開發愈來愈廣泛。例如,在計算機沒有安裝網卡的狀況下,將本機上的一些信息數據傳輸到另外一臺計算機上,那麼利用串口通訊就能夠實現。運行本程序,在「發送數據」文本框中輸入要傳送的數據,單擊【發送】按鈕,將傳送的數據發送到所選擇的端口號中;單擊【接收】按鈕,傳遞的數據被接收到「接收數據」文本框中。如圖13.1所示。
技術要點
在.NET Framework 2.0中提供了SerialPort類,該類主要實現串口數據通訊等。下面主要介紹該類的主要屬性(表13.1)和方法(表13.2)。
表13.1 SerialPort類的經常使用屬性
名 稱 |
說 明 |
BaseStream |
獲取 SerialPort 對象的基礎 Stream 對象 |
BaudRate |
獲取或設置串行波特率 |
BreakState |
獲取或設置中斷信號狀態 |
BytesToRead |
獲取接收緩衝區中數據的字節數 |
BytesToWrite |
獲取發送緩衝區中數據的字節數 |
CDHolding |
獲取端口的載波檢測行的狀態 |
CtsHolding |
獲取「能夠發送」行的狀態 |
DataBits |
獲取或設置每一個字節的標準數據位長度 |
DiscardNull |
獲取或設置一個值,該值指示 Null 字節在端口和接收緩衝區之間傳輸時是否被忽略 |
DsrHolding |
獲取數據設置就緒 (DSR) 信號的狀態 |
DtrEnable |
獲取或設置一個值,該值在串行通訊過程當中啓用數據終端就緒 (DTR) 信號 |
Encoding |
獲取或設置傳輸先後文本轉換的字節編碼 |
Handshake |
獲取或設置串行端口數據傳輸的握手協議 |
IsOpen |
獲取一個值,該值指示 SerialPort 對象的打開或關閉狀態 |
NewLine |
獲取或設置用於解釋 ReadLine( )和WriteLine( )方法調用結束的值 |
Parity |
獲取或設置奇偶校驗檢查協議 |
續表
名 稱 |
說 明 |
ParityReplace |
獲取或設置一個字節,該字節在發生奇偶校驗錯誤時替換數據流中的無效字節 |
PortName |
獲取或設置通訊端口,包括但不限於全部可用的 COM 端口 |
ReadBufferSize |
獲取或設置 SerialPort 輸入緩衝區的大小 |
ReadTimeout |
獲取或設置讀取操做未完成時發生超時以前的毫秒數 |
ReceivedBytesThreshold |
獲取或設置 DataReceived 事件發生前內部輸入緩衝區中的字節數 |
RtsEnable |
獲取或設置一個值,該值指示在串行通訊中是否啓用請求發送 (RTS) 信號 |
StopBits |
獲取或設置每一個字節的標準中止位數 |
WriteBufferSize |
獲取或設置串行端口輸出緩衝區的大小 |
WriteTimeout |
獲取或設置寫入操做未完成時發生超時以前的毫秒數 |
表13.2 SerialPort類的經常使用方法
方 法 名 稱 |
說 明 |
Close |
關閉端口鏈接,將 IsOpen 屬性設置爲False,並釋放內部 Stream 對象 |
Open |
打開一個新的串行端口鏈接 |
Read |
從 SerialPort 輸入緩衝區中讀取 |
ReadByte |
從 SerialPort 輸入緩衝區中同步讀取一個字節 |
ReadChar |
從 SerialPort 輸入緩衝區中同步讀取一個字符 |
ReadLine |
一直讀取到輸入緩衝區中的 NewLine 值 |
ReadTo |
一直讀取到輸入緩衝區中指定 value 的字符串 |
Write |
已重載。將數據寫入串行端口輸出緩衝區 |
WriteLine |
將指定的字符串和 NewLine 值寫入輸出緩衝區 |
注意:用跳線使串口的第二、3針鏈接,能夠在本地計算機上實現串口通訊,因此,經過串口的第二、3針的鏈接能夠對程序進行檢測。串口截面圖如圖13.2所示。
圖13.2 串口截面圖
實現過程
(1)新建一個項目,命名爲Ex13_01,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,分別用於執行發送數據和接受數據,添加兩個TextBox控件,用於輸入發送數據和顯示接收數據。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
serialPort1.PortName = "COM1";
serialPort1.BaudRate = 9600;
serialPort1.Open();
byte[] data = Encoding.Unicode.GetBytes(textBox1.Text);
string str = Convert.ToBase64String(data);
serialPort1.WriteLine(str);
MessageBox.Show("數據發送成功!","系統提示");
}
private void button2_Click(object sender, EventArgs e)
{
byte[] data = Convert.FromBase64String(serialPort1.ReadLine());
textBox2.Text = Encoding.Unicode.GetString(data);
serialPort1.Close();
MessageBox.Show("數據接收成功!","系統提示");
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
遠程監控對方計算機屏幕。
下位機控制程序。
實例419 經過串口關閉對方計算機
實例說明
在網絡應用程序中,主要經過網卡實現數據的傳輸,所以能夠利用套接字技術實現遠程關閉計算機。若是計算機中沒有安裝網卡,該如何實現遠程關閉計算機呢?本例實現了利用串口關閉對方計算機,程序運行結果如圖13.3所示。
技術要點
本實例使用SerialPort類的屬性和方法,請參見實例「經過串口發送數據」。下面主要介紹SerialPort類的DataReceived 事件,DataReceived 事件爲本實例的主要使用技術。DataReceived事件表示將處理 SerialPort 對象的數據接收事件的方法。串行接收事件能夠由 SerialData 枚舉中的任何項引發,是否引起此事件由操做系統決定,因此不必定會報告全部奇偶校驗錯誤。
注意:本實例從開發到測試,都是由本地計算機完成的,用戶只須要使用跳線將串口的第二、3針鏈接,能夠在本地計算機上實現串口通訊。跳線鏈接請參見圖13.2。
實現過程
(1)新建一個項目,命名爲Ex13_02,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,分別用於打開通訊串口和關閉對方計算機。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
//打開串口
serialPort1.PortName = "COM1";
serialPort1.Open();
button1.Enabled = false;
button2.Enabled = true;
} //數據接收事件,等待接收關機命令
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
byte[] data = Convert.FromBase64String(serialPort1.ReadLine());
string str = Encoding.Unicode.GetString(data);
serialPort1.Close();
if (str == "關機")
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("shutdown /s");
p.StandardInput.WriteLine("exit");
}
} //發送關機命令
private void button2_Click(object sender, EventArgs e)
{
if (button2.Text == "關閉計算機")
{
//發送關機命令數據
byte[] data = Encoding.Unicode.GetBytes("關機");
string str = Convert.ToBase64String(data);
serialPort1.WriteLine(str);
button2.Text = "取消關機";
}
else
{
button2.Text = "關閉計算機";
button1.Enabled = true;
button2.Enabled = false;
//取消關機
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("shutdown /a");
p.StandardInput.WriteLine("exit");
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
遠程控制對方計算機操做。
定時控制對方計算機關閉。
13.2 加 密 狗
一些商務管理軟件,爲了防止盜版,常用加密狗將軟件加密。下面的兩個實例將介紹如何將密碼寫入加密狗及利用加密狗來設計加密程序。
實例420 密碼寫入與讀出加密狗
實例說明
在使用加密狗時,須要向加密狗中寫入或讀取數據。例如,將密碼寫入或讀取加密狗,如何實現呢?運行本例,在文本框中設置密碼後,單擊【寫入】按鈕,便可將設置的密碼寫入加密狗,成功寫入後,單擊【讀出】按鈕,便可將寫入的密碼讀出並顯示在文本框中。如圖13.4所示。
技術要點
在購買加密狗時,廠家一般會附帶有開發手冊和一張光盤。開發手冊中介紹了加密狗的使用方法和開發資料。本例使用賽孚耐信息技術有限公司的加密狗產品,該產品提供了.NET中非託管的類庫,來完成加密狗的數據讀寫功能。下面介紹有關加密狗的類庫中的讀寫函數。
● DogWrite 函數
該函數將pdogData指向的數據寫入加密狗中,從DogAddr地址開始寫入,到DogBytes地址中止。
函數聲明以下:
[DllImport("Win32dll.dll", CharSet = CharSet.Ansi)]
public static unsafe extern uint DogWrite(uint idogBytes, uint idogAddr, byte* pdogData);
參數說明以下。
l idogAddr:對軟件狗讀寫操做時用戶區中的首地址。取值範圍爲0~99。
l IdogBytes:對軟件狗讀寫操做時的字節長度。讀寫時取值範圍爲1~100,而且與idogAddr之和不能超過100。
l pdogData:指針型變量。指向讀寫操做或變換的數據緩衝區。
l 返回值:0表示操做成功,其餘值是錯誤碼。
● DogRead函數
該函數從加密狗中的idogAddr開始的存儲區讀出數據,存入pdogData指定的緩衝區,讀出字節數爲idogBytes。切記,緩衝區大小要足夠長。
函數聲明以下:
[DllImport("Win32dll.dll", CharSet = CharSet.Ansi)]
public static unsafe extern uint DogRead(uint idogBytes, uint idogAddr, byte* pdogData);
參數說明以下。
l idogAddr:對軟件狗讀寫操做時用戶區中的首地址。取值範圍爲0~99。
l idogBytes:對軟件狗讀寫操做時的字節長度。讀寫時取值範圍爲1~100,而且與idogAddr之和不能超過100。
l pdogData:指針型變量。指向讀寫操做或變換的數據緩衝區。
l 返回值:0表示操做成功,其餘值是錯誤碼。
注意如下幾點。
在使用這個函數以前,必須將隨加密狗附帶的安裝程序安裝完整,並將安裝目錄下的Win32dll.dll文件複製到系統目錄下。例如:
在Windows 2003下將安裝目錄下的「\SafeNet China\SoftDog SDK V3.1\Win32\Win32dll\HighDll\ Win32dll.dll」文件複製到「C:\WINDOWS\system32\」文件夾中。
實現過程
(1)新建一個項目,命名爲Ex13_03,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,用於執行向加密狗數據的寫入與讀出數據,添加兩個TextBox控件,分別用於填寫向加密狗中寫入的數據和顯示讀取加密狗中的數據。
(3)主要程序代碼。
設置加密狗類,而且完善加密狗的讀寫功能,代碼以下:
[StructLayout(LayoutKind.Sequential)]
//這個類用於讀寫加密狗
public unsafe class Dog
{
public uint DogBytes, DogAddr; //設置加密狗字節長度和起始地址
public byte[] DogData; //設置數據的長度
public uint Retcode;
[DllImport("Win32dll.dll", CharSet = CharSet.Ansi)]
public static unsafe extern uint DogRead(uint idogBytes, uint idogAddr, byte* pdogData);
[DllImport("Win32dll.dll", CharSet = CharSet.Ansi)]
public static unsafe extern uint DogWrite(uint idogBytes, uint idogAddr, byte* pdogData);
public unsafe Dog(ushort num)
{
DogBytes = num;
DogData = new byte[DogBytes]; //設置數據的長度
}
public unsafe void ReadDog()
{
fixed (byte* pDogData = &DogData[0])
{
Retcode = DogRead(DogBytes, DogAddr, pDogData); //將數據讀出加密狗
}
}
public unsafe void WriteDog()
{
fixed (byte* pDogData = &DogData[0])
{
Retcode = DogWrite(DogBytes, DogAddr, pDogData); //將數據寫入加密狗
}
}
}
調用加密狗類,進行加密狗的讀寫功能,代碼以下:
private void button1_Click_1(object sender, EventArgs e)
{
Dog dog = new Dog(100);
dog.DogAddr = 0;
dog.DogBytes = 10;
string str = textBox1.Text;
for (int i = 0; i < str.Length; i++)
{
dog.DogData[i] = (byte)str[i];
}
dog.WriteDog();
MessageBox.Show("密碼已成功寫入加密狗!", "成功提示!", MessageBoxButtons.OK, MessageBoxIcon.Information);
textBox1.ReadOnly = true;
button1.Enabled = false;
button2.Enabled = true;
}
private void button2_Click_1(object sender, EventArgs e)
{
Dog dog = new Dog(100);
dog.DogAddr = 0;
dog.DogBytes = 10;
dog.ReadDog();
if (dog.Retcode == 0) //開始讀加密狗數據
{
char[] chTemp = new char[textBox1.Text.Length];
for (int i = 0; i < textBox1.Text.Length; i++)
{
chTemp[i] = (char)dog.DogData[i];
}
String str = new String(chTemp);
textBox2.Text = str;
}
else
{
textBox2.Text = "2:" + dog.Retcode;
}
textBox1.ReadOnly = false;
button2.Enabled = false;
button1.Enabled = true;
}
注意:本程序所使用的代碼爲不安全代碼,正常編譯是沒法經過的,那麼須要設置開發環境容許運行不安全代碼,設置步驟爲:在菜單欄中選擇「項目」/「屬性」/「生成」子菜單,在「生成」選項卡中選中「容許不安全代碼」選項便可。
觸類旁通
根據本實例,讀者能夠開發如下程序。
利用加密狗加密本身的軟件。
利用加密狗設計控制計算機使用的程序。
實例421 使用加密狗進行身份驗證
實例說明
在程序開發過程當中,對於一些機密的數據,開發人員須要將其有效的保護起來。例如,對於用戶的密碼,若是從數據庫中驗證用戶密碼,很容易被非法人員發現甚至破解。本例實現了利用加密狗進行身份驗證。實例運行結果如圖13.5所示。
技術要點
本例的關鍵是從加密狗中讀取數據,可使用ReadDog函數實現。有關該函數的介紹請參考實例「密碼寫入與讀出加密狗」中的「技術要點」部分。
實現過程
(1)新建一個項目,命名爲Ex13_03,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,用於數據驗證和退出程序,添加兩個TextBox控件,分別用於輸入用戶名稱和密碼。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
Dog dog = new Dog(100);
dog.DogAddr = 0;
dog.DogBytes = 6;
dog.ReadDog();
if (dog.Retcode == 0)
{
char[] chTemp = new char[6];
for (int i = 0; i < 6; i++)
{
chTemp[i] = (char)dog.DogData[i];
}
String str = new String(chTemp);
if (textBox2.Text==str)
{
MessageBox.Show("OK");
}
else
{
MessageBox.Show("error");
}
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
利用加密狗設計加密軟件。
使用加密狗控制用戶使用權限。
13.3 IC卡應用
IC(Integrated Circuit)卡,也被稱做智能卡(Smart Card),具備寫入數據和存儲數據的功能,IC卡內存儲器的內容能夠根據須要有條件地供外部讀取,完成信息處理和斷定。因爲其內部具備集成電路,不但能夠存儲大量信息,具備極強的保密性能,而且還具備抗干擾、無磨損、壽命長等特性。所以在各個領域中獲得普遍應用。下面經過兩個實例介紹IC卡的簡單應用。
實例422 向IC卡中寫入數據
實例說明
IC卡是攜帶應用信息和數據的媒體,空白IC卡是不能當即使用的,必須對IC卡應用系統進行初始化,寫入系統IC卡和我的密碼,我的專用信息和應用數據。下面介紹如何向IC卡中寫入數據。運行本例,在「數據」文本框中輸入要存入IC卡中的數據,單擊「寫數據」按鈕,便可將輸入的數據寫入IC卡中。如圖13.6所示。
技術要點
本例使用的是深圳明華生產的明華IC卡讀寫器,用戶在使用時將驅動程序安裝完畢後,便可正常使用本系統。
本例經過調用Mwic_32.dll連接庫,進行IC卡的讀寫工做。下面介紹與IC卡寫操做相關的幾個函數。
(1)auto_init函數
該函數用於初始化IC卡讀卡器。語法以下:
public static extern int auto_init(int port, int baud);
參數說明以下。
l port:標識端口號,Com1對應的端口號爲0;Com2對應的端口號爲1,依此類推。
l baud:標識波特率。
l 返回值:若是初始化成功,返回值是IC卡設備句柄;若是初始化失敗,返回值小於零。
(2)setsc_md函數
該函數用於設置設備密碼模式。語法以下:
public static extern int setsc_md(int icdev, int mode);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
l mode:標識設備密碼模式,若是爲0,設備密碼有效,設備在加電時必須驗證設備密碼才能對設備進行操做。若是爲1,設備密碼無效。
l 返回值:若是函數執行成功返回值爲零,不然小於零。
(3)get_status函數
該函數用於獲取設備的當前狀態。語法以下:
public static extern Int16 get_status(int icdev, Int16* state);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
l state:用於接收函數返回的結果。若是爲0表示讀卡器中無卡,爲1表示讀卡器中有卡。
l 返回值:若是函數執行成功返回值爲零,不然小於零。
(4)csc_4442函數
該函數用於覈對IC卡密碼。語法以下:
public static extern Int16 Csc_4442(int icdev, int len, [MarshalAs(UnmanagedType.LPArray)] byte[] p_string);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
l len:標識密碼長度,其值爲3。
l p_string:標識設置的密碼。
l 返回值:若是函數執行成功返回值爲零,不然小於零。
(5)swr_4442函數
該函數用於向IC卡中寫入數據。語法以下:
public static extern int swr_4442(int icdev, int offset, int len, char* w_string);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
l offset:標識地址的偏移量,範圍是0~255。
l len:標識字符串長度。
l w_string:標識寫入的數據。
(6)ic_exit函數
該函數用於關閉設備端口。語法以下:
public static extern int ic_exit(int icdev);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
(7)dv_beep函數
該函數使讀卡器嗡鳴。語法以下:
public static extern int dv_beep(int icdev, int time);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
l time:標識嗡鳴持續的時間,單位是10毫秒。
實現過程
(1)新建一個項目,命名爲Ex13_05,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,用於執行向卡中寫入數據和退出程序的操做,添加一個TextBox控件,將TextBox中數據寫入IC卡中。
(3)主要程序代碼。
將程序所使用的操做IC卡的函數,封裝在類IC中。代碼以下:
[StructLayout(LayoutKind.Sequential)]
public unsafe class IC
{
//對設備進行初始化
[DllImport("Mwic_32.dll", EntryPoint = "auto_init", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int auto_init(int port, int baud);
//設備密碼格式
[DllImport("Mwic_32.dll", EntryPoint = "setsc_md", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int setsc_md(int icdev, int mode);
//獲取設備當前狀態
[DllImport("Mwic_32.dll", EntryPoint = "get_status", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern Int16 get_status(int icdev, Int16* state);
//關閉設備通信接口
[DllImport("Mwic_32.dll", EntryPoint = "ic_exit", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int ic_exit(int icdev);
//使設備發出蜂鳴聲
[DllImport("Mwic_32.dll", EntryPoint = "dv_beep", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int dv_beep(int icdev, int time);
//向IC卡中寫數據
[DllImport("Mwic_32.dll", EntryPoint = "swr_4442", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern int swr_4442(int icdev, int offset, int len, char* w_string);
//覈對卡密碼
[DllImport("Mwic_32.dll", EntryPoint = "csc_4442", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern Int16 Csc_4442(int icdev, int len, [MarshalAs(UnmanagedType.LPArray)] byte[] p_string);
}
下面代碼主要用於將TextBox中數據寫入到IC卡中。代碼以下:
private void button1_Click(object sender, EventArgs e)
{
//初始化
int icdev = IC.auto_init(0, 9600);
if (icdev < 0)
MessageBox.Show("端口初始化失敗,請檢查接口線是否鏈接正確。","錯誤提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
int md = IC.setsc_md(icdev, 1); //設備密碼格式
unsafe
{
Int16 status = 0;
Int16 result = 0;
result = IC.get_status(icdev, &status);
if (result != 0)
{
MessageBox.Show("設備當前狀態錯誤!");
int d1 = IC.ic_exit(icdev); //關閉設備
return;
}
if (status != 1)
{
MessageBox.Show("請插入IC卡");
int d2 = IC.ic_exit(icdev); //關閉設備
return;
}
}
unsafe
{
//卡的密碼默認爲6個f(密碼爲:ffffff),1個f的16進制是15,兩個f的16進制是255
byte[] pwd = new byte[3] { 255, 255, 255 };
//byte[] pwd = new byte[3] { 0xff, 0xff, 0xff };
//char[] pass=new ch{0xff,0xff,0xff};
Int16 checkIC_pwd = IC.Csc_4442(icdev, 3, pwd);
if (checkIC_pwd < 0)
{
MessageBox.Show("IC卡密碼錯誤!");
return;
}
char str = 'a';
int write=-1;
for (int j = 0; j < textBox1.Text.Length; j++)
{
str = Convert.ToChar(textBox1.Text.Substring(j, 1));
write = IC.swr_4442(icdev, 33 + j, textBox1.Text.Length, &str);
}
if (write == 0)
{
int beep = IC.dv_beep(icdev, 20); //發出蜂鳴聲
MessageBox.Show("數據已成功寫入IC卡中!");
}
else
MessageBox.Show("數據寫入IC卡失敗!");
}
int d = IC.ic_exit(icdev); //關閉設備
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
在圖書借閱中使用IC卡。
利用IC卡控制上網。
實例423 讀取IC卡中的數據
實例說明
向IC卡寫入數據後,就能夠進行讀卡操做了。運行本例,將寫入數據的IC卡插入讀卡器,單擊【讀卡】按鈕,IC卡中的數據將顯示在文本框中。如圖13.7所示。
技術要點
本例中主要調用srd_4442函數讀取IC卡中的數據,相關函數介紹請參考實例「向IC卡中寫入數據」中的「技術要點」部分。這裏只介紹讀卡函數。
q srd_4442函數
該函數用於讀取IC卡中的數據。語法以下:
public static extern int srd_4442(int icdev, int offset, int len, char* r_string);
參數說明以下。
l icdev:標識設備句柄,一般是auto_init函數的返回值。
l offset:標識地址的偏移量,範圍是0~255。
l len:標識字符串長度。
l r_string:用於存儲返回的數據。
實現過程
(1)新建一個項目,命名爲Ex13_06,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,用於讀取卡中的數據和退出程序,添加一個TextBox控件,顯示卡中的數據。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
//初始化
int icdev = IC.auto_init(0, 9600);
if (icdev < 0)
MessageBox.Show("端口初始化失敗,請檢查接口線是否鏈接正確。", "錯誤提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
int md = IC.setsc_md(icdev, 1); //設備密碼格式
int i = IC.dv_beep(icdev, 10); //發出蜂鳴聲
unsafe
{
Int16 status = 0;
Int16 result = 0;
result = IC.get_status(icdev, &status);
if (result != 0)
{
MessageBox.Show("設備當前狀態錯誤!");
int d1 = IC.ic_exit(icdev); //關閉設備
return;
}
if (status != 1)
{
MessageBox.Show("請插入IC卡");
int d2 = IC.ic_exit(icdev); //關閉設備
return;
}
}
unsafe
{
char str = 'a';
int read = -1;
for (int j = 0; j < 6; j++)
{
read = IC.srd_4442(icdev, 33 + j, 1, &str);
textBox1.Text = textBox1.Text + Convert.ToString(str);
}
if (read == 0)
MessageBox.Show("IC卡中數據讀取成功!");
}
int d = IC.ic_exit(icdev); //關閉設備
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
讀取IC卡電話系統。
公交車刷卡系統。
實例424 利用IC卡製做考勤程序
實例說明
IC卡普遍應用於各行業,包括銀行卡、公交車刷卡系統、讀書卡等。下面介紹使用IC卡製做簡單的公司考勤系統。運行本例,單擊【刷卡】按鈕,便可對員工進行考勤。實現效果如圖13.8所示。
技術要點
有關IC卡的操做函數請參考實例「向IC卡中寫入數據」和「讀取IC卡中的數據」中的「技術要點」部分。
下面主要介紹經過IC卡如何實現員工考勤。主要將寫入IC卡中的卡號讀取出來,而後從數據表中查詢員工信息。具體代碼請參考實現過程。
實現過程
(1)新建一個項目,命名爲Ex13_07,默認窗體爲Form1。
(2)在Form1窗體中,主要添加5個TextBox控件和6個Label控件,用途如圖13.7所示,添加一個Button控件,執行刷IC卡命令。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
//初始化
int icdev = IC.auto_init(0, 9600);
if (icdev < 0)
label6.Text = "端口初始化失敗,請檢查接口線是否鏈接正確。";
unsafe
{
Int16 status = -1;
Int16 result = IC.get_status(icdev, &status);
int md = IC.setsc_md(icdev, 1); //設備密碼格式
if (result < 0)
{
int d1 = IC.ic_exit(icdev); //關閉設備
return;
}
else if ((result == 0) && (status == 0))
{
int d2 = IC.ic_exit(icdev); //關閉設備
label6.Text = "請插入IC卡";
return;
}
}
unsafe
{
char str = 'a';
int read = -1;
string ic = "";
for (int j = 0; j < 6; j++)
{
read = IC.srd_4442(icdev, 33 + j, 1, &str);
ic = ic + Convert.ToString(str);
}
textBox1.Text = ic;
if (read == 0)
label6.Text = "刷卡成功!";
int beep = IC.dv_beep(icdev, 20); //發出蜂鳴聲
int d3 = IC.ic_exit(icdev); //關閉設備
}
int d = IC.ic_exit(icdev); //關閉設備
//根據卡號,查找相應數據
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "price.mdb" + ";Persist Security Info=False");
OleDbDataAdapter dap = new OleDbDataAdapter("select * from worker where ICID='"+textBox1.Text+"'", con);
DataSet ds = new DataSet();
dap.Fill(ds, "table");
if (ds.Tables.Count > 0)
{
textBox2.Text = ds.Tables[0].Rows[0][0].ToString();
textBox3.Text = ds.Tables[0].Rows[0][1].ToString();
textBox4.Text = ds.Tables[0].Rows[0][2].ToString();
textBox5.Text = ds.Tables[0].Rows[0][3].ToString();
}
else
{
label6.Text = "不存在該用戶!";
}
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
代金卡系統。
工資發放系統。
13.4 監 控
在一些銀行、大型商場、辦公樓、升降電梯中,爲了保障公有財產、商品、辦公設備、資料、人身等的安全,都設有監控系統。在出現問題時,用戶能夠經過監控系統查找緣由。下面的幾個實例分別實現了攝像頭監控與定時監控的功能。
實例425 簡易視頻程序
實例說明
利用普通的簡易攝像頭,經過C#語言便可開發成簡易視頻程序。本實例利用市場上購買的普通攝像頭,利用VFW技術,實現單路視頻監控系統。運行程序,窗體中將顯示艦體攝像頭採集的視頻信息。如圖13.9所示。
技術要點
本實例主要使用了VFW(Video for Windows)技術。VFW 是Microsoft公司爲開發Windows平臺下的視頻應用程序提供的軟件工具包,提供了一系列應用程序編程接口(API),用戶能夠經過這些接口很方便地實現視頻捕獲、視頻編輯及視頻播放等通用功能,還可利用回調函數開發比較複雜的視頻應用程序。該技術的特色是播放視頻時不須要專用的硬件設備,並且應用靈活,能夠知足視頻應用程序開發的須要。Windows操做系統自身就攜帶了VFW技術,系統安裝時,會自動安裝VFW的相關組件。
VFW技術主要由六個功能模塊組成,下面進行簡單說明。
l AVICAP32.DLL:包含執行視頻捕獲的函數,給AVI文件的I/O處理和視頻,音頻設備驅動程序提供一個高級接口。
l MSVIDEO.DLL:包含一套特殊的DrawDib函數,用來處理程序上的視頻操做。
l MCIAVI.DRV:包括對VFW的MCI命令解釋器的驅動程序。
l AVIFILE.DLL:包含由標準多媒體I/O(mmio)函數提供的更高級的命令,用來訪問.AVI文件。
l ICM:壓縮管理器,用於管理的視頻壓縮/解壓縮的編譯碼器。
l ACM:音頻壓縮管理器,提供與ICM類似的服務,適用於波形音頻。
其中13.4節全部的實例主要使用AVICAP32.DLL中的函數和USER32.DLL中的函數,函數語法及結構以下。
(1)capCreateCaptureWindow函數
該函數用於建立一個視頻捕捉窗口。語法以下:
[DllImport("avicap32.dll")]
public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
參數說明以下。
l lpszWindowName:標識窗口的名稱。
l dwStyle:標識窗口風格。
l x、y:標識窗口的左上角座標。
l nWidth、nHeight:標識窗口的寬度和高度。
l hWnd:標識父窗口句柄。
l nID:標識窗口ID。
l 返回值:視頻捕捉窗口句柄。
(2)SendMessage函數
用於向Windows系統發送消息機制。
[DllImport("User32.dll")]
private static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, int lParam);
參數說明以下。
l hWnd:窗口句柄。
l wMsg:將要發送的消息。
l wParam、lParam:消息的參數,每一個消息都有兩個參數,參數設置由發送的消息而定。
實現過程
(1)新建一個項目,命名爲Ex13_08,默認窗體爲Form1,添加1個類文件(.CS),用於編寫視頻類。
(2)在Form1窗體中,主要添加1個PictrueBox控件,用於顯示視頻;添加4個Button控件,用於打開視頻、關閉視頻、拍攝照片和退出程序。
(3)主要程序代碼。
視頻類中主要實現打開視頻、關閉視頻以及經過視頻拍攝照片的功能。代碼以下:
public class VideoAPI //視頻API類
{
// 視頻API調用
[DllImport("avicap32.dll")]
public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
[DllImport("avicap32.dll")]
public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
[DllImport("User32.dll")]
public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
// 常量
public const int WM_USER = 0x400;
public const int WS_CHILD = 0x40000000;
public const int WS_VISIBLE = 0x10000000;
public const int SWP_NOMOVE = 0x2;
public const int SWP_NOZORDER = 0x4;
public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10;
public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;
public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;
public const int WM_CAP_SET_PREVIEW = WM_USER + 50;
public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;
public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45;
public const int WM_CAP_START = WM_USER;
public const int WM_CAP_SAVEDIB = WM_CAP_START + 25;
}
public class cVideo //視頻類
{
private IntPtr lwndC; //保存無符號句柄
private IntPtr mControlPtr; //保存管理指示器
private int mWidth;
private int mHeight;
public cVideo(IntPtr handle, int width, int height)
{
mControlPtr = handle; //顯示視頻控件的句柄
mWidth = width; //視頻寬度
mHeight = height; //視頻高度
}
/// <summary>
/// 打開視頻設備
/// </summary>
public void StartWebCam()
{
byte[] lpszName = new byte[100];
byte[] lpszVer = new byte[100];
VideoAPI.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);
this.lwndC = VideoAPI.capCreateCaptureWindowA(lpszName, VideoAPI.WS_CHILD | VideoAPI.WS_VISIBLE, 0, 0, mWidth, mHeight, mControlPtr, 0);
if (VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_CONNECT, 0, 0))
{
VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEWRATE, 100, 0);
VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SET_PREVIEW, true, 0);
}
}
/// <summary>
/// 關閉視頻設備
/// </summary>
public void CloseWebcam()
{
VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_DRIVER_DISCONNECT, 0, 0);
}
/// <summary>
/// 拍照
/// </summary>
/// <param name="path">要保存bmp文件的路徑</param>
public void GrabImage(IntPtr hWndC, string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
VideoAPI.SendMessage(lwndC, VideoAPI.WM_CAP_SAVEDIB, 0, hBmp.ToInt32());
}
}
Form1窗體中經過調用視頻類中的方法來實現相應的功能。
在【打開視頻】按鈕的Click事件中添加以下代碼:
private void button1_Click(object sender, EventArgs e)
{
btnPlay.Enabled = false;
btnStop.Enabled = true;
btnPz.Enabled = true;
video = new cVideo(pictureBox1.Handle, pictureBox1.Width, pictureBox1.Height);
video.StartWebCam();
}
在【關閉視頻】按鈕的Click事件中添加以下代碼:
private void b_stop_Click(object sender, EventArgs e)
{
btnPlay.Enabled = true;
btnStop.Enabled = false;
btnPz.Enabled = false;
video.CloseWebcam();
}
在【拍攝照片】按鈕的Click事件下添加以下代碼:
private void btnPz_Click(object sender, EventArgs e)
{
video.GrabImage(pictureBox1.Handle, "d:\\a.bmp");
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
無人值班視頻實時監控系統。
車庫安全實時監控系統。
實例426 攝像頭監控錄像
實例說明
本例是爲經過攝像頭來實現監控錄像的程序。運行本例後,單擊【開始監控】按鈕,程序將自動開始錄像,錄像文件(lx.avi)將保存在D盤根目錄下。運行程序,效果如圖13.10所示。
技術要點
在實例「簡易視頻程序」的技術要點中,使用的技術和相關函數已經介紹過。在這裏主要介紹如何將捕獲的視頻製做成 .AVI媒體文件。實現技術爲主要經過SendMessage函數發送Windows消息機制,消息值WM_CAP_FILE_SET_CAPTURE_FILEA和WM_CAP_SEQUENCE,分別用來設置視頻捕捉的文件名稱和初始化視頻流,捕捉視頻信息到文件:
private const int WM_USER = 0x400;
private const int WM_CAP_START = WM_USER;
private const int WM_CAP_SEQUENCE = WM_CAP_START + 62;
private const int WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20;
實現關鍵代碼以下:
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage(hWndC,WM_CAP_FILE_SET_CAPTURE_FILEA,0, hBmp.ToInt32());
SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0);
實現過程
(1)新建一個項目,命名爲Ex13_09,默認窗體爲Form1,添加一個類文件(.CS),用於編寫視頻類。
(2)在Form1窗體中,主要添加一個PictrueBox控件,用於顯示視頻;添加4個Button控件,用於開始監控、中止監控和監控程序。
(3)視頻類中主要程序代碼以下:
/// <summary>
/// 開始錄像
/// </summary>
/// <param name="path">要保存錄像的路徑</param>
public void StarKinescope(string path)
{
IntPtr hBmp = Marshal.StringToHGlobalAnsi(path);
SendMessage(hWndC,WM_CAP_FILE_SET_CAPTURE_FILEA,0, hBmp.ToInt32());
SendMessage(hWndC, WM_CAP_SEQUENCE, 0, 0);
}
/// <summary>
/// 中止錄像
/// </summary>
public void StopKinescope()
{
SendMessage(hWndC, WM_CAP_STOP, 0, 0);
}
(4)Form1窗體中主要程序代碼以下:
//開始錄像
private void button1_Click(object sender, EventArgs e)
{
btnStar.Enabled = false;
btnStop.Enabled = true;
video.StarKinescope(@"d:\lx.avi");
}
//中止錄像
private void button2_Click(object sender, EventArgs e)
{
btnStar.Enabled = true;
btnStop.Enabled = false;
video.StopKinescope();
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
小區視頻監控錄像系統。
公司財務室視頻監控系統。
實例427 超市攝像頭定時監控系統
實例說明
本實例實現超市攝像頭定時監控系統。運行本例後,在「定時監控設置」處設置監控的星期及時間,單擊【保存】按鈕,將「定時設置」參數數據保存到數據庫中。系統在運行到定時時間後,程序將自動進行監控。如圖13.11所示。另外,監控的錄像文件和圖片文件保存在D盤根目錄中,命名格式爲系統當前日期。
圖13.11 超市攝像頭定時監控
技術要點
相關技術要點請參見實例「攝像頭監控錄像」。另外,本實例利用Timer控件中的定時執行功能,進行數據的定時錄像工做。
實現過程
(1)新建一個項目,命名爲Ex13_10,默認窗體爲Form1,添加一個類文件(.CS),用於編寫視頻類。
(2)在Form1窗體中,主要添加一個PictrueBox控件,用於顯示視頻;其餘控件的添加如圖13.11所示。
(3)主要程序代碼。
private void timer1_Tick(object sender, EventArgs e)
{
string strTime="";
//星期一
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek)==1)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt1.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
//星期二
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek) == 2)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt2.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
//星期三
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek) == 3)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt3.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
//星期四
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek) == 4)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt4.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
//星期五
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek) == 5)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt5.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
//星期六
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek) == 6)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt6.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
//星期日
if (chk1.Checked && Convert.ToInt32(DateTime.Now.DayOfWeek) == 7)
{
strTime = DateTime.Now.ToString("HH:mm");
DateTime date = Convert.ToDateTime(mtxt7.Text);
if (strTime == date.ToString("HH:mm"))
video.StarKinescope(@"d:\" + DateTime.Today.Month.ToString() + DateTime.Today.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString() + ".avi");
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
車站定時監控系統。
公司定時安防系統。
13.5 語音卡控制
隨着語音技術的不斷髮展,語音卡在通訊行業應用很是普遍。本節經過幾個典型實例介紹語音卡程序的開發。
實例428 語音卡電話呼叫系統
實例說明
隨着科學技術的不斷髮展,語音卡被普遍地應用於商業軟件中。本例實現了利用語音卡實現電話呼叫的功能。實例運行結果如圖13.12所示。
技術要點
本例採用東進公司開發的8路模擬語音卡,該卡採用靈活的模式化設計,可按需配置外線、內線兩種模塊。該語音卡可實現坐席、會議、FSK數據收發、語音合成等多種功能,並提供SDK開發工具包。
在安裝完驅動程序後,相應的動態連接庫(NewSig.dll和Tc08a32.dll文件)會複製到Windows的系統目錄下。在語音卡的開發過程當中,主要經過調用NewSig.dll和Tc08a32.dll來實現相應的功能。下面介紹這兩個動態庫中的主要使用函數。
(1)LoadDRV函數
該函數用於加載動態連接庫。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern long LoadDRV();
返回值:返回值爲0表示成功;−1表示打開設備驅動程序錯誤。−2表示在讀取TC08A-V.INI文件時發生錯誤;−3表示INI文件的設置與實際的硬件不一致時發生錯誤。
(2)FreeDRV函數
該函數用於關閉驅動程序。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern long EnableCard(short wusedCh, short wFileBufLen);
(3)EnableCard函數
該函數用於初始化語音卡硬件,併爲每一個通道分配語音緩衝區。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern long EnableCard(short wusedCh, short wFileBufLen);
參數說明以下。
l wUsedCh:標識通道數量。
l WFileBufLen:標識分配的緩衝區大小。
(4)CheckValidCh函數
該函數檢測在當前機器內可用的通道總數。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern short CheckValidCh();
l 返回值:通道總數量。
(5)CheckChType函數
該函數用於測試某個通道的類型。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern short CheckChType(short wChnlNo);
參數說明以下。
l wChnlNo:標識通道號。
l 返回值:爲0表示內線;爲1表示外線;爲2表示懸空。
(6)PUSH_PLAY函數
該函數用於維持文件錄放音的持續進行,需在處理函數的大循環中調用。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern void PUSH_PLAY();
(7)SetBusyPara函數
該函數用於設置要檢測的掛機忙音的參數。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern void SetBusyPara(short BusyLen);
參數說明:
l BusyLen:標識忙音的時間長度,單位爲毫秒。
(8)RingDetect函數
該函數用於測試外線是否振鈴或內線是否提機。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern bool RingDetect(short wChnlNo);
參數說明以下。
l wChnlNo:標識通道號。
返回值:若是爲1,對於外線表示有振鈴信息;對於內線,表示提機。若是爲0,對於外線,表示無振鈴信息;對於內線,表示掛機。
(9)OffHook函數
該函數用於外線提機。對於內線,不起做用。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern void OffHook(short wChnlNo);
參數說明以下。
l wChnlNo:標識外線通道。
(10)HangUp函數
該函數用於外線掛機。對於內線,不起做用。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern void HangUp(short wChnlNo);
參數說明以下。
l wChnlNo:標識外線通道。
(11)Sig_Init函數
該函數用於完成信號音檢測的初始化工做。語法以下:
[DllImport("NewSig.dll", CharSet = CharSet.Auto)]
public static extern void Sig_Init(int Times);
參數說明以下。
l wPara:缺省值爲0,不起做用。
(12)Sig_CheckBusy函數
清空忙音檢測的緩衝區以及內部計數。當檢測對方掛機的忙音後,必須調用本函數。語法以下:
[DllImport("NewSig.DLL", CharSet = CharSet.Auto)]
public static extern void Sig_ResetCheck(short wChlNo);
參數說明以下。
l wChNo:標識通道號。
l 返回值:爲1表示檢測到忙音;爲0,表示沒有檢測到忙音。
(13)Sig_ResetCheck函數
該函數用於清空忙音檢測的緩衝區以及內部計數。當檢測對方掛機的忙音後,必須調用本函數。語法以下:
[DllImport("NewSig.DLL", CharSet = CharSet.Auto)]
public static extern void Sig_ResetCheck(short wChlNo);
參數說明以下。
l wChNo:標識通道號。
(14)Sig_StartDial函數
該函數用於撥打電話號碼。開始某通道的呼出過程。該函數只是設置通道的呼出緩衝區,真正的呼出過程須要循環調用Sig_CheckDial函數來逐步完成。語法以下:
[DllImport("NewSig.dll", CharSet = CharSet.Auto)]
public static extern int Sig_StartDial(short wChNo, [MarshalAs(UnmanagedType.LPArray)] byte[] DialNum, [MarshalAs(UnmanagedType.LPArray)] byte[] PreDialNum, short wMode);
參數說明以下。
l wChNo:標識通道號。
l DialNum:標識呼出號碼。
l PreDialNum:標識前導號碼。
l wMode:呼出檢測的模式。
(15)Sig_CheckDial函數
該函數用於檢測呼出結果。
在調用函數Sig_StartDial啓動撥號過程後,就能夠循環調用Sig_CheckDial函數維持撥號過程,並檢測呼出的結果,直至獲得結果爲止。
撥號的通常過程以下。
1.若是參數PreDialNum不爲空,則延遲1秒後撥出PreDialNum,若是參數PreDialNum爲空,則直接進入步驟3。
2.檢測PreDialNum是否已發完。如已發完轉至步驟3。
3.檢測是否有撥號音,如撥號音長度達到配置項DialToneAfterOffHook的數值,則發送DialNum碼串,並轉至步驟4。如在此步驟已等待配置項NoDialToneAfterOffHook定義的時間長度仍未檢測到撥號音,則返回0x10。
4.檢測DialNum碼串是否發完,如已發完則延遲StartDelay配置項的時間長度後進入步驟5。
5.若是從進入此步驟起已通過配置項RingLen定義的時間長度,撥號音仍未中止則返回0x10;若是在此步驟已等待配置項NoRingLen定義的時間長度仍未檢測到回鈴音則返回0x10;若是檢測到佔線忙音數達到配置項BusySigCount定義的數字,則返回0x21;若是檢測到對方摘機,則返回0x14;若是進入此步驟已通過配置項Ringback_NoAnswerTime定義的時間長度,而且已檢測到回鈴音,則返回0x13;其餘狀況返回0x10。
注意:在進行呼出結果檢測以前必須調用函數StartSigCheck啓動信號音採集過程,而且在進行呼出結果檢測時,要循環調用FeedSigFunc函數維持信號音採集過程。
語法以下:
[DllImport("NewSig.dll", CharSet = CharSet.Auto)]
public static extern int Sig_CheckDial(short wChNo);
參數說明以下。
l wChNo:標識通道號。
l 返回值包括如下幾種狀況。
l 16(0x10):還沒有得出結果。
l 15(0x0F):沒有撥號音。
l 33(0x21):檢測到對方佔線的忙音。
l 20(0x14):對方摘機,能夠進行通話。
l 19(0x13):振鈴若干次,無人接聽電話。
l 21(0x15):沒有信號音。
注意:關於語音卡其餘函數語法請參見光盤中的本實例文件D161A.CS,該文件給出大部分語音卡的函數語法。
實現過程
(1)新建一個項目,命名爲Ex13_11,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個Button控件,用於執行電話撥號和電話掛機,添加一個DataGridView控件,顯示語音卡各通道及通道狀態,添加Timer組件實現電話的呼出過程,添加一個TextBox控件,用於輸入呼出電話號碼。
(3)主要程序代碼。
在窗體裝載事件中,主要進行初始化語音卡驅動程序,而且檢測通道總數及狀態,爲每一條通道分配語音緩衝區。代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
//初始化驅動程序
long load = DJ160API.LoadDRV();
//檢測通道總數,併爲每一個通道分配語音緩衝區
short wuseCh = DJ160API.CheckValidCh();
short wFileBufLen = 16 * 1024;
long card = DJ160API.EnableCard(wuseCh, wFileBufLen);
//設置表格通道的行數
dataGridView1.RowCount = wuseCh;
//檢測每一個通道類型
short chanelTpye = 0; //定義通道類型變量
string strType = "";
for (short i = 0; i < wuseCh; i++)
{
chanelTpye = DJ160API.CheckChType(i);
dataGridView1[0, i].Value = i;
switch (chanelTpye)
{
case 0:
strType = "內線";
break;
case 1:
strType = "外線";
break;
case 2:
strType = "懸空";
break;
}
dataGridView1[1, i].Value = strType;
dataGridView1[2, i].Value = "空閒";
}
}
在DataGridView控件中選擇一個外線空閒通道,單擊【撥號】按鈕,進行電話撥號,而且將撥號過程當中的狀態顯示在相應的DataGirdView表格中。代碼以下:
private void button1_Click(object sender, EventArgs e)
{
short wuseCh = DJ160API.CheckValidCh();
short wFileBufLen = 16 * 1024;
long card = DJ160API.EnableCard(wuseCh, wFileBufLen);
DJ160API.Sig_Init(chanel);
//檢查(外線)是否有振鈴信號或(內線)是否有提機
bool ring = DJ160API.RingDetect(chanel);
//外線提機
DJ160API.OffHook(chanel);
byte[] ss =new byte[textBox1.Text.Length];
byte[] s ={ 0 };
for (int i = 0; i < textBox1.Text.Length; i++)
{
ss[i] = Convert.ToByte(textBox1.Text.Substring(i, 1));
}
DJ160API.Sig_StartDial(chanel, ss, s, 0);
timer1.Enabled = true;
dataGridView1[2, chanel].Value = "撥號中...";
dataGridView1[3, chanel].Value = textBox1.Text;
}
單擊【掛機】按鈕,實現電話掛機功能。代碼以下:
private void button2_Click(object sender, EventArgs e)
{
DJ160API.HangUp(chanel);
DJ160API.Sig_ResetCheck(chanel);
DJ160API.StartSigCheck(chanel);
timer1.Enabled = false;
dataGridView1[2, chanel].Value = "空閒";
dataGridView1[3, chanel].Value = "";
}
Sig_StartDial函數用於撥打電話號碼。開始某通道的呼出過程。該函數只是設置通道的呼出緩衝區,真正的呼出過程需循環調用Sig_CheckDial函數來逐步完成。代碼以下:
private void timer1_Tick(object sender, EventArgs e)
{
DJ160API.Sig_CheckDial(chanel);
}
單擊DataGridView控件的相應行記錄相應的通道號,代碼以下:
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{
chanel = (short)e.RowIndex;
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
實現電話自助服務系統。
實現電話自動報警系統。
實例429 客戶來電查詢系統
實例說明
隨着市場競爭的加重,企業愈來愈重視客戶服務和市場反饋。本例實現了電話來電的顯示支持功能。當有客戶打入電話時,會讀取客戶的電話號碼,根據電話號碼能夠提取客戶的相關信息,方便客服人員有針對性地進行服務。實例運行結果如圖13.13所示。
圖13.13 客戶來電查詢
技術要點
其餘相關函數介紹請參見實例「語音卡電話呼叫系統」,本實例主要介紹GetCallerIDStr函數,該函數用於獲取主叫號碼。語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern short GetCallerIDStr(short wChnlNo, byte[] IDStr);
參數說明以下。
l wChnlNo:標識通道號。
l IDStr:用於接收讀取的號碼。
l 返回值:爲0,表示未收到任何信息;爲1,表示正在接收頭信息;爲2表示正在接收ID號碼;爲3表示接收完畢,校驗正確;爲4表示接收完畢,校驗錯誤。
在調用GetCallerIDStr函數時,只有返回值爲3或4才表示已經正確接收了主機號碼。
實現過程
(1)新建一個項目,命名爲Ex13_12,默認窗體爲Form1。
(2)在Form1窗體中,主要添加一個DataGridView控件,顯示語音卡各通道和通道狀態,並在來電時顯示來電號碼;添加一個Timer控件用於時刻檢測來電信息;添加其餘控件及用途如圖13.13所示。
(3)主要程序代碼。
private void timer1_Tick(object sender, EventArgs e)
{
byte[] ss = new byte[100];
for (short i = 0; i < 8; i++)
{
DJ160API.StartSigCheck(i);
if(open_close==false)
DJ160API.ResetCallerIDBuffer(i);
if (DJ160API.RingDetect(i))
{
open_close = true;
//獲取來電號碼
result = DJ160API.GetCallerIDStr(i, ss);
if (result == 3 || result == 4)
{
string str = Encoding.UTF8.GetString(ss);
txtTel.Text = str;
txtTel.Text = txtTel.Text.Substring(txtTel.Text.Length - 8, 8);
dataGridView1[2, i].Value = txtTel.Text;
//查詢客戶資料
this.getMessage(txtTel.Text);
}
}
}
}
private void getMessage(string str)
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "db_csell.mdb" + ";Persist Security Info=False");
OleDbDataAdapter dap = new OleDbDataAdapter("SELECT * FROM 我的名錄表 WHERE 電話='" + str + "'", con);
DataSet ds = new DataSet();
dap.Fill(ds);
if (ds.Tables[0].Rows.Count > 0)
{
txtName.Text = ds.Tables[0].Rows[0]["姓名"].ToString();
txtDuty.Text = ds.Tables[0].Rows[0]["職務"].ToString();
txtAddress.Text = ds.Tables[0].Rows[0]["地址"].ToString();
txtMobile.Text = ds.Tables[0].Rows[0]["手機"].ToString();
txtCompany.Text = ds.Tables[0].Rows[0]["公司名稱"].ToString();
txtPostId.Text = ds.Tables[0].Rows[0]["郵編"].ToString();
}
else
{
labStatus.Text = "非本單位會員客戶。。。。";
}
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
用語音卡實現客戶某項費用的查詢。
用語音卡實現客戶在某個時間的留言信息。
用語音卡實現客戶購買物品的查詢。
實現客戶反饋電話錄音系統。
實例430 語音卡實現電話錄音
實例說明
現在的許多電話都具備電話錄音的功能。本例實現了該功能,當有電話打入時,即刻將雙方的對話信息進行錄音。實例運行結果如圖13.14所示。
技術要點
其餘相關函數介紹請參見實例「語音卡電話呼叫系統」,本實例主要介紹StartRecordFile函數和StopRecordFile函數。
(1)StartRecordFile函數用於開始文件錄音。中止該方式的錄音必定要用StopRecordFile函數。檢查錄音是否結束,用CheckRecordEnd函數。StartRecordFile函數語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern bool StartRecordFile(short wChnlNo, byte[] FileName, long dwRecordLen);
參數說明以下。
l wChnINo:標識錄音的通道號。
l FileName:標識錄音的文件名。
l dwRecordLen:標識文件大小。
(2)StopRecordFile函數用於中止錄音。該函數語法以下:
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern void StopRecordFile(short wChnlNo);
參數說明以下。
l wChnINo:標識要中止的錄音通道。
(3)CheckRecordEnd函數檢查指定通道錄音是否結束(緩衝區已滿)。
[DllImport("Tc08a32.dll", CharSet = CharSet.Auto)]
public static extern int CheckRecordEnd(int ChannelNo);
參數說明以下。
l wChnINo:標識錄音的通道號。
l 返回值:0表示未結束;1表明結束。
實現過程
(1)新建一個項目,命名爲Ex13_13,默認窗體爲Form1。
(2)在Form1窗體中,主要添加一個DataGridView控件,顯示語音卡各通道和通道狀態,並在來電時顯示來電號碼;添加一個Timer控件用於實時檢測來電信息,若是來電,程序將自動摘機而且實現錄音;添加其餘控件及用途如圖13.14所示。
(3)主要程序代碼。
private void timer1_Tick(object sender, EventArgs e)
{
//維持文件錄音持續執行
DJ160API.PUSH_PLAY();
for (short i = 0; i < 8; i++)
{
DJ160API.StartSigCheck(i);
if (open_close == false)
DJ160API.ResetCallerIDBuffer(i);
if (DJ160API.RingDetect(i))
{
open_close = true;
//摘機
DJ160API.OffHook(i);
DJ160API.StartSigCheck(i);
//是否掛機
if (DJ160API.ReadCheckResult(i, 2) != 33)
{
bool bl = DJ160API.StartRecordFile(i, Encoding.UTF8.GetBytes(@"D:\ly.001"), 600 * 1024);
dataGridView1[2, i].Value = "已接來電,開始錄音";
}
else
{
DJ160API.StopRecordFile(i);
open_close = false;
DJ160API.Sig_ResetCheck(i);
dataGridView1[2, i].Value = "";
}
if (DJ160API.CheckRecordEnd(i)==1)
{
DJ160API.StopRecordFile(i);
open_close = false;
dataGridView1[2, i].Value = "";
}
}
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
用語音卡實現電話點播歌曲,經過按鍵的選擇點播本身喜好的歌曲。
用語音卡實現產品報價,經過按鍵實現某些產品的報價。
利用語音卡實現產品報價。
13.6 手機程序開發
現在手機已成爲大衆的交流工具。有關手機的程序開發愈來愈普遍,本節經過幾個典型實例介紹如何利用短信貓發送、接收短信、遠程控制計算機、業務員銷售數據採集和短信息娛樂互動平臺。
實例431 利用短信貓收發短信息
實例說明
短信貓是利用SIM卡發送短信的硬件設備,經過串口或USB接口(根據設備型號而定)與計算機相連。在程序中能夠利用短信貓發送或接收短信。本例實現了利用短信貓收發短信息的功能。實例運行結果如圖13.15所示。
技術要點
本例使用的是北京人大金倉信息技術有限公司的串口短信貓。在購買短信貓時會附帶包括SDK的開發包,其中提供了操做短信貓的函數(封裝在dllforvc.dll動態庫中)。下面介紹操做短信貓的主要函數。
(1)GSMModemGetSnInfoNew函數
該函數獲取短信貓註冊須要的信息,代碼以下:
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetSnInfoNew",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetSnInfoNew(string device, string baudrate);
參數說明以下。
l device:通訊端口,爲null時系統會自動檢測。
l baudrate:通信波特率,爲null時系統會自動檢測。
(2)GSMModemGetDevice函數
該函數獲取當前的通信端口,代碼以下:
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetDevice",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetDevice();
(3)GSMModemGetBaudrate函數
該函數獲取當前的通信波特率,代碼以下:
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetBaudrate",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetBaudrate();
(4)GSMModemInitNew函數
該函數用於初始化短信貓。語法以下:
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemInitNew",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern bool GSMModemInitNew(
string device,
string baudrate,
string initstring,
string charset,
bool swHandshake,
string sn);
參數說明以下。
l device:標識通訊端口,若是爲NULL,系統會自動檢測。
l baudrate:標識通信波特率,若是爲NULL,系統會自動檢測。
l initstring:標識初始化命令,爲NULL便可。
l charset:標識通信字符集,爲NULL便可。
l swHandshake:標識是否進行軟件握手,爲False便可。
l sn:標識短信貓的受權號,須要根據實際狀況填寫。
(5)GSMModemSMSsend函數
該函數用於發送手機短信。語法以下:
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemSMSsend",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern bool GSMModemSMSsend(
string serviceCenterAddress,
int encodeval,
string text,
int textlen,
string phonenumber,
bool requestStatusReport);
參數說明以下。
l serviceCenterAddress:標識短信中心號碼,爲NULL便可。
l encodeval:標識短信息編碼格式,若是爲8,表示中文短信編碼。
l text:標識短信內容。
l textlen:標識短信內容的長度。
l phonenumber:標識接收短信的電話號碼。
l requestStatusReport:標識狀態報告。
(6)GSMModemSMSReadAll函數
該函數取得全部短信息,包括SIM卡和手機中的短信息。返回的短信內容格式爲電話號碼1|短信內容1||電話號碼2|短信內容2||:
//接收短信息返回字符串格式爲:手機號碼|短信內容||手機號碼|短信內容||
//RD_opt爲1表示接收短信息後不作任何處理,爲0表示接收後刪除信息
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemSMSReadAll",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemSMSReadAll(int RD_opt);
參數說明以下。
l RD_opt:對讀取後的短信息進行處理,0表示刪除,1表示不作處理。
實現過程
(1)新建一個項目,命名爲Ex13_14,默認窗體爲Form1。
(2)在Form1窗體中,主要添加TextBox控件和Label控件,控件的數量及用途如圖13.15所示,添加兩個Button控件,分別用於發送短信息和接收短信息。
(3)主要程序代碼。
將所使用的函數封裝在GMS類中。代碼以下:
class GMS
{
//初始化gsm modem,並鏈接gsm modem
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemInitNew",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern bool GSMModemInitNew(
string device,
string baudrate,
string initstring,
string charset,
bool swHandshake,
string sn);
//獲取短信貓新的標識號碼
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetSnInfoNew",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetSnInfoNew(string device, string baudrate);
//獲取當前通信端口
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetDevice",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetDevice();
//獲取當前通信波特率
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetBaudrate",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetBaudrate();
//斷開鏈接並釋放內存空間
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemRelease",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern void GSMModemRelease();
//取得錯誤信息
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemGetErrorMsg",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemGetErrorMsg();
//發送短信息
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemSMSsend",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern bool GSMModemSMSsend(
string serviceCenterAddress,
int encodeval,
string text,
int textlen,
string phonenumber,
bool requestStatusReport);
//接收短信息返回字符串格式爲:手機號碼|短信內容||手機號碼|短信內容||
//RD_opt爲1接收短信息後不作任何處理,0爲接收後刪除信息
[DllImport("dllforvc.dll",
EntryPoint = "GSMModemSMSReadAll",
CharSet = CharSet.Ansi,
CallingConvention = CallingConvention.StdCall)]
public static extern string GSMModemSMSReadAll(int RD_opt);
}
在裝載Form1窗體時,獲取設備信息。代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
//機器號碼,當參數爲空時,函數自動獲取設備信息
txtJQHM.Text = GMS.GSMModemGetSnInfoNew(txtCOM.Text, txtBTL.Text);
txtCOM.Text = GMS.GSMModemGetDevice(); //COM1
txtBTL.Text= GMS.GSMModemGetBaudrate(); //波特率
}
發送短信息。代碼以下:
private void btnSend_Click(object sender, EventArgs e)
{
if(txtSJHM.Text == "")
{
MessageBox.Show("手機號碼不能爲空!","提示", MessageBoxButtons.OK);
txtSJHM.Focus();
return;
}
if(txtContent.Text=="")
{
MessageBox.Show("短信內容不能爲空!", "提示", MessageBoxButtons.OK);
txtContent.Focus();
return;
}
//鏈接設備
if(GMS.GSMModemInitNew(txtCOM.Text, txtBTL.Text, null, null, false, txtPower.Text)==false)
{
MessageBox.Show("設備鏈接失敗!" + GMS.GSMModemGetErrorMsg(),"提示", MessageBoxButtons.OK);
return;
}
// 發送短信
if (GMS.GSMModemSMSsend(null, 8, txtContent.Text, Encoding.Default.GetByteCount(txtContent.Text),txtSJHM.Text, false) == true)
MessageBox.Show("短信發送成功!", "提示", MessageBoxButtons.OK);
else
MessageBox.Show("短信發送失敗!" + GMS.GSMModemGetErrorMsg(), "提示", MessageBoxButtons.OK);
}
接收短信息。代碼以下:
private void btnResvice_Click(object sender, EventArgs e)
{
//1)鏈接設備
if (GMS.GSMModemInitNew(txtCOM.Text, txtBTL.Text, null, null, false, txtPower.Text) == false)
{
MessageBox.Show("鏈接失敗!" + GMS.GSMModemGetErrorMsg(), "提示", MessageBoxButtons.OK);
return;
}
//2)接收短信
txtContent.Text = GMS.GSMModemSMSReadAll(1);
txtSJHM.Text = txtContent.Text.Substring(0, 13);
txtContent.Text = txtContent.Text.Substring(13, txtContent.Text.Length-13);
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
利用短信貓羣發短信。
辦公自動化系統,辦公短信通知、短信日程提醒、應急信息短信發佈和短信審批等。
實例432 利用短信遠程關閉計算機
實例說明
本例實現了利用短信遠程關閉計算機的功能。運行程序,首先,進行關機信息設置;而後,開啓服務;最後,經過手機向短信貓發送「關機」數據。片刻以後,指定的計算機將會自動關機。程序如圖13.16所示。
技術要點
相關函數請參見實例「利用短信貓收發短信息」中的技術要點。
實現過程
(1)新建一個項目,命名爲Ex13_15,默認窗體爲Form1。
(2)在Form1窗體中,主要添加TextBox控件和Label控件,控件的數量及用途如圖13.16所示,添加一個Button控件,用於開啓或中止遠程關閉計算機服務。
(3)主要程序代碼。
private void Form1_Load(object sender, EventArgs e)
{
//機器號碼
txtJQHM.Text = GMS.GSMModemGetSnInfoNew(txtCOM.Text, txtBTL.Text);
txtCOM.Text = GMS.GSMModemGetDevice(); //COM1
txtBTL.Text = GMS.GSMModemGetBaudrate(); //波特率
labStatus.Text = "服務關閉中。。。。。";
}
private void Close_Windows()
{
try
{
//指定生成 WMI 鏈接所需的全部設置
ConnectionOptions op = new ConnectionOptions();
op.Username = txtUser.Text; //遠程計算機用戶名稱
op.Password = txtPWD.Text; //遠程計算機用戶密碼
//設置操做管理範圍
ManagementScope scope = new ManagementScope("\\\\" + txtIP.Text + "\\root\\cimv2", op);
scope.Connect(); //將此 ManagementScope 鏈接到實際的 WMI 範圍。
ObjectQuery oq = new ObjectQuery("SELECT * FROM Win32_OperatingSystem");
ManagementObjectSearcher query = new ManagementObjectSearcher(scope, oq);
//獲得WMI控制
ManagementObjectCollection queryCollection = query.Get();
foreach (ManagementObject obj in queryCollection)
{
obj.InvokeMethod("ShutDown", null); //執行關閉遠程計算機
}
}
catch(Exception ex)
{
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.CreateNoWindow = true;
p.Start();
p.StandardInput.WriteLine("shutdown /s");
p.StandardInput.WriteLine("exit");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
//鏈接設備
if (GMS.GSMModemInitNew(txtCOM.Text, txtBTL.Text, null, null, false, txtPower.Text) == false)
{
MessageBox.Show("鏈接失敗!" + GMS.GSMModemGetErrorMsg(), "提示", MessageBoxButtons.OK);
return;
}
//接收短信
string str = GMS.GSMModemSMSReadAll(1);
if (str==null)
return;
if (str.Substring(str.IndexOf("|")+1, 2) == "關機")
{
this.Close_Windows();
}
}
private void button1_Click(object sender, EventArgs e)
{
if (button1.Text == "開啓服務")
{
timer1.Enabled = true;
labStatus.Text = "關機命令採集中。。。。。";
button1.Text = "中止服務";
}
else
{
timer1.Enabled = false;
button1.Text = "開啓服務";
labStatus.Text = "服務關閉中。。。。。";
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
利用短信實現客戶資料查詢。
保險行業中:保單查詢、續費提醒、客戶生日提醒和保費計算等。
實例433 短信息採集菸草銷售數據
實例說明
在各種銷售行業中,產品銷售數據量是企業不可缺乏的一項數據。當銷售人員在外地出差而且在沒有計算機的狀況下,如何及時的將銷售數據彙報到公司中呢?
本例實現利用短信息採集菸草銷售數據的功能。銷售人員根據規定的格式編輯短信發送到短信息貓中便可。運行程序,單擊【菸草銷售信息採集】按鈕採集菸草銷售數據,而後單擊【統計】按鈕,將銷售數據整理出來。如圖13.17所示。
技術要點
相關函數請參見實例「利用短信貓收發短信息」中的技術要點。
另外,程序規定的編輯短信息格式爲,以冒號「:」分隔並結束。例如「張三:業務員:12:長春:3400:」。其中,主要使用String.Split( )方法將信息數據拆分。
圖13.17 短信息採集菸草銷售數據
String.Split( )方法:返回包含此實例中的子字符串(由指定 Char 數組的元素分隔)的 String 數組。
語法:
public string[] Split (
params char[] separator
)
參數說明以下。
l separator:分隔此實例中子字符串的 Unicode 字符數組,不包含分隔符的空數組或空引用。
l 返回值:一個數組,其元素包含此實例中的子字符串,這些子字符串由 separator 中的一個或多個字符分隔。
實現過程
(1)新建一個項目,命名爲Ex13_16,默認窗體爲Form1。
(2)在Form1窗體中,主要添加TextBox控件和Label控件,控件的數量及用途如圖13.17所示,添加3個Button控件,分別用於發送短信息、採集銷售數據和整理採集數據,添加兩個DataGridView表格,分別用於顯示短信息內容和整理後的銷售數據。
(3)主要程序代碼。
單擊【菸草銷售信息採集】按鈕,接受短信息並保存到數據庫中。代碼以下:
private void btnResvice_Click(object sender, EventArgs e)
{
//鏈接設備
if (GMS.GSMModemInitNew(txtCOM.Text, txtBTL.Text, null, null, false, txtPower.Text) == false)
{
MessageBox.Show("鏈接失敗!" + GMS.GSMModemGetErrorMsg(), "提示", MessageBoxButtons.OK);
return;
}
//接收短信
string content = GMS.GSMModemSMSReadAll(0);
if (content ==null)
{
this.getMessage();
return;
}
content= content.Replace("||", "|"); // 替換||爲|
string[] str_sp = content.Split('|');// 進行分離
int k=0;
dataGridView1.ColumnCount = 2;
dataGridView1.RowCount = str_sp.Length / 2;
dataGridView1.Columns[0].HeaderText = "手機號碼";
dataGridView1.Columns[1].HeaderText = "短信息";
for (int i = 0; i < str_sp.Length / 2; i++)
{
for (int j = 0; j < 2; j++)
{
dataGridView1[j, i].Value = str_sp[k];
if (k % 2 != 0)
this.InsertMessage("insert into RecivedBox (Mobile,Content,reciveTime)values('" + Convert.ToString(dataGridView1[0, i].Value) + "','" + Convert.ToString(dataGridView1[1, i].Value) + "','" + DateTime.Now.ToString() + "') ");
k++;
}
}
this.getMessage();
}
自定義方法getSplitMessage()用來拆分短信息而且整理爲正規數據。代碼以下:
private void getSplitMessage()
{
string content = "";
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
content = content + Convert.ToString(dataGridView1["短信息", i].Value);
}
string[] str_sp = content.Split(':');// 進行分離
int k = 0;
dataGridView2.ColumnCount = 5;
dataGridView2.RowCount = str_sp.Length/5 ;
dataGridView2.Columns[0].HeaderText = "姓名";
dataGridView2.Columns[1].HeaderText = "職務";
dataGridView2.Columns[2].HeaderText = "月份";
dataGridView2.Columns[3].HeaderText = "銷售地區";
dataGridView2.Columns[4].HeaderText = "銷售數量";
for (int i = 0; i < str_sp.Length / 5; i++)
{
for (int j = 0; j < 5; j++)
{
dataGridView2[j, i].Value = str_sp[k];
k++;
}
}
}
自定義InsertMessage()方法,將接受的短信息保存到數據庫中。代碼以下:
private void InsertMessage(string strSql)
{
//將短信息內容添加到數據庫中
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "message.mdb" + ";Persist Security Info=False");
con.Open();
OleDbCommand cmd = new OleDbCommand(strSql, con);
cmd.ExecuteNonQuery();
con.Close();
}
自定義getMessage()方法,獲取數據庫中全部的短信息數據。代碼以下:
private void getMessage()
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "message.mdb" + ";Persist Security Info=False");
OleDbDataAdapter dap = new OleDbDataAdapter("select mobile as 手機號碼,content as 短信息,reciveTime as 日期 from RecivedBox", con);
DataSet ds = new DataSet();
dap.Fill(ds);
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
調用自定義getSplitMessage()方法,將整理後的銷售數據顯示在DataGridView表格中。代碼以下:
private void btnFind_Click(object sender, EventArgs e)
{
if(dataGridView1.Rows.Count>0)
this.getSplitMessage();
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
利用短信實現銷售業績查詢。
利用短信實現訂購商品。
實例434 「春晚」節目評比短信息互動平臺
實例說明
在觀看娛樂電視節目中,主持人常常帶動場外的電視觀衆參與到活動當中。例如,在春節聯歡晚會中,經過編輯短信來選取觀衆最喜歡的春晚節目,那麼本實例將實現爲「春晚」節目評比的短信息互動平臺。電視觀衆根據規定的格式編輯短信發送到短信息互動平臺進行節目評比。運行程序,單擊【獲取參與觀衆短信】按鈕,便可獲得觀衆的投票,如圖13.18所示。
技術要點
相關函數請參見實例「利用短信貓收發短信息」中的技術要點。
實現過程
(1)新建一個項目,命名爲Ex13_17,默認窗體爲Form1。
(2)在Form1窗體中,主要添加TextBox控件和Label控件,控件的數量及用途如圖13.18所示,添加一個Button控件,用於獲取參與的觀衆短信息,添加一個DataGridView控件,用於顯示觀衆的投票信息。
(3)主要程序代碼。
private void btnResvice_Click(object sender, EventArgs e)
{
//鏈接設備
if (GMS.GSMModemInitNew(txtCOM.Text, txtBTL.Text, null, null, false, txtPower.Text) == false)
{
MessageBox.Show("鏈接失敗!" + GMS.GSMModemGetErrorMsg(), "提示", MessageBoxButtons.OK);
return;
}
//接收短信
string content = GMS.GSMModemSMSReadAll(0);
if (content == null)
{
this.getMessage();
return;
}
content = content.Replace("||", "|"); // 替換||爲|
string[] str_sp = content.Split('|');// 進行分離
int k = 0;
string[,] str_Sp = new string[2, str_sp.Length / 2];
for (int i = 0; i < str_sp.Length / 2; i++)
{
for (int j = 0; j < 2; j++)
{
str_Sp[j, i] = str_sp[k];
if (k % 2 != 0)
this.InsertMessage("insert into RecivedBox (Mobile,Content,reciveTime)values('" + Convert.ToString(str_Sp[0, i]) + "','" + Convert.ToString(str_Sp[1, i]) + "','" + DateTime.Now.ToString() + "') ");
k++;
}
}
this.getMessage();
}
private void getMessage()
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "message.mdb" + ";Persist Security Info=False");
OleDbDataAdapter dap = new OleDbDataAdapter("select mobile as 手機號碼,content as 短信息,reciveTime as 日期 from RecivedBox", con);
DataSet ds = new DataSet();
dap.Fill(ds);
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
private void InsertMessage(string strSql)
{
//將短信息內容添加到數據庫中
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "message.mdb" + ";Persist Security Info=False");
con.Open();
OleDbCommand cmd = new OleDbCommand(strSql, con);
cmd.ExecuteNonQuery();
con.Close();
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
手機短信息平臺訂購商品。
定時向手機發送天氣預報
13.7 其他程序
實例435 條形碼掃描器銷售商品
實例說明
現在,許多超市都利用條形碼銷售商品。微機操做員利用掃描器在商品的條形碼處進行掃描,商品的詳細信息就會顯示在屏幕中。本例實現了利用條形碼銷售商品的功能。效果如圖13.19所示。
技術要點
當利用掃描器掃描條形碼時,條形碼數據會顯示在當前得到焦點的窗口控件中。例如,若是當前編輯框得到焦點,那麼條形碼數據會顯示在TextBox文本框中。而後會向TextBox文本框發送回車鍵按下時的消息。
在程序中只要觸發TextBox文本框的KeyDown事件,判斷當前按鍵是不是回車鍵,若是是,讀取TextBox文本框中的條形碼數據,並從數據表中根據條形碼查詢商品信息,將其顯示在DataGridView列表中。
實現過程
(1)新建一個項目,命名爲Ex13_18,默認窗體爲Form1。
(2)在Form1窗體中,主要添加TextBox控件,用於接收條形碼;添加一個DataGridView控件,用於顯示掃描器掃描條形碼的商品銷售信息。
(3)主要程序代碼。
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyValue == 13)
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "price.mdb" + ";Persist Security Info=False");
OleDbDataAdapter dap = new OleDbDataAdapter("select * from MerchandiseInfo where barcode='" + textBox1.Text + "'", con);
DataSet ds = new DataSet();
dap.Fill(ds);
if (ds.Tables[0].Rows.Count == 0)
{
MessageBox.Show("該商品不存在!", "系統提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
for (int i = 0; i < dataGridView1.RowCount; i++)
{
if (Convert.ToString(dataGridView1[0, i].Value) == "")
{
dataGridView1[0, i].Value = ds.Tables[0].Rows[0][0].ToString();
dataGridView1[1, i].Value = ds.Tables[0].Rows[0][1].ToString();
dataGridView1[2, i].Value = ds.Tables[0].Rows[0][2].ToString();
dataGridView1[3, i].Value = ds.Tables[0].Rows[0][3].ToString();
return;
}
}
}
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
超市條形碼掃描系統。
公司工具條形碼掃描系統。
實例436 利用神龍卡製做練歌房程序
實例說明
在開發酒店、賓館的點歌系統時,使用神龍DVD解壓卡能夠方便地進行媒體控制。神龍DVD解壓卡(如下簡稱神龍卡)是一款專門針對中國大陸市場而開發出來的DVD硬解壓卡,神龍卡與好萊塢卡的基本功能相近,兩卡比較具備如下幾個區別。
l 神龍卡可播放中國大陸全區碼DVD碟,好萊塢卡可播放全球1~6區碼影碟,可無數次解區碼。
l 神龍卡支持1~5M碼流播放,好萊塢卡可支持1~15M的視頻流播放。
l 神龍卡支持全屏播放,好萊塢卡支持全屏及窗口(便可縮放窗口)播放。
l 神龍卡支持Win 9x下工做環境,好萊塢卡可支持Win 9x及WinNT下工做環境。
本例利用神龍卡實現了音樂的控制功能。運行程序,結果如圖13.20所示。
圖13.20 利用神龍卡製做練歌房程序
技術要點
本程序主要經過一個第三方NNSREALmagicCtrl.ocx控件實現。在.NET下使用第三方控件,首先,須要進行Windows註冊,註冊命令爲「REgsvr32 路徑\NNSREALmagicCtrl.ocx」;其次,將註冊成功的控件添加到Microsoft Visual Studio 2005開發環境中,實現步驟爲:選擇菜單「工具」/「選擇工具箱」,彈出「選擇工具箱」窗口,在該窗口中選擇「COM組件」選項卡,在列表中選擇註冊的第三方控件,單擊【肯定】按鈕便可,如圖13.21所示。
圖13.21 添加第三方控件
實現過程
(1)新建一個項目,命名爲Ex13_19,默認窗體爲Form1。
(2)在Form1窗體中,主要添加DataGridView控件,用於選擇播放影音;添加其餘控件及用途如圖13.20所示。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
if (strFileName == "")
{
MessageBox.Show("請在列表中選擇播放文件!","系統提示");
return;
}
axREALmagicCtrl1.Filename = strFileName; //指定播放文件
axREALmagicCtrl1.Play(); //播放
}
private void btnPause_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.Pause(); //暫停播放
}
private void btnStop_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.Stop(); //中止播放
}
private void btnSpeed_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.CurrentFrame = axREALmagicCtrl1.CurrentFrame + 125; //快進
}
private void btnRecede_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.CurrentFrame = axREALmagicCtrl1.CurrentFrame - 125; //快退
}
private void rdoLeftTrack_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.AudioChannel = NNSREALmagicCtrl.TAudChannel.acLEFT; //左聲道
}
private void rdoRightTrack_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.AudioChannel = NNSREALmagicCtrl.TAudChannel.acRIGHT; //右聲道
}
private void rdoStereo_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.AudioChannel = NNSREALmagicCtrl.TAudChannel.acSTEREO; //立體聲
}
private void tbVolume_Scroll(object sender, EventArgs e)
{
axREALmagicCtrl1.Volume = tbVolume.Value; //音量
}
private void rdoTV_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.DisplayDevice = NNSREALmagicCtrl.TDisDev.ddTV; //TV輸出模式
}
private void rdoVGA_Click(object sender, EventArgs e)
{
axREALmagicCtrl1.DisplayDevice = NNSREALmagicCtrl.TDisDev.ddVGA; //VGA輸出模式
}
private void Form1_Load(object sender, EventArgs e)
{
if (!axREALmagicCtrl1.OpenDriver()) //打開驅動
{
MessageBox.Show("打開驅動失敗!!", "系統提示");
this.groupBox1.Enabled = false;
this.groupBox2.Enabled = false;
this.groupBox3.Enabled = false;
this.groupBox4.Enabled = false;
return;
}
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "DataBase.mdb" + ";Persist Security Info=False");
OleDbDataAdapter dap = new OleDbDataAdapter("select G_name as 影音名稱,G_YC as 原唱,G_wjlx as 文件格式 from g_music_name", con);
DataSet ds = new DataSet();
dap.Fill(ds); //顯示影音文件的相關屬性
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
private void dataGridView1_CellClick(object sender, DataGridViewCellEventArgs e)
{ //選擇播放的影音
strFileName = @"\vod\" + dataGridView1[0, e.RowIndex].Value.ToString() + "." + dataGridView1[2, e.RowIndex].Value.ToString();
}
觸類旁通
根據本實例,讀者能夠開發如下程序。
練歌房卡拉OK系統。
單機卡拉OK系統。
第16章 加密、安全與軟件註冊
16.1 數據加密與解密
在企業的計算機中,每每存有大量的機密文件,這些機密文件與企業的發展有緊密聯繫,若是這些機密文件保管不善,將會使企業遭受巨大的損失。本節經過幾個典型實例詳細介紹一下C#中的加密與解密技術。
實例463 數據加密技術
實例說明
本實例實現對文件的機密數據進行加密的功能。運行程序,在文本框中輸入要加密的數據,單擊【加密】按鈕,對數據進行加密,並將加密後的數據顯示在「加密後的字符」文本框中。實例運行結果如圖16.1所示。
技術要點
實現本實例功能主要用到了System.Security.Cryptography命名空間下的MD5Crypto- ServiceProvider類的ComputeHash( )方法、System.Text命名空間下的ASCIIEncoding類的ASCII屬性、GetBytes( )方法和GetString( )方法。下面分別進行介紹。
(1)System.Security.Cryptography命名空間
System.Security.Cryptography 命名空間提供加密服務(包括安全的數據編碼和解碼)以及許多其餘操做,例如散列法、隨機數字生成和消息身份驗證。
(2)MD5CryptoServiceProvider類
此類使用加密服務提供程序(CSP)提供的實現,計算輸入數據的MD5哈希值。
語法格式爲:
public sealed class MD5CryptoServiceProvider : MD5
注意:MD5CryptoServiceProvider類的哈希大小爲128位。
(3)ComputeHash( )方法
此方法計算指定字節數組的哈希值。
語法格式爲:
public byte[] ComputeHash (byte[] buffer)
參數說明以下。
l buffer:要計算其哈希代碼的字節數組。
l 返回值:計算所得的哈希代碼。
(4)System.Text命名空間
表示 ASCII、Unicode、UTF-7和UTF-8字符編碼的類;是用於將字符塊轉換爲字節塊和將字節塊轉換爲字符塊的抽象基類。
(5)ASCIIEncoding類
此類表示Unicode字符的ASCII字符編碼。
語法格式爲:
public class ASCIIEncoding : Encoding
(6)ASCII屬性
此屬性獲取 ASCII(7位)字符集的編碼。
語法格式爲:
public static Encoding ASCII { get; }
l 屬性值:ASCII(7 位)字符集的Encoding。
(7)GetBytes( )方法
此方法將指定的String中的全部字符編碼爲一個字節序列。
語法格式爲:
public virtual byte[] GetBytes (string s)
參數說明以下。
l s:包含要編碼的字符的String。
(8)GetString( )方法
此方法將指定字節數組中的全部字節解碼爲一個字符串。
語法格式爲:
public virtual string GetString (byte[] bytes)
參數說明以下。
l bytes:包含要解碼的字節序列的字節數組。
l 返回值:包含指定字節序列解碼結果的String。
注意:使用MD5CryptoServiceProvider類必須引用System.Security.Cryptography命名空間。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_01,默認窗體爲Form1。
(2)在Form1窗體中,主要添加兩個TextBox控件,用來輸入和顯示字符串;添加一個Button控件,用來執行加密操做。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{ MessageBox.Show("請輸入加密數據"); return; }
MD5CryptoServiceProvider M5 = new MD5CryptoServiceProvider();
textBox2.Text = ASCIIEncoding.ASCII.GetString(M5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(textBox1.Text)));
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
對機密的文件夾進行加密與解密。
在數據傳輸中使用,以便保證傳輸信息不被泄露。
實例464 文本文件加密與解密
實例說明
本實例實現對計算機中的一些很是機密的文本文件進行加密與解密操做。運行程序,單擊【選擇文件】按鈕,選擇要進行加密或解密的文本文件(.txt格式的文件),單擊【加密】或【解密】按鈕,便可完成對文本文件的加密或解密操做。實例運行結果如圖16.2所示。
技術要點
實現本實例功能主要用到了System.Security.Cryptography命名空間下的RijndaelManaged類的CreateDecryptor( )方法、CreateEncryptor( )方法、CryptoStream類的Write( )方法、FlushFinalBlock( )方法、Close( )方法、System.IO命名空間下的FileStream類、StreamReader類的ReadToEnd( )方法、StreamWriter類的Write( )方法、Flush( )方法和BinaryReader類的ReadBytes( )方法。System.Security.Cryptography命名空間在第16章實例463中已經作過詳細介紹,這裏再也不詳細描述,下面對本實例中用到的其餘知識進行詳細介紹。
(1)RijndaelManaged類
此類表示Rijndael對稱加密算法的全部實現必須從其繼承的基類中得到。
語法格式爲:
public abstract class Rijndael SymmetricAlgorithm
注意:此算法支持12八、192或256位的密鑰長度。
(2)CreateDecryptor( )方法
此方法使用指定的Key和初始化向量(IV)建立對稱的Rijndael解密器對象。
語法格式爲:
public override IcryptoTransform CreateDecryptor (byte[] rgbKey,byte[] rgbIV)
參數說明以下。
l rgbKey:用於對稱算法的機密密鑰。
l rgbIV:用於對稱算法的IV。
l 返回值:對稱的Rijndael解密器對象。
(3)CreateEncryptor( )方法
此方法使用指定的Key和初始化向量(IV)建立對稱的Rijndael加密器對象。
語法格式爲:
public override ICryptoTransform CreateEncryptor (byte[] rgbKey,byte[] rgbIV)
參數說明以下。
l rgbKe:用於對稱算法的機密密鑰。
l rgbIV:用於對稱算法的IV。
l 返回值:對稱的Rijndael加密器對象。
(4)CryptoStream類
此類定義將數據流連接到加密轉換的流。
語法格式爲:
public CryptoStream (Stream stream,ICryptoTransform transform,CryptoStreamMode mode)
參數說明以下。
l stream:對其執行加密轉換的流。
l Transform:要對流執行的加密轉換。
l Mode:CryptoStreamMode值之一。CryptoStreamMode值及明說如表16.1所示。
表16.1 CryptoStreamMode值及說明
值 |
說 明 |
Read |
對加密流的讀訪問 |
Write |
對加密流的寫訪問 |
(5)CryptoStream類的Write( )方法
此方法將一個字節序列寫入當前CryptoStream類中,並從當前位置寫入指定的字節數。
語法格式爲:
public override void Write (byte[] buffer,int offset,int count)
參數說明以下。
l buffer:字節數組。此方法將count個字節從buffer複製到當前流。
l offset:buffer中的字節偏移量,今後偏移量開始將字節複製到當前流。
l count:要寫入當前流的字節數。
(6)FlushFinalBlock( )方法
此方法用緩衝區的當前狀態更新基礎數據源或儲存庫,隨後清除緩衝區。
語法格式爲:
public void FlushFinalBlock ()
(7)Close( )方法
關閉當前流並釋放與之關聯的全部資源(如套接字和文件句柄)。
語法格式爲:
public virtual void Close ()
(8)System.IO命名空間
System.IO命名空間包含容許讀寫文件和數據流的類型以及提供基本文件和目錄支持的類型。
(9)FileStream類
此類公開以文件爲主的Stream,既支持同步讀寫操做,也支持異步讀寫操做。
語法格式爲:
public FileStream (string path,FileModemode,FileAccessaccess)
參數說明以下。
l path:當前FileStream類對象封裝文件的相對路徑或絕對路徑。
l Mode:FileMode常數,肯定如何打開或建立文件。FileMode常數的值及說明如表16.2所示。
l Access:FileAccess常數,肯定FileStream對象訪問文件的方式。這將獲取FileStream對象的CanRead和CanWrite屬性。若是path指定磁盤文件,則CanSeek爲True。FileAccess常數的值及說明如表16.3所示。
表16.2 FileMode常數的值及說明
常 數 值 |
說 明 |
Append |
打開現有文件並查找到文件尾,或建立新文件。FileMode.Append只能同FileAccess.Write一塊兒使用。任何讀嘗試都將失敗並引起ArgumentException |
Create |
指定操做系統應建立新文件。若是文件已存在,它將被改寫。這要求FileIOPermissionAccess.Write和System.IO.FileMode.Create等效於這樣的請求:若是文件不存在,則使用CreateNew;不然使用Truncate |
CreateNew |
指定操做系統應建立新文件。此操做須要FileIOPermissionAccess.Write。若是文件已存在,則將引起IOException |
Open |
指定操做系統應打開現有文件。打開文件的能力取決於FileAccess所指定的值。若是該文件不存在,則引起System.IO.FileNotFoundException |
OpenOrCreate |
指定操做系統應打開文件(若是文件存在);不然,應建立新文件。若是用FileAccess.Read打開文件,則須要FileIOPermissionAccess.Read。若是文件訪問爲FileAccess.Write或FileAccess.ReadWrite,則須要FileIOPermissionAccess.Write。若是文件訪問爲FileAccess.Append,則須要FileIOPermissionAccess.Append |
Truncate |
指定操做系統應打開現有文件。文件一旦打開,就將被截斷爲零字節大小。此操做須要FileIOPermissionAccessWrite。試圖從使用Truncate打開的文件中進行讀取將致使異常 |
表16.3 FileAccess常數的值及說明
常 數 值 |
說 明 |
Read |
對文件的讀訪問。可從文件中讀取數據。同Write組合即構成讀寫訪問權 |
ReadWrite |
對文件的讀訪問和寫訪問。可從文件讀取數據和將數據寫入文件 |
Write |
文件的寫訪問。可將數據寫入文件。同Read組合即構成讀/寫訪問權 |
(10)StreamReader類
此類實現一個TextReader,使其以一種特定的編碼從字節流中讀取字符。
語法格式爲:
public StreamReader (Stream stream)
參數說明以下。
l stream:要讀取的流。
(11)ReadToEnd( )方法
此方法從流的當前位置到末尾讀取流。
public override string ReadToEnd ()
l 返回值:字符串形式的流的其他部分(從當前位置到末尾)。若是當前位置位於流的末尾,則返回空字符串(「」)。
(12)StreamWriter類
此類實現一個TextWriter,使其以一種特定的編碼向流中寫入字符。
語法格式爲:
public StreamWriter (Stream stream)
參數說明以下。
l stream:要寫入的流。
(13)StreamWriter類的Write( )方法
此方法將字符寫入流。
語法格式爲:
public override void Write (char value)
參數說明以下。
l value:要寫入文本流中的字符。
(14)Flush( )方法
此方法清理當前編寫器的全部緩衝區,並使全部緩衝數據寫入基礎流。
語法格式爲:
public override void Flush ()
(15)BinaryReader類
此類用特定的編碼將基元數據類型讀做二進制值。
語法格式爲:
public BinaryReader (Stream input)
參數說明以下。
l Input:流。
(16)ReadBytes( )方法
此方法從當前流中將count個字節讀入字節數組,並使當前位置提高count個字節。
語法格式爲:
public virtual byte[] ReadBytes (int count)
參數說明以下。
l count:要讀取的字節數。
l 返回值:包含從基礎流中讀取的數據的字節數組。若是到達了流的末尾,則該字節數組可能小於所請求的字節數。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_02,默認窗體爲Form1。
(2)在Form1窗體中,主要添加一個TextBox控件,用來顯示文件路徑;添加一個OpenFileDialog控件,用來選擇要加密或解密的文件;添加3個Button控件,用來執行加密、解密和選擇文件操做。
(3)主要程序代碼。
加密文本文件的實現代碼以下:
private void button5_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{ MessageBox.Show("請選擇要加密的文件"); }
else
{
try{
string strPath = textBox1.Text;//加密文件的路徑
int intLent=strPath.LastIndexOf("\\")+1;
int intLong = strPath.Length;
//要加密的文件名稱
string strName = strPath.Substring(intLent,intLong-intLent);
int intTxt = strName.LastIndexOf(".");
int intTextLeng = strName.Length;
//取出文件的擴展名
string strTxt = strName.Substring(intTxt,intTextLeng-intTxt);
strName = strName.Substring(0,intTxt);
//加密後的文件名及路徑
string strOutName = strPath.Substring(0, strPath.LastIndexOf("\\") + 1) + strName + "Out" + strTxt;
//加密文件密鑰
byte[] key = { 24, 55, 102, 24, 98, 26, 67, 29, 84, 19, 37, 118, 104, 85, 121, 27, 93, 86, 24, 55, 102, 24, 98, 26, 67, 29, 9, 2, 49, 69, 73, 92 };
byte[] IV ={ 22, 56, 82, 77, 84, 31, 74, 24, 55, 102, 24, 98, 26, 67, 29, 99 };
RijndaelManaged myRijndael = new RijndaelManaged();
FileStream fsOut = File.Open(strOutName, FileMode.Create, FileAccess.Write);
FileStream fsIn = File.Open(strPath, FileMode.Open, FileAccess.Read);
//寫入加密文本文件
CryptoStream csDecrypt = new CryptoStream(fsOut, myRijndael.CreateEncryptor(key, IV), CryptoStreamMode.Write);
//讀加密文本
BinaryReader br = new BinaryReader(fsIn);
csDecrypt.Write(br.ReadBytes((int)fsIn.Length), 0, (int)fsIn.Length);
csDecrypt.FlushFinalBlock();
csDecrypt.Close();
fsIn.Close();
fsOut.Close();
if (MessageBox.Show(strOutName, "提示:加密成功!加密後的文件名及路徑爲:\n"+"是否刪除源文件", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
File.Delete(strPath);
textBox1.Text = "";
}else
{ textBox1.Text = ""; }
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
}
}
解密文本文件的實現代碼以下:
private void button4_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{
MessageBox.Show("請選擇要解密的文件路徑");
}
else
{
string strPath = textBox1.Text;//加密文件的路徑
int intLent = strPath.LastIndexOf("\\") + 1;
int intLong = strPath.Length;
//要加密的文件名稱
string strName = strPath.Substring(intLent, intLong - intLent);
int intTxt = strName.LastIndexOf(".");
int intTextLeng = strName.Length;
strName = strName.Substring(0, intTxt);
if (strName.LastIndexOf("Out") != -1)
{
strName = strName.Substring(0, strName.LastIndexOf("Out"));
}
else
{
strName = strName + "In";
}
//加密後的文件名及路徑
string strInName = strPath.Substring(0, strPath.LastIndexOf("\\") + 1) + strName + ".txt"; //解密文件密鑰
byte[] key = { 24, 55, 102, 24, 98, 26, 67, 29, 84, 19, 37, 118, 104, 85, 121, 27, 93, 86, 24, 55, 102, 24, 98, 26, 67, 29, 9, 2, 49, 69, 73, 92 };
byte[] IV ={ 22, 56, 82, 77, 84, 31, 74, 24, 55, 102, 24, 98, 26, 67, 29, 99 };
RijndaelManaged myRijndael = new RijndaelManaged();
FileStream fsOut = File.Open(strPath, FileMode.Open, FileAccess.Read);
CryptoStream csDecrypt = new CryptoStream(fsOut, myRijndael.CreateDecryptor(key, IV), CryptoStreamMode.Read);
StreamReader sr = new StreamReader(csDecrypt);//把文件讀出來
StreamWriter sw = new StreamWriter(strInName);//解密後文件寫入一個新的文件
sw.Write(sr.ReadToEnd());
sw.Flush();
sw.Close();
sr.Close();
fsOut.Close();
if (MessageBox.Show(strInName, "提示:解密成功!解密後的文件名及路徑爲:" + "是否刪除源文件", MessageBoxButtons.YesNo) == DialogResult.Yes)
{
File.Delete(strPath);
textBox1.Text = "";
}
else
{
textBox1.Text = "";
}
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
對重要公文進行加密。
對網絡中傳輸的文件進行加密與解密。
實例465 利用圖片加密文件
實例說明
本實例中,利用圖片生成密鑰,而後對文本文件進行加密和解密操做。運行程序,單擊【打開圖片】按鈕,選擇密鑰圖片,而後單擊【打開文本文件】按鈕,選擇要加密或解密的文件,單擊【加密】或【解密】按鈕完成文本文件的加密或解密操做。解密時的密鑰圖片要與加密時的密鑰圖片相同,不然解密不能成功。實例運行結果如圖16.3所示。
技術要點
實現本實例功能主要用到了System.Security.Cryptography命名空間下的RC2CryptoServiceProvider類的CreateDecryptor( )方法、CreateEncryptor( )方法、CryptoStream類的Write( )方法、FlushFinalBlock( )方法、Close( )方法、System.IO命名空間下的FileStream類、BinaryReader類的ReadBytes( )方法、BinaryWriter類的Write( )方法、File類的Delete( )方法和Copy( )方法。以上大部分知識在第16章實例464中已經作過詳細介紹,這裏再也不詳細講解。下面主要對RC2CryptoServiceProvider類、BinaryWriter類的Write( )方法、File類的Delete( )方法和Copy( )方法進行介紹。
(1)RC2CryptoServiceProvider類
此類定義訪問RC2算法的加密服務提供程序(CSP)實現的包裝對象。
(2)BinaryWriter類
此類以二進制形式將基元類型寫入流,並支持用特定的編碼寫入字符串。
語法格式爲:
public BinaryWriter (Streamoutput)
參數說明以下。
l output:輸出流。
(3)BinaryWriter類的Write( )方法
此方法將一個無符號字節寫入當前流,並將流的位置提高1個字節。
語法格式爲:
public virtual void Write (byte value)
參數說明以下。
l value:要寫入的無符號字節。
(4)File類
此類提供用於建立、複製、刪除、移動和打開文件的靜態方法,並協助建立FileStream對象。
(5)Delete( )方法
此方法刪除指定的文件。若是指定的文件不存在,則引起異常。
語法格式爲:
public static void Delete (string path)
參數說明以下。
l path:要刪除的文件的名稱。
(6)Copy( )方法
此方法將現有文件複製到新文件,不容許改寫同名的文件。
語法格式爲:
public static void Copy (string sourceFileName,string destFileName)
參數說明以下。
l sourceFileName:要複製的文件。
l destFileName:目標文件的名稱,不能是一個目錄或現有文件。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_03,默認窗體爲Form1。
(2)在Form1窗體中,主要添加一個TextBox控件,用來顯示加密或解密文件的路徑;添加一個OpenFileDialog控件,用來選擇要加密或解密的文件和打開密鑰的圖片;添加4個Button控件,用來執行加密、解密、打開文件和打開圖片操做;添加一個PictureBox控件,用於顯示密鑰圖片。
(3)主要程序代碼。
利用圖片加密文本文件的實現代碼以下:
private void button3_Click(object sender, EventArgs e)
{
try
{
if (pictureBox1.ImageLocation==null)
{ MessageBox.Show("請選擇一幅圖片用於加密"); return; }
if (textBox1.Text == "")
{ MessageBox.Show("請選擇加密文件路徑"); return; }
//圖片流
FileStream fsPic = new FileStream(pictureBox1.ImageLocation, FileMode.Open, FileAccess.Read);
//加密文件流
FileStream fsText = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read);
//初始化Key IV
byte[] bykey = new byte[16];
byte[] byIv = new byte[8];
fsPic.Read(bykey, 0, 16);
fsPic.Read(byIv, 0, 8);
//臨時加密文件
string strPath = textBox1.Text;//加密文件的路徑
int intLent = strPath.LastIndexOf("\\") + 1;
int intLong = strPath.Length;
string strName = strPath.Substring(intLent, intLong - intLent);//要加密的文件名稱
string strLinPath = "C:\\" + strName;//臨時加密文件路徑
FileStream fsOut = File.Open(strLinPath, FileMode.Create, FileAccess.Write);
//開始加密
RC2CryptoServiceProvider desc = new RC2CryptoServiceProvider();//desc進行加密
BinaryReader br = new BinaryReader(fsText);//從要加密的文件中讀出文件內容
CryptoStream cs = new CryptoStream(fsOut, desc.CreateEncryptor(bykey, byIv), CryptoStreamMode.Write);//寫入臨時加密文件
cs.Write(br.ReadBytes((int)fsText.Length), 0, (int)fsText.Length);//寫入加密流
cs.FlushFinalBlock();
cs.Flush();
cs.Close();
fsPic.Close();
fsText.Close();
fsOut.Close();
File.Delete(textBox1.Text.TrimEnd());//刪除原文件
File.Copy(strLinPath, textBox1.Text);//複製加密文件
File.Delete(strLinPath);//刪除臨時文件
MessageBox.Show("加密成功");
pictureBox1.ImageLocation = null;
textBox1.Text = "";
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
}
利用圖片解密文本文件的實現代碼以下:
private void button4_Click(object sender, EventArgs e)
{
try
{
//圖片流
FileStream fsPic = new FileStream(pictureBox1.ImageLocation, FileMode.Open, FileAccess.Read);
//解密文件流
FileStream fsOut = File.Open(textBox1.Text, FileMode.Open, FileAccess.Read);
//初始化Key IV
byte[] bykey = new byte[16];
byte[] byIv = new byte[8];
fsPic.Read(bykey, 0, 16);
fsPic.Read(byIv, 0, 8);
//臨時解密文件
string strPath = textBox1.Text;//加密文件的路徑
int intLent = strPath.LastIndexOf("\\") + 1;
int intLong = strPath.Length;
string strName = strPath.Substring(intLent, intLong - intLent);//要加密的文件名稱
string strLinPath = "C:\\" + strName;//臨時解密文件路徑
FileStream fs = new FileStream(strLinPath, FileMode.Create, FileAccess.Write);
//開始解密
RC2CryptoServiceProvider desc = new RC2CryptoServiceProvider();//desc進行解密
CryptoStream csDecrypt = new CryptoStream(fsOut, desc.CreateDecryptor(bykey, byIv), CryptoStreamMode.Read);//讀出加密文件
BinaryReader sr = new BinaryReader(csDecrypt);//從要加密流中讀出文件內容
BinaryWriter sw = new BinaryWriter(fs);//寫入解密流
sw.Write(sr.ReadBytes(Convert.ToInt32(fsOut.Length)));//
sw.Flush();
sw.Close();
sr.Close();
fs.Close();
fsOut.Close();
fsPic.Close();
csDecrypt.Flush();
File.Delete(textBox1.Text.TrimEnd());//刪除原文件
File.Copy(strLinPath, textBox1.Text);//複製加密文件
File.Delete(strLinPath);//刪除臨時文件
MessageBox.Show("解密成功");
pictureBox1.ImageLocation = null;
textBox1.Text = "";
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
利用各類圖片加密文件。
使用圖片批量解密文件。
16.2 Access數據庫安全
因爲Access數據庫操做簡單,使用方便,因此一些中小型的應用軟件常常採用Access數據庫。爲了保證數據庫的安全,常常要加密或鎖定數據庫,若是數據庫因爲某種緣由遭到破壞,就須要對數據庫進行修復。下面的幾個實例分別實現了加密、鎖定和修復Access數據庫的功能。
實例466 如何編程修復Access數據庫
實例說明
Access數據庫操做簡單,使用方便,是中小型企業常常採用的數據庫,但Access數據庫容易遭到破壞,並隨着時間的增長,數據庫文件會變得很是大,該如何解決這些問題呢?本實例經過壓縮數據庫的方法從新組織修復數據庫,減小了數據庫佔用的空間。運行程序,單擊【打開】按鈕,找到要修復的數據庫,單擊【開始修復】按鈕,便可完成修復數據庫操做。實例運行結果如圖16.4所示。
技術要點
實現本實例功能主要用到了JRO命名空間下JetEngineClass對象的CompactDatabase( )方法、System.IO命名空間下File類的Copy( )方法和Delete( )方法。下面分別進行介紹。
(1)CompactDatabase( )方法
CompactDatabase( )方法壓縮並回收本地數據庫中的浪費空間。
語法格式爲:
CompactDatabase(strng SourceConnection, string DestConnection)
參數說明以下。
l SourceConnection:字符串值,指定與要壓縮的源數據庫的鏈接。
l DestConnection:字符串值,指定與要經過壓縮建立的目標數據庫的鏈接。
注意:必須引用C:\Program Files\Common Files\System\ado\msjro.dll,該DLL包含JRO命名空間。
(2)Copy( )方法
此方法將現有文件複製到新文件,不容許改寫同名的文件。
語法格式爲:
public static void Copy (string sourceFileName,string destFileName)
參數說明以下。
l sourceFileName:要複製的文件。
l destFileName:目標文件的名稱,不能是一個目錄或現有文件。
(3)Delete( )方法
此方法刪除指定的文件。
語法格式爲:
public static void Delete (string path)
參數說明以下。
l path:要刪除的文件的名稱。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_04,默認窗體爲Form1。
(2)在Form1窗體中,主要添加一個TextBox控件,用來顯示修復數據庫文件的路徑;添加一個OpenFileDialog控件,用來選擇要修復的數據庫文件;添加3個Button控件,用來執行修復、退出和打開數據庫文件操做。
(3)主要程序代碼。
開始壓縮數據庫的實現代碼以下:
string strPathMdb = null;//數據庫路徑
private void button2_Click(object sender, EventArgs e)
{
if (!File.Exists(strPathMdb)) //檢查數據庫是否已存在
{
MessageBox.Show("目標數據庫不存在,沒法壓縮","操做提示");
return;
}
//聲明臨時數據庫的名稱
string temp = DateTime.Now.Year.ToString();
temp += DateTime.Now.Month.ToString();
temp += DateTime.Now.Day.ToString();
temp += DateTime.Now.Hour.ToString();
temp += DateTime.Now.Minute.ToString();
temp += DateTime.Now.Second.ToString() + ".bak";
temp = strPathMdb.Substring(0, strPathMdb.LastIndexOf("\\") + 1) + temp;
//定義臨時數據庫的鏈接字符串
string temp2 = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + temp;
//定義目標數據庫的鏈接字符串
string strPathMdb2 = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strPathMdb;
//建立一個JetEngineClass對象的實例
JRO.JetEngineClass jt = new JRO.JetEngineClass();
//使用JetEngineClass對象的CompactDatabase方法壓縮修復數據庫
jt.CompactDatabase(strPathMdb2, temp2);
//複製臨時數據庫到目標數據庫(覆蓋)
File.Copy(temp, strPathMdb, true);
//最後刪除臨時數據庫
File.Delete(temp);
MessageBox.Show("修復完成");
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
定時數據庫壓縮。
定時數據庫備份。
實例467 訪問帶驗證模式的Sqlserver 2000數據庫
實例說明
本實例實現了訪問帶驗證模式的SQL Server 2000數據庫的功能。用戶登陸數據庫時,必須輸入用戶名和密碼。運行程序,輸入計算機的名稱或地址、訪問數據庫的用戶名、密碼和數據庫名稱,單擊【登陸】按鈕,便可登陸數據庫。實例運行結果如圖16.5所示。
技術要點
實現本實例功能主要用到了ADO.NET的SqlConnection對象的Open( )方法、Close( )方法和ConnectionState枚舉。下面分別進行介紹。
(1)SqlConnection對象
此對象表示SQL Server數據庫的一個打開的鏈接。
語法格式爲:
public SqlConnection (string connectionString)
參數說明以下。
l connectionString:用於打開SQL Server數據庫的鏈接。
(2)Open( )方法
此方法使用ConnectionString所指定的屬性設置打開的數據庫鏈接。
語法格式爲:
public override void Open ()
(3)Close( )方法
此方法關閉與數據庫的鏈接。這是關閉任何打開鏈接的首選方法。
語法格式爲:
public override void Close ()
(4)ConnectionState枚舉
此枚舉描述與數據源鏈接的當前狀態。
語法格式爲:
public enum ConnectionState
ConnectionState枚舉值及說明如表16.4所示。
表16.4 ConnectionState枚舉值及說明
枚 舉 值 |
說 明 |
Broken |
與數據源的鏈接中斷。只有在鏈接打開以後纔可能發生這種狀況。能夠關閉處於這種狀態的鏈接,而後從新打開 |
Closed |
鏈接處於關閉狀態 |
Connecting |
鏈接對象正在與數據源鏈接 |
Executing |
鏈接對象正在執行命令 |
Fetching |
鏈接對象正在檢索數據 |
Open |
鏈接處於打開狀態 |
注意:使用SqlConnection對象必須引用System.Data.SqlClient命名空間。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_05,默認窗體爲Form1。
(2)在Form1窗體中,主要添加4個TextBox控件,用於輸入登陸信息;添加3個Button控件,用來執行登陸、斷開鏈接和退出操做。
(3)主要程序代碼。
登陸數據庫的實現代碼以下:
public SqlConnection con = null;//實義數據庫鏈接對象
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{
MessageBox.Show(textBox1.Tag.ToString()+"不能爲空","提示");
textBox1.Focus();
return;
}
if (textBox2.Text == "")
{
MessageBox.Show(textBox2.Tag.ToString() + "不能爲空", "提示");
textBox2.Focus();
return;
}
if (textBox4.Text == "")
{
MessageBox.Show(textBox4.Tag.ToString() + "不能爲空", "提示");
textBox4.Focus();
return;
}
try
{
string strcon = "server='" + textBox1.Text.Trim() + "';uid='" + textBox2.Text.Trim() + "';pwd='" + textBox3.Text + "';database='" + textBox4.Text.Trim() + "'";
con = new SqlConnection(strcon);//實例SqlConnect對象
con.Open();
MessageBox.Show("登陸成功");
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
}
斷開鏈接退出數據庫登陸的實現代碼以下:
private void button2_Click(object sender, EventArgs e)
{
if (con.State == ConnectionState.Open)
{
con.Close();
MessageBox.Show("鏈接已斷開");
}
else
{
MessageBox.Show("尚未鏈接數據庫");
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
對數據庫添加用戶。
對數據庫添加用戶權限。
16.3 軟件註冊與加密
爲了使開發的軟件能被更普遍地使用,開發者但願更多的用戶能試用軟件,而另外一方面,又不想讓用戶長時間無償使用未經受權的軟件,這就須要設計軟件註冊程序。下面經過幾個典型實例介紹保護軟件安全的方法。
實例468 利用INI文件對軟件進行註冊
實例說明
本實例實現使用INI文件對軟件的用戶信息進行註冊的功能。運行程序,輸入登陸名稱、登陸口令和註冊碼,單擊【註冊】按鈕進行註冊,若是註冊成功,則給出提示;若是信息已註冊,系統給出提示信息。實例運行結果如圖16.6所示。
技術要點
實現本實例功能主要用到API函數WritePrivateProfileString和GetPrivateProfileString函數。下面分別進行介紹。
(1)WritePrivateProfileString函數
此函數實現對INI文件的寫操做。
函數聲明以下。
[ DllImport ( "kernel32" ) ]
private static extern long WritePrivateProfileString ( string section ,string key , string val , string filePath ) ;
參數說明以下。
l section:INI文件中的段落。
l key:INI文件中的關鍵字。
l val:INI文件中關鍵字的數值。
l filePath:INI文件完整的路徑和名稱。
(2)GetPrivateProfileString函數
此函數實現對INI文件的讀操做。
函數聲明以下。
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
參數說明如表16.5所示。
表16.5 參數說明
參 數 值 |
說 明 |
section |
INI文件中的段落名稱 |
key |
INI文件中的關鍵字 |
def |
沒法讀取時候的缺省數值 |
retVal |
讀取數值 |
size |
數值的大小 |
filePath |
INI文件的完整路徑和名稱 |
注意:使用API函數必須引用System.Runtime.InteropServices命名空間。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_07,默認窗體爲Form1。
(2)在Form1窗體中,主要添加3個TextBox控件,用於輸入註冊信息;添加兩個Button控件,用來執行註冊和退出操做。
(3)主要程序代碼。
註冊用戶信息的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
FileStream c = new FileStream("C:\\desck.ini",FileMode.OpenOrCreate,FileAccess.Write);
}
[ DllImport ( "kernel32" ) ]
private static extern long WritePrivateProfileString ( string section ,string key , string val , string filePath ) ;
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
private void button1_Click(object sender, EventArgs e)
{
StringBuilder temp = new StringBuilder(200);
string FileName = "C:\\desck.ini";//NI文件的完整的路徑和名稱。
foreach (object ct in Controls)
{
if (ct.GetType().ToString() == "System.Windows.Forms.TextBox")
{
TextBox tx = (TextBox)ct;
if (tx.Text == "")
{
MessageBox.Show(tx.Tag.ToString()+"不能爲空");
}
}
}
string section = textBox3.Text;//INI文件中的段落
string key = textBox1.Text;//INI文件中的關鍵字
string keyValue = textBox2.Text;//INI文件中的關鍵字
int i = GetPrivateProfileString(section, key, "沒法讀取對應數值!", temp, 200, FileName);//判斷是否註冊過
if (temp.ToString() == "沒法讀取對應數值!")
{
WritePrivateProfileString(section, key, keyValue, FileName);
MessageBox.Show("註冊成功寫入INI文件!", "信息");
}
else
{
MessageBox.Show("此信息已註冊過了");
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
對INI文件加密保存註冊信息。
對組合INI文件加密保存註冊信息。
實例469 利用註冊表設計軟件註冊程序
實例說明
大多數應用軟件會將用戶輸入的註冊信息寫進註冊表中,程序運行過程當中,能夠將這些信息從註冊表中讀出。本實例主要實如今程序中對註冊表進行操做的功能,運行程序,單擊【註冊】按鈕,會將用戶輸入的信息寫入註冊表中。實例運行結果如圖16.7所示。
技術要點
實現本實例功能主要用到了Microsoft.Win32命名空間下的Registry類的CurrentUser屬性、RegistryKey類的OpenSubKey( )方法、GetSubKeyNames( )方法、SetValue( )方法和CreateSubKey( )方法。下面分別進行介紹。
(1)Microsoft.Win32命名空間
Microsoft.Win32命名空間提供兩種類型的類:處理由操做系統引起的事件的類和操做系統註冊表的類。
(2)RegistryKey類
此類表示Windows註冊表中的項級節點,此類是註冊表封裝。
語法格式爲:
public sealed class RegistryKey : MarshalByRefObject, IDisposable
注意:要獲取RegistryKey實例,須要使用Registry類的靜態成員之一。
(3)Registry類
此類提供表示Windows註冊表中的根項的RegistryKey對象,並提供訪問項/值對的static( )方法。
語法格式爲:
public static class Registry
(4)CurrentUser屬性
此屬性包含有關當前用戶首選項的信息,該字段讀取Windows 註冊表中的HKEY_ CURRENT_USER註冊表項。
語法格式爲:
public static readonly RegistryKey CurrentUser
注意:存儲在此項中的信息包括環境變量的設置和有關程序組、顏色、打印機、網絡鏈接和應用程序首選項的數據,此項使創建當前用戶的設置更容易。在此項中,軟件供應商存儲要在其應用程序中使用的當前用戶特定的首選項。
(5)OpenSubKey( )方法
此方法檢索指定的子項。
語法格式爲:
public RegistryKey OpenSubKey (string name,bool writable)
參數說明以下。
l name:要打開的子項的名稱或路徑。
l writable:若是須要項的寫訪問權限,則設置爲True。
l 返回值:請求的子項;若是操做失敗,則爲空引用。
(6)CreateSubKey( )方法
此方法建立一個新子項或打開一個現有子項以進行寫訪問。字符串subkey不區分大小寫。
語法格式爲:
public RegistryKey CreateSubKey (string subkey)
參數說明以下。
l subkey:要建立或打開的子項的名稱或路徑。
l 返回值:RegistryKey對象,表示新建的子項或空引用。若是爲subkey指定了零長度字符串,則返回當前的RegistryKey對象。
(7)GetSubKeyNames( )方法
此方法檢索包含全部子項名稱的字符串數組。
語法格式爲:
public string[] GetSubKeyNames ()
l 返回值:包含當前項的子項名稱的字符串數組。
(8)SetValue( )方法
此方法設置指定的名稱/值對。
語法格式爲:
public void SetValue (string name,Object value)
參數說明以下。
l name:要存儲的值的名稱。
l value:要存儲的數據。
注意:對註冊表操做使用RegistryKey類和Registry類時,必須引用Microsoft.Win32 命名空間。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_07,默認窗體爲Form1。
(2)在Form1窗體中,主要添加3個TextBox控件,用於輸入註冊信息;添加兩個Button控件,用來執行註冊和退出操做。
(3)主要程序代碼。
private void button1_Click(object sender, EventArgs e)
{
if(textBox1.Text=="")
{
MessageBox.Show("公司名稱不能爲空"); return;
}
if(textBox2.Text=="")
{ MessageBox.Show("用戶名稱不能爲空"); return; }
if (textBox3.Text == "")
{ MessageBox.Show("註冊碼不能爲空"); return; }
//實例RegistryKey 類對象
Microsoft.Win32.RegistryKey retkey1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("software").OpenSubKey("ZHY").OpenSubKey("ZHY.INI", true);
foreach (string strName in retkey1.GetSubKeyNames())//判斷註冊碼是否過時
{
if (strName == textBox3.Text)
{
MessageBox.Show("此註冊碼已通過期");
return;
}
}//開始註冊信息
Microsoft.Win32.RegistryKey retkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("software", true).CreateSubKey("ZHY").CreateSubKey("ZHY.INI").CreateSubKey(textBox3.Text.TrimEnd());
retkey.SetValue("UserName", textBox2.Text);
retkey.SetValue("capataz", textBox1.Text);
retkey.SetValue("Code", textBox3.Text);
MessageBox.Show("註冊成功,您可使用本軟件");
Application.Exit();
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
註冊信息加密後存入註冊表。
記錄用戶試用次數的註冊程序。
實例470 利用網卡序列號設計軟件註冊程序
實例說明
本實例實現了利用本機網卡序列號生成軟件註冊碼的功能。運行程序,自動得到本機網卡序列號,單擊【生成註冊碼】按鈕,生成軟件註冊碼,將註冊碼依次輸入下面的文本框,單擊【註冊】按鈕實現軟件註冊功能。實例運行結果如圖16.8所示。
技術要點
實現本實例功能主要用到了Microsoft.Win32命名空間下的Registry類的CurrentUser屬性、RegistryKey類的OpenSubKey( )方法、GetSubKeyNames( )方法、SetValue( )方法、CreateSubKey( )方法、System.Management命名空間下的ManagementClass類的GetInstances( )方法、ManagementObjectCollection類和ManagementObject類。Microsoft.Win32命名空間下的類和方法在第16章實例469中已經作過介紹,這裏再也不詳細說明,下面主要對System.Management命名空間及該命名空間下的類進行詳細介紹。
(1)System.Management命名空間
提供對大量管理信息和管理事件集合的訪問,這些信息和事件是與根據Windows管理規範 (WMI)結構對系統、設備和應用程序設置檢測點有關的。
(2)ManagementClass類
表示公共信息模型(CIM)管理類。管理類是一個WMI類,如Win32_LogicalDisk和Win32_Process,前者表示磁盤驅動器,後者表示進程(如Notepad.exe)。
語法格式爲:
public class ManagementClass : ManagementObject
(3)GetInstances( )方法
返回該類的全部實例的集合。
語法格式爲:
public ManagementObjectCollection GetInstances ()
l 返回值:表示該類實例的ManagementObject對象的集合。
(4)ManagementObjectCollection類
基於指定的查詢檢索管理對象的集合。此類是用於檢索管理信息的較爲經常使用的入口點之一。例如,能夠用於枚舉系統中的全部磁盤驅動器、網絡適配器、進程及更多管理對象,或者用於查詢全部處於活動狀態的網絡鏈接以及暫停的服務等。
(5)ManagementObject類
表示 WMI 實例。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_08,默認窗體爲Form1。
(2)在Form1窗體中添加4個TextBox控件、3個Button控件和6個Label控件。其中,TextBox控件用輸入註冊碼,Button控件用來執行註冊、退出和生成註冊碼操做,Label控件用於顯示計算機名稱、網卡序列號、軟件註冊碼和一些提示信息等。
(3)主要程序代碼。
得到網卡序列號和計算機名稱的實現代碼以下:
private void Form1_Load(object sender, EventArgs e)
{
label2.Text = Environment.MachineName.ToString();//獲得計算機名
label4.Text = GetNetCardMacAddress();//獲得網卡信息
}
//得到網卡信息函數
public string GetNetCardMacAddress()
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
string str = "";
foreach (ManagementObject mo in moc)
{
if ((bool)mo["IPEnabled"] == true)
str = mo["MacAddress"].ToString();
}
return str;
}
生成註冊碼的實現代碼以下:
string[] strLanCode = new string[12];// 網卡信息存儲
string[] strkey ={ "Q", "W", "7", "E", "D", "F", "2", "G", "R", "T", "Y", "8", "P", "N", "B", "V", "C", "X", "Z", "0", "9", "I", "8", "6", "U", "O", "P", "M", "5", "4", "3", "1", "A", "S", "H", "J", "K", "L" };
//生成註冊碼
public int intRand = 0;//判斷隨機生成次數
private void button1_Click(object sender, EventArgs e)
{
//把網卡信息轉換成字符串
string strCode = GetNetCardMacAddress();//調用函數獲取網卡信息
strCode = strCode.Substring(0, 2) + strCode.Substring(3, 2) + strCode.Substring(6, 2) + strCode.Substring(9, 2) + strCode.Substring(12, 2) +strCode.Substring(15, 2);
string strb = strCode.Substring(0, 4) + strCode.Substring(4, 4) + strCode.Substring(8, 4);//網卡信息存儲
for (int i = 0; i < strLanCode.Length; i++)//把網卡信息存入數組
{
strLanCode[i] = strb.Substring(i, 1);
}
Random ra = new Random();
switch (intRand)//隨機生成註冊碼的順序
{
case 0:
label5.Text = strCode.Substring(0, 4) + "-" + strCode.Substring(4, 4) + "-" + strCode.Substring(8, 4) + "-" + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString();
intRand = 1;
break;
case 1:
label5.Text = strCode.Substring(0, 4) + "-" + strCode.Substring(4, 4) + "-" + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + "-" + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString();
intRand = 2;
break;
case 2:
label5.Text = strCode.Substring(0, 4) + "-" + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + "-" + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + "-" + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString();
intRand = 3;
break;
case 3:
label5.Text = strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + "-" + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + "-" + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + strLanCode[ra.Next(0, 11)] + "-" + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString() + strkey[ra.Next(0, 37)].ToString();
intRand = 0;
break;
}
}
註冊軟件的實現代碼以下。
private void button2_Click(object sender, EventArgs e)
{
if (label5.Text == "")
{ MessageBox.Show("請生成註冊碼"); }
else
{
string strNameKey = textBox1.Text.TrimEnd() + textBox2.Text.TrimEnd() + textBox3.Text.TrimEnd() + textBox4.Text.TrimEnd();
string strNumber = label5.Text.Substring(0, 4) + label5.Text.Substring(5, 4) + label5.Text.Substring(10, 4) + label5.Text.Substring(15, 4);
if (strNameKey == strNumber)
{
Microsoft.Win32.RegistryKey retkey1 = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("software").OpenSubKey("ZHY").OpenSubKey("ZHY.INI", true);
foreach (string strName in retkey1.GetSubKeyNames())//判斷註冊碼是否過時
{
if (strName == strNameKey)
{
MessageBox.Show("此註冊碼已通過期");
return;
}
}//開始註冊信息
Microsoft.Win32.RegistryKey retkey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("software",true).CreateSubKey("ZHY").CreateSubKey("ZHY.INI").CreateSubKey(strNumber.TrimEnd());
retkey.SetValue("UserName", "明日科技");
MessageBox.Show("註冊成功!", "提示");
Application.Exit();
}
else
{ MessageBox.Show("註冊碼輸入錯誤"); }
}
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
應用組件的註冊使用。
銷售的軟件產品進行受權。
實例471 根據cpu序列號、磁盤序列號設計軟件註冊程序
實例說明
本實例根據計算機的cpu號和硬盤序列號通過簡單的計算自動生成一組無規律的註冊碼來實現應用程序的註冊。運行程序,單擊【生成機器碼】按鈕,生成24位的機器碼,單擊【生成註冊碼】按鈕,根據生成的機器碼自動轉換出24位註冊碼,將註冊碼輸入文本框中,單擊【註冊】按扭,完成軟件註冊功能。實例運行對果如圖16.9所示。
技術要點
實現本實例功能主要用到了Microsoft.Win32命名空間下的Registry類的CurrentUser屬性、RegistryKey類的OpenSubKey( )方法、GetSubKeyNames( )方法、SetValue( )方法、CreateSubKey( )方法、System.Management命名空間下的ManagementClass類的GetInstances( )方法、ManagementObjectCollection類和ManagementObject類、Char字符、Random類的Next( )方法。Microsoft.Win32和System.Management命名空間下的類和方法在第16章實例469和470中已經作過介紹,這裏再也不詳細講解。下面對本實例中用到的其餘知識進行詳細介紹。
(1)Char字符
Char類型的常數能夠寫成字符、十六進制換碼序列或Unicode表示形式,用戶也能夠顯式轉換整數字符代碼。
(2)Random類
表示僞隨機數生成器,一種可以產生知足某些隨機性統計要求的數字序列的設備。
(3)Next方法
返回一個指定範圍內的隨機數。
語法格式爲:
public virtual int Next (int minValue,int maxValue)
參數說明以下。
l minValue:返回的隨機數的下界(隨機數可取該下界值)。
l maxValue:返回的隨機數的上界(隨機數不能取該上界值)。maxValue必須大於或等於minValue。
l 返回值:一個大於或等於minValue且小於maxValue的32位帶符號整數,即返回的值範圍包括minValue但不包括maxValue。若是minValue等於maxValue,則返回minValue。
實現過程
(1)新建一個Windows應用程序,將其命名爲Ex16_08,默認窗體爲Form1。
(2)在Form1窗體中,主要添加一個TextBox控件,用來輸入註冊碼;添加4個Button控件,用來執行註冊、退出、生成註冊碼和生成機器碼操做;添加3個Label控件,用於顯示軟件註冊碼和機器碼等信息。
(3)主要程序代碼。
得到CPU序列號和硬盤序列號的實現代碼以下:
public string GetDiskVolumeSerialNumber()取得設備硬盤的卷標號
{
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObject disk = new ManagementObject("win32_logicaldisk.deviceid=\"d:\"");
disk.Get();
return disk.GetPropertyValue("VolumeSerialNumber").ToString();
}
public string getCpu()得到CPU的序列號
{
string strCpu = null;
ManagementClass myCpu = new ManagementClass("win32_Processor");
ManagementObjectCollection myCpuConnection = myCpu.GetInstances();
foreach( ManagementObject myObject in myCpuConnection)
{
strCpu = myObject.Properties["Processorid"].Value.ToString();
break;
}
return strCpu;
}
生成機器碼的實現代碼以下:
private void button1_Click(object sender, EventArgs e)
{
label2.Text = getCpu() + GetDiskVolumeSerialNumber();//得到24位CPU和硬盤序列號
string[] strid = new string[24];
for (int i = 0; i < 24; i++)//把字符賦給數組
{
strid[i] = label2.Text.Substring(i, 1);
}
label2.Text = "";
Random rdid = new Random();
for (int i = 0; i < 24; i++)//從數組隨機抽取24個字符組成新的字符生成機器碼
{
label2.Text += strid[rdid.Next(0, 24)];
}
}
生成註冊碼的實現代碼以下:
public int[] intCode = new int[127];//用於存密鑰
public void setIntCode()//給數組賦值小於10個的隨機數
{
Random ra = new Random();
for (int i = 1; i < intCode.Length;i++ )
{
intCode[i] = ra.Next(0, 9);
}
}
public int[] intNumber = new int[25];//用於存機器碼的AscII值
public char[] Charcode = new char[25];//存儲機器碼字
//生成註冊碼
private void button2_Click(object sender, EventArgs e)
{
if (label2.Text != "")
{
//把機器碼存入數組中
setIntCode();//初始化127位數組
for (int i = 1; i < Charcode.Length; i++)//把機器碼存入數組中
{
Charcode[i] = Convert.ToChar(label2.Text.Substring(i - 1, 1));
}
for (int j = 1; j < intNumber.Length; j++)//把字符的ASCII值存入一個整數組中
{
intNumber[j] = intCode[Convert.ToInt32(Charcode[j])] + Convert.ToInt32(Charcode[j]);
}
string strAsciiName = null;//用於存儲機器碼
for (int j = 1; j < intNumber.Length; j++)
{
//MessageBox.Show((Convert.ToChar(intNumber[j])).ToString());
if (intNumber[j] >= 48 && intNumber[j] <= 57)//判斷字符ASCII值是否在0~9之間
{
strAsciiName += Convert.ToChar(intNumber[j]).ToString();
}
else if (intNumber[j] >= 65 && intNumber[j] <= 90)//判斷字符ASCII值是否在A~Z之間
{
strAsciiName += Convert.ToChar(intNumber[j]).ToString();
}
else if (intNumber[j] >= 97 && intNumber[j] <= 122)//判斷字符ASCII值是否在a~z之間
{
strAsciiName += Convert.ToChar(intNumber[j]).ToString();
}
else//判斷字符ASCII值不在以上範圍內
{
if (intNumber[j] > 122)//判斷字符ASCII值是否大於z
{ strAsciiName += Convert.ToChar(intNumber[j] - 10).ToString(); }
else
{
strAsciiName += Convert.ToChar(intNumber[j] - 9).ToString();
}
}
label3.Text = strAsciiName;//獲得註冊碼
}
}
else
{ MessageBox.Show("請選生成機器碼","註冊提示"); }
}
觸類旁通
根據本實例,讀者能夠實現如下功能。
獲取CPU信息。
進行遠程軟件產品的註冊。