Option Explicit On
Option Strict On

Imports System
Imports System.Windows.Forms
Imports System.ComponentModel
Imports System.Drawing

Friend Class frmInputMessageBox : Inherits System.Windows.Forms.Form
    Private _InputResults As InputDialogResults.InputMsgResults

    Public ReadOnly Property InputResults() As InputDialogResults.InputMsgResults
        Get
            Return _InputResults
        End Get
    End Property

    Public Sub New(ByVal Prompt As String, Optional ByVal Title As String = "", Optional ByVal DefaultResponse As String = "", Optional ByVal XPos As Integer = -1, Optional ByVal YPos As Integer = -1)
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        _InputResults = New InputDialogResults.InputMsgResults

        Me.Text = Title
        'Determine if prompt label size needs changed.
        ComputeLabelHeight(Prompt)

        Me.lblPrompt.Text = Prompt
        Me.txtResponse.Text = DefaultResponse

        If XPos > -1 Or YPos > -1 Then
            Me.Location = New Drawing.Point(XPos, YPos)
        End If
    End Sub

#Region " Windows Form Designer generated code "
    'Form overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    Friend WithEvents btnOK As System.Windows.Forms.Button
    Friend WithEvents btnCancel As System.Windows.Forms.Button
    Friend WithEvents lblPrompt As System.Windows.Forms.Label
    Friend WithEvents txtResponse As System.Windows.Forms.TextBox
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        Me.btnOK = New System.Windows.Forms.Button
        Me.btnCancel = New System.Windows.Forms.Button
        Me.lblPrompt = New System.Windows.Forms.Label
        Me.txtResponse = New System.Windows.Forms.TextBox
        Me.SuspendLayout()
        '
        'btnOK
        '
        Me.btnOK.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK
        Me.btnOK.Location = New System.Drawing.Point(289, 11)
        Me.btnOK.Name = "btnOK"
        Me.btnOK.Size = New System.Drawing.Size(62, 22)
        Me.btnOK.TabIndex = 1
        Me.btnOK.Text = "OK"
        '
        'btnCancel
        '
        Me.btnCancel.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        Me.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.btnCancel.Location = New System.Drawing.Point(289, 38)
        Me.btnCancel.Name = "btnCancel"
        Me.btnCancel.Size = New System.Drawing.Size(62, 22)
        Me.btnCancel.TabIndex = 2
        Me.btnCancel.Text = "Cancel"
        '
        'lblPrompt
        '
        Me.lblPrompt.Location = New System.Drawing.Point(8, 8)
        Me.lblPrompt.Name = "lblPrompt"
        Me.lblPrompt.Size = New System.Drawing.Size(272, 75)
        Me.lblPrompt.TabIndex = 3
        Me.lblPrompt.Text = "Prompt"
        '
        'txtResponse
        '
        Me.txtResponse.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
        Me.txtResponse.Location = New System.Drawing.Point(8, 102)
        Me.txtResponse.Name = "txtResponse"
        Me.txtResponse.Size = New System.Drawing.Size(336, 20)
        Me.txtResponse.TabIndex = 0
        Me.txtResponse.Text = "Value"
        '
        'frmInputMessageBox
        '
        Me.AcceptButton = Me.btnOK
        Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
        Me.CancelButton = Me.btnCancel
        Me.ClientSize = New System.Drawing.Size(354, 132)
        Me.Controls.Add(Me.txtResponse)
        Me.Controls.Add(Me.lblPrompt)
        Me.Controls.Add(Me.btnCancel)
        Me.Controls.Add(Me.btnOK)
        Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
        Me.MaximizeBox = False
        Me.MinimizeBox = False
        Me.MinimumSize = New System.Drawing.Size(0, 130)
        Me.Name = "frmInputMessageBox"
        Me.ShowInTaskbar = False
        Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide
        Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen
        Me.Text = "Title"
        Me.ResumeLayout(False)
        Me.PerformLayout()

    End Sub

