/// <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()); } }
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()); } }
/// <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)); }
/// <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); } } }
/// <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); } } } } }
/// <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); }
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(); } } }
/// <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; } }
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(); } } }