diff --git a/Logic/ApplicationSettings.cs b/Logic/ApplicationSettings.cs
index 7f10264d..192ce7c8 100644
--- a/Logic/ApplicationSettings.cs
+++ b/Logic/ApplicationSettings.cs
@@ -37,9 +37,9 @@ public class ApplicationSettings
private static string _default = "default";
// Application Specific Settings we want to protect
- private string _clientVersion = "1.7.1";
+ private string _clientVersion = "1.7.2";
private string _version = "4";
- private int _clientCodeVersion = 105;
+ private int _clientCodeVersion = 106;
public string ClientVersion { get { return _clientVersion; } }
public string Version { get { return _version; } }
diff --git a/Logic/KeyInterceptor.cs b/Logic/KeyInterceptor.cs
new file mode 100644
index 00000000..514bcb85
--- /dev/null
+++ b/Logic/KeyInterceptor.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Diagnostics;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+
+namespace XiboClient
+{
+ ///
+ /// Adapted from: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
+ ///
+ class KeyInterceptor
+ {
+ private const int WH_KEYBOARD_LL = 13;
+ private const int WM_KEYDOWN = 0x0100;
+ private static LowLevelKeyboardProc _proc = HookCallback;
+ private static IntPtr _hookId = IntPtr.Zero;
+
+ public static void SetHook()
+ {
+ using (Process curProcess = Process.GetCurrentProcess())
+ {
+ using (ProcessModule curModule = curProcess.MainModule)
+ {
+ SetWindowsHookEx(WH_KEYBOARD_LL, _proc, GetModuleHandle(curModule.ModuleName), 0);
+ }
+ }
+ }
+
+ public static void UnsetHook()
+ {
+ UnhookWindowsHookEx(_hookId);
+ }
+
+ private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (nCode >= 0)
+ {
+ KeyStore.Instance.HandleRawKey(wParam, lParam);
+ }
+
+ return CallNextHookEx(_hookId, nCode, wParam, lParam);
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool UnhookWindowsHookEx(IntPtr hhk);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr GetModuleHandle(string lpModuleName);
+ }
+}
\ No newline at end of file
diff --git a/Logic/KeyStore.cs b/Logic/KeyStore.cs
index 0795d53a..b5e67891 100644
--- a/Logic/KeyStore.cs
+++ b/Logic/KeyStore.cs
@@ -83,6 +83,34 @@ public bool PreFilterMessage(ref Message m)
return handled;
}
+ ///
+ /// Handle Raw Keypresses
+ ///
+ ///
+ ///
+ public void HandleRawKey(IntPtr wParam, IntPtr lParam)
+ {
+ bool handled = false;
+ Keys key = Keys.None;
+
+ if (wParam == (IntPtr)WM_KEYDOWN)
+ {
+ key = (Keys)Marshal.ReadInt32(lParam);
+ handled = HandleModifier(key, false);
+ }
+ else if (wParam == (IntPtr)WM_KEYUP)
+ {
+ key = (Keys)Marshal.ReadInt32(lParam);
+ handled = HandleModifier(key, true);
+ if (false == handled)
+ {
+ // If one of the defined keys was pressed then we
+ // raise an event.
+ handled = HandleDefinedKey(key);
+ }
+ }
+ }
+
///
/// Compares a key against the definitions, and raises an event
/// if there is a match.
diff --git a/Logic/MouseInterceptor.cs b/Logic/MouseInterceptor.cs
new file mode 100644
index 00000000..843c6c29
--- /dev/null
+++ b/Logic/MouseInterceptor.cs
@@ -0,0 +1,122 @@
+using System;
+using System.Diagnostics;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+using System.Drawing;
+
+namespace XiboClient.Logic
+{
+ public delegate void MouseInterceptorEventHandler();
+
+ ///
+ /// Adapted From: http://blogs.msdn.com/b/toub/archive/2006/05/03/589468.aspx
+ ///
+ class MouseInterceptor
+ {
+ private static LowLevelMouseProc _proc = HookCallback;
+ private static IntPtr _hookID = IntPtr.Zero;
+
+ private static MouseInterceptor s_instance = null;
+ // The KeyPressed Event
+ public event MouseInterceptorEventHandler MouseEvent;
+
+ private static Point _mouseLocation;
+
+ public static IntPtr SetHook()
+ {
+ using (Process curProcess = Process.GetCurrentProcess())
+ using (ProcessModule curModule = curProcess.MainModule)
+ {
+ return SetWindowsHookEx(WH_MOUSE_LL, _proc, GetModuleHandle(curModule.ModuleName), 0);
+ }
+ }
+
+ public static void UnsetHook()
+ {
+ UnhookWindowsHookEx(_hookID);
+ }
+
+ private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam);
+
+ private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
+ {
+ if (nCode >= 0)
+ {
+ if (MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam || MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam)
+ {
+ MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));
+ Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y);
+
+ if (Math.Abs(_mouseLocation.X - hookStruct.pt.x) > 5 || Math.Abs(_mouseLocation.Y - hookStruct.pt.y) > 5)
+ {
+ if (MouseInterceptor.s_instance != null && MouseInterceptor.s_instance.MouseEvent != null)
+ MouseInterceptor.s_instance.MouseEvent();
+ }
+
+ _mouseLocation = new Point(hookStruct.pt.x, hookStruct.pt.y);
+ }
+ }
+
+ return CallNextHookEx(_hookID, nCode, wParam, lParam);
+ }
+
+ ///
+ /// Returns the singleton instance.
+ ///
+ public static MouseInterceptor Instance
+ {
+ get
+ {
+ if (null == s_instance)
+ s_instance = new MouseInterceptor();
+
+ return s_instance;
+ }
+ }
+
+ private const int WH_MOUSE_LL = 14;
+
+ private enum MouseMessages
+ {
+ WM_LBUTTONDOWN = 0x0201,
+ WM_LBUTTONUP = 0x0202,
+ WM_MOUSEMOVE = 0x0200,
+ WM_MOUSEWHEEL = 0x020A,
+ WM_RBUTTONDOWN = 0x0204,
+ WM_RBUTTONUP = 0x0205
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct POINT
+ {
+ public int x;
+ public int y;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct MSLLHOOKSTRUCT
+ {
+ public POINT pt;
+ public uint mouseData;
+ public uint flags;
+ public uint time;
+ public IntPtr dwExtraInfo;
+ }
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr SetWindowsHookEx(int idHook,
+ LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool UnhookWindowsHookEx(IntPtr hhk);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
+ IntPtr wParam, IntPtr lParam);
+
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ private static extern IntPtr GetModuleHandle(string lpModuleName);
+
+ }
+}
diff --git a/MainForm.cs b/MainForm.cs
index d9d04a14..af7a416a 100644
--- a/MainForm.cs
+++ b/MainForm.cs
@@ -38,6 +38,7 @@
using System.Runtime.InteropServices;
using System.Globalization;
using Xilium.CefGlue;
+using XiboClient.Logic;
namespace XiboClient
{
@@ -49,7 +50,6 @@ public partial class MainForm : Form
private int _scheduleId;
private int _layoutId;
private bool _screenSaver = false;
- private Point _mouseLocation;
double _layoutWidth;
double _layoutHeight;
@@ -95,7 +95,6 @@ enum EXECUTION_STATE : uint
public MainForm(IntPtr previewHandle)
{
InitializeComponent();
- InitializeCommon();
// Set the preview window of the screen saver selection
// dialog in Windows as the parent of this form.
@@ -122,7 +121,6 @@ public MainForm(IntPtr previewHandle)
public MainForm(bool screenSaver)
{
InitializeComponent();
- InitializeCommon();
if (screenSaver)
InitializeScreenSaver(false);
@@ -133,16 +131,9 @@ public MainForm(bool screenSaver)
public MainForm()
{
InitializeComponent();
- InitializeCommon();
InitializeXibo();
}
- private void InitializeCommon()
- {
- // Add a message filter
- Application.AddMessageFilter(KeyStore.Instance);
- }
-
private void InitializeXibo()
{
Thread.CurrentThread.Name = "UI Thread";
@@ -220,35 +211,14 @@ private void InitializeScreenSaver(bool preview)
// Configure some listeners for the mouse (to quit)
if (!preview)
{
- MouseMove += ScreenSaverForm_MouseMove;
- MouseDown += ScreenSaverForm_MouseClick;
-
KeyStore.Instance.ScreenSaver = true;
- }
- }
-
- private void ScreenSaverForm_MouseMove(object sender, MouseEventArgs e)
- {
- if (!_screenSaver)
- return;
- if (!_mouseLocation.IsEmpty)
- {
- // Terminate if mouse is moved a significant distance
- if (Math.Abs(_mouseLocation.X - e.X) > 5 ||
- Math.Abs(_mouseLocation.Y - e.Y) > 5)
- Application.Exit();
+ MouseInterceptor.Instance.MouseEvent += Instance_MouseEvent;
}
-
- // Update current mouse location
- _mouseLocation = e.Location;
}
- private void ScreenSaverForm_MouseClick(object sender, MouseEventArgs e)
+ void Instance_MouseEvent()
{
- if (!_screenSaver)
- return;
-
Close();
}
@@ -258,6 +228,7 @@ private void ScreenSaverForm_MouseClick(object sender, MouseEventArgs e)
///
void Instance_KeyPress(string name)
{
+ Debug.WriteLine("KeyPress " + name);
if (name == "ClientInfo")
{
// Toggle
@@ -271,6 +242,7 @@ void Instance_KeyPress(string name)
}
else if (name == "ScreenSaver")
{
+ Debug.WriteLine("Closing due to ScreenSaver key press");
if (!_screenSaver)
return;
@@ -328,7 +300,8 @@ private void MainForm_Load(object sender, EventArgs e)
Cursor.Hide();
// Move the cursor to the starting place
- SetCursorStartPosition();
+ if (!_screenSaver)
+ SetCursorStartPosition();
// Show the splash screen
ShowSplashScreen();
diff --git a/Program.cs b/Program.cs
index c5779161..9600d8e4 100644
--- a/Program.cs
+++ b/Program.cs
@@ -23,6 +23,7 @@
using System.Runtime.InteropServices;
using System.Diagnostics;
using Xilium.CefGlue;
+using XiboClient.Logic;
namespace XiboClient
{
@@ -91,12 +92,20 @@ static int Main(string[] args)
// Preview the screen saver
case "/p":
// args[1] is the handle to the preview window
+ KeyInterceptor.SetHook();
+ MouseInterceptor.SetHook();
RunClient(new IntPtr(long.Parse(args[1])));
+ KeyInterceptor.UnsetHook();
+ MouseInterceptor.UnsetHook();
break;
// Show the screen saver
case "/s":
+ KeyInterceptor.SetHook();
+ MouseInterceptor.SetHook();
RunClient(true);
+ KeyInterceptor.UnsetHook();
+ MouseInterceptor.UnsetHook();
break;
// Configure the screesaver's settings
@@ -107,13 +116,20 @@ static int Main(string[] args)
// Show the screen saver
default:
+ KeyInterceptor.SetHook();
+ MouseInterceptor.SetHook();
RunClient(true);
+ KeyInterceptor.UnsetHook();
+ MouseInterceptor.UnsetHook();
break;
}
}
}
else
{
+ // Add a message filter
+ Application.AddMessageFilter(KeyStore.Instance);
+
// No arguments were passed - we run the usual client
RunClient();
}
diff --git a/XiboClient.csproj b/XiboClient.csproj
index 0fec522d..ca96c04b 100644
--- a/XiboClient.csproj
+++ b/XiboClient.csproj
@@ -114,7 +114,9 @@
+
+
diff --git a/XiboClient.v11.suo b/XiboClient.v11.suo
index 713c8791..16ab26eb 100644
Binary files a/XiboClient.v11.suo and b/XiboClient.v11.suo differ
diff --git a/bin/x86/Release/Xibo.scr b/bin/x86/Release/Xibo.scr
index aeb4b0ae..48614be5 100644
Binary files a/bin/x86/Release/Xibo.scr and b/bin/x86/Release/Xibo.scr differ
diff --git a/bin/x86/Release/XiboClient.XmlSerializers.dll b/bin/x86/Release/XiboClient.XmlSerializers.dll
index 6a573388..e5c38891 100644
Binary files a/bin/x86/Release/XiboClient.XmlSerializers.dll and b/bin/x86/Release/XiboClient.XmlSerializers.dll differ
diff --git a/bin/x86/Release/XiboClient.exe b/bin/x86/Release/XiboClient.exe
index aeb4b0ae..13519de0 100644
Binary files a/bin/x86/Release/XiboClient.exe and b/bin/x86/Release/XiboClient.exe differ
diff --git a/bin/x86/Release/XiboClient.pdb b/bin/x86/Release/XiboClient.pdb
index c14ebe60..55f5e965 100644
Binary files a/bin/x86/Release/XiboClient.pdb and b/bin/x86/Release/XiboClient.pdb differ