4

我正在构建一个功能类似于触摸屏上的键盘的表单。我目前遇到的问题是,当我按下一个按钮(例如“1”按钮)时,它必须将该字符“1”添加到一个编辑框中,该框显示已按下的键。现在我遇到的问题是,一旦有人按下一个键,我可以将char添加到编辑框中已经显示的字符串中,但是光标走到了编辑框的前面,并没有出现在后面。我使用以下代码向编辑框添加一个字符:

edtPassword.text := edtPassword.text + key;

现在只是将字符添加到编辑框的末尾,但是如何将光标移动到编辑框的末尾。

另外,我还有一个退格按钮,如果单击它,我将使用什么代码擦除编辑框中字符串的最后一个字符?

我正在使用德尔福 XE2

4

2 回答 2

6

免责声明:

我没有按原样回答这个问题。当我需要一个虚拟键盘时,我试图提出一种我宁愿遵循的方法。

1.现成的组件呢?

我建议您使用该TTouchKeyboard组件,它是一个 VCL 组件,代表一个虚拟键盘。也就是说,您正在开发一些东西,这已经是 Delphi 发行版的一部分。自 2010 版以来,它是 Delphi 的一部分,但我不能说在哪个发行版中。

2.它看起来很丑,我宁愿自己做:

当我TTouchKeyboard第一次看到组件时,我希望它允许所有者绘图。好吧,不幸的是没有。在这种情况下,我会尝试自己模拟击键,而不是为您可能很快或以后使用的其他组件解决这样的情况。

2.1。如何以自己的方式模拟击键?

以下代码使用该SendInput函数模拟击键,它基于TTouchKeyboard组件使用的代码:

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;

以及上述函数的用法。您可以将虚拟键、扫描码或两者都传递给此函数。当您不确定它们中的任何一个时,传递值 -1 并且键码将由该MapVirtualKey函数额外映射。以下示例显示如何发送 aBackspace和 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. 如何以禁止的方式模拟击键?

您也可以违背参考并使用SendKeyfromVcl.Touch.Keyboard单位。在参考文献中指出,它在SendKey内部使用,不应该被调用,但它在单元外部可见,如果你足够大胆,你可以像这样使用它:

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. 如何在不同的视图中模拟击键?

于 2012-09-24T13:23:20.287 回答
3

你可以试试:

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

您也可以将消息发布到编辑窗口句柄,如下所示:

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

至于退格,由于您的光标是虚拟的,您可以通过删除文本中的最后一个符号来模拟删除。

如果您的小键盘计划在某个时候包含箭头键,您将需要计算光标的当前位置并删除符号,而不是在文本末尾,而是在与光标值(偏移量)相对应的任意位置。

于 2012-09-23T17:24:23.833 回答