コード例 #1
0
ファイル: UnsafeNative.cs プロジェクト: lulzzz/Cauldron
        /// <summary>
        /// Sends the specified message string to a window. The SendMessage function calls the window
        /// procedure for the specified window and does not return until the window procedure has
        /// processed the message.
        /// </summary>
        /// <param name="hwnd">A handle to the window whose window procedure will receive the message.</param>
        /// <param name="message">The message to be sent to the window</param>
        /// <exception cref="Win32Exception">Win32 error occures</exception>
        /// <exception cref="ArgumentException">HWND is <see cref="IntPtr.Zero"/></exception>
        /// <exception cref="ArgumentNullException"><paramref name="message"/> is null</exception>
        /// <exception cref="ArgumentException"><paramref name="message"/> is empty</exception>
        public static void SendMessage(IntPtr hwnd, string message)
        {
            if (hwnd == IntPtr.Zero)
            {
                throw new ArgumentException("HWND cannot be IntPtr.Zero");
            }

            if (message == null)
            {
                throw new ArgumentNullException("The message cannot be null");
            }

            if (message == "")
            {
                throw new ArgumentException("The message cannot be empty");
            }

            var messageBytes = Encoding.Default.GetBytes(message); /* ANSII encoding */
            var data         = new UnsafeNative.COPYDATASTRUCT
            {
                dwData = (IntPtr)100,
                lpData = message,
                cbData = messageBytes.Length + 1 /* +1 because of 0 termination */
            };

            if (UnsafeNative.SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, ref data) != 0)
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }
コード例 #2
0
        private static async void OnIconChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            var value = args.NewValue as ImageSource;

            if (value == null)
            {
                SetIcon(d, await UnsafeNative.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location).ToBitmapImageAsync());
            }
        }
コード例 #3
0
ファイル: UnsafeNative.cs プロジェクト: lulzzz/Cauldron
        /// <summary>
        /// Brings the thread that created the specified window into the foreground and activates the
        /// window. Keyboard input is directed to the window, and various visual cues are changed for
        /// the user. The system assigns a slightly higher priority to the thread that created the
        /// foreground window than it does to other threads.
        /// </summary>
        /// <param name="hwnd">
        /// A handle to the window that should be activated and brought to the foreground.
        /// </param>
        /// <returns>Returns true if successful; otherwise false</returns>
        /// <exception cref="ArgumentException"><paramref name="hwnd"/> is <see cref="IntPtr.Zero"/></exception>
        public static bool ActivateWindow(IntPtr hwnd)
        {
            if (hwnd == IntPtr.Zero)
            {
                throw new ArgumentException("HWND cannot be IntPtr.Zero");
            }

            return(UnsafeNative.SetForegroundWindow(hwnd));
        }
コード例 #4
0
ファイル: ParamPassing.cs プロジェクト: lulzzz/Cauldron
 /// <summary>
 /// Brings the thread that created the specified application into the foreground and activates the
 /// window. Keyboard input is directed to the window, and various visual cues are changed for
 /// the user. The system assigns a slightly higher priority to the thread that created the
 /// foreground window than it does to other threads.
 /// </summary>
 /// <param name="selector">If returns true, the window is activated.</param>
 public static void BringToFront(Func <Process, bool> selector)
 {
     foreach (var item in Processes.Where(x => x.MainWindowHandle != IntPtr.Zero))
     {
         if (selector(item))
         {
             UnsafeNative.ActivateWindow(item.MainWindowHandle);
         }
     }
 }
