WindowsFormsApplicationBase
是一个在 .NET Framework 中用来简化 Windows Forms 应用程序启动过程的基类,通常用于简化应用程序的生命周期管理和其他一些功能。它属于 Microsoft.VisualBasic.ApplicationServices
命名空间,通常在使用 Visual Basic 时会较为常见,但也可以在 C# 中使用。
主要功能
-
单实例应用程序:
IsSingleInstance
属性控制应用程序是否只运行一个实例。当设置为true
时,如果启动了一个新的实例,新的实例会向已经运行的实例发送消息,而不是再次启动。 -
启动事件:
- OnStartup:在应用程序启动时执行的代码,可以在这里设置一些启动逻辑,比如加载配置文件、初始化全局资源等。
- OnCreateMainForm: 创建主窗体。你可以在这里指定应用程序的主窗体(通常是
Form
)。 -
OnStartupNextInstance:当应用程序设置为 单实例模式(即
IsSingleInstance = true
)时,如果用户启动了一个新的实例,OnStartupNextInstance
方法将被调用,而不会重新创建主窗体,而是激活已运行的实例。
-
退出事件:
- OnShutdown: 应用程序关闭时触发,你可以在这里释放资源或者保存应用程序的状态。
- OnUnhandledException: 如果应用程序遇到未处理的异常,它会触发此事件。你可以用来做异常日志记录或者显示友好的错误信息。
使用场景1、增加Splash启动动画
static class Program
{
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
// Application.EnableVisualStyles();
// Application.EnableRTLMirroring();
// Application.Run(new Form1());
string[] commandline = new string[0];
My.Application.Run(commandline);
}
static class My
{
private static MyApplication _app;
private static object _appSyncRoot = new object();
public static MyApplication Application
{
get
{
if (_app == null)
{
lock (_appSyncRoot)
{
if (_app == null)
{
_app = new MyApplication();
}
}
}
return _app;
}
}
}
class MyApplication : WindowsFormsApplicationBase
{
public MyApplication() : base(AuthenticationMode.Windows)
{
IsSingleInstance = true;
EnableVisualStyles = true;
ShutdownStyle = ShutdownMode.AfterMainFormCloses;
}
//1.OnInitialize 是应用程序启动时的第一个回调方法,它在主窗体创建之前被调用。这个方法通常用于执行一些应用程序级别的初始化操作,如加载设置、配置资源、初始化全局状态等。它在应用程序的生命周期中仅被调用一次。
protected override bool OnInitialize(ReadOnlyCollection<string> commandLineArgs)
{
Console.WriteLine("OnInitialize: 应用程序初始化");
return base.OnInitialize(commandLineArgs);
}
//2.OnCreateSplashScreen 是用于创建应用程序启动时的 启动画面(Splash Screen)的回调方法。你可以通过重写这个方法来控制在应用程序加载和初始化期间显示一个自定义的启动画面。
protected override void OnCreateSplashScreen()
{
Console.WriteLine("OnCreateSplashScreen: 初始化动画");
SplashScreen = new SplashScreen();
}
//3.在应用程序启动时执行的代码,可以在这里设置一些启动逻辑,比如加载配置文件、初始化全局资源等。
protected override bool OnStartup(StartupEventArgs eventArgs)
{
Console.WriteLine("OnStartup: 应用程序启动");
return base.OnStartup(eventArgs);
}
//4.创建主窗体。可以在这里指定应用程序的主窗体(通常是 Form)。
protected override void OnCreateMainForm()
{
Console.WriteLine("OnCreateMainForm: 创建主窗体");
MainForm = new Form1();
}
//5.当应用程序设置为 单实例模式(即 IsSingleInstance = true)时,如果用户启动了一个新的实例,OnStartupNextInstance 方法将被调用,而不会重新创建主窗体,而是激活已运行的实例。
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
base.OnStartupNextInstance(eventArgs);
}
//6.应用程序关闭时触发,可以在这里释放资源或者保存应用程序的状态
protected override void OnShutdown()
{
Console.WriteLine("OnShutdown: 应用程序关闭");
base.OnShutdown();
}
//如果应用程序遇到未处理的异常,它会触发此事件。你可以用来做异常日志记录或者显示友好的错误信息。
protected override bool OnUnhandledException(Microsoft.VisualBasic.ApplicationServices.UnhandledExceptionEventArgs e)
{
Console.WriteLine("OnUnhandledException: 发生了未处理的异常");
return base.OnUnhandledException(e);
}
}
}
//启动界面
public SplashScreen()
{
InitializeComponent();
//延时以增加Splash Screen的显示时间
System.Threading.Thread.Sleep(1000);
}
使用场景2、类似微信双击快捷方式激活窗体
修改方法OnStartupNextInstance
protected override void OnStartupNextInstance(StartupNextInstanceEventArgs eventArgs)
{
Console.WriteLine("OnStartupNextInstance: 再次进入");
if (MainForm != null)
{
if (!MainForm.Visible)
{
MainForm.Visible = true;
}
if (MainForm.WindowState != FormWindowState.Normal)
{
MainForm.WindowState = FormWindowState.Normal;
}
MainForm.Activate();
}
base.OnStartupNextInstance(eventArgs);
}
使用场景3、也可以类似wps 在同一个软件内打开不同的文档
要使用 Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e参数
StartupNextInstanceEventArgs
提供了以下信息:
CommandLine
:一个字符串数组,包含启动应用程序时传递的命令行参数。
当然还需要写入注册表,实现双击.xxx后缀时自动调用应用程序:
string extension = ".xxx";
string title = "SingleInstanceApplication";
string extensionDescription = "A Test xxx";
// Uncomment this line to create the file registration.
// In Windows Vista, you'll need to run the application
// as an administrator.
FileRegistrationHelper.SetFileAssociation(
extension, title + "." + extensionDescription);
protected override void OnStartupNextInstance(
Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs e)
{
if (e.CommandLine.Count > 0)
{
new xxx(e.CommandLine[0]);
}
}
public class FileRegistrationHelper
{
public static void SetFileAssociation(string extension, string progID)
{
// Create extension subkey
SetValue(Registry.ClassesRoot, extension, progID);
// Create progid subkey
string assemblyFullPath = System.Reflection.Assembly.GetExecutingAssembly().Location.Replace("/", @"\");
StringBuilder sbShellEntry = new StringBuilder();
sbShellEntry.AppendFormat("\"{0}\" \"%1\"", assemblyFullPath);
SetValue(Registry.ClassesRoot, progID + @"\shell\open\command", sbShellEntry.ToString());
StringBuilder sbDefaultIconEntry = new StringBuilder();
sbDefaultIconEntry.AppendFormat("\"{0}\",0", assemblyFullPath);
SetValue(Registry.ClassesRoot, progID + @"\DefaultIcon", sbDefaultIconEntry.ToString());
// Create application subkey
SetValue(Registry.ClassesRoot, @"Applications\" + Path.GetFileName(assemblyFullPath), "", "NoOpenWith");
}
private static void SetValue(RegistryKey root, string subKey, object keyValue)
{
SetValue(root, subKey, keyValue, null);
}
private static void SetValue(RegistryKey root, string subKey, object keyValue, string valueName)
{
bool hasSubKey = ((subKey != null) && (subKey.Length > 0));
RegistryKey key = root;
try
{
if (hasSubKey) key = root.CreateSubKey(subKey);
key.SetValue(valueName, keyValue);
}
finally
{
if (hasSubKey && (key != null)) key.Close();
}
}
}
}
禁止 App.xaml 自动生成 Main()
在 WPF 项目的 .csproj
文件中,找到 <PropertyGroup>
,添加以下内容:
<PropertyGroup>
<StartupObject>WpfApp.Program</StartupObject>
</PropertyGroup>
这会阻止 App.xaml
自动生成 Main()
方法,并使用 Program.Main()
作为应用入口。