Click here to Skip to main content
Click here to Skip to main content

Glass Message Box in .NET

By , 11 Jul 2012
 

Introduction

In my software development career I have seen many types of message boxes. In VB 6.0:  MsgBox(“ ……”). In .NET: MessageBox.Show(“……”). But all message boxes are dull looking. This article demonstrates a smooth, glass effect message box for Windows based development.

Using the Code

The following is the main part of this control. The MakeMessage function generates a message box according to the string size.

Private Shared Function MakeMessage(ByVal WinText As String, _
                                    ByVal WinHeader As String, _
                                    ByVal WinIcon As MessageBoxIcon, _
                                    ByVal WinButtons As MessageBoxButtons, _
                                    ByVal WinDefault As MessageBoxDefaultButton) As DialogResult


    ObjWinMessage = Nothing
    ObjWinMessage = New Glass()

    MessageText = "" : MessageText = WinText
    HeaderText = "" : HeaderText = WinHeader

    FormWidth = 0 : FormHeight = 0
    HeaderWidth = 0
    MsgWidth = 0 : MsgHeight = 0
    WinReturn = 0

    REM Check Message And Header Text Length When Equal To Zero
    If MessageText.Trim().Length = 0 And HeaderText.Trim().Length = 0 Then

        FormSize = New Size(305, 135)
        FormWidth = 305 : FormHeight = 135
        WinMsg.Size = New Size(FormSize.Width, FormSize.Height)

        GoTo Mess

    End If

    HeaderWidth = StringSize(HeaderText.Trim(), MaxWidth, WinFnt).Width
    MessageSize = StringSize(MessageText.Trim(), MaxWidth, WinFnt)
    MsgWidth = MessageSize.Width : MsgHeight = MessageSize.Height

    If HeaderText.Trim().Length > 0 And MessageText.Trim().Length = 0 Then

        HeaderWidth = HeaderWidth + 80
        WinReturn = Math.Max(HeaderWidth, 305)
        FormSize = New Size(WinReturn, 135)
        FormWidth = FormSize.Width : FormHeight = FormSize.Height

        GoTo Mess

    End If

    HeaderWidth = HeaderWidth + 80
    FormWidth = MsgWidth + 60
    FormHeight = MsgHeight + 120

    If HeaderText.Trim().Length = 0 And MessageText.Trim().Length > 0 Then

        FormWidth = Math.Max(FormWidth, 305)
        FormHeight = Math.Max(FormHeight, 135)
        FormSize = New Size(FormWidth, FormHeight)
        FormWidth = FormSize.Width : FormHeight = FormSize.Height

        GoTo Mess

    End If

    If HeaderText.Trim().Length > 0 And MessageText.Trim().Length > 0 Then

        WinReturn = Math.Max(HeaderWidth, FormWidth)
        FormWidth = Math.Max(WinReturn, 305)
        FormHeight = Math.Max(FormHeight, 135)
        FormSize = New Size(FormWidth, FormHeight)
        FormWidth = FormSize.Width : FormHeight = FormSize.Height

        GoTo Mess

    End If

