TEdit - 如果剪贴板包含特定字符串,则忽略粘贴操作

TEdit - ignore paste operation if clipboard contains specific string

我想在粘贴到 TEdit 控件之前检查剪贴板字符串(同时使用 Ctrl+V 和上下文菜单 'Paste')。如果剪贴板中包含特定字符串,则 TEdit 控件不应粘贴该字符串。剪贴板文本应保持原样,不应被清除。

对于 CTRL-V,您可以创建一个 OnKeyPress 事件处理程序以在粘贴之前验证剪贴板中的文本。

我结合了检查单个字符与 table 个有效字符以及检查整个粘贴是否无效的字符串。

注意:无效字符串可能仍然是手动输入的,因为这只是检查粘贴文本中的无效字符串。如果您需要检查以确保用户不会一次输入一个错误的字符串,请在 OnChange 事件处理程序中调用 valid_string()

#include <Clipbrd.hpp>
#include <algorithm>
#include <vector>

// A function to validate a pasted string against a number of blacklisted strings
bool valid_string(const UnicodeString& InStr) {
    static const std::vector<UnicodeString> BadStrings{"  ", "--"};

    return std::find_if(BadStrings.begin(), BadStrings.end(), [&](const auto& 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 &Key)
{
    TEdit& 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
        auto& 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 && valid_string(paste))) { // reject the whole paste
                Key = 0;
            }
        }
    }
}

下面是一个在 OnChange 处理程序中完成所有操作的示例。这应该从上下文菜单中捕获错误的粘贴,以及用户是否键入任何非法组合(即使它包含有效字符)。

#include <utility>

void __fastcall TForm1::Edit1Change(TObject *Sender)
{
    TEdit& 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 && 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.
    }
}