public partial class LockScreenView : Window
{
public LockScreenView()
{
InitializeComponent();
// Create canvas border
m_canvasBorder = new Rectangle();
m_canvasBorder.Stroke = System.Windows.Media.Brushes.Red;
m_canvasBorder.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
m_canvasBorder.VerticalAlignment = System.Windows.VerticalAlignment.Top;
m_canvasBorder.RadiusX = m_canvasBorder.RadiusY = 5;
Grid.SetColumnSpan(m_canvasBorder, 2);
Grid.SetRow(m_canvasBorder, 1);
MainGrid.Children.Add(m_canvasBorder);
this.m_isEnableDWM = this.CheckDWM();
this.InitializeIOCtrl();
this.EnableLockScreen = true;
FocusManager.SetFocusedElement(this, this.txtPassword);
}
private void OnLogin(object sender, RoutedEventArgs e)
{
if (AppClient.Instance.XXXService.VerifyUser(AppClient.Instance.ClientID, this.txtUserName.Text, this.txtPassword.Password))
{
AppClient.Instance.UserContext.CurrentLockCount = AppClient.Instance.UserContext.AutoLockCount;
AppClient.Instance.UserMode = UserMode.None;
this.EnableLockScreen = false;
this.Close();
}
else
{
txtPassword.Clear();
}
}
private void OnLogOff(object sender, RoutedEventArgs e)
{
}
protected override void OnClosed(EventArgs e)
{
if (this.m_event != null)
this.m_event.Close();
if (this.m_file != null)
this.m_file.Close();
base.OnClosed(e);
}
private void WindowSizeChanged(object sender, SizeChangedEventArgs e)
{
var left = this.MainGrid.ColumnDefinitions[0].ActualWidth - this.MainCanvas.ActualWidth / 2;
var top = this.MainGrid.RowDefinitions[0].ActualHeight;
var rect = new System.Drawing.Rectangle((int)left, (int)top, (int)this.MainCanvas.Width, (int)this.MainCanvas.Height);
// Draw border
m_canvasBorder.Width = rect.Width;
m_canvasBorder.Height = rect.Height;
m_canvasBorder.Margin = new Thickness(181, 0, 182, 0);
if (!this.m_isEnableDWM) return;
// Obtain the window handle for WPF application
IntPtr mainWindowPtr = new WindowInteropHelper(this).Handle;
HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(mainWindowPtr);
NativeMethods.DWM_BLURBEHIND blurBehind;
blurBehind.dwFlags = NativeMethods.DWM_BB.Enable | NativeMethods.DWM_BB.BlurRegion;
blurBehind.fEnable = true;
blurBehind.fTransitionOnMaximized = false;
blurBehind.hRgnBlur = IntPtr.Zero;
var rgn = RoundedRectangle.CreateRegion(rect);
blurBehind.hRgnBlur = rgn.GetHrgn(desktop);
NativeMethods.DwmEnableBlurBehindWindow(mainWindowSrc.Handle, ref blurBehind);
rgn.Dispose();
}
private void InitializeIOCtrl()
{
var file = NativeMethods.CreateFile(NativeMethods.DOS_DEVICE_NAME,
NativeMethods.GENERIC_READ | NativeMethods.GENERIC_WRITE, 0, IntPtr.Zero, NativeMethods.OPEN_EXISTING, 0, IntPtr.Zero);
m_file = new SafeFileHandle(file, true);
if (m_file.IsInvalid == false)
m_event = new ManualResetEvent(false);
}
private bool EnableLockScreen
{
set
{
if (value != m_isEnableLS)
{
if (value == true)
enableToolStripMenuItem_Click(this, new EventArgs());
else
disableToolStripMenuItem_Click(this, new EventArgs());
m_isEnableLS = value;
}
}
}
private void enableToolStripMenuItem_Click(object sender, EventArgs e)
{
if (m_file.IsInvalid == false)
{
uint bytesReturned = 0;
if (m_isSetFilterData == false)
{
unsafe
{
var ioCtrl = NativeMethods.CTL_CODE(
NativeMethods.FILE_DEVICE_KEYBOARD_FILTER,
NativeMethods.IOCTL_KEYBOARD_FILTER_SET_EVENT,
NativeMethods.METHOD_BUFFERED,
NativeMethods.FILE_ANY_ACCESS
);
int handle = m_event.SafeWaitHandle.DangerousGetHandle().ToInt32();
int* pHandle = &handle;
var ret = NativeMethods.DeviceIoControl(m_file.DangerousGetHandle(), ioCtrl, (IntPtr)(pHandle), 4, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
List<ushort[]> listFd = new List<ushort[]>();
listFd.Add(NativeMethods.GetSAS_L());
listFd.Add(NativeMethods.GetSAS_R());
listFd.Add(NativeMethods.GetTaskSwitch());
listFd.Add(NativeMethods.GetTaskSwitch3D_L());
listFd.Add(NativeMethods.GetTaskSwitch3D_R());
listFd.Add(NativeMethods.GetWin_L());
listFd.Add(NativeMethods.GetWin_R());
int size = listFd.Count * FILTER_DATA_LENGTH;
ushort* fd = stackalloc ushort[size];
ushort* tmp = fd;
for (int i = 0; i < listFd.Count; ++i)
{
for (int j = 0; j < FILTER_DATA_LENGTH; ++j, ++tmp)
{
*tmp = listFd[i][j];
}
}
ioCtrl = NativeMethods.CTL_CODE(
NativeMethods.FILE_DEVICE_KEYBOARD_FILTER,
NativeMethods.IOCTL_KEYBOARD_FILTER_SET_KEY,
NativeMethods.METHOD_BUFFERED,
NativeMethods.FILE_ANY_ACCESS
);
ret = NativeMethods.DeviceIoControl(m_file.DangerousGetHandle(), ioCtrl, (IntPtr)(fd), (uint)size * 2, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
m_isSetFilterData = true;
}
}
m_event.Set();
}
}
private void disableToolStripMenuItem_Click(object sender, EventArgs e)
{
if (m_file.IsInvalid == false)
{
m_event.Reset();
}
}
private bool CheckDWM()
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version.Major >= 6)
{
if (NativeMethods.DwmIsCompositionEnabled() == false)
return false;
else
return true;
}
else
return false;
}
private SafeFileHandle m_file = null;
private ManualResetEvent m_event = null;
private bool m_isSetFilterData = false; // Indicate if filter data is sent to kernel
private bool m_isEnableLS = false;
private const int FILTER_DATA_LENGTH = 4;
private bool m_isEnableDWM = false;
private Rectangle m_canvasBorder;
}
internal class NativeMethods
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern IntPtr CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern bool DeviceIoControl(
IntPtr hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
uint nInBufferSize,
IntPtr lpOutBuffer,
uint nOutBufferSize,
out uint lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern bool DwmIsCompositionEnabled();
[DllImport("dwmapi.dll")]
public static extern void DwmEnableBlurBehindWindow(IntPtr hwnd, ref DWM_BLURBEHIND blurBehind);
public static uint CTL_CODE(uint DeviceType, uint Function, uint Method, uint Access)
{
return ((DeviceType << 16) | (Access << 14) | (Function << 2) | Method);
}
public static ushort[] GetSAS_L()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_CTRL;
fd[1] = KEY_DEL;
fd[2] = KEY_ALT;
fd[3] = KEY_NUM;
return fd;
}
public static ushort[] GetSAS_R()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_CTRL;
fd[1] = KEY_DEL;
fd[2] = KEY_ALT;
fd[3] = KEY_NUM_PERIOD;
return fd;
}
public static ushort[] GetTaskSwitch()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_ALT;
fd[1] = KEY_TAB;
return fd;
}
public static ushort[] GetWin_L()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_LWIN;
return fd;
}
public static ushort[] GetWin_R()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_RWIN;
return fd;
}
public static ushort[] GetTaskSwitch3D_L()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_LWIN;
fd[1] = KEY_TAB;
return fd;
}
public static ushort[] GetTaskSwitch3D_R()
{
var fd = new ushort[FILTER_DATA_LENGTH];
fd[0] = KEY_RWIN;
fd[1] = KEY_TAB;
return fd;
}
[Flags]
public enum DWM_BB
{
Enable = 1,
BlurRegion = 2,
TransitionMaximized = 4
}
[Flags]
public enum SendMessageTimeoutFlags
{
SMTO_NORMAL = 0x0,
SMTO_BLOCK = 0x1,
SMTO_ABORTIFHUNG = 0x2,
SMTO_NOTIMEOUTIFNOTHUNG = 0x8
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Right;
public int Top;
public int Bottom;
};
[StructLayout(LayoutKind.Sequential)]
public struct DWM_BLURBEHIND
{
public DWM_BB dwFlags;
public bool fEnable;
public IntPtr hRgnBlur;
public bool fTransitionOnMaximized;
}
public const short FILE_ATTRIBUTE_NORMAL = 0x80;
public const short INVALID_HANDLE_VALUE = -1;
public const uint GENERIC_READ = 0x80000000;
public const uint GENERIC_WRITE = 0x40000000;
public const uint CREATE_NEW = 1;
public const uint CREATE_ALWAYS = 2;
public const uint OPEN_EXISTING = 3;
public const uint METHOD_BUFFERED = 0;
public const uint METHOD_IN_DIRECT = 1;
public const uint METHOD_OUT_DIRECT = 2;
public const uint METHOD_NEITHER = 3;
public const uint FILE_ANY_ACCESS = 0;
public const uint FILE_READ_ACCESS = 0x0001;
public const uint FILE_WRITE_ACCESS = 0x0002;
public const uint FILE_DEVICE_KEYBOARD_FILTER = 0x8000;
public const uint IOCTL_KEYBOARD_FILTER_SET_EVENT = 1;
public const uint IOCTL_KEYBOARD_FILTER_CLEAR_EVENT = 2;
public const uint IOCTL_KEYBOARD_FILTER_SET_KEY = 4;
public const string DOS_DEVICE_NAME = "\\.\aKbFilter";
public const int ERROR_TIMEOUT = 1460;
public const int ERROR_INVALID_WINDOW_HANDLE = 1400;
public const int ERROR_SUCCESS = 0;
public const int ERROR_LOGIN_FAIL = 1;
public const int ERROR_INVALID_LOGIN = 2;
public const int ERROR_INVALID_PWD = 3;
public const int ERROR_INVALID_USERNAME = 4;
public const int MAX_NAME_PWD_LENGTH = 32;
public const int MAX_TIME_OUT = 2000;
public const int MAX_PATH = 260;
private const int FILTER_DATA_LENGTH = 4;
private const ushort KEY_CTRL = 0x1D;
private const ushort KEY_ALT = 0x38;
private const ushort KEY_DEL = 0x53;
private const ushort KEY_NUM = 0x2A;
private const ushort KEY_TAB = 0x0F;
private const ushort KEY_NUM_PERIOD = 0x53;
private const ushort KEY_LWIN = 0x5B;
private const ushort KEY_RWIN = 0x5C;
}
public abstract class RoundedRectangle
{
public enum RectangleCorners
{
None = 0, TopLeft = 1, TopRight = 2, BottomLeft = 4, BottomRight = 8,
All = TopLeft | TopRight | BottomLeft | BottomRight
}
public static GraphicsPath Create(int x, int y, int width, int height,
int radius, RectangleCorners corners)
{
int xw = x + width;
int yh = y + height;
int xwr = xw - radius;
int yhr = yh - radius;
int xr = x + radius;
int yr = y + radius;
int r2 = radius * 2;
int xwr2 = xw - r2;
int yhr2 = yh - r2;
GraphicsPath p = new GraphicsPath();
p.StartFigure();
//Top Left Corner
if ((RectangleCorners.TopLeft & corners) == RectangleCorners.TopLeft)
{
p.AddArc(x, y, r2, r2, 180, 90);
}
else
{
p.AddLine(x, yr, x, y);
p.AddLine(x, y, xr, y);
}
//Top Edge
p.AddLine(xr, y, xwr, y);
//Top Right Corner
if ((RectangleCorners.TopRight & corners) == RectangleCorners.TopRight)
{
p.AddArc(xwr2, y, r2, r2, 270, 90);
}
else
{
p.AddLine(xwr, y, xw, y);
p.AddLine(xw, y, xw, yr);
}
//Right Edge
p.AddLine(xw, yr, xw, yhr);
//Bottom Right Corner
if ((RectangleCorners.BottomRight & corners) == RectangleCorners.BottomRight)
{
p.AddArc(xwr2, yhr2, r2, r2, 0, 90);
}
else
{
p.AddLine(xw, yhr, xw, yh);
p.AddLine(xw, yh, xwr, yh);
}
//Bottom Edge
p.AddLine(xwr, yh, xr, yh);
//Bottom Left Corner
if ((RectangleCorners.BottomLeft & corners) == RectangleCorners.BottomLeft)
{
p.AddArc(x, yhr2, r2, r2, 90, 90);
}
else
{
p.AddLine(xr, yh, x, yh);
p.AddLine(x, yh, x, yhr);
}
//Left Edge
p.AddLine(x, yhr, x, yr);
p.CloseFigure();
return p;
}
public static GraphicsPath Create(System.Drawing.Rectangle rect, int radius, RectangleCorners c)
{ return Create(rect.X, rect.Y, rect.Width, rect.Height, radius, c); }
public static GraphicsPath Create(int x, int y, int width, int height, int radius)
{ return Create(x, y, width, height, radius, RectangleCorners.All); }
public static GraphicsPath Create(System.Drawing.Rectangle rect, int radius)
{ return Create(rect.X, rect.Y, rect.Width, rect.Height, radius); }
public static GraphicsPath Create(int x, int y, int width, int height)
{ return Create(x, y, width, height, 5); }
public static GraphicsPath Create(System.Drawing.Rectangle rect)
{ return Create(rect.X, rect.Y, rect.Width, rect.Height); }
public static System.Drawing.Region CreateRegion(System.Drawing.Rectangle rect)
{ return new System.Drawing.Region(Create(rect.X, rect.Y, rect.Width, rect.Height)); }
}