Browse Source

* initial keyboard handling

Michael Van Canneyt 4 months ago
parent
commit
b9c70d5f9d
1 changed files with 204 additions and 4 deletions
  1. 204 4
      src/win32/fresnel.win32.pas

+ 204 - 4
src/win32/fresnel.win32.pas

@@ -17,7 +17,7 @@ uses
   {$ENDIF}
   {$ENDIF}
   // fresnel
   // fresnel
   UTF8Utils,
   UTF8Utils,
-  Fresnel.Classes, Fresnel.Forms, Fresnel.WidgetSet, Fresnel.DOM,
+  Fresnel.keys, Fresnel.Classes, Fresnel.Forms, Fresnel.WidgetSet, Fresnel.DOM,
   Fresnel.Events, FCL.Events;
   Fresnel.Events, FCL.Events;
 
 
 type
 type
@@ -51,6 +51,7 @@ type
     function GetClientSize: TFresnelPoint; override;
     function GetClientSize: TFresnelPoint; override;
     procedure Invalidate; override;
     procedure Invalidate; override;
     procedure InvalidateRect(const aRect: TFresnelRect); override;
     procedure InvalidateRect(const aRect: TFresnelRect); override;
+    function HandleKeyMsg(aKey,aFlags : WPARAM; IsDown : Boolean) : boolean; virtual;
     procedure HandleMouseMsg(XPos,YPos: longint; MouseEventId: TEventID;
     procedure HandleMouseMsg(XPos,YPos: longint; MouseEventId: TEventID;
       Button: TMouseButton; Shiftstate: TShiftState); virtual;
       Button: TMouseButton; Shiftstate: TShiftState); virtual;
     function HandlePaintMsg: LRESULT; virtual;
     function HandlePaintMsg: LRESULT; virtual;
@@ -191,6 +192,8 @@ var
 
 
 var
 var
   aWndInfo: PWin32WindowInfo;
   aWndInfo: PWin32WindowInfo;
+  isKeyCanceled : Boolean;
+  
 begin
 begin
   aWndInfo:=GetWin32WindowInfo(aHandle);
   aWndInfo:=GetWin32WindowInfo(aHandle);
   if aWndInfo<>nil then
   if aWndInfo<>nil then
@@ -210,14 +213,14 @@ begin
       end;
       end;
     WM_KEYDOWN:
     WM_KEYDOWN:
       begin
       begin
-        writeln('KeyDown: ',aWParam);
-        if aWParam=VK_ESCAPE then
+        isKeyCanceled:=aForm.HandleKeyMsg(aWParam,aLParam,True);
+        if (aWParam=VK_ESCAPE) and not (IsKeyCanceled) then
           PostQuitMessage(0);
           PostQuitMessage(0);
         exit(0);
         exit(0);
       end;
       end;
     WM_KEYUP:
     WM_KEYUP:
       begin
       begin
-        writeln('KeyUp: ',aWParam);
+        isKeyCanceled:=aForm.HandleKeyMsg(aWParam,aLParam,False);
         exit(0);
         exit(0);
       end;
       end;
 
 
@@ -432,6 +435,203 @@ begin
   Windows.InvalidateRect(FWindow,aRect.GetRect,false);
   Windows.InvalidateRect(FWindow,aRect.GetRect,false);
 end;
 end;
 
 
