1

我正在为键盘开发一个钩子并使用 SetWindowsHookEx,并将每个击键添加到 TStringList 中。为了操作 TStringList 中的击键,我总是使用“.Text”属性。例如,要添加键入的击键,我使用:

KeyStrokes.Text:= KeyStrokes.Text + AChr;

如果我检测到 [backspace],那么我尝试使用以下方法删除 StringList 中的最后一个字符:

KeyStrokes.Text := Copy(KeyStrokes.Text, 1, length(KeyStrokes.Text) - 1);

当我使用相同的“.Text”属性在 TMemo 中添加时,所有这些都正常工作。但是自从我放入 TStringList 时,在保存的 Log.txt 文件中(使用 .SaveToFile 属性)我得到的日志是这样的:

H

大号

大号

而不是“你好”。我尝试了“.Append”、“.Add”属性,但始终相同。当然,删除最后一个字母的退格键不再起作用......如何正确输入击键?这甚至可以在 TStringList 中做到吗?

4

3 回答 3

2

TStringList将换行符保存到文件的唯一方法是TStringList,当您调用SaveToFile(). 原因是读取Text属性会在末尾插入一个隐式换行符,在写回Text. 因此,每次击键最终都会作为列表中的一个新字符串。

就像其他人所说的那样,TStringList首先是这个工作的错误工具。改用简单的String

KeyStrokes: String;
...
KeyStrokes := KeyStrokes + AChr;
...
Delete(KeyStrokes, Length(KeyStrokes), 1);
于 2013-09-05T22:54:08.003 回答
2

TStringList似乎不是适合这项工作的工具,至少如果您要使用该Text物业的话。正如您从文档中知道的那样,读取该Text属性会将列表中的所有项目与换行符连接起来。写入该属性会在每个换行符处拆分新值,并在列表中为每个项目创建一个单独的条目。

如果你试图跟踪击键,你不希望你的数据结构通过插入和删除看起来像击键但不代表真正击键的东西来默默地修改你的数据。(特别要注意,读取该Text属性将在结果末尾附加一个换行符。这会影响您的退格逻辑。)

使用普通的旧字符串来跟踪字符串输入的当前状态。

于 2013-09-05T22:50:32.747 回答
1

使用普通字符串似乎更实用。在评论中,您担心会丢失一些功能,并说:“检测 [enter] 时我正在换行”。sLineBreak通过为行尾 (EOL) 标记附加一个常量,您可以轻松地使用普通字符串支持这一点。在 Windows 上,这等于#13#10(回车和换行)。您唯一需要注意的是,当您使用退格键删除 EOL 时,您需要删除正确数量的字符:Windows 为 2,Linux/MAC 为 1。Length(sLineBreak)会告诉你有多少。

您可能要考虑的另一个选项是TStringBuilder类。它旨在建立零碎的字符串,因此可以满足您的目的。

最后,如果你真的想使用TStringList,你可以单独操作字符串(即不使用Text属性):

FInputData: TStrings;
FInputData := TStringList.Create;
FInputData.Add(''); { Important to always have at least 1 string }

{ When adding a character "Ch" }
FInputData[FInputData.Count-1] := FInputData[FInputData.Count-1] + Ch;

{ When detecting the Enter Key }
FInputData.Add('');

{ When detecting Backspace }
S := FInputData[FInputData.Count-1];
if (S <> '') then
begin
  { Delete last character on current line }
  Delete(S, Length(S), 1);
  FInputData[FInputData.Count-1] := S;
end
else if (S = '') and (FInputData.Count > 1) then
begin
  { Go back to previous line if current is empty, but don't delete if 
    there's nothing left. (Remember: always have at least 1 string) }
  FInputData.Delete(FInputData.Count-1);
end;

{ To write the current data }
Writeln(FInputData.Text);
于 2013-09-06T19:41:29.857 回答