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
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 ?
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With