#End Region

    Private Sub ComputeLabelHeight(ByVal sz As String)
        Dim fnt As New Font(Me.lblPrompt.Font.Name, Me.lblPrompt.Font.Size)
        ' Compute the string dimensions in the given font
        Dim bmp As Bitmap = New Bitmap(1, 1, Drawing.Imaging.PixelFormat.Format32bppArgb)
        Dim gph As Graphics = Graphics.FromImage(bmp)

        Dim lineHeight As Integer = CInt(Me.lblPrompt.Font.Height * 1.25)
        Dim stringSize As SizeF = gph.MeasureString(sz, fnt)
        Dim lines As Integer = CInt((Math.Floor(stringSize.Width) + ((Split(sz, vbNewLine).Length) * Me.lblPrompt.Width)) / Me.lblPrompt.Width)

        Me.lblPrompt.Height = (lines * lineHeight)
        Me.Height = Me.lblPrompt.Top + (lines * lineHeight) + 72

        gph.Dispose()
        bmp.Dispose()
    End Sub

    Private Sub btnOK_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnOK.Click
        Me._InputResults.Response = Me.txtResponse.Text
        Me._InputResults.DialogResult = InputDialogResults.InputMsgResults.InputDialogResult.OK
    End Sub

    Private Sub frmInputMessageBox_Disposed(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Disposed
        Me._InputResults = Nothing
    End Sub

    Private Sub btnCancel_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnCancel.Click
        Me._InputResults.Response = String.Empty
        Me._InputResults.DialogResult = InputDialogResults.InputMsgResults.InputDialogResult.Cancel
    End Sub
End Class

Public Class InputDialogResults
    Public Structure InputMsgResults
        Enum InputDialogResult
            [OK]
            [Cancel]
        End Enum

        Dim Response As String
        Dim DialogResult As InputDialogResult
    End Structure
End Class

Public Class InputMessageBox
    Private Shared frmInputBox As frmInputMessageBox

#Region " Overloaded InputMessageBox Show Method "
    Public Overloads Shared Function Show(ByVal Prompt As String) As InputDialogResults.InputMsgResults
        frmInputBox = New frmInputMessageBox(Prompt)
        frmInputBox.ShowDialog()

        Dim Results As InputDialogResults.InputMsgResults = frmInputBox.InputResults
        frmInputBox.Close()
        frmInputBox.Dispose()

        Return Results
    End Function

    Public Overloads Shared Function Show(ByVal Prompt As String, ByVal Title As String) As InputDialogResults.InputMsgResults
        frmInputBox = New frmInputMessageBox(Prompt, Title)
        frmInputBox.ShowDialog()

        Dim Results As InputDialogResults.InputMsgResults = frmInputBox.InputResults
        frmInputBox.Close()
        frmInputBox.Dispose()

        Return Results
    End Function

    Public Overloads Shared Function Show(ByVal Prompt As String, ByVal Title As String, ByVal DefaultResponse As String) As InputDialogResults.InputMsgResults
        frmInputBox = New frmInputMessageBox(Prompt, Title, DefaultResponse)
        frmInputBox.ShowDialog()

        Dim Results As InputDialogResults.InputMsgResults = frmInputBox.InputResults
        frmInputBox.Close()
        frmInputBox.Dispose()

        Return Results
    End Function

    Public Overloads Shared Function Show(ByVal Prompt As String, ByVal Title As String, ByVal DefaultResponse As String, ByVal XPos As Integer, ByVal YPos As Integer) As InputDialogResults.InputMsgResults
        frmInputBox = New frmInputMessageBox(Prompt, Title, DefaultResponse, XPos, YPos)
        frmInputBox.ShowDialog()

        Dim Results As InputDialogResults.InputMsgResults = frmInputBox.InputResults
        frmInputBox.Close()
        frmInputBox.Dispose()

        Return Results
    End Function
#End Region
End Class

Module InputMessageBoxFunctions
    Private Const CANCEL As String = Chr(24)

    'Function: myInputBox
    'Purpose: Provides the user with a VB.NET InputBox with one exception:
    '         it can tell the user whether or not the Cancel button has been
    '         pressed.
    '         The difference between this function and the VB.NET InputBox
    '         is that the VB.NET InputBox only returns "" (aka String.Empty or
    '         Nothing) when the Cancel button is pushed whether or not anything
    '         has been entered into the InputBox. It wasn't made clear enough
    '         to me when the Cancel button was pressed, hence this function.
    'Parameters: Takes same parameters as a VB.NET InputBox
    'Returns: If OK was pressed, will return the text typed in.
    '         If Cancel was pressed, it will return the "Cancel" ASCII character
    Public Function myInputBox(ByVal Prompt As String, Optional ByVal Title As String = "", Optional ByVal DefaultResponse As String = "") As String
        Dim result As InputDialogResults.InputMsgResults = InputMessageBox.Show(Prompt, Title, DefaultResponse)

        If result.DialogResult = InputDialogResults.InputMsgResults.InputDialogResult.OK Then
            myInputBox = result.Response
        Else
            myInputBox = CANCEL
        End If
    End Function

    'Function: InputBox
    'Purpose: Extremely similar to the VB.NET InputBox, except that upon the
    '         user clicking the Cancel button, rather than returning "" (aka
    '         String.Empty or Nothing), this will return the Default Response.
    'Parameters: Takes same parameters as a VB.NET InputBox
    'Returns: If OK was pressed, will return the text typed in.
    '         If Cancel was pressed, it will return the Default Response.
    Public Function InputBox(ByVal Prompt As String, Optional ByVal Title As String = "", Optional ByVal DefaultResponse As String = "") As String
        InputBox = myInputBox(Prompt, Title, DefaultResponse)

        If InputBox = CANCEL Then
            InputBox = DefaultResponse
        End If
    End Function
End Module