コード例 #5
0
        /// <summary>
        /// Extracts an icon from a exe, dll or ico file.
        /// </summary>
        /// <param name="filename">The filename of the resource</param>
        /// <param name="iconIndex">THe index of the icon</param>
        /// <returns>The icon represented by a byte array</returns>
        public static byte[] ExtractAssociatedIcon(string filename, int iconIndex = 0)
        {
            if (filename == null)
            {
                throw new ArgumentNullException(nameof(filename));
            }

            if (filename == "")
            {
                throw new ArgumentException("filename is empty");
            }

            unsafe
            {
                IntPtr[] largeIcons = new IntPtr[] { IntPtr.Zero };

                try
                {
                    var count = UnsafeNative.ExtractIconEx(filename, iconIndex, largeIcons, null, 1);

                    if (count > 0 && largeIcons[0] != IntPtr.Zero)
                    {
                        var icon = Icon.FromHandle(largeIcons[0]);

                        using (var stream = new MemoryStream())
                        {
                            icon.ToBitmap().Save(stream, ImageFormat.Png);
                            stream.Seek(0, SeekOrigin.Begin);

                            return(stream.ToArray());
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    foreach (IntPtr ptr in largeIcons)
                    {
                        if (ptr != IntPtr.Zero)
                        {
                            UnsafeNative.DestroyIcon(ptr);
                        }
                    }
                }
            }
        }
コード例 #6
0
ファイル: ParamPassing.cs プロジェクト: lulzzz/Cauldron
        /// <summary>
        /// Brings the thread that created the specified application into the foreground and activates the
        /// window. Keyboard input is directed to the window, and various visual cues are changed for
        /// the user. The system assigns a slightly higher priority to the thread that created the
        /// foreground window than it does to other threads.
        /// <para/>
        /// This will only activate the first application instance in the list, if multiple instances are active.
        /// </summary>
        /// <returns>Returns true if successfull; otherwise false</returns>
        public static bool BringToFront()
        {
            var process = Processes.FirstOrDefault(x => x.MainWindowHandle != IntPtr.Zero);

            if (process != null)
            {
                UnsafeNative.ActivateWindow(process.MainWindowHandle);
                return(true);
            }

            return(false);
        }
コード例 #7
0
        private async void ApplicationBase_Startup(object sender, StartupEventArgs e)
        {
            if (this.isInitialized)
            {
                return;
            }

            this.isInitialized = true;

            if (e.Args != null && e.Args.Length > 0 && e.Args[0] == "registerUriScheme")
            {
                try
                {
                    RegisterUrlProtocols();
                }
                catch
                {
                    // don't show anything... This will only annoy users
                }

                this.Shutdown();
                return;
            }

            ParamPassing.Configure(e.Args, x =>
            {
                x.IsSingleInstance     = this.IsSingleInstance;
                x.BringToFront         = this.ShouldBringToFront;
                x.RandomSelectInstance = true;
                x.DataSeparator        = '\n';

                x.ParameterPassedCallback = new Action <string[]>(args =>
                {
                    if (args != null && args.Length > 0 && args[0].IndexOf(':') > 0 &&
                        ApplicationUrlProtocols.Contains(args[0].Split(':').First(),
                                                         new DynamicEqualityComparer <string>((a, b) => string.Equals(a, b, StringComparison.CurrentCultureIgnoreCase))))
                    {
                        try
                        {
                            this.OnActivationProtocol(new Uri(args[0]));
                        }
                        catch
                        {
                            // if the application recieves malformed or bad urls... We should just ignore it here
                        }
                    }
                    else
                    {
                        this.OnActivated(args);
                    }
                });

                x.ExitDelegate = () =>
                {
                    this.Shutdown();
                    Environment.Exit(0);
                };
            });

            if (this.IsSingleInstance && ParamPassing.AreOtherInstanceActive)
            {
                if (ParamPassing.BringToFront())
                {
                    this.Shutdown();
                }
            }
            else
            {
                if (this.IsSinglePage)
                {
                    WindowType windowType = null;
                    var        window     = Common.CreateWindow(ref windowType);

                    window.ContentTemplateSelector = new CauldronTemplateSelector();

                    window.MinHeight             = 353;
                    window.MinWidth              = 502;
                    window.ShowInTaskbar         = true;
                    window.Topmost               = false;
                    window.WindowStartupLocation = WindowStartupLocation.Manual;
                    window.WindowState           = WindowState.Normal;
                    window.Icon = await UnsafeNative.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location).ToBitmapImageAsync();

                    window.Title = ApplicationInfo.ApplicationName;

                    PersistentWindowInformation.Load(window, this.GetType());

                    window.SizeChanged += (s, e1) =>
                    {
                        if (window.WindowState == WindowState.Normal)
                        {
                            PersistentWindowProperties.SetHeight(window, e1.NewSize.Height);
                            PersistentWindowProperties.SetWidth(window, e1.NewSize.Width);
                        }
                    };
                    window.Closing += (s, e1) => PersistentWindowInformation.Save(window, this.GetType());

                    window.Show();

                    window.Content = this;
                    window.Activate();
                    await this.OnPreload();

                    var rootFrame = new NavigationFrame();
                    rootFrame.DataContext = this;
                    window.Content        = rootFrame;
                    window.InputBindings.Add(new KeyBinding(new RelayCommand(async() => { await rootFrame.GoBack(); }, () => rootFrame.CanGoBack), Key.Back, ModifierKeys.None));
                }
                else if (this.GetType().GetCustomAttribute <ViewAttribute>() != null || Application.Current.Resources.Contains($"View_{this.GetType().Name}"))
                {
                    var oldShutdownMode = Application.Current.ShutdownMode;
                    Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                    this.Navigator.As <Navigator>()?.NavigateInternal <ApplicationBase>(this, null, null);
                    await this.OnPreload();

                    if (Application.Current.MainWindow == null)
                    {
                        Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                        Application.Current.Shutdown();
                        return;
                    }

                    Application.Current.MainWindow.Activate();
                    this.Navigator.TryClose(this);
                    Application.Current.ShutdownMode = oldShutdownMode;
                }

                Application.Current.MainWindow = null;
                await this.OnStartup(new LaunchActivatedEventArgs(e.Args));

                if (Application.Current.MainWindow != null)
                {
                    Application.Current.MainWindow.AddHookParameterPassing();
                    Application.Current.MainWindow.Activate();
                }
            }
        }
コード例 #8
0
ファイル: ParamPassing.cs プロジェクト: lulzzz/Cauldron
        /// <summary>
        /// Configures the parameter passing
        /// </summary>
        /// <param name="args">The arguments passed to the application.</param>
        /// <param name="config">A delegate used to configure the parameter passing.</param>
        public static void Configure(string[] args, Action <ParameterPassingConfig> config)
        {
            var processes = Processes;

            @params = new ParameterPassingConfig(processes);
            config(@params);

            if (@params.Instances.Length == 0)
            {
                @params.ParameterPassedCallback(args);
                return; // In this case we just proceed on loading the program
            }

            // Single instance true will overrule everything else
            if (@params.IsSingleInstance)
            {
                if (args.Length > 0)
                {
                    UnsafeNative.SendMessage(processes[0].MainWindowHandle, string.Join(@params.DataSeparator.ToString(), args));
                }

                @params.ExitDelegate();
                return;
            }

            // You may want to have some parameters passed and some not
            if (@params.ValidationDelegate != null && [email protected](args))
            {
                return;
            }

            // Down here every empty args array will cause the to load regardless the config
            if (args.Length == 0)
            {
                @params.ParameterPassedCallback(args);
                return;
            }

            // If the process to prefer property is not null then we will only send the params to that certain process
            if (@params.ProcessToPrefer != null)
            {
                UnsafeNative.SendMessage(@params.ProcessToPrefer.MainWindowHandle, string.Join(@params.DataSeparator.ToString(), args));
                @params.ExitDelegate();
                return;
            }

            if (@params.Instances.Length == 1)
            {
                UnsafeNative.SendMessage(@params.Instances[0].MainWindowHandle, string.Join(@params.DataSeparator.ToString(), args));
                @params.ExitDelegate();
                return;
            }
            else if (@params.PassToAllInstances)
            {
                for (int i = 0; i < @params.Instances.Length; i++)
                {
                    UnsafeNative.SendMessage(@params.Instances[i].MainWindowHandle, string.Join(@params.DataSeparator.ToString(), args));
                }

                @params.ExitDelegate();
                return;
            }
            else if (@params.RandomSelectInstance)
            {
                UnsafeNative.SendMessage(Randomizer.Next(@params.Instances).MainWindowHandle, string.Join(@params.DataSeparator.ToString(), args));
                @params.ExitDelegate();
                return;
            }
        }
コード例 #9
0
        private async void ApplicationBase_Startup(object sender, StartupEventArgs e)
        {
            this.isInitialized = true;

            ParamPassing.Configure(e.Args, x =>
            {
                x.IsSingleInstance     = this.IsSingleInstance;
                x.BringToFront         = this.ShouldBringToFront;
                x.RandomSelectInstance = true;
                x.DataSeparator        = '\n';

                x.ParameterPassedCallback = new Action <string[]>(args => this.OnActivated(args));

                x.ExitDelegate = () =>
                {
                    this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                    this.Shutdown();
                };
            });

            if (this.IsSingleInstance && ParamPassing.AreOtherInstanceActive)
            {
                if (ParamPassing.BringToFront())
                {
                    this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
                    this.Shutdown();
                }
            }
            else
            {
                if (this.IsSinglePage)
                {
                    WindowType windowType = null;
                    var        window     = Common.CreateWindow(ref windowType);

                    window.ContentTemplateSelector = new CauldronTemplateSelector();

                    window.MinHeight             = 353;
                    window.MinWidth              = 502;
                    window.ShowInTaskbar         = true;
                    window.Topmost               = false;
                    window.WindowStartupLocation = WindowStartupLocation.Manual;
                    window.WindowState           = WindowState.Normal;
                    window.Icon = await UnsafeNative.ExtractAssociatedIcon(Assembly.GetEntryAssembly().Location).ToBitmapImageAsync();

                    window.Title = ApplicationInfo.ApplicationName;

                    PersistentWindowInformation.Load(window, this.GetType());

                    window.SizeChanged += (s, e1) =>
                    {
                        if (window.WindowState == WindowState.Normal)
                        {
                            PersistentWindowProperties.SetHeight(window, e1.NewSize.Height);
                            PersistentWindowProperties.SetWidth(window, e1.NewSize.Width);
                        }
                    };
                    window.Closing += (s, e1) => PersistentWindowInformation.Save(window, this.GetType());

                    window.Show();

                    window.Content = this;
                    window.Activate();
                    await this.OnPreload();

                    var rootFrame = new NavigationFrame();
                    rootFrame.DataContext = this;
                    window.Content        = rootFrame;
                    window.InputBindings.Add(new KeyBinding(new RelayCommand(async() => { await rootFrame.GoBack(); }, () => rootFrame.CanGoBack), Key.Back, ModifierKeys.None));
                }
                else if (this.GetType().GetCustomAttribute <ViewAttribute>() != null || Application.Current.Resources.Contains($"View_{this.GetType().Name}"))
                {
                    this.Navigator.As <Navigator>()?.NavigateInternal <ApplicationBase>(this, null, null);
                    await this.OnPreload();

                    Application.Current.MainWindow.Activate();
                }

                await this.OnStartup(new LaunchActivatedEventArgs(e.Args));

                this.Navigator.TryClose(this);

                if (Application.Current.MainWindow != null)
                {
                    Application.Current.MainWindow.AddHookParameterPassing();
                    Application.Current.MainWindow.Activate();
                }
            }
        }