我终于设法使用 richedit 和 iczelion 的教程完成了语法高亮显示。 现在我找到了,它肯定不够快。我正在考虑向前迈出这一步:自定义编辑控件。但我不知道该怎么做。你们能告诉我该怎么做吗?给我一些信息开始?甚至一些教程或推荐一些书?
现在我不要求你们为我拼写出来,只是一些开始。我将为此使用 C++/ASM/Win32 API。我敢肯定你们中的许多人之前已经制作过自定义编辑控件,所以您甚至可以分享您的经验。
谢谢,
开发人员
最佳答案
我花了一天时间编写我自己的自定义编辑控件 - 它运行良好,所以我想在这里分享我的经验,也许对于某些人来说这段代码可能会有所帮助......因为自定义绘制一个通用的编辑控件是不可能的( see here ),您必须编写自己的编辑控件。一般步骤是:
// global vars
int select; // current selection position
int cursor; // current cursor position
HWND parent; // parent window
wchar_t buf[MAXINPUTBUF]; // edit buffer
WNDPROC oldproc; // old window procedure
// create custom control window
hWnd = CreateWindowW(L"static", NULL, WS_CHILD | WS_TABSTOP | SS_LEFT | SS_NOTIFY, 0, 0, 0, 0, parent, NULL, (HINSTANCE)GetWindowLongPtr(parent, GWL_HINSTANCE), NULL);
// todo: use SetProp() to store all global vars
oldproc = (WNDPROC)SetWindowLongPtrW(hWnd, GWL_WNDPROC, (LONG_PTR)InputWndProc);
SetWindowPos(hWnd, HWND_TOP, x, y, cx, cy, 0);
描述了如何显示键盘输入here .我的窗口过程如下所示
LRESULT CALLBACK InputWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDOWN:
//SetFocus(hWnd);
PostMessageW(GetParent(hWnd), WM_NEXTDLGCTL, (WPARAM)hWnd, TRUE);
break;
case WM_KILLFOCUS:
HideCaret(hWnd);
DestroyCaret();
break;
case WM_SETFOCUS:
{
RECT r;
GetClientRect(hWnd, &r);
// Create a solid black caret.
CreateCaret(hWnd, (HBITMAP) NULL, 2, r.bottom-r.top);
ShowCaret(hWnd);
InputWndRedraw(hWnd);
}
return FALSE;
case WM_GETDLGCODE:
return DLGC_WANTALLKEYS | DLGC_WANTARROWS;
case WM_KEYDOWN:
{
switch (wParam)
{
case 'V':
if (0x8000 & GetKeyState(VK_CONTROL))
{
HANDLE h;
wchar_t *cb;
int len,slen;
InputWndDelete(hWnd);
OpenClipboard(NULL);
h = GetClipboardData(CF_UNICODETEXT);
cb = (wchar_t*)GlobalLock(h);
if (cb)
{
memcpy(buf+(cursor+len)*sizeof(wchar_t), buf+cursor*sizeof(wchar_t), (slen-cursor)*sizeof(wchar_t));
memcpy(buf+cursor*sizeof(wchar_t), cb, len*sizeof(wchar_t));
}
GlobalUnlock(h);
CloseClipboard();
InputWndRedraw(hWnd);
}
break;
case VK_RIGHT:
if (cursor-1 >= MAXINPUTBUF || cursor >= (int)wcslen(buf))
break;
cursor++;
if (!(GetKeyState(VK_SHIFT) & 0x8000))
select = cursor;
InputWndRedraw(hWnd);
break;
case VK_TAB:
PostMessageW(GetParent(hWnd), WM_NEXTDLGCTL, GetKeyState(VK_SHIFT) & 0x8000, FALSE);
break;
case VK_LEFT:
if (cursor <= 0)
break;
cursor--;
if (!(GetKeyState(VK_SHIFT) & 0x8000))
select = cursor;
InputWndRedraw(hWnd);
break;
case VK_HOME:
cursor = 0;
if (!(GetKeyState(VK_SHIFT) & 0x8000))
select = cursor;
InputWndRedraw(hWnd);
break;
case VK_END:
cursor = wcslen(buf);
if (!(GetKeyState(VK_SHIFT) & 0x8000))
select = cursor;
InputWndRedraw(hWnd);
break;
case VK_DELETE:
if (cursor >= (int)wcslen(buf))
{
InputWndDelete(hWnd);
InputWndRedraw(hWnd);
break;
}
if (select == cursor)
select ++;
InputWndDelete(hWnd);
InputWndRedraw(hWnd);
break;
case VK_BACK:
if (cursor <= 0)
{
InputWndDelete(hWnd);
InputWndRedraw(hWnd);
break;
}
if (select == cursor)
cursor --;
InputWndDelete(hWnd);
InputWndRedraw(hWnd);
}
}
break;
case WM_CHAR:
if (wParam < VK_SPACE)
break;
InputWndDelete(hWnd);
if (wcslen(buf)+1 < MAXINPUTBUF)
{
wmemmove(buf+(cursor+1)*sizeof(wchar_t), buf+cursor*sizeof(wchar_t), wcslen(s->buf)-cursor);
buf[cursor] = wParam;
cursor++;
select = cursor;
}
InputWndRedraw(hWnd);
break;
case WM_ERASEBKGND:
// no flickering
return TRUE;
case WM_PAINT:
{
HDC dc;
PAINTSTRUCT paint;
dc = BeginPaint(hWnd, &paint);
InputWndDraw(hWnd, dc);
EndPaint(hWnd, &paint);
}
return TRUE;
}
return CallWindowProcW(oldproc, hWnd, msg, wParam, lParam);
}
删除当前选定的文本(从选择到光标)。
void InputWndDelete(HWND hWnd)
{
int len;
len = wcslen(buf);
if (select > cursor)
{
memcpy(buf+cursor*sizeof(wchar_t), buf+select*sizeof(wchar_t), (len - select)*sizeof(wchar_t));
ZeroMemory(buf+(len-select+cursor)*sizeof(wchar_t), (MAXINPUTBUF-len+select-cursor)*sizeof(wchar_t));
select = cursor;
}
else if (select < cursor)
{
memcpy(buf+select*sizeof(wchar_t), buf+cursor*sizeof(wchar_t), (len - cursor)*sizeof(wchar_t));
ZeroMemory(buf+(len-cursor+select)*sizeof(wchar_t), (MAXINPUTBUF-len+cursor-select)*sizeof(wchar_t));
cursor = select;
}
else
{
select = cursor;
}
}
在窗口DC上绘制窗口
void InputWndRedraw(HWND hWnd)
{
HDC hdc;
HideCaret(hWnd);
hdc = GetDC(hWnd);
InputWndDraw(hWnd, hdc);
ReleaseDC(hWnd, hdc);
ShowCaret(hWnd);
}
在设备上下文中绘制输入缓冲区 (buf*)。语法高亮和其他格式设置功能在这里...
void InputWndDraw(HWND hWnd, HDC hdc)
{
RECT r,cr;
GetClientRect(hWnd, &cr);
// draw selected rectangle FillRect()...
CopyRect(&r,&cr);
DrawTextW(hdc, buf, -1, &r, DT_LEFT | DT_TOP);
if (cursor)
DrawTextW(hdc, buf, cursor, &r, DT_LEFT | DT_TOP | DT_CALCRECT);
else
r.right = cr.left;
if (GetFocus() == hWnd)
{
if (r.right > cr.right)
SetCaretPos(cr.right, cr.top);
else
SetCaretPos(r.right, cr.top);
}
}
关于c++ - 自定义编辑控件win32,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8074047/