主要介紹如何動態創建窗體,在窗體關閉前加入提示信息以及任意控制窗體移動等相關技術,這些都是在實際開發中被廣泛應用的技術。
044 在關閉窗口前加入確認對話框
窗口正要關閉但是沒有關閉之前會觸發 FormClosing 事件,該事件中的參數 FormClosing EventArgs e 中包含 Cancel 屬性,如果設置該屬性為 True,窗口將不會被關閉。因此在該事件處理代碼中可以提示用戶是否關閉程序,如果用戶不想關閉程序,則設置該參數為 True。利用 MessageBox 參數的返回值可以知道用戶所選中的按鈕。
創建一個項目,默認窗體為 Form1。
namespace _044_QueryClose { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (MessageBox.Show("將要關閉窗體,是否繼續?","詢問",MessageBoxButtons.YesNo) == DialogResult.Yes) { e.Cancel = false; //不取消事件的值 } else { e.Cancel = true; //取消事件的值 } } } }
045 通過子窗體刷新父窗體
本實例在子窗體刷新父窗體時,主要應用事件來對主窗體進行刷新。當子窗體產生相對應的更新操作時,通過子窗體的一個方法,觸發主窗體中對應的處理事件。
1.創建一個項目,修改默認窗體為 ChildRefurbishParent;添加一個 Windows 窗體,將其命名為 ChildWindow。
2.在 ChildRefurbishParent 窗體上添加一個 DataGridView 控件和一個 MenuStrip 控件。設置 ChildRefurbishParent 窗體的 MainMenuStrip 屬性為 menuStrip1、WindowState 屬性為 Maximized 以及 IsMdiContainer 屬性為 True。在 ChildWindow 窗體中添加兩個 GroupBox 控件、5個 Label 控件、4個 TextBox 控件、一個 ComboBox 控件以及3個 Button 控件。
:在做與數據庫有關的操作時,需要引用命名空間 System.Data.SqlClient。
//ChildRefurbishParent窗體代碼 namespace _045_ChildRefurbishParent { public partial class ChildRefurbishParent : Form { public ChildRefurbishParent() { InitializeComponent(); } /// <summary> /// 本實例應該設置主窗體的IsMdiContainer屬性為true、MainMenuStrip屬性為所添加的菜單欄、WindowState屬性為Maximized、窗體名稱為ChildRefurbishParent、設置AllowUserToAddRows屬性為false /// </summary> #region 聲明的變量 public static bool flag = false;//標識是否創建新的子窗體 ChildWindow BabyWindow = new ChildWindow();//實例化一個子窗體 DataSet PubsSet = new DataSet(); //定義一個數據集對象 public static string[] IDArray; //聲明一個一維字符串數組 public DataTable IDTable; //聲明一個數據表對象 SqlDataAdapter IDAdapter; //聲明一個數據讀取器對象 SqlDataAdapter PubsAdapter; //聲明一個數據讀取器對象 SqlConnection ConnPubs; //聲明一個數據庫連接對象 SqlCommand PersonalInformation; //聲明一個執行SQL語句的對象 #endregion //在ChildRefurbishParent窗體的加載過程中,需要顯示數據庫中的數據 private void ChildRefurbishParent_Load(object sender, EventArgs e) { //string ConnString = "Data Source=.;DataBase=db_01;integrated security=sspi";//本地數據庫連接字符串 string ConnString = "server=55.66.77.88;user id=sa;pwd=123456;DataBase=db_01";//遠程數據庫連接字符串 string AdapterString = "select userId as 編號,userName as 姓名 ,phone as 電話,address as 住址 from tb_01";//用於查詢的字符串 string IDString = "select userID from tb_01";//讀取數據庫中用戶的ID編號字符串 ConnPubs = new SqlConnection(ConnString);//建立數據庫連接 PubsAdapter = new SqlDataAdapter(AdapterString, ConnPubs);//創建PubsAdapter數據讀取器 IDAdapter = new SqlDataAdapter(IDString, ConnPubs);//用於讀取用戶編號的讀取器 PubsAdapter.Fill(PubsSet, "Authors");//填充PubsSet數據集 IDAdapter.Fill(PubsSet, "ID");//填充PubsSet數據集 DataTable PubsTable = PubsSet.Tables["Authors"];//將數據寫入PubsTable表 IDTable = PubsSet.Tables["ID"];//將數據寫入ID表 IDArray = new string[IDTable.Rows.Count];//為數組定義最大長度 dataGridView1.DataSource = PubsTable.DefaultView;//設置dataGridView1的數據源 for (int i = 0; i < IDTable.Rows.Count; i++) //循環遍歷數據表中的每一行數據 { for (int j = 0; j < IDTable.Columns.Count; j++)//循環遍歷數據表中的每一列數據 { IDArray[i] = IDTable.Rows[i][j].ToString(); //將數據表中的數據添加至一個一維數組 } } } #region 單擊菜單“操作類型”中的“添加與刪除”選項,顯示出子窗體 private void AddandDelete_Click(object sender, EventArgs e) { if (flag == false)//判斷標識的值決定是否創建窗體 { CreateChildWindow();//創建子窗體 } for (int i = 0; i < this.dataGridView1.Controls.Count; i++)//循環遍歷DataGridView控件上的控件集 { if (this.dataGridView1.Controls[i].Name.Equals(BabyWindow.Name))//當存在子窗體時 { flag = true;//改變標識Flag的值 break;//退出循環體 } } } #endregion private void ExitProject_Click(object sender, EventArgs e) { Application.Exit();//退出本程序 } #region 創建子窗體的CreateChildWindow方法 public void CreateChildWindow() { ChildWindow BabyWindow = new ChildWindow();//實例化一個子窗體 BabyWindow.MdiParent = this;//設置子窗體的父窗體為當前窗體 this.dataGridView1.Controls.Add(BabyWindow);//在DataGridView控件中添加子窗體 BabyWindow.UpdateDataGridView += new EventHandler(BabyWindow_UpdateDataGridView); BabyWindow.Show();//顯示子窗體 } //子窗體通過事件BabyWindow_UpdateDataGridView來實現對主窗體數據的更新 void BabyWindow_UpdateDataGridView(object sender, EventArgs e) { if (ChildWindow.GlobalFlag == false) //當單擊刪除按鈕時 { if (ConnPubs.State == ConnectionState.Closed) //當數據庫處於斷開狀態時 { ConnPubs.Open(); //打開數據庫的連接 } string AfreshString = "delete tb_01 where userID=" + ChildWindow.DeleteID.Trim();//定義一個刪除數據的字符串 PersonalInformation = new SqlCommand(AfreshString, ConnPubs); //執行刪除數據庫字段 PersonalInformation.ExecuteNonQuery(); //執行SQL語句並返回受影響的行數 ConnPubs.Close(); //關閉數據庫 DisplayData(); //顯示數據庫更新後的內容 MessageBox.Show("數據刪除成功!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);//彈出刪除數據成功的提示 } else { if (ConnPubs.State == ConnectionState.Closed) //當數據庫處於關閉狀態時 { ConnPubs.Open(); //打開數據庫 } string InsertString = "insert into tb_01 values('" + ChildWindow.idContent + "','" + ChildWindow.nameContent + "','" + ChildWindow.phoneContent + "','" + ChildWindow.addressContent + "')";//定義一個插入數據的字符串變量 PersonalInformation = new SqlCommand(InsertString, ConnPubs);//執行插入數據庫字段 PersonalInformation.ExecuteNonQuery();//執行SQL語句並返回受影響的行數 ConnPubs.Close(); //關閉數據庫 DisplayData(); //顯示更新後的數據 MessageBox.Show("數據添加成功!", "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);//彈出添加成功的提示信息 } } #endregion #region 在更改主窗體中的數據時,需要隨時顯示數據庫中的數據 public void DisplayData() { PubsSet.Clear(); //string ConnString = "Data Source=.;DataBase=db_01;integrated security=sspi";//本地數據庫連接字符串 string ConnString = "server=55.66.77.88;user id=sa;pwd=123456;DataBase=db_01";//遠程數據庫連接字符串 ConnPubs = new SqlConnection(ConnString);//建立數據庫連接 string DisplayString = "select userId as 編號,userName as 姓名 ,phone as 電話,address as 住址 from tb_01";//定義讀取數據庫的字段 SqlDataAdapter PersonalAdapter = new SqlDataAdapter(DisplayString, ConnPubs); //定義一個讀取數據庫數據的讀取器 PersonalAdapter.Fill(PubsSet, "DisplayTable"); //向表DisplayTable中填充數據 dataGridView1.DataSource = PubsSet.Tables["DisplayTable"].DefaultView;//設定DataGridView控件的數據源 } #endregion } }
//ChildWindow窗體代碼 namespace _045_ChildRefurbishParent { public partial class ChildWindow : Form { public ChildWindow() { InitializeComponent(); } ///<summary> /// 本實例僅可創建一個窗口,因此在這裡屏蔽關閉按鈕;最大化後沒有實際意義,因此關閉MaximizeBox屬性值為False ///</summary> #region 變量的聲明 public event EventHandler UpdateDataGridView = null;//定義一個處理更新DataGridView控件內容的方法 public static string DeleteID; //定義一個表示刪除數據編號的字符串 public static string idContent; //該變量用來存儲數據編號 public static string nameContent;//該變量用來存儲姓名 public static string phoneContent;//該變量用來存儲電話 public static string addressContent;//該變量用來存儲住址 public static bool GlobalFlag; //該變量用來標識是否創建新的子窗體 #endregion //UpdateData方法用來觸發主窗體中的處理事件 protected void UpdateData() { if (UpdateDataGridView != null)//當觸發更新DataGridView事件時 { UpdateDataGridView(this, EventArgs.Empty);//更新DataGridView控件中的內容 } } //在窗體的關閉事件中標識此窗體已處於關閉狀態 private void ChildWindow_FormClosing(object sender, FormClosingEventArgs e) { ChildRefurbishParent.flag = false; //設定該值為false表示可以創建新窗體 } //當窗體加載時,在ComboBox控件中加載數據庫中的數據編號 private void ChildWindow_Load(object sender, EventArgs e) { for (int i = 0; i < ChildRefurbishParent.IDArray.Length; i++) //循環遍歷數組中的每一個元素 { comboBox1.Items.Add(ChildRefurbishParent.IDArray[i].ToString());//向Combobox控件中添加內容 comboBox1.SelectedIndex = 0;//設定當前選中項的索引為0 } } //在ComboBox控件中選定將要刪除的記錄,單擊“刪除”按鈕刪除數據 private void deleteButton_Click(object sender, EventArgs e) { GlobalFlag = false; //設定全局變量表示為false if (comboBox1.Items.Count > 1)//當ComboBox中剩不小於2條內容時 { DeleteID = comboBox1.SelectedItem.ToString();//將選中項轉化為int型 if (comboBox1.Items.Count != 0)//當ComboBox中剩1條內容時 { comboBox1.Items.Remove(comboBox1.SelectedItem); comboBox1.SelectedIndex = 0; } } UpdateData();//更新Combobox控件中的內容 } //當在文本框中輸入的錯誤信息過多時,單擊“取消”按鈕即可清空輸入的所有內容 private void cancelButton_Click(object sender, EventArgs e) { id.Clear(); //清空編號文本框中的內容 name.Clear();//清空姓名文本框中的內容 phone.Clear();//清空電話號碼文本框中的內容 address.Clear();//清空居住地址文本框中的內容 id.Focus();//設定當前鼠標的焦點在編號文本框中 } //當在文本框中輸入添加的信息後,單擊“提交”按鈕數據即可更新到主窗體重 private void submitButton_Click(object sender, EventArgs e) { GlobalFlag = true; //設定標識的值為true if (!(comboBox1.Items.Equals(idContent)))//當Combobox控件中不存在將添加的信息時 { comboBox1.Items.Add(idContent);//在Combobox控件中添加一條記錄 } UpdateData(); } //當窗體中文本框的內容發生改變時,應該保存對應文本框的值,這樣方便數據庫的更新 private void id_TextChanged(object sender, EventArgs e) { idContent = id.Text; //保存新添加記錄的編號 } private void name_TextChanged(object sender, EventArgs e) { nameContent = name.Text;//保存填入的姓名 } private void phone_TextChanged(object sender, EventArgs e) { phoneContent = phone.Text;//保存填入的電話號碼 } private void address_TextChanged(object sender, EventArgs e) { addressContent = address.Text;//保存填入的地址信息 } } }
046 拖動無邊框窗體
本實例主要用到 Windows 的兩個 API 函數,即 ReleaseCapture 和 SendMessage。
:當調用 Windows 的 API 函數時,需要引用命名空間 System.Runtime.InteropServices。
創建一個項目,默認窗體為 Form1,在 Form1 窗體上添加一個 ContextMenuStrip 控件。設置 Form1 窗體的 ContextMenuStrip 屬性為 contextMenuStrip1。
namespace _046_DragNoFrameWindow { public partial class Form1 : Form { public Form1() { InitializeComponent(); } /// <summary> /// 本實例需設置窗體的FormBorderStyle屬性為None、設置ContextMenuStrip屬性為當前添加的實例 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> #region 本程序中用到的API函數 [DllImport("user32.dll")] public static extern bool ReleaseCapture(); //用來釋放被當前線程中某個窗口捕獲的光標 [DllImport("user32.dll")] public static extern bool SendMessage(IntPtr hwdn, int wMsg, int mParam, int lParam);//向指定的窗體發送Windows消息 #endregion #region 本程序中需要聲明的變量 public const int WM_SYSCOMMAND = 0x0112; //該變量表示將向Windows發送的消息類型 public const int SC_MOVE = 0xF010; //該變量表示發送消息的附加消息 public const int HTCAPTION = 0x0002; //該變量表示發送消息的附加消息 #endregion private void ExitContext_Click(object sender, EventArgs e) { Application.Exit(); //退出本程序 } private void Form1_MouseDown(object sender, MouseEventArgs e) { ReleaseCapture(); //用來釋放被當前線程中某個窗口捕獲的光標 SendMessage(this.Handle, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0); //向Windows發送拖動窗體的消息 } } }