#include "private.h" #include "commdlg.h" #include "TextInputCtrl.h" extern HINSTANCE g_hInst; #define TEXTINPUTCTRL_CLASSNAME TEXT("TextInputCtrlClassName") #define TIMERID_CARET 0x100 //---------------------------------------------------------------- // // // //---------------------------------------------------------------- ATOM CTextInputCtrl::RegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)s_WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = NULL; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = NULL; wcex.lpszClassName = TEXTINPUTCTRL_CLASSNAME; wcex.hIconSm = NULL; return RegisterClassEx(&wcex); } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- HWND CTextInputCtrl::Create(HWND hwndParent) { _hwnd = CreateWindow(TEXTINPUTCTRL_CLASSNAME, NULL, WS_CHILD, 0, 0, 0, 0, hwndParent, NULL, g_hInst, this); return _hwnd; } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- LRESULT CALLBACK CTextInputCtrl::s_WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; CTextInputCtrl *ptic; switch (message) { case WM_CREATE: SetThis(hwnd, ((CREATESTRUCT *)lParam)->lpCreateParams); SetTimer(hwnd, TIMERID_CARET, GetCaretBlinkTime(), NULL); GetThis(hwnd)->OnCreate(hwnd, wParam, lParam); break; case WM_DESTROY: ptic = GetThis(hwnd); if (ptic) { ptic->OnDestroy(); } break; case WM_SETFOCUS: ptic = GetThis(hwnd); if (ptic) { ptic->OnSetFocus(wParam, lParam); } break; case WM_PAINT: ptic = GetThis(hwnd); hdc = BeginPaint(hwnd, &ps); if (ptic) ptic->OnPaint(hdc); EndPaint(hwnd, &ps); break; case WM_KEYDOWN: ptic = GetThis(hwnd); if (ptic) ptic->OnKeyDown(wParam, lParam); break; case WM_LBUTTONDOWN: ptic = GetThis(hwnd); if (ptic) ptic->OnLButtonDown(wParam, lParam); break; case WM_LBUTTONUP: ptic = GetThis(hwnd); if (ptic) ptic->OnLButtonUp(wParam, lParam); break; case WM_RBUTTONDOWN: ptic = GetThis(hwnd); if (ptic) ptic->OnRButtonDown(wParam, lParam); break; case WM_RBUTTONUP: ptic = GetThis(hwnd); if (ptic) ptic->OnRButtonUp(wParam, lParam); break; case WM_MOUSEMOVE: ptic = GetThis(hwnd); if (ptic) ptic->OnMouseMove(wParam, lParam); break; case WM_IME_COMPOSITION: if (lParam & GCS_RESULTSTR) { HIMC himc = ImmGetContext(hwnd); if (himc) { LONG nSize = ImmGetCompositionString(himc, GCS_RESULTSTR, NULL, 0); if (nSize) { LPWSTR psz = (LPWSTR)LocalAlloc(LPTR, nSize + sizeof(WCHAR)); if (psz) { ImmGetCompositionString(himc, GCS_RESULTSTR, psz, nSize); LocalFree(psz); } } } ImmReleaseContext(hwnd, himc); // // If we don't want to receive WM_IME_CHAR or WM_CHAR with // this result string, we should not call DefWindowProc() // with GCS_RESULTSTR, GCS_RESULTREADSTR, GCS_RESULTCLAUSE and // GCS_RESULTREADCLAUSE flags. // // lParam &= ~(GCS_RESULTCLAUSE | // GCS_RESULTREADCLAUSE | // GCS_RESULTREADSTR | // GCS_RESULTSTR); // if (!lParam) // break; // } return DefWindowProc(hwnd, message, wParam, lParam); case WM_IME_CHAR: // // wParam is a character of the result string. // if we don't want to receive WM_CHAR message for this character, // we should not call DefWindowProc(). // return DefWindowProc(hwnd, message, wParam, lParam); case WM_CHAR: // // wParam is a character of the result string. // switch ((WCHAR)wParam) { case 0x08: case 0x0a: return 0; default: break; } ptic = GetThis(hwnd); if (ptic) { WCHAR wc[2]; wc[0] = (WCHAR)wParam; wc[1] = L'\0'; ptic->_editor.InsertAtSelection(wc); InvalidateRect(hwnd, NULL, TRUE); } break; case WM_TIMER: if (wParam == TIMERID_CARET) { ptic = GetThis(hwnd); if (ptic) { HDC hdc = GetDC(hwnd); ptic->_editor.BlinkCaret(hdc); ReleaseDC(hwnd, hdc); } } break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnPaint(HDC hdc) { _editor.Render(hdc, &_lfCurrentFont); } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnKeyDown(WPARAM wParam, LPARAM lParam) { UINT nSelStart; UINT nSelEnd; switch (0xff & wParam) { case VK_LEFT: if (GetKeyState(VK_SHIFT) & 0x80) { nSelStart = _editor.GetSelectionStart(); nSelEnd = _editor.GetSelectionEnd(); if (nSelStart > 0) { _editor.MoveSelection(nSelStart - 1, nSelEnd); } } else { _editor.MoveSelectionPrev(); } InvalidateRect(_hwnd, NULL, TRUE); break; case VK_RIGHT: if (GetKeyState(VK_SHIFT) & 0x80) { nSelStart = _editor.GetSelectionStart(); nSelEnd = _editor.GetSelectionEnd(); _editor.MoveSelection(nSelStart, nSelEnd + 1); } else { _editor.MoveSelectionNext(); } InvalidateRect(_hwnd, NULL, TRUE); break; case VK_UP: _editor.MoveSelectionUpDown(TRUE); InvalidateRect(_hwnd, NULL, TRUE); break; case VK_DOWN: _editor.MoveSelectionUpDown(FALSE); InvalidateRect(_hwnd, NULL, TRUE); break; case VK_HOME: _editor.MoveSelectionToLineFirstEnd(TRUE); InvalidateRect(_hwnd, NULL, TRUE); break; case VK_END: _editor.MoveSelectionToLineFirstEnd(FALSE); InvalidateRect(_hwnd, NULL, TRUE); break; case VK_DELETE: nSelStart = _editor.GetSelectionStart(); nSelEnd = _editor.GetSelectionEnd(); if (nSelStart == nSelEnd) { _editor.DeleteAtSelection(FALSE); } else { _editor.DeleteSelection(); } InvalidateRect(_hwnd, NULL, TRUE); break; case VK_BACK: nSelStart = _editor.GetSelectionStart(); nSelEnd = _editor.GetSelectionEnd(); if (nSelStart == nSelEnd) { _editor.DeleteAtSelection(TRUE); } else { _editor.DeleteSelection(); } InvalidateRect(_hwnd, NULL, TRUE); break; } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnCreate(HWND hwnd, WPARAM wParam, LPARAM lParam) { _editor.SetWnd(hwnd); _editor.InitTSF(); } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnDestroy() { _editor.UninitTSF(); } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnSetFocus(WPARAM wParam, LPARAM lParam) { _editor.SetFocusDocumentMgr(); } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnLButtonDown(WPARAM wParam, LPARAM lParam) { if (AleartMouseSink(lParam)) { return; } _editor.TerminateCompositionString(); POINT pt; _uSelDragStart = (UINT)-1; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (_editor.MoveSelectionAtPoint(pt)) { InvalidateRect(_hwnd, NULL, TRUE); _uSelDragStart = _editor.GetSelectionStart(); } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnLButtonUp(WPARAM wParam, LPARAM lParam) { if (AleartMouseSink(lParam)) { return; } UINT nSelStart = _editor.GetSelectionStart(); UINT nSelEnd = _editor.GetSelectionEnd(); POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (_editor.MoveSelectionAtPoint(pt)) { UINT nNewSelStart = _editor.GetSelectionStart(); UINT nNewSelEnd = _editor.GetSelectionEnd(); _editor.MoveSelection(min(nSelStart, nNewSelStart), max(nSelEnd, nNewSelEnd)); InvalidateRect(_hwnd, NULL, TRUE); } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnRButtonDown(WPARAM wParam, LPARAM lParam) { if (AleartMouseSink(lParam)) { return; } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnRButtonUp(WPARAM wParam, LPARAM lParam) { if (AleartMouseSink(lParam)) { return; } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::OnMouseMove(WPARAM wParam, LPARAM lParam) { if (AleartMouseSink(lParam)) { return; } if (wParam & MK_LBUTTON) { POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); if (_editor.MoveSelectionAtPoint(pt)) { UINT nNewSelStart = _editor.GetSelectionStart(); UINT nNewSelEnd = _editor.GetSelectionEnd(); _editor.MoveSelection(min(_uSelDragStart, nNewSelStart), max(_uSelDragStart, nNewSelEnd)); InvalidateRect(_hwnd, NULL, TRUE); } } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- void CTextInputCtrl::SetFont(HWND hwndParent) { CHOOSEFONT cf; LOGFONT lf = _lfCurrentFont; cf.lStructSize = sizeof(CHOOSEFONT); cf.hwndOwner = hwndParent; cf.lpLogFont = &lf; cf.Flags = CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS; cf.rgbColors = RGB(0, 0, 0); cf.lCustData = 0; cf.lpfnHook = NULL; cf.lpTemplateName = NULL; cf.hInstance = NULL; cf.lpszStyle = NULL; cf.nFontType = SCREEN_FONTTYPE; cf.nSizeMin = 0; cf.nSizeMax = 0; if (ChooseFont(&cf)) { _lfCurrentFont = lf; InvalidateRect(_hwnd, NULL, TRUE); } } //---------------------------------------------------------------- // // // //---------------------------------------------------------------- BOOL CTextInputCtrl::AleartMouseSink(LPARAM lParam) { POINT pt; pt.x = GET_X_LPARAM(lParam); pt.y = GET_Y_LPARAM(lParam); BOOL bEaten = FALSE; DWORD dwBtnState; if (GetKeyState(VK_LBUTTON) & 0x80) dwBtnState = MK_LBUTTON; else if (GetKeyState(VK_RBUTTON) & 0x80) dwBtnState = MK_RBUTTON; _editor.AleartMouseSink(pt, dwBtnState, &bEaten); return bEaten; }