.NET Windows Form开发心得
第一次用VS.NET 2003做Windows Form 开发, 总结一下
1. 把所有的资源放在一个或多个DLL里, 就象游戏软件把所有的图片做一个资源包, 所有的音效做一个资源包的做法类似, 好处是可以减少主程序的大小, 另外把业务代码根据需要放在一个或多个DLL里, 最终是能够提升软件自动升级的效率, 避免无意义的下载流量, 当然, 为了避免出现DLL Hell, 最好是把所有的DLL加上Strong Name
2. 把应用程序的主入口点的代码放到一个新单元的启动类里, 好处是与主窗体的代码分开, 流程更加清晰
3. 用执行文件的版本号作为系统的版本号,避免出现多个定义的地方
4.有时需要统一设置窗体上控件的属性,作界面上的运行期绑定,下面提供一个返回所有控件的函数
5.消息机制,写Windows程序,很有可能需要自定义消息加以处理
6. 调用Jet Engine压缩Access数据库
7. 程序中嵌入WebBrowser, .NET封装的AxWebBrowser的功能实在是够弱的,下面2篇文章基本上包括了设置WebBrowser的方方面面
http://icebird.cnblogs.com/articles/403056.html
http://icebird.cnblogs.com/articles/403031.html
by the way, CodeRush for VS.NET 和 Refactor! Pro for VS.NET真的很好用,不愧是DevExpress出品
1. 把所有的资源放在一个或多个DLL里, 就象游戏软件把所有的图片做一个资源包, 所有的音效做一个资源包的做法类似, 好处是可以减少主程序的大小, 另外把业务代码根据需要放在一个或多个DLL里, 最终是能够提升软件自动升级的效率, 避免无意义的下载流量, 当然, 为了避免出现DLL Hell, 最好是把所有的DLL加上Strong Name
/// <summary>
/// 从资源DLL中取得需要的资源
/// </summary>
public static Stream GetResource(string fileName)
{
Stream stream = null;
Type resourceType = typeof(ResourceManager); //ResourceManager是资源DLL中定义的一个DummyClass
string resourceName = resourceType.Namespace + "." + fileName.Replace("\\", ".");
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(resourceType);
if (assembly == null)
throw new Exception("无法装载资源文件: " + resourceType.Namespace + ".dll");
stream = System.Reflection.Assembly.GetAssembly(resourceType).GetManifestResourceStream(resourceName);
if (stream == null)
throw new Exception("无法取得资源: " + fileName);
return stream;
}
/// 从资源DLL中取得需要的资源
/// </summary>
public static Stream GetResource(string fileName)
{
Stream stream = null;
Type resourceType = typeof(ResourceManager); //ResourceManager是资源DLL中定义的一个DummyClass
string resourceName = resourceType.Namespace + "." + fileName.Replace("\\", ".");
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetAssembly(resourceType);
if (assembly == null)
throw new Exception("无法装载资源文件: " + resourceType.Namespace + ".dll");
stream = System.Reflection.Assembly.GetAssembly(resourceType).GetManifestResourceStream(resourceName);
if (stream == null)
throw new Exception("无法取得资源: " + fileName);
return stream;
}
2. 把应用程序的主入口点的代码放到一个新单元的启动类里, 好处是与主窗体的代码分开, 流程更加清晰
3. 用执行文件的版本号作为系统的版本号,避免出现多个定义的地方
Assembly assembly = Assembly.GetExecutingAssembly();
object[] assemblyTitleAttributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (assemblyTitleAttributes.Length > 0)
title = (assemblyTitleAttributes[0] as AssemblyTitleAttribute).Title;
version = assembly.GetName().Version.ToString();
object[] assemblyTitleAttributes = assembly.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
if (assemblyTitleAttributes.Length > 0)
title = (assemblyTitleAttributes[0] as AssemblyTitleAttribute).Title;
version = assembly.GetName().Version.ToString();
4.有时需要统一设置窗体上控件的属性,作界面上的运行期绑定,下面提供一个返回所有控件的函数
/// <summary>
/// 取得指定容器上的全部子控件
/// </summary>
public static Control[] GetAllControls(Control ctrl)
{
ArrayList allControls = new ArrayList();
Queue queue = new Queue();
queue.Enqueue(ctrl.Controls);
while( queue.Count > 0 )
{
Control.ControlCollection
controls = (Control.ControlCollection)queue.Dequeue();
if( controls == null || controls.Count == 0 )
continue;
foreach( Control control in controls )
{
allControls.Add(control);
queue.Enqueue(control.Controls);
}
}
return (Control[])allControls.ToArray(typeof(Control));
}
/// 取得指定容器上的全部子控件
/// </summary>
public static Control[] GetAllControls(Control ctrl)
{
ArrayList allControls = new ArrayList();
Queue queue = new Queue();
queue.Enqueue(ctrl.Controls);
while( queue.Count > 0 )
{
Control.ControlCollection
controls = (Control.ControlCollection)queue.Dequeue();
if( controls == null || controls.Count == 0 )
continue;
foreach( Control control in controls )
{
allControls.Add(control);
queue.Enqueue(control.Controls);
}
}
return (Control[])allControls.ToArray(typeof(Control));
}
5.消息机制,写Windows程序,很有可能需要自定义消息加以处理
protected override void DefWndProc(ref System.Windows.Forms.Message m)
{
switch(m.Msg)
{
case CM_MYMESSAGE:
//Do My Business
break;
default:
base.DefWndProc(ref m);
break;
}
}
{
switch(m.Msg)
{
case CM_MYMESSAGE:
//Do My Business
break;
default:
base.DefWndProc(ref m);
break;
}
}
private const int CM_CUSTOMMESSAGE = 0x1600;
/// <summary>
/// 自定义消息
/// </summary>
public const int CM_MYMESSAGE = CM_CUSTOMMESSAGE + 1;
[DllImport("User32.dll",EntryPoint="SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("User32.dll",EntryPoint="PostMessage")]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
/// <summary>
/// 自定义消息
/// </summary>
public const int CM_MYMESSAGE = CM_CUSTOMMESSAGE + 1;
[DllImport("User32.dll",EntryPoint="SendMessage")]
public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("User32.dll",EntryPoint="PostMessage")]
public static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
6. 调用Jet Engine压缩Access数据库
/// <summary>
/// 压缩数据库
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="newFileName">文件名</param>
public static bool CompactDatabase(string fileName, string newFileName)
{
bool result = false;
//如果要压缩的数据库打开的话,先关闭之
string TempFile;
if (newFileName == String.Empty)
TempFile = Path.GetTempFileName();
else
TempFile = newFileName;
try
{
object[] oParams;
object objJRO = Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine"));
oParams = new object[] {TConnection.ConnectionString(fileName), "Provider=Microsoft.Jet.OLEDB.4.0;Data" + " Source=" + TempFile + ";Jet OLEDB:Engine Type=5"};
objJRO.GetType().InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod, null, objJRO, oParams);
if (newFileName == String.Empty)
{
File.Delete(fileName);
File.Move(TempFile, fileName);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(objJRO);
objJRO = null;
result = true;
}
finally
{
//如果有必要的话,恢复数据库连接
}
return result;
}
/// 压缩数据库
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="newFileName">文件名</param>
public static bool CompactDatabase(string fileName, string newFileName)
{
bool result = false;
//如果要压缩的数据库打开的话,先关闭之
string TempFile;
if (newFileName == String.Empty)
TempFile = Path.GetTempFileName();
else
TempFile = newFileName;
try
{
object[] oParams;
object objJRO = Activator.CreateInstance(Type.GetTypeFromProgID("JRO.JetEngine"));
oParams = new object[] {TConnection.ConnectionString(fileName), "Provider=Microsoft.Jet.OLEDB.4.0;Data" + " Source=" + TempFile + ";Jet OLEDB:Engine Type=5"};
objJRO.GetType().InvokeMember("CompactDatabase", System.Reflection.BindingFlags.InvokeMethod, null, objJRO, oParams);
if (newFileName == String.Empty)
{
File.Delete(fileName);
File.Move(TempFile, fileName);
}
System.Runtime.InteropServices.Marshal.ReleaseComObject(objJRO);
objJRO = null;
result = true;
}
finally
{
//如果有必要的话,恢复数据库连接
}
return result;
}
7. 程序中嵌入WebBrowser, .NET封装的AxWebBrowser的功能实在是够弱的,下面2篇文章基本上包括了设置WebBrowser的方方面面
http://icebird.cnblogs.com/articles/403056.html
http://icebird.cnblogs.com/articles/403031.html
by the way, CodeRush for VS.NET 和 Refactor! Pro for VS.NET真的很好用,不愧是DevExpress出品