我最終設法使用richedit和iczelion的教程來完成語法突出顯示。 現在我發現它,它肯定不夠快。我正在考慮採取這一步:自定義編輯控件。但我不知道如何去做。你們能告訴我怎麼去做嗎?給我一些信息開始?也許甚至一些教程或建議一些書?自定義編輯控件win32
現在我不是要求你們爲我拼出來,只是開始。我將爲此使用C++/ASM/Win32 API。我相信你們之中很多人都已經做過自定義的編輯控制,所以可能你甚至可以分享你的經驗。
感謝,
Devjeet
我最終設法使用richedit和iczelion的教程來完成語法突出顯示。 現在我發現它,它肯定不夠快。我正在考慮採取這一步:自定義編輯控件。但我不知道如何去做。你們能告訴我怎麼去做嗎?給我一些信息開始?也許甚至一些教程或建議一些書?自定義編輯控件win32
現在我不是要求你們爲我拼出來,只是開始。我將爲此使用C++/ASM/Win32 API。我相信你們之中很多人都已經做過自定義的編輯控制,所以可能你甚至可以分享你的經驗。
感謝,
Devjeet
你會希望尋找到所有者繪製控件。 MSDN有example of doing this with a list box。您可以將其調整爲編輯控件。
Pure Win32擁有者繪製控件具有非常大量的代碼。如果你只是告訴我們你想用編輯框做什麼可能會更好,也許有人會知道現有的解決方案,將爲你工作。 –
感謝您的response.ok,所以我想用它做一些基本的語法突出顯示。沒有花哨的東西。只需基本的語法高亮。我正在尋找有用的東西來開發,這看起來不錯。之前我還沒有開發過這樣的規模,我期待這是一個非常有趣的體驗。 – devjeetroy
編輯控件沒有「所有者繪製」樣式。 http://msdn.microsoft.com/en-us/library/windows/desktop/bb775464%28v=vs.85%29.aspx因此,你不能*適應你的建議。 – Kissaki
我花了一天的時間寫自己的自定義編輯控件 - 它運行良好,所以我會在這裏分享我的經驗,也許對於這個代碼會有幫助的人...因爲自定義繪製常見的編輯控件是不可能的(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);
}
}
[Visual Studio的樣品(http://archive.msdn.microsoft.com/vcsamplesmfc)有一個寫字板和超墊樣品 –
謝謝,但實際上並非即時通訊尋找MFC教程。 – devjeetroy
一旦您考慮到非英語語言,恰當的自定義編輯控制決非易事。我建議你重新考慮。 –