Поймать текст, прежде чем он будет вставлен в текстовое представление

У меня есть текстовое представление, и когда что-то вставляется в него из буфера обмена, мне нужно перехватить этот текст и выполнить некоторую предварительную обработку, прежде чем оно попадет в текстовое представление.

Я пытался прослушать событие «PasteClipboard», которое не дает мне возможности изменить входящий текст. и событие "textview.Buffer.Changed", которое срабатывает после того, как вставленный текст попадает в текстовое представление.

Заранее спасибо.


person AvatarOfChronos    schedule 11.11.2009    source источник
comment
Итак, если вы используете Buffer.Changed, вы действительно видите, что текст перед модификацией вспыхивает до того, как появится ваша измененная версия?   -  person kdt    schedule 12.11.2009
comment
к сожалению, нет, к моменту срабатывания buffer.changed текст, который я пытаюсь поймать, уже помещен в текстовый буфер.   -  person AvatarOfChronos    schedule 18.11.2009


Ответы (3)


Насколько я знаю, ваш лучший вариант - постобработать текст после его вставки - событие InsertText в TextBuffer имеет аргументы, которые сообщают вам положение и размер вставленного текста, поэтому вы можете удалить, обработать и повторно вставить его. Вы, конечно, хотели бы избежать перехвата 1-символьных вставок (нажатий клавиш) и ваших собственных повторных вставок, но это тривиально.

Единственный другой вариант, который я могу придумать, - это повторно реализовать поддержку вставки, перехватив команду клавиши вставки, щелчок средней кнопкой мыши и т. д., но обратите внимание, что командные клавиши могут быть переопределены в пользовательских файлах gtkrc, поэтому правильная реализация этого может стать волосатым.

Возможно, также стоит задать вопрос на IRC-канале #gtk+ на irc.gnome.org.

person Mikayla Hutchinson    schedule 19.11.2009
comment
Есть ли что-нибудь похожее на WndProc в GTK? Я не работал с Mono несколько лет и, признаюсь, немного заржавел с фреймворком. - person Chris; 20.11.2009
comment
Не то чтобы я в курсе, нет. Он основан на событиях (сигналы в C) на всем пути вниз. Системы сообщений Windows/X/Carbon скрыты абстракцией платформы GDK. - person Mikayla Hutchinson; 20.11.2009
comment
Конечно, даже если бы они были, вам также понадобится эквивалент WM_PASTE, который здесь больше проблема TBH. - person Mikayla Hutchinson; 20.11.2009
comment
Тем не менее... обычно в подобных ситуациях встроенное поведение обрабатывается обработчиком сигналов, добавляемым самим виджетом. Таким образом, чтобы упредить встроенное поведение, вы можете поместить [GLib.ConnectBefore] в свой обработчик сигнала, чтобы он подключался до встроенного обработчика, а затем дополнительно установить arg.RetVal в true, если вы хотите предотвратить распространение сигнала на обработчик виджета. Однако это работает только в том случае, если EventArgs является подклассом SignalArgs, что здесь, похоже, не так. - person Mikayla Hutchinson; 20.11.2009

Немного погуглив, я нашел следующую документацию на Gtk.TextBuffer и альтернатива GTK .net WndProc в Mono. Похоже, вы можете добавить атрибут [GLib.ConnectBefore] в свой код, чтобы получить доступ к методу GTK WndProc. Приведенный выше код Beaner, вероятно, будет работать с небольшими изменениями для среды GTK.

person Chris    schedule 19.11.2009
comment
Прямого эквивалента WndProc в GTK нет. - person Mikayla Hutchinson; 20.11.2009

Это может не помочь вам, но я перехватываю сообщение WM_PASTE в пользовательском элементе управления, который реализует TextBox. Я получаю GetText из буфера обмена в строковую переменную, и если она соответствует тому, что я ищу, я вношу свои изменения в переменную и устанавливаю .Text в свою переменную и проглатываю событие, чтобы текстовое поле не получило его. Если это не то, что я ищу, но разрешено, я просто передаю событие с помощью base.WndProc(ref m).

Образец:

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_PASTE)
    {
        string clipboardVin = Clipboard.GetText();
        string newVin = "";
        if (SelectionLength > 0)
        {
            newVin = Text.Replace(SelectedText, "");
        }
        else
        {
            newVin = Text;
        }
        newVin = newVin.Insert(SelectionStart, clipboardVin);
        if (!vinRegEx.IsMatch(newVin))
        {
            m.Result = new IntPtr(Convert.ToInt32(true));
            MessageBox.Show("The resulting text is not a valid VIN.", "Can Not Paste", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
        else
        {
            base.WndProc(ref m);
        }
    }
    else
    {
        base.WndProc(ref m);
    }
}
person jac    schedule 11.11.2009
comment
к сожалению, это мне не помогает. Я пытаюсь сделать это на linux под gtk. - person AvatarOfChronos; 16.11.2009
comment
Следует ли удалить тег С# из этого вопроса? - person jac; 20.11.2009
comment
Нет, это С#. GTK# — это оболочка .NET/Mono для кросс-платформенного инструментария GTK+, например System.Windows.Forms — это оболочка для графического интерфейса Win32. - person Mikayla Hutchinson; 20.11.2009