Using .net RichTextEdit, but filtering data types?

The control RichTextEditin .NET does 99% of what I need to do for my application, with the exception of a few little things:

  • I want to prohibit inserting / dragging images into the control
  • When the text is inserted / dragged into the control, I want to reset its style for the default control

As far as I can tell, Microsoft has not provided any type of “no image” properties on this control that you can use, which would be ideal.

My thought was that I can respond to the " textChanged" event and then delete the image and / or reset the text style before it appears on the screen. Of course, this will be a complete hack. Firstly, a custom drag and drop icon and a mouse icon mean that images are not available and they really are not.

To ask a short short question, is there a way to set a filter for data types that a control can import RichTextEditthrough Copy & Paste and Drag & Drop?

+3
source share
1 answer

; .NET RichTextBox, , COM- IRichEditOleCallback.

, ATL ++ ( , , , COM- Plain Ol , ):

#include <windows.h>
#include <Richole.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlcomcli.h>
#include <string>

struct RattyRichEditOleCallbackImpl: public CComObjectRoot, public IRichEditOleCallback
{
  HWND* hRichEdit;
  RattyRichEditOleCallbackImpl(): hRichEdit(NULL) {}
  HRESULT SetRichEditCtl(HWND *hCtl)
  {
    hRichEdit = hCtl;
    return S_OK;
  }
  HRESULT QueryAcceptData(LPDATAOBJECT lpdataobj, CLIPFORMAT* lpcfFormat, DWORD reco, BOOL fReally, HGLOBAL hMetaPict)
  {
    // This list of image formats covers all the standard ones listed in
    // the [MSDN docs](https://msdn.microsoft.com/en-us/library/ff729168.aspx)
    // if there are more CF_blahs that correspond to images, add them here
    if (*lpcfFormat == CF_DIB || *lpcfFormat == CF_DIBV5
      || *lpcfFormat == CF_BITMAP || *lpcfFormat == CF_TIFF
      || *lpcfFormat == CF_ENHMETAFILE || *lpcfFormat == CF_METAFILEPICT
      || *lpcfFormat == CF_PALETTE || *lpcfFormat == CF_DSPBITMAP
      || *lpcfFormat == CF_DSPMETAFILEPICT || *lpcfFormat == CF_DSPENHMETAFILE
      || *lpcfFormat >= CF_GDIOBJECTFIRST || *lpcfFormat <= CF_GDIOBJECTLAST)
    {
      // Bail out with an error HRESULT because we don't want some stinkin' image in our rich edit control!
      return E_NOTIMPL;
    }
    // Try to convert anything else to plain ol' Unicode text
    else
    {
      *lpcfFormat = CF_UNICODETEXT;
      // Are we being asked to paste this?
      if (fReally)
      {
        // Insert the data as text with the default style
        FORMATETC fmt = {*lpcfFormat, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
        STGMEDIUM stg;
        HRESULT res = E_UNEXPECTED;
        if (hRichEdit && (res = lpdataobj->GetData(fmt, stg)) == S_OK)
        {
          // Lock the HGLOBAL as it might not be ordinary heap mem
          WCHAR* pText = GlobalLock(stg.hGlobal);
          if (!pText)
          {
            ReleaseStgMedium(stg);
            return res;
          }
          std::wstring text(pText);

          // Do a bit of selection trickiness to ensure we have the default text style -- we can't just EM_PASTESPECIAL due to recursion issues
          DWORD cursorPos, selPos;
          SendMessageW(hRichEdit, EM_GETSEL, &cursorPos, &selPos);
          if (cursorPos == selPos)
          {
            // No selection, so select the character after the cursor, fetch it, and append it to the text
            SendMessageW(hRichEdit, EM_SETSEL, cursorPos, cursorPos + 1);
            WCHAR buffer[2];
            TEXTRANGEW tr = {{cursorPos, cursorPos + 1}, buffer};
            SendMessageW(hRichEdit, EM_GETTEXTRANGE, 0, &tr);
            text.append(buffer[0]);
          }
          // Now that we have ourselves a selection -- we can unformat it then replace it
          CHARFORMAT2 cf;
          cf.cbSize = sizeof(CHARFORMAT2);
          SendMessageW(hRichEdit, EM_GETCHARFORMAT, SCF_DEFAULT, &cf);
          SendMessageW(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, &cf);
          SendMessageW(hRichEdit, EM_REPLACESEL, TRUE, text.c_str());

          GlobalUnlock(stg.hGlobal);
          ReleaseStgMedium(stg);
          // We did the work ourselves, so don't ask the control to do anything for us, unless something broke that is
          res = S_FALSE;
        }
        return res;
      }
      else
      {
        // Have the control check for us to see if it can coerce what on the clipboard to CF_UNICODETEXT
        return S_OK;
      }
    }
  }
};

typedef CComObject<RattyRichEditOleCallbackImpl> RattyRichEditOleCallback;

inline void AttachRattyCallbackToRichEdit(HWND *hRichEdit)
{
  RattyRichEditOleCallback* pCb;
  if (RattyRichEditOleCallback::CreateInstance(&pCb) == S_OK)
  {
    CComPtr cb(pCb);
    cb->SetRichEditCtl(hRichEdit);
    SendMessage(hRichEdit, EM_SETOLECALLBACK, 0, cb);
  }
}
0

Source: https://habr.com/ru/post/1709479/


All Articles