Updated HotKey management and registration.

Added HotKey settings to settings side panel.
String resource update for new settings panel.
This commit is contained in:
Lorenz Cuno Klopfenstein 2011-03-27 22:12:02 +02:00
parent 3ad9a6eb11
commit 34a190dbde
18 changed files with 1010 additions and 697 deletions

View file

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace OnTopReplica {
class HotKeyTextBox : TextBox {
protected override void OnCreateControl() {
ReadOnly = true;
base.OnCreateControl();
}
readonly Keys[] IgnoredKeys = new Keys[] {
Keys.ControlKey,
Keys.Control,
Keys.Alt,
Keys.Menu,
Keys.ShiftKey,
Keys.Shift,
Keys.LWin,
Keys.RWin
};
readonly Keys[] CancelKeys = new Keys[] {
Keys.Back,
Keys.Escape
};
protected override void OnKeyUp(KeyEventArgs e) {
if (CancelKeys.Contains(e.KeyCode)) {
Text = string.Empty;
}
else if (!IgnoredKeys.Contains(e.KeyCode)) {
var sb = new StringBuilder();
if (e.Control)
sb.Append("[CTRL]+");
if (e.Alt)
sb.Append("[ALT]+");
if (e.Shift)
sb.Append("[SHIFT]+");
sb.Append(e.KeyCode.ToString());
Text = sb.ToString();
}
e.Handled = true;
base.OnKeyUp(e);
}
}
}

View file

@ -56,13 +56,6 @@ namespace OnTopReplica {
//Init message pump extensions
_msgPumpManager.Initialize(this);
//Add hotkeys
var hotKeyMgr = _msgPumpManager.Get<MessagePumpProcessors.HotKeyManager>();
hotKeyMgr.RegisterHotKey(Native.HotKeyModifiers.Control | Native.HotKeyModifiers.Shift,
Keys.O, new Native.HotKeyMethods.HotKeyHandler(HotKeyOpenHandler));
hotKeyMgr.RegisterHotKey(Native.HotKeyModifiers.Control | Native.HotKeyModifiers.Shift,
Keys.C, new Native.HotKeyMethods.HotKeyHandler(HotKeyCloneHandler));
//Set to Key event preview
this.KeyPreview = true;
}
@ -280,26 +273,6 @@ namespace OnTopReplica {
}
}
void HotKeyOpenHandler() {
if (IsFullscreen)
IsFullscreen = false;
if (!Program.Platform.IsHidden(this)) {
Program.Platform.HideForm(this);
}
else {
EnsureMainFormVisible();
}
}
void HotKeyCloneHandler() {
var handle = Win32Helper.GetCurrentForegroundWindow();
if (handle.Handle == this.Handle)
return;
SetThumbnail(handle, null);
}
#endregion
#region Fullscreen

View file

