3

.NETのRichTextEditコントロールは、いくつかの小さなことを除いて、アプリケーションで必要なことの 99% を実行します。

  1. コントロールへの画像の貼り付け/ドラッグを禁止したい
  2. テキストがコントロールに貼り付け/ドラッグされたときに、そのスタイルをコントロールのデフォルトにリセットしたい

私が解決できる限り、Microsoft は、このコントロールで使用できる「画像なし」プロパティを提供していません。これは理想的です。

私の考えでは、「textChanged」イベントに応答して、画像を削除したり、画面にレンダリングされる前にテキスト スタイルをリセットしたりできると考えていました。もちろん、これは完全なハックになります。たとえば、ユーザーのドラッグ アンド ドロップ マウス アイコンは、画像がドロップ可能であることを示しますが、実際にはそうではありません。

RichTextEdit長い質問を短くするために、コントロールがコピー & ペーストやドラッグ & ドロップを介してインポートできるデータ型の種類にフィルターを設定する方法はありますか?

4

1 に答える 1

0

これは可能です。ただし、必要なコールバックはIRichEditOleCallback COM インターフェイス内に存在するため、.NET RichTextBox インターフェイスの境界を離れる必要があります。

ATL C++ で何が関係しているかを理解するために (ただし、これが機能するという保証はありません。作業している言語に関係なく、Plain 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);
  }
}
于 2015-04-17T21:07:59.723 に答える