• 2018-8-10-wpf-单例


    title author date CreateTime categories
    wpf 单例
    lindexi
    2018-08-10 19:16:53 +0800
    2018-2-13 17:23:3 +0800
    WPF

    本文告诉大家如何做一个 wpf 单例程序。单例就是用户只能运行这个程序一次,也就是内存只有存在这个程序一个。

    首先创建项目,右击 App.xaml.cs 选择编译为 Page ,原来是 ApplicationDefinition

    打开 App.xaml 删除StartupUri="MainWindow.xaml",不然下面的代码会启动两个窗口

    然后创建 Main ,请添加下面代码

        public partial class App : Application
        {
            App()
            {
                InitializeComponent();
            }
    
            [STAThread]
            static void Main()
            {
                App app = new App();
                MainWindow window = new MainWindow();
                app.Run(window);
            }
        }

    然后就在 Main 写逻辑,这里判断是否有全局锁,如果有就不启动。添加锁的代码很简单。

    static Mutex mutex = new Mutex(true, "lindexi");

    如果程序没有启动,那么通过下面的代码判断现在只有他一个软件

    if (_mutex.WaitOne(TimeSpan.Zero, true))

    现在的主函数就是判断可以启动就创建窗口

            static void Main()
            {
                App app = new App();
                if (_mutex.WaitOne(TimeSpan.Zero, true))
                {
                    //如果申请成功
                    MainWindow window = new MainWindow();
                    app.Run(window);
                }
            }

    但是如果不能启动,就需要启动原来启动的程序。这里使用一个特殊方法,先创建一个类,可以发送消息给原先的程序。需要知道,在windows上,程序和系统通信都是使用消息,通过模拟消息就可以让其他程序做出特殊的效果,如让他放在窗口最前。

    如果需要发送消息,那么需要使用下面的方法。下面代码注册了一个自己的消息,这样在自己的程序可以判断WM_SHOWME来把自己给用户。

        internal class NativeMethods
        {
            public const int HWND_BROADCAST = 0xffff;
            public static readonly int WM_SHOWME = RegisterWindowMessage("WM_SHOWME");
            [DllImport("user32")]
            public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
            [DllImport("user32")]
            public static extern int RegisterWindowMessage(string message);
        }

    接着修改主函数,在已经启动一个程序,就让他打开。这个方法就是发送一个特殊的消息,只有自己的程序知道这个消息是显示。

            static void Main()
            {
                App app = new App();
                if (_mutex.WaitOne(TimeSpan.Zero, true))
                {
                    //如果申请成功
                    MainWindow window = new MainWindow();
                    app.Run(window);
                    _mutex.ReleaseMutex();
                }
                else
                {
                    NativeMethods.PostMessage(
                        (IntPtr) NativeMethods.HWND_BROADCAST,
                        NativeMethods.WM_SHOWME,
                        IntPtr.Zero,
                        IntPtr.Zero);
                }
            }

    然后发送消息需要让程序自己监听,于是打开 MainWindow.xaml.cs 添加下面的代码,如果监听消息是让自己显示,那么就打开自己。

            protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
                HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
                source.AddHook(WndProc);
            }
    
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
            {
                if (msg == NativeMethods.WM_SHOWME)
                {
                    Activate();
                }
                return IntPtr.Zero;
            }

    这样就可以运行一个程序,再次打开也会打开原来的程序。

    但是程序有一个坑,如果是多用户,那么打开只能是一个程序,请看下面的代码。

            private static Mutex _mutex = new Mutex(true, "lindexi" + Environment.UserName);
    

    实际文章就想说如何在多用户系统使用单例。

    参见:Writing a custom Main() method for WPF applications — The Stochastic Game

    C# .NET Single Instance Application - Sanity Free Coding - C#, .NET, PHP

    代码:wpf 单例 PfalmcYmgtx-CSDN下载

  • 相关阅读:
    true和false
    计算几何算法概览
    pixi.js 总结
    typescript 不用import?
    nodejs 新特性
    p2 碰撞
    Java学习笔记(十四)——Java静态工厂
    Java学习笔记(十三一)——Xml 常用知识总结
    读书笔记(二) ——《恶意》你善良吗?
    Spring学习(二)——Spring中的AOP的初步理解
  • 原文地址:https://www.cnblogs.com/lindexi/p/12085638.html
Copyright © 2020-2023  润新知