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:
Lorenz Cuno Klopfenstein 2010-11-17 00:59:41 +01:00
parent 47e3c48d16
commit d83527e1f9
12 changed files with 133 additions and 105 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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) {

View file

@ -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();

View file

@ -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
}

View file

@ -80,5 +80,6 @@ namespace OnTopReplica {
}
#endregion
}
}

View file

@ -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" />

View file

@ -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
}
}

View 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
}

View file

@ -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);
}
}
}
}

View file

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

View file

@ -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) {