RichEdit富文本编辑框在实际开发中应用的比较多,现将在平时工作中使用到的做以梳理:
HMODULE m_hRichEditDll = NULL;
HWND hRichEdit = NULL;
1. 初始化RICHED20.dll
BOOL InitRichEditCtrlModule()
{
m_hRichEditDll = LoadLibrary_api_s(L"RICHED20.dll");
return NULL != m_hRichEditDll;
}
2. 创建ReichEdit控件
if (!hRichEdit)
{
DestroyWindow(hRichEdit);
hRichEdit = NULL;
}
{
//创建控件
hRichEdit = CreateWindowEx(
WS_EX_CLIENTEDGE | WS_EX_TRANSPARENT | WS_EX_WINDOWEDGE, L"RichEdit20W", NULL,
WS_CHILD | WS_VISIBLE | /*WS_VSCROLL | WS_HSCROLL |*/ ES_MULTILINE | ES_NOHIDESEL | ES_WANTRETURN, x,
y, 10, 30, win->hwndCanvas, 0, NULL, 0);
//设置控件需要响应的消息
SendMessage(hRichEdit, EM_SETEVENTMASK, 0,
ENM_SELCHANGE | ENM_MOUSEEVENTS | ENM_CHANGE | ENM_KEYEVENTS | ENM_SCROLL | ENM_DROPFILES |
ENM_REQUESTRESIZE);
//设置控件字体样式
CHARFORMAT cf;
ZeroMemory(&cf, sizeof(CHARFORMAT));
cf.cbSize = sizeof(CHARFORMAT);
cf.dwMask = CFM_BOLD | CFM_COLOR | CFM_FACE | CFM_ITALIC | CFM_SIZE | CFM_UNDERLINE;
cf.dwEffects = 0;
cf.yHeight = 18 * 18; //文字高度
cf.crTextColor = RGB(255, 0, 0); //文字颜色
_tcscpy_s(cf.szFaceName, sizeof(cf.szFaceName) / sizeof(WCHAR), L"Helv"); //设置字体
::SendMessage(hRichEdit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
RECT winRect;
// 获取RichEdit控件的屏幕矩形
GetWindowRect(hRichEdit, &winRect);
// 获取RichEdit控件的行数
int iLineCount = (int)::SendMessage(hRichEdit, EM_GETLINECOUNT, 0, 0);
// 分别遍历每行上面的文本
int iRetLen = 0;
TCHAR tmpItemContent[2048 + 1] = {0};
for (int nIndex = 0; nIndex < iLineCount; nIndex++) {
memset(tmpItemContent, 0x00, sizeof(tmpItemContent));
*(LPWORD)tmpItemContent = (WORD)2048;
// 获取指定行上的文本
iRetLen = ::SendMessage(hRichEdit, EM_GETLINE, nIndex, (LPARAM)tmpItemContent);
}
// 分别遍历每行的字符位置
int xMax = 0, yMax = 0;
POINT pt;
for (int iPosIndex = 0; iPosIndex < iRetLen; iPosIndex++) {
::SendMessage(hRichEdit, EM_POSFROMCHAR, (WPARAM)&pt, (LPARAM)iPosIndex);
pt.x > xMax ? xMax = pt.x : 0;
pt.y > yMax ? yMax = pt.y : 0;
wsprintf(tmpBuf, L"nIndex[%d] iPosIndex[%d] [%c] (%d, %d) \n", nIndex, iPosIndex,
tmpItemContent[iPosIndex], pt.x, pt.y);
OutputDebugString(tmpBuf);
}
获取焦点
::SetFocus(hRichEdit);
}
3. ReichEdit控件事件处理
3.1 实时获取控件大小,并修改控件大小(在父类消息处理函数中处理WM_NOTIFY消息)
LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
...
case WM_NOTIFY:
{
LPNMHDR nmhdr = (LPNMHDR)lParam;
if (nmhdr->code == EN_REQUESTRESIZE) {
REQRESIZE* pReqResize = (REQRESIZE*)lParam;
int iWidth = pReqResize->rc.right - pReqResize->rc.left;
int iHeight = pReqResize->rc.bottom - pReqResize->rc.top;
TCHAR szText[4096 + 1] = {0};
int iCharNum = GetWindowText(hRichEdit, szText, 4096);
int cx = iCharNum * 18 * 2; //18代表控件上的字宽
RECT winRect;
GetWindowRect(hWnd, &winRect);
POINT pRB = {winRect.right, winRect.bottom};
ScreenToClient(hWnd, &pRB);
int iMaxWidth = pRB.x - pReqResize->rc.left;
if (cx > iMaxWidth)
iWidth = iMaxWidth;
else
iWidth = cx;
::MoveWindow(hRichEdit, pReqResize->rc.left, pReqResize->rc.top, iWidth, iHeight, TRUE);
}
}
breeak;
case WM_KEYDOWN: {
TCHAR tmpBuf[128] = {0};
if (wParam == VK_RETURN) {
wsprintf(tmpBuf, L"回车键\n");
OutputDebugString(tmpBuf);
} else if (wParam == VK_BACK) {
wsprintf(tmpBuf, L"回格键\n");
OutputDebugString(tmpBuf);
}
} break;
...
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
}
4. 卸载RICHED20.dll
void UnInitRichEditCtrlModule()
{
if (m_hRichEditDll)
FreeLibrary(m_hRichEditDll);
m_hRichEditDll = NULL;
}
//windows操作系统dpi换算
static int s_iDPI = ::GetDeviceCaps(::GetDC(NULL), LOGPIXELSX);
#define GDIWIDTH(i) (i * (s_iDPI / 96))
//通过控件句柄和控件上的字体获取控件宽度
static UINT GetStringWidth(const HWND& hWnd, const std::wstring& szStr, const HFONT& hFont) {
TCHAR tmpBuf[128] = {0};
if (NULL == hFont)
OutputDebugString(L"NULL ============ hFont\n");
if (!hFont || szStr.empty())
return 0;
HDC hdc = GetDC(NULL);
HFONT hOldFont = (HFONT)SelectObject(hdc, hFont);
SIZE size = {0};
int nCount = szStr.size();
::GetTextExtentPoint32(hdc, szStr.c_str(), nCount, &size);
SelectObject(hdc, hOldFont);
ReleaseDC(NULL, hdc);
wsprintf(tmpBuf, L" =======> szStr [%s] nCount [%s] cx [%d]\n", szStr.c_str(), nCount, size.cx);
OutputDebugString(tmpBuf);
return size.cx;
}