Large code refactoring.

Removed features: glass cannot be disabled and form doesn't recall last position and size. Code simplified.
Fullscreen mode doesn't require separate form.
Fixed clicking with new GlassForm.
Extended click forwarding to right clicks (needs send implementation).
Improved Windows 7 support with platform specific hiding of main form.
Working scaling of form via mouse wheel.
This commit is contained in:
Lorenz Cuno Klopfenstein 2010-06-30 02:36:21 +02:00
parent 64fad6e529
commit 12b80982fd
20 changed files with 440 additions and 1433 deletions

View file

@ -83,21 +83,25 @@ namespace OnTopReplica {
ClientSize = new Size(newWidth, newHeight);
}
public void AdjustSize(double delta) {
int newWidth = Math.Max((int)(ClientSize.Width + delta), MinimumSize.Width);
int newHeight = (int)((newWidth - ExtraPadding.Horizontal) / AspectRatio + ExtraPadding.Vertical);
/// <summary>
/// Adjusts the size of the form by a pixel increment while keeping its aspect ratio.
/// </summary>
/// <param name="pixelIncrement">Change of size in pixels.</param>
public void AdjustSize(int pixelOffset) {
Size origSize = Size;
//Readjust if we go lower than minimal height
if (newHeight < MinimumSize.Height) {
newHeight = MinimumSize.Height;
newWidth = (int)((newHeight - ExtraPadding.Vertical) * AspectRatio + ExtraPadding.Horizontal);
}
//Resize to new width (clamped to max allowed size and minimum form size)
int newWidth = Math.Max(Math.Min(origSize.Width + pixelOffset,
SystemInformation.MaxWindowTrackSize.Width),
MinimumSize.Width);
//Compute movement to re-center
int deltaX = newWidth - ClientSize.Width;
int deltaY = newHeight - ClientSize.Height;
//Determine new height while keeping aspect ratio
int newHeight = (int)((newWidth - ExtraPadding.Horizontal - clientSizeConversionWidth) / AspectRatio) + ExtraPadding.Vertical + clientSizeConversionHeight;
ClientSize = new Size(newWidth, newHeight);
//Apply and move form to recenter
Size = new Size(newWidth, newHeight);
int deltaX = Size.Width - origSize.Width;
int deltaY = Size.Height - origSize.Height;
Location = new Point(Location.X - (deltaX / 2), Location.Y - (deltaY / 2));
}

View file

@ -1,20 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace OnTopReplica {
class ClickThroughLabel : Label {
protected override void WndProc(ref Message m) {
if (m.Msg == NativeMethods.WM_NCHITTEST) {
m.Result = new IntPtr(NativeMethods.HTTRANSPARENT);
return;
}
base.WndProc(ref m);
}
}
}

View file

@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace OnTopReplica {
public class CloneClickEventArgs : EventArgs {
@ -10,13 +11,17 @@ namespace OnTopReplica {
public bool IsDoubleClick { get; set; }
public CloneClickEventArgs(Point location) {
public MouseButtons Buttons { get; set; }
public CloneClickEventArgs(Point location, MouseButtons buttons) {
ClientClickLocation = location;
Buttons = buttons;
IsDoubleClick = false;
}
public CloneClickEventArgs(Point location, bool doubleClick) {
public CloneClickEventArgs(Point location, MouseButtons buttons, bool doubleClick) {
ClientClickLocation = location;
Buttons = buttons;
IsDoubleClick = doubleClick;
}

View file

@ -27,7 +27,7 @@ namespace OnTopReplica {
e.SuppressKeyPress = true;
}
Console.WriteLine("{0} ({1})", e.KeyCode, e.KeyValue);
//Console.WriteLine("{0} ({1})", e.KeyCode, e.KeyValue);
base.OnKeyUp(e);
}

View file

@ -1,221 +0,0 @@
namespace OnTopReplica {
partial class FullscreenForm {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FullscreenForm));
this.menuContext = new System.Windows.Forms.ContextMenuStrip(this.components);
this.windowsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuWindows = new System.Windows.Forms.ContextMenuStrip(this.components);
this.noneToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.modeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuModeStandard = new System.Windows.Forms.ToolStripMenuItem();
this.menuModeOnTop = new System.Windows.Forms.ToolStripMenuItem();
this.menuModeClickThrough = new System.Windows.Forms.ToolStripMenuItem();
this.opacityToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuOpacity100 = new System.Windows.Forms.ToolStripMenuItem();
this.menuOpacity75 = new System.Windows.Forms.ToolStripMenuItem();
this.menuOpacity50 = new System.Windows.Forms.ToolStripMenuItem();
this.menuOpacity25 = new System.Windows.Forms.ToolStripMenuItem();
this.quitFullscreenModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this._thumbnail = new OnTopReplica.ThumbnailPanel();
this.menuContext.SuspendLayout();
this.menuWindows.SuspendLayout();
this.SuspendLayout();
//
// menuContext
//
this.menuContext.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.windowsToolStripMenuItem,
this.modeToolStripMenuItem,
this.opacityToolStripMenuItem,
this.quitFullscreenModeToolStripMenuItem});
this.menuContext.Name = "contextMenuStrip1";
this.menuContext.Size = new System.Drawing.Size(186, 114);
//
// windowsToolStripMenuItem
//
this.windowsToolStripMenuItem.DropDown = this.menuWindows;
this.windowsToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.window_multiple16;
this.windowsToolStripMenuItem.Name = "windowsToolStripMenuItem";
this.windowsToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.windowsToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuWindows;
this.windowsToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuWindowsTT;
this.windowsToolStripMenuItem.DropDownOpening += new System.EventHandler(this.Menu_Windows_opening);
//
// menuWindows
//
this.menuWindows.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.noneToolStripMenuItem});
this.menuWindows.Name = "menuWindows";
this.menuWindows.OwnerItem = this.windowsToolStripMenuItem;
this.menuWindows.Size = new System.Drawing.Size(118, 26);
//
// noneToolStripMenuItem
//
this.noneToolStripMenuItem.Name = "noneToolStripMenuItem";
this.noneToolStripMenuItem.Size = new System.Drawing.Size(117, 22);
this.noneToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuWindowsNone;
//
// modeToolStripMenuItem
//
this.modeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.menuModeStandard,
this.menuModeOnTop,
this.menuModeClickThrough});
this.modeToolStripMenuItem.Name = "modeToolStripMenuItem";
this.modeToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.modeToolStripMenuItem.Text = Strings.FullscreenMode;
this.modeToolStripMenuItem.DropDownOpening += new System.EventHandler(this.Menu_Mode_opening);
//
// menuModeStandard
//
this.menuModeStandard.Name = "menuModeStandard";
this.menuModeStandard.Size = new System.Drawing.Size(152, 22);
this.menuModeStandard.Text = Strings.FullscreenModeNormal;
this.menuModeStandard.ToolTipText = Strings.FullscreenModeNormalTT;
this.menuModeStandard.Click += new System.EventHandler(this.Menu_Mode_standard);
//
// menuModeOnTop
//
this.menuModeOnTop.Name = "menuModeOnTop";
this.menuModeOnTop.Size = new System.Drawing.Size(152, 22);
this.menuModeOnTop.Text = Strings.FullscreenModeAlwaysOnTop;
this.menuModeOnTop.ToolTipText = Strings.FullscreenModeAlwaysOnTopTT;
this.menuModeOnTop.Click += new System.EventHandler(this.Menu_Mode_ontop);
//
// menuModeClickThrough
//
this.menuModeClickThrough.Name = "menuModeClickThrough";
this.menuModeClickThrough.Size = new System.Drawing.Size(152, 22);
this.menuModeClickThrough.Text = Strings.FullscreenModeClickThrough;
this.menuModeClickThrough.ToolTipText = Strings.FullscreenModeClickThroughTT;
this.menuModeClickThrough.Click += new System.EventHandler(this.Menu_Mode_clickthrough);
//
// opacityToolStripMenuItem
//
this.opacityToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.menuOpacity100,
this.menuOpacity75,
this.menuOpacity50,
this.menuOpacity25});
this.opacityToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.window_opacity16;
this.opacityToolStripMenuItem.Name = "opacityToolStripMenuItem";
this.opacityToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.opacityToolStripMenuItem.Text = Strings.MenuOpacity;
this.opacityToolStripMenuItem.DropDownOpening += new System.EventHandler(this.Menu_Opacity_opening);
//
// menuOpacity100
//
this.menuOpacity100.Name = "menuOpacity100";
this.menuOpacity100.Size = new System.Drawing.Size(153, 22);
this.menuOpacity100.Text = Strings.MenuOp100;
this.menuOpacity100.ToolTipText = Strings.MenuOp100TT;
this.menuOpacity100.Click += new System.EventHandler(this.Menu_Opacity_100);
//
// menuOpacity75
//
this.menuOpacity75.Name = "menuOpacity75";
this.menuOpacity75.Size = new System.Drawing.Size(153, 22);
this.menuOpacity75.Text = Strings.MenuOp75;
this.menuOpacity75.ToolTipText = Strings.MenuOp75TT;
this.menuOpacity75.Click += new System.EventHandler(this.Menu_Opacity_75);
//
// menuOpacity50
//
this.menuOpacity50.Name = "menuOpacity50";
this.menuOpacity50.Size = new System.Drawing.Size(153, 22);
this.menuOpacity50.Text = Strings.MenuOp50;
this.menuOpacity50.ToolTipText = Strings.MenuOp50TT;
this.menuOpacity50.Click += new System.EventHandler(this.Menu_Opacity_50);
//
// menuOpacity25
//
this.menuOpacity25.Name = "menuOpacity25";
this.menuOpacity25.Size = new System.Drawing.Size(153, 22);
this.menuOpacity25.Text = Strings.MenuOp25;
this.menuOpacity25.ToolTipText = Strings.MenuOp25TT;
this.menuOpacity25.Click += new System.EventHandler(this.Menu_Opacity_25);
//
// quitFullscreenModeToolStripMenuItem
//
this.quitFullscreenModeToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.close_new;
this.quitFullscreenModeToolStripMenuItem.Name = "quitFullscreenModeToolStripMenuItem";
this.quitFullscreenModeToolStripMenuItem.Size = new System.Drawing.Size(185, 22);
this.quitFullscreenModeToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuQuitFullscreen;
this.quitFullscreenModeToolStripMenuItem.Click += new System.EventHandler(this.Menu_Quit_click);
//
// _thumbnail
//
this._thumbnail.BackColor = System.Drawing.SystemColors.Control;
this._thumbnail.ClickThrough = true;
this._thumbnail.Cursor = System.Windows.Forms.Cursors.Default;
this._thumbnail.Dock = System.Windows.Forms.DockStyle.Fill;
this._thumbnail.DrawMouseRegions = false;
this._thumbnail.FullscreenMode = false;
this._thumbnail.GlassMode = false;
this._thumbnail.Location = new System.Drawing.Point(0, 0);
this._thumbnail.Name = "_thumbnail";
this._thumbnail.ShownRegion = new System.Drawing.Rectangle(0, 0, 0, 0);
this._thumbnail.ShowRegion = false;
this._thumbnail.Size = new System.Drawing.Size(284, 264);
this._thumbnail.TabIndex = 0;
//
// FullscreenForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(284, 264);
this.ContextMenuStrip = this.menuContext;
this.Controls.Add(this._thumbnail);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.Name = "FullscreenForm";
this.Text = Strings.FullscreenTitle;
this.menuContext.ResumeLayout(false);
this.menuWindows.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private ThumbnailPanel _thumbnail;
private System.Windows.Forms.ContextMenuStrip menuContext;
private System.Windows.Forms.ToolStripMenuItem windowsToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem quitFullscreenModeToolStripMenuItem;
private System.Windows.Forms.ContextMenuStrip menuWindows;
private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem modeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem menuModeStandard;
private System.Windows.Forms.ToolStripMenuItem menuModeOnTop;
private System.Windows.Forms.ToolStripMenuItem menuModeClickThrough;
private System.Windows.Forms.ToolStripMenuItem opacityToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem menuOpacity100;
private System.Windows.Forms.ToolStripMenuItem menuOpacity75;
private System.Windows.Forms.ToolStripMenuItem menuOpacity50;
private System.Windows.Forms.ToolStripMenuItem menuOpacity25;
}
}

View file

@ -1,260 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using VistaControls.TaskDialog;
using OnTopReplica.Properties;
namespace OnTopReplica {
partial class FullscreenForm : Form {
public FullscreenForm() {
InitializeComponent();
_thumbnail.GlassMode = true;
//Set mode
Mode = (Settings.Default.FullscreenAlwaysOnTop) ? FullscreenMode.AlwaysOnTop : FullscreenMode.Normal;
//Set native renderer on context menu
Asztal.Szótár.NativeToolStripRenderer.SetToolStripRenderer(new Control[] {
menuContext, menuWindows
});
}
WindowHandle _lastHandle;
WindowManager _manager = new WindowManager(WindowManager.EnumerationMode.TaskWindows);
public void DisplayFullscreen(Screen screen, WindowHandle window) {
_lastHandle = window;
//Init thumbnail
_thumbnail.SetThumbnailHandle(window);
//Form setup
this.Location = screen.WorkingArea.Location;
this.Size = screen.WorkingArea.Size;
}
public void CloseFullscreen() {
this.Visible = false;
_thumbnail.UnsetThumbnail();
}
public Rectangle ShownRegion {
get {
return _thumbnail.ShownRegion;
}
set {
_thumbnail.ShownRegion = value;
}
}
public bool ShowRegion {
get {
return _thumbnail.ShowRegion;
}
set {
_thumbnail.ShowRegion = value;
}
}
public WindowHandle LastWindowHandle {
get {
return _lastHandle;
}
}
#region Event handling
public event EventHandler<CloseRequestEventArgs> CloseRequest;
protected virtual void OnCloseRequest() {
if (CloseRequest != null)
CloseRequest(this, new CloseRequestEventArgs {
LastWindowHandle = _lastHandle,
LastRegion = (_thumbnail.ShowRegion) ? (Rectangle?)_thumbnail.ShownRegion : null
});
}
protected override void OnDoubleClick(EventArgs e) {
OnCloseRequest();
base.OnDoubleClick(e);
}
protected override void OnKeyUp(KeyEventArgs e) {
if (e.KeyCode == Keys.Escape) {
e.Handled = true;
OnCloseRequest();
}
else if (e.KeyCode == Keys.Enter && e.Modifiers == Keys.Alt) {
e.Handled = true;
OnCloseRequest();
}
base.OnKeyUp(e);
}
protected override void OnClosing(CancelEventArgs e) {
base.OnClosing(e);
//Never close
OnCloseRequest();
e.Cancel = true;
}
protected override void OnActivated(EventArgs e) {
base.OnActivated(e);
//Disable "click through" on show: this prevents case in which the user
//cannot return to standard mode closing and re-opening the fullscreen mode
if (Mode == FullscreenMode.ClickThrough)
Mode = (Settings.Default.FullscreenAlwaysOnTop) ? FullscreenMode.AlwaysOnTop : FullscreenMode.Normal;
}
#endregion
#region Mode
FullscreenMode _mode;
public FullscreenMode Mode {
get {
return _mode;
}
set {
_mode = value;
Settings.Default.FullscreenAlwaysOnTop = (value != FullscreenMode.Normal);
//Top most if always on top or click through
this.TopMost = (value != FullscreenMode.Normal);
this.TransparencyKey = (value == FullscreenMode.ClickThrough) ? Color.Black : Color.White;
this.Invalidate();
}
}
#endregion
#region Menus
private void Menu_Windows_opening(object sender, EventArgs e) {
_manager.Refresh(WindowManager.EnumerationMode.TaskWindows);
WindowListHelper.PopulateMenu(this, _manager, menuWindows, _lastHandle, new EventHandler(Menu_Window_click));
}
void Menu_Window_click(object sender, EventArgs e) {
//Ensure menu is closed
menuContext.Close();
//Get clicked item and window index from tag
ToolStripItem tsi = (ToolStripItem)sender;
var windowData = tsi.Tag as WindowListHelper.WindowSelectionData;
//Handle "-none-" window request
if (windowData == null) {
OnCloseRequest();
return;
}
try {
_thumbnail.SetThumbnailHandle(windowData.Handle);
if (windowData.Region != null) {
_thumbnail.ShownRegion = windowData.Region.Rect;
_thumbnail.ShowRegion = true;
}
else {
_thumbnail.ShowRegion = false;
}
_lastHandle = windowData.Handle;
}
catch (Exception) {
OnCloseRequest();
}
}
private void Menu_Mode_opening(object sender, EventArgs e) {
menuModeStandard.Checked = (Mode == FullscreenMode.Normal);
menuModeOnTop.Checked = (Mode == FullscreenMode.AlwaysOnTop);
menuModeClickThrough.Checked = (Mode == FullscreenMode.ClickThrough);
}
private void Menu_Mode_standard(object sender, EventArgs e) {
Mode = FullscreenMode.Normal;
}
private void Menu_Mode_ontop(object sender, EventArgs e) {
Mode = FullscreenMode.AlwaysOnTop;
}
private void Menu_Mode_clickthrough(object sender, EventArgs e) {
if (!CheckFirstTimeClickThrough())
return;
Mode = FullscreenMode.ClickThrough;
}
private void Menu_Opacity_100(object sender, EventArgs e) {
this.Opacity = 1.0;
}
private void Menu_Opacity_75(object sender, EventArgs e) {
this.Opacity = 0.75;
}
private void Menu_Opacity_50(object sender, EventArgs e) {
this.Opacity = 0.5;
}
private void Menu_Opacity_25(object sender, EventArgs e) {
this.Opacity = 0.25;
}
private void Menu_Opacity_opening(object sender, EventArgs e) {
menuOpacity100.Checked = (Opacity == 1.0);
menuOpacity75.Checked = (Opacity == 0.75);
menuOpacity50.Checked = (Opacity == 0.5);
menuOpacity25.Checked = (Opacity == 0.25);
}
private void Menu_Quit_click(object sender, EventArgs e) {
OnCloseRequest();
}
#endregion
/// <summary>Check if the user uses click-through for the first time and asks confirmation.</summary>
/// <returns>Returns whether to switch to click through mode or not.</returns>
private bool CheckFirstTimeClickThrough() {
if (Settings.Default.FirstTimeClickThrough) {
//Alert the user about click through
TaskDialog dlg = new TaskDialog(Strings.InfoClickThrough, Strings.InfoClickThroughTitle, Strings.InfoClickThroughInformation);
dlg.CommonIcon = TaskDialogIcon.Information;
dlg.ExpandedControlText = Strings.ErrorDetailButton;
dlg.ExpandedInformation = Strings.InfoClickThroughDetails;
dlg.UseCommandLinks = true;
dlg.CustomButtons = new CustomButton[] {
new CustomButton(Result.Yes, Strings.InfoClickThroughOk),
new CustomButton(Result.No, Strings.InfoClickThroughNo)
};
var result = dlg.Show(this);
return result.CommonButton == Result.Yes;
//Settings.Default.ClickThrough = (dlg.Show(this).CommonButton == Result.Yes);
}
Settings.Default.FirstTimeClickThrough = false;
return true;
}
}
}

View file

@ -1,254 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuContext.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="menuWindows.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>142, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAMDAAAAEAGACoHAAAFgAAACgAAAAwAAAAYAAAAAEAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AABBdztCdjhDeDpCdzlCdjpDdzpFfD5EeTpGfDtFfDtFfjpJgjtHfjlHgTpIgjtNiDxKgzlKhDlKiDhO
iztNijpMjDpPjTtSkz1Vlz1YnD1bpD5dpz1hqT9lrEFkrT5oskJnsD1prT1orD1mqTlmpjlkpDdmozpj
nDVhmDRekzJekTJekDNjkjNeijFbiC1ahSxDeDlDdztDdztEdzpFejpEeDhEdzlEeDpGezhGfThGfDhH
fThHfjlIgjhIgzpKgzhJhDhKhjhLhzlNiTlLiDlPjTlVlz1VmDxYnTxdoT5gqD1iqj9jrkBlr0BnsEBp
rz1nrT1orTtmqzhlpzhopjpjoDVgmzNgmDNflTJejy9cjy5gkS9bii5ciC1chyxbhytCdjpDdzlDeDlG
eztDdjhDdzhDdzdEeDhHfDdFejZFezdGfTdJgzlIgDdIgTlKgzdLhDhKhjlLhjhMiTlQkDpSlDtXmDtY
nTtcozxepz1hqz1jrT1oskBorztpsDxnrjxorTtmqzplqTppqjxioDVfnDRfmDNflTJdkjBekjFcji9c
iy9biS1ciCxciCtgjS1DdjhEezpDeDhCdTdEdTZEdjVFeDVFeDVHdzREezZGfjdIfTZHfTdIgDdJgjdK
hDZKhDZKhDZMhzdTkztSlDpWmjtanjtcozxepz1gqD1kqzxorz1nsD5psDxorztlrTtmqzpmqDxkpTli
oDZgnTVelzNclTJdkjFilTNaji5biy5bii1bii1ciSxfjSxdiypGejpCdTZDdThFdTdGeDdFeDZEdzdG
eDZIejhLgTpIeztLfjdKgDlLgjlMhDpMhTlOhTpPjDtTkTtWlTxZmj5coT5gpT9ipz9kqD9prUForj5p
sEBpsEBpsT9prz9nrD9qrEJkozlloDlinThhmjdgmDZhlzRflDJbjzBcjTFejTBdjDBejC9eiyxejStf
kC1DdTdEdzhFdzlIeDpIeTtKejpKez5NfT1QgD9QgUBPgUBShD9RhUBSh0BTiEFVi0BdlUVak0JdmUNi
n0VlokVnpkZoqUVprERusEVusUVts0ZutEdvs0VvskZusEVvrkZrqEJppENnokJmnz9mnT1qnzxkmDpi
lDhikjZhkjVjkDVmlTZgjzFhjy9jki5ili1DdjdGeDpIeDtMeT1Pe0BRfkRWhkdWg0ZahklbiUtaiUxd
i0tcjExej0tglE1kmU5mnE9nn05ro05up09wq1Bzr1F2s1F1s053tFB2tlF3tlF4tlB2tlB4tlF2sU9z
rU5yqk1yqExwpUxwpUlypkluoUhsnEZsm0VrmkJql0Jtmz5pljtolzhplzZomjNspTJGeDpKeTpMej5S
e0FVgUdahkteiE5jjFNokFdpkllqk1tslltsmVxyoV5xol52pF12p196rWB7sGB+smGAtmCEumKCuWCD
umGCul+Du1+Du2CEvF+FvWGDuF+Dt16As11/sFyAsFyAr1t+rVp9qVt8qFp7pVd6plV5pVN2oU9zn0px
oUZunj9wojxwqThwrjZIdzpOeD5SfkJbhEpehU5ljFZskV1zl2R5nGp8oWx9oXCBpXCDq3KErXKGr3KJ
tHSLtnSLuHSNvXWPvnSRwHSRw3WSwnWSwXOSwXSSw3OSw3STw3ORwHKQv3KQvXGPu3GPunGQunKNt3GN
tXCMtG+NtG+MsmyMs2uGrWWErWGArFp+qlR7rEt5sEV3tj91vzxMdjtRfUFZgUlhhlFqjFp0lWR8nG+G
o3iPqoCUr4SWtYmZuImau4ubvoudwYyfw4ufxYyhx42jyo6jyoykyoylzI2lzI2ky4ukyo2kzYyjyouj
yoqjyYqjyIuixouixomix4uhxIqhwomhwoihwYeiwYeiwYedvoGZvH2UunSQuWyOumKGuleDv1CAykl6
2UFSfEFWfkVghE9qjVuIhYP89e3z9e/n9PDn9fDn9PHn9fHo9fHp9vLq9fHq9fHp9fDq9PDr9O/r9O/s
9O7s9O3s8+3s8+vs8urs8unr8efr8Obs8Obt8OXu8eXv8OTw8eTz9OX4+Of8+ez9+ez++e3++en9+ej9
+OX89+L89t/69OT57uKUzGaN01yF4lGB+EtQeT5bgUpliVZzkmONiIPk6efS8vSj6vCl6++n6++o7O6q
7O6t7e6v7u6x7u6y7ey27uy47uy88Oy/8OvC8OrE8OjG8ObK8OTL8eDO8d7T8d7a8eDg8uLk8uTm8+Po
9N/s+Nny+9L4/Nb7/NL8/M/8/Mr8/Mf8+8H8+bb89rD699f68eGe33aS62SL/Fp/+1BTe0Neg01ri1t6
lWqWkYzc6+qj6u441d861t091ts/19lD2NhJ2dhO2tdR29VU29Jb3tFh4NFq5dJx6NF66tGK69WW69in
7Nmu7dS27c+57ci07cOr7b6n7cC07rzH8bPO9KfV9pva85jp74vt64Hv6Hbx5nDy5Gbz4FT120r466r6
79qm9IGY/HGM+2R2qUtWe0NihFBvjV9/mG+dmZTd7Ouj6e031Nw61Ns91dlA1tdC19VG2dRL29NX4NZe
5Nhl6Nlm69Vt8NJ289KB9tGR9tOd9dKr9NGy8sy78cnB9MS7872x8reu8bq187jF97XC76LD55LF33nS
2mna1Vze0F3iz1jnzVLsy0bwxj/346b57tuo/YmZ/XmDoFt4lUpXfENkhFFyj2GFnnSjnpre7euh6Ooz
09Y21tc52dc62NI81sxA1shE2MVQ3chZ5cth68tg7MRk67ts67d17bSI8LeT7rWh67Oj4qqo3KOo3Jmd
2ouP2YCL2YGV24Cn34Kp13Wx1Hm0y2bCx1vKwUfUw0fbwUTgvkHluj7suzv236X57tyq75CUrXOHol95
l05ZekRmhVJ4lWWIoHamop7e7eug5uYxzcw00M040sw50cc+1chC1sRI2MFS2L1b375k5r5l57Ro5Khs
3aBx2pd63JN/24mD14CCzXSGym2Lzm+OymuPxGeVu2CWul6avF6dtFOptFizsky3ska+sDvItT3Stz/Z
tjvftDrntzr03qX479ynvIyYsXaHomB6mE9bfkRpiFN5lmSLo3mopKDe7Oqh4+E3y8U70Mc/0sY+zrxF
0rtM1rlT2rVW1qte2qdo36Jz459z2ZFwzIJsv3F1wnJ3w3J+wmx8uV2Cs1CDsVGErE2EpUqGm0GKlz6R
ljualTekmz+snT2unjq0oDDAqDHJqzXPqjXTpjTaqjXu2KP37dyrwJCXrniJpGJ7mVBcgUVrjFR6mGaK
p3iopKDf7Oml49s+yblFz71J0LtIzLFO0K5T0KhZz6JbyZVix4xryYh1y4NzxHtwuW1sr150sFl0rVZ3
qk92okN9njl+nzx+mTt8kTl8hS9/gSqFfyeLfyWRgSWZhSWehySmjiarkSm1li68ly7GmS7NnDDo0qH2
7NypvI6Xr3eKo2N7mFBehEVrj1V6nGaMp3mopKDf7Oen4NVDw6tJyK5Nx6pLwJ1OvJFRuYlWt4Fct31l
uXhsunR0uG5xsGNuplVsnkVxnT9wmj1wlDZuiy10hyN2gyF4fx95ex55dx17dR1/dR2Fdx6LeR+SfCCa
giKjiiKokCiwlCq0lS++ly/FmDHm0KD17NypvY6Yr3iKpGR7l09fiEVsk1R7nGWMqXiopKDf6uWn2s1C
spJItJNLso9MsIhMqHtNoW9PmWNVmV5enVpln1ZomktmlENljjdrjzFxjyhyiyJwhB5ufht0gBp6gRp8
fhl7eRl4dBl5cRl8cRqBchuHdByOeR6XgB+fhyKjjSerkSqtlS60ljC5lzThz6T07N2pvY6Yr3iJo2N8
l05hi0VulFR8n2SOrXmopKDf5+Km0ME9mnVAmnJClmxEk2VGjV1Ki1VQi05ZkUtlmEdsmkFtlTdsjS1q
hiNwhx5zhxp1hhlzghd0gBZ7gxV/gxaAfxV9eRV5chZ4bxZ6bhd+bxiEchmMdxuUfx2dhR+jiSKrkiWv
mCq0mi+2lzPezqP07N6pvo+Yr3iJo2J8l09ijkVul1N8omSMqneopKDf5uClyLY8il9Bjl5FjVpIjlZM
jE9RjUhZjEFijjltlDNzlCx0jyRxhh1wgRh1hRZ5hxV6iBR5hRN7hBKBhxKDhRKDgRJ+ehJ6cxN5bxN5
bRR8bhWCcReLeBmUfxychB2hhh+oiyKvkiS0lim1li7czqL17d+pvY6Yr3aKo2N8l09ikEVtmFR8oGSM
qneopKDf5d6mxa8+g09EiU9LjUtQjEVXlT5bkzhklTJsjip3lCR9kx58jhl4hhV3gxJ8iRJ+ixKAjBF/
iRGCiRCGihCGhg+EgQ+Aeg99dA97cRB6bhF9bxODcxWNexeVgRqbgxyegh2jhx+wliO7nSW/nSjgzp71
7d+qvYyYrnaJo2N7lk5ikEVtl1N7n2SMqXenpKDg5N2nwqlCgEJKikFUkj9YkDlflzNikixqkyVyix5+
kRuDkhiDjRR9hhB9hw+DjQ+HkA+HkA+GjQ6IjQ2Kiw2HhgyDgAyAegx/dg19cg59bw9/cRCGdhOPfhaW
gRiZgRmafhqdfhymix+ylCK6mSTfzpz27t+qvYyZr3WKo2N8lk1ij0VtllN7nmOMqXenpKDg49upwqRG
fzZRkTdamDRelC9hkCdkiiBtjRx4iheFkhmJkxaHjhOAhg2DiQyLkg2Plg2PlQyKjwuNjwuNiwqJhQmE
fwmBegqAdgp/cwt+cQ2BdA6JexGRgBOVgBWVfReVehiXehmghh2rkiG3myTf0Jz47+CqvYyZr3WJomJ8
lk9hj0RsllJ7nmOLqHenpKDg5NqrwqBLjS9UnS9boSxdjiVegB5kfhlvgxV8ihKJkxiMkhWJjROChgmH
jAmPlAqUmAqTlwqPkQmRkAmOigiKhQiEfgeAeQd/dgh9cwl9cgqCdgyKfQ+PfxGQfBKOdxSPdRWSdheX
eRmeiCCqkyPa0p338N+pvIyYrnaJomJ8lk1gjkNslFN6nGSMqXinpKDh5NmrwZ1LiChTlihZmCVciB5e
fBhlfBRwghF9iQ6JkRSMkBKIixCEhgaLjQeTlQeXmAiVlgeTkQeTkAeQigaKhAaEfQWBeQV+dQZ7cgd8
cgiCeAuJfQ2LfA+KdxCIchGJcBOMchWSdheZhR+jjyLW0J328N+pvIuYrnWJomB8l01fjEJsk1F5m2OK
pHanpKDh49mrv5tJgiNQiSFXjx9agBlfehRmeRBxfw19hwuHjA6JjAyFhwqFhgWNjgWTkwWXlQaUkgWU
kQaUjwWQiAWJggWEfAR/eAR7cwV4cAV6cgeAeAmFeguFdw2CcQ6BbA+CaxGGbhSMchaUfxuahx/Sy5v0
7t+pvIuYrnWJo2B8l01hjEJpkVF4l2KKonWnpKDg4tiqvJlHbh1OeBxVfxpbfhZfeBJldg5wfQt8hAmE
iAmGhweCgwaFhQSPjgWVkwWYlAWTjgSUjgSSiwSOhgSIfwSCegR+dgR4cQR1bwR4cgV+dweAdwl9cQp6
agx6Zw18Zw+AahKGbxSNdBeVfxzQx5n07+CpvIuZrnSKomB8l01diEJqjlB4lWGIoHSnpKDg4tiquphG
ahpOdRlVfRdbfRRedhBkdAxvegl7ggeDhQaEhASAgAOFhQSQjwWXkwWYkwWTjASTiwSQhwSMggSFfQSA
eAR7cwR1bwNzbgN2cgR5dAZ4cQh1aglyZApzYgx2Yw56ZxGBaxOIcRWRfBnOxZjz7uCqvIuZrnSJoV59
lkxchEFpjFB3k2CIn3WnpKDf4tipuZdFaBdNcRVUehNaehFddA1icQpteAh5fwaAgwWBgQN+fgOFhASP
jQSVkQWUjgWQiQWQhwSOhASJfwSDegR9dQR4cANzbQNybQNzcAN0cAVxawZsYwhrXglsXQtwXw11Yw97
aBKCbRSLdxjLwpfz7t+qvIuYrXOJoV58lkxcgj9oik93k2GInnSnpKDg49mpuJVFZRRMbRJUdhBZdw5c
cQtgbghsdQZ3fAV8fgR8fQN7ewOEgwSNigSSjQSPiASNhQSMggSKgASFewSAdwR7cgR2bgNxawNxbANw
bgNuawRpZAVlXQdkWQhmWQpqWwxvXg51ZBB8ahKEcBXIvpbx7uKqvIqYrXOLoV58lkxagkFoiE91kGCG
nXOnop7f4tipt5REYhFLaQ9Scg1XcwxbbwlfbAdpcgV0eQR3eQN3eAN3dwODgQOJhgSMhwSHgQSIgASH
fgOFfAOBdwN8cwN3bwNzbANvagNvawJsagJoZQNhXQRfVwVeVQdhVQhkVwppWwxvYA92ZhF+bBPGvZXw
7eGqu4qarXOKoV58lUxYfD5oh010j12EmnCkoJvf4deptpNEYA9JZg1QbgtVcAlZbQddaQZocARxdgNz
dgNydAN0dQOCgQOIhQSJhASDfASDewOEfAOBeAN9dAN4bwN0bANvagNuaQNsaQJpZgJiXwNbVwNZUgRZ
UQVbUQdfUwlkVwtqXA1xYw94aRHDvJTw7OCnuYaYrHCJoFx8lUpcgD5kg0lyjFqBl2yfm5bd39WptZFD
Xg1IYgtPaglTbAhXagZcZwVmbgNucwJwcwJvcQJzcwKBfwOGgwSEfwR/eAR/dwOBeAN9dQN6cQN0bQNw
agNtaANraANpZgNkYQNcWQNXUgNUTwRVTgVWTgZaUAdfVAplWQxrXw5yZRDAupPw696ktYCWqWuInlh7
lEdWeTlhgUduilZ8lGaZlZDc3dOntZFBXgxGYQpLZwlQaQdUaAVZZwRibQRqcwVrcgVqcAVvdAN7fgSA
gAR8ewR5dgR5dgR6dgR3cwRzbwRvbANraQNoZwNnZwNjZQNeXwNWVwNRUQNOTgNOTQRQTQVTTwdYUgle
VgtkXAxrYg69uJLv6t2dr3ePpGSDmlJ4kUJVeThef0Nqh1B3kV+RjIfk493U28qotZGptpCsuZCvuo+x
uY6zuY63vI26v4+7v4+6vo+9v43Bw47DxI7BwY7AwI7BwI7BwI6/vo69vY68u427uo25uo24uY23uI20
tY2xso2vr42tro2tro6uro6vr4+ysI+0spC2s5G5tpHd28v38umVqWyJnlt9lUt0jT9TeDVbfj5lhEpw
jVaHgn308evo5uDe4dbh4tfj5Njj5djk5djk5djl5djm5tnm5tnm5tnm5tjn59fn59fn5tfn5dfn5djn
5djm5dfm5Nfm5Nfl5Nfl5Nfl5Njl5Njk5Njk49jj49jj4tjj4tjj4tjj4tjk49nk4tnk4tfk4dbr6OH9
9u+KoF+AmFB3kENvijhReDJWezljhkRnh0rV1NSLhX+Qi4eYk4+emZWinpmloZymop2mop2mop2mop2m
op2mop2lop2lop2lop2loZ2loZ2loZ2loZ2loZ2loZ2loZ2loZ2lop2lop2mop2mop2mop2mop2mop2m
op2mop2mop2loJyhnZicmJOVkYyPioWSj4t/lU53kERxiTlqhTBOdi5WfTVXfzlehUJmi0lvklJ1m1h9
p2GBrmaGuWqJxm6K1nCK6XKL6XOHyG+EnGmFnWqGnmiIoGqGn2mHoGqHoGmIommIo2qJpGqKpWmKpmqK
p2qMqGqMqWqMqWqNqWqNqWuMqGqOqGqOqGqOp2mNpmiMpGeLomSIoF+DnFh+l1B7k0l0jkBuijhrhTBm
gypLeCxPei9VfzVZhTheij1lkkNtn0tup05yslN1xVV411l27Fp47F9xplVyjVFxjlFzkFJzklN0klN1
klJ2lFN2lVF2llJ2llJ3mVN4mlJ5m1J5nVF6nlN6n1N9nVN9n1R8n1R9nlN9n1J9nVJ9nFF8m1B8mU97
l014lUd2kkRzj0BwjDpqhzRohS9mgChifiRKeClNfC1RgC5VhjBYjTVfmTphoT5jsEBnxURn2kVr70pn
70tijUBhgT5igj5ihT5lhz5jhz9miEBmiD9oiz9ojD5njD9njD9pkEBqkT9rkz9slT9slkBul0BvlT9u
l0Bul0Bvlj9vlj9vlT5vkz5vkT1vkDtujjptjThrijVpiDFnhi5kgytkgidifyNefR9KeidNfihQhCtS
jCxWmTBYojNcsTVcxzZb5Tle8z1e8z9VeTBVeTBWeTBYejFYfTBafzFYgDFagDJbgDBchDBagzFchTJd
hzFeiTFgizFhjDBhjjFikDJkkTJkkDJkkTJlkjFlkDFkjzBljzBjji5miy5lii1miC5khyxjhCphgydh
giVffyRffx9gfR9dexxJfiZLgyZOiyhRlipSpCtStC5Wyy9V6TFW9zVU9TdMciZOcCVNciZOdSZQdyZR
eCZReSdReydTfCdUfCdVfydUfiZWgSZVgyZXhiZZhyZaiSdbiydcjSdejihgjihejihejihfjSdfjShf
jCdfiiVgiCVfhyRfhCNegyJdgSJcgCBdfx9bfh5bfhxcexpaeRlKhCVLjCVQliZRpSdPuCpR0CtS8SxV
+jBQ+jBGbR9JcB9JbyBJcR5KcSBMdSBNdiBOeSFOeiJPeiBQeiBRfSBRfh9TgCBTgiFVhSBWhiBYiCBX
iR9YjSBbjiFbjCFajSJajSFbjSBaiiBaiiBaiB9ahh5bhh1agx1bgx1bgRxagBtbfxpafhlafBhcehha
eBhNjyZNlyRRqChSuyhR1ytS+C1V/jFP/i5Gbh5Hbh9Jbx9KciBJcR9KdCBMdiBNdyBOeSBPeh9Peh9Q
eyBRfh9RfiBSgR9UgyFVhR9ViCBYiSFYjCBZjSFcjyBcjyBdjyJbkCFcjiBejCBbjCBbih9diB9bhh1a
hRxcgx1bghpbgRxbgBpafxlafBhbehdbehdOmiVPqSdQvilR2SxR/S1V/jFL1yxGbB9Hbh9Gbh9Mch9I
cB9JcB9Kcx9MdSBMdyBOeCBNeSBPeR9QeyBQfR9RfiBSgR5SgyBVhSBWiCBYiCBXix9ZjB5cjx9cjx9d
jyFajyBcjR9bjB5bjCBbih9chx5chh1bhRxchBtbgxtZgBtbgBpbfhlcexhaexhbehdPqidRwClR2ylR
/S5U/zFLwyhGbR9FbB9GbR9JcB9Jbh5LcR9KcR9Mcx5MdSBNdyBOeCBOeiFPeh9QfB9RfSBRfiBSgR5S
gyBUgx5Whx9YiR9Xix9ZjR5bjx9cjx9dkCFajyBbjh9cjR9bjCBbih9diB9dhh1chRxbhBtbgxxbgBpb
gBpbfRlcexhcexhcexgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
</value>
</data>
</root>

