Widow – Rev 21

Subversion Repositories:
Rev:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using Windows;
using Gma.System.MouseKeyHook;

namespace Widow
{
    public partial class RuleEditForm : Form
    {
        #region Public Enums, Properties and Fields

        public Windows.Windows Windows { get; }

        public MainForm Form { get; set; }

        public DrawOverlayForm DrawOverlayForm { get; set; }

        public IKeyboardMouseEvents GlobalMouseHook { get; set; }

        #endregion

        #region Constructors, Destructors and Finalizers

        public RuleEditForm(MainForm mainForm, Windows.Windows windows) : this(windows)
        {
            Form = mainForm;

            Form.WindowCreated += Form_WindowCreated;
            Form.WindowDestroyed += Form_WindowDestroyed;
        }

        public RuleEditForm(Windows.Windows windows) : this()
        {
            Windows = windows;

            foreach (var window in windows.Window)
            {
                windowRulesListBox.Items.Add(window);
            }
        }

        private RuleEditForm()
        {
            InitializeComponent();

            desktopWindowsListBox.DisplayMember = nameof(Window.Title);
            desktopWindowsListBox.SetDoubleBuffered();
            windowRulesListBox.DisplayMember = nameof(Window.Title);
            windowRulesListBox.SetDoubleBuffered();

            Task.Run(RefreshWindows);
        }

        /// <summary>
        ///     Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null)
            {
                Form.WindowCreated -= Form_WindowCreated;
                Form.WindowDestroyed -= Form_WindowDestroyed;

                components.Dispose();
            }

            base.Dispose(disposing);
        }

        #endregion

        #region Event Handlers

        private void Form_WindowDestroyed(object sender, WindowDestroyedEventArgs e)
        {
            if (string.IsNullOrEmpty(e.Title))
            {
                return;
            }

            var indices = new List<int>();
            for (var i = 0; i < desktopWindowsListBox.Items.Count; ++i)
            {
                if (((Window) desktopWindowsListBox.Items[i]).Title == e.Title)
                {
                    indices.Add(i);
                }
            }

            foreach (var index in indices)
            {
                desktopWindowsListBox.Items.RemoveAt(index);
            }
        }

        private void Form_WindowCreated(object sender, WindowCreatedEventArgs e)
        {
            if (string.IsNullOrEmpty(e.Title))
            {
                return;
            }

            var found = false;
            foreach (var window in desktopWindowsListBox.Items)
            {
                if (((Window) window).Title == e.Title)
                {
                    found = true;
                    break;
                }
            }

            if (found)
            {
                return;
            }

            if (!Natives.GetWindowRect(e.Handle, out var rect))
            {
                return;
            }

            var process = Helpers.GetProcessName(e.Handle);
            if (string.IsNullOrEmpty(process))
            {
                return;
            }

            var newWindow = new Window(process, e.Title, rect.Top, rect.Left, rect.Right - rect.Left,
                rect.Bottom - rect.Top);

            desktopWindowsListBox.Items.Add(newWindow);
        }

        private void WindowRulesListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            var listBox = (ListBox) sender;

            if (listBox.SelectedIndex == -1)
            {
                WindowTitle.Text = string.Empty;
                ignoreLeftCheckBox.Checked = false;
                WindowLeft.Text = string.Empty;
                ignoreTopCheckBox.Checked = false;
                WindowTop.Text = string.Empty;
                ignoreWidthCheckBox.Checked = false;
                WindowWidth.Text = string.Empty;
                ignoreHeightCheckBox.Checked = false;
                WindowHeight.Text = string.Empty;
                return;
            }

            var window = (Window) listBox.SelectedItem;

            if (window == null)
            {
                return;
            }

