Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to let the cursor go to the end of the string, when adding chars via button clicks using keypad

Im building a form that will function like a keypad on a touch screen. The problem Im having at the moment is that when I person presses a button for example the '1' button, it must add that char '1' to an edit box, which displays the keys already pressed. Now the problem Im experiencing is that once a person presses a key, I can add the char to the string already displayed in the edit box, but the cursor goes to the front of the edit box, and does not appear at the back. I use the following code to add a char to the edit box:

edtPassword.text := edtPassword.text + key;

Now that just adds the char to the end of the edit box, but how do I move the cursor to the end of the edit box.

Plus I do also have a backspace button, what code would I use the erase the last char of the string in the edit box if you clicked it?

Im using Delphi XE2

like image 572
Japster Avatar asked Jan 16 '23 12:01

Japster


2 Answers

Disclaimer:

I'm not answering the question as it is. I'm trying to propose a way I'll rather follow when I'd need a virtual keyboard.

1. What about ready made component ?

I would suggest you to use the TTouchKeyboard component, which is a VCL component, representing a virtual keyboard. That said, you're developing something, what is already a part of Delphi distributions. It's a part of Delphi since version 2010, but I can't say in which distributions.

2. It looks ugly and I'll rather make my own:

When I've seen TTouchKeyboard component for the first time, I was hoping that allows owner drawing. Well, unfortunately doesn't. In that case I'd try to simulate key strokes by myself rather than solve cases like this for another components you may soon or later use.

2.1. How to simulate keystrokes in your own way ?

The following code simulates keystrokes by using the SendInput function and it's based on the code used by TTouchKeyboard component:

type
  TKeyState = (ksDown, ksUp);

function SendInputKey(AVirtualKey: Integer; AScanCode: Integer;
  AKeyState: TKeyState): Boolean;
var
  Input: TInput;
begin
  Input.Itype := INPUT_KEYBOARD;
  if (AVirtualKey = -1) and (AScanCode >= 0) then
  begin
    Input.ki.wVk := MapVirtualKey(AScanCode, MAPVK_VSC_TO_VK);
    Input.ki.wScan := AScanCode;
  end
  else if (AVirtualKey >= 0) and (AScanCode = -1) then
  begin
    Input.ki.wVk := AVirtualKey;
    Input.ki.wScan := MapVirtualKey(AVirtualKey, MAPVK_VK_TO_VSC);
  end
  else if (AVirtualKey >= 0) and (AScanCode >= 0) then
  begin
    Input.ki.wVk := AVirtualKey;
    Input.ki.wScan := AScanCode;
  end;
  case AKeyState of
    ksDown: Input.ki.dwFlags := 0;
    ksUp: Input.ki.dwFlags := KEYEVENTF_KEYUP;
  end;
  Result := SendInput(1, Input, SizeOf(TInput)) = 1;
end;

And the usage of the above function. You can pass virtual key, scan code or both to this function. When you'll be unsure with either of them, pass value of -1 and the key code will be additionally mapped by the MapVirtualKey function. The following example shows how to send a Backspace and then Shift + A:

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
  SendInputKey(VK_BACK, -1, ksDown);
  SendInputKey(VK_BACK, -1, ksUp);
  SendInputKey(VK_SHIFT, -1, ksDown);
  SendInputKey(Ord('A'), -1, ksDown);
  SendInputKey(Ord('A'), -1, ksUp);
  SendInputKey(VK_SHIFT, -1, ksUp);
end;

2.2. How to simulate keystrokes in a forbidden way ?

You may also go against the reference and use the SendKey from Vcl.Touch.Keyboard unit. In the reference is stated that the SendKey is used internally and shouldn't be called but it's visible outside of the unit and if you're bold enough you can use it like this:

uses
  Vcl.Touch.Keyboard, Vcl.Touch.KeyboardTypes;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  KeyData: TKeyData;
begin
  KeyData := VKey(VK_BACK, -1);
  SendKey(KeyData, ksDown);
  SendKey(KeyData, ksUp);
  KeyData := VKey(VK_SHIFT, -1);
  SendKey(KeyData, ksDown);
  KeyData := VKey(Ord('A'), -1);
  SendKey(KeyData, ksDown);
  SendKey(KeyData, ksUp);
  KeyData := VKey(VK_SHIFT, -1);
  SendKey(KeyData, ksUp);
end;

2.3. How to simulate keystrokes in a different view ?

  • How to send text to another application ?
  • How to send keys to another application ?
  • How to send keys without using SendMessage and PostMessage ?
  • How to programmatically simulate user input ?
like image 180
TLama Avatar answered Feb 11 '23 01:02

TLama


You may try:

edtPassword.Text := edtPassword.Text + key;
edtPassword.SelStart := Length(edtPassword.Text);
edtPassword.SelLenght := 0;

Also you could post messages to the edit window handle, like this:

PostMessage(edtPassword.Handle, WM_KEYDOWN, VK_END, 0);
PostMessage(edtPassword.Handle, WM_KEYUP, VK_END, 0);
PostMessage(edtPassword.Handle, WM_CHAR, StrToInt(key), 0);

As for backspace, since your cursor is virtual, you could simulate deletion just by removing last symbol in the text.

If your keypad is planned to include arrow keys some time, you will need to calculate current position of the cursor and remove symbol not at the end of text, but in arbitrary position corresponding to the cursor value (offset).

like image 40
Stan Avatar answered Feb 11 '23 02:02

Stan