transparent RadTextBox with round corners and customized scrollbars

8 posts, 0 answers
  1. mdanh
    mdanh avatar
    17 posts
    Member since:
    Jul 2012

    Posted 16 Aug 2010 Link to this post

    Hi

    Is it possible to have a RadTextBox that has rounded corners, transparent background and cusomized scrollbars. I have tried the Theme Builder but could not find any satisfactory way to do it.

    Look forward to any hints.
    Thanks
  2. Stefan
    Admin
    Stefan avatar
    2891 posts

    Posted 20 Aug 2010 Link to this post

    Hi mdanh,

    Thank you for contacting us.

    You can easily make the corners of RadTextBox rounded through applying a RectangleShape to the Shape property of RadTextBoxElement. Please refer to the attached screenshot. 

    However, I am afraid that you will not be able to make RadTextBox transparent or customize its scrollbars. The reason is that internally we are using a standard Microsoft textbox which is not flexible for any modifications of this kind. Please excuse us for the caused inconvenience.

    If there is anything else we can help you with, do not hesitate to contact us.

    Regards,
    Stefan
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. UI for WinForms is Visual Studio 2017 Ready
  4. mdanh
    mdanh avatar
    17 posts
    Member since:
    Jul 2012

    Posted 20 Aug 2010 Link to this post

    Thanks for the reply.

    I understand that the scrollbars could not be easily customized. However, are there any possibilities for the transparent background? I found on the internet the source code of AlphaBlendTextbox that works reasonably well for normal .NET textbox. I tried to apply it to RadTextBox and the result is a broken RadTextBox that has no transparency and unexpected behaviour. Refer to source code below. If the class inherits from TextBox, not RadTextBox, everything works resonably well.

    Do you perhaps know what I did wrongly, or are there any fundamental differences between .NET TextBox and RadTextBox that make it impossible to apply similar effects to RadTextBox?

    Thanks for any hints.

    Imports System
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.Drawing
    Imports System.Data
    Imports System.Windows.Forms
    Imports System.Drawing.Imaging
    Imports System.Runtime.InteropServices
    Imports Telerik.WinControls.UI
     
    ''' <summary>
    ''' AlphaBlendTextBox: A .Net textbox that can be translucent to the background.
    ''' </summary>
    ''' <remarks>
    ''' and was converted to VB.NET by Minh Danh
    '''</remarks>
    Public Class AlphaBlendTextBox
        Inherits RadTextBox
     
    #Region "Private variables"
     
        Private myPictureBox As uPictureBox
        Private myUpToDate As Boolean = False
        Private myCaretUpToDate As Boolean = False
        Private myBitmap As Bitmap
        Private myAlphaBitmap As Bitmap
     
        Private myFontHeight As Integer = 10
     
        Private myTimer1 As System.Windows.Forms.Timer
     
        Private myCaretState As Boolean = True
     
        Private myPaintedFirstTime As Boolean = False
     
        Private myBackColor As Color = Color.White
        Private myBackAlpha As Integer = 10
     
        ''' <summary>
        ''' Required designer variable.
        ''' </summary>
        Private components As System.ComponentModel.Container = Nothing
    #End Region
     
    #Region "Public methods and overrides"
        Public Sub New()
            ' This call is required by the Windows.Forms Form Designer.
            InitializeComponent()
            ' TODO: Add any initialization after the InitializeComponent call
     
            Me.BackColor = myBackColor
     
            Me.SetStyle(ControlStyles.UserPaint, False)
            Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            Me.SetStyle(ControlStyles.DoubleBuffer, True)
     
     
            myPictureBox = New uPictureBox()
            Me.Controls.Add(myPictureBox)
            myPictureBox.Dock = DockStyle.Fill
        End Sub
     
        Protected Overloads Overrides Sub OnResize(ByVal e As EventArgs)
     
            MyBase.OnResize(e)
            Me.myBitmap = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            '(this.Width,this.Height);
            Me.myAlphaBitmap = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            '(this.Width,this.Height);
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnKeyDown(ByVal e As KeyEventArgs)
            MyBase.OnKeyDown(e)
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnKeyUp(ByVal e As KeyEventArgs)
            MyBase.OnKeyUp(e)
            myUpToDate = False
            Me.Invalidate()
     
        End Sub
     
        Protected Overloads Overrides Sub OnKeyPress(ByVal e As KeyPressEventArgs)
            MyBase.OnKeyPress(e)
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnMouseUp(ByVal e As MouseEventArgs)
            MyBase.OnMouseUp(e)
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnGiveFeedback(ByVal gfbevent As GiveFeedbackEventArgs)
            MyBase.OnGiveFeedback(gfbevent)
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnMouseLeave(ByVal e As EventArgs)
            Try
                'found this code to find the current cursor location
                'at http://www.syncfusion.com/FAQ/WinForms/FAQ_c50c.asp#q597q
     
                Dim ptCursor As Point = Cursor.Position
     
                Dim f As Form = Me.FindForm()
                ptCursor = f.PointToClient(ptCursor)
                If Not Me.Bounds.Contains(ptCursor) Then
                    MyBase.OnMouseLeave(e)
                End If
            Catch ex As Exception
            End Try
        End Sub
     
        Protected Overloads Overrides Sub OnChangeUICues(ByVal e As UICuesEventArgs)
            MyBase.OnChangeUICues(e)
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnGotFocus(ByVal e As EventArgs)
            MyBase.OnGotFocus(e)
            myCaretUpToDate = False
            myUpToDate = False
            Me.Invalidate()
     
     
            myTimer1 = New System.Windows.Forms.Timer(Me.components)
     
            myTimer1.Interval = CInt(Win32.GetCaretBlinkTime())
     
            '  usually around 500;
            AddHandler myTimer1.Tick, AddressOf myTimer1_Tick
            myTimer1.Enabled = True
        End Sub
     
        Protected Overloads Overrides Sub OnLostFocus(ByVal e As EventArgs)
            MyBase.OnLostFocus(e)
            myCaretUpToDate = False
            myUpToDate = False
            Me.Invalidate()
     
            myTimer1.Dispose()
        End Sub
     
        Protected Overloads Overrides Sub OnFontChanged(ByVal e As EventArgs)
            If Me.myPaintedFirstTime Then
                Me.SetStyle(ControlStyles.UserPaint, False)
            End If
     
            MyBase.OnFontChanged(e)
     
            If Me.myPaintedFirstTime Then
                Me.SetStyle(ControlStyles.UserPaint, True)
            End If
     
     
            myFontHeight = GetFontHeight()
     
     
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub OnTextChanged(ByVal e As EventArgs)
            MyBase.OnTextChanged(e)
            myUpToDate = False
            Me.Invalidate()
        End Sub
     
        Protected Overloads Overrides Sub WndProc(ByRef m As Message)
     
            MyBase.WndProc(m)
     
            ' need to rewrite as a big switch
     
            If m.Msg = Win32.WM_PAINT Then
                myPaintedFirstTime = True
     
                If Not myUpToDate OrElse Not myCaretUpToDate Then
                    GetBitmaps()
                End If
                myUpToDate = True
                myCaretUpToDate = True
     
                If myPictureBox.Image IsNot Nothing Then
                    myPictureBox.Image.Dispose()
                End If
     
                myPictureBox.Image = DirectCast(myAlphaBitmap.Clone(), Image)
     
            ElseIf m.Msg = Win32.WM_HSCROLL OrElse m.Msg = Win32.WM_VSCROLL Then
                myUpToDate = False
                Me.Invalidate()
     
            ElseIf m.Msg = Win32.WM_LBUTTONDOWN OrElse m.Msg = Win32.WM_RBUTTONDOWN OrElse m.Msg = Win32.WM_LBUTTONDBLCLK Then
                '  || m.Msg == win32.WM_MOUSELEAVE  ///****
                myUpToDate = False
                Me.Invalidate()
     
            ElseIf m.Msg = Win32.WM_MOUSEMOVE Then
                If m.WParam.ToInt32() <> 0 Then
                    'shift key or other buttons
                    myUpToDate = False
                    Me.Invalidate()
                End If
            End If
     
     
     
            'System.Diagnostics.Debug.WriteLine("Pro: " + m.Msg.ToString("X"));
     
        End Sub
     
        ''' <summary>
        ''' Clean up any resources being used.
        ''' </summary>
        Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
            If disposing Then
                'this.BackColor = Color.Pink;
                If components IsNot Nothing Then
                    components.Dispose()
                End If
            End If
            MyBase.Dispose(disposing)
        End Sub
    #End Region
     
    #Region "Public property overrides"
         
        Public Shadows Property BackColor() As Color
            Get
                Return Color.FromArgb(MyBase.BackColor.R, MyBase.BackColor.G, MyBase.BackColor.B)
            End Get
            Set(ByVal value As Color)
                myBackColor = value
                MyBase.BackColor = value
                myUpToDate = False
            End Set
        End Property
     
    #End Region
     
    #Region "Private functions and classes"
     
        Private Function GetFontHeight() As Integer
            Dim g As Graphics = Me.CreateGraphics()
            Dim sf_font As SizeF = g.MeasureString("X", Me.Font)
            g.Dispose()
            Return CInt(sf_font.Height)
        End Function
     
        Private Sub GetBitmaps()
     
            If myBitmap Is Nothing OrElse myAlphaBitmap Is Nothing OrElse myBitmap.Width <> Width OrElse myBitmap.Height <> Height OrElse myAlphaBitmap.Width <> Width OrElse
     
    myAlphaBitmap.Height <> Height Then
                myBitmap = Nothing
                myAlphaBitmap = Nothing
            End If
     
            If myBitmap Is Nothing Then
                myBitmap = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
                '(Width,Height);
                myUpToDate = False
            End If
     
     
            If Not myUpToDate Then
                'Capture the TextBox control window
     
                Me.SetStyle(ControlStyles.UserPaint, False)
     
                Win32.CaptureWindow(Me, myBitmap)
     
                Me.SetStyle(ControlStyles.UserPaint, True)
                Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
     
                Me.BackColor = Color.FromArgb(myBackAlpha, myBackColor)
            End If
            '--
     
     
     
            Dim r2 As New Rectangle(0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            Dim tempImageAttr As New ImageAttributes()
     
            'Found the color map code in the MS Help
            'tempColorMap is an array having only 1 element, index starting from 0
            'original C# code: ColorMap[] tempColorMap = new ColorMap[1];
            Dim tempColorMap As ColorMap() = New ColorMap(0) {}
            tempColorMap(0) = New ColorMap()
            tempColorMap(0).OldColor = Color.FromArgb(255, myBackColor)
            tempColorMap(0).NewColor = Color.FromArgb(myBackAlpha, myBackColor)
     
            tempImageAttr.SetRemapTable(tempColorMap)
     
            If myAlphaBitmap IsNot Nothing Then
                myAlphaBitmap.Dispose()
            End If
     
     
            myAlphaBitmap = New Bitmap(Me.ClientRectangle.Width, Me.ClientRectangle.Height)
            '(Width,Height);
            Dim tempGraphics1 As Graphics = Graphics.FromImage(myAlphaBitmap)
     
            tempGraphics1.DrawImage(myBitmap, r2, 0, 0, Me.ClientRectangle.Width, Me.ClientRectangle.Height, _
             GraphicsUnit.Pixel, tempImageAttr)
     
            tempGraphics1.Dispose()
     
            '----
     
            If Me.Focused AndAlso (Me.SelectionLength = 0) Then
                Dim tempGraphics2 As Graphics = Graphics.FromImage(myAlphaBitmap)
                If myCaretState Then
                    'Draw the caret
                    Dim caret As Point = Me.findCaret()
                    Dim p As New Pen(Me.ForeColor, 3)
                    tempGraphics2.DrawLine(p, caret.X, caret.Y + 0, caret.X, caret.Y + myFontHeight)
                    tempGraphics2.Dispose()
     
                End If
            End If
     
     
     
        End Sub
     
        Private Function findCaret() As Point
            '  Find the caret translated from code at
            '            * http://www.vb-helper.com/howto_track_textbox_caret.html
            '            *
            '            * and
            '            *
            '            * http://www.microbion.co.uk/developers/csharp/textpos2.htm
            '            *
            '            * Changed to EM_POSFROMCHAR
            '            *
            '            * This code still needs to be cleaned up and debugged
            '            *
     
     
            Dim pointCaret As New Point(0)
            Dim i_char_loc As Integer = Me.SelectionStart
            Dim pi_char_loc As New IntPtr(i_char_loc)
     
            Dim i_point As Integer = Win32.SendMessage(Me.Handle, Win32.EM_POSFROMCHAR, pi_char_loc, IntPtr.Zero)
            pointCaret = New Point(i_point)
     
            If i_char_loc = 0 Then
                pointCaret = New Point(0)
            ElseIf i_char_loc >= Me.Text.Length Then
                pi_char_loc = New IntPtr(i_char_loc - 1)
                i_point = Win32.SendMessage(Me.Handle, Win32.EM_POSFROMCHAR, pi_char_loc, IntPtr.Zero)
                pointCaret = New Point(i_point)
     
                Dim g As Graphics = Me.CreateGraphics()
                Dim t1 As [String] = Me.Text.Substring(Me.Text.Length - 1, 1) + "X"
                Dim sizet1 As SizeF = g.MeasureString(t1, Me.Font)
                Dim sizex As SizeF = g.MeasureString("X", Me.Font)
                g.Dispose()
                Dim xoffset As Integer = CInt(sizet1.Width - sizex.Width)
                pointCaret.X = pointCaret.X + xoffset
     
                If i_char_loc = Me.Text.Length Then
                    Dim slast As [String] = Me.Text.Substring(Text.Length - 1, 1)
                    If slast = vbLf Then
                        pointCaret.X = 1
                        pointCaret.Y = pointCaret.Y + myFontHeight
                    End If
     
                End If
            End If
     
     
     
            Return pointCaret
        End Function
     
        Private Sub myTimer1_Tick(ByVal sender As Object, ByVal e As EventArgs)
            'Timer used to turn caret on and off for focused control
     
            myCaretState = Not myCaretState
            myCaretUpToDate = False
            Me.Invalidate()
        End Sub
     
        Private Class uPictureBox
            Inherits PictureBox
            Public Sub New()
                Me.SetStyle(ControlStyles.Selectable, False)
                Me.SetStyle(ControlStyles.UserPaint, True)
                Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
                Me.SetStyle(ControlStyles.DoubleBuffer, True)
     
                Me.Cursor = Nothing
                Me.Enabled = True
     
                Me.SizeMode = PictureBoxSizeMode.Normal
            End Sub
     
            'uPictureBox
            Protected Overloads Overrides Sub WndProc(ByRef m As Message)
                If m.Msg = Win32.WM_LBUTTONDOWN OrElse m.Msg = Win32.WM_RBUTTONDOWN OrElse m.Msg = Win32.WM_LBUTTONDBLCLK OrElse m.Msg =
     
    Win32.WM_MOUSELEAVE OrElse m.Msg = Win32.WM_MOUSEMOVE Then
                    'Send the above messages back to the parent control
                    Win32.PostMessage(Me.Parent.Handle, CUInt(m.Msg), m.WParam, m.LParam)
     
                ElseIf m.Msg = Win32.WM_LBUTTONUP Then
                    '??  for selects and such
                    Me.Parent.Invalidate()
                End If
     
     
                MyBase.WndProc(m)
            End Sub
        End Class
    #End Region
     
    #Region "Component Designer generated code"
        ''' <summary>
        ''' Required method for Designer support - do not modify
        ''' the contents of this method with the code editor.
        ''' </summary>
        Private Sub InitializeComponent()
            components = New System.ComponentModel.Container()
        End Sub
    #End Region
     
    #Region "New Public Properties"
        <Category("Appearance"), Description("The alpha value used to blend the control's background. Valid values are 0 through 255."), Browsable(True), DesignerSerializationVisibility
     
    (DesignerSerializationVisibility.Visible)> _
        Public Property BackAlpha() As Integer
            Get
                Return myBackAlpha
            End Get
            Set(ByVal value As Integer)
                Dim v As Integer = value
                If v > 255 Then
                    v = 255
                End If
                myBackAlpha = v
                myUpToDate = False
                Invalidate()
            End Set
        End Property
    #End Region
    End Class
  5. Boryana
    Admin
    Boryana avatar
    330 posts

    Posted 25 Aug 2010 Link to this post

    Hi mdanh,

    Thank you for writing back.

    Our team tested the original AlphaBlendTextBox project and we found that the following three slight modifications are needed for the code to work with RadTextBox:
    • The AlphaBlendTextBox should inherit HostedTextBoxBase, instead of RadTextBox.
    • The internal TextBox in our RadTextBox should be substituted with the custom AlphaBlendTextBox. Here is a sample snippet:

    Me.radTextBox1.TextBoxElement.Children.RemoveAt(0)
    Dim item As New RadTextBoxItem(New AlphaBlendTextBox())
    Me.radTextBox1.TextBoxElement.Children.Insert(0, item)
    • The BackColor properties of the RadTextBox and the its FillPrimitive should be set to Transparent.
    Me.radTextBox1.BackColor = Color.Transparent;
    Me.radTextBox1.TextBoxElement.Fill.BackColor = Color.Transparent;

    I hope you will find this helpful. Let me know if you have further questions. I will be glad to assist you.

    Kind regards,
    Boryana
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  6. mdanh
    mdanh avatar
    17 posts
    Member since:
    Jul 2012

    Posted 29 Aug 2010 Link to this post

    Thanks so much for the suggestions and code snippet. I have been able to make AlphaBlendTextbox work with RadTextBox.
  7. Nikolay
    Admin
    Nikolay avatar
    1803 posts

    Posted 01 Sep 2010 Link to this post

    Hi mdanh,

    We are glad to hear that our solution was helpful. If you have additional questions, feel free to contact us.

    Sincerely yours,
    Nikolay
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  8. mdanh
    mdanh avatar
    17 posts
    Member since:
    Jul 2012

    Posted 07 Sep 2010 Link to this post

    Hi

    I found a problem.

    When using the code snippet you gave, the property Nulltext of the original RadTextBox does not work - nothing is shown. I have tried to change NullText and NullTextColor to no avail. Also is there a way to change the forecolor and backcolor of the selected text (it seems distorted)? It was not found in "Edit UI Elements" and trying to use theme builder on this modified RadTextBox results in a distorted RadTextBox. If the color cannot be change, how can I simply disable text selection (via mouse and keyboard)?
  9. Nikolay
    Admin
    Nikolay avatar
    1803 posts

    Posted 13 Sep 2010 Link to this post

    Hello mdanh,

    Thank you for getting back to us.

    The text selection is a feature of the Microsoft TextBox and we do not have control over it. As to the NullText and NullTextColor, the process of replacing the internal RadTextBoxItem with a custom one breaks the internal property synchronization. Therefore, you need to set these properties directly to the AlphaBlendTextBox instance:
    Me.radTextBox1.TextBoxElement.Children.RemoveAt(0)
    Dim abtb As New AlphaBlendTextBox()
    Dim item As New RadTextBoxItem(abtb)
    Me.radTextBox1.TextBoxElement.Children.Insert(0, item)
      
    Me.radTextBox1.BackColor = Color.Transparent
    Me.radTextBox1.TextBoxElement.Fill.BackColor = Color.Transparent
      
    abtb.NullText = "NullText"
    abtb.NullTextColor = Color.Green

    All the best,
    Nikolay
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top
UI for WinForms is Visual Studio 2017 Ready