            WindowTitle.Text = window.Title;
            ignoreLeftCheckBox.Checked = window.IgnoreLeft;
            WindowLeft.Text = window.Left.ToString();
            ignoreTopCheckBox.Checked = window.IgnoreTop;
            WindowTop.Text = window.Top.ToString();
            ignoreWidthCheckBox.Checked = window.IgnoreWidth;
            WindowWidth.Text = window.Width.ToString();
            ignoreHeightCheckBox.Checked = window.IgnoreHeight;
            WindowHeight.Text = window.Height.ToString();
        }

        private void RefreshButton_Click(object sender, EventArgs e)
        {
            Task.Run(RefreshWindows);
        }

        private void RemoveButton_Click(object sender, EventArgs e)
        {
            var window = (Window) windowRulesListBox.SelectedItem;
            if (window == null)
            {
                return;
            }

            var index = -1;
            for (var i = 0; i < windowRulesListBox.Items.Count; ++i)
            {
                if (((Window) windowRulesListBox.Items[i]).Title != window.Title)
                {
                    continue;
                }

                index = i;
                break;
            }

            if (index == -1)
            {
                return;
            }

            windowRulesListBox.Items.RemoveAt(index);
            Windows.Window.Remove(window);
        }

        private void AddButton_Click(object sender, EventArgs e)
        {
            var window = (Window) desktopWindowsListBox.SelectedItem;
            if (window == null)
            {
                return;
            }

            var found = false;
            foreach (var windowRule in windowRulesListBox.Items)
            {
                if (((Window) windowRule).Title != window.Title)
                {
                    continue;
                }

                found = true;
                break;
            }

            if (found)
            {
                return;
            }

            windowRulesListBox.Items.Add(window);
            Windows.Window.Add(window);
        }

        private void OnWindowSettings_TextChanged(object sender, EventArgs e)
        {
            var selectedWindow = (Window) windowRulesListBox.SelectedItem;

            if (selectedWindow == null)
            {
                WindowTitle.Text = string.Empty;
                WindowLeft.Text = string.Empty;
                WindowTop.Text = string.Empty;
                WindowWidth.Text = string.Empty;
                WindowHeight.Text = string.Empty;

                return;
            }

            var textBox = (TextBox) sender;
            switch (textBox.Name)
            {
                case nameof(WindowTitle):
                    selectedWindow.Title = textBox.Text;
                    break;
                case nameof(WindowLeft):
                    if (int.TryParse(textBox.Text, out var left))
                    {
                        selectedWindow.Left = left;
                    }

                    break;
                case nameof(WindowTop):
                    if (int.TryParse(textBox.Text, out var top))
                    {
                        selectedWindow.Top = top;
                    }

                    break;
                case nameof(WindowWidth):
                    if (int.TryParse(textBox.Text, out var width))
                    {
                        selectedWindow.Width = width;
                    }

                    break;
                case nameof(WindowHeight):
                    if (int.TryParse(textBox.Text, out var height))
                    {
                        selectedWindow.Height = height;
                    }

                    break;
            }
        }

        private void OnIgnoreWindowSettings_CheckedChanged(object sender, EventArgs e)
        {
            var selectedWindow = (Window) windowRulesListBox.SelectedItem;

            if (selectedWindow == null)
            {
                ignoreLeftCheckBox.Checked = false;
                ignoreTopCheckBox.Checked = false;
                ignoreWidthCheckBox.Checked = false;
                ignoreHeightCheckBox.Checked = false;

                return;
            }

            var checkBox = (CheckBox) sender;
            switch (checkBox.Name)
            {
                case nameof(ignoreHeightCheckBox):
                    selectedWindow.IgnoreHeight = checkBox.Checked;
                    break;
                case nameof(ignoreWidthCheckBox):
                    selectedWindow.IgnoreWidth = checkBox.Checked;
                    break;
                case nameof(ignoreTopCheckBox):
                    selectedWindow.IgnoreTop = checkBox.Checked;
                    break;
                case nameof(ignoreLeftCheckBox):
                    selectedWindow.IgnoreLeft = checkBox.Checked;
                    break;
            }
        }

        private void DrawButton_Click(object sender, EventArgs e)
        {
            var selectedWindow = (Window) windowRulesListBox.SelectedItem;
            if (selectedWindow == null)
            {
                return;
            }

            if (DrawOverlayForm != null)
            {
                return;
            }

            DrawOverlayForm = new DrawOverlayForm();
            DrawOverlayForm.WindowDrawn += DrawOverlayForm_WindowDrawn;
            DrawOverlayForm.Closed += DrawOverlayForm_Closed;
            DrawOverlayForm.Show();
        }

        private void DrawOverlayForm_WindowDrawn(object sender, WindowDrawnEventArgs e)
        {
            var selectedWindow = (Window) windowRulesListBox.SelectedItem;
            if (selectedWindow == null)
            {
                return;
            }

            WindowLeft.Text = e.Left.ToString();
            WindowTop.Text = e.Top.ToString();
            WindowWidth.Text = e.Width.ToString();
            WindowHeight.Text = e.Height.ToString();

            selectedWindow.Left = e.Left;
            selectedWindow.Top = e.Top;
            selectedWindow.Width = e.Width;
            selectedWindow.Height = e.Height;
        }

        private void DrawOverlayForm_Closed(object sender, EventArgs e)
        {
            DrawOverlayForm.Closed -= DrawOverlayForm_Closed;
            DrawOverlayForm.WindowDrawn -= DrawOverlayForm_WindowDrawn;
            DrawOverlayForm.Dispose();
            DrawOverlayForm = null;
        }

        private void PickButton_Click(object sender, EventArgs e)
        {
            // Start global mouse key hook.
            GlobalMouseHook = Hook.GlobalEvents();
            GlobalMouseHook.MouseClick += GlobalMouseHook_MouseClick;

            // Set cross cursor.
            foreach (var cursor in Enum.GetValues(typeof(Natives.OCR_SYSTEM_CURSORS)))
            {
                Natives.SetSystemCursor(
                    Natives.CopyIcon(Natives.LoadCursor(IntPtr.Zero, (int) Natives.OCR_SYSTEM_CURSORS.OCR_CROSS)),
                    (uint) cursor);
            }
        }

        private void GlobalMouseHook_MouseClick(object sender, MouseEventArgs e)
        {
            var hWnd = Natives.WindowFromPoint(new Point(e.X, e.Y));
            Natives.GetWindowThreadProcessId(hWnd, out var pid);
            var process = Process.GetProcessById((int) pid);
            var windowTitle = Helpers.GetWindowTitle(process.MainWindowHandle);
            if (string.IsNullOrEmpty(windowTitle))
            {
                return;
            }

            var windowClass = Helpers.GetWindowClass(process.MainWindowHandle);
            if (string.IsNullOrEmpty(windowClass))
            {
                return;
            }

            if (!Natives.GetWindowRect(process.MainWindowHandle, out var rect))
            {
                return;
            }

            var window = new Window(windowClass, windowTitle, rect.Top, rect.Left, rect.Right - rect.Left,
                rect.Bottom - rect.Top);

            var found = false;
            foreach (var windowRule in windowRulesListBox.Items)
            {
                if (((Window) windowRule).Title != window.Title)
                {
                    continue;
                }

                found = true;
                break;
            }

            if (found)
            {
                return;
            }

            windowRulesListBox.Items.Add(window);
            Windows.Window.Add(window);

            // Revert cursor.
            Natives.SystemParametersInfo(0x0057, 0, null, 0);

            // Remove global mouse key hook.
            GlobalMouseHook.MouseClick -= GlobalMouseHook_MouseClick;
            GlobalMouseHook.Dispose();
            GlobalMouseHook = null;
        }

        #endregion

        #region Private Methods

        private void RefreshWindows()
        {
            foreach (var handle in Helpers.FindWindows((wnd, param) => true))
            {
                var windowTitle = Helpers.GetWindowTitle(handle);
                if (string.IsNullOrEmpty(windowTitle))
                {
                    continue;
                }

                var windowClass = Helpers.GetWindowClass(handle);
                if (string.IsNullOrEmpty(windowClass))
                {
                    continue;
                }

                if (!Natives.GetWindowRect(handle, out var rect))
                {
                    continue;
                }

                var window = new Window(windowClass, windowTitle, rect.Top, rect.Left, rect.Right - rect.Left,
                    rect.Bottom - rect.Top);

                this.InvokeIfRequired(form =>
                {
                    var found = false;
                    foreach (var item in desktopWindowsListBox.Items)
                    {
                        if (((Window) item).Title != window.Title)
                        {
                            continue;
                        }

                        found = true;
                        break;
                    }

                    if (!found)
                    {
                        desktopWindowsListBox.Items.Add(window);
                    }
                });
            }
        }

        #endregion
    }
}

Generated by GNU Enscript 1.6.5.90.