Solved

Overriding Textbox with SetStyle breaks it

Posted on 2006-11-19
2
757 Views
Last Modified: 2012-05-05
The goal is to build a custom TextBox, which permits drawing a bold box around it, to accentuate the box.
To do this, it is necessary to override the OnPaint event.
The onPaint event only fires if SetStyle is called in the control's constructor.
The problem is that the custom textbox doesn't display the same font, nor does it display the value as design time.
And I don't want to reinvent the wheel by reimplementing the standard textbox drawing of standard text.
If you use the designer to add a standard TextBox and MyTextBox controls, you will see the differences in behavior.
What is necessary, so that OnPaint may be called, but otherwise standard TextBox behavior is used?

Imports System.Windows.Forms
Imports System.Drawing

Public Class MyTextBox
    Inherits TextBox

    Public Sub New()
        MyBase.new()
        SetStyle(ControlStyles.UserPaint, True)  ' enable OnPaint call
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)
    End Sub
End Class
0
Comment
Question by:brotherbill999
2 Comments
 
LVL 96

Accepted Solution

by:
Bob Learned earned 500 total points
ID: 17979226
Here is an VB.NET 2005 example that overrides the default WndProc to wait for the WM_PAINT message:

Imports System.ComponentModel
Imports System.Runtime.InteropServices

Public Class CustomTextBox : Inherits TextBox

    <Description("Returns a window handler."), _
    DllImport("user32.dll", _
    SetLastError:=True, CharSet:=CharSet.Auto, ExactSpelling:=True, _
    CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Function GetWindowDC(ByVal hWnd As IntPtr) As IntPtr
    End Function

    <Description("frees a window handler."), _
        DllImport("user32.dll", _
        SetLastError:=True, CharSet:=CharSet.Auto, ExactSpelling:=True, _
        CallingConvention:=CallingConvention.StdCall)> _
    Private Shared Function ReleaseDC(ByVal hWnd As IntPtr, ByVal hDC As IntPtr) As Integer
    End Function

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_PAINT = &HF
        MyBase.WndProc(m)

        If m.Msg = WM_PAINT Then
            Dim hDC As IntPtr = GetWindowDC(Handle)
            Using gdc As Graphics = Graphics.FromHdc(hDC)
                Dim rect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
                Using pen As New Pen(Color.Red, 2)
                    gdc.DrawRectangle(pen, rect)
                    ReleaseDC(Handle, hDC)
                End Using
            End Using

        End If
    End Sub
End Class

Bob
0
 

Author Comment

by:brotherbill999
ID: 17981476
Thanks Bob, here's a solution that meets my needs.  The key is overriding WndProc as you indicated.
You certainly have helped me O Learned One.
Here's the working solution that works for me!

Imports System.Windows.Forms
Imports System.Drawing

Public Class MyTextBox
    Inherits TextBox

    ' Draw a thick blue border around the TextBox, using the Parent's Graphics
    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const WM_PAINT As Integer = &HF
        MyBase.WndProc(m)

        If m.Msg = WM_PAINT Then
            Const boldThickness As Integer = 2     ' 2 pixels
            If boldThickness <= 0 Then Exit Sub
            Dim grfx As Graphics = Parent.CreateGraphics
            Dim location As Point = Me.Location
            Dim size As Size = Me.Size
            Dim rect As New Rectangle(location.X, location.Y, size.Width, size.Height)
            rect.Inflate((boldThickness + 1) >> 1, (boldThickness + 1) >> 1)
            If (boldThickness Mod 2) = 1 Then
                rect.Height -= 1
                rect.Width -= 1
            End If
            Dim pen As New Pen(Color.Blue, boldThickness)
            grfx.DrawRectangle(pen, rect)
            grfx.Dispose()
        End If
    End Sub
End Class
0

Featured Post

Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
It’s quite interesting for me as I worked with Excel using vb.net for some time. Here are some topics which I know want to share with others whom this might help. First of all if you are working with Excel then you need to Download the Following …
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…

786 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question