mirror of
https://github.com/LorenzCK/OnTopReplica.git
synced 2024-05-20 20:33:06 +12:00
Merge
This commit is contained in:
commit
94696ab80b
34
OnTopReplica/AppPaths.cs
Normal file
34
OnTopReplica/AppPaths.cs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnTopReplica {
|
||||||
|
public static class AppPaths {
|
||||||
|
|
||||||
|
const string AppDataFolder = "OnTopReplica";
|
||||||
|
|
||||||
|
public static void SetupPaths() {
|
||||||
|
var roamingAppData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||||
|
var roamingAppDataApplicationPath = Path.Combine(roamingAppData, AppDataFolder);
|
||||||
|
|
||||||
|
if (!Directory.Exists(roamingAppDataApplicationPath)) {
|
||||||
|
Directory.CreateDirectory(roamingAppDataApplicationPath);
|
||||||
|
}
|
||||||
|
PrivateRoamingFolderPath = roamingAppDataApplicationPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string PrivateRoamingFolderPath { get; private set; }
|
||||||
|
|
||||||
|
public static string GenerateCrashDumpPath() {
|
||||||
|
var now = DateTime.Now;
|
||||||
|
|
||||||
|
string dump = string.Format("OnTopReplica-dump-{0}{1}{2}-{3}{4}.txt",
|
||||||
|
now.Year, now.Month, now.Day,
|
||||||
|
now.Hour, now.Minute);
|
||||||
|
|
||||||
|
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), dump);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,7 +116,8 @@ namespace OnTopReplica {
|
||||||
MinimumSize.Width);
|
MinimumSize.Width);
|
||||||
|
|
||||||
//Determine new height while keeping aspect ratio
|
//Determine new height while keeping aspect ratio
|
||||||
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientSizeConversionWidth) / AspectRatio) + ExtraPadding.Vertical + clientSizeConversionHeight;
|
var clientConversionDifference = ClientWindowDifference;
|
||||||
|
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientConversionDifference.Width) / AspectRatio) + ExtraPadding.Vertical + clientConversionDifference.Height;
|
||||||
|
|
||||||
//Apply and move form to recenter
|
//Apply and move form to recenter
|
||||||
Size = new Size(newWidth, newHeight);
|
Size = new Size(newWidth, newHeight);
|
||||||
|
@ -134,9 +135,7 @@ namespace OnTopReplica {
|
||||||
AspectRatio = ((double)aspectRatioSource.Width / (double)aspectRatioSource.Height);
|
AspectRatio = ((double)aspectRatioSource.Width / (double)aspectRatioSource.Height);
|
||||||
_keepAspectRatio = true;
|
_keepAspectRatio = true;
|
||||||
|
|
||||||
#if DEBUG
|
Log.Write("Setting new aspect ratio {0} (for {1})", AspectRatio, aspectRatioSource);
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Setting aspect ratio of {0} (for {1}).", AspectRatio, aspectRatioSource));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (forceRefresh) {
|
if (forceRefresh) {
|
||||||
RefreshAspectRatio();
|
RefreshAspectRatio();
|
||||||
|
@ -163,11 +162,13 @@ namespace OnTopReplica {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected override void WndProc(ref Message m) {
|
protected override void WndProc(ref Message m) {
|
||||||
if (KeepAspectRatio && m.Msg == WM.SIZING) {
|
if (KeepAspectRatio && m.Msg == WM.SIZING) {
|
||||||
|
var clientSizeConversion = ClientWindowDifference;
|
||||||
|
|
||||||
var rc = (Native.NRectangle)Marshal.PtrToStructure(m.LParam, typeof(Native.NRectangle));
|
var rc = (Native.NRectangle)Marshal.PtrToStructure(m.LParam, typeof(Native.NRectangle));
|
||||||
int res = m.WParam.ToInt32();
|
int res = m.WParam.ToInt32();
|
||||||
|
|
||||||
int width = (rc.Right - rc.Left) - clientSizeConversionWidth - ExtraPadding.Horizontal;
|
int width = (rc.Right - rc.Left) - clientSizeConversion.Width - ExtraPadding.Horizontal;
|
||||||
int height = (rc.Bottom - rc.Top) - clientSizeConversionHeight - ExtraPadding.Vertical;
|
int height = (rc.Bottom - rc.Top) - clientSizeConversion.Height - ExtraPadding.Vertical;
|
||||||
|
|
||||||
if (res == WMSZ.LEFT || res == WMSZ.RIGHT) {
|
if (res == WMSZ.LEFT || res == WMSZ.RIGHT) {
|
||||||
//Left or right resize, adjust top and bottom
|
//Left or right resize, adjust top and bottom
|
||||||
|
@ -175,7 +176,7 @@ namespace OnTopReplica {
|
||||||
int diffHeight = height - targetHeight;
|
int diffHeight = height - targetHeight;
|
||||||
|
|
||||||
rc.Top += (int)(diffHeight / 2.0);
|
rc.Top += (int)(diffHeight / 2.0);
|
||||||
rc.Bottom = rc.Top + targetHeight + ExtraPadding.Vertical + clientSizeConversionHeight;
|
rc.Bottom = rc.Top + targetHeight + ExtraPadding.Vertical + clientSizeConversion.Height;
|
||||||
}
|
}
|
||||||
else if (res == WMSZ.TOP || res == WMSZ.BOTTOM) {
|
else if (res == WMSZ.TOP || res == WMSZ.BOTTOM) {
|
||||||
//Up or down resize, adjust left and right
|
//Up or down resize, adjust left and right
|
||||||
|
@ -183,15 +184,15 @@ namespace OnTopReplica {
|
||||||
int diffWidth = width - targetWidth;
|
int diffWidth = width - targetWidth;
|
||||||
|
|
||||||
rc.Left += (int)(diffWidth / 2.0);
|
rc.Left += (int)(diffWidth / 2.0);
|
||||||
rc.Right = rc.Left + targetWidth + ExtraPadding.Horizontal + clientSizeConversionWidth;
|
rc.Right = rc.Left + targetWidth + ExtraPadding.Horizontal + clientSizeConversion.Width;
|
||||||
}
|
}
|
||||||
else if (res == WMSZ.RIGHT + WMSZ.BOTTOM || res == WMSZ.LEFT + WMSZ.BOTTOM) {
|
else if (res == WMSZ.RIGHT + WMSZ.BOTTOM || res == WMSZ.LEFT + WMSZ.BOTTOM) {
|
||||||
//Lower corner resize, adjust bottom
|
//Lower corner resize, adjust bottom
|
||||||
rc.Bottom = rc.Top + (int)(width / AspectRatio) + ExtraPadding.Vertical + clientSizeConversionHeight;
|
rc.Bottom = rc.Top + (int)(width / AspectRatio) + ExtraPadding.Vertical + clientSizeConversion.Height;
|
||||||
}
|
}
|
||||||
else if (res == WMSZ.LEFT + WMSZ.TOP || res == WMSZ.RIGHT + WMSZ.TOP) {
|
else if (res == WMSZ.LEFT + WMSZ.TOP || res == WMSZ.RIGHT + WMSZ.TOP) {
|
||||||
//Upper corner resize, adjust top
|
//Upper corner resize, adjust top
|
||||||
rc.Top = rc.Bottom - (int)(width / AspectRatio) - ExtraPadding.Vertical - clientSizeConversionHeight;
|
rc.Top = rc.Bottom - (int)(width / AspectRatio) - ExtraPadding.Vertical - clientSizeConversion.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
Marshal.StructureToPtr(rc, m.LParam, false);
|
Marshal.StructureToPtr(rc, m.LParam, false);
|
||||||
|
@ -204,15 +205,15 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
#region ClientSize/Size conversion helpers
|
#region ClientSize/Size conversion helpers
|
||||||
|
|
||||||
int clientSizeConversionWidth, clientSizeConversionHeight;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a client size measurement to a window size measurement.
|
/// Converts a client size measurement to a window size measurement.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="clientSize">Size of the window's client area.</param>
|
/// <param name="clientSize">Size of the window's client area.</param>
|
||||||
/// <returns>Size of the whole window.</returns>
|
/// <returns>Size of the whole window.</returns>
|
||||||
public Size FromClientSizeToSize(Size clientSize) {
|
public Size FromClientSizeToSize(Size clientSize) {
|
||||||
return new Size(clientSize.Width + clientSizeConversionWidth, clientSize.Height + clientSizeConversionHeight);
|
var difference = ClientWindowDifference;
|
||||||
|
|
||||||
|
return new Size(clientSize.Width + difference.Width, clientSize.Height + difference.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -221,18 +222,24 @@ namespace OnTopReplica {
|
||||||
/// <param name="size">Size of the whole window.</param>
|
/// <param name="size">Size of the whole window.</param>
|
||||||
/// <returns>Size of the window's client area.</returns>
|
/// <returns>Size of the window's client area.</returns>
|
||||||
public Size FromSizeToClientSize(Size size) {
|
public Size FromSizeToClientSize(Size size) {
|
||||||
return new Size(size.Width - clientSizeConversionWidth, size.Height - clientSizeConversionHeight);
|
var difference = ClientWindowDifference;
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnShown(EventArgs e) {
|
return new Size(size.Width - difference.Width, size.Height - difference.Height);
|
||||||
base.OnShown(e);
|
|
||||||
|
|
||||||
clientSizeConversionWidth = Size.Width - ClientSize.Width;
|
|
||||||
clientSizeConversionHeight = Size.Height - ClientSize.Height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the difference in pixels between a client size value and a window size value (depending on window decoration).
|
||||||
|
/// </summary>
|
||||||
|
protected Size ClientWindowDifference {
|
||||||
|
get {
|
||||||
|
long style = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.Style).ToInt64();
|
||||||
|
long exStyle = WindowMethods.GetWindowLong(this.Handle, WindowMethods.WindowLong.ExStyle).ToInt64();
|
||||||
|
return WindowMethods.ConvertClientToWindowRect(new NRectangle(0, 0, 0, 0), style, exStyle).Size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,8 +31,6 @@ namespace OnTopReplica {
|
||||||
e.SuppressKeyPress = true;
|
e.SuppressKeyPress = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Console.WriteLine("{0} ({1})", e.KeyCode, e.KeyValue);
|
|
||||||
|
|
||||||
base.OnKeyUp(e);
|
base.OnKeyUp(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
74
OnTopReplica/Log.cs
Normal file
74
OnTopReplica/Log.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace OnTopReplica {
|
||||||
|
static class Log {
|
||||||
|
|
||||||
|
const string LogFileName = "lastrun.log.txt";
|
||||||
|
|
||||||
|
private readonly static StreamWriter Writer;
|
||||||
|
|
||||||
|
static Log() {
|
||||||
|
try {
|
||||||
|
var filepath = Path.Combine(AppPaths.PrivateRoamingFolderPath, LogFileName);
|
||||||
|
Writer = new StreamWriter(new FileStream(filepath, FileMode.Create));
|
||||||
|
Writer.AutoFlush = true;
|
||||||
|
}
|
||||||
|
catch (Exception) {
|
||||||
|
Writer = null;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
throw;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(string message) {
|
||||||
|
WriteLine(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(string format, object arg0) {
|
||||||
|
WriteLine(string.Format(format, arg0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(string format, object arg0, object arg1) {
|
||||||
|
WriteLine(string.Format(format, arg0, arg1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Write(string format, params object[] args) {
|
||||||
|
WriteLine(string.Format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteDetails(string caption, string format, params object[] args) {
|
||||||
|
WriteLines(caption, string.Format(format, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void WriteException(string message, Exception exception) {
|
||||||
|
if (exception != null) {
|
||||||
|
WriteLines(message, exception.ToString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WriteLines(message, "(no last exception)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteLine(string message) {
|
||||||
|
var s = string.Format("{0,-8:HH:mm:ss} {1}", DateTime.Now, message);
|
||||||
|
Writer.WriteLine(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteLines(params string[] messages) {
|
||||||
|
if (messages.Length > 0)
|
||||||
|
WriteLine(messages[0]);
|
||||||
|
if (messages.Length > 1) {
|
||||||
|
for (int i = 1; i < messages.Length; ++i) {
|
||||||
|
Writer.WriteLine(" {0}", messages[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -188,8 +188,10 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
case WM.NCHITTEST:
|
case WM.NCHITTEST:
|
||||||
//Make transparent to hit-testing if in click through mode
|
//Make transparent to hit-testing if in click through mode
|
||||||
if (ClickThroughEnabled && (ModifierKeys & Keys.Alt) != Keys.Alt) {
|
if (ClickThroughEnabled) {
|
||||||
m.Result = (IntPtr)HT.TRANSPARENT;
|
m.Result = (IntPtr)HT.TRANSPARENT;
|
||||||
|
|
||||||
|
RefreshClickThroughComeBack();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -264,7 +266,7 @@ namespace OnTopReplica {
|
||||||
/// <param name="region">Region of the window to clone or null.</param>
|
/// <param name="region">Region of the window to clone or null.</param>
|
||||||
public void SetThumbnail(WindowHandle handle, ThumbnailRegion region) {
|
public void SetThumbnail(WindowHandle handle, ThumbnailRegion region) {
|
||||||
try {
|
try {
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Cloning window HWND {0} of class {1}.", handle.Handle, handle.Class));
|
Log.Write("Cloning window HWND {0} of class {1}", handle.Handle, handle.Class);
|
||||||
|
|
||||||
CurrentThumbnailWindowHandle = handle;
|
CurrentThumbnailWindowHandle = handle;
|
||||||
_thumbnailPanel.SetThumbnailHandle(handle, region);
|
_thumbnailPanel.SetThumbnailHandle(handle, region);
|
||||||
|
@ -273,7 +275,7 @@ namespace OnTopReplica {
|
||||||
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, !FullscreenManager.IsFullscreen);
|
SetAspectRatio(_thumbnailPanel.ThumbnailPixelSize, !FullscreenManager.IsFullscreen);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
System.Diagnostics.Trace.Fail("Unable to set thumbnail.", ex.ToString());
|
Log.WriteException("Unable to set new thumbnail", ex);
|
||||||
|
|
||||||
ThumbnailError(ex, false, Strings.ErrorUnableToCreateThumbnail);
|
ThumbnailError(ex, false, Strings.ErrorUnableToCreateThumbnail);
|
||||||
_thumbnailPanel.UnsetThumbnail();
|
_thumbnailPanel.UnsetThumbnail();
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
using System;
|
using OnTopReplica.Native;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using OnTopReplica.Properties;
|
using OnTopReplica.Properties;
|
||||||
using WindowsFormsAero.TaskDialog;
|
using System;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using WindowsFormsAero.TaskDialog;
|
||||||
|
|
||||||
namespace OnTopReplica {
|
namespace OnTopReplica {
|
||||||
//Contains some feature implementations of MainForm
|
//Contains some feature implementations of MainForm
|
||||||
|
@ -36,6 +35,7 @@ namespace OnTopReplica {
|
||||||
#region Click-through
|
#region Click-through
|
||||||
|
|
||||||
bool _clickThrough = false;
|
bool _clickThrough = false;
|
||||||
|
|
||||||
readonly Color DefaultNonClickTransparencyKey;
|
readonly Color DefaultNonClickTransparencyKey;
|
||||||
|
|
||||||
public bool ClickThroughEnabled {
|
public bool ClickThroughEnabled {
|
||||||
|
@ -43,21 +43,56 @@ namespace OnTopReplica {
|
||||||
return _clickThrough;
|
return _clickThrough;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
//Adjust opacity if fully opaque
|
|
||||||
/*if (value && Opacity == 1.0)
|
|
||||||
Opacity = 0.75;
|
|
||||||
if (!value)
|
|
||||||
Opacity = 1.0;*/
|
|
||||||
|
|
||||||
//Enable transparency and force as top-most
|
|
||||||
TransparencyKey = (value) ? Color.Black : DefaultNonClickTransparencyKey;
|
TransparencyKey = (value) ? Color.Black : DefaultNonClickTransparencyKey;
|
||||||
if (value)
|
if (value) {
|
||||||
|
//Re-force as top most (always helps in some cases)
|
||||||
TopMost = true;
|
TopMost = true;
|
||||||
|
}
|
||||||
|
|
||||||
_clickThrough = value;
|
_clickThrough = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Must NOT be equal to any other valid opacity value
|
||||||
|
const double ClickThroughHoverOpacity = 0.6;
|
||||||
|
|
||||||
|
Timer _clickThroughComeBackTimer = null;
|
||||||
|
long _clickThroughComeBackTicks;
|
||||||
|
const int ClickThroughComeBackTimerInterval = 1000;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When the mouse hovers over a fully opaque click-through form,
|
||||||
|
/// this fades the form to semi-transparency
|
||||||
|
/// and starts a timeout to get back to full opacity.
|
||||||
|
/// </summary>
|
||||||
|
private void RefreshClickThroughComeBack() {
|
||||||
|
if (this.Opacity == 1.0) {
|
||||||
|
this.Opacity = ClickThroughHoverOpacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_clickThroughComeBackTimer == null) {
|
||||||
|
_clickThroughComeBackTimer = new Timer();
|
||||||
|
_clickThroughComeBackTimer.Tick += _clickThroughComeBackTimer_Tick;
|
||||||
|
_clickThroughComeBackTimer.Interval = ClickThroughComeBackTimerInterval;
|
||||||
|
}
|
||||||
|
_clickThroughComeBackTicks = DateTime.UtcNow.Ticks;
|
||||||
|
_clickThroughComeBackTimer.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _clickThroughComeBackTimer_Tick(object sender, EventArgs e) {
|
||||||
|
var diff = DateTime.UtcNow.Subtract(new DateTime(_clickThroughComeBackTicks));
|
||||||
|
if (diff.TotalSeconds > 2) {
|
||||||
|
var mousePointer = WindowMethods.GetCursorPos();
|
||||||
|
|
||||||
|
if (!this.ContainsMousePointer(mousePointer)) {
|
||||||
|
if (this.Opacity == ClickThroughHoverOpacity) {
|
||||||
|
this.Opacity = 1.0;
|
||||||
|
}
|
||||||
|
_clickThroughComeBackTimer.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Chrome
|
#region Chrome
|
||||||
|
|
|
@ -73,11 +73,10 @@ namespace OnTopReplica {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Menu_Opacity_click(object sender, EventArgs e) {
|
private void Menu_Opacity_click(object sender, EventArgs e) {
|
||||||
//Get clicked menu item
|
ToolStripMenuItem tsi = (ToolStripMenuItem)sender;
|
||||||
ToolStripMenuItem tsi = sender as ToolStripMenuItem;
|
|
||||||
|
|
||||||
if (tsi != null && this.Visible) {
|
if (this.Visible) {
|
||||||
//Get opacity from the tag
|
//Target opacity is stored in the item's tag
|
||||||
this.Opacity = (double)tsi.Tag;
|
this.Opacity = (double)tsi.Tag;
|
||||||
Program.Platform.OnFormStateChange(this);
|
Program.Platform.OnFormStateChange(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace OnTopReplica {
|
||||||
_processors[processor.GetType()] = processor;
|
_processors[processor.GetType()] = processor;
|
||||||
processor.Initialize(form);
|
processor.Initialize(form);
|
||||||
|
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Registered message pump processor: {0}", processor.GetType()));
|
Log.Write("Registered message pump processor: {0}", processor.GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -27,10 +27,10 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
//Register window shell hook
|
//Register window shell hook
|
||||||
if (!HookMethods.RegisterShellHookWindow(form.Handle)) {
|
if (!HookMethods.RegisterShellHookWindow(form.Handle)) {
|
||||||
Console.Error.WriteLine("Failed to register shell hook window.");
|
Log.Write("Failed to register shell hook window");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.Diagnostics.Trace.WriteLine("Shell hook window registered successfully.");
|
Log.Write("Shell hook window registered successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Register message pump processors
|
//Register message pump processors
|
||||||
|
@ -65,10 +65,10 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
if (!HookMethods.DeregisterShellHookWindow(Form.Handle)) {
|
if (!HookMethods.DeregisterShellHookWindow(Form.Handle)) {
|
||||||
Console.Error.WriteLine("Failed to deregister shell hook window.");
|
Log.Write("Failed to deregister shell hook window");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.Diagnostics.Trace.WriteLine("Deregistered shell hook window successfully.");
|
Log.Write("Deregistered shell hook window successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var processor in _processors.Values) {
|
foreach (var processor in _processors.Values) {
|
||||||
|
|
|
@ -71,8 +71,6 @@ namespace OnTopReplica.MessagePumpProcessors {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleForegroundWindowChange(IntPtr activeWindow) {
|
private void HandleForegroundWindowChange(IntPtr activeWindow) {
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("New active window (h {0}). ", activeWindow));
|
|
||||||
|
|
||||||
//Seek window in tracked handles
|
//Seek window in tracked handles
|
||||||
WindowHandleWrapper activated = null;
|
WindowHandleWrapper activated = null;
|
||||||
foreach (var i in _lruHandles) {
|
foreach (var i in _lruHandles) {
|
||||||
|
@ -82,7 +80,6 @@ namespace OnTopReplica.MessagePumpProcessors {
|
||||||
|
|
||||||
if (activated == null) {
|
if (activated == null) {
|
||||||
//New foreground window is not tracked
|
//New foreground window is not tracked
|
||||||
System.Diagnostics.Trace.WriteLine("Active window is not tracked.");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +90,7 @@ namespace OnTopReplica.MessagePumpProcessors {
|
||||||
//Get least recently used
|
//Get least recently used
|
||||||
var next = _lruHandles[0];
|
var next = _lruHandles[0];
|
||||||
|
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Tracked. Switching to {0} (last use: {1}).", next.WindowHandle.Title, next.LastTimeUsed));
|
Log.Write("Switched to tracked window: switching to {0} (last use: {1})", next.WindowHandle.Title, next.LastTimeUsed);
|
||||||
|
|
||||||
Form.SetThumbnail(next.WindowHandle, null);
|
Form.SetThumbnail(next.WindowHandle, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ namespace OnTopReplica.MessagePumpProcessors {
|
||||||
var key = ++_lastUsedKey;
|
var key = ++_lastUsedKey;
|
||||||
|
|
||||||
if (!HotKeyMethods.RegisterHotKey(owner.Handle, key, modifiers, keyCode)) {
|
if (!HotKeyMethods.RegisterHotKey(owner.Handle, key, modifiers, keyCode)) {
|
||||||
Console.Error.WriteLine("Failed to create hotkey on keys {0}.", keyCode);
|
Log.Write("Failed to create hotkey on key {0} with modifiers {1}", keyCode, modifiers);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ namespace OnTopReplica.MessagePumpProcessors {
|
||||||
|
|
||||||
public void Dispose() {
|
public void Dispose() {
|
||||||
if (!HotKeyMethods.UnregisterHotKey(_hwnd, RegistrationKey)) {
|
if (!HotKeyMethods.UnregisterHotKey(_hwnd, RegistrationKey)) {
|
||||||
Console.Error.WriteLine("Failed to unregister hotkey #{0}.", RegistrationKey);
|
Log.Write("Failed to unregister hotkey #{0}", RegistrationKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ namespace OnTopReplica.MessagePumpProcessors {
|
||||||
if (msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
|
if (msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
|
||||||
int hookCode = msg.WParam.ToInt32();
|
int hookCode = msg.WParam.ToInt32();
|
||||||
|
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Hook msg #{0}: {1}", hookCode, msg.LParam));
|
Log.Write("Hook msg #{0}: {1}", hookCode, msg.LParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -12,8 +12,9 @@ namespace OnTopReplica.Native {
|
||||||
|
|
||||||
static HookMethods() {
|
static HookMethods() {
|
||||||
WM_SHELLHOOKMESSAGE = RegisterWindowMessage("SHELLHOOK");
|
WM_SHELLHOOKMESSAGE = RegisterWindowMessage("SHELLHOOK");
|
||||||
if (WM_SHELLHOOKMESSAGE == 0)
|
if (WM_SHELLHOOKMESSAGE == 0) {
|
||||||
Console.Error.WriteLine("Failed to register SHELLHOOK Windows message.");
|
Log.Write("Failed to register SHELLHOOK window message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int WM_SHELLHOOKMESSAGE {
|
public static int WM_SHELLHOOKMESSAGE {
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
namespace OnTopReplica.Native {
|
namespace OnTopReplica.Native {
|
||||||
|
|
||||||
/// <summary>A native Rectangle Structure.</summary>
|
/// <summary>A native Rectangle Structure.</summary>
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
struct NRectangle {
|
struct NRectangle {
|
||||||
|
@ -52,4 +54,13 @@ namespace OnTopReplica.Native {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class NRectangleExtensions {
|
||||||
|
|
||||||
|
public static NRectangle ToNativeRectangle(this Size size) {
|
||||||
|
return new NRectangle(0, 0, size.Width, size.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@ namespace OnTopReplica.Native {
|
||||||
public const int NCLBUTTONDOWN = 0x00A1;
|
public const int NCLBUTTONDOWN = 0x00A1;
|
||||||
public const int NCLBUTTONDBLCLK = 0x00A3;
|
public const int NCLBUTTONDBLCLK = 0x00A3;
|
||||||
public const int NCRBUTTONUP = 0x00A5;
|
public const int NCRBUTTONUP = 0x00A5;
|
||||||
|
public const int NCMOUSELEAVE = 0x02A2;
|
||||||
public const int SYSCOMMAND = 0x0112;
|
public const int SYSCOMMAND = 0x0112;
|
||||||
public const int GETTEXT = 0x000D;
|
public const int GETTEXT = 0x000D;
|
||||||
public const int GETTEXTLENGTH = 0x000E;
|
public const int GETTEXTLENGTH = 0x000E;
|
||||||
|
|
|
@ -9,6 +9,22 @@ namespace OnTopReplica.Native {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static class WindowMethods {
|
static class WindowMethods {
|
||||||
|
|
||||||
|
public static System.Drawing.Point GetCursorPos() {
|
||||||
|
NPoint ret;
|
||||||
|
if (GetCursorPosInternal(out ret))
|
||||||
|
return ret.ToPoint();
|
||||||
|
else {
|
||||||
|
#if DEBUG
|
||||||
|
throw new InvalidOperationException("Unable to GetCursorPos");
|
||||||
|
#else
|
||||||
|
return default(System.Drawing.Point);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", EntryPoint="GetCursorPos")]
|
||||||
|
private static extern bool GetCursorPosInternal(out NPoint point);
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true)]
|
[DllImport("user32.dll", SetLastError = true)]
|
||||||
public static extern bool GetClientRect(IntPtr handle, out NRectangle rect);
|
public static extern bool GetClientRect(IntPtr handle, out NRectangle rect);
|
||||||
|
|
||||||
|
@ -40,17 +56,6 @@ namespace OnTopReplica.Native {
|
||||||
return String.Empty;
|
return String.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MaxClassLength = 255;
|
|
||||||
|
|
||||||
public static string GetWindowClass(IntPtr hwnd) {
|
|
||||||
var sb = new StringBuilder(MaxClassLength + 1);
|
|
||||||
RealGetWindowClass(hwnd, sb, MaxClassLength);
|
|
||||||
return sb.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
|
||||||
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder lpString, uint maxCount);
|
|
||||||
|
|
||||||
public enum WindowLong {
|
public enum WindowLong {
|
||||||
WndProc = (-4),
|
WndProc = (-4),
|
||||||
HInstance = (-6),
|
HInstance = (-6),
|
||||||
|
@ -61,11 +66,6 @@ namespace OnTopReplica.Native {
|
||||||
Id = (-12)
|
Id = (-12)
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ClassLong {
|
|
||||||
Icon = -14,
|
|
||||||
IconSmall = -34
|
|
||||||
}
|
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
public enum WindowStyles : long {
|
public enum WindowStyles : long {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
@ -115,7 +115,23 @@ namespace OnTopReplica.Native {
|
||||||
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
|
[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
|
||||||
static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLong nIndex, IntPtr dwNewLong);
|
static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, WindowLong nIndex, IntPtr dwNewLong);
|
||||||
|
|
||||||
#region Class styles
|
#region Window class
|
||||||
|
|
||||||
|
const int MaxClassLength = 255;
|
||||||
|
|
||||||
|
public static string GetWindowClass(IntPtr hwnd) {
|
||||||
|
var sb = new StringBuilder(MaxClassLength + 1);
|
||||||
|
RealGetWindowClass(hwnd, sb, MaxClassLength);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
|
||||||
|
static extern uint RealGetWindowClass(IntPtr hwnd, [Out] StringBuilder lpString, uint maxCount);
|
||||||
|
|
||||||
|
public enum ClassLong {
|
||||||
|
Icon = -14,
|
||||||
|
IconSmall = -34
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("user32.dll", EntryPoint = "GetClassLongPtrW")]
|
[DllImport("user32.dll", EntryPoint = "GetClassLongPtrW")]
|
||||||
static extern IntPtr GetClassLong64(IntPtr hWnd, int nIndex);
|
static extern IntPtr GetClassLong64(IntPtr hWnd, int nIndex);
|
||||||
|
@ -137,5 +153,28 @@ namespace OnTopReplica.Native {
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
public static extern IntPtr GetMenu(IntPtr hwnd);
|
public static extern IntPtr GetMenu(IntPtr hwnd);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts client size rectangle to window rectangle, according to window styles.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clientRectangle">Client area bounding box.</param>
|
||||||
|
/// <param name="windowStyle">Style of window to compute.</param>
|
||||||
|
/// <param name="extendedWindowStyle">Extended style of window to compute.</param>
|
||||||
|
public static NRectangle ConvertClientToWindowRect(NRectangle clientRectangle, long windowStyle, long extendedWindowStyle) {
|
||||||
|
NRectangle tmp = clientRectangle;
|
||||||
|
if (AdjustWindowRectEx(ref tmp, windowStyle, false, extendedWindowStyle)) {
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
#if DEBUG
|
||||||
|
throw new InvalidOperationException("Failed to convert client rectangle to window rectangle");
|
||||||
|
#else
|
||||||
|
return clientRectangle;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[DllImport("user32.dll")]
|
||||||
|
private static extern bool AdjustWindowRectEx(ref NRectangle clientToWindowRect, long windowStyle, bool hasMenu, long extendedWindowStyle);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,6 +101,7 @@
|
||||||
</Reference>
|
</Reference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="AppPaths.cs" />
|
||||||
<Compile Include="AspectRatioForm.cs">
|
<Compile Include="AspectRatioForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -115,6 +116,7 @@
|
||||||
<Compile Include="ImageComboBox.cs">
|
<Compile Include="ImageComboBox.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Log.cs" />
|
||||||
<Compile Include="MainForm_Features.cs">
|
<Compile Include="MainForm_Features.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
|
|
@ -13,7 +13,15 @@ namespace OnTopReplica {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static PlatformSupport Create() {
|
public static PlatformSupport Create() {
|
||||||
var os = Environment.OSVersion;
|
var os = Environment.OSVersion;
|
||||||
|
var platform = CreateFromOperatingSystem(os);
|
||||||
|
|
||||||
|
Log.Write("{0} detected, using support class {1}",
|
||||||
|
os.VersionString, platform.GetType().FullName);
|
||||||
|
|
||||||
|
return platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PlatformSupport CreateFromOperatingSystem(OperatingSystem os) {
|
||||||
if (os.Platform != PlatformID.Win32NT)
|
if (os.Platform != PlatformID.Win32NT)
|
||||||
return new Other();
|
return new Other();
|
||||||
|
|
||||||
|
|
|
@ -33,29 +33,6 @@ namespace OnTopReplica.Platforms {
|
||||||
form.Show();
|
form.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public override void OnFormStateChange(MainForm form) {
|
|
||||||
//SetWindowStyle(form);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Used to alter the window style. Not used anymore.
|
|
||||||
/// </summary>
|
|
||||||
private void SetWindowStyle(MainForm form) {
|
|
||||||
if (!form.FullscreenManager.IsFullscreen) {
|
|
||||||
//This hides the app from ALT+TAB
|
|
||||||
//Note that when minimized, it will be shown as an (ugly) minimized tool window
|
|
||||||
//thus we do not minimize, but set to transparent when hiding
|
|
||||||
long exStyle = WindowMethods.GetWindowLong(form.Handle, WindowMethods.WindowLong.ExStyle).ToInt64();
|
|
||||||
|
|
||||||
exStyle |= (long)(WindowMethods.WindowExStyles.ToolWindow);
|
|
||||||
//exStyle &= ~(long)(WindowMethods.WindowExStyles.AppWindow);
|
|
||||||
|
|
||||||
WindowMethods.SetWindowLong(form.Handle, WindowMethods.WindowLong.ExStyle, new IntPtr(exStyle));
|
|
||||||
|
|
||||||
//WindowMethods.SetWindowLong(form.Handle, WindowMethods.WindowLong.HwndParent, WindowManagerMethods.GetDesktopWindow());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,15 @@ namespace OnTopReplica {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main(string[] args) {
|
static void Main(string[] args) {
|
||||||
|
try {
|
||||||
|
AppPaths.SetupPaths();
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
MessageBox.Show(string.Format("Unable to setup application folders: {0}", ex), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Write("Launching OnTopReplica v.{0}", Application.ProductVersion);
|
||||||
|
|
||||||
//Hook fatal abort handler
|
//Hook fatal abort handler
|
||||||
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
|
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
|
||||||
|
|
||||||
|
@ -31,6 +40,8 @@ namespace OnTopReplica {
|
||||||
return;
|
return;
|
||||||
Platform.PreHandleFormInit();
|
Platform.PreHandleFormInit();
|
||||||
|
|
||||||
|
Log.Write("Platform support initialized");
|
||||||
|
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
|
|
||||||
|
@ -65,7 +76,7 @@ namespace OnTopReplica {
|
||||||
_mainForm.IsChromeVisible = true;
|
_mainForm.IsChromeVisible = true;
|
||||||
|
|
||||||
//Persist settings
|
//Persist settings
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Persisting {0} size {1} to settings.", _mainForm.Location, _mainForm.ClientSize));
|
Log.Write("Last position before shutdown: {0}, size: {1}", _mainForm.Location, _mainForm.Size);
|
||||||
Settings.Default.RestoreLastPosition = _mainForm.Location;
|
Settings.Default.RestoreLastPosition = _mainForm.Location;
|
||||||
Settings.Default.RestoreLastSize = _mainForm.ClientSize;
|
Settings.Default.RestoreLastSize = _mainForm.ClientSize;
|
||||||
Settings.Default.Save();
|
Settings.Default.Save();
|
||||||
|
@ -90,20 +101,21 @@ namespace OnTopReplica {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static void UpdateManager_CheckCompleted(object sender, UpdateCheckCompletedEventArgs e) {
|
static void UpdateManager_CheckCompleted(object sender, UpdateCheckCompletedEventArgs e) {
|
||||||
if (e.Success && e.Information != null) {
|
if (e.Success && e.Information != null) {
|
||||||
|
Log.Write("Updated check successful (latest version is {0})", e.Information.LatestVersion);
|
||||||
|
|
||||||
if (e.Information.IsNewVersion) {
|
if (e.Information.IsNewVersion) {
|
||||||
Update.ConfirmAndInstall();
|
Update.ConfirmAndInstall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Failed to check updates. {0}", e.Error));
|
Log.WriteException("Unable to check for updates", e.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
|
||||||
string dump = string.Format("OnTopReplica-dump-{0}{1}{2}-{3}{4}.txt",
|
Log.WriteException("Unhandled exception", e.ExceptionObject as Exception);
|
||||||
DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day,
|
|
||||||
DateTime.Now.Hour, DateTime.Now.Minute);
|
string path = AppPaths.GenerateCrashDumpPath();
|
||||||
string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), dump);
|
|
||||||
|
|
||||||
using (var s = new FileStream(path, FileMode.Create)) {
|
using (var s = new FileStream(path, FileMode.Create)) {
|
||||||
using (var sw = new StreamWriter(s)) {
|
using (var sw = new StreamWriter(s)) {
|
||||||
|
@ -114,14 +126,16 @@ namespace OnTopReplica {
|
||||||
sw.WriteLine("Last exception:");
|
sw.WriteLine("Last exception:");
|
||||||
sw.WriteLine(e.ExceptionObject.ToString());
|
sw.WriteLine(e.ExceptionObject.ToString());
|
||||||
sw.WriteLine();
|
sw.WriteLine();
|
||||||
sw.WriteLine("OnTopReplica v.{0}", Assembly.GetEntryAssembly().GetName().Version);
|
sw.WriteLine("OnTopReplica v.{0}", Application.ProductVersion);
|
||||||
sw.WriteLine("OS: {0}", Environment.OSVersion.ToString());
|
sw.WriteLine("OS: {0}", Environment.OSVersion.ToString());
|
||||||
sw.WriteLine(".NET: {0}", Environment.Version.ToString());
|
sw.WriteLine(".NET: {0}", Environment.Version.ToString());
|
||||||
sw.WriteLine("Aero DWM: {0}", WindowsFormsAero.OsSupport.IsCompositionEnabled);
|
sw.WriteLine("DWM: {0}", WindowsFormsAero.OsSupport.IsCompositionEnabled);
|
||||||
sw.WriteLine("Launch command: {0}", Environment.CommandLine);
|
sw.WriteLine("Launch command: {0}", Environment.CommandLine);
|
||||||
sw.WriteLine("UTC time: {0} {1}", DateTime.UtcNow.ToShortDateString(), DateTime.UtcNow.ToShortTimeString());
|
sw.WriteLine("UTC time: {0} {1}", DateTime.UtcNow.ToShortDateString(), DateTime.UtcNow.ToShortTimeString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.Write("Crash dump written to {0}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
var move = end.Difference(start);
|
var move = end.Difference(start);
|
||||||
|
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("From {0} to {1} => {2}.", start, end, move));
|
//System.Diagnostics.Trace.WriteLine(string.Format("From {0} to {1} => {2}.", start, end, move));
|
||||||
|
|
||||||
var original = form.Location;
|
var original = form.Location;
|
||||||
form.Location = new Point(original.X + move.X, original.Y + move.Y);
|
form.Location = new Point(original.X + move.X, original.Y + move.Y);
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace OnTopReplica.StartupOptions {
|
||||||
options.StartLocation = Settings.Default.RestoreLastPosition;
|
options.StartLocation = Settings.Default.RestoreLastPosition;
|
||||||
options.StartSize = Settings.Default.RestoreLastSize;
|
options.StartSize = Settings.Default.RestoreLastSize;
|
||||||
|
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Restoring window at {0} size {1}.", Settings.Default.RestoreLastPosition, Settings.Default.RestoreLastSize));
|
Log.Write("Restoring window at {0} size {1}", Settings.Default.RestoreLastPosition, Settings.Default.RestoreLastSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Settings.Default.RestoreLastWindow) {
|
if (Settings.Default.RestoreLastWindow) {
|
||||||
|
@ -45,14 +45,20 @@ namespace OnTopReplica.StartupOptions {
|
||||||
var seeker = new RestoreWindowSeeker(new IntPtr(handle), title, className);
|
var seeker = new RestoreWindowSeeker(new IntPtr(handle), title, className);
|
||||||
seeker.SkipNotVisibleWindows = true;
|
seeker.SkipNotVisibleWindows = true;
|
||||||
seeker.Refresh();
|
seeker.Refresh();
|
||||||
|
|
||||||
var resultHandle = seeker.Windows.FirstOrDefault();
|
var resultHandle = seeker.Windows.FirstOrDefault();
|
||||||
|
|
||||||
if (resultHandle != null) {
|
if (resultHandle != null) {
|
||||||
//Load window
|
//Found a window: load it!
|
||||||
options.WindowId = resultHandle.Handle;
|
options.WindowId = resultHandle.Handle;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
System.Diagnostics.Trace.WriteLine("Couldn't find window to restore.");
|
Log.WriteDetails("Failed to find window to restore from last use",
|
||||||
|
"HWND {0}, Title '{1}', Class '{2}'",
|
||||||
|
Settings.Default.RestoreLastWindowHwnd,
|
||||||
|
Settings.Default.RestoreLastWindowTitle,
|
||||||
|
Settings.Default.RestoreLastWindowClass
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,11 +67,17 @@ namespace OnTopReplica.StartupOptions {
|
||||||
var cmdOptions = new NDesk.Options.OptionSet()
|
var cmdOptions = new NDesk.Options.OptionSet()
|
||||||
.Add<long>("windowId=", "Window handle ({HWND}) to be cloned.", id => {
|
.Add<long>("windowId=", "Window handle ({HWND}) to be cloned.", id => {
|
||||||
options.WindowId = new IntPtr(id);
|
options.WindowId = new IntPtr(id);
|
||||||
|
options.WindowTitle = null;
|
||||||
|
options.WindowClass = null;
|
||||||
})
|
})
|
||||||
.Add<string>("windowTitle=", "Partial {TITLE} of the window to be cloned.", s => {
|
.Add<string>("windowTitle=", "Partial {TITLE} of the window to be cloned.", s => {
|
||||||
|
options.WindowId = null;
|
||||||
options.WindowTitle = s;
|
options.WindowTitle = s;
|
||||||
|
options.WindowClass = null;
|
||||||
})
|
})
|
||||||
.Add<string>("windowClass=", "{CLASS} of the window to be cloned.", s => {
|
.Add<string>("windowClass=", "{CLASS} of the window to be cloned.", s => {
|
||||||
|
options.WindowId = null;
|
||||||
|
options.WindowTitle = null;
|
||||||
options.WindowClass = s;
|
options.WindowClass = s;
|
||||||
})
|
})
|
||||||
.Add("v|visible", "If set, only clones windows that are visible.", s => {
|
.Add("v|visible", "If set, only clones windows that are visible.", s => {
|
||||||
|
|
|
@ -92,8 +92,8 @@ namespace OnTopReplica.StartupOptions {
|
||||||
#region Application
|
#region Application
|
||||||
|
|
||||||
public void Apply(MainForm form) {
|
public void Apply(MainForm form) {
|
||||||
//GUI
|
Log.Write("Applying command line launch parameters");
|
||||||
form.IsChromeVisible = !DisableChrome;
|
|
||||||
form.Opacity = (double)Opacity / 255.0;
|
form.Opacity = (double)Opacity / 255.0;
|
||||||
|
|
||||||
//Seek handle for thumbnail cloning
|
//Seek handle for thumbnail cloning
|
||||||
|
@ -120,7 +120,6 @@ namespace OnTopReplica.StartupOptions {
|
||||||
handle = seeker.Windows.FirstOrDefault();
|
handle = seeker.Windows.FirstOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Position lock
|
|
||||||
if (StartPositionLock.HasValue) {
|
if (StartPositionLock.HasValue) {
|
||||||
form.PositionLock = StartPositionLock.Value;
|
form.PositionLock = StartPositionLock.Value;
|
||||||
}
|
}
|
||||||
|
@ -150,6 +149,8 @@ namespace OnTopReplica.StartupOptions {
|
||||||
form.ClickForwardingEnabled = true;
|
form.ClickForwardingEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.IsChromeVisible = !DisableChrome;
|
||||||
|
|
||||||
//Fullscreen
|
//Fullscreen
|
||||||
if (Fullscreen) {
|
if (Fullscreen) {
|
||||||
form.FullscreenManager.SwitchFullscreen();
|
form.FullscreenManager.SwitchFullscreen();
|
||||||
|
|
|
@ -194,7 +194,9 @@ namespace OnTopReplica {
|
||||||
/// <param name="handle">Handle of the window to clone.</param>
|
/// <param name="handle">Handle of the window to clone.</param>
|
||||||
/// <param name="region">Optional region.</param>
|
/// <param name="region">Optional region.</param>
|
||||||
public void SetThumbnailHandle(WindowHandle handle, ThumbnailRegion region) {
|
public void SetThumbnailHandle(WindowHandle handle, ThumbnailRegion region) {
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Setting thumbnail to handle {0}, with region {1}.", handle, region), "ThumbnailPanel");
|
Log.WriteDetails("Setting new thumbnail",
|
||||||
|
"HWND {0}, region {1}", handle, region
|
||||||
|
);
|
||||||
|
|
||||||
if (_thumbnail != null && !_thumbnail.IsInvalid) {
|
if (_thumbnail != null && !_thumbnail.IsInvalid) {
|
||||||
_thumbnail.Close();
|
_thumbnail.Close();
|
||||||
|
@ -203,8 +205,8 @@ namespace OnTopReplica {
|
||||||
|
|
||||||
//Get form and register thumbnail on it
|
//Get form and register thumbnail on it
|
||||||
Form owner = this.TopLevelControl as Form;
|
Form owner = this.TopLevelControl as Form;
|
||||||
if(owner == null)
|
if (owner == null)
|
||||||
throw new Exception("Internal error: ThumbnailPanel.TopLevelControl is not a Form.");
|
throw new Exception("Internal error: ThumbnailPanel.TopLevelControl is not a Form.");
|
||||||
|
|
||||||
_labelGlass.Visible = false;
|
_labelGlass.Visible = false;
|
||||||
|
|
||||||
|
@ -219,7 +221,7 @@ namespace OnTopReplica {
|
||||||
/// Disposes current thumbnail and enters stand-by mode.
|
/// Disposes current thumbnail and enters stand-by mode.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UnsetThumbnail() {
|
public void UnsetThumbnail() {
|
||||||
System.Diagnostics.Trace.WriteLine("Unsetting thumbnail.");
|
Log.Write("Unsetting thumbnail");
|
||||||
|
|
||||||
if (_thumbnail != null && !_thumbnail.IsInvalid) {
|
if (_thumbnail != null && !_thumbnail.IsInvalid) {
|
||||||
_thumbnail.Close();
|
_thumbnail.Close();
|
||||||
|
@ -327,7 +329,7 @@ namespace OnTopReplica {
|
||||||
endPoint.Y - startPoint.Y
|
endPoint.Y - startPoint.Y
|
||||||
);
|
);
|
||||||
|
|
||||||
System.Diagnostics.Trace.WriteLine(string.Format("Drawn from {0} to {1}, as region {2}.", start, end, final));
|
//System.Diagnostics.Trace.WriteLine(string.Format("Drawn from {0} to {1}, as region {2}.", start, end, final));
|
||||||
|
|
||||||
//Signal
|
//Signal
|
||||||
OnRegionDrawn(final);
|
OnRegionDrawn(final);
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace OnTopReplica.WindowSeekers {
|
||||||
if (titleSeekString == null)
|
if (titleSeekString == null)
|
||||||
throw new ArgumentNullException();
|
throw new ArgumentNullException();
|
||||||
|
|
||||||
TitleMatch = titleSeekString.Trim();
|
TitleMatch = titleSeekString.Trim().ToLowerInvariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
public string TitleMatch { get; private set; }
|
public string TitleMatch { get; private set; }
|
||||||
|
@ -30,15 +30,19 @@ namespace OnTopReplica.WindowSeekers {
|
||||||
if (!WindowManagerMethods.IsTopLevel(handle.Handle))
|
if (!WindowManagerMethods.IsTopLevel(handle.Handle))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
string handleTitle = handle.Title.ToLowerInvariant();
|
||||||
int points = 0;
|
int points = 0;
|
||||||
|
|
||||||
//Give points for partial match
|
//Give points for partial match
|
||||||
if (handle.Title.StartsWith(TitleMatch, StringComparison.InvariantCultureIgnoreCase))
|
if (handleTitle.Equals(TitleMatch)) {
|
||||||
points += 10;
|
points += 20;
|
||||||
|
}
|
||||||
//Give points for exact match
|
else if (handleTitle.StartsWith(TitleMatch)) {
|
||||||
if (handle.Title.Equals(TitleMatch, StringComparison.InvariantCultureIgnoreCase))
|
points += 15;
|
||||||
|
}
|
||||||
|
else if (handleTitle.Contains(TitleMatch)) {
|
||||||
points += 10;
|
points += 10;
|
||||||
|
}
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,5 +46,15 @@ namespace OnTopReplica {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks whether a control contains a mouse pointer position in screen coordinates.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="screenCoordinates">Mouse pointer position in screen coordinates.</param>
|
||||||
|
public static bool ContainsMousePointer(this Control ctrl, System.Drawing.Point screenCoordinates) {
|
||||||
|
var bb = new System.Drawing.Rectangle(ctrl.Location, ctrl.Size);
|
||||||
|
|
||||||
|
return bb.Contains(screenCoordinates);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue