Window restoring option added (by window class, window title and window HWND).

This commit is contained in:
Lorenz Cuno Klopfenstein 2011-03-22 11:56:07 +01:00
parent 4cfd61ba28
commit c2347b25a5
15 changed files with 348 additions and 78 deletions

View file

@ -37,6 +37,7 @@
this.clickForwardingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.clickThroughToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.groupSwitchModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.restoreLastClonedWindowToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuContextOpacity = new System.Windows.Forms.ToolStripMenuItem();
this.menuOpacity = new System.Windows.Forms.ContextMenuStrip(this.components);
this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
@ -69,6 +70,7 @@
this.englishToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.cestinaToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.danskToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
this.espanolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.italianoToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuContextClose = new System.Windows.Forms.ToolStripMenuItem();
@ -77,7 +79,6 @@
this.menuFullscreenContext = new System.Windows.Forms.ContextMenuStrip(this.components);
this.enableClickthroughToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.fullExitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.espanolToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.menuContext.SuspendLayout();
this.menuWindows.SuspendLayout();
this.menuOpacity.SuspendLayout();
@ -154,17 +155,19 @@
this.advancedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.clickForwardingToolStripMenuItem,
this.clickThroughToolStripMenuItem,
this.groupSwitchModeToolStripMenuItem});
this.groupSwitchModeToolStripMenuItem,
this.restoreLastClonedWindowToolStripMenuItem});
this.advancedToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.xiao_wrench;
this.advancedToolStripMenuItem.Name = "advancedToolStripMenuItem";
this.advancedToolStripMenuItem.Size = new System.Drawing.Size(168, 22);
this.advancedToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuAdvanced;
this.advancedToolStripMenuItem.DropDownOpening += new System.EventHandler(this.Menu_Advanced_opening);
//
// clickForwardingToolStripMenuItem
//
this.clickForwardingToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.clickforwarding;
this.clickForwardingToolStripMenuItem.Name = "clickForwardingToolStripMenuItem";
this.clickForwardingToolStripMenuItem.Size = new System.Drawing.Size(199, 22);
this.clickForwardingToolStripMenuItem.Size = new System.Drawing.Size(218, 22);
this.clickForwardingToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuClickForwarding;
this.clickForwardingToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuClickForwardingTT;
this.clickForwardingToolStripMenuItem.Click += new System.EventHandler(this.Menu_ClickForwarding_click);
@ -173,7 +176,7 @@
//
this.clickThroughToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.window_opacity;
this.clickThroughToolStripMenuItem.Name = "clickThroughToolStripMenuItem";
this.clickThroughToolStripMenuItem.Size = new System.Drawing.Size(199, 22);
this.clickThroughToolStripMenuItem.Size = new System.Drawing.Size(218, 22);
this.clickThroughToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuClickThrough;
this.clickThroughToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuClickThroughTT;
this.clickThroughToolStripMenuItem.Click += new System.EventHandler(this.Menu_ClickThrough_click);
@ -182,11 +185,18 @@
//
this.groupSwitchModeToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.groupmode;
this.groupSwitchModeToolStripMenuItem.Name = "groupSwitchModeToolStripMenuItem";
this.groupSwitchModeToolStripMenuItem.Size = new System.Drawing.Size(199, 22);
this.groupSwitchModeToolStripMenuItem.Size = new System.Drawing.Size(218, 22);
this.groupSwitchModeToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuGroupSwitch;
this.groupSwitchModeToolStripMenuItem.ToolTipText = global::OnTopReplica.Strings.MenuGroupSwitchTT;
this.groupSwitchModeToolStripMenuItem.Click += new System.EventHandler(this.Menu_GroupSwitchMode_click);
//
// restoreLastClonedWindowToolStripMenuItem
//
this.restoreLastClonedWindowToolStripMenuItem.Name = "restoreLastClonedWindowToolStripMenuItem";
this.restoreLastClonedWindowToolStripMenuItem.Size = new System.Drawing.Size(218, 22);
this.restoreLastClonedWindowToolStripMenuItem.Text = "Restore last cloned window";
this.restoreLastClonedWindowToolStripMenuItem.Click += new System.EventHandler(this.Menu_RestoreLastWindow_click);
//
// menuContextOpacity
//
this.menuContextOpacity.DropDown = this.menuOpacity;
@ -467,6 +477,15 @@
this.danskToolStripMenuItem1.Text = "Dansk";
this.danskToolStripMenuItem1.Click += new System.EventHandler(this.Menu_Language_click);
//
// espanolToolStripMenuItem
//
this.espanolToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.flag_spanish;
this.espanolToolStripMenuItem.Name = "espanolToolStripMenuItem";
this.espanolToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.espanolToolStripMenuItem.Tag = "es-ES";
this.espanolToolStripMenuItem.Text = "Español";
this.espanolToolStripMenuItem.Click += new System.EventHandler(this.Menu_Language_click);
//
// italianoToolStripMenuItem
//
this.italianoToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.flag_ita;
@ -538,15 +557,6 @@
this.fullExitToolStripMenuItem.Text = global::OnTopReplica.Strings.MenuQuitFullscreen;
this.fullExitToolStripMenuItem.Click += new System.EventHandler(this.Menu_Fullscreen_ExitFullscreen_click);
//
// espanolToolStripMenuItem
//
this.espanolToolStripMenuItem.Image = global::OnTopReplica.Properties.Resources.flag_spanish;
this.espanolToolStripMenuItem.Name = "espanolToolStripMenuItem";
this.espanolToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
this.espanolToolStripMenuItem.Text = "Español";
this.espanolToolStripMenuItem.Tag = "es-ES";
this.espanolToolStripMenuItem.Click += new System.EventHandler(this.Menu_Language_click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@ -554,11 +564,10 @@
this.BackColor = System.Drawing.SystemColors.Control;
this.ClientSize = new System.Drawing.Size(264, 204);
this.ControlBox = false;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Sizable; //.SizableToolWindow;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(20, 34);
this.MinimumSize = new System.Drawing.Size(20, 38);
this.Name = "MainForm";
this.Text = "OnTopReplica";
this.TopMost = true;
@ -625,6 +634,7 @@
private System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
private System.Windows.Forms.ToolStripMenuItem restorePositionAndSizeToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem espanolToolStripMenuItem;
private System.Windows.Forms.ToolStripMenuItem restoreLastClonedWindowToolStripMenuItem;
}
}

View file

@ -1,15 +1,15 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using OnTopReplica.Native;
using OnTopReplica.Properties;
using OnTopReplica.StartupOptions;
using OnTopReplica.Update;
using OnTopReplica.WindowSeekers;
using VistaControls.Dwm;
using VistaControls.TaskDialog;
using System.Collections.Generic;
using OnTopReplica.Native;
using OnTopReplica.Update;
using OnTopReplica.StartupOptions;
using OnTopReplica.WindowSeekers;
namespace OnTopReplica {
@ -52,7 +52,7 @@ namespace OnTopReplica {
//Side panel
_sidePanelContainer = new Panel {
Location = new Point(ClientSize.Width, 0),
Location = new Point(ClientSize.Width + 5, 0),
Anchor = AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom,
Enabled = false,
Visible = false,
@ -126,6 +126,13 @@ namespace OnTopReplica {
}
protected override void OnClosing(CancelEventArgs e) {
//Store last thumbnail, if any
if (_thumbnailPanel.IsShowingThumbnail && CurrentThumbnailWindowHandle != null) {
Settings.Default.RestoreLastWindowTitle = CurrentThumbnailWindowHandle.Title;
Settings.Default.RestoreLastWindowHwnd = CurrentThumbnailWindowHandle.Handle.ToInt64();
Settings.Default.RestoreLastWindowClass = CurrentThumbnailWindowHandle.Class;
}
_msgPumpManager.Dispose();
Program.Platform.CloseForm(this);
@ -262,7 +269,8 @@ namespace OnTopReplica {
FitToThumbnail(0.5);
}
else if (e.KeyCode == Keys.D3 || e.KeyCode == Keys.NumPad3 || e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0) {
else if (e.KeyCode == Keys.D3 || e.KeyCode == Keys.NumPad3 ||
e.KeyCode == Keys.D0 || e.KeyCode == Keys.NumPad0) {
FitToThumbnail(1.0);
}
@ -340,8 +348,8 @@ namespace OnTopReplica {
_preFullscreenSize = ClientSize;
_preFullscreenBorderStyle = FormBorderStyle;
var currentScreen = Screen.FromControl(this);
FormBorderStyle = FormBorderStyle.None;
var currentScreen = Screen.FromControl(this);
Size = currentScreen.WorkingArea.Size;
Location = currentScreen.WorkingArea.Location;
}

View file

@ -64,10 +64,18 @@ namespace OnTopReplica {
Native.WindowManagerMethods.SetForegroundWindow(CurrentThumbnailWindowHandle.Handle);
}
private void Menu_Advanced_opening(object sender, EventArgs e) {
restoreLastClonedWindowToolStripMenuItem.Checked = Settings.Default.RestoreLastWindow;
}
private void Menu_GroupSwitchMode_click(object sender, EventArgs e) {
SetSidePanel(new SidePanels.GroupSwitchPanel());
}
private void Menu_RestoreLastWindow_click(object sender, EventArgs e) {
Settings.Default.RestoreLastWindow = !Settings.Default.RestoreLastWindow;
}
private void Menu_ClickForwarding_click(object sender, EventArgs e) {
ClickForwardingEnabled = !ClickForwardingEnabled;
}

View file

@ -84,5 +84,16 @@ namespace OnTopReplica.Native {
[DllImport("user32.dll")]
public static extern IntPtr GetWindow(IntPtr hwnd, GetWindowMode mode);
/// <summary>
/// Checks whether a window is a top-level window (has no owner nor parent window).
/// </summary>
/// <param name="hwnd">Handle to the window to check.</param>
public static bool IsTopLevel(IntPtr hwnd) {
bool hasParent = WindowManagerMethods.GetParent(hwnd).ToInt64() != 0;
bool hasOwner = WindowManagerMethods.GetWindow(hwnd, WindowManagerMethods.GetWindowMode.GW_OWNER).ToInt64() != 0;
return (!hasParent && !hasOwner);
}
}
}

View file

@ -114,6 +114,7 @@
<Compile Include="CloseRequestEventArgs.cs" />
<Compile Include="EnumerableExtensions.cs" />
<Compile Include="ExtensionAttribute.cs" />
<Compile Include="GeometryExtensions.cs" />
<Compile Include="MainForm_Features.cs">
<SubType>Form</SubType>
</Compile>
@ -138,9 +139,22 @@
<Compile Include="Native\HT.cs" />
<Compile Include="Pair.cs" />
<Compile Include="Platforms\DebugPlatform.cs" />
<Compile Include="SidePanels\OptionsPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="SidePanels\OptionsPanel.Designer.cs">
<DependentUpon>OptionsPanel.cs</DependentUpon>
</Compile>
<Compile Include="SidePanels\GroupSwitchPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="SidePanels\GroupSwitchPanel.Designer.cs">
<DependentUpon>GroupSwitchPanel.cs</DependentUpon>
</Compile>
<Compile Include="WindowSeekers\BaseWindowSeeker.cs" />
<Compile Include="WindowSeekers\ByClassWindowSeeker.cs" />
<Compile Include="WindowSeekers\ByTitleWindowSeeker.cs" />
<Compile Include="WindowSeekers\RestoreWindowSeeker.cs" />
<Compile Include="WindowSeekers\TaskWindowSeeker.cs" />
<None Include="Native\ITaskBarList.cs" />
<Compile Include="Native\InputMethods.cs" />
@ -159,12 +173,6 @@
<Compile Include="SidePanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="SidePanels\GroupSwitchPanel.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="SidePanels\GroupSwitchPanel.Designer.cs">
<DependentUpon>GroupSwitchPanel.cs</DependentUpon>
</Compile>
<Compile Include="StartupOptions\CliStatus.cs" />
<Compile Include="StartupOptions\CommandLineReportForm.cs">
<SubType>Form</SubType>
@ -210,7 +218,9 @@
</EmbeddedResource>
<EmbeddedResource Include="SidePanels\GroupSwitchPanel.resx">
<DependentUpon>GroupSwitchPanel.cs</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="SidePanels\OptionsPanel.resx">
<DependentUpon>OptionsPanel.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="StartupOptions\CommandLineReportForm.resx">
<DependentUpon>CommandLineReportForm.cs</DependentUpon>
@ -378,72 +388,72 @@
<ItemGroup>
<PublishFile Include="Assets\icon.ico">
<Visible>False</Visible>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
<PublishFile Include="Assets\screenshot-icon.ico">
<Visible>False</Visible>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
<PublishFile Include="Assets\window_multiple16.ico">
<Visible>False</Visible>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
<PublishFile Include="Assets\xiao_arrow.png">
<Visible>False</Visible>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Exclude</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>File</FileType>
</PublishFile>
<PublishFile Include="cs\OnTopReplica.resources">
<Visible>False</Visible>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>Satellite</FileType>
</PublishFile>
<PublishFile Include="da\OnTopReplica.resources">
<Visible>False</Visible>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>Satellite</FileType>
</PublishFile>
<PublishFile Include="it\OnTopReplica.resources">
<Visible>False</Visible>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<Group>
</Group>
<TargetPath>
</TargetPath>
<PublishState>Include</PublishState>
<IncludeHash>True</IncludeHash>
<FileType>Satellite</FileType>
</PublishFile>
</ItemGroup>

View file

@ -11,6 +11,7 @@
<VerifyUploadedFiles>false</VerifyUploadedFiles>
<ErrorReportUrlHistory>
</ErrorReportUrlHistory>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
<PropertyGroup>
<EnableSecurityDebugging>false</EnableSecurityDebugging>

View file

@ -34,18 +34,6 @@ namespace OnTopReplica.Properties {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool AutoFitOnResize {
get {
return ((bool)(this["AutoFitOnResize"]));
}
set {
this["AutoFitOnResize"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("255")]
@ -165,5 +153,53 @@ namespace OnTopReplica.Properties {
this["RestoreLastPosition"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool RestoreLastWindow {
get {
return ((bool)(this["RestoreLastWindow"]));
}
set {
this["RestoreLastWindow"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string RestoreLastWindowClass {
get {
return ((string)(this["RestoreLastWindowClass"]));
}
set {
this["RestoreLastWindowClass"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string RestoreLastWindowTitle {
get {
return ((string)(this["RestoreLastWindowTitle"]));
}
set {
this["RestoreLastWindowTitle"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("0")]
public long RestoreLastWindowHwnd {
get {
return ((long)(this["RestoreLastWindowHwnd"]));
}
set {
this["RestoreLastWindowHwnd"] = value;
}
}
}
}

View file

@ -5,9 +5,6 @@
<Setting Name="SavedRegions" Type="OnTopReplica.StoredRegionArray" Scope="User">
<Value Profile="(Default)" />
</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>
@ -38,5 +35,17 @@
<Setting Name="RestoreLastPosition" Type="System.Drawing.Point" Scope="User">
<Value Profile="(Default)">0, 0</Value>
</Setting>
<Setting Name="RestoreLastWindow" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="RestoreLastWindowClass" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="RestoreLastWindowTitle" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
<Setting Name="RestoreLastWindowHwnd" Type="System.Int64" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
</Settings>
</SettingsFile>

View file

@ -4,6 +4,7 @@ using System.Text;
using System.Drawing;
using System.ComponentModel;
using OnTopReplica.Properties;
using OnTopReplica.WindowSeekers;
namespace OnTopReplica.StartupOptions {
class Factory {
@ -30,6 +31,27 @@ namespace OnTopReplica.StartupOptions {
options.StartLocation = Settings.Default.RestoreLastPosition;
options.StartSize = Settings.Default.RestoreLastSize;
}
if (Settings.Default.RestoreLastWindow) {
var handle = Settings.Default.RestoreLastWindowHwnd;
var title = Settings.Default.RestoreLastWindowTitle;
var className = Settings.Default.RestoreLastWindowClass;
var seeker = new RestoreWindowSeeker(new IntPtr(handle), title, className);
seeker.SkipNotVisibleWindows = true;
seeker.Refresh();
var resultHandle = seeker.Windows.FirstOrDefault();
if (resultHandle != null) {
//Load window
options.WindowId = resultHandle.Handle;
}
#if DEBUG
else {
Console.WriteLine("Couldn't find window to restore.");
}
#endif
}
}
private static void ParseCommandLine(string[] args, Options options) {

View file

@ -115,7 +115,7 @@ namespace OnTopReplica {
if (handle == IntPtr.Zero)
return null;
return new WindowHandle(handle, string.Empty);
return new WindowHandle(handle, null);
}
}

View file

@ -6,12 +6,19 @@ using OnTopReplica.Native;
namespace OnTopReplica {
/// <summary>Helper class that keeps a window handle (HWND), the title of the window and can load its icon.</summary>
/// <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;
string _title;
/// <summary>
/// Creates a new WindowHandle instance. The handle pointer must be valid, the title
/// may be null or empty and will be updated as requested.
/// </summary>
public WindowHandle(IntPtr p, string title) {
_handle = p;
_title = title;
@ -19,6 +26,10 @@ namespace OnTopReplica {
public string Title {
get {
if (_title == null) {
_title = WindowMethods.GetWindowText(_handle) ?? string.Empty;
}
return _title;
}
}
@ -32,10 +43,11 @@ namespace OnTopReplica {
IntPtr hIcon;
if (MessagingMethods.SendMessageTimeout(_handle, WM.GETICON, new IntPtr(2), new IntPtr(0),
MessagingMethods.SendMessageTimeoutFlags.AbortIfHung | MessagingMethods.SendMessageTimeoutFlags.Block, 500, out hIcon) == IntPtr.Zero)
hIcon = IntPtr.Zero;
MessagingMethods.SendMessageTimeoutFlags.AbortIfHung | MessagingMethods.SendMessageTimeoutFlags.Block, 500, out hIcon) == IntPtr.Zero) {
hIcon = IntPtr.Zero;
}
if (hIcon.ToInt64() != 0) {
if (hIcon != IntPtr.Zero) {
_icon = Icon.FromHandle(hIcon);
}
else {
@ -54,7 +66,26 @@ namespace OnTopReplica {
}
}
public override string ToString() {
string _class = null;
/// <summary>
/// Gets the window's class name.
/// </summary>
/// <remarks>
/// This value is cached and is never null.
/// </remarks>
public string Class {
get {
if (_class == null) {
_class = Native.WindowMethods.GetWindowClass(Handle) ?? string.Empty;
}
return _class;
}
}
#region Object override
public override string ToString() {
return _title;
}
@ -74,9 +105,11 @@ namespace OnTopReplica {
return _handle.GetHashCode();
}
#region IWin32Window Members
#endregion
public IntPtr Handle {
#region IWin32Window Members
public IntPtr Handle {
get { return _handle; }
}
@ -87,7 +120,7 @@ namespace OnTopReplica {
/// </summary>
/// <param name="handle">Handle value.</param>
public static WindowHandle FromHandle(IntPtr handle) {
return new WindowHandle(handle, string.Empty);
return new WindowHandle(handle, null);
}
}

View file

@ -10,15 +10,18 @@ namespace OnTopReplica.WindowSeekers {
/// </summary>
abstract class BaseWindowSeeker {
List<WindowHandle> _list = new List<WindowHandle>();
IList<WindowHandle> _list = new List<WindowHandle>();
/// <summary>
/// Get the matching windows from the last refresh.
/// </summary>
public IEnumerable<WindowHandle> Windows {
public virtual IList<WindowHandle> Windows {
get {
return _list;
}
protected set {
_list = value;
}
}
/// <summary>

View file

@ -26,10 +26,8 @@ namespace OnTopReplica.WindowSeekers {
if (string.IsNullOrEmpty(title))
return false;
//Skip non-top-level windows (skips most internal controls)
bool hasParent = (long)WindowManagerMethods.GetParent(hwnd) != 0;
bool hasOwner = (long)WindowManagerMethods.GetWindow(hwnd, WindowManagerMethods.GetWindowMode.GW_OWNER) != 0;
if (hasParent || hasOwner)
//Skip non top-level windows
if (!WindowManagerMethods.IsTopLevel(hwnd))
return false;
var modTitle = title.Trim().ToLower();

View file

@ -0,0 +1,112 @@
using System;
using System.Collections.Generic;
using System.Text;
using OnTopReplica.Native;
namespace OnTopReplica.WindowSeekers {
/// <summary>
/// Window seeker that attempts to locate a window to restore (by class, title and ID).
/// </summary>
class RestoreWindowSeeker : BaseWindowSeeker {
public RestoreWindowSeeker(IntPtr handle, string title, string className){
Handle = handle;
Title = title;
Class = className;
}
public IntPtr Handle { get; private set; }
public string Title { get; private set; }
public string Class { get; private set; }
bool _mustBeOrdered = true;
public override void Refresh() {
//Whenever the window list is refreshed, the list must be reordered
_mustBeOrdered = true;
_points = new Dictionary<long, int>();
base.Refresh();
}
Dictionary<long, int> _points = new Dictionary<long, int>();
protected override bool InspectWindow(IntPtr hwnd, string title, ref bool terminate) {
if (!WindowManagerMethods.IsTopLevel(hwnd))
return false;
int points = 0;
//Class exact match
if (!string.IsNullOrEmpty(Class)) {
string wndClass = WindowMethods.GetWindowClass(hwnd);
if (Class.Equals(wndClass, StringComparison.InvariantCulture)) {
points += 10;
}
}
//Title match (may not be exact, but let's try)
if (!string.IsNullOrEmpty(Title) && !string.IsNullOrEmpty(title)) {
if (title.StartsWith(Title, StringComparison.InvariantCultureIgnoreCase)) {
points += 10;
}
}
//Handle match (will probably not work, but anyhow)
if (Handle != IntPtr.Zero) {
if (Handle == hwnd) {
points += 5;
}
}
//Store handle if it matches
if (points > 0) {
_points.Add(hwnd.ToInt64(), points);
return true;
}
else
return false;
}
public override IList<WindowHandle> Windows {
get {
if (_mustBeOrdered) {
WindowHandle[] arr = new WindowHandle[base.Windows.Count];
base.Windows.CopyTo(arr, 0);
Array.Sort<WindowHandle>(arr, new PointComparer(_points));
//Store ordered array
base.Windows = arr;
_mustBeOrdered = false;
}
return base.Windows;
}
}
private class PointComparer : IComparer<WindowHandle> {
public PointComparer(IDictionary<long, int> pointDict) {
_pointDict = pointDict;
}
IDictionary<long, int> _pointDict;
public int Compare(WindowHandle x, WindowHandle y) {
int px = 0;
_pointDict.TryGetValue(x.Handle.ToInt64(), out px);
int py = 0;
_pointDict.TryGetValue(y.Handle.ToInt64(), out py);
return py.CompareTo(px); //inverse comparison (from max points to min)
}
}
}
}

View file

@ -7,9 +7,6 @@
</configSections>
<userSettings>
<OnTopReplica.Properties.Settings>
<setting name="AutoFitOnResize" serializeAs="String">
<value>True</value>
</setting>
<setting name="Opacity" serializeAs="String">
<value>255</value>
</setting>
@ -40,6 +37,18 @@
<setting name="RestoreLastPosition" serializeAs="String">
<value>0, 0</value>
</setting>
<setting name="RestoreLastWindow" serializeAs="String">
<value>False</value>
</setting>
<setting name="RestoreLastWindowClass" serializeAs="String">
<value />
</setting>
<setting name="RestoreLastWindowTitle" serializeAs="String">
<value />
</setting>
<setting name="RestoreLastWindowHwnd" serializeAs="String">
<value>0</value>
</setting>
</OnTopReplica.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>