방법.. 잘 읽어봐라..-_-;
Form 페이지 만든 후 Form의 Designer.cs 페이지에서 해당프로젝트.Controls.TextBoxExt() 라고 InitializeComponent와
제일 아래 private Head1Ton.Dev.Controls.TextBoxExt txtBoxExt1; 이라고 변경해줘야만 한다.
텍스트 박스에 값을 입력하지 않으면 배경에 특정 메시지를 보여주고, 값을 입력하면 보이지 않게 해달라는 요청을 받았습니다.
그런데!!
텍스트박스는 OnPaint를 기본적으로 쉽게 사용할 수 없습니다. SetStyle 메서드에서 UserPaint 플래그를 설정하면 가능하지만, 글씨 같은 부분도 모두 처리해 줘야되기 때문에 여간 번거로운게 아닙니다. 제가 원하는건 오직‘배경에 뭔가 처리!’ 그것 뿐이라구요..ㅠㅡㅠ
그래서 WndProc 를 재정의해서 이벤트를 받아오는 방법을 사용했습니다. 주의라고 까진 아니지만, 유심히 보실 부분은 WM_KILLFOCUS 도 처리해주고 있는것인데요. 텍스트 박스를 멀티라인 지원으로 해놓으면, WM_PAINT 가 발생을 하지 않더군요. 그래서 WM_PAINT 에서도 처리를 해주었습니다.
using System; using System.Drawing; using System.Windows.Forms;
namespace TextBoxPaintSample.Controls { public class TextBoxExt : TextBox { private string waterMarkText = string.Empty; // 워터마크로 사용할 문자열 private Color waterMarkColor = Color.Gray; // 워터마크로 사용할 문자색
protected override void WndProc(ref Message m) { // base.WndProc 중복 호출을 피하기 위해서 bool isCallAlready = false;
// WM_PAINT 메세지를 받아서 처리 if (m.Msg == 0x000F) // WM_PAINT = 0x000F { // 원래 처리해야될 로직을 먼저 호출해서 처리해줌 base.WndProc(ref m); isCallAlready = true;
DrawWaterMarkText(); } // Multiline == true 일때는 포커스 빠질때 WM_PAINT가 발생 안하므로 else if (m.Msg == 0x0008 && this.Multiline) // WM_KILLFOCUS = 0x0008 { DrawWaterMarkText(); }
if (false == isCallAlready) base.WndProc(ref m); }
// 텍스트박스의 크기를 계산해서 워터마크를 그려줌 private void DrawWaterMarkText() { if (string.IsNullOrEmpty(this.Text) && false == string.IsNullOrEmpty(this.WaterMarkText) && this.IsHandleCreated && false == this.Focused && this.Visible) { using (Graphics g = Graphics.FromHwnd(this.Handle)) { // 텍스트의 vertical 정렬을 하기 위한 계산들 StringFormat sf = new StringFormat(); float textHeight = g.MeasureString(this.WaterMarkText, this.Font, this.Width, sf).Height; float textY = ((float)this.Height - textHeight) / (float)2.0; RectangleF bounds = new RectangleF( 0, textY, (float)this.Width, (float)this.Height - (textY * (float)2.0));
g.DrawString(this.WaterMarkText, this.Font, new SolidBrush(this.WaterMarkColor),bounds, sf); } } }
public string WaterMarkText { get { return waterMarkText; } set { waterMarkText = value; } }
public Color WaterMarkColor { get { return waterMarkColor; } set { waterMarkColor = value; } }
} } |
샘플 결과

이러한 코드를 바탕으로 텍스트 박스의 배경으로 이미지를 넣는다던지 하는 처리도 가능하리라 생각됩니다.
소스코드 전체를 첨부합니다. VS2005에서 작성 및 테스트되었습니다.
ps. 사실, 이 포스트의 내용은 제가 원래 작성하고자 했던 내용은 아닙니다만, 문제해결의 과정을, 혹은 진짜 이 내용이 필요하신분을 위해서 먼저 작성하였습니다. 다음 포스트에서는 TextBox를 상속받을 수 없는경우, 즉 다른 사람이 만든 TextBox에서 컨트롤만 얻어올 수 있을때의 대처 방법을 포스팅 하겠습니다.
'Program > C#' 카테고리의 다른 글
주사위놀이 (0) | 2010.02.09 |
---|---|
Silent Install of MS .Net Framework Version 2 (0) | 2010.02.05 |
윈도우 폼 간 도킹 기능 (0) | 2010.01.26 |
윈폼 파일 드레그하기 (0) | 2010.01.26 |
C# 초보자분들을 위한 기초강좌 (0) | 2010.01.24 |