View file

@ -40,8 +40,6 @@
this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem3 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripMenuItem4 = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
this.toolStripMenuItem5 = new System.Windows.Forms.ToolStripMenuItem();
this.resizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuResize = new System.Windows.Forms.ContextMenuStrip(this.components);
this.doubleToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
@ -55,8 +53,6 @@
this.topRightToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.bottomLeftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.bottomRightToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator();
this.recallLastPositionAndSizeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.chromeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.reduceToIconToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
@ -93,7 +89,7 @@
this.aboutToolStripMenuItem,
this.menuContextClose});
this.menuContext.Name = "menuContext";
this.menuContext.Size = new System.Drawing.Size(169, 274);
this.menuContext.Size = new System.Drawing.Size(169, 296);
this.menuContext.Opening += new System.ComponentModel.CancelEventHandler(this.Menu_opening);
//
// menuContextWindows
@ -161,14 +157,12 @@
this.toolStripMenuItem1,
this.toolStripMenuItem2,
this.toolStripMenuItem3,
this.toolStripMenuItem4,
this.toolStripSeparator2,
this.toolStripMenuItem5});
this.toolStripMenuItem4});
this.menuOpacity.Name = "menuOpacity";
this.menuOpacity.OwnerItem = this.menuContextOpacity;
this.menuOpacity.ShowCheckMargin = true;
this.menuOpacity.ShowImageMargin = false;
this.menuOpacity.Size = new System.Drawing.Size(154, 120);
this.menuOpacity.Size = new System.Drawing.Size(154, 114);
this.menuOpacity.Opening += new System.ComponentModel.CancelEventHandler(this.Menu_Opacity_opening);
//
// toolStripMenuItem1
@ -209,21 +203,6 @@
this.toolStripMenuItem4.ToolTipText = global::OnTopReplica.Strings.MenuOp25TT;
this.toolStripMenuItem4.Click += new System.EventHandler(this.Menu_Opacity_click);
//
// toolStripSeparator2
//
this.toolStripSeparator2.Name = "toolStripSeparator2";
this.toolStripSeparator2.Size = new System.Drawing.Size(150, 6);
//
// toolStripMenuItem5
//
this.toolStripMenuItem5.Checked = true;
this.toolStripMenuItem5.CheckState = System.Windows.Forms.CheckState.Checked;
this.toolStripMenuItem5.Name = "toolStripMenuItem5";
this.toolStripMenuItem5.Size = new System.Drawing.Size(153, 22);
this.toolStripMenuItem5.Text = global::OnTopReplica.Strings.MenuGlass;
this.toolStripMenuItem5.ToolTipText = global::OnTopReplica.Strings.MenuGlassTT;
this.toolStripMenuItem5.Click += new System.EventHandler(this.Menu_Opacity_Glass_click);
//
// resizeToolStripMenuItem
//
this.resizeToolStripMenuItem.DropDown = this.menuResize;
@ -292,9 +271,7 @@
this.topLeftToolStripMenuItem,
this.topRightToolStripMenuItem,
this.bottomLeftToolStripMenuItem,
this.bottomRightToolStripMenuItem,
this.toolStripSeparator4,
this.recallLastPositionAndSizeToolStripMenuItem});
this.bottomRightToolStripMenuItem});
this.dockToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.pos_null;
this.dockToolStripMenuItem.Name = "dockToolStripMenuItem";
this.dockToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
@ -305,7 +282,7 @@
//
this.topLeftToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.pos_topleft;
this.topLeftToolStripMenuItem.Name = "topLeftToolStripMenuItem";
this.topLeftToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.topLeftToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
this.topLeftToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuPosTopLeft;
this.topLeftToolStripMenuItem.Click += new System.EventHandler(this.Menu_Position_TopLeft);
//
@ -313,7 +290,7 @@
//
this.topRightToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.pos_topright;
this.topRightToolStripMenuItem.Name = "topRightToolStripMenuItem";
this.topRightToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.topRightToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
this.topRightToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuPosTopRight;
this.topRightToolStripMenuItem.Click += new System.EventHandler(this.Menu_Position_TopRight);
//
@ -321,7 +298,7 @@
//
this.bottomLeftToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.pos_bottomleft;
this.bottomLeftToolStripMenuItem.Name = "bottomLeftToolStripMenuItem";
this.bottomLeftToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.bottomLeftToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
this.bottomLeftToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuPosBottomLeft;
this.bottomLeftToolStripMenuItem.Click += new System.EventHandler(this.Menu_Position_BottomLeft);
//
@ -329,23 +306,10 @@
//
this.bottomRightToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.pos_bottomright;
this.bottomRightToolStripMenuItem.Name = "bottomRightToolStripMenuItem";
this.bottomRightToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.bottomRightToolStripMenuItem.Size = new System.Drawing.Size(145, 22);
this.bottomRightToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuPosBottomRight;
this.bottomRightToolStripMenuItem.Click += new System.EventHandler(this.Menu_Position_BottomRight);
//
// toolStripSeparator4
//
this.toolStripSeparator4.Name = "toolStripSeparator4";
this.toolStripSeparator4.Size = new System.Drawing.Size(214, 6);
//
// recallLastPositionAndSizeToolStripMenuItem
//
this.recallLastPositionAndSizeToolStripMenuItem.Name = "recallLastPositionAndSizeToolStripMenuItem";
this.recallLastPositionAndSizeToolStripMenuItem.Size = new System.Drawing.Size(217, 22);
this.recallLastPositionAndSizeToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuRecall;
this.recallLastPositionAndSizeToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuRecallTT;
this.recallLastPositionAndSizeToolStripMenuItem.Click += new System.EventHandler(this.Menu_Position_Recall_click);
//
// chromeToolStripMenuItem
//
this.chromeToolStripMenuItem.Name = "chromeToolStripMenuItem";
@ -453,14 +417,13 @@
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.Control;
this.ClientSize = new System.Drawing.Size(264, 204);
this.ClientSize = new System.Drawing.Size(264, 208);
this.ControlBox = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimumSize = new System.Drawing.Size(200, 210);
this.Name = "MainForm";
this.TopMost = true;
this.DoubleClick += new System.EventHandler(this.Form_doubleclick);
this.menuContext.ResumeLayout(false);
this.menuWindows.ResumeLayout(false);
this.menuOpacity.ResumeLayout(false);
@ -486,18 +449,14 @@
private System.Windows.Forms.ToolStripMenuItem aboutToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem reduceToIconToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem selectRegionToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem resizeToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem5;
private System.Windows.Forms.ToolStripMenuItem resizeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem noneToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem switchToWindowToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem dockToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem topLeftToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem topRightToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem bottomLeftToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem bottomRightToolStripMenuItem;
private System.Windows.Forms.ToolStripSeparator toolStripSeparator4;
private System.Windows.Forms.ToolStripMenuItem recallLastPositionAndSizeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem bottomRightToolStripMenuItem;
private System.Windows.Forms.ContextMenuStrip menuResize;
private System.Windows.Forms.ToolStripMenuItem doubleToolStripMenuItem1;
private System.Windows.Forms.ToolStripMenuItem fitToWindowToolStripMenuItem1;

