// SPDX-License-Identifier: LGPL-3.0-linking-exception {******************************* CONTRIBUTOR(S) ****************************** - Edivando S. Santos Brasil | mailedivando@gmail.com (Compatibility with delphi VCL 11/2018) ***************************** END CONTRIBUTOR(S) *****************************} unit BCKeyboard; {$I bgracontrols.inc} interface uses Classes, SysUtils, {$IFDEF FPC}LCLType, LResources, LMessages,{$ENDIF}Forms, Controls, Graphics, Dialogs, {$IFNDEF FPC}Types, Windows, Messages, BGRAGraphics, GraphType, FPImage, BCBaseCtrls,{$ENDIF} BCThemeManager, BCButton, BCPanel, MouseAndKeyInput; type { TBCKeyboard } TBCKeyboard = class(TComponent) private FBCThemeManager: TBCThemeManager; FButton: TBCButton; FOnUserChange: TNotifyEvent; FPanel, FRow1, FRow2, FRow3, FRow4: TBCPanel; FPanelsColor: TColor; F_q, F_w, F_e, F_r, F_t, F_y, F_u, F_i, F_o, F_p, F_a, F_s, F_d, F_f, F_g, F_h, F_j, F_k, F_l, F_z, F_x, F_c, F_v, F_b, F_n, F_m, F_shift, F_space, F_back: TBCButton; FVisible: boolean; procedure SetFButton(AValue: TBCButton); procedure SetFPanel(AValue: TBCPanel); procedure SetFPanelsColor(AValue: TColor); procedure SetFThemeManager(AValue: TBCThemeManager); protected procedure PressVirtKey(p: longint); procedure PressShiftVirtKey(p: longint); procedure OnButtonClick(Sender: TObject; {%H-}Button: TMouseButton; {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: integer); virtual; { When value is changed by the user } property OnUserChange: TNotifyEvent read FOnUserChange write FOnUserChange; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; // Show in a custom form or panel procedure Show(AControl: TWinControl); overload; // Try to Show in the form where this component is placed procedure Show(); overload; // Hide the component procedure Hide(); // Update buttons style procedure UpdateButtonStyle; public { The real panel that's used as container for all the numeric buttons } property Panel: TBCPanel read FPanel write SetFPanel; { The color of all the panels involved in the control } property PanelsColor: TColor read FPanelsColor write SetFPanelsColor; { A fake button that's used as style base for all the numeric buttons } property ButtonStyle: TBCButton read FButton write SetFButton; { If it's visible or not } property Visible: boolean read FVisible; published property ThemeManager: TBCThemeManager read FBCThemeManager write SetFThemeManager; end; {$IFDEF FPC}procedure Register;{$ENDIF} implementation {$IFDEF FPC}procedure Register; begin RegisterComponents('BGRA Controls', [TBCKeyboard]); end; {$ENDIF} { TBCKeyboard } procedure TBCKeyboard.SetFThemeManager(AValue: TBCThemeManager); begin if FBCThemeManager = AValue then Exit; FBCThemeManager := AValue; end; procedure TBCKeyboard.PressVirtKey(p: longint); begin KeyInput.Down(p); KeyInput.Up(p); end; procedure TBCKeyboard.PressShiftVirtKey(p: longint); begin KeyInput.Down(VK_SHIFT); KeyInput.Down(p); KeyInput.Up(p); KeyInput.Up(VK_SHIFT); end; procedure TBCKeyboard.OnButtonClick(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: integer); var btn: TBCButton; str: string; begin btn := TBCButton(Sender); str := btn.Caption; if str = F_shift.Caption then begin F_shift.Down := not F_shift.Down; if not F_shift.Down then begin F_q.Caption := LowerCase(F_q.Caption); F_w.Caption := LowerCase(F_w.Caption); F_e.Caption := LowerCase(F_e.Caption); F_r.Caption := LowerCase(F_r.Caption); F_t.Caption := LowerCase(F_t.Caption); F_y.Caption := LowerCase(F_y.Caption); F_u.Caption := LowerCase(F_u.Caption); F_i.Caption := LowerCase(F_i.Caption); F_o.Caption := LowerCase(F_o.Caption); F_p.Caption := LowerCase(F_p.Caption); F_a.Caption := LowerCase(F_a.Caption); F_s.Caption := LowerCase(F_s.Caption); F_d.Caption := LowerCase(F_d.Caption); F_f.Caption := LowerCase(F_f.Caption); F_g.Caption := LowerCase(F_g.Caption); F_h.Caption := LowerCase(F_h.Caption); F_j.Caption := LowerCase(F_j.Caption); F_k.Caption := LowerCase(F_k.Caption); F_l.Caption := LowerCase(F_l.Caption); F_z.Caption := LowerCase(F_z.Caption); F_x.Caption := LowerCase(F_x.Caption); F_c.Caption := LowerCase(F_c.Caption); F_v.Caption := LowerCase(F_v.Caption); F_b.Caption := LowerCase(F_b.Caption); F_n.Caption := LowerCase(F_n.Caption); F_m.Caption := LowerCase(F_m.Caption); end else begin F_q.Caption := UpperCase(F_q.Caption); F_w.Caption := UpperCase(F_w.Caption); F_e.Caption := UpperCase(F_e.Caption); F_r.Caption := UpperCase(F_r.Caption); F_t.Caption := UpperCase(F_t.Caption); F_y.Caption := UpperCase(F_y.Caption); F_u.Caption := UpperCase(F_u.Caption); F_i.Caption := UpperCase(F_i.Caption); F_o.Caption := UpperCase(F_o.Caption); F_p.Caption := UpperCase(F_p.Caption); F_a.Caption := UpperCase(F_a.Caption); F_s.Caption := UpperCase(F_s.Caption); F_d.Caption := UpperCase(F_d.Caption); F_f.Caption := UpperCase(F_f.Caption); F_g.Caption := UpperCase(F_g.Caption); F_h.Caption := UpperCase(F_h.Caption); F_j.Caption := UpperCase(F_j.Caption); F_k.Caption := UpperCase(F_k.Caption); F_l.Caption := UpperCase(F_l.Caption); F_z.Caption := UpperCase(F_z.Caption); F_x.Caption := UpperCase(F_x.Caption); F_c.Caption := UpperCase(F_c.Caption); F_v.Caption := UpperCase(F_v.Caption); F_b.Caption := UpperCase(F_b.Caption); F_n.Caption := UpperCase(F_n.Caption); F_m.Caption := UpperCase(F_m.Caption); end; end else if str = F_back.Caption then begin {$IFDEF CPUX86_64} Application.ProcessMessages; KeyInput.Press(VK_BACK); Application.ProcessMessages; {$ELSE} {$IFDEF FPC} Application.QueueAsyncCall(@PressVirtKey, VK_BACK); {$ELSE} SendKey(VK_BACK); {$ENDIF} {$ENDIF} end else begin if str = F_space.Caption then str := ' '; {$IFDEF CPUX86_64} Application.ProcessMessages; if F_shift.Down then KeyInput.Down(VK_SHIFT); KeyInput.Press(Ord(UpperCase(str)[1])); if F_shift.Down then KeyInput.Up(VK_SHIFT); Application.ProcessMessages; {$ELSE} if F_shift.Down then {$IFDEF FPC} Application.QueueAsyncCall(@PressShiftVirtKey, Ord(UpperCase(str)[1])) {$ELSE} SendKey(Ord(UpperCase(str)[1]), Shift) {$ENDIF} else {$IFDEF FPC} Application.QueueAsyncCall(@PressVirtKey, Ord(UpperCase(str)[1])); {$ELSE} SendKey(Ord(UpperCase(str)[1])) {$ENDIF} {$ENDIF} end; if Assigned(FOnUserChange) then FOnUserChange(Self); end; constructor TBCKeyboard.Create(AOwner: TComponent); begin inherited Create(AOwner); FVisible := False; FButton := TBCButton.Create(Self); FPanel := TBCPanel.Create(Self); FPanel.AutoSize := True; FPanel.ChildSizing.ControlsPerLine := 1; FPanel.ChildSizing.Layout := cclLeftToRightThenTopToBottom; FPanel.Caption := 'Panel1'; FPanel.BorderBCStyle := bpsBorder; { qwertyuiop } FRow1 := TBCPanel.Create(FPanel); FRow1.AutoSize := True; FRow1.Caption := ''; FRow1.BorderBCStyle := bpsBorder; FRow1.ChildSizing.ControlsPerLine := 10; FRow1.ChildSizing.Layout := cclLeftToRightThenTopToBottom; FRow1.Parent := FPanel; F_q := TBCButton.Create(FRow1); F_q.Caption := 'Q'; F_q.Parent := FRow1; F_q.OnMouseDown := OnButtonClick; F_w := TBCButton.Create(FRow1); F_w.Caption := 'W'; F_w.Parent := FRow1; F_w.OnMouseDown := OnButtonClick; F_e := TBCButton.Create(FRow1); F_e.Caption := 'E'; F_e.Parent := FRow1; F_e.OnMouseDown := OnButtonClick; F_r := TBCButton.Create(FRow1); F_r.Caption := 'R'; F_r.Parent := FRow1; F_r.OnMouseDown := OnButtonClick; F_t := TBCButton.Create(FRow1); F_t.Caption := 'T'; F_t.Parent := FRow1; F_t.OnMouseDown := OnButtonClick; F_y := TBCButton.Create(FRow1); F_y.Caption := 'Y'; F_y.Parent := FRow1; F_y.OnMouseDown := OnButtonClick; F_u := TBCButton.Create(FRow1); F_u.Caption := 'U'; F_u.Parent := FRow1; F_u.OnMouseDown := OnButtonClick; F_i := TBCButton.Create(FRow1); F_i.Caption := 'I'; F_i.Parent := FRow1; F_i.OnMouseDown := OnButtonClick; F_o := TBCButton.Create(FRow1); F_o.Caption := 'O'; F_o.Parent := FRow1; F_o.OnMouseDown := OnButtonClick; F_p := TBCButton.Create(FRow1); F_p.Caption := 'P'; F_p.Parent := FRow1; F_p.OnMouseDown := OnButtonClick; { asdfghjkl } FRow2 := TBCPanel.Create(FPanel); FRow2.AutoSize := True; FRow2.Caption := ''; FRow2.BorderBCStyle := bpsBorder; FRow2.ChildSizing.ControlsPerLine := 9; FRow2.ChildSizing.Layout := cclLeftToRightThenTopToBottom; FRow2.Parent := FPanel; F_a := TBCButton.Create(FRow2); F_a.Caption := 'A'; F_a.Parent := FRow2; F_a.OnMouseDown := OnButtonClick; F_s := TBCButton.Create(FRow2); F_s.Caption := 'S'; F_s.Parent := FRow2; F_s.OnMouseDown := OnButtonClick; F_d := TBCButton.Create(FRow2); F_d.Caption := 'D'; F_d.Parent := FRow2; F_d.OnMouseDown := OnButtonClick; F_f := TBCButton.Create(FRow2); F_f.Caption := 'F'; F_f.Parent := FRow2; F_f.OnMouseDown := OnButtonClick; F_g := TBCButton.Create(FRow2); F_g.Caption := 'G'; F_g.Parent := FRow2; F_g.OnMouseDown := OnButtonClick; F_h := TBCButton.Create(FRow2); F_h.Caption := 'H'; F_h.Parent := FRow2; F_h.OnMouseDown := OnButtonClick; F_j := TBCButton.Create(FRow2); F_j.Caption := 'J'; F_j.Parent := FRow2; F_j.OnMouseDown := OnButtonClick; F_k := TBCButton.Create(FRow2); F_k.Caption := 'K'; F_k.Parent := FRow2; F_k.OnMouseDown := OnButtonClick; F_l := TBCButton.Create(FRow2); F_l.Caption := 'L'; F_l.Parent := FRow2; F_l.OnMouseDown := OnButtonClick; { zxcvbnm } FRow3 := TBCPanel.Create(FPanel); FRow3.AutoSize := True; FRow3.Caption := ''; FRow3.BorderBCStyle := bpsBorder; FRow3.ChildSizing.ControlsPerLine := 9; FRow3.ChildSizing.Layout := cclLeftToRightThenTopToBottom; FRow3.Parent := FPanel; F_shift := TBCButton.Create(FRow3); F_shift.Caption := '^'; F_shift.Parent := FRow3; F_shift.OnMouseDown := OnButtonClick; F_shift.Down := True; F_z := TBCButton.Create(FRow3); F_z.Caption := 'Z'; F_z.Parent := FRow3; F_z.OnMouseDown := OnButtonClick; F_x := TBCButton.Create(FRow3); F_x.Caption := 'X'; F_x.Parent := FRow3; F_x.OnMouseDown := OnButtonClick; F_c := TBCButton.Create(FRow3); F_c.Caption := 'C'; F_c.Parent := FRow3; F_c.OnMouseDown := OnButtonClick; F_v := TBCButton.Create(FRow3); F_v.Caption := 'V'; F_v.Parent := FRow3; F_v.OnMouseDown := OnButtonClick; F_b := TBCButton.Create(FRow3); F_b.Caption := 'B'; F_b.Parent := FRow3; F_b.OnMouseDown := OnButtonClick; F_n := TBCButton.Create(FRow3); F_n.Caption := 'N'; F_n.Parent := FRow3; F_n.OnMouseDown := OnButtonClick; F_m := TBCButton.Create(FRow3); F_m.Caption := 'M'; F_m.Parent := FRow3; F_m.OnMouseDown := OnButtonClick; F_back := TBCButton.Create(FRow3); F_back.Caption := '<-'; F_back.Parent := FRow3; F_back.OnMouseDown := OnButtonClick; { shift space back } FRow4 := TBCPanel.Create(FPanel); FRow4.AutoSize := True; FRow4.Caption := ''; FRow4.BorderBCStyle := bpsBorder; FRow4.ChildSizing.ControlsPerLine := 1; FRow4.ChildSizing.Layout := cclLeftToRightThenTopToBottom; FRow4.Parent := FPanel; F_space := TBCButton.Create(FRow4); F_space.Caption := '____________________'; F_space.Parent := FRow4; F_space.OnMouseDown := OnButtonClick; end; destructor TBCKeyboard.Destroy; begin { Everything inside the panel will be freed } FPanel.Free; inherited Destroy; end; procedure TBCKeyboard.Show(AControl: TWinControl); begin FPanel.Parent := AControl; FVisible := True; end; procedure TBCKeyboard.Show; begin if Self.Owner is TWinControl then Show(Self.Owner as TWinControl) else raise Exception.Create('The parent is not TWinControl descendant.'); end; procedure TBCKeyboard.Hide; begin FPanel.Parent := nil; FVisible := False; end; procedure TBCKeyboard.UpdateButtonStyle; var shift_down: boolean; begin F_q.Assign(FButton); F_w.Assign(FButton); F_e.Assign(FButton); F_r.Assign(FButton); F_t.Assign(FButton); F_y.Assign(FButton); F_u.Assign(FButton); F_i.Assign(FButton); F_o.Assign(FButton); F_p.Assign(FButton); F_a.Assign(FButton); F_s.Assign(FButton); F_d.Assign(FButton); F_f.Assign(FButton); F_g.Assign(FButton); F_h.Assign(FButton); F_j.Assign(FButton); F_k.Assign(FButton); F_l.Assign(FButton); F_z.Assign(FButton); F_x.Assign(FButton); F_c.Assign(FButton); F_v.Assign(FButton); F_b.Assign(FButton); F_n.Assign(FButton); F_m.Assign(FButton); shift_down := F_shift.Down; F_shift.Assign(FButton); F_shift.Down := shift_down; F_back.Assign(FButton); F_space.Assign(FButton); end; procedure TBCKeyboard.SetFButton(AValue: TBCButton); begin if FButton = AValue then Exit; FButton := AValue; end; procedure TBCKeyboard.SetFPanel(AValue: TBCPanel); begin if FPanel = AValue then Exit; FPanel := AValue; end; procedure TBCKeyboard.SetFPanelsColor(AValue: TColor); begin if FPanelsColor = AValue then Exit; FPanelsColor := AValue; FPanel.Background.Color := AValue; FRow1.Background.Color := AValue; FRow2.Background.Color := AValue; FRow3.Background.Color := AValue; FRow4.Background.Color := AValue; end; end.