1 #pragma once
2 #include <ui/rosctrls.h>
3 
4 class CRichEdit : public CWindow
5 {
6     HMODULE m_LoadedLibrary;
7 
8     VOID
9     GenericInsertText(LPCWSTR lpszText, SIZE_T InsertedTextLen, DWORD dwEffects)
10     {
11         SETTEXTEX SetText;
12         SIZE_T Len = GetTextLen();
13 
14         if (InsertedTextLen)
15         {
16             /* Insert new text */
17             SetText.flags = ST_SELECTION;
18             SetText.codepage = 1200;
19 
20             SendMessageW(EM_SETTEXTEX, (WPARAM)&SetText, (LPARAM)lpszText);
21 
22             if ((dwEffects == CFM_LINK) && !PathIsURLW(lpszText))
23             {
24                 // if text is not an URL, no styling is used
25                 SetRangeFormatting(Len, Len + InsertedTextLen, 0);
26             }
27             else
28             {
29                 SetRangeFormatting(Len, Len + InsertedTextLen, dwEffects);
30             }
31         }
32     }
33 
34   public:
35     CRichEdit() : CWindow(), m_LoadedLibrary(NULL)
36     {
37     }
38 
39     VOID
40     SetRangeFormatting(SIZE_T Start, SIZE_T End, DWORD dwEffects)
41     {
42         CHARFORMAT2W CharFormat;
43 
44         SendMessageW(EM_SETSEL, Start, End);
45 
46         ZeroMemory(&CharFormat, sizeof(CharFormat));
47 
48         CharFormat.cbSize = sizeof(CharFormat);
49         CharFormat.dwMask = dwEffects;
50         CharFormat.dwEffects = dwEffects;
51 
52         SendMessageW(EM_SETCHARFORMAT, SCF_WORD | SCF_SELECTION, (LPARAM)&CharFormat);
53 
54         SendMessageW(EM_SETSEL, End, End + 1);
55     }
56 
57     LONG
58     GetTextLen()
59     {
60         GETTEXTLENGTHEX TxtLenStruct;
61 
62         TxtLenStruct.flags = GTL_NUMCHARS;
63         TxtLenStruct.codepage = 1200;
64 
65         return (LONG)SendMessageW(EM_GETTEXTLENGTHEX, (WPARAM)&TxtLenStruct, 0);
66     }
67 
68     /*
69      * Insert text (without cleaning old text)
70      * Supported effects:
71      *   - CFM_BOLD
72      *   - CFM_ITALIC
73      *   - CFM_UNDERLINE
74      *   - CFM_LINK
75      */
76     VOID
77     InsertText(LPCWSTR lpszText, DWORD dwEffects)
78     {
79         GenericInsertText(lpszText, wcslen(lpszText), dwEffects);
80     }
81 
82     VOID
83     InsertText(const CStringW &szText, DWORD dwEffects)
84     {
85         GenericInsertText(szText.GetString(), szText.GetLength(), dwEffects);
86     }
87     /*
88      * Clear old text and add new
89      */
90     VOID
91     SetText(LPCWSTR lpszText, DWORD dwEffects)
92     {
93         SetWindowTextW(L"");
94         InsertText(lpszText, dwEffects);
95     }
96 
97     VOID
98     SetText(const CStringW &szText, DWORD dwEffects)
99     {
100         SetText(szText.GetString(), dwEffects);
101     }
102 
103     HWND
104     Create(HWND hwndParent)
105     {
106         m_LoadedLibrary = LoadLibraryW(L"riched20.dll");
107 
108         m_hWnd = CreateWindowExW(
109             0, L"RichEdit20W", NULL, WS_CHILD | WS_VISIBLE | ES_MULTILINE | ES_LEFT | ES_READONLY, 205, 28, 465, 100,
110             hwndParent, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
111 
112         if (m_hWnd)
113         {
114             SendMessageW(EM_SETBKGNDCOLOR, 0, GetSysColor(COLOR_BTNFACE));
115             SendMessageW(WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0);
116             SendMessageW(EM_SETEVENTMASK, 0, ENM_LINK | ENM_MOUSEEVENTS);
117             SendMessageW(EM_SHOWSCROLLBAR, SB_VERT, TRUE);
118         }
119 
120         return m_hWnd;
121     }
122 
123     virtual VOID
124     OnLink(ENLINK *Link)
125     {
126     }
127 
128     ~CRichEdit()
129     {
130         if (m_LoadedLibrary)
131         {
132             FreeLibrary(m_LoadedLibrary);
133         }
134     }
135 };
136