프로그래밍/C# 2009/04/08 21:23
텍스트 박스에 값을
입력하지 않으면 배경에 특정 메시지를 보여주고, 값을 입력하면 보이지 않게 해달라는 요청을 받았습니다.
그런데!!
텍스트박스는 OnPaint를 기본적으로 쉽게 사용할 수 없습니다. SetStyle 메서드에서
UserPaint 플래그를 설정하면 가능하지만, 글씨 같은
부분도 모두 처리해 줘야되기 때문에 여간 번거로운게 아닙니다. 제가 원하는건 오직 ‘배경에 뭔가 처리!’ 그것 뿐이라구요..ㅠㅡㅠ
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에서 컨트롤만 얻어올 수 있을때의 대처 방법을 포스팅 하겠습니다.
http://lemonwidz.com/tc/trackback/23
kwangho | 2009/04/28 16:44
오오~~ 훈스타고 왔는 데 워터마크 기능이되네요.
잘은 모르겠으나 재정의하는 거 같은데 신기하네요
잘은 모르겠으나 재정의하는 거 같은데 신기하네요
지송 | 2010/07/15 00:06
안녕하세요. ^^;
다름이 아니오라. 위 워터마크효과를 이용해서 제 텍스트박스기능에 붙였는데...
다른창이 텍스트박스 위로 올라갔다 내려갔다를 몇차례 반복하면 잔상이 남게 되는 현상이 발견되어서
해결 방법을 찾아서 댓글 남겨드립니다.
TextRenderer.DrawText(g, waterMarkText, Font, Rectangle.Truncate(bounds), waterMarkColor, BackColor, TextFormatFlags.Default);
글을 이렇게 쓰시면 잔상이 생기진 않더라고요. ^^ 더운 여름 잘 보내시고요. 컨트롤 잘쓸께요.
다름이 아니오라. 위 워터마크효과를 이용해서 제 텍스트박스기능에 붙였는데...
다른창이 텍스트박스 위로 올라갔다 내려갔다를 몇차례 반복하면 잔상이 남게 되는 현상이 발견되어서
해결 방법을 찾아서 댓글 남겨드립니다.
TextRenderer.DrawText(g, waterMarkText, Font, Rectangle.Truncate(bounds), waterMarkColor, BackColor, TextFormatFlags.Default);
글을 이렇게 쓰시면 잔상이 생기진 않더라고요. ^^ 더운 여름 잘 보내시고요. 컨트롤 잘쓸께요.
유쾌한냐옹이 | 2012/02/28 09:33
훈스에서 퇴근5초전 님 추천받아왔는데 정말 유익하군요.
왔사 겁내 저한테 필요한 정보에욬ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
have a gd day 에용~
멋져부러
왔사 겁내 저한테 필요한 정보에욬ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
have a gd day 에용~
멋져부러
유쾌한냐옹이 | 2012/02/28 10:33
이미지를 올려놓을 경우 엄청 뻔쩍거리네요..;;ㅠㅠ
TextBoxPaintSample.zip

0