View file

@ -10,40 +10,21 @@ namespace OnTopReplica {
public partial class MainForm : AspectRatioForm {
//Visualization status
bool _clickForwarding = false;
//GUI
ThumbnailPanel _thumbnailPanel = null;
RegionBox _regionBox = null;
FullscreenForm _fullscreenForm;
ThumbnailPanel _thumbnailPanel;
RegionBox _regionBox;
HotKeyManager _hotKeyManager;
//Window manager
WindowManager _windowManager;
WindowManager _windowManager = new WindowManager();
WindowHandle _lastWindowHandle = null;
//Override position and size on startup
bool _startOverride = false;
Point _startLocation;
Size _startSize;
public MainForm(Point location, Size size)
: this() {
_startOverride = true;
_startLocation = location;
_startSize = size;
}
public MainForm() {
InitializeComponent();
KeepAspectRatio = false;
//Thumbnail panel
_thumbnailPanel = new ThumbnailPanel(Settings.Default.UseGlass){
ClickThrough = !_clickForwarding,
_thumbnailPanel = new ThumbnailPanel {
Location = Point.Empty,
Anchor = AnchorStyles.Bottom | AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right,
Size = ClientSize
@ -65,17 +46,13 @@ namespace OnTopReplica {
_regionBox.RegionSet += new RegionBox.RegionSetHandler(RegionBox_RegionChanged);
Controls.Add(_regionBox);
//Full screen form
_fullscreenForm = new FullscreenForm();
_fullscreenForm.CloseRequest += new EventHandler<CloseRequestEventArgs>(FullscreenForm_CloseRequest);
//Set native renderer on context menus
Asztal.Szótár.NativeToolStripRenderer.SetToolStripRenderer(
menuContext, menuWindows, menuOpacity, menuResize, menuLanguages
);
//Hook keyboard handler
this.KeyUp += new KeyEventHandler(Common_Key);
this.KeyUp += new KeyEventHandler(Form_KeyUp);
this.KeyPreview = true;
//Add hotkeys
@ -86,19 +63,13 @@ namespace OnTopReplica {
#region Child forms & controls events
void FullscreenForm_CloseRequest(object sender, CloseRequestEventArgs e) {
if (_isFullscreen) {
ToggleFullscreen();
}
}
void RegionBox_RegionChanged(object sender, Rectangle region) {
_thumbnailPanel.ShownRegion = region;
_thumbnailPanel.SelectedRegion = region;
SetAspectRatio(region.Size);
}
void RegionBox_RequestRegionReset(object sender, EventArgs e) {
_thumbnailPanel.ResetShownRegion();
_thumbnailPanel.ConstrainToRegion = false;
SetAspectRatio(_thumbnailPanel.ThumbnailOriginalSize);
}
@ -107,9 +78,8 @@ namespace OnTopReplica {
}
void Thumbnail_CloneClick(object sender, CloneClickEventArgs e) {
if (_clickForwarding) {
Win32Helper.InjectFakeMouseClick(_lastWindowHandle.Handle, e.ClientClickLocation, e.IsDoubleClick);
}
//TODO: handle other mouse buttons
Win32Helper.InjectFakeMouseClick(_lastWindowHandle.Handle, e.ClientClickLocation, e.IsDoubleClick);
}
void RegionBox_RequestClosing(object sender, EventArgs e) {
@ -137,9 +107,6 @@ namespace OnTopReplica {
_regionBox.Visible = value;
_regionBox.Enabled = value;
//Disable dragging
HandleMouseMove = !value;
//Enable region drawing on thumbnail
_thumbnailPanel.DrawMouseRegions = value;
@ -161,7 +128,7 @@ namespace OnTopReplica {
};
_regionBox.Size = new Size(_regionBox.Width, ClientSize.Height);
//Check form boundaries and move form if necessary
//Check form boundaries and move form if necessary (if it crosses the right screen border)
if (value) {
var screenCurr = Screen.FromControl(this);
int pRight = Location.X + Size.Width + cWindowBoundary;
@ -191,24 +158,11 @@ namespace OnTopReplica {
protected override void OnShown(EventArgs e) {
base.OnShown(e);
//Get a window manager
_windowManager = new WindowManager();
//Platform specific form initialization
Program.Platform.InitForm(this);
//Reload position settings if needed
if (_startOverride) {
Location = _startLocation;
Size = _startSize;
}
else if (Settings.Default.WindowPositionStored) {
Location = Settings.Default.LastLocation;
ClientSize = Settings.Default.LastSize;
}
//Glassify window
SetGlass(Settings.Default.UseGlass);
GlassEnabled = true;
}
protected override void OnClosing(CancelEventArgs e) {
@ -216,15 +170,6 @@ namespace OnTopReplica {
_hotKeyManager.Dispose();
_hotKeyManager = null;
//Store position settings
if (Settings.Default.StoreWindowPosition) {
Settings.Default.WindowPositionStored = true;
Settings.Default.LastLocation = Location;
Settings.Default.LastSize = ClientSize;
}
else
Settings.Default.WindowPositionStored = false;
base.OnClosing(e);
}
@ -236,28 +181,50 @@ namespace OnTopReplica {
new Margins(-1);
}
protected override void OnActivated(EventArgs e) {
base.OnActivated(e);
protected override void OnDeactivate(EventArgs e) {
base.OnDeactivate(e);
//HACK: sometimes, even if TopMost is true, the window loses its "always on top" status.
// This is an attempt of a fix that probably won't work...
if (!IsFullscreen) { //fullscreen mode doesn't use TopMost
TopMost = true;
}
}
protected override void OnMouseWheel(MouseEventArgs e) {
base.OnMouseWheel(e);
AdjustSize(e.Delta);
int change = (int)(e.Delta / 6.0); //assumes a mouse wheel "tick" is in the 80-120 range
AdjustSize(change);
}
protected override void WndProc(ref Message m) {
if (_hotKeyManager != null)
_hotKeyManager.ProcessHotKeys(m);
base.WndProc(ref m);
switch(m.Msg){
case NativeMethods.WM_NCRBUTTONUP:
//Open context menu if right button clicked on caption (i.e. all of the window area because of glass)
if (m.WParam.ToInt32() == NativeMethods.HTCAPTION) {
menuContext.Show(MousePosition);
m.Result = IntPtr.Zero;
return;
}
break;
//Open context menu if right button clicked on caption (i.e. all of the window area because of glass)
if (m.Msg == NativeMethods.WM_NCRBUTTONUP) {
if (m.WParam.ToInt32() == NativeMethods.HTCAPTION) {
menuContext.Show(MousePosition);
}
case NativeMethods.WM_NCLBUTTONDBLCLK:
//Toggle fullscreen mode if double click on caption (whole glass area)
if (m.WParam.ToInt32() == NativeMethods.HTCAPTION) {
IsFullscreen = !IsFullscreen;
m.Result = IntPtr.Zero;
return;
}
break;
}
base.WndProc(ref m);
}
#endregion
@ -269,8 +236,8 @@ namespace OnTopReplica {
}
private void Menu_opening(object sender, CancelEventArgs e) {
//Cancel if currently "fullscreen" mode
if (_isFullscreen) {
//Cancel if currently in "fullscreen" mode
if (IsFullscreen) {
e.Cancel = true;
return;
}
@ -285,9 +252,8 @@ namespace OnTopReplica {
selectRegionToolStripMenuItem.Enabled = _thumbnailPanel.IsShowingThumbnail;
switchToWindowToolStripMenuItem.Enabled = _thumbnailPanel.IsShowingThumbnail;
resizeToolStripMenuItem.Enabled = _thumbnailPanel.IsShowingThumbnail;
chromeToolStripMenuItem.Checked = (FormBorderStyle == FormBorderStyle.SizableToolWindow);
forwardClicksToolStripMenuItem.Checked = _clickForwarding;
chromeToolStripMenuItem.Checked = (FormBorderStyle == FormBorderStyle.Sizable);
forwardClicksToolStripMenuItem.Checked = _thumbnailPanel.ReportThumbnailClicks;
}
private void Menu_Close_click(object sender, EventArgs e) {
@ -297,14 +263,13 @@ namespace OnTopReplica {
private void Menu_About_click(object sender, EventArgs e) {
this.Hide();
var box = new AboutForm();
box.Location = RecenterLocation(this, box);
box.ShowDialog();
Location = RecenterLocation(box, this);
using (var box = new AboutForm()) {
box.Location = RecenterLocation(this, box);
box.ShowDialog();
Location = RecenterLocation(box, this);
}
this.Show();
box.Dispose();
}
private void Menu_Language_click(object sender, EventArgs e) {
@ -318,27 +283,6 @@ namespace OnTopReplica {
MessageBox.Show("Error");
}
private Point RecenterLocation(Control original, Control final) {
int origX = original.Location.X + original.Size.Width / 2;
int origY = original.Location.Y + original.Size.Height / 2;
int finX = origX - final.Size.Width / 2;
int finY = origY - final.Size.Height / 2;
//Check boundaries
var screen = Screen.FromControl(final);
if (finX < screen.WorkingArea.X)
finX = screen.WorkingArea.X;
if (finX + final.Size.Width > screen.WorkingArea.Width)
finX = screen.WorkingArea.Width - final.Size.Width;
if (finY < screen.WorkingArea.Y)
finY = screen.WorkingArea.Y;
if (finY + final.Size.Height > screen.WorkingArea.Height)
finY = screen.WorkingArea.Height - final.Size.Height;
return new Point(finX, finY);
}
void Menu_Windows_itemclick(object sender, EventArgs e) {
//Ensure the menu is closed
menuContext.Close();
@ -362,27 +306,22 @@ namespace OnTopReplica {
if (_lastWindowHandle == null)
return;
Program.Platform.HideForm(this);
NativeMethods.SetForegroundWindow(_lastWindowHandle.Handle);
this.Hide();
}
private void Menu_Forward_click(object sender, EventArgs e) {
if (Settings.Default.FirstTimeClickForwarding && !_clickForwarding) {
TaskDialog dlg = new TaskDialog(Strings.InfoClickForwarding,
Strings.InfoClickForwardingTitle, Strings.InfoClickForwardingContent);
dlg.CommonButtons = TaskDialogButton.Yes | TaskDialogButton.No;
Results result = dlg.Show(this);
if (result.CommonButton == Result.No)
if (Settings.Default.FirstTimeClickForwarding && !_thumbnailPanel.ReportThumbnailClicks) {
TaskDialog dlg = new TaskDialog(Strings.InfoClickForwarding, Strings.InfoClickForwardingTitle, Strings.InfoClickForwardingContent) {
CommonButtons = TaskDialogButton.Yes | TaskDialogButton.No
};
if (dlg.Show(this).CommonButton == Result.No)
return;
Settings.Default.FirstTimeClickForwarding = false;
}
_clickForwarding = !_clickForwarding;
_thumbnailPanel.ClickThrough = !_clickForwarding;
_thumbnailPanel.ReportThumbnailClicks = !_thumbnailPanel.ReportThumbnailClicks;
}
private void Menu_Opacity_opening(object sender, CancelEventArgs e) {
@ -399,9 +338,6 @@ namespace OnTopReplica {
else
i.Checked = false;
}
//Glass state
toolStripMenuItem5.Checked = Settings.Default.UseGlass;
}
private void Menu_Opacity_click(object sender, EventArgs e) {
@ -414,10 +350,6 @@ namespace OnTopReplica {
}
}
private void Menu_Opacity_Glass_click(object sender, EventArgs e) {
SetGlass(!Settings.Default.UseGlass);
}
private void Menu_Region_click(object sender, EventArgs e) {
RegionBoxShowing = true;
}
@ -425,8 +357,6 @@ namespace OnTopReplica {
private void Menu_Resize_opening(object sender, CancelEventArgs e) {
if (!_thumbnailPanel.IsShowingThumbnail)
e.Cancel = true;
recallLastPositionAndSizeToolStripMenuItem.Checked = Settings.Default.StoreWindowPosition;
}
private void Menu_Resize_Double(object sender, EventArgs e) {
@ -446,11 +376,7 @@ namespace OnTopReplica {
}
private void Menu_Resize_Fullscreen(object sender, EventArgs e) {
ToggleFullscreen();
}
private void Menu_Position_Recall_click(object sender, EventArgs e) {
Settings.Default.StoreWindowPosition = !Settings.Default.StoreWindowPosition;
IsFullscreen = true;
}
private void Menu_Position_TopLeft(object sender, EventArgs e) {
@ -489,27 +415,9 @@ namespace OnTopReplica {
);
}
private int ChromeBorderVertical {
get {
if (FormBorderStyle == FormBorderStyle.SizableToolWindow)
return SystemInformation.FrameBorderSize.Height;
else
return 0;
}
}
private int ChromeBorderHorizontal {
get {
if (FormBorderStyle == FormBorderStyle.SizableToolWindow)
return SystemInformation.FrameBorderSize.Width;
else
return 0;
}
}
private void Menu_Reduce_click(object sender, EventArgs e) {
//Hide form
this.Hide();
//Hide form in a platform specific way
Program.Platform.HideForm(this);
}
private void Menu_Windows_opening(object sender, EventArgs e) {
@ -520,7 +428,7 @@ namespace OnTopReplica {
}
private void Menu_Chrome_click(object sender, EventArgs e) {
if (FormBorderStyle == FormBorderStyle.SizableToolWindow) {
if (FormBorderStyle == FormBorderStyle.Sizable) {
FormBorderStyle = FormBorderStyle.None;
Location = new Point {
X = Location.X + SystemInformation.FrameBorderSize.Width,
@ -528,7 +436,7 @@ namespace OnTopReplica {
};
}
else {
FormBorderStyle = FormBorderStyle.SizableToolWindow;
FormBorderStyle = FormBorderStyle.Sizable;
Location = new Point {
X = Location.X - SystemInformation.FrameBorderSize.Width,
Y = Location.Y - SystemInformation.FrameBorderSize.Height
@ -542,16 +450,12 @@ namespace OnTopReplica {
#region Event handling
private void Form_doubleclick(object sender, EventArgs e) {
if(_thumbnailPanel.IsShowingThumbnail)
ToggleFullscreen();
}
void Common_Key(object sender, KeyEventArgs e) {
void Form_KeyUp(object sender, KeyEventArgs e) {
//ALT
if (e.Modifiers == Keys.Alt) {
if (e.KeyCode == Keys.Enter) {
e.Handled = true;
ToggleFullscreen();
IsFullscreen = !IsFullscreen;
}
else if (e.KeyCode == Keys.D1 || e.KeyCode == Keys.NumPad1) {
@ -570,14 +474,26 @@ namespace OnTopReplica {
FitToThumbnail(2.0);
}
}
//ESCAPE
else if (e.KeyCode == Keys.Escape) {
//Toggle fullscreen
if (IsFullscreen) {
IsFullscreen = false;
}
//Disable click forwarding
else if (_thumbnailPanel.ReportThumbnailClicks) {
_thumbnailPanel.ReportThumbnailClicks = false;
}
}
}
void HotKeyOpenHandler() {
if (_isFullscreen)
ToggleFullscreen();
if (IsFullscreen)
IsFullscreen = false;
if (this.Visible) {
this.Hide();
if (Visible && WindowState != FormWindowState.Minimized) {
Program.Platform.HideForm(this);
}
else {
EnsureMainFormVisible();
@ -588,44 +504,40 @@ namespace OnTopReplica {
#region Fullscreen
bool _isFullscreen = false;
private void ToggleFullscreen() {
if (_isFullscreen) {
//Update thumbnail
if (_fullscreenForm.LastWindowHandle != null) {
StoredRegion region = null;
if(_fullscreenForm.ShowRegion)
region = new StoredRegion { Rect = _fullscreenForm.ShownRegion };
bool _isFullscreen = false;
Point _preFullscreenLocation;
Size _preFullscreenSize;
ThumbnailSet(_fullscreenForm.LastWindowHandle, region);
public bool IsFullscreen {
get {
return _isFullscreen;
}
set {
if (IsFullscreen == value)
return;
RegionBoxShowing = false; //on switch, always hide region box
GlassEnabled = !value;
FormBorderStyle = (value) ? FormBorderStyle.None : FormBorderStyle.Sizable;
TopMost = !value;
//Location and size
if (value) {
_preFullscreenLocation = Location;
_preFullscreenSize = Size;
var currentScreen = Screen.FromControl(this);
Size = currentScreen.WorkingArea.Size;
Location = currentScreen.WorkingArea.Location;
}
else {
Location = _preFullscreenLocation;
Size = _preFullscreenSize;
}
else
ThumbnailUnset();
//Update properties
this.Opacity = _fullscreenForm.Opacity;
_fullscreenForm.Hide();
this.Show();
}
else {
if (_lastWindowHandle == null) {
//Should not happen... if it does, do nothing
return;
}
_fullscreenForm.DisplayFullscreen(Screen.FromControl(this), _lastWindowHandle);
_fullscreenForm.ShownRegion = _thumbnailPanel.ShownRegion;
_fullscreenForm.ShowRegion = _thumbnailPanel.ShowRegion;
_fullscreenForm.Opacity = this.Opacity;
_fullscreenForm.Show();
this.Hide();
}
_isFullscreen = !_isFullscreen;
}
_isFullscreen = value;
}
}
#endregion
@ -649,10 +561,6 @@ namespace OnTopReplica {
//Set aspect ratio (this will resize the form)
SetAspectRatio(_thumbnailPanel.ThumbnailOriginalSize);
//GUI
selectRegionToolStripMenuItem.Enabled = true;
resizeToolStripMenuItem.Enabled = true;
}
private void ThumbnailUnset(){
@ -674,17 +582,14 @@ namespace OnTopReplica {
ThumbnailUnset();
}
/// <summary>Automatically sizes the window in order to accomodate the thumbnail p times.</summary>
/// <param name="p">Scale of the thumbnail to consider.</param>
private void FitToThumbnail(double p) {
try {
Size originalSize = _thumbnailPanel.ThumbnailOriginalSize;
Size fittedSize = new Size((int)(originalSize.Width * p), (int)(originalSize.Height * p));
this.ClientSize = fittedSize;
ClientSize = fittedSize;
}
catch (Exception ex) {
ThumbnailError(ex, false, Strings.ErrorUnableToFit);
@ -695,41 +600,77 @@ namespace OnTopReplica {
#region GUI stuff
/// <summary>Do whatever needed to set the "glass" effect to the desired state.</summary>
protected void SetGlass(bool b) {
this.GlassEnabled = b;
_thumbnailPanel.GlassMode = b;
_regionBox.GlassMode = b;
private Point RecenterLocation(Control original, Control final) {
int origX = original.Location.X + original.Size.Width / 2;
int origY = original.Location.Y + original.Size.Height / 2;
this.Invalidate();
int finX = origX - final.Size.Width / 2;
int finY = origY - final.Size.Height / 2;
//Store
Settings.Default.UseGlass = b;
}
//Check boundaries
var screen = Screen.FromControl(final);
if (finX < screen.WorkingArea.X)
finX = screen.WorkingArea.X;
if (finX + final.Size.Width > screen.WorkingArea.Width)
finX = screen.WorkingArea.Width - final.Size.Width;
if (finY < screen.WorkingArea.Y)
finY = screen.WorkingArea.Y;
if (finY + final.Size.Height > screen.WorkingArea.Height)
finY = screen.WorkingArea.Height - final.Size.Height;
return new Point(finX, finY);
}
private int ChromeBorderVertical {
get {
if (FormBorderStyle == FormBorderStyle.Sizable)
return SystemInformation.FrameBorderSize.Height;
else
return 0;
}
}
private int ChromeBorderHorizontal {
get {
if (FormBorderStyle == FormBorderStyle.Sizable)
return SystemInformation.FrameBorderSize.Width;
else
return 0;
}
}
/// <summary>
/// Displays an error task dialog.
/// </summary>
/// <param name="mainInstruction">Main instruction of the error dialog.</param>
/// <param name="explanation">Detailed informations about the error.</param>
/// <param name="errorMessage">Expanded error codes/messages.</param>
private void ShowErrorDialog(string mainInstruction, string explanation, string errorMessage) {
TaskDialog dlg = new TaskDialog(mainInstruction, Strings.ErrorGenericTitle, explanation);
dlg.CommonIcon = TaskDialogIcon.Stop;
dlg.IsExpanded = false;
TaskDialog dlg = new TaskDialog(mainInstruction, Strings.ErrorGenericTitle, explanation) {
CommonIcon = TaskDialogIcon.Stop,
IsExpanded = false
};
if (!string.IsNullOrEmpty(errorMessage)) {
dlg.ExpandedInformation = Strings.ErrorGenericInfoText + errorMessage;
dlg.ExpandedControlText = Strings.ErrorGenericInfoButton;
}
dlg.Show(this.Handle);
dlg.Show(this);
}
/// <summary>
/// Ensures that the main form is visible (either closing the fullscreen mode or reactivating from task icon).
/// </summary>
public void EnsureMainFormVisible() {
if (_isFullscreen)
ToggleFullscreen();
if (IsFullscreen)
IsFullscreen = false;
//Ensure main form is shown
this.Show();
this.Activate();
this.TopMost = true;
WindowState = FormWindowState.Normal;
Show();
Activate();
TopMost = true;
}
/// <summary>
@ -763,7 +704,6 @@ namespace OnTopReplica {
Location = nuLoc;
Size = MinimumSize;
_fullscreenForm.Hide();
this.Show();
this.Activate();
}

View file

@ -274,6 +274,10 @@ namespace OnTopReplica
public const int MK_LBUTTON = 0x0001;
public const int WM_SYSCOMMAND = 0x0112;
public const int SC_MAXIMIZE = 61458;
public const int SC_RESTORE = 61490;
public static IntPtr MakeLParam(int LoWord, int HiWord) {
return new IntPtr((HiWord << 16) | (LoWord & 0xffff));
}

View file

@ -107,9 +107,6 @@
<Compile Include="AspectRatioForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ClickThroughLabel.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="CloneClickEventArgs.cs" />
<Compile Include="CloseRequestEventArgs.cs" />
<Compile Include="WindowsSevenMethods.cs" />
@ -140,12 +137,6 @@
<Compile Include="FocusedTextBox.cs">
<SubType>Component</SubType>
</Compile>
<None Include="FullscreenForm.cs">
<SubType>Form</SubType>
</None>
<None Include="FullscreenForm.Designer.cs">
<DependentUpon>FullscreenForm.cs</DependentUpon>
</None>
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
@ -173,9 +164,6 @@
<LastGenOutput>Strings.it.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<None Include="FullscreenForm.resx">
<DependentUpon>FullscreenForm.cs</DependentUpon>
</None>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
<SubType>Designer</SubType>

View file

@ -32,11 +32,14 @@ namespace OnTopReplica {
public abstract bool CheckCompatibility();
/// <summary>
/// Initialized the application. Called once in the app lifetime.
/// Initializes the application. Called once in the app lifetime.
/// </summary>
public virtual void InitApp() {
}
/// <summary>
/// Gets the main OnTopReplica form.
/// </summary>
protected MainForm Form { get; private set; }
/// <summary>
@ -50,6 +53,14 @@ namespace OnTopReplica {
public virtual void ShutdownApp() {
}
/// <summary>
/// Hides a form in a way that it can be restored later by the user.
/// </summary>
/// <param name="form">Form to hide.</param>
public virtual void HideForm(MainForm form) {
form.Hide();
}
#region IDisposable Members
bool _isDisposed = false;

View file

@ -23,5 +23,9 @@ namespace OnTopReplica.Platforms {
//do nothing
}
public override void HideForm(MainForm form) {
form.WindowState = FormWindowState.Minimized;
}
}
}

View file

@ -39,7 +39,7 @@ namespace OnTopReplica {
Settings.Default.MustUpdate = false;
}
bool reloadSettings = false;
bool mustReloadForm = false;
Point reloadLocation = new Point();
Size reloadSize = new Size();
@ -49,15 +49,16 @@ namespace OnTopReplica {
Settings.Default.Language = _languageChangeCode;
_languageChangeCode = null;
Form form;
if (reloadSettings)
form = new MainForm(reloadLocation, reloadSize);
else
form = new MainForm();
Form form = new MainForm();
if (mustReloadForm) {
form.Location = reloadLocation;
form.Size = reloadSize;
}
Application.Run(form);
reloadSettings = true;
//Enable reloading on next loop
mustReloadForm = true;
reloadLocation = form.Location;
reloadSize = form.Size;
}

View file

@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4927
// Runtime Version:4.0.30319.1
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@ -12,7 +12,7 @@ namespace OnTopReplica.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@ -34,18 +34,6 @@ namespace OnTopReplica.Properties {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool UseGlass {
get {
return ((bool)(this["UseGlass"]));
}
set {
this["UseGlass"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
@ -70,54 +58,6 @@ namespace OnTopReplica.Properties {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0, 0")]
public global::System.Drawing.Point LastLocation {
get {
return ((global::System.Drawing.Point)(this["LastLocation"]));
}
set {
this["LastLocation"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0, 0")]
public global::System.Drawing.Size LastSize {
get {
return ((global::System.Drawing.Size)(this["LastSize"]));
}
set {
this["LastSize"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool WindowPositionStored {
get {
return ((bool)(this["WindowPositionStored"]));
}
set {
this["WindowPositionStored"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool StoreWindowPosition {
get {
return ((bool)(this["StoreWindowPosition"]));
}
set {
this["StoreWindowPosition"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("(Default)")]

View file

@ -5,27 +5,12 @@
<Setting Name="SavedRegions" Type="OnTopReplica.StoredRegionArray" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="UseGlass" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="AutoFitOnResize" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
<Setting Name="Opacity" Type="System.Byte" Scope="User">
<Value Profile="(Default)">255</Value>
</Setting>
<Setting Name="LastLocation" Type="System.Drawing.Point" Scope="User">
<Value Profile="(Default)">0, 0</Value>
</Setting>
<Setting Name="LastSize" Type="System.Drawing.Size" Scope="User">
<Value Profile="(Default)">0, 0</Value>
</Setting>
<Setting Name="WindowPositionStored" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="StoreWindowPosition" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="Language" Type="System.Globalization.CultureInfo" Scope="User">
<Value Profile="(Default)">(Default)</Value>
</Setting>

View file

@ -13,106 +13,58 @@ namespace OnTopReplica {
//DWM Thumbnail stuff
Thumbnail _thumbnail = null;
bool _regionEnabled = false;
Rectangle _regionCurrent;
//Labels
ClickThroughLabel _labelNoGlass;
ThemedLabel _labelGlass;
public ThumbnailPanel()
: this(false) {
}
/// <summary>Constructs a new ThumbnailPanel with a given glass mode value.</summary>
/// <param name="enableGlass">True if glass should be enabled.</param>
public ThumbnailPanel(bool enableGlass) {
public ThumbnailPanel() {
InitFormComponents();
GlassMode = enableGlass;
UpdateRightClickLabels();
}
private void InitFormComponents() {
BackColor = Color.Black;
//Themed Label
_labelGlass = new ThemedLabel();
_labelGlass.Dock = DockStyle.Fill;
_labelGlass.ForeColor = SystemColors.ControlText;
_labelGlass.Location = Point.Empty;
_labelGlass.Size = ClientSize;
_labelGlass.Name = "labelGlass";
_labelGlass.Text = Strings.RightClick;
_labelGlass.TextAlign = HorizontalAlignment.Center;
_labelGlass.TextAlignVertical = VerticalAlignment.Center;
_labelGlass = new ThemedLabel {
Dock = DockStyle.Fill,
ForeColor = SystemColors.ControlText,
Location = Point.Empty,
Size = ClientSize,
Name = "labelGlass",
Text = Strings.RightClick,
TextAlign = HorizontalAlignment.Center,
TextAlignVertical = VerticalAlignment.Center
};
this.Controls.Add(_labelGlass);
//Standard label
_labelNoGlass = new ClickThroughLabel();
_labelNoGlass.Dock = DockStyle.Fill;
_labelNoGlass.BackColor = Color.Transparent;
_labelNoGlass.Location = Point.Empty;
_labelNoGlass.Size = ClientSize;
_labelNoGlass.Name = "labelNoGlass";
_labelNoGlass.Text = Strings.RightClick;
_labelNoGlass.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.Controls.Add(_labelNoGlass);
}
#region Settings
bool _glassMode = true;
public bool GlassMode {
get {
return _glassMode;
}
set {
_glassMode = value;
UpdateBackColor();
UpdateRightClickLabels();
}
}
bool _fullscreenMode = false;
public bool FullscreenMode {
get {
return _fullscreenMode;
}
set {
_fullscreenMode = value;
UpdateBackColor();
UpdateRightClickLabels();
}
}
#region Properties and settings
/// <summary>
/// Gets or sets the region that is currently shown on the thumbnail. When set, enabled region showing.
/// Gets or sets the region that is currently shown on the thumbnail. When set, also enabled region constrain.
/// </summary>
public Rectangle ShownRegion {
public Rectangle SelectedRegion {
get {
return _regionCurrent;
}
set {
_regionEnabled = true;
_regionCurrent = value;
UpdateThubmnail();
ConstrainToRegion = true;
}
}
bool _regionEnabled = false;
/// <summary>
/// Gets or sets whether the thumbnail is constrained to a region or not.
/// </summary>
public bool ShowRegion {
public bool ConstrainToRegion {
get {
return _regionEnabled;
}
set {
_regionEnabled = value;
UpdateThubmnail();
}
}
@ -120,7 +72,7 @@ namespace OnTopReplica {
bool _drawMouseRegions = false;
/// <summary>
/// Gets or sets whether the thumbnail allows region drawing.
/// Gets or sets whether the control is is "region drawing" mode and reports them via events.
/// </summary>
public bool DrawMouseRegions {
get {
@ -134,36 +86,69 @@ namespace OnTopReplica {
//Cursor change
Cursor = (value) ? Cursors.Cross : Cursors.Default;
//Refresh gui
UpdateThubmnail();
_labelGlass.Visible = !value;
this.Invalidate();
}
}
private byte ThumbnailOpacity {
/// <summary>
/// Gets the target opacity of the thumbnail, depending on the control's state.
/// </summary>
protected byte ThumbnailOpacity {
get {
return (_drawMouseRegions) ? (byte)130 : (byte)255;
}
}
bool _clickThrough = true;
/// <summary>
/// Gets or sets whether the control should report clicks made on the cloned thumbnail.
/// </summary>
public bool ReportThumbnailClicks {
get;
set;
}
public bool ClickThrough {
get {
return _clickThrough;
}
set {
_clickThrough = value;
}
}
/// <summary>
/// Gets the thumbnail's original size.
/// </summary>
public Size ThumbnailOriginalSize {
get {
if (_thumbnail != null && !_thumbnail.IsInvalid)
return (_regionEnabled) ? _regionCurrent.Size : _thumbnail.SourceSize;
else
throw new Exception(Strings.ErrorNoThumbnail);
}
}
#endregion
public void ResetShownRegion() {
_regionEnabled = false;
#region GUI event handling
UpdateThubmnail();
}
protected override void OnResize(EventArgs eventargs) {
base.OnResize(eventargs);
UpdateThubmnail();
}
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
//Make transparent to hit-testing if clicks must not be registered
if (m.Msg == NativeMethods.WM_NCHITTEST && m.Result.ToInt32() == NativeMethods.HTCLIENT &&
!DrawMouseRegions && !ReportThumbnailClicks) {
m.Result = new IntPtr(NativeMethods.HTTRANSPARENT);
}
}
#endregion
#region Thumbnail interface
/// <summary>
/// Creates a new thumbnail of a certain window.
/// </summary>
/// <param name="handle">Handle of the window to clone.</param>
public void SetThumbnailHandle(WindowHandle handle) {
if (_thumbnail != null && !_thumbnail.IsInvalid)
_thumbnail.Close();
@ -171,133 +156,129 @@ namespace OnTopReplica {
//Get form and register thumbnail on it
Form owner = this.TopLevelControl as Form;
if(owner == null)
throw new Exception();
//Reset region
_regionEnabled = false;
throw new Exception("Internal error: ThumbnailPanel.TopLevelControl is not a Form.");
_thumbnail = DwmManager.Register(owner, handle.Handle);
//Do empty thumbnail update to init DWM info (source size)
_thumbnail.Update(ClientRectangle, (byte)255, true, true);
//Correct update
UpdateThubmnail();
ConstrainToRegion = false; //this also invokes a thumbnail update
}
/// <summary>
/// Disposes current thumbnail and enters stand-by mode.
/// </summary>
public void UnsetThumbnail() {
if (_thumbnail != null && !_thumbnail.IsInvalid)
_thumbnail.Close();
_thumbnail = null;
UpdateRightClickLabels();
}
/// <summary>
/// Gets whether the control is currently displaying a thumbnail.
/// </summary>
public bool IsShowingThumbnail {
get {
return (_thumbnail != null && !_thumbnail.IsInvalid);
}
}
int padWidth = 0;
int padHeight = 0;
Size thumbnailSize;
int _padWidth = 0;
int _padHeight = 0;
Size _thumbnailSize;
/// <summary>Updates the thumbnail options and the right-click labels.</summary>
/// <summary>
/// Updates the thumbnail options and the right-click label.
/// </summary>
private void UpdateThubmnail() {
if (_thumbnail != null && !_thumbnail.IsInvalid){
try {
Size sourceSize = (_regionEnabled) ? _regionCurrent.Size : _thumbnail.SourceSize;
thumbnailSize = ComputeIdealSize(sourceSize, Size);
padHeight = (Size.Height - thumbnailSize.Height) / 2;
Size sourceSize = ThumbnailOriginalSize;
_thumbnailSize = ComputeIdealSize(sourceSize, Size);
_padHeight = (Size.Height - _thumbnailSize.Height) / 2;
var target = new Rectangle(0, padHeight, thumbnailSize.Width, thumbnailSize.Height);
var target = new Rectangle(0, _padHeight, _thumbnailSize.Width, _thumbnailSize.Height);
Rectangle source = (_regionEnabled) ? _regionCurrent : new Rectangle(Point.Empty, _thumbnail.SourceSize);
_thumbnail.Update(target, source, ThumbnailOpacity, true, true);
}
catch {
//Any error updating the thumbnail forces to unset (handle may be not valid)
//Any error updating the thumbnail forces to unset (handle may not be valid anymore)
UnsetThumbnail();
return;
}
}
UpdateRightClickLabels();
}
/// <summary>Computes ideal thumbnail size given an original size and a target to fit.</summary>
/// <param name="sourceSize">Size of the original thumbnail.</param>
/// <param name="clientSize">Size of the client area to fit.</param>
private Size ComputeIdealSize(Size sourceSize, Size clientSize) {
double sourceRatio = (double)sourceSize.Width / (double)sourceSize.Height;
double clientRatio = (double)clientSize.Width / (double)clientSize.Height;
Size ret = new Size(clientSize.Width, (int)((double)clientSize.Width / sourceRatio));
return ret;
}
/// <summary>
/// Updates the background color.
/// Computes ideal thumbnail size given an original size and a target to fit.
/// </summary>
private void UpdateBackColor() {
BackColor = (FullscreenMode || GlassMode) ? Color.Black : SystemColors.Control;
/// <param name="sourceSize">Size of the original thumbnail.</param>
/// <param name="clientSize">Size of the client area to fit.</param>
private Size ComputeIdealSize(Size sourceSize, Size clientSize) {
double sourceRatio = (double)sourceSize.Width / (double)sourceSize.Height;
double clientRatio = (double)clientSize.Width / (double)clientSize.Height;
Size ret = new Size(clientSize.Width, (int)((double)clientSize.Width / sourceRatio));
//TODO: enable width padding if width > height
return ret;
}
/// <summary>Updates the right-click labels.</summary>
/// <remarks>If a thumbnail is shown no label will be visible. If no thumbnail is active, the correct label will be visible.</remarks>
private void UpdateRightClickLabels(){
if (_thumbnail != null && !_thumbnail.IsInvalid) {
//Thumbnail active and no region drawing
_labelGlass.Visible = false;
_labelNoGlass.Visible = false;
}
else {
//Update visibility
_labelGlass.Visible = _glassMode;
_labelNoGlass.Visible = !_glassMode;
}
}
#endregion
#region Event handling
#region Region drawing
protected override void OnResize(EventArgs eventargs) {
UpdateThubmnail();
//Set if currently drawing a window (first click/drag was initiated)
bool _drawingRegion = false;
//Set if drawing was suspended because the mouse left the control
bool _drawingSuspended = false;
Point _regionStartPoint;
Point _regionLastPoint;
base.OnResize(eventargs);
}
public delegate void RegionDrawnHandler(object sender, Rectangle region);
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
public event RegionDrawnHandler RegionDrawn;
//Make transparent to hit-testing
if (m.Msg == NativeMethods.WM_NCHITTEST && m.Result.ToInt32() == 1 &&
!DrawMouseRegions && ClickThrough) {
m.Result = new IntPtr(NativeMethods.HTTRANSPARENT);
}
}
protected virtual void OnRegionDrawn(Rectangle region) {
//Fix region if necessary (bug report by Gunter, via comment)
if (region.Width < 1) region.Width = 1;
if (region.Height < 1) region.Height = 1;
protected override void OnMouseClick(MouseEventArgs e) {
//Raise clicking event to allow click forwarding
if (!_clickThrough && e.Button == MouseButtons.Left) {
if(_thumbnail != null)
OnCloneClick(ScreenToThumbnail(e.Location), false);
}
var evt = RegionDrawn;
if (evt != null)
evt(this, region);
}
base.OnMouseClick(e);
}
/// <summary>
/// Raises a RegionDrawn event, given a starting and an ending point of the drawn region.
/// </summary>
protected void RaiseRegionDrawn(Point start, Point end) {
if (_thumbnailSize.Width < 1 || _thumbnailSize.Height < 1) //causes DivBy0
return;
protected override void OnMouseDoubleClick(MouseEventArgs e) {
//Raise double clicking event to allow click forwarding
if (!_clickThrough && e.Button == MouseButtons.Left) {
if (_thumbnail != null)
OnCloneClick(ScreenToThumbnail(e.Location), true);
}
//Compute bounds
int left = Math.Min(start.X, end.X);
int right = Math.Max(start.X, end.X);
int top = Math.Min(start.Y, end.Y);
int bottom = Math.Max(start.Y, end.Y);
base.OnMouseDoubleClick(e);
}
//Clip to boundaries
left = Math.Max(0, left);
right = Math.Min(_thumbnailSize.Width, right);
top = Math.Max(0, top);
bottom = Math.Min(_thumbnailSize.Height, bottom);
//Compute region rectangle in thumbnail coordinates
var startPoint = ClientToThumbnail(new Point(left, top));
var endPoint = ClientToThumbnail(new Point(right, bottom));
var final = new Rectangle(
startPoint,
new Size(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y)
);
//Update region
SelectedRegion = final;
OnRegionDrawn(final);
}
protected override void OnMouseDown(MouseEventArgs e) {
if (DrawMouseRegions && e.Button == MouseButtons.Left) {
@ -317,7 +298,7 @@ namespace OnTopReplica {
//Region completed
_drawingRegion = false;
_drawingSuspended = false;
HandleRegionDrawn(_regionStartPoint, _regionLastPoint);
RaiseRegionDrawn(_regionStartPoint, _regionLastPoint);
this.Invalidate();
}
@ -381,109 +362,69 @@ namespace OnTopReplica {
#endregion
//Set if currently drawing a window (first click/drag was initiated)
bool _drawingRegion = false;
//Set if drawing was suspended because the mouse left the control
bool _drawingSuspended = false;
Point _regionStartPoint;
Point _regionLastPoint;
#region Thumbnail clone click
public delegate void RegionDrawnHandler(object sender, Rectangle region);
protected override void OnMouseClick(MouseEventArgs e) {
base.OnMouseClick(e);
public event RegionDrawnHandler RegionDrawn;
protected virtual void OnRegionDrawn(Rectangle region) {
//Fix region if necessary (bug report by Gunter, via comment)
if (region.Width < 1) region.Width = 1;
if (region.Height < 1) region.Height = 1;
var evt = RegionDrawn;
if (evt != null)
evt(this, region);
}
protected Point ScreenToThumbnail(Point position) {
//Compensate padding
position.X -= padWidth;
position.Y -= padHeight;
PointF proportionalPosition = new PointF(
(float)position.X / thumbnailSize.Width,
(float)position.Y / thumbnailSize.Height
);
//Get real pixel region info
Size source = (_regionEnabled) ? _regionCurrent.Size : _thumbnail.SourceSize;
Point offset = (_regionEnabled) ? _regionCurrent.Location : Point.Empty;
return new Point(
(int)((proportionalPosition.X * source.Width) + offset.X),
(int)((proportionalPosition.Y * source.Height) + offset.Y)
);
}
protected void HandleRegionDrawn(Point start, Point end) {
if (thumbnailSize.Width == 0 || thumbnailSize.Height == 0) //causes DivBy0
if (_thumbnail == null)
return;
int left = Math.Min(start.X, end.X);
int right = Math.Max(start.X, end.X);
int top = Math.Min(start.Y, end.Y);
int bottom = Math.Max(start.Y, end.Y);
//Raise clicking event to allow click forwarding
if (ReportThumbnailClicks) {
OnCloneClick(ClientToThumbnail(e.Location), e.Button, false);
}
}
//Clip to boundaries
left = Math.Max(0, left);
right = Math.Min(thumbnailSize.Width, right);
top = Math.Max(0, top);
bottom = Math.Min(thumbnailSize.Height, bottom);
protected override void OnMouseDoubleClick(MouseEventArgs e) {
base.OnMouseDoubleClick(e);
//Offset points of padding space around thumbnail
left -= padWidth;
right -= padWidth;
top -= padHeight;
bottom -= padHeight;
if (_thumbnail == null)
return;
//Get proportional region on thumbnail size
RectangleF region = new RectangleF(
(float)left / thumbnailSize.Width,
(float)top / thumbnailSize.Height,
(float)(right - left) / thumbnailSize.Width,
(float)(bottom - top) / thumbnailSize.Height
);
//Compute real pixel-region
Size source = (_regionEnabled) ? _regionCurrent.Size : _thumbnail.SourceSize;
Point offset = (_regionEnabled) ? _regionCurrent.Location : Point.Empty;
Rectangle regionPixel = new Rectangle(
(int)(region.Left * source.Width) + offset.X,
(int)(region.Top * source.Height) + offset.Y,
(int)(region.Width * source.Width),
(int)(region.Height * source.Height)
);
//Update region
ShownRegion = regionPixel;
//Report to hooked event handlers that the current region has changed
OnRegionDrawn(regionPixel);
}
public Size ThumbnailOriginalSize {
get {
if (_thumbnail != null && !_thumbnail.IsInvalid)
return (_regionEnabled) ? _regionCurrent.Size : _thumbnail.SourceSize;
else
throw new Exception(Strings.ErrorNoThumbnail);
}
}
//Raise double clicking event to allow click forwarding
if (ReportThumbnailClicks) {
OnCloneClick(ClientToThumbnail(e.Location), e.Button, true);
}
}
/// <summary>
/// Is raised when the thumbnail clone is clicked.
/// </summary>
public event EventHandler<CloneClickEventArgs> CloneClick;
protected virtual void OnCloneClick(Point location, bool doubleClick){
if(CloneClick != null)
CloneClick(this, new CloneClickEventArgs(location, doubleClick));
}
}
protected virtual void OnCloneClick(Point location, MouseButtons buttons, bool doubleClick){
var evt = CloneClick;
if(evt != null)
evt(this, new CloneClickEventArgs(location, buttons, doubleClick));
}
#endregion
/// <summary>
/// Convert a point in client coordinates to a point expressed in terms of a cloned thumbnail window.
/// </summary>
/// <param name="position">Point in client coordinates.</param>
protected Point ClientToThumbnail(Point position) {
//Compensate padding
position.X -= _padWidth;
position.Y -= _padHeight;
PointF proportionalPosition = new PointF(
(float)position.X / _thumbnailSize.Width,
(float)position.Y / _thumbnailSize.Height
);
//Get real pixel region info
Size source = (_regionEnabled) ? _regionCurrent.Size : _thumbnail.SourceSize;
Point offset = (_regionEnabled) ? _regionCurrent.Location : Point.Empty;
return new Point(
(int)((proportionalPosition.X * source.Width) + offset.X),
(int)((proportionalPosition.Y * source.Height) + offset.Y)
);
}
}
}

View file

@ -4,6 +4,7 @@ using System.Text;
using System.Drawing;
namespace OnTopReplica {
/// <summary>Helper class that keeps a window handle (HWND), the title of the window and can load its icon.</summary>
public class WindowHandle : System.Windows.Forms.IWin32Window {
IntPtr _handle;
@ -77,5 +78,6 @@ namespace OnTopReplica {
}
#endregion
}
}

View file

@ -5,7 +5,8 @@ using System.Text;
namespace OnTopReplica {
/// <summary>A helper class that allows you to easily build and keep a list of Windows (in the form of WindowHandle objects).</summary>
public class WindowManager {
List<WindowHandle> _windows = null;
List<WindowHandle> _windows = new List<WindowHandle>();
public enum EnumerationMode {
/// <summary>All windows with 'Visible' flag.</summary>
@ -18,14 +19,6 @@ namespace OnTopReplica {
TaskWindows
}
public WindowManager() {
Refresh(EnumerationMode.AllTopLevel);
}
public WindowManager(EnumerationMode mode) {
Refresh(mode);
}
/// <summary>Refreshes the window list.</summary>
public void Refresh(EnumerationMode mode) {
_windows = new List<WindowHandle>();

View file

@ -7,27 +7,12 @@
</configSections>
<userSettings>
<OnTopReplica.Properties.Settings>
<setting name="UseGlass" serializeAs="String">
<value>True</value>
</setting>
<setting name="AutoFitOnResize" serializeAs="String">
<value>True</value>
</setting>
<setting name="Opacity" serializeAs="String">
<value>255</value>
</setting>
<setting name="LastLocation" serializeAs="String">
<value>0, 0</value>
</setting>
<setting name="LastSize" serializeAs="String">
<value>0, 0</value>
</setting>
<setting name="WindowPositionStored" serializeAs="String">
<value>False</value>
</setting>
<setting name="StoreWindowPosition" serializeAs="String">
<value>False</value>
</setting>
<setting name="Language" serializeAs="String">
<value>(Default)</value>
</setting>