diff --git a/src/Jiayi.UI/Core/KeyCode.cs b/src/Jiayi.UI/Core/KeyCode.cs new file mode 100644 index 0000000..ab7f18f --- /dev/null +++ b/src/Jiayi.UI/Core/KeyCode.cs @@ -0,0 +1,235 @@ +namespace Jiayi.UI.Core; + +// meant to mirror win32 virtual key codes... so some of these are not used +public enum KeyCode : byte +{ + None = 0x00, + LeftButton, + RightButton, + Cancel, + MiddleButton, + SideButton1, // or page up + SideButton2, // or page down + + // 0x07 is reserved + + Back = 0x08, + Tab, + + // 0x0A-0x0B are reserved + + Clear = 0x0C, + Return, + + // 0x0E-0x0F are unassigned + + Shift = 0x10, + Control, + Alt, // or menu + Pause, + CapsLock, // or capital + Kana, // or hangul + ImeOn, + Junja, + ImeFinal, + Kanji, // or hanja + ImeOff, + Escape, + ImeConvert, + ImeNonConvert, + ImeAccept, + ImeModeChange, + Space, + PageUp, // or prior + PageDown, // or next + End, + Home, + LeftArrow, + UpArrow, + RightArrow, + DownArrow, + Select, + Print, + Execute, + PrintScreen, // or snapshot + Insert, + Delete, + Help, + + // alphanumeric keys + Alpha0 = 0x30, + Alpha1, + Alpha2, + Alpha3, + Alpha4, + Alpha5, + Alpha6, + Alpha7, + Alpha8, + Alpha9, + + // 0x3A-0x40 are undefined + + A = 0x41, + B, + C, + D, + E, + F, + G, + H, + I, + J, + K, + L, + M, + N, + O, + P, + Q, + R, + S, + T, + U, + V, + W, + X, + Y, + Z, + Windows, // left windows key (the only one that matters) + + // basically... skip the right windows key + + Application = 0x5D, // or context menu + + // 0x5E is reserved + + Sleep = 0x5F, + + // numpad keys + Numpad0 = 0x60, + Numpad1, + Numpad2, + Numpad3, + Numpad4, + Numpad5, + Numpad6, + Numpad7, + Numpad8, + Numpad9, + Multiply, + Add, + Separator, + Subtract, + Decimal, // or period, although it's not really a period + Divide, + + // function keys + F1 = 0x70, + F2, + F3, + F4, + F5, + F6, + F7, + F8, + F9, + F10, + F11, + F12, + + // now the rest of the function keys aren't on a standard keyboard, but they're here anyway + F13, + F14, + F15, + F16, + F17, + F18, + F19, + F20, + F21, + F22, + F23, + F24, + + // 0x88-0x8F are reserved + + NumLock = 0x90, + ScrollLock, + + // 0x92-0x96 are OEM specific, and 0x97-0x9F are unassigned + + LeftShift = 0xA0, + RightShift, + LeftControl, + RightControl, + LeftAlt, // or left menu + RightAlt, // or right menu + + // browser keys idk if i've ever seen these + BrowserBack, + BrowserForward, + BrowserRefresh, + BrowserStop, + BrowserSearch, + BrowserFavorites, + BrowserHome, + + // media keys + VolumeMute, + VolumeDown, + VolumeUp, + MediaNext, + MediaPrevious, + MediaStop, + MediaPlay, + + LaunchMail, + LaunchMediaSelect, + LaunchApp1, + LaunchApp2, + + // 0xB8-0xB9 are reserved + + Oem1 = 0xBA, // semicolon key for US keyboards + OemPlus, // plus key for any region + OemComma, // comma key for any region + OemMinus, // minus key for any region + OemPeriod, // period key for any region + Oem2, // slash key for US keyboards + Oem3, // tilde key for US keyboards + + // 0xC1-0xDA are reserved + + Oem4 = 0xDB, // left bracket key for US keyboards + Oem5, // backslash key for US keyboards + Oem6, // right bracket key for US keyboards + Oem7, // single quote key for US keyboards + Oem8, // this could literally be anything + + // 0xE0 is reserved and 0xE1 is OEM specific + + Oem102 = 0xE2, // backslash key for any region that isn't the US; for US keyboards, it's the angle bracket key + + // 0xE3 and 0xE4 are OEM specific + + ImeProcess = 0xE5, + + // 0xE6 is OEM specific + + Packet = 0xE7, + + // 0xE8 is unassigned and 0xE9-0xF5 are OEM specific + + Attention = 0xF6, // attn key + CrSel, + ExSel, + EraseEof, + Play, + Zoom, + + // 0xFC technically has a key code, but it's reserved + + Pa1 = 0xFD, + OemClear +} \ No newline at end of file diff --git a/src/Jiayi.UI/Core/KeyModifier.cs b/src/Jiayi.UI/Core/KeyModifier.cs new file mode 100644 index 0000000..79921a0 --- /dev/null +++ b/src/Jiayi.UI/Core/KeyModifier.cs @@ -0,0 +1,11 @@ +namespace Jiayi.UI.Core; + +[Flags] +public enum KeyModifier : uint +{ + None = 0, + Alt = 1, + Control = 2, + Shift = 4, + Windows = 8 +} \ No newline at end of file diff --git a/src/Jiayi.UI/Core/Window.cs b/src/Jiayi.UI/Core/Window.cs index 1563dce..19537f5 100644 --- a/src/Jiayi.UI/Core/Window.cs +++ b/src/Jiayi.UI/Core/Window.cs @@ -4,6 +4,7 @@ using System.Runtime.InteropServices; using Windows.Win32.Foundation; using Windows.Win32.UI.WindowsAndMessaging; +using Jiayi.UI.Eventing.Arguments; using Jiayi.UI.Eventing.Handlers; using Jiayi.UI.Render; using static Windows.Win32.PInvoke; @@ -64,7 +65,7 @@ public string Title public Vector2 MinimumSize { get; set; } = new(300, 300); public Vector2 MaximumSize { get; set; } = new(10000, 10000); - // end of cool properties + // cool events private readonly List _eventHandlers = new(); public Window(string title, Vector2 size) @@ -105,6 +106,7 @@ public Window(string title, Vector2 size) AddEventHandler(); AddEventHandler(); AddEventHandler(); + AddEventHandler(); } private void AddEventHandler() where T : EventHandler, new() @@ -141,4 +143,10 @@ public void Close() Application.Current.Exit(); } } + + // cool methods for cool inheritance + public virtual void Initialize() {} // implement and call this in your constructor + public virtual void KeyDown(KeyEventArgs e) {} + public virtual void KeyUp(KeyEventArgs e) {} + public virtual void KeyChar(KeyCharEventArgs e) {} } \ No newline at end of file diff --git a/src/Jiayi.UI/Eventing/Arguments/KeyCharEventArgs.cs b/src/Jiayi.UI/Eventing/Arguments/KeyCharEventArgs.cs new file mode 100644 index 0000000..e1bac25 --- /dev/null +++ b/src/Jiayi.UI/Eventing/Arguments/KeyCharEventArgs.cs @@ -0,0 +1,12 @@ +namespace Jiayi.UI.Eventing.Arguments; + +// best for text input. if you need to handle special keys, use KeyEventArgs +public class KeyCharEventArgs : EventArgs +{ + public char KeyChar { get; } + + public KeyCharEventArgs(char keyChar) + { + KeyChar = keyChar; + } +} \ No newline at end of file diff --git a/src/Jiayi.UI/Eventing/Arguments/KeyEventArgs.cs b/src/Jiayi.UI/Eventing/Arguments/KeyEventArgs.cs new file mode 100644 index 0000000..d9c937a --- /dev/null +++ b/src/Jiayi.UI/Eventing/Arguments/KeyEventArgs.cs @@ -0,0 +1,19 @@ +using System.Text; +using Jiayi.UI.Core; + +namespace Jiayi.UI.Eventing.Arguments; + +// best for special keys. if you need to handle text input, use KeyCharEventArgs +public class KeyEventArgs : EventArgs +{ + public KeyCode KeyCode { get; } + public KeyModifier Modifiers { get; } + public bool KeyDown { get; set; } + + public KeyEventArgs(KeyCode keyCode, KeyModifier modifiers, bool keyDown) + { + KeyCode = keyCode; + Modifiers = modifiers; + KeyDown = keyDown; + } +} \ No newline at end of file diff --git a/src/Jiayi.UI/Eventing/Handlers/DrawHandler.cs b/src/Jiayi.UI/Eventing/Handlers/DrawHandler.cs index ecff7bb..01aaec1 100644 --- a/src/Jiayi.UI/Eventing/Handlers/DrawHandler.cs +++ b/src/Jiayi.UI/Eventing/Handlers/DrawHandler.cs @@ -21,10 +21,6 @@ public override void HandleMessage(Window window, uint message, WPARAM wParam, L window.Graphics.Clear(window.BackgroundColor); // draw widgets here - // test squares for now - window.Graphics.FillRect(new Vector2(100, 100), new Vector2(100, 100), Color.Red); - window.Graphics.FillRect(new Vector2(200, 200), new Vector2(100, 100), Color.Green); - window.Graphics.FillRect(new Vector2(300, 300), new Vector2(100, 100), Color.Blue); window.Graphics.End(); } diff --git a/src/Jiayi.UI/Eventing/Handlers/KeyboardHandler.cs b/src/Jiayi.UI/Eventing/Handlers/KeyboardHandler.cs new file mode 100644 index 0000000..17934d5 --- /dev/null +++ b/src/Jiayi.UI/Eventing/Handlers/KeyboardHandler.cs @@ -0,0 +1,52 @@ +using System.Drawing; +using System.Numerics; +using Windows.Win32.Foundation; +using Jiayi.UI.Core; +using Jiayi.UI.Eventing.Arguments; +using Vortice.Direct2D1; +using static Windows.Win32.PInvoke; + +namespace Jiayi.UI.Eventing.Handlers; + +public class KeyboardHandler() : EventHandler(WM_KEYUP, WM_SYSKEYUP, WM_KEYDOWN, WM_SYSKEYDOWN, WM_CHAR) +{ + // current key modifiers + private KeyModifier _modifiers; + + public override void HandleMessage(Window window, uint message, WPARAM wParam, LPARAM lParam) + { + switch (message) + { + // key up + case WM_KEYUP: + case WM_SYSKEYUP: + var code = (KeyCode)wParam.Value; + _modifiers &= ~KeyCodeToModifier(code); + window.KeyUp(new KeyEventArgs(code, _modifiers, false)); + break; + + // key down + case WM_KEYDOWN: + case WM_SYSKEYDOWN: + code = (KeyCode)wParam.Value; + _modifiers |= KeyCodeToModifier(code); + window.KeyDown(new KeyEventArgs(code, _modifiers, true)); + break; + + // character input + case WM_CHAR: + window.KeyChar(new KeyCharEventArgs((char)wParam.Value)); + break; + } + } + + // this syntax is funny + private KeyModifier KeyCodeToModifier(KeyCode code) => code switch + { + KeyCode.Shift or KeyCode.LeftShift or KeyCode.RightShift => KeyModifier.Shift, + KeyCode.Control or KeyCode.LeftControl or KeyCode.RightControl => KeyModifier.Control, + KeyCode.Alt or KeyCode.LeftAlt or KeyCode.RightAlt => KeyModifier.Alt, + KeyCode.Windows => KeyModifier.Windows, + _ => KeyModifier.None + }; +} \ No newline at end of file diff --git a/src/Jiayi.UI/Jiayi.UI.csproj b/src/Jiayi.UI/Jiayi.UI.csproj index c1d4e05..2c1483b 100644 --- a/src/Jiayi.UI/Jiayi.UI.csproj +++ b/src/Jiayi.UI/Jiayi.UI.csproj @@ -16,7 +16,7 @@ - +