using System; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows.Forms; using RyzStudio.Windows.Forms; using static CursorGuardRail.MainForm; namespace CursorGuardRail { public partial class MainForm : Form { [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } [DllImport("user32.dll", SetLastError = true)] private static extern bool ClipCursor(ref RECT lpRect); [DllImport("user32.dll", SetLastError = true)] private static extern bool ClipCursor(IntPtr lpRect); private bool _requestExit = false; private Rectangle? _lockCursorArea; private readonly Timer _timer; public MainForm() { InitializeComponent(); screensLayout1.Padding = new Padding(10); _timer = new() { Interval = 50 }; _timer.Tick += (_, _) => { if (Cursor.Clip != _lockCursorArea.Value) { ClipCursor(_lockCursorArea.Value); } }; } protected async override void OnShown(EventArgs e) { base.OnShown(e); await Task.Run(() => { UIControl.Invoke(screensLayout1, (_) => screensLayout1.InvalidateScreens()); }); //memoBox1.Focus(); } protected override void OnFormClosing(FormClosingEventArgs e) { if (!_requestExit) { e.Cancel = true; this.Hide(); return; } ClipCursor(Rectangle.Empty); base.OnFormClosing(e); } public AppSession CurrentSession { get { if (field == null) field = new AppSession(); return field; } private set => field = value; } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public bool IsCursorLocked { get => field; set { field = value; dialogFooter1.Button1.Checked = value; dialogFooter1.Button1Text = value ? "&Unlock Cursor" : "&Lock Cursor"; toolStripMenuItem2.Text = value ? "&Unlock Cursor" : "&Lock Cursor"; if (value) { _lockCursorArea = GetMaxScreenBound(); if (!_lockCursorArea.HasValue || _lockCursorArea == Rectangle.Empty) { this.IsCursorLocked = false; return; } //ClipCursor(_lockCursorArea.Value); _timer.Start(); } else { ClipCursor(Rectangle.Empty); if (_timer.Enabled) { _timer.Stop(); } } } } = false; private void menuStrip1_MenuActivate(object sender, EventArgs e) { //saveAsToolStripMenuItem.Enabled = (!this.IsBusy && (this.SearchPathList.Count > 0)); //toolStripMenuItem2.Enabled = (!this.IsBusy && (_foundFiles.Count > 0)); } #region Main Menu /// /// New /// /// /// private async void newToolStripMenuItem_Click(object sender, EventArgs e) { refreshToolStripMenuItem_Click(sender, e); } /// /// Close /// /// /// private void exitToolStripMenuItem2_Click(object sender, EventArgs e) { _requestExit = true; this.Close(); } /// /// Refresh /// /// /// private async void refreshToolStripMenuItem_Click(object sender, EventArgs e) { await Task.Run(() => { this.IsCursorLocked = false; ClipCursor(Rectangle.Empty); UIControl.Invoke(screensLayout1, (_) => screensLayout1.InvalidateScreens()); }); } /// /// Options /// /// /// private void optionsToolStripMenuItem_Click(object sender, EventArgs e) { // Do nothing } /// /// Help /// /// /// private void viewHelpToolStripMenuItem1_Click(object sender, EventArgs e) { RyzStudio.Diagnostics.Process.Execute(AppResource.AppHelpURL); } /// /// About /// /// /// private void aboutToolStripMenuItem1_Click(object sender, EventArgs e) { var form = new RyzStudio.Forms.T3AboutForm(); form.ProductURL = AppResource.AppProductURL; form.AuthorURL = AppResource.AppAuthorURL; form.CompanyURL = AppResource.AppCompanyURL; form.ProductCopyrightStartYear = 2026; form.ProductLogo = AppResource.icon_64; form.ShowDialog(); } #endregion /// /// Hide/show /// /// /// private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) { if (this.Visible) { this.Hide(); } else { this.Show(); } } /// /// Lock/unlock cursor /// /// /// private void toolStripMenuItem2_Click(object sender, EventArgs e) { this.IsCursorLocked = !this.IsCursorLocked; } /// /// Refresh /// /// /// private async void button1_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { refreshToolStripMenuItem_Click(sender, e); } } /// /// Open display settings /// /// /// private async void button2_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) { try { Process.Start(new ProcessStartInfo { FileName = "ms-settings:display", UseShellExecute = true }); } catch (Exception) { // Do nothing } } } /// /// Enable /// /// /// private async void dialogFooter1_OnButton1Click(object sender, MouseEventArgs e) { this.IsCursorLocked = !this.IsCursorLocked; } /// /// Close /// /// /// private void dialogFooter1_OnButton2Click(object sender, MouseEventArgs e) { this.Close(); } private Rectangle GetMaxScreenBound() { Rectangle? rect = null; for (var i = 0; i < screensLayout1.Screens.Count; i++) { if (!screensLayout1.Screens[i].IsSelected) { continue; } if (rect == null) { rect = Screen.AllScreens[i].Bounds; } else { rect = Rectangle.Union(Screen.AllScreens[i].Bounds, rect.Value); } } return rect ?? Rectangle.Empty; } private void ClipCursor(Rectangle rect) { if (rect == Rectangle.Empty) { ClipCursor(IntPtr.Zero); } else { var rect2 = new RECT { Left = rect.X, Top = rect.Y, Right = rect.Width, Bottom = rect.Height }; ClipCursor(ref rect2); } } } }