Feature added: Automatic transparency in click-through mode.

Some minor clean up.
This commit is contained in:
Lorenz Cuno Klopfenstein 2013-10-16 15:58:27 +02:00
parent 15f5691168
commit bc03f9298b
6 changed files with 82 additions and 17 deletions

View file

@ -188,8 +188,10 @@ namespace OnTopReplica {
case WM.NCHITTEST:
//Make transparent to hit-testing if in click through mode
if (ClickThroughEnabled && (ModifierKeys & Keys.Alt) != Keys.Alt) {
if (ClickThroughEnabled) {
m.Result = (IntPtr)HT.TRANSPARENT;
RefreshClickThroughComeBack();
return;
}
break;

View file

@ -1,10 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
using OnTopReplica.Native;
using OnTopReplica.Properties;
using WindowsFormsAero.TaskDialog;
using System;
using System.Drawing;
using System.Windows.Forms;
using WindowsFormsAero.TaskDialog;
namespace OnTopReplica {
//Contains some feature implementations of MainForm
@ -36,6 +35,7 @@ namespace OnTopReplica {
#region Click-through
bool _clickThrough = false;
readonly Color DefaultNonClickTransparencyKey;
public bool ClickThroughEnabled {
@ -43,21 +43,56 @@ namespace OnTopReplica {
return _clickThrough;
}
set {
//Adjust opacity if fully opaque
/*if (value && Opacity == 1.0)
Opacity = 0.75;
if (!value)
Opacity = 1.0;*/
//Enable transparency and force as top-most
TransparencyKey = (value) ? Color.Black : DefaultNonClickTransparencyKey;
if (value)
if (value) {
//Re-force as top most (always helps in some cases)
TopMost = true;
}
_clickThrough = value;
}
}
//Must NOT be equal to any other valid opacity value
const double ClickThroughHoverOpacity = 0.6;
Timer _clickThroughComeBackTimer = null;
long _clickThroughComeBackTicks;
const int ClickThroughComeBackTimerInterval = 1000;
/// <summary>
/// When the mouse hovers over a fully opaque click-through form,
/// this fades the form to semi-transparency
/// and starts a timeout to get back to full opacity.
/// </summary>
private void RefreshClickThroughComeBack() {
if (this.Opacity == 1.0) {
this.Opacity = ClickThroughHoverOpacity;
}
if (_clickThroughComeBackTimer == null) {
_clickThroughComeBackTimer = new Timer();
_clickThroughComeBackTimer.Tick += _clickThroughComeBackTimer_Tick;
_clickThroughComeBackTimer.Interval = ClickThroughComeBackTimerInterval;
}
_clickThroughComeBackTicks = DateTime.UtcNow.Ticks;
_clickThroughComeBackTimer.Start();
}
void _clickThroughComeBackTimer_Tick(object sender, EventArgs e) {
var diff = DateTime.UtcNow.Subtract(new DateTime(_clickThroughComeBackTicks));
if (diff.TotalSeconds > 2) {
var mousePointer = WindowMethods.GetCursorPos();
if (!this.ContainsMousePointer(mousePointer)) {
if (this.Opacity == ClickThroughHoverOpacity) {
this.Opacity = 1.0;
}
_clickThroughComeBackTimer.Stop();
}
}
}
#endregion
#region Chrome

View file

@ -73,11 +73,10 @@ namespace OnTopReplica {
}
private void Menu_Opacity_click(object sender, EventArgs e) {
//Get clicked menu item
ToolStripMenuItem tsi = sender as ToolStripMenuItem;
ToolStripMenuItem tsi = (ToolStripMenuItem)sender;
if (tsi != null && this.Visible) {
//Get opacity from the tag
if (this.Visible) {
//Target opacity is stored in the item's tag
this.Opacity = (double)tsi.Tag;
Program.Platform.OnFormStateChange(this);
}

View file

@ -21,6 +21,7 @@ namespace OnTopReplica.Native {
public const int NCLBUTTONDOWN = 0x00A1;
public const int NCLBUTTONDBLCLK = 0x00A3;
public const int NCRBUTTONUP = 0x00A5;
public const int NCMOUSELEAVE = 0x02A2;
public const int SYSCOMMAND = 0x0112;
public const int GETTEXT = 0x000D;
public const int GETTEXTLENGTH = 0x000E;

View file

@ -9,6 +9,22 @@ namespace OnTopReplica.Native {
/// </summary>
static class WindowMethods {
public static System.Drawing.Point GetCursorPos() {
NPoint ret;
if (GetCursorPosInternal(out ret))
return ret.ToPoint();
else {
#if DEBUG
throw new InvalidOperationException("Unable to GetCursorPos");
#else
return default(System.Drawing.Point);
#endif
}
}
[DllImport("user32.dll", EntryPoint="GetCursorPos")]
private static extern bool GetCursorPosInternal(out NPoint point);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetClientRect(IntPtr handle, out NRectangle rect);

View file

@ -46,5 +46,17 @@ namespace OnTopReplica {
}
}
/// <summary>
/// Checks whether a control contains a mouse pointer position in screen coordinates.
/// </summary>
/// <param name="screenCoordinates">Mouse pointer position in screen coordinates.</param>
public static bool ContainsMousePointer(this Control ctrl, System.Drawing.Point screenCoordinates) {
var bb = new System.Drawing.Rectangle(ctrl.Location, ctrl.Size);
//Console.Out.WriteLine("<{0},{1}> in {2}? {3}", screenCoordinates.X, screenCoordinates.Y, bb, bb.Contains(screenCoordinates));
return bb.Contains(screenCoordinates);
}
}
}