Mess:
    Call CreateBaseScreen()

    Call CreateHeader()
    Call CreateMessageIcon()
    Call CreateMeaasge()

    Call AddToBaseScreen()

    WinMessage.Text = WinText
    LblHeader.Text = WinHeader

    Select Case WinIcon

        Case MessageBoxIcon.Asterisk
            PicIcon.Image = Drawing.SystemIcons.Asterisk.ToBitmap()
        Case MessageBoxIcon.Error
            PicIcon.Image = Drawing.SystemIcons.Error.ToBitmap()
        Case MessageBoxIcon.Exclamation
            PicIcon.Image = Drawing.SystemIcons.Exclamation.ToBitmap()
        Case MessageBoxIcon.Hand
            PicIcon.Image = Drawing.SystemIcons.Hand.ToBitmap()
        Case MessageBoxIcon.Information
            PicIcon.Image = Drawing.SystemIcons.Information.ToBitmap()
        Case MessageBoxIcon.None
            PicIcon.Image = Nothing
        Case MessageBoxIcon.Question
            PicIcon.Image = Drawing.SystemIcons.Question.ToBitmap()
        Case MessageBoxIcon.Stop
            PicIcon.Image = Drawing.SystemIcons.Error.ToBitmap()
        Case MessageBoxIcon.Warning
            PicIcon.Image = Drawing.SystemIcons.Warning.ToBitmap()

    End Select

    Call CreateMessageButtons(WinButtons)

    Select Case WinButtons

        Case MessageBoxButtons.AbortRetryIgnore

            Select Case WinDefault
                Case MessageBoxDefaultButton.Button1
                    CmdAbort.Select()
                    CmdAbort.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button2
                    CmdRetry.Select()
                    CmdRetry.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button3
                    CmdIgnore.Select()
                    CmdIgnore.Focus() : Exit Select

            End Select

        Case MessageBoxButtons.OK

            Select Case WinDefault
                Case MessageBoxDefaultButton.Button1
                    CmdOk.Select()
                    CmdOk.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button2
                    CmdOk.Select()
                    CmdOk.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button3
                    CmdOk.Select()
                    CmdOk.Focus() : Exit Select

            End Select

        Case MessageBoxButtons.OKCancel

            Select Case WinDefault
                Case MessageBoxDefaultButton.Button1
                    CmdOk.Select()
                    CmdOk.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button2
                    CmdCancel.Select()
                    CmdCancel.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button3
                    CmdCancel.Select()
                    CmdCancel.Focus() : Exit Select

            End Select

        Case MessageBoxButtons.RetryCancel

            Select Case WinDefault
                Case MessageBoxDefaultButton.Button1
                    CmdRetry.Select()
                    CmdRetry.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button2
                    CmdCancel.Select()
                    CmdCancel.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button3
                    CmdCancel.Select()
                    CmdCancel.Focus() : Exit Select

            End Select

        Case MessageBoxButtons.YesNo

            Select Case WinDefault
                Case MessageBoxDefaultButton.Button1
                    CmdYes.Select()
                    CmdYes.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button2
                    CmdNo.Select()
                    CmdNo.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button3
                    CmdNo.Select()
                    CmdNo.Focus() : Exit Select

            End Select

        Case MessageBoxButtons.YesNoCancel

            Select Case WinDefault
                Case MessageBoxDefaultButton.Button1
                    CmdYes.Select()
                    CmdYes.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button2
                    CmdNo.Select()
                    CmdNo.Focus() : Exit Select
                Case MessageBoxDefaultButton.Button3
                    CmdCancel.Select()
                    CmdCancel.Focus() : Exit Select

            End Select

    End Select

    WinMsg.Refresh()
    WinMsg.ShowDialog()

    Return WinMake

End Function

Measure String

This function helps to size of the message box according to the font size:

Private Shared Function StringSize(ByVal WinMsgText As String, _
                                       ByVal WinWdth As Integer, _
                                       ByVal WinFnt As Font) As Size

    Dim GRA As Graphics = WinMsg.CreateGraphics()
    Dim SZF As SizeF = GRA.MeasureString(WinMsgText, WinFnt, WinWdth)

    GRA.Dispose()

    Dim SZ As New Size(DirectCast(Convert.ToInt16(SZF.Width + 100), Int16), _
                       DirectCast(Convert.ToInt16(SZF.Height), Int16))

    Return SZ

End Function

The painting part of the message box

Private Shared Sub WinMsg_Paint(ByVal sender As Object, _
              ByVal e As System.Windows.Forms.PaintEventArgs) Handles WinMsg.Paint

    Dim MGraphics As Graphics = e.Graphics
    Dim MPen As New Pen(Color.FromArgb(96, 155, 173), 1)

    Dim Area As New Rectangle(0, 0, WinMsg.Width - 1, WinMsg.Height - 1)
    Dim LGradient As New LinearGradientBrush(Area, Color.FromArgb(166, 197, 227), _
                                             Color.FromArgb(245, 251, 251), _
                                             LinearGradientMode.BackwardDiagonal)

    With MGraphics

        .CompositingMode = CompositingMode.SourceOver
        .CompositingQuality = CompositingQuality.HighQuality
        .InterpolationMode = InterpolationMode.HighQualityBicubic
        .PixelOffsetMode = PixelOffsetMode.HighSpeed

        .FillRectangle(LGradient, Area)
        .DrawRectangle(MPen, Area)

    End With

    LGradient.Dispose()
    MPen.Dispose()

End Sub

