Как CRichEditCtrl узнает, что была выполнена операция вставки?

У него есть такие методы, как CRichEditCtrl::Copy(), CRichEditCtrl::Paste() который вы можете вызвать, но я не могу обнаружить ни одного сообщения, которое элемент управления посылает Windows, говоря ему выполнить операцию вставки. Кто-нибудь знает, существует ли такая вещь? Или делает CRichEditCtrl сделать что-то более низкое, например, мониторинг событий WM_CHAR? Если да, могу ли я использовать какие-либо внутренние методы или мне просто нужно свернуть свои собственные, чтобы переопределить стандартную функциональность вставки?

То, что я на самом деле хочу, это для моего пользовательского подкласса (CMyRichEditCtrl : CRichEditCtrl) игнорировать любое форматирование текста, вставленного в элемент управления. Либо получая данные буфера обмена в другом формате буфера обмена, либо вставляя их как обычно и немедленно удаляя форматирование вставленного текста.

Что я пробовал до сих пор:

  1. Проверка сообщения на WM_PASTE в CMyRichEditCtrl::PreTranslateMessage()
  2. Создание метода virtual void CMyRichEditCtrl::Paste()
  3. Установка точки останова на CRichEditCtrl::Paste() в afxcmn.inl
  4. Сбрасывать каждое проходящее сообщение CMyRichEditCtrl::PreTranslateMessage()

Результаты:

1: сообщение WM_PASTE не обнаружено
2: это никогда не называется
3: это никогда не ударил... как?
4: элемент управления никогда не получает сообщений WM_COMMAND, WM_PASTE или фокусировки. В основном только сообщения о перемещении мыши и нажатии клавиши.

Кажется, другие люди действительно сделали это успешно. Мне интересно, может ли моя версия MFC или что-то испортить, на данный момент.

6 ответов

Решение

Обрабатывать сообщение EN_PROTECTED.

ON_NOTIFY_REFLECT(EN_PROTECTED, &YourClass::OnProtected)

// call this from the parent class
void YourClass::Initialize()
{
    CHARFORMAT format = { sizeof(CHARFORMAT) };
    format.dwEffects = CFE_PROTECTED; 
    format.dwMask = CFM_PROTECTED;

    SetDefaultCharFormat(format);
    SetEventMask(ENM_PROTECTED);
}

void YourClass::OnProtected(NMHDR* pNMHDR, LRESULT* pResult)
{
    *pResult = 0; 

    ENPROTECTED* pEP = (ENPROTECTED*)pNMHDR;
    if (pEP->msg == WM_PASTE)
        pResult = 1; // prevent paste
}

Когда пользователь запрашивает действие вставки, обычно происходит отправка сообщения WM_COMMAND с идентификатором ID_EDIT_PASTE в элемент управления расширенным редактированием. По умолчанию в MFC это обрабатывается CRichEditCtrl::OnEditPaste(), который вызывает Paste () для самого элемента управления редактирования.

Для этого я должен извлечь класс из CRichEditCtrl, добавить метод OnEditPaste и направить ему сообщение с помощью

ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)

декларация, которая должна работать. Кроме того, в вашем PreTranslateMessage вы можете искать WM_COMMAND с wParam ID_EDIT_PASTE.

Кстати, я решил проблему, очень похожую на вашу (вставьте без форматирования), просто имея реализацию OnEditPaste с

void MyRichEdit::OnEditPaste()
{
  SendMessage(EM_PASTESPECIAL,CF_UNICODETEXT);
}

Это отвечает на запрос вставки, отправляя сообщение вставки в элемент управления, который настаивает на том, что формат данных представляет собой простой текст.

Наконец, я должен отметить, что вышеупомянутая методика достаточна для того, чтобы перехватывать все вставки, запускаемые из пользовательского интерфейса. Однако он не будет отлавливать программно-запускаемые вставки, когда ваш код отправляет WM_PASTE в элемент управления редактирования. В этих случаях проще всего просто изменить свой код. Однако, если вы действительно хотите перехватывать такие случаи, вам нужно запачкать руки с помощью COM и IRichEditOleCallback::QueryAcceptData. Но вы почти наверняка не хотите туда идти:-)

Используйте макрос ON_MESSAGE в вашем производном классе.

ON_MESSAGE (WM_PASTE, OnPaste)

LRESULT CMyRichEditCtrl:: OnPaste (WPARAM, LPARAM)

Если вы откроете файл RichEdit.h, вы заметите, что некоторые сообщения находятся в диапазоне WM_USER. Возможно, именно так MFC обрабатывает события для элемента управления Rich Edit.

Я должен выступить, как показано ниже

void MyRichEcit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{


if( ( GetKeyState(VK_CONTROL)<0 && nChar==88 ) || (nChar==VK_DELETE && GetKeyState(VK_SHIFT) < 0) ) //cut
    {

    }

if( ( GetKeyState(VK_CONTROL)<0 && nChar==86 ) || (nChar==VK_INSERT && GetKeyState(VK_SHIFT) < 0) ) //paste
    {

    }


    CWnd::OnKeyDown(nChar, nRepCnt, nFlags);    
}

Вы пробовали CRichEditCtrl::PasteSpecial(CF_TEXT)? Думаю, он делает то, что вам нужно.

Windows определяет сообщения для вырезания / копирования / вставки. см. WM_CUT.

Вероятно, он отвечает на эти сообщения, а не на сообщения WM_CHAR, чтобы знать, когда выполнять операции с буфером обмена.

Другие вопросы по тегам