【问题标题】:Using .net RichTextEdit, but filtering data types?使用.net RichTextEdit,但过滤数据类型?
【发布时间】:2010-10-30 06:35:40
【问题描述】:

.NET 中的 RichTextEdit 控件完成了我需要为我的应用程序执行的 99% 的操作,除了一些小事情:

  1. 我想禁止将图像粘贴/拖动到控件中
  2. 将文本粘贴/拖动到控件中时,我想将其样式重置为控件的默认样式

据我所知,Microsoft 没有在此控件上提供任何类型的“无图像”属性供您使用,这将是理想的。

我的想法是我可以响应“textChanged”事件,然后在图像呈现到屏幕之前删除图像和/或重置文本样式。当然,这将是一个彻头彻尾的黑客攻击。一方面,用户的拖放鼠标图标表明图像是可拖放的,而实际上不是。

为了让一个长长的问题简短,有没有办法对RichTextEdit 控件可以通过复制和粘贴和拖放操作导入的数据类型设置过滤器?

【问题讨论】:

    标签: .net drag-and-drop richtextbox copy-paste


    【解决方案1】:

    这是可能的;但是,您必须离开 .NET RichTextBox 接口的限制才能执行此操作,因为所需的回调位于 IRichEditOleCallback COM 接口中。

    为了让您了解 ATL C++ 中所涉及的内容(但不能保证这将起作用,并且您必须对其进行调整以适应您使用任何语言创建的普通 Ol' COM 对象) ):

    #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's 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);
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-07
      • 2011-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多