使用.net RichTextEdit,但过滤数据类型?

发布于 2024-07-22 05:27:46 字数 411 浏览 3 评论 0原文

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

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

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

我的想法是,我可以响应“textChanged”事件,然后在渲染到屏幕之前删除图像和/或重置文本样式。 当然,这完全是一种黑客行为。 一方面,用户的拖放鼠标图标将表明图像是可放置的,但实际上却不可放置。

长话短说,有没有办法设置过滤器来限制 RichTextEdit 控件可以通过复制粘贴和拖放导入哪些类型的数据类型?

The RichTextEdit control in .NET does 99% of what I need to do for my application, except for a few little things:

  1. I want to disallow pasting/dragging images into the control
  2. When text is pasted/dragged into the control, I want to reset its style to the control's default

As far as I can work out, Microsoft hasn't provided any type of "no images" property on this control that you can use, which would be ideal.

My thought was that I could respond to the "textChanged" event then remove the image and/or reset the text style before it gets rendered to the screen. Of course this would be a total hack. For one thing, the user's drag&drop mouse icon would indicate that images are droppable and they really aren't.

To make a long question short, is there a way to set a filter on what type of data types a RichTextEdit control can import via Copy&Paste and Drag&Drop?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遮了一弯 2024-07-29 05:27:46

这个有可能; 但是,您必须离开 .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);
  }
}

This is possible; however, you'll have to leave the confines of the .NET RichTextBox interface to do it, as the callback needed lives in the IRichEditOleCallback COM interface.

To give you an idea of what's involved, in ATL C++ (no guarantees that this will work though, and you'll have to adapt it to however you create a Plain Ol' COM Object in whatever language you're working in):

#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);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文