From 03621c071dd98bb109d9e6b851e934a070f0cbe0 Mon Sep 17 00:00:00 2001 From: Vadim Lopatin Date: Tue, 15 Apr 2014 15:49:46 +0400 Subject: [PATCH] key events --- examples/example1/main.d | 2 +- src/dlangui/core/events.d | 147 ++++++++++++++++++++++++ src/dlangui/platforms/common/platform.d | 9 ++ src/dlangui/platforms/windows/winapp.d | 60 ++++++++++ src/dlangui/widgets/widget.d | 5 + 5 files changed, 222 insertions(+), 1 deletion(-) diff --git a/examples/example1/main.d b/examples/example1/main.d index 3e569ae3..ac7e3ec0 100644 --- a/examples/example1/main.d +++ b/examples/example1/main.d @@ -155,7 +155,7 @@ extern (C) int UIAppMain(string[] args) { window.mainWidget = (new Button()).text("sample button"); } window.show(); - window.showPopup((new TextWidget()).text("POPUP"d)); + //window.showPopup((new TextWidget()).text("POPUP"d)); window.windowCaption = "New Window Caption"; // run message loop diff --git a/src/dlangui/core/events.d b/src/dlangui/core/events.d index 8e9a0ff3..ec53a82d 100644 --- a/src/dlangui/core/events.d +++ b/src/dlangui/core/events.d @@ -177,6 +177,153 @@ class MouseEvent { } +enum KeyAction : uint { + KeyDown, + KeyUp, + Text, + Repeat, +} + +enum KeyFlag : uint { + Control = 0x0008, + Shift = 0x0004, + Alt = 0x0080, + RControl = 0x0108, + RShift = 0x0104, + RAlt = 0x0180 +} + +enum KeyCode : uint { + BACK = 8, + TAB = 9, + RETURN = 0x0D, + SHIFT = 0x10, + CONTROL = 0x11, + ALT = 0x12, // VK_MENU + PAUSE = 0x13, + CAPS = 0x14, // VK_CAPITAL, caps lock + ESCAPE = 0x1B, // esc + SPACE = 0x20, + PAGEUP = 0x21, // VK_PRIOR + PAGEDOWN = 0x22, // VK_NEXT + END = 0x23, // VK_END + HOME = 0x24, // VK_HOME + LEFT = 0x25, + UP = 0x26, + RIGHT = 0x27, + DOWN = 0x28, + INS = 0x2D, + DEL = 0x2E, + KEY_0 = 0x30, + KEY_1 = 0x31, + KEY_2 = 0x32, + KEY_3 = 0x33, + KEY_4 = 0x34, + KEY_5 = 0x35, + KEY_6 = 0x36, + KEY_7 = 0x37, + KEY_8 = 0x38, + KEY_9 = 0x39, + KEY_A = 0x41, + KEY_B = 0x42, + KEY_C = 0x43, + KEY_D = 0x44, + KEY_E = 0x45, + KEY_F = 0x46, + KEY_G = 0x47, + KEY_H = 0x48, + KEY_I = 0x49, + KEY_J = 0x4a, + KEY_K = 0x4b, + KEY_L = 0x4c, + KEY_M = 0x4d, + KEY_N = 0x4e, + KEY_O = 0x4f, + KEY_P = 0x50, + KEY_Q = 0x51, + KEY_R = 0x52, + KEY_S = 0x53, + KEY_T = 0x54, + KEY_U = 0x55, + KEY_V = 0x56, + KEY_W = 0x57, + KEY_X = 0x58, + KEY_Y = 0x59, + KEY_Z = 0x5a, + LWIN = 0x5b, + RWIN = 0x5c, + NUM_0 = 0x60, + NUM_1 = 0x61, + NUM_2 = 0x62, + NUM_3 = 0x63, + NUM_4 = 0x64, + NUM_5 = 0x65, + NUM_6 = 0x66, + NUM_7 = 0x67, + NUM_8 = 0x68, + NUM_9 = 0x69, + MUL = 0x6A, + ADD = 0x6B, + DIV = 0x6F, + SUB = 0x6D, + DECIMAL = 0x6E, + F1 = 0x70, + F2 = 0x71, + F3 = 0x72, + F4 = 0x73, + F5 = 0x74, + F6 = 0x75, + F7 = 0x76, + F8 = 0x77, + F9 = 0x78, + F10 = 0x79, + F11 = 0x7a, + F12 = 0x7b, + F13 = 0x7c, + F14 = 0x7d, + F15 = 0x7e, + F16 = 0x7f, + F17 = 0x80, + F18 = 0x81, + F19 = 0x82, + F20 = 0x83, + F21 = 0x84, + F22 = 0x85, + F23 = 0x86, + F24 = 0x87, + NUMLOCK = 0x90, + SCROLL = 0x91, // scroll lock + LSHIFT = 0xA0, + RSHIFT = 0xA1, + LCONTROL = 0xA2, + RCONTROL = 0xA3, + LALT = 0xA4, + RALT = 0xA5, +} + +/// keyboard event +class KeyEvent { + protected KeyAction _action; + protected uint _keyCode; + protected uint _flags; + protected dstring _text; + /// key action (KeyDown, KeyUp, Text, Repeat) + @property KeyAction action() { return _action; } + /// key code + @property uint keyCode() { return _keyCode; } + /// flags (shift, ctrl, alt...) + @property uint flags() { return _flags; } + /// entered text, for Text action + @property dstring text() { return _text; } + /// create key event + this(KeyAction action, uint keyCode, uint flags, dstring text = null) { + _action = action; + _keyCode = keyCode; + _flags = flags; + _text = text; + } +} + enum ScrollAction : ubyte { /// space above indicator pressed PageUp, diff --git a/src/dlangui/platforms/common/platform.d b/src/dlangui/platforms/common/platform.d index 19f7b9ed..d36ff4d8 100644 --- a/src/dlangui/platforms/common/platform.d +++ b/src/dlangui/platforms/common/platform.d @@ -177,6 +177,15 @@ class Window { _mouseCaptureButtons = event.flags & (MouseFlag.LButton|MouseFlag.RButton|MouseFlag.MButton); } + protected bool dispatchKeyEvent(Widget root, KeyEvent event) { + return false; + } + + /// dispatch keyboard event + bool dispatchKeyEvent(KeyEvent event) { + return false; + } + protected bool dispatchMouseEvent(Widget root, MouseEvent event) { // only route mouse events to visible widgets if (root.visibility != Visibility.Visible) diff --git a/src/dlangui/platforms/windows/winapp.d b/src/dlangui/platforms/windows/winapp.d index a2465a90..79af617e 100644 --- a/src/dlangui/platforms/windows/winapp.d +++ b/src/dlangui/platforms/windows/winapp.d @@ -415,6 +415,49 @@ class Win32Window : Window { return res; } + + protected uint _keyFlags; + + protected void updateKeyFlags(KeyAction action, KeyFlag flag) { + if (action == KeyAction.KeyDown) + _keyFlags |= flag; + else + _keyFlags &= ~flag; + } + + bool onKey(KeyAction action, uint keyCode, int repeatCount, dchar character = 0) { + KeyEvent event; + if (action == KeyAction.KeyDown || action == KeyAction.KeyUp) { + switch(keyCode) { + case KeyCode.SHIFT: + updateKeyFlags(action, KeyFlag.Shift); + break; + case KeyCode.CONTROL: + updateKeyFlags(action, KeyFlag.Control); + break; + case KeyCode.ALT: + updateKeyFlags(action, KeyFlag.Alt); + break; + default: + break; + } + event = new KeyEvent(action, keyCode, _keyFlags); + } else if (action == KeyAction.Text && character != 0) { + dchar[] text; + text ~= character; + event = new KeyEvent(action, 0, _keyFlags, text); + } + bool res = false; + if (event !is null) { + res = dispatchKeyEvent(event); + } + if (res) { + Log.d("Calling update() after key event"); + update(); + } + return res; + } + /// request window redraw override void invalidate() { InvalidateRect(_hwnd, null, FALSE); @@ -699,6 +742,23 @@ LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } // not processed - default handling return DefWindowProc(hwnd, message, wParam, lParam); + case WM_KEYDOWN: + case WM_KEYUP: + if (window !is null) { + int repeatCount = lParam & 0xFFFF; + if (window.onKey(message == WM_KEYDOWN ? KeyAction.KeyDown : KeyAction.KeyDown, wParam, repeatCount)) + return 0; // processed + return 0; + } + break; + case WM_UNICHAR: + if (window !is null) { + int repeatCount = lParam & 0xFFFF; + if (window.onKey(KeyAction.Text, wParam, repeatCount, wParam == UNICODE_NOCHAR ? 0 : wParam)) + return 1; // processed + return 1; + } + break; case WM_GETMINMAXINFO: case WM_NCCREATE: case WM_NCCALCSIZE: diff --git a/src/dlangui/widgets/widget.d b/src/dlangui/widgets/widget.d index 7a9c3d03..22c948ff 100644 --- a/src/dlangui/widgets/widget.d +++ b/src/dlangui/widgets/widget.d @@ -310,6 +310,11 @@ class Widget { // ======================================================= // Events + /// process key event, return true if event is processed. + bool onKeyEvent(KeyEvent event) { + return false; + } + /// process mouse event; return true if event is processed by widget. bool onMouseEvent(MouseEvent event) { //Log.d("onMouseEvent ", id, " ", event.action, " (", event.x, ",", event.y, ")");