?
Solved

Overriding Textbox with SetStyle breaks it

Posted on 2006-11-19
2
Medium Priority
?
785 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 2000 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

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Integration Management Part 2
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …
Suggested Courses

850 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