Dreamine.UI.WinForms 1.0.1
Dreamine.UI.WinForms 사용자 인터페이스 기능과 구성 요소를 제공합니다.
로딩중...
검색중...
일치하는것 없음
DreamineTextBox.cs
이 파일의 문서화 페이지로 가기
1using System.Drawing;
2using System.Runtime.InteropServices;
4
6
15public class DreamineTextBox : UserControl
16{
25 private const int EM_SETCUEBANNER = 0x1501;
74 [DllImport("user32.dll", CharSet = CharSet.Unicode)]
75 private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, string lParam);
76
85 private readonly TextBox _inner;
94 private bool _isFocused;
95
96 // ── Properties ────────────────────────────────────────
105 public new string Text
106 {
107 get => _inner.Text;
108 set => _inner.Text = value;
109 }
110
119 private string _hint = string.Empty;
128 public string Hint
129 {
130 get => _hint;
131 set
132 {
133 _hint = value;
134 if (_inner.IsHandleCreated)
135 SendMessage(_inner.Handle, EM_SETCUEBANNER, (IntPtr)1, _hint);
136 }
137 }
138
147 public bool IsReadOnly
148 {
149 get => _inner.ReadOnly;
150 set { _inner.ReadOnly = value; Invalidate(); }
151 }
152
161 public int SelectionStart
162 {
163 get => _inner.SelectionStart;
164 set => _inner.SelectionStart = Math.Clamp(value, 0, _inner.TextLength);
165 }
166
176 {
177 get => _inner.SelectionLength;
178 set => _inner.SelectionLength = Math.Clamp(value, 0, _inner.TextLength - _inner.SelectionStart);
179 }
180
189 public IntPtr TextBoxHandle => _inner.Handle;
190
199 public override Color ForeColor
200 {
201 get => base.ForeColor;
202 set { base.ForeColor = value; if (_inner != null) _inner.ForeColor = value; }
203 }
204
213 public new Font Font
214 {
215 get => base.Font;
216 set { base.Font = value; if (_inner != null) _inner.Font = value; }
217 }
218
227 public new event EventHandler? TextChanged;
228
245 public void InsertText(string text)
246 {
247 if (_inner.ReadOnly)
248 return;
249
250 _inner.SelectedText = text;
251 _inner.Focus();
252 }
253
278 public void ReplaceTextTail(int replaceCount, string text)
279 {
280 if (_inner.ReadOnly)
281 return;
282
283 var currentText = _inner.Text ?? string.Empty;
284 var selectionStart = Math.Clamp(_inner.SelectionStart, 0, currentText.Length);
285 var selectionLength = Math.Clamp(_inner.SelectionLength, 0, currentText.Length - selectionStart);
286
287 if (selectionLength > 0)
288 {
289 _inner.SelectedText = text;
290 }
291 else
292 {
293 var removeStart = Math.Max(0, selectionStart - replaceCount);
294 removeStart = Math.Min(removeStart, currentText.Length);
295 var removeLength = Math.Clamp(selectionStart - removeStart, 0, currentText.Length - removeStart);
296 _inner.Text = currentText.Remove(removeStart, removeLength).Insert(removeStart, text);
297 _inner.SelectionStart = removeStart + text.Length;
298 }
299
300 _inner.Focus();
301 }
302
311 public void Backspace()
312 {
313 if (_inner.ReadOnly)
314 return;
315
316 var currentText = _inner.Text ?? string.Empty;
317 var selectionStart = Math.Clamp(_inner.SelectionStart, 0, currentText.Length);
318 var selectionLength = Math.Clamp(_inner.SelectionLength, 0, currentText.Length - selectionStart);
319
320 if (selectionLength > 0)
321 {
322 _inner.SelectedText = string.Empty;
323 }
324 else if (selectionStart > 0)
325 {
326 _inner.Text = currentText.Remove(selectionStart - 1, 1);
327 _inner.SelectionStart = selectionStart - 1;
328 }
329
330 _inner.Focus();
331 }
332
349 public string GetTextBeforeCaret()
350 {
351 var currentText = _inner.Text ?? string.Empty;
352 var caret = Math.Clamp(_inner.SelectionStart, 0, currentText.Length);
353 return currentText[..caret];
354 }
355
356 // ── Constructor ───────────────────────────────────────
366 {
367 // _inner must be created first — SetStyle and property setters below
368 // can trigger OnLayout / ForeColor / Font overrides before the field is set.
369 _inner = new TextBox
370 {
371 BorderStyle = BorderStyle.None,
372 BackColor = DreamineTheme.InputBackground,
374 Font = new Font("Segoe UI", 10f, FontStyle.Regular, GraphicsUnit.Point),
375 Dock = DockStyle.Fill,
376 Margin = Padding.Empty,
377 };
378
379 _inner.GotFocus += (_, _) => { _isFocused = true; Invalidate(); };
380 _inner.LostFocus += (_, _) => { _isFocused = false; Invalidate(); };
381 _inner.TextChanged += (s, e) => TextChanged?.Invoke(this, e);
382 _inner.HandleCreated += (_, _) =>
383 {
384 if (!string.IsNullOrEmpty(_hint))
385 SendMessage(_inner.Handle, EM_SETCUEBANNER, (IntPtr)1, _hint);
386 };
387
388 SetStyle(
389 ControlStyles.AllPaintingInWmPaint |
390 ControlStyles.UserPaint |
391 ControlStyles.DoubleBuffer |
392 ControlStyles.ResizeRedraw, true);
393
394 BackColor = DreamineTheme.InputBackground;
396 Font = _inner.Font;
397 Height = 36;
398 Padding = new Padding(2);
399
400 Controls.Add(_inner);
401 }
402
411 protected override Padding DefaultPadding => new Padding(6, 0, 6, 0);
412
429 protected override void OnLayout(LayoutEventArgs e)
430 {
431 base.OnLayout(e);
432 if (_inner == null) return;
433 _inner.SetBounds(6, (Height - _inner.PreferredHeight) / 2,
434 Width - 12, _inner.PreferredHeight);
435 }
436
453 protected override void OnPaint(PaintEventArgs e)
454 {
455 var g = e.Graphics;
456 var rect = new Rectangle(0, 0, Width - 1, Height - 1);
457
458 using var bgBrush = new SolidBrush(BackColor);
460 if (!Enabled) borderColor = Color.FromArgb(80, borderColor);
461 using var pen = new Pen(borderColor, 1.5f);
463 }
464
473 protected override Size DefaultSize => new(220, 36);
474}
override void OnPaint(PaintEventArgs e)
static IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, string lParam)
void ReplaceTextTail(int replaceCount, string text)
override void OnLayout(LayoutEventArgs e)
static void FillRoundedRect(Graphics g, Brush fill, Pen? border, Rectangle rect, float radius)
static readonly Color BorderFocus
static readonly Color TextPrimary
static readonly Color BorderNormal
static readonly Color InputBackground