Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
markuskonojacki committed May 27, 2021
1 parent d72ec04 commit 5332610
Show file tree
Hide file tree
Showing 35 changed files with 5,767 additions and 0 deletions.
20 changes: 20 additions & 0 deletions mkCursorClip.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "mkCursorClip", "mkCursorClip\mkCursorClip.csproj", "{5E8680DA-881C-4AC4-8B6A-6982644540FB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x86 = Debug|x86
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5E8680DA-881C-4AC4-8B6A-6982644540FB}.Debug|x86.ActiveCfg = Debug|x86
{5E8680DA-881C-4AC4-8B6A-6982644540FB}.Debug|x86.Build.0 = Debug|x86
{5E8680DA-881C-4AC4-8B6A-6982644540FB}.Release|x86.ActiveCfg = Release|x86
{5E8680DA-881C-4AC4-8B6A-6982644540FB}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
8 changes: 8 additions & 0 deletions mkCursorClip/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Application x:Class="mkCursorClip.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>

</Application.Resources>
</Application>
16 changes: 16 additions & 0 deletions mkCursorClip/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;

namespace mkCursorClip
{
/// <summary>
/// Interaktionslogik für "App.xaml"
/// </summary>
public partial class App : Application
{
}
}
7 changes: 7 additions & 0 deletions mkCursorClip/MainWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Window x:Class="mkCursorClip.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="http://www.hardcodet.net/taskbar"
Title="MainWindow" Height="0" Width="0"
ShowInTaskbar="False" WindowStyle="None" Loaded="Window_Loaded" Opacity="0" Visibility="Hidden">
</Window>
234 changes: 234 additions & 0 deletions mkCursorClip/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using Hardcodet.Wpf.TaskbarNotification;
using RamGecTools;

