Public Class MsgBoxEx
    Public Sub New(ByVal message As String, ByVal title As String)
        Me.New(message, title, MessageBoxIcon.None)
    End Sub

    Public Sub New(ByVal message As String, ByVal title As String, ByVal icon As MessageBoxIcon)
        Me.New(message, title, getMessageBoxIcon(icon))
    End Sub

    Public Sub New(ByVal message As String, ByVal title As String, ByVal icon As Icon)
        InitializeComponent()
        Me.messageLbl.Text = message
        Me.Text = title
        Me.m_sysIcon = icon
        If Me.m_sysIcon Is Nothing Then Me.messageLbl.Location = New System.Drawing.Point(FORM_X_MARGIN, FORM_Y_MARGIN)
    End Sub

    Private Shared Function getMessageBoxIcon(ByVal icon As MessageBoxIcon) As Icon
        Dim oIcon As Icon = Nothing

        Select Case icon
            Case MessageBoxIcon.Asterisk
                oIcon = SystemIcons.Asterisk
            Case MessageBoxIcon.[Error]
                oIcon = SystemIcons.[Error]
            Case MessageBoxIcon.Exclamation
                oIcon = SystemIcons.Exclamation
            Case MessageBoxIcon.Question
                oIcon = SystemIcons.Question
        End Select

        If oIcon IsNot Nothing Then
            Return DevExpress.Utils.Drawing.Helpers.StockIconHelper.GetWindows8AssociatedIcon(oIcon)
        Else
            Return Nothing
        End If
    End Function

    Private m_minWidth As Integer
    Private m_minHeight As Integer

    Public Sub SetMinSize(ByVal width As Integer, ByVal height As Integer)
        m_minWidth = width
        m_minHeight = height
    End Sub

    Public Sub SetButtons(ParamArray names As String())
        Dim drs As DialogResult() = New DialogResult(names.Length - 1) {}

        For i As Integer = 0 To names.Length - 1
            drs(i) = DialogResult.None
        Next

        Me.SetButtons(names, drs)
    End Sub

    Public Sub SetButtons(ByVal names As String(), ByVal results As DialogResult())
        Me.SetButtons(names, results, 1)
    End Sub

    Public Sub SetButtons(ByVal names As String(), ByVal results As DialogResult(), ByVal def As Integer)
        If names Is Nothing Then Throw New ArgumentNullException("btnText", "Button Text is null")
        Dim count As Integer = names.Length
        If count < 1 OrElse count > 3 Then Throw New ArgumentException("Invalid number of buttons. Must be between 1 and 3.")
        m_minButtonRowWidth += setButtonParams(btn1, names(0), If(def = 1, 1, 2), results(0))

        If count > 1 Then
            m_minButtonRowWidth += setButtonParams(btn2, names(1), If(def = 2, 1, 3), results(1)) + BUTTON_SPACE
        End If

        If count > 2 Then
            m_minButtonRowWidth += setButtonParams(btn3, names(2), If(def = 3, 1, 4), results(2)) + BUTTON_SPACE
        End If
    End Sub

    Private m_minButtonRowWidth As Integer

    Private Shared Function setButtonParams(ByVal btn As Button, ByVal text As String, ByVal tab As Integer, ByVal dr As DialogResult) As Integer
        btn.Text = text
        btn.Visible = True
        btn.DialogResult = dr
        btn.TabIndex = tab
        Return btn.Size.Width
    End Function

    Public Sub SetCheckbox(ByVal text As String)
        Me.SetCheckbox(text, False)
    End Sub

    Public Sub SetCheckbox(ByVal text As String, ByVal chcked As Boolean)
        Me.chkBx.Visible = True
        Me.chkBx.Text = text
        Me.chkBx.Checked = chcked
        Me.m_minButtonRowWidth += Me.chkBx.Size.Width + CHECKBOX_SPACE
    End Sub

    Private Sub DialogBox_Load(ByVal sender As Object, ByVal e As EventArgs)
        If Not btn1.Visible Then Me.SetButtons(New String() {"OK"}, New DialogResult() {DialogResult.OK})
        m_minButtonRowWidth += 2 * FORM_X_MARGIN
        Me.setDialogSize()
        Me.setButtonRowLocations()
    End Sub

    Const FORM_Y_MARGIN As Integer = 10
    Const FORM_X_MARGIN As Integer = 16
    Const BUTTON_SPACE As Integer = 5
    Const CHECKBOX_SPACE As Integer = 15
    Const TEXT_Y_MARGIN As Integer = 30

    Private Sub setDialogSize()
        Dim requiredWidth As Integer = Me.messageLbl.Location.X + Me.messageLbl.Size.Width + FORM_X_MARGIN
        requiredWidth = If(requiredWidth > m_minButtonRowWidth, requiredWidth, m_minButtonRowWidth)
        Dim requiredHeight As Integer = Me.messageLbl.Location.Y + Me.messageLbl.Size.Height - Me.btn2.Location.Y + Me.ClientSize.Height + TEXT_Y_MARGIN
        Dim minSetWidth As Integer = If(Me.ClientSize.Width > Me.m_minWidth, Me.ClientSize.Width, Me.m_minWidth)
        Dim minSetHeight As Integer = If(Me.ClientSize.Height > Me.m_minHeight, Me.ClientSize.Height, Me.m_minHeight)
        Dim s As Size = New Size()
        s.Width = If(requiredWidth > minSetWidth, requiredWidth, minSetWidth)
        s.Height = If(requiredHeight > minSetHeight, requiredHeight, minSetHeight)
        Me.ClientSize = s
    End Sub

    Private Sub setButtonRowLocations()
        Dim formWidth As Integer = Me.ClientRectangle.Width
        Dim x As Integer = formWidth - FORM_X_MARGIN
        Dim y As Integer = btn1.Location.Y

        If btn3.Visible Then
            x -= btn3.Size.Width
            btn3.Location = New Point(x, y)
            x -= BUTTON_SPACE
        End If

        If btn2.Visible Then
            x -= btn2.Size.Width
            btn2.Location = New Point(x, y)
            x -= BUTTON_SPACE
        End If

        x -= btn1.Size.Width
        btn1.Location = New Point(x, y)
        If Me.chkBx.Visible Then Me.chkBx.Location = New Point(FORM_X_MARGIN, Me.chkBx.Location.Y)
    End Sub

    Private m_sysIcon As Icon

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        If m_sysIcon IsNot Nothing Then
            Dim g As Graphics = e.Graphics
            g.DrawIconUnstretched(m_sysIcon, New Rectangle(FORM_X_MARGIN, FORM_Y_MARGIN, m_sysIcon.Width, m_sysIcon.Height))
        End If

        MyBase.OnPaint(e)
    End Sub

    Public ReadOnly Property CheckboxChecked As Boolean
        Get
            Return Me.chkBx.Checked
        End Get
    End Property

    Private m_result As DialogBoxResult

    Public ReadOnly Property Result As DialogBoxResult
        Get
            Return m_result
        End Get
    End Property

    Private Sub btn_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btn1.Click, btn2.Click, btn3.Click
        If sender.Equals(btn1) Then
            m_result = DialogBoxResult.Button1
        ElseIf sender.Equals(btn2) Then
            m_result = DialogBoxResult.Button2
        ElseIf sender.Equals(btn3) Then
            m_result = DialogBoxResult.Button3
        End If

        If (CType(sender, Button)).DialogResult = DialogResult.None Then
            Close()
        End If
    End Sub

    Enum DialogBoxResult
        Button1
        Button2
        Button3
    End Enum
End Class
