#borland-c #rad-studio
#borland-c #rad-студия #rad-studio
Вопрос:
Я хочу проверить строку буфера обмена перед вставкой в элемент управления TEdit (используя как Ctrl V, так и контекстное меню «Вставить»). Если буфер обмена содержит в себе определенную строку, то TEdit control не должен вставлять эту строку. Текст в буфере обмена должен оставаться как есть, не должен очищаться.
Ответ №1:
Для CTRL-V
вы могли бы создать OnKeyPress
обработчик событий для проверки текста в буфере обмена перед его вставкой.
Я сделал комбинацию проверки одного символа по таблице допустимых символов, а также проверки полной вставки по недопустимым строкам.
Примечание: Недопустимые строки все еще могут быть введены вручную, поскольку это проверяет наличие недопустимых строк только во вставленном тексте. Если вам нужно проверить, чтобы пользователь не вводил неверные строки по одному символу за раз, вызовите valid_string()
в OnChange
обработчике событий.
#include <Clipbrd.hpp>
#include <algorithm>
#include <vector>
// A function to validate a pasted string against a number of blacklisted strings
bool valid_string(const UnicodeStringamp; InStr) {
static const std::vector<UnicodeString> BadStrings{" ", "--"};
return std::find_if(BadStrings.begin(), BadStrings.end(), [amp;](const autoamp; badstr) {
// return true if the current badstr was found
return
std::search(InStr.begin(),
InStr.end(),
badstr.begin(),
badstr.end()) != InStr.end();
}) == BadStrings.end(); // true if a bad string was NOT found
}
// OnKeyPress event handler
void __fastcall TForm1::Edit1KeyPress(TObject *Sender, System::WideChar amp;Key)
{
TEditamp; se = *static_cast<TEdit*>(Sender);
using StrType = decltype(se.Text);
// A lambda to validate a single character:
static const auto validkey = [](auto Ch) {
// example of valid characters:
static const StrType Accepted = "0123456789 -()";
return std::find(Accepted.begin(), Accepted.end(), Ch) != Accepted.end();
};
if(Key >= ' ') { // don't validate control characters
// Single key validation
if(not validkey(Key)) Key = 0;
} else if(Key == 22) { // CTRL-V - check that the whole clipboard buffer is ok
autoamp; c = *Clipboard();
if(c.HasFormat(CF_UNICODETEXT)) {
// Extract the pasted string
StrType paste = StrType(c.AsText.c_str());
// Use the lambda on all characters
bool all_chars_ok = std::all_of(paste.begin(), paste.end(), validkey);
if(not (all_chars_ok amp;amp; valid_string(paste))) { // reject the whole paste
Key = 0;
}
}
}
}
Вот пример выполнения всего этого в OnChange
обработчике вместо этого. Это должно выявить неправильные вставки из контекстного меню, а также если пользователь вводит какие-либо недопустимые комбинации (даже если они состоят из допустимых символов).
#include <utility>
void __fastcall TForm1::Edit1Change(TObject *Sender)
{
TEditamp; se = *static_cast<TEdit*>(Sender);
using StrType = decltype(se.Text);
static StrType old_text;
// A lambda to validate a single character:
static const auto validkey = [](auto Ch) {
// example of valid characters:
static const StrType Accepted = "0123456789 -()";
return std::find(Accepted.begin(), Accepted.end(), Ch) != Accepted.end();
};
// Making an unnecessary copy of the text.
// Using se.Text's iterators directly fails for some reason.
auto txt = se.Text;
// Use the lambda on all characters
bool all_chars_ok = std::all_of(txt.begin(), txt.end(), validkey);
if(all_chars_ok amp;amp; valid_string(txt)) {
// All is ok, save this text
old_text = std::move(txt);
} else {
// Revert back to the old text
se.Text = old_text;
se.SelStart = old_text.Length();
// se.Undo(); // May be a better idea to use instead.
}
}
Комментарии:
1. Вы должны проверить
CF_UNICODETEXT
вместо или, по крайней мере, в дополнение кCF_TEXT
. В C Builder 2009TEdit::Text
иTClipboard::AsText
будетUnicodeString
, иTClipboard::AsText
будет использоватьсяCF_UNICODETEXT
внутри.