mirror of
https://github.com/LorenzCK/OnTopReplica.git
synced 2024-05-21 04:43:55 +12:00
Fixed platform specific initialization (split in pre/post handle creation init steps).
Added some debugging classes (shell hook interceptor and a fake debug platform).
This commit is contained in:
parent
47e3c48d16
commit
d83527e1f9
2
OnTopReplica/MainForm.Designer.cs
generated
2
OnTopReplica/MainForm.Designer.cs
generated
|
@ -554,7 +554,7 @@
|
|||
this.BackColor = System.Drawing.SystemColors.Control;
|
||||
this.ClientSize = new System.Drawing.Size(264, 204);
|
||||
this.ControlBox = false;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
|
||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; //.SizableToolWindow;
|
||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace OnTopReplica {
|
|||
|
||||
public MainForm(Options startupOptions) {
|
||||
_startupOptions = startupOptions;
|
||||
Program.Platform.PreHandleFormInit(this);
|
||||
|
||||
//WinForms init pass
|
||||
InitializeComponent();
|
||||
|
@ -110,7 +111,7 @@ namespace OnTopReplica {
|
|||
_windowSeeker.OwnerHandle = this.Handle;
|
||||
|
||||
//Platform specific form initialization
|
||||
Program.Platform.InitForm(this);
|
||||
Program.Platform.PostHandleFormInit(this);
|
||||
}
|
||||
|
||||
protected override void OnShown(EventArgs e) {
|
||||
|
@ -126,6 +127,7 @@ namespace OnTopReplica {
|
|||
|
||||
protected override void OnClosing(CancelEventArgs e) {
|
||||
_msgPumpManager.Dispose();
|
||||
Program.Platform.CloseForm(this);
|
||||
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
|
|
@ -184,10 +184,13 @@ namespace OnTopReplica {
|
|||
|
||||
string langCode = tsi.Tag as string;
|
||||
|
||||
if (Program.ForceGlobalLanguageChange(langCode))
|
||||
MessageBox.Show("Should change to {0}", langCode);
|
||||
//TODO
|
||||
|
||||
/*if (Program.ForceGlobalLanguageChange(langCode))
|
||||
this.Close();
|
||||
else
|
||||
MessageBox.Show("Error");
|
||||
MessageBox.Show("Error");*/
|
||||
}
|
||||
|
||||
private void Menu_About_click(object sender, EventArgs e) {
|
||||
|
|
|
@ -41,6 +41,9 @@ namespace OnTopReplica {
|
|||
Register(new WindowKeeper(), form);
|
||||
Register(new HotKeyManager(), form);
|
||||
Register(new GroupSwitchManager(), form);
|
||||
#if DEBUG
|
||||
//Register(new ShellInterceptProcessor(), form);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -71,6 +74,11 @@ namespace OnTopReplica {
|
|||
if (!HookMethods.DeregisterShellHookWindow(Form.Handle)) {
|
||||
Console.Error.WriteLine("Failed to deregister shell hook window.");
|
||||
}
|
||||
else {
|
||||
#if DEBUG
|
||||
Console.WriteLine("Deregistered shell hook window successfully.");
|
||||
#endif
|
||||
}
|
||||
|
||||
foreach (var processor in _processors.Values) {
|
||||
processor.Dispose();
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using OnTopReplica.Native;
|
||||
|
||||
namespace OnTopReplica.MessagePumpProcessors {
|
||||
|
||||
#if DEBUG
|
||||
|
||||
/// <summary>
|
||||
/// Basic shell message interceptor to use for debugging.
|
||||
/// </summary>
|
||||
class ShellInterceptProcessor : BaseMessagePumpProcessor {
|
||||
|
||||
public override bool Process(ref Message msg) {
|
||||
if (msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
|
||||
int hookCode = msg.WParam.ToInt32();
|
||||
|
||||
Console.WriteLine("Hook msg #{0}: {1}", hookCode, msg.LParam);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void Shutdown() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
|
@ -80,5 +80,6 @@ namespace OnTopReplica {
|
|||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,12 +130,14 @@
|
|||
<Compile Include="MessagePumpProcessors\GroupSwitchManager.cs" />
|
||||
<Compile Include="IMessagePumpProcessor.cs" />
|
||||
<Compile Include="MessagePumpProcessors\BaseMessagePumpProcessor.cs" />
|
||||
<Compile Include="MessagePumpProcessors\ShellInterceptProcessor.cs" />
|
||||
<Compile Include="MessagePumpProcessors\WindowKeeper.cs" />
|
||||
<Compile Include="Native\ErrorMethods.cs" />
|
||||
<Compile Include="Native\HookMethods.cs" />
|
||||
<Compile Include="Native\HotKeyMethods.cs" />
|
||||
<Compile Include="Native\HT.cs" />
|
||||
<Compile Include="Pair.cs" />
|
||||
<Compile Include="Platforms\DebugPlatform.cs" />
|
||||
<Compile Include="WindowSeekers\BaseWindowSeeker.cs" />
|
||||
<Compile Include="WindowSeekers\ByClassWindowSeeker.cs" />
|
||||
<Compile Include="WindowSeekers\ByTitleWindowSeeker.cs" />
|
||||
|
|
|
@ -5,8 +5,12 @@ using OnTopReplica.Platforms;
|
|||
using System.Windows.Forms;
|
||||
|
||||
namespace OnTopReplica {
|
||||
abstract class PlatformSupport : IDisposable {
|
||||
|
||||
abstract class PlatformSupport {
|
||||
|
||||
/// <summary>
|
||||
/// Creates a concrete PlatformSupport instance based on the OS the app is running on.
|
||||
/// </summary>
|
||||
public static PlatformSupport Create() {
|
||||
var os = Environment.OSVersion;
|
||||
|
||||
|
@ -32,32 +36,26 @@ namespace OnTopReplica {
|
|||
/// <summary>
|
||||
/// Checks whether OnTopReplica is compatible with the platform.
|
||||
/// </summary>
|
||||
/// <returns>Returns false if OnTopReplica cannot run.</returns>
|
||||
/// <returns>Returns false if OnTopReplica cannot run and should terminate right away.</returns>
|
||||
public abstract bool CheckCompatibility();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the application. Called once in the app lifetime.
|
||||
/// Initializes a form before it is fully constructed and before the window handle has been created.
|
||||
/// </summary>
|
||||
public virtual void InitApp() {
|
||||
public virtual void PreHandleFormInit(MainForm form) {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the main OnTopReplica form.
|
||||
/// </summary>
|
||||
protected MainForm Form { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a form. Called once in the form lifetime.
|
||||
/// Initializes a form after its handle has been created.
|
||||
/// </summary>
|
||||
/// <param name="form">Form to initialize.</param>
|
||||
public virtual void InitForm(MainForm form) {
|
||||
Form = form;
|
||||
public virtual void PostHandleFormInit(MainForm form) {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Prepares the app for shutdown. Called once before the program terminates.
|
||||
/// Called before closing a form. Called once during a form's lifetime.
|
||||
/// </summary>
|
||||
public virtual void ShutdownApp() {
|
||||
public virtual void CloseForm(MainForm form) {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -65,14 +63,13 @@ namespace OnTopReplica {
|
|||
/// </summary>
|
||||
/// <param name="form">Form to hide.</param>
|
||||
public virtual void HideForm(MainForm form) {
|
||||
form.Hide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the form is currently hidden or not.
|
||||
/// </summary>
|
||||
public virtual bool IsHidden(MainForm form) {
|
||||
return !form.Visible;
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -81,7 +78,6 @@ namespace OnTopReplica {
|
|||
/// </summary>
|
||||
/// <param name="form">Form to restore.</param>
|
||||
public virtual void RestoreForm(MainForm form) {
|
||||
form.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -91,19 +87,5 @@ namespace OnTopReplica {
|
|||
public virtual void OnFormStateChange(MainForm form) {
|
||||
}
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
bool _isDisposed = false;
|
||||
|
||||
public void Dispose() {
|
||||
if (_isDisposed)
|
||||
return;
|
||||
|
||||
this.ShutdownApp();
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
22
OnTopReplica/Platforms/DebugPlatform.cs
Normal file
22
OnTopReplica/Platforms/DebugPlatform.cs
Normal file
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OnTopReplica.Platforms {
|
||||
|
||||
#if DEBUG
|
||||
|
||||
/// <summary>
|
||||
/// Fake platform for debugging.
|
||||
/// </summary>
|
||||
class DebugPlatform : PlatformSupport {
|
||||
|
||||
public override bool CheckCompatibility() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
|
@ -4,9 +4,15 @@ using OnTopReplica.Native;
|
|||
using VistaControls.Dwm;
|
||||
|
||||
namespace OnTopReplica.Platforms {
|
||||
|
||||
class WindowsSeven : WindowsVista {
|
||||
|
||||
public override void InitForm(MainForm form) {
|
||||
public override void PreHandleFormInit(MainForm form) {
|
||||
//Set Application ID
|
||||
WindowsSevenMethods.SetCurrentProcessExplicitAppUserModelID("OnTopReplica");
|
||||
}
|
||||
|
||||
public override void PostHandleFormInit(MainForm form) {
|
||||
DwmManager.SetWindowFlip3dPolicy(form, Flip3DPolicy.ExcludeAbove);
|
||||
DwmManager.SetExludeFromPeek(form, true);
|
||||
DwmManager.SetDisallowPeek(form, true);
|
||||
|
@ -14,11 +20,6 @@ namespace OnTopReplica.Platforms {
|
|||
SetWindowStyle(form);
|
||||
}
|
||||
|
||||
public override void InitApp() {
|
||||
//Set Application ID
|
||||
WindowsSevenMethods.SetCurrentProcessExplicitAppUserModelID("OnTopReplica");
|
||||
}
|
||||
|
||||
public override void HideForm(MainForm form) {
|
||||
form.Opacity = 0;
|
||||
}
|
||||
|
@ -30,7 +31,9 @@ namespace OnTopReplica.Platforms {
|
|||
public override void RestoreForm(MainForm form) {
|
||||
if (form.Opacity == 0.0)
|
||||
form.Opacity = 1.0;
|
||||
|
||||
form.Show();
|
||||
|
||||
SetWindowStyle(form);
|
||||
}
|
||||
|
||||
|
@ -42,11 +45,13 @@ namespace OnTopReplica.Platforms {
|
|||
if (!form.IsFullscreen) {
|
||||
//This hides the app from ALT+TAB
|
||||
//Note that when minimized, it will be shown as an (ugly) minimized tool window
|
||||
Native.WindowMethods.SetWindowLong(form.Handle, WindowMethods.WindowLong.ExStyle,
|
||||
//thus we do not minimize, but set to transparent when hiding
|
||||
WindowMethods.SetWindowLong(form.Handle, WindowMethods.WindowLong.ExStyle,
|
||||
(IntPtr)WindowMethods.WindowExStyles.ToolWindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using VistaControls.Dwm;
|
||||
using OnTopReplica.Properties;
|
||||
using VistaControls.TaskDialog;
|
||||
|
||||
namespace OnTopReplica.Platforms {
|
||||
|
||||
|
@ -15,30 +11,45 @@ namespace OnTopReplica.Platforms {
|
|||
MessageBox.Show(Strings.ErrorDwmOffContent, Strings.ErrorDwmOff, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NotificationIcon _icon;
|
||||
|
||||
public override void InitForm(MainForm form) {
|
||||
DwmManager.SetWindowFlip3dPolicy(form, Flip3DPolicy.ExcludeAbove);
|
||||
|
||||
public override void PreHandleFormInit(MainForm form) {
|
||||
//Do not show in task bar, but display notify icon
|
||||
//NOTE: this effectively makes Windows ignore the Flip 3D policy set above (on Windows 7)
|
||||
//NOTE: this also makes HotKey registration critically fail on Windows 7
|
||||
form.ShowInTaskbar = false;
|
||||
}
|
||||
|
||||
public override void PostHandleFormInit(MainForm form) {
|
||||
DwmManager.SetWindowFlip3dPolicy(form, Flip3DPolicy.ExcludeAbove);
|
||||
|
||||
//Install tray icon
|
||||
_icon = new NotificationIcon(form);
|
||||
}
|
||||
|
||||
public override void ShutdownApp() {
|
||||
public override void CloseForm(MainForm form) {
|
||||
if (_icon != null) {
|
||||
_icon.Dispose();
|
||||
_icon = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool IsHidden(MainForm form) {
|
||||
return !form.Visible;
|
||||
}
|
||||
|
||||
public override void HideForm(MainForm form) {
|
||||
form.Hide();
|
||||
}
|
||||
|
||||
public override void RestoreForm(MainForm form) {
|
||||
form.Show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows.Forms;
|
||||
using OnTopReplica.Properties;
|
||||
using System.Threading;
|
||||
using System.Globalization;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using VistaControls.TaskDialog;
|
||||
using OnTopReplica.Update;
|
||||
using System.Reflection;
|
||||
using OnTopReplica.StartupOptions;
|
||||
using OnTopReplica.Update;
|
||||
|
||||
namespace OnTopReplica {
|
||||
|
||||
|
@ -17,8 +13,6 @@ namespace OnTopReplica {
|
|||
|
||||
public static PlatformSupport Platform { get; private set; }
|
||||
|
||||
static CultureInfo _languageChangeCode = Settings.Default.Language;
|
||||
|
||||
static UpdateManager _updateManager;
|
||||
|
||||
static MainForm _mainForm;
|
||||
|
@ -28,14 +22,13 @@ namespace OnTopReplica {
|
|||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main(string[] args) {
|
||||
//Hook abort handler
|
||||
//Hook fatal abort handler
|
||||
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
|
||||
|
||||
//Initialize and check for platform support
|
||||
Platform = PlatformSupport.Create();
|
||||
if (!Platform.CheckCompatibility())
|
||||
return;
|
||||
Platform.InitApp();
|
||||
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
|
@ -56,53 +49,18 @@ namespace OnTopReplica {
|
|||
if (options.Status == CliStatus.Information || options.Status == CliStatus.Error)
|
||||
return;
|
||||
|
||||
bool mustReloadForm = false;
|
||||
Point reloadLocation = new Point();
|
||||
Size reloadSize = new Size();
|
||||
|
||||
do {
|
||||
//Update language settings
|
||||
Thread.CurrentThread.CurrentUICulture = _languageChangeCode;
|
||||
Settings.Default.Language = _languageChangeCode;
|
||||
_languageChangeCode = null;
|
||||
|
||||
_mainForm = new MainForm(options);
|
||||
if (mustReloadForm) {
|
||||
_mainForm.Location = reloadLocation;
|
||||
_mainForm.Size = reloadSize;
|
||||
}
|
||||
//Load language
|
||||
Thread.CurrentThread.CurrentUICulture = Settings.Default.Language;
|
||||
|
||||
//Show form
|
||||
using (_mainForm = new MainForm(options)) {
|
||||
Application.Run(_mainForm);
|
||||
|
||||
//Enable reloading on next loop
|
||||
mustReloadForm = true;
|
||||
reloadLocation = _mainForm.Location;
|
||||
reloadSize = _mainForm.Size;
|
||||
//Persist settings
|
||||
Settings.Default.RestoreLastPosition = _mainForm.Location;
|
||||
Settings.Default.RestoreLastSize = _mainForm.ClientSize;
|
||||
Settings.Default.Save();
|
||||
}
|
||||
while (_languageChangeCode != null);
|
||||
|
||||
//Persist settings
|
||||
Settings.Default.RestoreLastPosition = reloadLocation;
|
||||
Settings.Default.RestoreLastSize = reloadSize;
|
||||
Settings.Default.Save();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces a global language change. As soon as the main form is closed, the change is performed
|
||||
/// and the form is reopened using the new language.
|
||||
/// </summary>
|
||||
public static bool ForceGlobalLanguageChange(string languageCode) {
|
||||
if (string.IsNullOrEmpty(languageCode))
|
||||
return false;
|
||||
|
||||
try {
|
||||
_languageChangeCode = new CultureInfo(languageCode);
|
||||
}
|
||||
catch {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
||||
|
|
Loading…
Reference in a new issue