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