我正在为键盘开发一个钩子并使用SetWindowsHookEx,我在TStringList中添加每个击键。要操纵TStringList内部的击键,我总是使用'.Text'属性。要添加键入的击键,例如我使用:
KeyStrokes.Text:= KeyStrokes.Text + AChr;
如果我检测到[退格],那么我尝试使用以下命令删除StringList中的最后一个字符:
KeyStrokes.Text:= Copy(KeyStrokes.Text,1,length(KeyStrokes.Text) - 1);
当我使用相同的'.Text'属性在TMemo中添加时,所有这些都正常工作。但是当我放入TStringList时,在保存的Log.txt文件中(使用.SaveToFile属性)我得到的日志如下:
ħ
电子
→
→
0
而不是'你好'。我试过'.Append','。添加'属性并且总是一样的。当然,删除最后一个字母的退格键不再起作用了...如何正确地进行击键?甚至可以在TStringList中做到吗?
答案 0 :(得分:1)
TStringList
似乎不适合这项工作,至少在你打算使用Text
财产的情况下不行。正如您在文档中所知,阅读Text
属性会使用换行符连接列表中的所有项目。写入该属性在每个换行符时拆分新值,并在列表中为每个项创建一个单独的条目。
如果您正在尝试跟踪击键,则不希望您的数据结构通过插入和删除看起来像击键但不代表真正击键的内容来静默地挖掘您的数据。 (特别要注意,读取Text
属性会在结果的末尾追加换行符。这会影响你的退格逻辑。)
使用普通的旧字符串来跟踪字符串输入的当前状态。
答案 1 :(得分:1)
TStringList
可以将换行符保存到文件的唯一方法是TStringList
在您调用SaveToFile()
时其中包含多个字符串。原因是因为读取Text
属性会在结尾插入一个隐含的换行符,这些换行符在写回Text
之前不会被剥离。因此,每次击键最终都会成为列表中的新字符串。
与其他人一样,TStringList
首先是这项工作的错误工具。请改用简单的String
:
KeyStrokes: String;
...
KeyStrokes := KeyStrokes + AChr;
...
Delete(KeyStrokes, Length(KeyStrokes), 1);
答案 2 :(得分:0)
使用普通的字符串似乎更实际。在评论中你担心失去一些功能,说:“我在检测[输入]时正在执行换行符”。通过为行尾(EOL)标记附加sLineBreak
常量,您可以使用普通字符串轻松支持此功能。在Windows上,这等于#13#10
(回车和换行)。您唯一需要注意的是,当您使用退格键删除EOL时,您需要删除正确的字符数:2表示Windows,1表示Linux / MAC。 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);