namespace mkCursorClip
{
public partial class MainWindow : Window
{
mkCursorClip.Properties.Settings config = mkCursorClip.Properties.Settings.Default;
public MainWindow()
{
InitializeComponent();
this.addNotifycationIcon();
this.initKeyboardHook();
}

#region keyboardHook handling
KeyboardHook keyboardHook = new KeyboardHook();
bool keyOneDown = false;
bool keyTwoDown = false;
KeyboardHook.VKeys keyOne;
KeyboardHook.VKeys keyTwo;

private void initKeyboardHook()
{
keyboardHook.KeyDown += new KeyboardHook.KeyboardHookCallback(keyboardHook_KeyDown);
keyboardHook.KeyUp += new KeyboardHook.KeyboardHookCallback(keyboardHook_KeyUp);
keyboardHook.Install();

}

void keyboardHook_KeyUp(KeyboardHook.VKeys key, ref bool handled)
{
if (key == keyOne)
keyOneDown = false;
if (key == keyTwo)
keyTwoDown = false;
}

void keyboardHook_KeyDown(KeyboardHook.VKeys key, ref bool handled)
{
config.Reload();
keyOne = (KeyboardHook.VKeys)Enum.Parse(typeof(KeyboardHook.VKeys), config.keyOne);
keyTwo = (KeyboardHook.VKeys)Enum.Parse(typeof(KeyboardHook.VKeys), config.keyTwo);

if (key == keyOne)
keyOneDown = true;
if (key == keyTwo)
keyTwoDown = true;

if (keyOneDown && keyTwoDown)
{
this.toggleClip();
handled = true;
}
}
#endregion

/// <summary>
/// check for keyTwoDown and LControl to be pressed and clips cursor to window
/// </summary>
#region WinAPI for window picking
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
static extern bool GetWindowRect(IntPtr hWnd, out Rect lpRect);

[StructLayout(LayoutKind.Sequential)]
private struct Rect
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
#endregion
bool windowHooked = false; // TODO: replace with x/y check of cursor
Rect rect = new Rect();
private void toggleClip()
{
config.Reload();
int leftBorder = config.left;
int rightBorder = config.right + config.left;
int topBorder = config.top;
int bottomBorder = config.top + config.bottom;

if (windowHooked == true)
{
System.Windows.Forms.Cursor.Clip = System.Drawing.Rectangle.Empty;
windowHooked = false;
}
else
{
GetWindowRect(GetForegroundWindow(), out rect);
System.Windows.Forms.Cursor.Clip = new System.Drawing.Rectangle(rect.Left + leftBorder,
rect.Top + topBorder,
rect.Right - rect.Left - rightBorder,
rect.Bottom - rect.Top - bottomBorder);
windowHooked = true;
}
}

/// <summary>
/// Generates and adds the notification icon to the tray
/// </summary>
private void addNotifycationIcon()
{
TaskbarIcon notifyIcon = new TaskbarIcon();
System.Windows.Controls.ContextMenu notifyMenu = new System.Windows.Controls.ContextMenu();
System.Windows.Controls.MenuItem settingsItem = new System.Windows.Controls.MenuItem();
System.Windows.Controls.MenuItem exitItem = new System.Windows.Controls.MenuItem();

settingsItem.Header = "Settings";
settingsItem.Click += new RoutedEventHandler(settingsItem_Click);
notifyMenu.Items.Add(settingsItem);

exitItem.Header = "Exit";
exitItem.Click += new RoutedEventHandler(exitItem_Click);
notifyMenu.Items.Add(exitItem);

notifyIcon.ToolTipText = "mkCursorClip";
notifyIcon.IconSource = System.Windows.Media.Imaging.BitmapFrame.Create(new System.Uri("pack://application:,,,/mkCursorClip.ico"));
notifyIcon.ContextMenu = notifyMenu;
}

/// <summary>
/// context menu item 'Exit'
/// </summary>
void exitItem_Click(object sender, RoutedEventArgs e)
{
this.Close();
}

/// <summary>
/// context menu item 'Settings'
/// </summary>
SettingsWindow settingsWindow;
bool settingsWindowOpen = false;
void settingsItem_Click(object sender, RoutedEventArgs e)
{
if (settingsWindowOpen)
{
settingsWindow.Focus();
}
else
{
settingsWindow = new SettingsWindow();
settingsWindow.Show();
settingsWindow.Closed += new EventHandler(settingsWindow_Closed);
settingsWindowOpen = true;
}
}

void settingsWindow_Closed(object sender, EventArgs e)
{
settingsWindow = null;
settingsWindowOpen = false;
}

#region Window styles (Hide from Alt+Tab)
[Flags]
public enum ExtendedWindowStyles
{
// ...
WS_EX_TOOLWINDOW = 0x00000080,
// ...
}

public enum GetWindowLongFields
{
// ...
GWL_EXSTYLE = (-20),
// ...
}

[DllImport("user32.dll")]
public static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);

public static IntPtr SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong)
{
int error = 0;
IntPtr result = IntPtr.Zero;
// Win32 SetWindowLong doesn't clear error on success
SetLastError(0);

if (IntPtr.Size == 4)
{
// use SetWindowLong
Int32 tempResult = IntSetWindowLong(hWnd, nIndex, IntPtrToInt32(dwNewLong));
error = Marshal.GetLastWin32Error();
result = new IntPtr(tempResult);
}
else
{
// use SetWindowLongPtr
result = IntSetWindowLongPtr(hWnd, nIndex, dwNewLong);
error = Marshal.GetLastWin32Error();
}

if ((result == IntPtr.Zero) && (error != 0))
{
throw new System.ComponentModel.Win32Exception(error);
}

return result;
}

[DllImport("user32.dll", EntryPoint = "SetWindowLongPtr", SetLastError = true)]
private static extern IntPtr IntSetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

[DllImport("user32.dll", EntryPoint = "SetWindowLong", SetLastError = true)]
private static extern Int32 IntSetWindowLong(IntPtr hWnd, int nIndex, Int32 dwNewLong);

private static int IntPtrToInt32(IntPtr intPtr)
{
return unchecked((int)intPtr.ToInt64());
}

[DllImport("kernel32.dll", EntryPoint = "SetLastError")]
public static extern void SetLastError(int dwErrorCode);
#endregion
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper wndHelper = new WindowInteropHelper(this);
int exStyle = (int)GetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE);
exStyle |= (int)ExtendedWindowStyles.WS_EX_TOOLWINDOW;
SetWindowLong(wndHelper.Handle, (int)GetWindowLongFields.GWL_EXSTYLE, (IntPtr)exStyle);
}
}
}
55 changes: 55 additions & 0 deletions mkCursorClip/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;

// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die mit einer Assembly verknüpft sind.
[assembly: AssemblyTitle("mkCursorClip")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mkCursorClip")]
[assembly: AssemblyCopyright("Copyright © 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
[assembly: ComVisible(false)]

//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
//<UICulture>ImCodeVerwendeteKultur</UICulture> in der .csproj-Datei
//in einer <PropertyGroup> fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
//(Deutschland) verwenden, legen Sie <UICulture> auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.

//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]


[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
//(wird verwendet, wenn eine Ressource auf der Seite
// oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
//(wird verwendet, wenn eine Ressource auf der Seite, in der Anwendung oder einem
// designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
)]


// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Loading

0 comments on commit 5332610

Please sign in to comment.