Improve minimizing to tray, and restore the existing instance if SMXConfig is launched when it's already minimized to the tray.
This commit is contained in:
parent
ded697cf4c
commit
cce566624a
@ -2,6 +2,7 @@ using System;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace smx_config
|
namespace smx_config
|
||||||
{
|
{
|
||||||
@ -24,6 +25,13 @@ namespace smx_config
|
|||||||
{
|
{
|
||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
// If an instance is already running, foreground it and exit.
|
||||||
|
if(ForegroundExistingInstance())
|
||||||
|
{
|
||||||
|
Shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If we're being launched on startup, but the LaunchOnStartup setting is false,
|
// If we're being launched on startup, but the LaunchOnStartup setting is false,
|
||||||
// then the user turned off auto-launching but we're still being launched for some
|
// then the user turned off auto-launching but we're still being launched for some
|
||||||
// reason (eg. a renamed launch shortcut that we couldn't find to remove). As
|
// reason (eg. a renamed launch shortcut that we couldn't find to remove). As
|
||||||
@ -82,13 +90,38 @@ namespace smx_config
|
|||||||
window.Closed += MainWindowClosed;
|
window.Closed += MainWindowClosed;
|
||||||
window.Show();
|
window.Show();
|
||||||
}
|
}
|
||||||
else if(window.WindowState == WindowState.Minimized)
|
else if(IsMinimizedToTray())
|
||||||
{
|
{
|
||||||
window.WindowState = WindowState.Normal;
|
window.Visibility = Visibility.Visible;
|
||||||
window.Activate();
|
window.Activate();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
window.WindowState = WindowState.Minimized;
|
{
|
||||||
|
MinimizeToTray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsMinimizedToTray()
|
||||||
|
{
|
||||||
|
return window.Visibility == Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void MinimizeToTray()
|
||||||
|
{
|
||||||
|
// Just hide the window. Don't actually set the window to minimized, since it
|
||||||
|
// won't do anything and it causes problems when restoring the window.
|
||||||
|
window.Visibility = Visibility.Collapsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BringToForeground()
|
||||||
|
{
|
||||||
|
// Restore or create the window. Don't minimize if we're already restored.
|
||||||
|
if(window == null || IsMinimizedToTray())
|
||||||
|
ToggleMainWindow();
|
||||||
|
|
||||||
|
// Focus the window.
|
||||||
|
window.WindowState = WindowState.Normal;
|
||||||
|
window.Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MainWindowClosed(object sender, EventArgs e)
|
private void MainWindowClosed(object sender, EventArgs e)
|
||||||
@ -123,6 +156,33 @@ namespace smx_config
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If another instance other than this one is running, send it WM_USER to tell it to
|
||||||
|
// foreground itself. Return true if another instance was found.
|
||||||
|
private bool ForegroundExistingInstance()
|
||||||
|
{
|
||||||
|
bool createdNew = false;
|
||||||
|
EventWaitHandle SMXConfigEvent = new EventWaitHandle(false, EventResetMode.AutoReset, "SMXConfigEvent", out createdNew);
|
||||||
|
if(!createdNew)
|
||||||
|
{
|
||||||
|
// Signal the event to foreground the existing instance.
|
||||||
|
SMXConfigEvent.Set();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPool.RegisterWaitForSingleObject(SMXConfigEvent, ForegroundApplicationCallback, this, Timeout.Infinite, false);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ForegroundApplicationCallback(Object self, Boolean timedOut)
|
||||||
|
{
|
||||||
|
// This is called when another instance sends us a message over SMXConfigEvent.
|
||||||
|
Application.Current.Dispatcher.Invoke(new Action(() => {
|
||||||
|
App application = (App) Application.Current;
|
||||||
|
application.BringToForeground();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
// Create a tray icon. For some reason there's no WPF interface for this,
|
// Create a tray icon. For some reason there's no WPF interface for this,
|
||||||
// so we have to use Forms.
|
// so we have to use Forms.
|
||||||
void CreateTrayIcon()
|
void CreateTrayIcon()
|
||||||
|
@ -357,6 +357,9 @@ namespace smx_config
|
|||||||
shortcut.WindowStyle = 0;
|
shortcut.WindowStyle = 0;
|
||||||
shortcut.Save();
|
shortcut.Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", CharSet = CharSet.Auto)]
|
||||||
|
public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This class just makes it easier to assemble binary command packets.
|
// This class just makes it easier to assemble binary command packets.
|
||||||
|
@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Interop;
|
||||||
|
|
||||||
namespace smx_config
|
namespace smx_config
|
||||||
{
|
{
|
||||||
@ -65,20 +66,16 @@ namespace smx_config
|
|||||||
if(result == MessageBoxResult.No)
|
if(result == MessageBoxResult.No)
|
||||||
e.Cancel = true;
|
e.Cancel = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
StateChanged += delegate(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
// Closing the main window entirely when minimized to the tray would be
|
|
||||||
// nice, but with WPF we don't really save memory by doing that, so
|
|
||||||
// just hide the window.
|
|
||||||
ShowInTaskbar = WindowState != WindowState.Minimized;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void OnApplyTemplate()
|
public override void OnApplyTemplate()
|
||||||
{
|
{
|
||||||
base.OnApplyTemplate();
|
base.OnApplyTemplate();
|
||||||
|
|
||||||
|
// Add our WndProc hook.
|
||||||
|
HwndSource source = (HwndSource) PresentationSource.FromVisual(this);
|
||||||
|
source.AddHook(new HwndSourceHook(WndProcHook));
|
||||||
|
|
||||||
Version1.Content = "SMXConfig version " + SMX.SMX.Version();
|
Version1.Content = "SMXConfig version " + SMX.SMX.Version();
|
||||||
Version2.Content = "SMXConfig version " + SMX.SMX.Version();
|
Version2.Content = "SMXConfig version " + SMX.SMX.Version();
|
||||||
|
|
||||||
@ -516,5 +513,21 @@ namespace smx_config
|
|||||||
// until we call dialog.Close above.
|
// until we call dialog.Close above.
|
||||||
dialog.ShowDialog();
|
dialog.ShowDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int WM_SYSCOMMAND = 0x0112;
|
||||||
|
const int SC_MINIMIZE = 0xF020;
|
||||||
|
private IntPtr WndProcHook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled)
|
||||||
|
{
|
||||||
|
App application = (App) Application.Current;
|
||||||
|
|
||||||
|
if(msg == WM_SYSCOMMAND && ((int)wparam & 0xFFF0) == SC_MINIMIZE)
|
||||||
|
{
|
||||||
|
// Cancel minimize, and call MinimizeToTray instead.
|
||||||
|
handled = true;
|
||||||
|
application.MinimizeToTray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return IntPtr.Zero;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user