RichEditD2D Window Controls
This post is for desktop programmers who use RichEdit window controls in their applications and would like to have more display functionality. Examples of such controls include the desktop Outlook To, Cc, and Subject lines as well as WinForms RichTextBox controls, WordPad, and myriad other programs. It’s easy to create a RichEdit window control by calling CreateWindowEx(dwExStyle, lpClassName, …), where lpClassName identifies the class of RichEdit control. Up to January 2020, all RichEdit window controls use the RichEdit GDI/Uniscribe code path. Accordingly, they cannot benefit from the many improvements only available on the RichEdit D2D/DirectWrite path. Such improvements include color-font support, color emoji, OpenType features such as swash variants and stylistic sets, and variable-font axis settings.
In January 2020, the Microsoft 365 RichEdit introduced a D2D/DirectWrite RichEdit window control with the new window class “RichEditD2D”. It uses D2D/DirectWrite for text and images and the window’s HDC for rendering embedded objects and printing. On my laptop, the Microsoft 365 RichEdit is housed in C:\Program Files\Microsoft Office\root\vfs\ProgramFilesCommonX64\Microsoft Shared\OFFICE16\riched20.dll.
The RichEditD2D window class is implemented using the ID2D1Factory::CreateDCRenderTarget() method to create a highly functional ID2D1RenderTarget for an HDC. Image display doesn’t need an HDC and is rendered correctly on the D2D/DirectWrite path. OLE objects need an HDC and are queued up for rendering after the D2D/DirectWrite rendering finishes. It’s important to support OLE objects partly because the desktop Outlook To and Cc resolved email addresses are OLE objects.
The RichEditD2D window class works well with the Win32 Outlook To, Cc, and subject lines, rendering emoji in color on the subject line. Released versions of Outlook don’t use the RichEditD2D window class, since changing the window class involves many code changes. But there’s a new message EM_SWITCHTOD2D (WM_USER + 389) with wparam = lparam = 0 that switches the current window control to D2D. Send this message as soon after creating the control as possible. In particular, if text messages have been received, the EM_SWITCHTOD2D message will fail. Outlook uses this message for the subject line and now displays color emoji 😊. This message effectively changes a RichEdit20WPT window control to a RichEditD2DPT window control. Note that the RichEditD2D implementation hasn’t been ported to Window’s msftedit.dll used by WordPad and other non-Office programs.
RichEdit windowless controls have supported the D2D/DirectWrite code path for years now. For such controls, the client has to implement the ITextHost or ITextHost2 interface, which are more complicated than simply calling CreateWindowEx(). They’re also more flexible, so many programs use windowless RichEdit controls in Office and in Windows. For example, the XAML TextBox and RichTextBox controls use windowless controls running in the D2D/DirectWrite mode and automatically enable color emoji.
For windowless controls, color fonts aren’t enabled by default. To enable them, send the message EM_SETTYPOGRAPHYOPTIONS with wparam = lparam = TO_DEFAULTCOLOREMOJI | TO_DISPLAYFONTCOLOR, where TO_DEFAULTCOLOREMOJI = 0x1000 and TO_DISPLAYFONTCOLOR = 0x2000. In a windowless control, you can do this by calling
ITextServices::TxSendMessage(EM_SETTYPOGRAPHYOPTIONS, TO_DEFAULTCOLOREMOJI | TO_DISPLAYFONTCOLOR, TO_DEFAULTCOLOREMOJI | TO_DISPLAYFONTCOLOR, nullptr);