Как CRichEditCtrl узнает, что была выполнена операция вставки?
У него есть такие методы, как CRichEditCtrl::Copy()
, CRichEditCtrl::Paste()
который вы можете вызвать, но я не могу обнаружить ни одного сообщения, которое элемент управления посылает Windows, говоря ему выполнить операцию вставки. Кто-нибудь знает, существует ли такая вещь? Или делает CRichEditCtrl
сделать что-то более низкое, например, мониторинг событий WM_CHAR? Если да, могу ли я использовать какие-либо внутренние методы или мне просто нужно свернуть свои собственные, чтобы переопределить стандартную функциональность вставки?
То, что я на самом деле хочу, это для моего пользовательского подкласса (CMyRichEditCtrl : CRichEditCtrl
) игнорировать любое форматирование текста, вставленного в элемент управления. Либо получая данные буфера обмена в другом формате буфера обмена, либо вставляя их как обычно и немедленно удаляя форматирование вставленного текста.
Что я пробовал до сих пор:
- Проверка сообщения на WM_PASTE в
CMyRichEditCtrl::PreTranslateMessage()
- Создание метода
virtual void CMyRichEditCtrl::Paste()
- Установка точки останова на
CRichEditCtrl::Paste()
в afxcmn.inl - Сбрасывать каждое проходящее сообщение
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, чтобы знать, когда выполнять операции с буфером обмена.