做Winform开发有三年了
自己也封装了不少控件
下面把我现在每一个程序都要用的自己的封闭的公共运行库分享出来与大家交流
功能简单,确是很实用
这个库主要由三个部分组成
1.配置文件管理,主要思想是二进制的序列化,由于当时没用想到用XML,各位达人见笑。
2.窗体工厂,就是一个反射工厂,简单的封装了几个函数,由于当时对反射不了解,有几个参数弄的很可笑,大家也笑纳吧,嘿嘿
3.应用程序入口,主要实现了运行时保证程序只运行一个实例。并合并了数据连接等。。。
中间有的地方可能写的不大好,因为这个程序也用 了近两年了,我现在所有的winform程序都是以这个为基础。
有的接口不合理(比如FormFactory那几个函数)只是为了不对现有的程序做大改动
希望能与各们Winform达人交流,沟通
好了。代码奉上。
1.配置文件管理
namespace SFTech.Forms
{
[Serializable]
public class Settings
{
private static Settings _instatance;
private static object flag = new object();
#region 私有成员
private static readonly string FileName = "FormApp.BIN";
private System.Collections.Hashtable _keyTable;
#endregion
static Settings()
{
if (_instatance == null)
{
lock (flag)
{
IFormatter formatter = new BinaryFormatter();
if (!File.Exists(FileName))
{
new Settings().Save();
}
using (FileStream _file = new FileStream(FileName, FileMode.Open))
{
try
{
_instatance = (Settings)formatter.Deserialize(_file);
}
catch (InvalidCastException ex)
{
_file.Close();
File.Delete(FileName);
_instatance = new Settings();
}
_file.Close();
}
}
}
}
private Settings()
{
_keyTable = new System.Collections.Hashtable();
}
public static Settings Instatance
{
get
{
return _instatance;
}
}
public void Save()
{
IFormatter _serializer = new BinaryFormatter();
using (FileStream _file = new FileStream(FileName, FileMode.OpenOrCreate))
{
_serializer.Serialize(_file, this);
}
}
public String this[String Key]
{
get
{
if (_keyTable == null)
_keyTable = new System.Collections.Hashtable();
if (_keyTable.ContainsKey(Key) == false)
_keyTable.Add(Key, "");
return _keyTable[Key] as string;
}
set
{
_keyTable[Key] = value;
}
}
}
}
2.窗体工厂
{
public class FormFactory
{
private Form _parent;
private String _nameSpace;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="parent">MDI父窗体</param>
public FormFactory(Form parent)
{
this._parent = parent;
_nameSpace = parent.GetType().Namespace;
}
public DialogResult ShowDialog(String FormName)
{
Form form = System.Reflection.Assembly.Load(_nameSpace).CreateInstance(_nameSpace + "." + FormName) as Form;
form.StartPosition = FormStartPosition.CenterParent;
if (form != null)
return form.ShowDialog(_parent);
return DialogResult.Cancel;
}
public DialogResult ShowDialog(String AppName,String NameSpace,String FormName)
{
Form form = System.Reflection.Assembly.Load(AppName).CreateInstance(NameSpace + "." + FormName) as Form;
form.StartPosition = FormStartPosition.CenterParent;
if (form != null)
return form.ShowDialog(_parent);
return DialogResult.Cancel;
}
public Form ShowMdiChiden(string FormName)
{
return ShowMdiChiden(_nameSpace, FormName);
}
public Form ShowMdiChiden(string NameSpace,string FormName)
{
Form child = System.Reflection.Assembly.Load(NameSpace ).CreateInstance(NameSpace + "." + FormName) as Form;
child.MdiParent = this._parent;
child.Show();
child.WindowState = FormWindowState.Normal;
child.Activate();
return child;
}
public Form GetSingleForm(String FormName)
{
return GetSingleForm(_nameSpace,_nameSpace, FormName);
}
public Form GetSingleForm(string AppSetName,string NameSpace, string FormName)
{
Type formTpye = System.Reflection.Assembly.Load(AppSetName ).GetType(NameSpace + "." + FormName);
foreach (Form child in this._parent.MdiChildren)
{
if (child.GetType() == formTpye)
{
child.WindowState = FormWindowState.Normal;
child.Activate();
child.Show();
return child;
}
}
Form _child = System.Reflection.Assembly.Load(AppSetName).CreateInstance(NameSpace + "." + FormName) as Form;
_child.MdiParent = this._parent;
_child.Show();
_child.WindowState = FormWindowState.Normal;
_child.Activate();
return _child;
}
}
}
3.一个简单的数据库设置窗体
{
public partial class DBSet : System.Windows.Forms.Form
{
private SqlConnectionStringBuilder connectionString;
private string _Key;
public DBSet()
{
InitializeComponent();
}
public DBSet(String Connect)
{
InitializeComponent();
try
{
_Key = Connect;
connectionString = new SqlConnectionStringBuilder(SFTech.Forms .Settings.Instatance[Connect]);
connectionString.InitialCatalog = Connect;
}
catch
{
connectionString = new SqlConnectionStringBuilder();
}
}
private void DBSet_Load(object sender, EventArgs e)
{
//this.Text = AppConfigration.ServiceAdd;
serverTextBox.Text = connectionString.DataSource;
userTextBox.Text = connectionString.UserID;
passTextBox.Text = connectionString.Password;
checkBox1.Checked = connectionString.IntegratedSecurity;
}
private void button2_Click(object sender, EventArgs e)
{
connectionString.DataSource = serverTextBox.Text;
connectionString.InitialCatalog = _Key;
connectionString.IntegratedSecurity = checkBox1.Checked;
connectionString.ApplicationName = SFTech.Forms.App.AppName;
if (!checkBox1.Checked)
{
connectionString.UserID = userTextBox.Text;
connectionString.Password = passTextBox.Text;
}
SFTech.Forms .Settings.Instatance[_Key] = connectionString.ToString();
try
{
using (var conn = new System.Data.SqlClient.SqlConnection(connectionString.ToString()))
{
conn.Open();
conn.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(this, "无法连接到指定的数据库,请检查设置是否正确", "无法连接", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
SFTech.Forms .Settings.Instatance.Save();
this.DialogResult = DialogResult.OK;
}
public String GetConnectString()
{
this.ShowDialog();
return this.connectionString.ToString();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
this.userTextBox.Enabled = !this.checkBox1.Checked;
this.passTextBox.Enabled = !this.checkBox1.Checked;
if (this.checkBox1.Checked == true)
{
this.passTextBox.Text = null;
this.userTextBox.Text = null;
}
}
private void userTextBox_TextChanged(object sender, EventArgs e)
{
}
private void DBSet_FormClosing(object sender, FormClosingEventArgs e)
{
}
}
}
namespace SFTech.Forms
{
partial class DBSet
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要
/// 使用代码编辑器修改此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.userTextBox = new System.Windows.Forms.TextBox();
this.serverTextBox = new System.Windows.Forms.TextBox();
this.passTextBox = new System.Windows.Forms.TextBox();
this.label4 = new System.Windows.Forms.Label();
this.label3 = new System.Windows.Forms.Label();
this.label1 = new System.Windows.Forms.Label();
this.button1 = new System.Windows.Forms.Button();
this.button2 = new System.Windows.Forms.Button();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// groupBox1
//
this.groupBox1.Controls.Add(this.checkBox1);
this.groupBox1.Controls.Add(this.userTextBox);
this.groupBox1.Controls.Add(this.serverTextBox);
this.groupBox1.Controls.Add(this.passTextBox);
this.groupBox1.Controls.Add(this.label4);
this.groupBox1.Controls.Add(this.label3);
this.groupBox1.Controls.Add(this.label1);
this.groupBox1.Location = new System.Drawing.Point(13, 13);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(278, 133);
this.groupBox1.TabIndex = 0;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "数据库参数";
//
// checkBox1
//
this.checkBox1.AutoSize = true;
this.checkBox1.Location = new System.Drawing.Point(83, 50);
this.checkBox1.Name = "checkBox1";
this.checkBox1.Size = new System.Drawing.Size(138, 16);
this.checkBox1.TabIndex = 8;
this.checkBox1.Text = "使用windows帐户登录";
this.checkBox1.UseVisualStyleBackColor = true;
this.checkBox1.CheckedChanged += new System.EventHandler(this.checkBox1_CheckedChanged);
//
// userTextBox
//
this.userTextBox.Location = new System.Drawing.Point(83, 71);
this.userTextBox.Name = "userTextBox";
this.userTextBox.Size = new System.Drawing.Size(179, 21);
this.userTextBox.TabIndex = 7;
this.userTextBox.TextChanged += new System.EventHandler(this.userTextBox_TextChanged);
//
// serverTextBox
//
this.serverTextBox.Location = new System.Drawing.Point(83, 26);
this.serverTextBox.Name = "serverTextBox";
this.serverTextBox.Size = new System.Drawing.Size(179, 21);
this.serverTextBox.TabIndex = 5;
//
// passTextBox
//
this.passTextBox.Location = new System.Drawing.Point(83, 95);
this.passTextBox.Name = "passTextBox";
this.passTextBox.PasswordChar = '*';
this.passTextBox.Size = new System.Drawing.Size(179, 21);
this.passTextBox.TabIndex = 4;
//
// label4
//
this.label4.AutoSize = true;
this.label4.Location = new System.Drawing.Point(6, 102);
this.label4.Name = "label4";
this.label4.Size = new System.Drawing.Size(35, 12);
this.label4.TabIndex = 3;
this.label4.Text = "密码:";
//
// label3
//
this.label3.AutoSize = true;
this.label3.Location = new System.Drawing.Point(6, 78);
this.label3.Name = "label3";
this.label3.Size = new System.Drawing.Size(71, 12);
this.label3.TabIndex = 2;
this.label3.Text = "登录用户名:";
//
// label1
//
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(6, 29);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(71, 12);
this.label1.TabIndex = 0;
this.label1.Text = "服务器地址:";
//
// button1
//
this.button1.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.button1.Location = new System.Drawing.Point(216, 151);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "取消";
this.button1.UseVisualStyleBackColor = true;
//
// button2
//
this.button2.Location = new System.Drawing.Point(135, 151);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 2;
this.button2.Text = "确定";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// DBSet
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(306, 187);
this.Controls.Add(this.button2);
this.Controls.Add(this.button1);
this.Controls.Add(this.groupBox1);
this.Name = "DBSet";
this.ShowIcon = false;
this.Text = "数据库设置";
this.Load += new System.EventHandler(this.DBSet_Load);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.DBSet_FormClosing);
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TextBox passTextBox;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox userTextBox;
private System.Windows.Forms.TextBox serverTextBox;
private System.Windows.Forms.CheckBox checkBox1;
}
}
4.核心类 APP 应用程序入口
{
/// <summary>
/// 应用程序统一入口
/// </summary>
public class App
{
/// <summary>
/// 程序运行名称
/// </summary>
public static string AppName
{
get
{
string appName = null;
object[] attributes = Assembly.GetEntryAssembly ().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (attributes.Length > 0)
{
AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
if (titleAttribute.Title != "")
{
appName = titleAttribute.Title;
}
}
if (appName == null)
appName = System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
var i = Assembly.GetEntryAssembly ().GetName();
return appName + " " + i.Version;
}
}
/// <summary>
/// 当前程序运行的主窗口
/// </summary>
public static System.Windows.Forms.Form AppMainForm
{
get;
private set;
}
/// <summary>
/// 连接的数据库名称
/// </summary>
private static string DbKey
{
get;
set;
}
/// <summary>
/// 窗体工厂
/// </summary>
public static FormFactory FormFactory
{
get;
private set;
}
/// <summary>
/// 运行程序
/// </summary>
/// <param name="type">主窗体类型</param>
/// <param name="DataBaseName">数据库名称</param>
public static void RunApp(System.Type type, string DataBaseName )
{
Process instance = RunningInstance();
if (instance == null)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
System.Windows.Forms.Form MainForm = type.Assembly.CreateInstance(type.FullName) as System.Windows.Forms.Form;// type.InvokeMember(type.Name, System.Reflection.BindingFlags.Default,new System.Reflection.Binder(), null, null) as System.Windows.Forms.Form;
App.AppMainForm = MainForm;
DbKey = DataBaseName;
FormFactory = new FormFactory(MainForm);
Application.Run(MainForm);
}
else
{
//已经有一个实例在运行
HandleRunningInstance(instance);
}
}
/// <summary>
/// 数据库连接字符串
/// </summary>
public static string ConnectionString
{
get
{
if (IsReadyConnected() == false)
{
var r = new SFTech.Forms.DBSet(DbKey);
r.StartPosition = FormStartPosition.CenterScreen;
if (AppMainForm.Visible == true)
r.ShowDialog(AppMainForm);
else
{
r.ShowDialog();
}
}
return SFTech.Forms.Settings.Instatance[DbKey];
}
}
/// <summary>
/// 设置数据库连接
/// </summary>
public static void SetDb()
{
new SFTech.Forms.DBSet(DbKey).ShowDialog(AppMainForm);
}
private static string _ConnectString { get; set; }
private static bool? Connected = null;
private static bool IsReadyConnected()
{
if (Connected != true)
{
if (SFTech.Forms.Settings.Instatance[DbKey] == "")
{
Connected = false;
return false;
}
else
{
try
{
System.Data.SqlClient.SqlConnectionStringBuilder bulder = new SqlConnectionStringBuilder(SFTech.Forms.Settings.Instatance[DbKey]);
bulder.ApplicationName = "Soway 连接测试";
using (var conn = new System.Data.SqlClient.SqlConnection(bulder.ToString()))
{
conn.Open();
conn.Close();
}
bulder.ApplicationName = AppName;
SFTech.Forms.Settings.Instatance[DbKey] = bulder.ToString();
SFTech.Forms.Settings.Instatance.Save();
Connected = true;
return true;
}
catch(Exception ex)
{
SFTech.Debug.DebugConsole.WriteLine(ex.ToString());
Connected = false;
return false;
}
}
}
return true;
}
#region 确保只有一个实例
public static Process RunningInstance()
{
Process current = Process.GetCurrentProcess();
Process[] processes = Process.GetProcessesByName(current.ProcessName);
foreach (Process process in processes)
{
if (process.Id != current.Id)
{
if (Assembly.GetEntryAssembly().Location.Replace("/", "\\") == current.MainModule.FileName)
{
return process;
}
}
}
return null;
}
private static void HandleRunningInstance(Process instance)
{
ShowWindowAsync(instance.MainWindowHandle, 1); //调用api函数,正常显示窗口
SetForegroundWindow(instance.MainWindowHandle); //将窗口放置最前端。
}
[DllImport("User32.dll")]
private static extern bool ShowWindowAsync(System.IntPtr hWnd, int cmdShow);
[DllImport("User32.dll")]
private static extern bool SetForegroundWindow(System.IntPtr hWnd);
#endregion
}
}
在程序中使用的话,Program就变成这样:
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
SFTech.Forms.App.RunApp(typeof(MainForm), "ALRFID");
}
}
打开一个窗体,只需要 :
SFTech.Forms.App.FormFactory.GetSingleForm("程序集名称", "命名空间", "窗体类型名称");
要使用数据库连接串,只要:
SFTech.Forms.App.ConnectionString
而且中间的操作,类似于连接是否可用,是否保存了字符串,都会自动处理,如果连接不可用或没有设置连接参数,会自动弹出设置窗体。
文章是早上发的,很多人看了有点晕,不知道弄这个是为什么
下面说明一下
APP类的一个核心作用,是保证程序只运行一个实例。
因为很多winform的软件,都有类似的要求。
设置部分不用多说了
下面说一下为什么要用窗体工厂。
窗体工厂,乍一想是没有什么作用的,因为我完全可以New 一个新窗体出来
但是如果在配合用户管理的模式下,那么窗体工厂是要配合用户管理使用的。下面贴一小段代码,大家感受一下。
Demo我就不上传了
整个工程很简单,加入引用以后,一个主窗体MainForm,四个随便增加 的窗体Form1到Form4
MainForm只更改一个属性,就是IsMdiContainer=True
Program.cs主函数 改为
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
SFTech.Forms.App.RunApp(typeof(MainForm), "aa");
}
}
MainForm只加一个Load事件
如下
一些说明我已经加在注释里了
{
public MainForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
MenuStrip Main = new MenuStrip();
//窗体名称,在这里,直接用一个简单的字符串数组代替
//但是如果你有一个好的用户管理结构,这部分应该是在用户登录以后动态的生成一个树形结构
String[] forms = new String[]{
"Form1","Form2","Form3","Form4"};
//根据信息,动态生成菜单
for (int i = 0; i <forms.Length ; i++)
{
ToolStripItem strip = new ToolStripMenuItem();
strip.Text = "Open"+forms[i];//这里一切从简,只求似了
strip.Tag = forms[i];//我这里的Tag只保存了一个字符串,但是要注意,在实际应用中,Tag是可以保存你的自定义数据的。
strip.Click += new EventHandler(strip_Click);
Main.Items.Add(strip);
}
this.Controls.Add(Main);
this.MainMenuStrip = Main;
}
//菜单打开的处理函数,四个菜单项,只用一个
//工程复杂了,哪怕是四十个,四百个,也只用这一个处理函数
void strip_Click(object sender, EventArgs e)
{
//窗体工厂,就这么使用。。。
SFTech.Forms.App.FormFactory.GetSingleForm((sender as ToolStripItem).Tag.ToString());
}
}