我有一个StringGrid,它能够使用OnDraw方法绘制新行。
它工作正常,但现在我希望用户可以使用键盘输入新行。目前,多行文本必须被复制到StringGrid中。
每次按下VK_RETURN,StringGrid都会离开编辑模式。我该怎么办才能避免这种情况?
对于新行,我想要Ctrl + Return,就像它在Skype中一样。
procedure TForm1.StringGrid1KeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key = VK_RETURN) and (ssCtrl in Shift) then // Ctrl+Return = New Line
begin
// TODO: Do NOT cancel edit mode
// TODO: Insert #13#10 at current cursor position
end;
end;
答案 0 :(得分:3)
TStringGrid的内置单元格编辑器不支持多行文本(它是TCustomMaskEdit
的后代,它是单行的)。您必须使用单独的UI控件(例如TMemo
)来编辑多行文本。有几种不同的方法可以实现这一目标:
停用网格的内置编辑器(从网格的goEditing
属性中删除Options
标记),并在TMemo
附近放置TStringGrid
TForm
。当用户选择单元格(并可选择单击按钮/菜单)时,将其当前文本分配到备忘录中。如果用户进行了任何更改(并可选择单击其他按钮/菜单),请将新文本指定回单元格。
上述内容的变体:设计一个单独的TMemo
,其上有ShowModal()
和保存按钮。当用户选择单元格(或按下按钮/菜单)时,将单元格的当前文本分配给表单的备忘录,然后通过调用其ModalResult
方法显示该表单。如果用户单击“保存”按钮,请通过将其mrOk
属性设置为ShowModal()
来关闭“表单”。如果mrOk
返回Invalidate()
,请将备忘录的当前文本分配给正在编辑的单元格,然后ShowModal()
网格以触发重新绘制。如果TStringGrid
返回任何其他内容,则不执行任何操作。
上述内容的一种变体:启用网格的内置编辑器,并按上述方式设计单独的表单,然后配置TStringGrid
以自动触发表单,而无需以以任何方式更改UI的其余部分。
从GetEditStyle()
派生一个新类,让它覆盖虚拟esEllipsis
方法以返回esSimple
(默认返回CreateEditor()
),并覆盖虚拟TInplaceEditList
方法返回TInplaceEdit
派生类的新实例(默认情况下返回TInplaceEditList
个对象)。这将导致单元格在编辑时显示按钮而不是编辑字段。
让您的UpdateContents()
派生类拥有您的Form的实例,然后覆盖虚拟DoEditButtonClick()
方法以检索当前的单元格文本并将其分配给Form?#s备注,并覆盖虚拟ShowModal()
方法以模态方式显示表单并相应地响应template <typename F, typename Tuple, size_t... I>
decltype(auto) apply_impl(F&& f, Tuple&& t, index_sequence<I...>) {
return forward<F>(f)(get<I>(forward<Tuple>(t))...);
}
template <typename F, typename Tuple>
decltype(auto) apply(F&& f, Tuple&& t) {
using Indices = make_index_sequence<tuple_size<decay_t<Tuple>>::value>;
return apply_impl(forward<F>(f), forward<Tuple>(t), Indices{});
}
的返回值。