1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4 
5 #include "win32textedit.h"
6 
7 #if WINDOWS
8 
9 #include "win32support.h"
10 #include "../../vstkeycode.h"
11 
12 namespace VSTGUI {
13 
14 //-----------------------------------------------------------------------------
CreateEditControl(DWORD wxStyle,const WCHAR * string,DWORD wstyle,const CRect & rect,HWND parent)15 HWND CreateEditControl (DWORD wxStyle, const WCHAR* string, DWORD wstyle, const CRect& rect,
16                         HWND parent)
17 {
18 	return CreateWindowEx (wxStyle, TEXT ("EDIT"), string, wstyle, static_cast<int> (rect.left),
19 	                       static_cast<int> (rect.top), static_cast<int> (rect.getWidth ()),
20 	                       static_cast<int> (rect.getHeight ()), parent, nullptr, GetInstance (),
21 	                       nullptr);
22 }
23 
24 //-----------------------------------------------------------------------------
Win32TextEdit(HWND parent,IPlatformTextEditCallback * textEdit)25 Win32TextEdit::Win32TextEdit (HWND parent, IPlatformTextEditCallback* textEdit)
26 : IPlatformTextEdit (textEdit)
27 , platformControl (0)
28 , platformFont (0)
29 , platformBackColor (0)
30 , oldWndProcEdit (0)
31 {
32 	CRect rect = textEdit->platformGetSize ();
33 	CFontRef fontID = textEdit->platformGetFont ();
34 
35 	CHoriTxtAlign horiTxtAlign = textEdit->platformGetHoriTxtAlign ();
36 	int wstyle = 0;
37 	if (horiTxtAlign == kLeftText)
38 		wstyle |= ES_LEFT;
39 	else if (horiTxtAlign == kRightText)
40 		wstyle |= ES_RIGHT;
41 	else
42 		wstyle |= ES_CENTER;
43 
44 	CPoint textInset = textEdit->platformGetTextInset ();
45 	rect.offset (textInset.x, textInset.y);
46 	rect.right -= textInset.x*2;
47 	rect.bottom -= textInset.y*2;
48 
49 	// get/set the current font
50 	LOGFONT logfont = {0};
51 
52 	CCoord fontH = fontID->getSize ();
53 	if (fontH > rect.getHeight ())
54 		fontH = rect.getHeight () - 3;
55 	if (fontH < rect.getHeight ())
56 	{
57 		CCoord adjust = (rect.getHeight () - (fontH + 3)) / (CCoord)2;
58 		rect.top += adjust;
59 		rect.bottom -= adjust;
60 	}
61 	UTF8StringHelper stringHelper (textEdit->platformGetText ());
62 	text = stringHelper;
63 
64 	CColor backColor = textEdit->platformGetBackColor ();
65 	DWORD wxStyle = WS_EX_LAYERED;
66 	wxStyle = WS_EX_COMPOSITED;
67 	wstyle |= WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL;
68 	if (textEdit->platformIsSecureTextEdit ())
69 		wstyle |= ES_PASSWORD;
70 	platformControl = CreateEditControl (wxStyle, stringHelper.getWideString (), wstyle, rect, parent);
71 	if (!platformControl)
72 	{
73 		wxStyle &= ~WS_EX_LAYERED;
74 		platformControl = CreateEditControl (wxStyle, stringHelper.getWideString (), wstyle, rect, parent);
75 		if (!platformControl)
76 		{
77 			wxStyle &= ~WS_EX_COMPOSITED;
78 			platformControl = CreateEditControl (wxStyle, stringHelper.getWideString (), wstyle, rect, parent);
79 		}
80 	}
81 	else
82 	{
83 		SetLayeredWindowAttributes (platformControl, RGB (backColor.red, backColor.green, backColor.blue), 0, LWA_COLORKEY);
84 	}
85 	platformBackColor = CreateSolidBrush (RGB (backColor.red, backColor.green, backColor.blue));
86 
87 	logfont.lfWeight = FW_NORMAL;
88 	logfont.lfHeight = (LONG)-fontH;
89 	logfont.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
90 	UTF8StringHelper fontNameHelper (fontID->getName ());
91 	VSTGUI_STRCPY (logfont.lfFaceName, fontNameHelper);
92 
93 	logfont.lfClipPrecision	 = CLIP_STROKE_PRECIS;
94 	logfont.lfOutPrecision	 = OUT_STRING_PRECIS;
95 	logfont.lfQuality 	     = DEFAULT_QUALITY;
96 	logfont.lfCharSet        = ANSI_CHARSET;
97 
98 	platformFont = CreateFontIndirect (&logfont);
99 
100 	SetWindowLongPtr (platformControl, GWLP_USERDATA, (__int3264)(LONG_PTR)this);
101 	SendMessage (platformControl, WM_SETFONT, (WPARAM)platformFont, true);
102 	SendMessage (platformControl, EM_SETMARGINS, EC_LEFTMARGIN|EC_RIGHTMARGIN, MAKELONG (0, 0));
103 	SendMessage (platformControl, EM_SETSEL, 0, -1);
104 	SendMessage (platformControl, EM_LIMITTEXT, 255, 0);
105 	SetFocus (platformControl);
106 
107 	oldWndProcEdit = (WINDOWSPROC)(LONG_PTR)SetWindowLongPtr (platformControl, GWLP_WNDPROC, (__int3264)(LONG_PTR)procEdit);
108 
109 }
110 
111 //-----------------------------------------------------------------------------
~Win32TextEdit()112 Win32TextEdit::~Win32TextEdit () noexcept
113 {
114 	if (platformControl)
115 	{
116 		SetWindowLongPtr (platformControl, GWLP_WNDPROC, (__int3264)(LONG_PTR)oldWndProcEdit);
117 		DestroyWindow (platformControl);
118 	}
119 	if (platformFont)
120 		DeleteObject (platformFont);
121 	if (platformBackColor)
122 		DeleteObject (platformBackColor);
123 }
124 
125 //-----------------------------------------------------------------------------
getText()126 UTF8String Win32TextEdit::getText ()
127 {
128 #if 1
129 	return text.c_str ();
130 #else
131 	if (platformControl)
132 	{
133 		int textLength = GetWindowTextLength (platformControl);
134 		TCHAR* newText = new TCHAR[textLength+1];
135 		GetWindowText (platformControl, newText, textLength+1);
136 		UTF8StringHelper windowText (newText);
137 		text = windowText;
138 		delete [] newText;
139 		return text.c_str ();
140 	}
141 	return "";
142 #endif
143 }
144 
145 //-----------------------------------------------------------------------------
setText(const UTF8String & _text)146 bool Win32TextEdit::setText (const UTF8String& _text)
147 {
148 	if (platformControl && text != _text)
149 	{
150 		UTF8StringHelper windowText (_text);
151 		return SetWindowText (platformControl, windowText) ? true : false;
152 	}
153 	return false;
154 }
155 
156 //-----------------------------------------------------------------------------
updateSize()157 bool Win32TextEdit::updateSize ()
158 {
159 	// TODO: Implement me !
160 	return false;
161 }
162 
163 //-----------------------------------------------------------------------------
textChanged()164 void Win32TextEdit::textChanged ()
165 {
166 	if (platformControl)
167 	{
168 		int textLength = GetWindowTextLength (platformControl);
169 		TCHAR* newText = new TCHAR[textLength+1];
170 		GetWindowText (platformControl, newText, textLength+1);
171 		UTF8StringHelper windowText (newText);
172 		text = windowText;
173 		delete [] newText;
174 		textEdit->platformTextDidChange ();
175 	}
176 }
177 
178 //-----------------------------------------------------------------------------
procEdit(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)179 LONG_PTR WINAPI Win32TextEdit::procEdit (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
180 {
181 	Win32TextEdit* win32TextEdit = (Win32TextEdit*)(LONG_PTR) GetWindowLongPtr (hwnd, GWLP_USERDATA);
182 	if (win32TextEdit)
183 	{
184 		WINDOWSPROC oldProc = win32TextEdit->oldWndProcEdit;
185 		switch (message)
186 		{
187 			case WM_GETDLGCODE :
188 			{
189 				LONG_PTR flags = DLGC_WANTALLKEYS;
190 				return flags;
191 			}
192 
193 			case WM_KEYDOWN:
194 			{
195 				if (win32TextEdit->textEdit)
196 				{
197 					if (auto keyCode = keyMessageToKeyCode (wParam, lParam))
198 					{
199 						// for now only dispatch virtual keys
200 						if (keyCode->character == 0 && win32TextEdit->textEdit->platformOnKeyDown (*keyCode))
201 							return 0;
202 					}
203 				}
204 				break;
205 			}
206 
207 			case WM_KILLFOCUS:
208 			{
209 				if (win32TextEdit->textEdit)
210 				{
211 					win32TextEdit->textEdit->platformLooseFocus (false);
212 					return 0;
213 				}
214 				break;
215 			}
216 			case WM_COMMAND:
217 			{
218 				if (HIWORD (wParam) == EN_CHANGE && win32TextEdit->textEdit)
219 				{
220 					win32TextEdit->textChanged ();
221 				}
222 				return 0;
223 			}
224 		}
225 		return CallWindowProc (oldProc, hwnd, message, wParam, lParam);
226 	}
227 	return DefWindowProc (hwnd, message, wParam, lParam);
228 }
229 
230 } // namespace
231 
232 #endif // WINDOWS
233