@ -10,7 +10,7 @@ namespace OnTopReplica.MessagePumpProcessors {
#region IMessagePumpProcessor Members
public void Initialize(MainForm form) {
public virtual void Initialize(MainForm form) {
Form = form;
}
@ -18,10 +18,10 @@ namespace OnTopReplica.MessagePumpProcessors {
#endregion
bool _isDisposed = false;
protected abstract void Shutdown();
bool _isDisposed = false;
#region IDisposable Members
public void Dispose() {

View file

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using OnTopReplica.Native;
using OnTopReplica.Properties;
namespace OnTopReplica.MessagePumpProcessors {
@ -11,40 +12,156 @@ namespace OnTopReplica.MessagePumpProcessors {
/// </summary>
class HotKeyManager : BaseMessagePumpProcessor {
int _lastUsedKey = 0;
Dictionary<int, HotKeyMethods.HotKeyHandler> _handlers = new Dictionary<int, HotKeyMethods.HotKeyHandler>();
public void RegisterHotKey(HotKeyModifiers mod, Keys keys, HotKeyMethods.HotKeyHandler handler) {
var newKey = ++_lastUsedKey;
if (!HotKeyMethods.RegisterHotKey(Form.Handle, newKey, (int)mod, (int)keys)) {
Console.Error.WriteLine("Failed to register {0} hot key.", newKey);
return;
public HotKeyManager() {
Enabled = true;
}
_handlers[newKey] = handler;
delegate void HotKeyHandler();
/// <summary>
/// Wraps hot key handler registration data.
/// </summary>
private class HotKeyHandlerRegistration : IDisposable {
private HotKeyHandlerRegistration() {
}
private HotKeyHandlerRegistration(IntPtr hwnd, int key, HotKeyHandler handler) {
if (hwnd == IntPtr.Zero)
throw new ArgumentException();
if (handler == null)
throw new ArgumentNullException();
_hwnd = hwnd;
RegistrationKey = key;
Handler = handler;
}
static int _lastUsedKey = 0;
/// <summary>
/// Registers a new hotkey and returns a handle to the registration.
/// </summary>
/// <returns>Returns null on failure.</returns>
public static HotKeyHandlerRegistration Register(Form owner, int keyCode, int modifiers, HotKeyHandler handler) {
var key = ++_lastUsedKey;
if (!HotKeyMethods.RegisterHotKey(owner.Handle, key, modifiers, keyCode)) {
Console.Error.WriteLine("Failed to create hotkey on keys {0}.", keyCode);
return null;
}
return new HotKeyHandlerRegistration(owner.Handle, key, handler);
}
IntPtr _hwnd;
public int RegistrationKey { get; private set; }
public HotKeyHandler Handler { get; private set; }
public void Dispose() {
if (!HotKeyMethods.UnregisterHotKey(_hwnd, RegistrationKey)) {
Console.Error.WriteLine("Failed to unregister hotkey #{0}.", RegistrationKey);
}
}
}
Dictionary<int, HotKeyHandlerRegistration> _handlers = new Dictionary<int, HotKeyHandlerRegistration>();
public override void Initialize(MainForm form) {
base.Initialize(form);
RefreshHotkeys();
}
public override bool Process(ref Message msg) {
if (msg.Msg == HotKeyMethods.WM_HOTKEY) {
if (Enabled && msg.Msg == HotKeyMethods.WM_HOTKEY) {
int keyId = msg.WParam.ToInt32();
if (!_handlers.ContainsKey(keyId))
return false;
_handlers[keyId].Invoke();
_handlers[keyId].Handler.Invoke();
}
return false;
}
public bool Enabled { get; set; }
/// <summary>
/// Refreshes registered hotkeys from Settings.
/// </summary>
/// <remarks>
/// Application settings contain hotkey registration strings that are used
/// automatically by this registration process.
/// </remarks>
public void RefreshHotkeys() {
ClearHandlers();
RegisterHandler(Settings.Default.HotKeyCloneCurrent, HotKeyCloneHandler);
RegisterHandler(Settings.Default.HotKeyShowHide, HotKeyShowHideHandler);
}
private void RegisterHandler(string spec, HotKeyHandler handler) {
if (string.IsNullOrEmpty(spec))
return; //this can happen and is allowed => simply don't register
if (handler == null)
throw new ArgumentNullException();
int modifiers = 0, keyCode = 0;
try {
HotKeyMethods.TranslateStringToKeyValues(spec, out modifiers, out keyCode);
}
catch (ArgumentException) {
//TODO: swallowed exception
return;
}
var reg = HotKeyHandlerRegistration.Register(Form, keyCode, modifiers, handler);
_handlers.Add(reg.RegistrationKey, reg);
}
private void ClearHandlers() {
foreach (var hotkey in _handlers) {
hotkey.Value.Dispose();
}
_handlers.Clear();
}
protected override void Shutdown() {
foreach (var key in _handlers.Keys) {
if (!HotKeyMethods.UnregisterHotKey(Form.Handle, key)) {
Console.Error.WriteLine("Failed to unregister {0} hot key.", key);
ClearHandlers();
}
#region Hotkey callbacks
/// <summary>
/// Handles "show/hide" hotkey. Ensures the form is in restored state and switches
/// between shown and hidden states.
/// </summary>
void HotKeyShowHideHandler() {
if (Form.IsFullscreen)
Form.IsFullscreen = false;
if (!Program.Platform.IsHidden(Form)) {
Program.Platform.HideForm(Form);
}
else {
Form.EnsureMainFormVisible();
}
}
/// <summary>
/// Handles the "clone current" hotkey.
/// </summary>
void HotKeyCloneHandler() {
var handle = Win32Helper.GetCurrentForegroundWindow();
if (handle.Handle == Form.Handle)
return;
Form.SetThumbnail(handle, null);
}
#endregion
}
}

View file

@ -15,6 +15,7 @@ namespace OnTopReplica.MessagePumpProcessors {
if (Form.CurrentThumbnailWindowHandle != null &&
msg.Msg == HookMethods.WM_SHELLHOOKMESSAGE) {
int hookCode = msg.WParam.ToInt32();
if (hookCode == HookMethods.HSHELL_WINDOWDESTROYED) {
//Check whether the destroyed window is the one we were cloning
IntPtr destroyedHandle = msg.LParam;

View file

@ -14,10 +14,11 @@ namespace OnTopReplica.Native {
Windows = 0x8
}
/// <summary>
/// Static native methods for HotKey management.
/// </summary>
static class HotKeyMethods {
public delegate void HotKeyHandler();
public const int WM_HOTKEY = 0x312;
[DllImport("user32.dll")]
@ -26,7 +27,52 @@ namespace OnTopReplica.Native {
[DllImport("user32.dll")]
public static extern bool UnregisterHotKey(IntPtr hWnd, int id);
public delegate void FormDelegate(HotKeyModifiers mod, Keys key, HotKeyHandler handler);
/// <summary>
/// Translates a key combination specification into key code values.
/// </summary>
/// <param name="hotkeySpec">Key combination specification (see remarks).</param>
/// <param name="modifiers">Modifier values.</param>
/// <param name="keys">Key values.</param>
/// <remarks>
/// Specification can contain one single key value (from the enumeration System.Windows.Forms.Keys)
/// preceded by modifier strings (each one separated by a single '+').
/// For instance:
/// [CTRL]+[ALT]+A
/// or
/// [ALT]+[SHIFT]+O
/// </remarks>
public static void TranslateStringToKeyValues(string hotkeySpec, out int modifiers, out int keys) {
if (string.IsNullOrEmpty(hotkeySpec))
throw new ArgumentNullException();
modifiers = 0;
keys = 0;
if (ExtractModifier(ref hotkeySpec, "[CTRL]+"))
modifiers |= (int)HotKeyModifiers.Control;
if (ExtractModifier(ref hotkeySpec, "[ALT]+"))
modifiers |= (int)HotKeyModifiers.Alt;
if (ExtractModifier(ref hotkeySpec, "[SHIFT]+"))
modifiers |= (int)HotKeyModifiers.Shift;
//Attempt to translate last part (should be single key)
try {
var keyValue = Enum.Parse(typeof(Keys), hotkeySpec, true);
keys = (int)keyValue;
}
catch (ArgumentException) {
throw new ArgumentException("Couldn't parse key value '" + hotkeySpec + "'.");
}
}
private static bool ExtractModifier(ref string spec, string modifier) {
int modIndex = spec.IndexOf(modifier);
if (modIndex == -1)
return false;
spec = spec.Remove(modIndex, modifier.Length);
return true;
}
}
}

View file

@ -115,6 +115,9 @@
<Compile Include="EnumerableExtensions.cs" />
<Compile Include="ExtensionAttribute.cs" />
<Compile Include="GeometryExtensions.cs" />
<Compile Include="HotKeyTextBox.cs">
<SubType>Component</SubType>
</Compile>
<Compile Include="ImageComboBox.cs">
<SubType>Component</SubType>
</Compile>
@ -206,7 +209,6 @@
<Compile Include="StoredRegionComparer.cs" />
<Compile Include="Native\WindowsSevenMethods.cs" />
<None Include="Native\CommonControls.cs" />
<Compile Include="EnumerationExtensions.cs" />
<Compile Include="MessagePumpProcessors\HotKeyManager.cs" />
<Compile Include="PlatformSupport.cs" />
<Compile Include="Platforms\Other.cs" />

View file

@ -201,5 +201,29 @@ namespace OnTopReplica.Properties {
this["RestoreLastWindowHwnd"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("[CTRL]+[SHIFT]+C")]
public string HotKeyCloneCurrent {
get {
return ((string)(this["HotKeyCloneCurrent"]));
}
set {
this["HotKeyCloneCurrent"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("[CTRL]+[SHIFT]+O")]
public string HotKeyShowHide {
get {
return ((string)(this["HotKeyShowHide"]));
}
set {
this["HotKeyShowHide"] = value;
}
}
}
}

View file

@ -47,5 +47,11 @@
<Setting Name="RestoreLastWindowHwnd" Type="System.Int64" Scope="User">
<Value Profile="(Default)">0</Value>
</Setting>
<Setting Name="HotKeyCloneCurrent" Type="System.String" Scope="User">
<Value Profile="(Default)">[CTRL]+[SHIFT]+C</Value>
</Setting>
<Setting Name="HotKeyShowHide" Type="System.String" Scope="User">
<Value Profile="(Default)">[CTRL]+[SHIFT]+O</Value>
</Setting>
</Settings>
</SettingsFile>

View file

@ -25,10 +25,17 @@
private void InitializeComponent() {
this.btnClose = new System.Windows.Forms.Button();
this.panelMain = new System.Windows.Forms.Panel();
this.groupHotkeys = new System.Windows.Forms.GroupBox();
this.label1 = new System.Windows.Forms.Label();
this.lblHotKeyShowHide = new System.Windows.Forms.Label();
this.txtHotKeyShowHide = new OnTopReplica.HotKeyTextBox();
this.lblHotKeyClone = new System.Windows.Forms.Label();
this.txtHotKeyClone = new OnTopReplica.HotKeyTextBox();
this.groupLanguage = new System.Windows.Forms.GroupBox();
this.comboLanguage = new OnTopReplica.ImageComboBox();
this.lblLanguage = new System.Windows.Forms.Label();
this.panelMain.SuspendLayout();
this.groupHotkeys.SuspendLayout();
this.groupLanguage.SuspendLayout();
this.SuspendLayout();
//
@ -39,7 +46,7 @@
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(75, 23);
this.btnClose.TabIndex = 0;
this.btnClose.Text = "Close";
this.btnClose.Text = Strings.MenuClose;
this.btnClose.UseVisualStyleBackColor = true;
this.btnClose.Click += new System.EventHandler(this.Close_click);
//
@ -49,12 +56,77 @@
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelMain.AutoScroll = true;
this.panelMain.Controls.Add(this.groupHotkeys);
this.panelMain.Controls.Add(this.groupLanguage);
this.panelMain.Location = new System.Drawing.Point(0, 0);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(260, 211);
this.panelMain.TabIndex = 1;
//
// groupHotkeys
//
this.groupHotkeys.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.groupHotkeys.Controls.Add(this.label1);
this.groupHotkeys.Controls.Add(this.lblHotKeyShowHide);
this.groupHotkeys.Controls.Add(this.txtHotKeyShowHide);
this.groupHotkeys.Controls.Add(this.lblHotKeyClone);
this.groupHotkeys.Controls.Add(this.txtHotKeyClone);
this.groupHotkeys.Location = new System.Drawing.Point(3, 77);
this.groupHotkeys.Name = "groupHotkeys";
this.groupHotkeys.Size = new System.Drawing.Size(254, 113);
this.groupHotkeys.TabIndex = 1;
this.groupHotkeys.TabStop = false;
this.groupHotkeys.Text = Strings.SettingsHotKeyTitle;
//
// label1
//
this.label1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.label1.Location = new System.Drawing.Point(6, 68);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(158, 43);
this.label1.TabIndex = 4;
this.label1.Text = Strings.SettingsHotKeyDescription;
//
// lblHotKeyShowHide
//
this.lblHotKeyShowHide.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.lblHotKeyShowHide.Location = new System.Drawing.Point(170, 22);
this.lblHotKeyShowHide.Name = "lblHotKeyShowHide";
this.lblHotKeyShowHide.Size = new System.Drawing.Size(78, 17);
this.lblHotKeyShowHide.TabIndex = 3;
this.lblHotKeyShowHide.Text = Strings.SettingsHotKeyShowHide;
//
// txtHotKeyShowHide
//
this.txtHotKeyShowHide.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtHotKeyShowHide.Location = new System.Drawing.Point(6, 19);
this.txtHotKeyShowHide.Name = "txtHotKeyShowHide";
this.txtHotKeyShowHide.ReadOnly = true;
this.txtHotKeyShowHide.Size = new System.Drawing.Size(158, 20);
this.txtHotKeyShowHide.TabIndex = 2;
//
// lblHotKeyClone
//
this.lblHotKeyClone.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.lblHotKeyClone.Location = new System.Drawing.Point(170, 48);
this.lblHotKeyClone.Name = "lblHotKeyClone";
this.lblHotKeyClone.Size = new System.Drawing.Size(78, 29);
this.lblHotKeyClone.TabIndex = 1;
this.lblHotKeyClone.Text = Strings.SettingsHotKeyClone;
//
// txtHotKeyClone
//
this.txtHotKeyClone.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.txtHotKeyClone.Location = new System.Drawing.Point(6, 45);
this.txtHotKeyClone.Name = "txtHotKeyClone";
this.txtHotKeyClone.ReadOnly = true;
this.txtHotKeyClone.Size = new System.Drawing.Size(158, 20);
this.txtHotKeyClone.TabIndex = 0;
//
// groupLanguage
//
this.groupLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
@ -66,10 +138,12 @@
this.groupLanguage.Size = new System.Drawing.Size(254, 68);
this.groupLanguage.TabIndex = 0;
this.groupLanguage.TabStop = false;
this.groupLanguage.Text = "Language:";
this.groupLanguage.Text = Strings.SettingsLanguageTitle;
//
// comboLanguage
//
this.comboLanguage.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.comboLanguage.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed;
this.comboLanguage.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.comboLanguage.FormattingEnabled = true;
@ -86,9 +160,9 @@
| System.Windows.Forms.AnchorStyles.Right)));
this.lblLanguage.Location = new System.Drawing.Point(6, 43);
this.lblLanguage.Name = "lblLanguage";
this.lblLanguage.Size = new System.Drawing.Size(242, 23);
this.lblLanguage.Size = new System.Drawing.Size(242, 22);
this.lblLanguage.TabIndex = 1;
this.lblLanguage.Text = "Requires a restart.";
this.lblLanguage.Text = Strings.SettingsRestartRequired;
//
// OptionsPanel
//
@ -101,6 +175,8 @@
this.Name = "OptionsPanel";
this.Size = new System.Drawing.Size(260, 240);
this.panelMain.ResumeLayout(false);
this.groupHotkeys.ResumeLayout(false);
this.groupHotkeys.PerformLayout();
this.groupLanguage.ResumeLayout(false);
this.ResumeLayout(false);
@ -113,5 +189,11 @@
private System.Windows.Forms.GroupBox groupLanguage;
private System.Windows.Forms.Label lblLanguage;
private ImageComboBox comboLanguage;
private System.Windows.Forms.GroupBox groupHotkeys;
private HotKeyTextBox txtHotKeyClone;
private System.Windows.Forms.Label lblHotKeyShowHide;
private HotKeyTextBox txtHotKeyShowHide;
private System.Windows.Forms.Label lblHotKeyClone;
private System.Windows.Forms.Label label1;
}
}

View file

@ -13,8 +13,17 @@ namespace OnTopReplica.SidePanels {
public OptionsPanel() {
InitializeComponent();
}
public override void OnFirstShown(MainForm form) {
base.OnFirstShown(form);
PopulateLanguageComboBox();
//Stop hotkey handling and load current shortcuts
form.MessagePumpManager.Get<OnTopReplica.MessagePumpProcessors.HotKeyManager>().Enabled = false;
txtHotKeyShowHide.Text = Settings.Default.HotKeyShowHide;
txtHotKeyClone.Text = Settings.Default.HotKeyCloneCurrent;
}
private void Close_click(object sender, EventArgs e) {
@ -23,18 +32,40 @@ namespace OnTopReplica.SidePanels {
public override string Title {
get {
return Strings.MenuSettings;
return Strings.SettingsTitle;
}
}
public override void OnClosing(MainForm form) {
base.OnClosing(form);
//Update hotkey settings and update processor
Settings.Default.HotKeyShowHide = txtHotKeyShowHide.Text;
Settings.Default.HotKeyCloneCurrent = txtHotKeyClone.Text;
var manager = form.MessagePumpManager.Get<OnTopReplica.MessagePumpProcessors.HotKeyManager>();
manager.RefreshHotkeys();
manager.Enabled = true;
}
#region Language
Pair<CultureInfo, Image>[] _languageList = {
new Pair<CultureInfo, Image>(new CultureInfo("en-US"), Resources.flag_usa),
new Pair<CultureInfo, Image>(new CultureInfo("it-IT"), Resources.flag_ita),
new Pair<CultureInfo, Image>(new CultureInfo("cs-CZ"), Resources.flag_czech),
new Pair<CultureInfo, Image>(new CultureInfo("da-DK"), Resources.flag_danish),
new Pair<CultureInfo, Image>(new CultureInfo("es-ES"), Resources.flag_spanish),
class CultureWrapper {
public CultureWrapper(string name, CultureInfo culture, Image img) {
Culture = culture;
Image = img;
Name = name;
}
public CultureInfo Culture { get; set; }
public Image Image { get; set; }
public string Name { get; set; }
}
CultureWrapper[] _languageList = {
new CultureWrapper("English", new CultureInfo("en-US"), Resources.flag_usa),
new CultureWrapper("Italiano", new CultureInfo("it-IT"), Resources.flag_ita),
new CultureWrapper("Čeština", new CultureInfo("cs-CZ"), Resources.flag_czech),
new CultureWrapper("Dansk", new CultureInfo("da-DK"), Resources.flag_danish),
new CultureWrapper("Español", new CultureInfo("es-ES"), Resources.flag_spanish),
};
private void PopulateLanguageComboBox() {
@ -48,18 +79,21 @@ namespace OnTopReplica.SidePanels {
int selectedIndex = -1;
foreach (var langPair in _languageList) {
var item = new ImageComboBoxItem(langPair.Item1.NativeName, imageList.Images.Count) {
Tag = langPair.Item1
var item = new ImageComboBoxItem(langPair.Name, imageList.Images.Count) {
Tag = langPair.Culture
};
imageList.Images.Add(langPair.Item2);
imageList.Images.Add(langPair.Image);
comboLanguage.Items.Add(item);
if (langPair.Item1.Equals(CultureInfo.CurrentUICulture) ||
(CultureInfo.CurrentUICulture.Equals(CultureInfo.InvariantCulture) && langPair.Item1.TwoLetterISOLanguageName.Equals("en"))) {
if (langPair.Culture.Equals(CultureInfo.CurrentUICulture)) {
selectedIndex = comboLanguage.Items.Count - 1;
}
}
//Handle case when there is not explicitly set culture (default to first one, i.e. english)
if (CultureInfo.CurrentUICulture.Equals(CultureInfo.InvariantCulture))
selectedIndex = 0;
comboLanguage.SelectedIndex = selectedIndex;
}

View file

@ -871,24 +871,6 @@ namespace OnTopReplica {
}
}
/// <summary>
/// Looks up a localized string similar to Glass.
/// </summary>
internal static string MenuGlass {
get {
return ResourceManager.GetString("MenuGlass", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Toggles &quot;glass mode&quot; on and off..
/// </summary>
internal static string MenuGlassTT {
get {
return ResourceManager.GetString("MenuGlassTT", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Group Switch mode.
/// </summary>
@ -1348,6 +1330,69 @@ namespace OnTopReplica {
}
}
/// <summary>
/// Looks up a localized string similar to Clone current window.
/// </summary>
internal static string SettingsHotKeyClone {
get {
return ResourceManager.GetString("SettingsHotKeyClone", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to These system-wide shortcuts can also be used when OnTopReplica is not in focus..
/// </summary>
internal static string SettingsHotKeyDescription {
get {
return ResourceManager.GetString("SettingsHotKeyDescription", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Show/Hide.
/// </summary>
internal static string SettingsHotKeyShowHide {
get {
return ResourceManager.GetString("SettingsHotKeyShowHide", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Hot keys:.
/// </summary>
internal static string SettingsHotKeyTitle {
get {
return ResourceManager.GetString("SettingsHotKeyTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Language:.
/// </summary>
internal static string SettingsLanguageTitle {
get {
return ResourceManager.GetString("SettingsLanguageTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Requires a restart..
/// </summary>
internal static string SettingsRestartRequired {
get {
return ResourceManager.GetString("SettingsRestartRequired", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Settings.
/// </summary>
internal static string SettingsTitle {
get {
return ResourceManager.GetString("SettingsTitle", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A lightweight, real-time, always on top thumbnail of a window of your choice..
/// </summary>

View file

@ -309,12 +309,6 @@ Režim "Proklikávání" je možné zvolit později v menu</value>
<data name="MenuFitQuarter" xml:space="preserve">
<value>1:4 Čtvrtinová</value>
</data>
<data name="MenuGlass" xml:space="preserve">
<value>Glass efekt</value>
</data>
<data name="MenuGlassTT" xml:space="preserve">
<value>Přepíná "glass efekt" okna.</value>
</data>
<data name="MenuOp100" xml:space="preserve">
<value>100% (neprůhledné)</value>
</data>

View file

@ -304,12 +304,6 @@ Du kan aktivere gennem klik senere.</value>
<data name="MenuFitQuarter" xml:space="preserve">
<value>1:4 kvart</value>
</data>
<data name="MenuGlass" xml:space="preserve">
<value>Glas</value>
</data>
<data name="MenuGlassTT" xml:space="preserve">
<value>Vælger "glas tilstand" til/fra</value>
</data>
<data name="MenuOp100" xml:space="preserve">
<value>100% (uigennemsigtig)</value>
</data>

View file

@ -334,12 +334,6 @@ Se podrá activar Click a través más tarde</value>
<data name="MenuFitQuarter" xml:space="preserve">
<value>1:4 Un cuarto</value>
</data>
<data name="MenuGlass" xml:space="preserve">
<value>Efecto vidrio</value>
</data>
<data name="MenuGlassTT" xml:space="preserve">
<value>Activa o desactiva el efecto vidrio.</value>
</data>
<data name="MenuGroupSwitch" xml:space="preserve">
<value>Modo en grupo</value>
</data>

View file

@ -334,11 +334,11 @@ Puoi abilitare il Click-Through in futuro</value>
<data name="MenuFitQuarter" xml:space="preserve">
<value>1:4 Quarto</value>
</data>
<data name="MenuGlass" xml:space="preserve">
<value>Effetto vetro</value>
<data name="SettingsHotKeyDescription" xml:space="preserve">
<value>Queste scorciatoie possono essere usate quando OnTopReplica non è attivo.</value>
</data>
<data name="MenuGlassTT" xml:space="preserve">
<value>Abilita o disabilita l'effetto vetro.</value>
<data name="SettingsHotKeyClone" xml:space="preserve">
<value>Clona finestra corrente</value>
</data>
<data name="MenuGroupSwitch" xml:space="preserve">
<value>Modalità Gruppo di finestre</value>
@ -487,4 +487,34 @@ Puoi abilitare il Click-Through in futuro</value>
<data name="UpdateNow" xml:space="preserve">
<value>Aggiorna!</value>
</data>
<data name="SettingsHotKeyShowHide" xml:space="preserve">
<value>Nascondi</value>
</data>
<data name="SettingsHotKeyTitle" xml:space="preserve">
<value>Scorciatoie:</value>
</data>
<data name="SettingsLanguageTitle" xml:space="preserve">
<value>Lingua:</value>
</data>
<data name="SettingsRestartRequired" xml:space="preserve">
<value>Richiede un riavvio.</value>
</data>
<data name="SettingsTitle" xml:space="preserve">
<value>Impostazioni</value>
</data>
<data name="MenuRestoreLast" xml:space="preserve">
<value>Ripristina ultima finestra</value>
</data>
<data name="MenuRestoreLastTT" xml:space="preserve">
<value>Se abilitato, all'avvio OnTopReplica tenterà di ripristinare l'ultima finestra precedentemente clonata.</value>
</data>
<data name="MenuSettings" xml:space="preserve">
<value>Impostazioni...</value>
</data>
<data name="MenuSettingsTT" xml:space="preserve">
<value>Mostra il pannello delle impostazioni.</value>
</data>
<data name="MenuPosCenter" xml:space="preserve">
<value>Centrato</value>
</data>
</root>

View file

@ -1,110 +1,5 @@
<?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>
@ -439,12 +334,6 @@ You can enable click-through later</value>
<data name="MenuFitQuarter" xml:space="preserve">
<value>1:4 Quarter</value>
</data>
<data name="MenuGlass" xml:space="preserve">
<value>Glass</value>
</data>
<data name="MenuGlassTT" xml:space="preserve">
<value>Toggles "glass mode" on and off.</value>
</data>
<data name="MenuGroupSwitch" xml:space="preserve">
<value>Group Switch mode</value>
</data>
@ -607,4 +496,25 @@ You can enable click-through later</value>
<data name="MenuRestoreLastTT" xml:space="preserve">
<value>When enabled, OnTopReplica will attempt to restore the last cloned window on start up.</value>
</data>
<data name="SettingsHotKeyClone" xml:space="preserve">
<value>Clone current window</value>
</data>
<data name="SettingsHotKeyDescription" xml:space="preserve">
<value>These system-wide shortcuts can also be used when OnTopReplica is not in focus.</value>
</data>
<data name="SettingsHotKeyShowHide" xml:space="preserve">
<value>Show/Hide</value>
</data>
<data name="SettingsHotKeyTitle" xml:space="preserve">
<value>Hot keys:</value>
</data>
<data name="SettingsLanguageTitle" xml:space="preserve">
<value>Language:</value>
</data>
<data name="SettingsRestartRequired" xml:space="preserve">
<value>Requires a restart.</value>
</data>
<data name="SettingsTitle" xml:space="preserve">
<value>Settings</value>
</data>
</root>

View file

@ -49,6 +49,12 @@
<setting name="RestoreLastWindowHwnd" serializeAs="String">
<value>0</value>
</setting>
<setting name="HotKeyCloneCurrent" serializeAs="String">
<value>[CTRL]+[SHIFT]+C</value>
</setting>
<setting name="HotKeyShowHide" serializeAs="String">
<value>[CTRL]+[SHIFT]+O</value>
</setting>
</OnTopReplica.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>