Private Shared Sub LblHeader_Paint(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.PaintEventArgs) Handles LblHeader.Paint

    Dim MGraphics As Graphics = e.Graphics
    Dim MPen As New Pen(Color.FromArgb(96, 155, 173), 1)

    Dim Area As New Rectangle(0, 0, LblHeader.Width - 1, LblHeader.Height - 1)
    Dim LGradient As New LinearGradientBrush(Area, Color.FromArgb(166, 197, 227), _
                                             Color.FromArgb(245, 251, 251), LinearGradientMode.BackwardDiagonal)

    With MGraphics

        .CompositingMode = CompositingMode.SourceOver
        .CompositingQuality = CompositingQuality.HighQuality
        .InterpolationMode = InterpolationMode.HighQualityBicubic
        .PixelOffsetMode = PixelOffsetMode.HighSpeed

        .FillRectangle(LGradient, Area)
        .DrawRectangle(MPen, Area)

    End With

    Dim DrawBrush As New SolidBrush(Color.Black)
    Dim DrawPoint As New PointF(2.0F, 4.0F)

    With e.Graphics

        .CompositingMode = CompositingMode.SourceOver
        .CompositingQuality = CompositingQuality.HighQuality
        .TextRenderingHint = Drawing.Text.TextRenderingHint.AntiAliasGridFit
        .DrawString(HeaderText.ToString(), WinFnt, DrawBrush, DrawPoint)

    End With

    LGradient.Dispose()
    MPen.Dispose()

End Sub

License

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

About the Author

Gehan Fernando
Software Developer (Senior) AKLO Information Technologies (PVT) Ltd
Sri Lanka Sri Lanka
Member
Gehan Fernando Currently attached to AKLO Information Technologies (Pvt) Ltd as Snr. Software Engineer having a Comprehensive Knowledge in VB 6.0, VB.NET, C#.NET, SQL Server and Oracle. (Completed MCP, MCPD in .NET), I started my IT Career in 2000 and at the very beginning I was attached To Develop a Distributed Transaction Application and Database Applications. My interests lies in the areas of developing GDI+ Applications, Server Client Applications, Hardware Supporting Applications, Robotic Applications, and Database Applications, SOA applications, Windows Mobile and Microsoft Game Applications.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
BugIt minimizes my MDI Form [modified]membermatt Ricci6 Dec '12 - 9:09 
Whenever the user clicks one of the buttons (Yes, No, Ok, etc...) the messagebox dissappears, but then my form is minimized to the task bar UNLESS no other applications are open. If I am running MS Word, and my program with the message box, every click of the button minimizes my app to the taskbar and bring MSWord (for example) to the front. I have tried some code in the ShowWinMessage sub after 'Return Result":
 
       Dim pro() As Process = Process.GetProcessesByName("xxxxxxx")
       Dim instance As Process
       For Each instance In pro
           ' How to bring it to front.
           Dim WinPtr As IntPtr = instance.MainWindowHandle
 
           ' Verify there is a mainWindow
           If WinPtr = IntPtr.Zero Then
               Return
           Else
               'bring it to front.
               SetForegroundWindow(WinPtr)
 
           End If
       Next
 

<DllImport("USER32.DLL")> _
    Public Shared Function SetForegroundWindow(hWnd As IntPtr) As Boolean
    End Function
 

Please help!

modified 10 Dec '12 - 9:58.

GeneralRe: It minimizes my MDI Formmembermatt Ricci10 Dec '12 - 6:05 
I found out the answer. After the return WinResult line in ShowWinMessage Sub, I used the ShowWindowsAsync function as shown here.
 
http://www.bobpowell.net/singleinstance.htm[^]
QuestionMakeMessage - codingmemberDanielLey26 Jul '12 - 8:11 
Hi,
in your method: MakeMessage you are using a lot of IF clauses to check four different states - i.e.: If HeaderText.Trim().Length > 0 And MessageText.Trim().Length > 0 Then. This makes the code reading very difficult; therefore I would prefer to put it in one statement delimited by elseif. The further advantage is that you can save the exit points 'GoTo' as well; this looks like old VB or VBA coding.
QuestionMy vote of 4memberbobfox16 Jul '12 - 4:34 
Nice, just one tip: rendering quality of Header is poor.
To fix it, in LblHeader_Paint() method change TextRenderingHint to Drawing.Text.TextRenderingHint.ClearTypeGridFit.
I additionally use a bold Header font.
GeneralMy vote of 4memberMehran Taheri12 Jul '12 - 4:27 
Great!

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 11 Jul 2012
Article Copyright 2012 by Gehan Fernando
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid