Win32 user control

I finally managed to get syntax highlighting with the richedit and iczelion tutorials. Now that I find this, it is, of course, not fast enough. I'm going to take this one step further: a custom control. But I do not know how to do this. Could you guys tell me how to do this? Give me some info to get started? Maybe even some kind of textbook or offer some book?

Now I do not ask you guys to put this out for me, just to start something. For this, I will use the C ++ / ASM / Win32 API. I'm sure many of you have already created custom editing controls, so maybe you can even share your experience.

Thanks,

Devjeet

+4
source share
2 answers

You will want to look at the owner’s controls. MSDN has an example of this with a list box . You can adapt it to the Edit control.

0
source

I spent one day coding my own custom edit control - it works well, so I would like to share my experience here, maybe this code could be useful for someone ... Since custom drawing a common edit control impossible ( see here ), you must write your own control for editing. The main steps:

// 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); 

How to display keyboard input is described here . My window procedure is as follows

 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); } 

Delete the currently selected text (from selection to cursor).

 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; } } 

Draw a window on a DC window

 void InputWndRedraw(HWND hWnd) { HDC hdc; HideCaret(hWnd); hdc = GetDC(hWnd); InputWndDraw(hWnd, hdc); ReleaseDC(hWnd, hdc); ShowCaret(hWnd); } 

Draw an input buffer (buf *) in the device context. Syntax highlighting and other formatting features go here ...

 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); } } 
+5
source

Source: https://habr.com/ru/post/1380497/


All Articles