+function ToUnicodeEx(wVirtKey:UINT; wScanCode:UINT; lpKeyState:PBYTE; pwszBuff:LPWSTR; cchBuff:longint;wFlags:UINT;dwhkl: HKL):longint; external 'user32' name 'ToUnicodeEx';
+
+Function KeyCodeToUnicode(aKey,aFlags : WPARAM) : Word;
+
+var 
+  lState : array[0..255] of byte;
+  lChars : array[0..1] of unicodechar; // Buffer for Unicode character (including null terminator)
+  lRes : Integer;
+  lLayout : HKL;
+  
+begin
+  Result:=0;
+  if not GetKeyboardState(@lState)  then
+    exit;
+  lLayout:=GetKeyboardLayout(0); // 0 means the current thread's input locale.
+  lRes:=ToUnicodeEx(
+        aKey,          // Virtual-key code
+        ((aFlags shr 16) and $FF), // Scan code
+        @lState,   // Keyboard-state array
+        @lChars,     // Buffer for translated character
+        2,               // Size of buffer
+        1,               // Flags (1 means translate dead keys)
+        lLayout  // Current keyboard layout
+  );
+  if (lRes=1) then
+    Result:=Ord(lChars[0]) // Return the Unicode character
+  else if (lRes = -1) then
+    begin
+    // Dead-key character; ToUnicodeEx will have stored the dead key state.
+    // So we must call ToUnicodeEx again with a space to get the composed character.
+    lRes:=ToUnicodeEx(
+        VK_SPACE,
+        MapVirtualKeyEx(VK_SPACE, MAPVK_VK_TO_VSC, lLayout),
+        @lState,
+        @lChars,
+        2,
+        1,
+        lLayout
+    );
+    if (lRes=1) then
+      Result:=Ord(lChars[0]); // Return the composed character.
+    end;
+end; 
+
+Function WinKeyToFresnelKey(aKey,aFlags : WParam) : Integer;
+
+begin
+  Result:=KeyCodeToUnicode(aKey,aFlags);
+  if Result<>0 then
+    exit;
+  Case aKey of
+    VK_0..VK_9 :
+      result:=Ord('0')+(aKey-VK_0);
+    VK_A..VK_Z :
+      begin
+      Result:=Ord(aKey);
+      if not (ssShift in KeyboardStateToShiftState) then
+        Result:=Result+(Ord('a')-Ord('A'));
+      end;
+    VK_BACK : Result:=TKeyCodes.BackSpace;
+    VK_TAB : Result:=TKeyCodes.Tab;
+    VK_CLEAR : Result:=TKeyCodes.Clear;
+    VK_RETURN : Result:=TKeyCodes.Enter;
+    VK_LSHIFT,
+    VK_RSHIFT,
+    VK_SHIFT : Result:=TKeyCodes.Shift;
+    VK_LCONTROL,
+    VK_RCONTROL,
+    VK_CONTROL 	: Result:=TKeyCodes.Control;
+    VK_LMENU,
+    VK_RMENU,
+    VK_MENU 	: Result:=TKeyCodes.Alt;
+    VK_PAUSE 	: Result:=TKeyCodes.Pause;
+    VK_CAPITAL 	: Result:=TKeyCodes.CapsLock;
+    VK_KANA 	: Result:=TKeyCodes.KanaMode;
+   // VK_HANGUL 	: Result:=TKeyCodes.HangulMode;
+    VK_JUNJA 	: Result:=TKeyCodes.JunjaMode;
+    VK_FINAL 	: Result:=TKeyCodes.FinalMode;
+    VK_HANJA 	: Result:=TKeyCodes.HanjaMode;
+    //VK_KANJI 	: Result:=TKeyCodes.KanjiMode;
+    VK_ESCAPE 	: Result:=TKeyCodes.Escape;
+    VK_CONVERT 	: Result:=TKeyCodes.Convert ;
+    VK_NONCONVERT 	: Result:=TKeyCodes.NonConvert;
+    VK_ACCEPT 	: Result:=TKeyCodes.Accept ;
+    VK_MODECHANGE 	: Result:=TKeyCodes.ModeChange;
+    VK_SPACE 	: Result:=Ord(' ');
+    VK_PRIOR 	: Result:=TKeyCodes.PageUp;
+    VK_NEXT 	: Result:=TKeyCodes.PageDown;
+    VK_END 	: Result:=TKeyCodes.End_;
+    VK_HOME 	: Result:=TKeyCodes.Home;
+    VK_LEFT 	: Result:=TKeyCodes.ArrowLeft;
+    VK_UP 	: Result:=TKeyCodes.ArrowUp;
+    VK_RIGHT 	: Result:=TKeyCodes.ArrowRight;
+    VK_DOWN 	: Result:=TKeyCodes.ArrowDown;
+    VK_SELECT 	: Result:=TKeyCodes.Select ;
+    VK_EXECUTE 	: Result:=TKeyCodes.Execute ;
+    VK_SNAPSHOT 	: Result:=TKeyCodes.PrintScreen ;
+    VK_INSERT 	: Result:=TKeyCodes.Insert ;
+    VK_DELETE 	: Result:=TKeyCodes.Delete ;
+    VK_HELP 	: Result:=TKeyCodes.Help ;
+    VK_LWIN 	: Result:=TKeyCodes.Meta ;
+    VK_RWIN 	: Result:=TKeyCodes.Meta ;
+    VK_APPS 	: Result:=TKeyCodes.Contextmenu ;
+    VK_SLEEP 	: Result:=TKeyCodes.StandBy ;
+    VK_NUMPAD0 	: Result:=Ord('0');
+    VK_NUMPAD1 	: Result:=Ord('1')+(aKey-VK_NUMPAD1);
+    VK_MULTIPLY 	: Result:=TKeyCodes.Multiply ;
+    VK_ADD 	: Result:=TKeyCodes.Add ;
+    VK_SEPARATOR 	: Result:=TKeyCodes.Separator ;
+    VK_SUBTRACT 	: Result:=TKeyCodes.Subtract ;
+    VK_DECIMAL 	: Result:=TKeyCodes.Decimal ;
+    VK_DIVIDE 	: Result:=TKeyCodes.Divide ;
+    VK_F1..VK_F24 	: Result:=TKeyCodes.F1+(aKey-VK_F1);
+    VK_NUMLOCK 	: Result:=TKeyCodes.NumLock ;
+    VK_SCROLL 	: Result:=TKeyCodes.ScrollLock ;
+    VK_BROWSER_BACK 	: Result:=TKeyCodes.BrowserBack;
+    VK_BROWSER_FORWARD 	: Result:=TKeyCodes.BrowserForward;
+    VK_BROWSER_REFRESH 	: Result:=TKeyCodes.BrowserRefresh;
+    VK_BROWSER_STOP 	: Result:=TKeyCodes.BrowserStop;
+    VK_BROWSER_SEARCH 	: Result:=TKeyCodes.Browsersearch;
+    VK_BROWSER_FAVORITES 	: Result:=TKeyCodes.BrowserFavorites;
+    VK_BROWSER_HOME 	: Result:=TKeyCodes.BrowserHome;
+    VK_VOLUME_MUTE 	: Result:=TKeyCodes.AudioVolumeMute;
+    VK_VOLUME_DOWN 	: Result:=TKeyCodes.AudioVolumeDown;
+    VK_VOLUME_UP 	: Result:=TKeyCodes.AudioVolumeUp;
+    VK_MEDIA_NEXT_TRACK 	: Result:=TKeyCodes.MediaTrackNext;
+    VK_MEDIA_PREV_TRACK 	: Result:=TKeyCodes.MediaTrackPrevious;
+    VK_MEDIA_STOP 	: Result:=TKeyCodes.MediaStop;
+    VK_MEDIA_PLAY_PAUSE 	: Result:=TKeyCodes.MediaPlayPause;
+    VK_LAUNCH_MAIL 	: Result:=TKeyCodes.LaunchMail ;
+    VK_LAUNCH_MEDIA_SELECT 	: Result:=TKeyCodes.LaunchMediaPlayer ;
+    VK_LAUNCH_APP1 	: Result:=TKeyCodes.LaunchApplication1 ;
+    VK_LAUNCH_APP2 	: Result:=TKeyCodes.LaunchApplication2 ;
+    VK_PROCESSKEY 	: Result:=TKeyCodes.Process ;
+    VK_ATTN 	: Result:=TKeyCodes.KanaMode ;
+    VK_CRSEL 	: Result:=TKeyCodes.CrSel ;
+    VK_EXSEL 	: Result:=TKeyCodes.ExSel ;
+    VK_EREOF 	: Result:=TKeyCodes.EraseEof ;
+    VK_PLAY 	: Result:=TKeyCodes.Play ;
+    VK_ZOOM 	: Result:=TKeyCodes.ZoomToggle ;
+    VK_OEM_CLEAR 	: Result:=TKeyCodes.Clear ;
+  else
+    Result:=0;
+  { // Not supported
+    // VK_CANCEL :      : Result:=TKeyCodes. ;
+    // VK_IME_ON 	: Result:=TKeyCodes. ;
+    // VK_IME_OFF 	: Result:=TKeyCodes. ;
+    // VK_PRINT 	: Result:=TKeyCodes. ;
+    // VK_PACKET 	: Result:=TKeyCodes. ;
+    // VK_NONAME 	: Result:=TKeyCodes. ;
+    // VK_PA1 	        : Result:=TKeyCodes. ;
+    // VK_OEM_1 	: Result:=TKeyCodes. ;
+    // VK_OEM_PLUS 	: Result:=TKeyCodes. ;
+    // VK_OEM_COMMA 	: Result:=TKeyCodes. ;
+    // VK_OEM_MINUS 	: Result:=TKeyCodes. ;
+    // VK_OEM_PERIOD 	: Result:=TKeyCodes. ;
+    // VK_OEM_2 	: Result:=TKeyCodes. ;
+    // VK_OEM_3 	: Result:=TKeyCodes. ;
+    // VK_OEM_4 	: Result:=TKeyCodes. ;
+    // VK_OEM_5 	: Result:=TKeyCodes. ;
+    // VK_OEM_6 	: Result:=TKeyCodes. ;
+    // VK_OEM_7 	: Result:=TKeyCodes. ;
+    // VK_OEM_8 	: Result:=TKeyCodes. ;
+    // VK_OEM_102 	: Result:=TKeyCodes. ;
+  
+  }  
+  end;  
+end;
+
+
+function TWin32WSForm.HandleKeyMsg(aKey,aFlags : WParam; IsDown : Boolean) : boolean;
+
+var
+  lData : TFresnelKeyEventInit;
+  lShift : TShiftState;
+  lInput : TFresnelInputEventInit;
+
+begin
+  lData:=Default(TFresnelKeyEventInit);
+//  lShift:=WinKeyCodeToShiftState(aKey);
+  lData.ShiftState:=KeyboardStateToShiftState;
+  lData.NumKey:=WinKeyToFresnelKey(aKey,aFlags);
+  
+  if isdown and not Form.WSKey(lData,evtKeyDown) then
+    begin
+    lInput:=Default(TFresnelInputEventInit);
+    if NumKeyToInputType(lData.NumKey,lData.ShiftState,lInput.InputType) then
+      begin
+      if (lData.NumKey>0) then
+        lInput.Data:=UnicodeToUTF8(lData.NumKey);
+      Form.WSInput(lInput);
+      end;
+    end;
+
+//  Form.WSKey(WSData,MouseEventId);
+end;
+
 procedure TWin32WSForm.HandleMouseMsg(XPos, YPos: longint;
 procedure TWin32WSForm.HandleMouseMsg(XPos, YPos: longint;
   MouseEventId: TEventID; Button: TMouseButton; Shiftstate: TShiftState);
   MouseEventId: TEventID; Button: TMouseButton; Shiftstate: TShiftState);
 var
 var