Click here to Skip to main content
15,885,172 members
Articles / Desktop Programming / Windows Forms

Textbox with rounded corners

Rate me:
Please Sign up or sign in to vote.
2.96/5 (13 votes)
1 Feb 2007CPOL3 min read 190.2K   8.7K   51   6
A TextBox control with rounded corners.

Sample image

Introduction

I've been looking around a bit to find an example of how to get a Windows Forms TextBox painted with rounded corners, but I did not find a solution. I collected some useful tips, put them all together with some logic, and came up with a satisfying solution. Because I have found many excellent coding tips on this site, I'm posting the source here so it hopefully can be useful for someone.

Overview

To come up with the rounded corners textbox, I started trying to work with the paint override event, but unfortunately without any result, which is due to the fact (I assume) that the textbox is derived from Windows. Therefore, I tried overriding the WM_PAINT API instead, which had the desired results.

The tricky part then was that I first could only draw on the client area of the textbox, which resulted in a very small textbox. Once again, API came up with a solution: I added two declarations, one for GetWindowDC to get a handle on the non-client area, and one for ReleaseDC to clean up after my custom drawing.

Now that I could fully use the graphics of my textbox, and added the coding to draw a rounded rectangle, I was still not completely satisfied because the height of my textbox was dependent on the font size. I tried searching a way to override this "hidden" autosize event, but did not find a working solution. I came up with a way to be able to change the textbox's height by setting the multiline feature to true, but I still believe there has to be a better way for this. Because I also added a method which catches the Enter-keypress and which returns a Tab-keypress instead, the multiline solution will do for my needs.

Because the rounded textbox control is part of a bigger solution I recently wrote, you will also find some custom properties, OriText, NewText, and a custom event Texthaschanged, which actually is a way to check whether the control text has changed before the Onleave-event takes place, and the custom properties provide access to the original text as well as the new text. I needed these properties and left them in the control, maybe someone finds them useful.

The code

OK, time for the code.

The procedure below handles the event of pressing the Enter key, as well as the event of pressing the "," key. The Enter key has been replaced by a Tab key so the next control in the tab order will be selected. The second part of the procedure is to handle the input of a decimal character and format the input according to Belgian point for decimal format.

VB
Protected Overrides Function ProcessCmdKey(ByRef msg _
                    As System.Windows.Forms.Message, _
                    ByVal keyData As System.Windows.Forms.Keys) As Boolean 
    If msg.WParam.ToInt32() = CInt(Keys.Enter) Then 
        SendKeys.Send("{Tab}")
        Return True 
    ElseIf msg.WParam.ToInt32() = CInt(Keys.Decimal) Then 
        SendKeys.Send(",")
        Return True 
    End If 
End Function

The next method is the actual overriding of the WM_Paint event, in which the redrawing is done. It makes uses of the API functions GetWindowDC and ReleaseDC to get the actual graphics of the control, including the non-client area.

VB
Protected Overrides Sub WndProc(ByRef m As _
          System.Windows.Forms.Message) Handles MyBase.WndProc(m)
    Select Case m.Msg
        Case &HF 'WM_PAINT 
            Dim rect As New Rectangle(0, 0, MyBase.Width, MyBase.Height)
            Dim hDC As IntPtr = GetWindowDC(Me.Handle)
            Dim g As Graphics = Graphics.FromHdc(hDC)
            If Me.Enabled Then 
                g.Clear(Color.White)
            Else 
                g.Clear(Color.FromName("control"))
            End If 
            DrawBorder(g)
            DrawText(g)
            ReleaseDC(Me.Handle, hDC)
            g.Dispose()
        Case &H7, &H8, &H200, &H2A3
        'CMB_DROPDOWN, CMB_CLOSEUP, WM_SETFOCUS, 
        'WM_KILLFOCUS, WM_MOUSEMOVE, 'WM_MOUSELEAVE 
            UpdateState()
    End Select 
End Sub

To get the rounded corners, the method shown below is used.

VB
Private Sub TekenRondeRechthoek(ByVal g As Graphics, _
            ByVal pen As Pen, ByVal rectangle As Rectangle, _
            ByVal radius As Single)
    Dim size As Single = (radius * 2.0!)
    Dim gp As GraphicsPath = New GraphicsPath
    gp.AddArc(rectangle.X, rectangle.Y, size, size, 180, 90)
    gp.AddArc((rectangle.X + (rectangle.Width - size)), _
               rectangle.Y, size, size, 270, 90)
    gp.AddArc((rectangle.X + (rectangle.Width - size)), _
              (rectangle.Y + (rectangle.Height - size)), _
              size, size, 0, 90)
    gp.AddArc(rectangle.X, (rectangle.Y + _
             (rectangle.Height - size)), size, size, 90, 90)
    gp.CloseFigure()
    g.DrawPath(pen, gp)
    gp.Dispose()
End Sub

The complete code example is included in the attached zip-file. I hope it can be useful for anyone.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Web Developer
Belgium Belgium
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionI was curious if this function and source code can be adapted to VBA Excel environment Pin
Member 1436760313-May-19 23:06
Member 1436760313-May-19 23:06 
GeneralMy vote of 1 Pin
Member 1105007424-Jun-18 16:54
Member 1105007424-Jun-18 16:54 
QuestionDefault size Pin
John F Berry18-Feb-13 10:18
John F Berry18-Feb-13 10:18 
Thank you very much for this great example. I am curious about one thing though. When the control is added, I need to resize the control so it all shows. This also holds true when changing the font size within the control. How can this be adjusted?
GeneralMy vote of 3 Pin
Burak Tunçbilek10-Jul-12 12:04
Burak Tunçbilek10-Jul-12 12:04 
GeneralUse WM_NCPAINT message Pin
Bernhard Elbl1-Feb-07 23:03
Bernhard Elbl1-Feb-07 23:03 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.