I modified some of this:
1) Text height calculation was not quite right
2) little less padding on the top and bottom of the richtextbox
3) position -3, -4 did not work for me, changed to 0, 0
Thanks for the code.
Imports System.Diagnostics
Imports System.Drawing
Imports System.Globalization
Imports System.Linq
Imports System.Windows.Forms
Public Class FlexibleMessageBox
#Region "Public statics"
Public Shared MAX_WIDTH_FACTOR As Double = 0.7
Public Shared MAX_HEIGHT_FACTOR As Double = 0.7
Public Shared mbFont As Font = New System.Drawing.Font("Microsoft Sans Serif", 9.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CByte(0))
#End Region
#Region "Public show functions"
Public Shared Function Show(ByVal text As String) As DialogResult
Return FlexibleMessageBoxForm.Show(Nothing, text, String.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal owner As IWin32Window, ByVal text As String) As DialogResult
Return FlexibleMessageBoxForm.Show(owner, text, String.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal text As String, ByVal caption As String) As DialogResult
Return FlexibleMessageBoxForm.Show(Nothing, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal owner As IWin32Window, ByVal text As String, ByVal caption As String) As DialogResult
Return FlexibleMessageBoxForm.Show(owner, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons) As DialogResult
Return FlexibleMessageBoxForm.Show(Nothing, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal owner As IWin32Window, ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons) As DialogResult
Return FlexibleMessageBoxForm.Show(owner, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons, ByVal icon As MessageBoxIcon) As DialogResult
Return FlexibleMessageBoxForm.Show(Nothing, text, caption, buttons, icon, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal owner As IWin32Window, ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons, ByVal icon As MessageBoxIcon) As DialogResult
Return FlexibleMessageBoxForm.Show(owner, text, caption, buttons, icon, MessageBoxDefaultButton.Button1)
End Function
Public Shared Function Show(ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons, ByVal icon As MessageBoxIcon, ByVal defaultButton As MessageBoxDefaultButton) As DialogResult
Return FlexibleMessageBoxForm.Show(Nothing, text, caption, buttons, icon, defaultButton)
End Function
Public Shared Function Show(ByVal owner As IWin32Window, ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons, ByVal icon As MessageBoxIcon, ByVal defaultButton As MessageBoxDefaultButton) As DialogResult
Return FlexibleMessageBoxForm.Show(owner, text, caption, buttons, icon, defaultButton)
End Function
#End Region
#Region "Internal form class"
Private Class FlexibleMessageBoxForm
Inherits Form
#Region "Form-Designer generated code"
Private components As System.ComponentModel.IContainer = Nothing
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso (components IsNot Nothing) Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Private Sub InitializeComponent()
Me.components = New System.ComponentModel.Container()
Me.button1 = New System.Windows.Forms.Button()
Me.richTextBoxMessage = New System.Windows.Forms.RichTextBox()
Me.FlexibleMessageBoxFormBindingSource = New System.Windows.Forms.BindingSource(Me.components)
Me.panel1 = New System.Windows.Forms.Panel()
Me.pictureBoxForIcon = New System.Windows.Forms.PictureBox()
Me.button2 = New System.Windows.Forms.Button()
Me.button3 = New System.Windows.Forms.Button()
DirectCast(Me.FlexibleMessageBoxFormBindingSource, System.ComponentModel.ISupportInitialize).BeginInit()
Me.panel1.SuspendLayout()
DirectCast(Me.pictureBoxForIcon, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SuspendLayout()
Me.button1.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.button1.AutoSize = True
Me.button1.DialogResult = System.Windows.Forms.DialogResult.OK
Me.button1.Location = New System.Drawing.Point(11, 67)
Me.button1.MinimumSize = New System.Drawing.Size(0, 24)
Me.button1.Name = "button1"
Me.button1.Size = New System.Drawing.Size(75, 24)
Me.button1.TabIndex = 2
Me.button1.Text = "OK"
Me.button1.UseVisualStyleBackColor = True
Me.button1.Visible = False
Me.richTextBoxMessage.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) Or System.Windows.Forms.AnchorStyles.Left) Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.richTextBoxMessage.BackColor = System.Drawing.Color.White
Me.richTextBoxMessage.BorderStyle = System.Windows.Forms.BorderStyle.None
Me.richTextBoxMessage.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.FlexibleMessageBoxFormBindingSource, "MessageText", True, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged))
Me.richTextBoxMessage.Font = New System.Drawing.Font("Microsoft Sans Serif", 9.5F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, CByte(0))
Me.richTextBoxMessage.Location = New System.Drawing.Point(50, 16)
Me.richTextBoxMessage.Margin = New System.Windows.Forms.Padding(0)
Me.richTextBoxMessage.Name = "richTextBoxMessage"
Me.richTextBoxMessage.[ReadOnly] = True
Me.richTextBoxMessage.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical
Me.richTextBoxMessage.Size = New System.Drawing.Size(200, 30)
Me.richTextBoxMessage.TabIndex = 0
Me.richTextBoxMessage.Text = "<Message>"
AddHandler Me.richTextBoxMessage.LinkClicked, New System.Windows.Forms.LinkClickedEventHandler(AddressOf Me.richTextBoxMessage_LinkClicked)
Me.panel1.Anchor = CType((((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Bottom) Or System.Windows.Forms.AnchorStyles.Left) Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.panel1.BackColor = System.Drawing.Color.White
Me.panel1.Controls.Add(Me.pictureBoxForIcon)
Me.panel1.Controls.Add(Me.richTextBoxMessage)
Me.panel1.Location = New System.Drawing.Point(0, 0)
Me.panel1.Name = "panel1"
Me.panel1.Size = New System.Drawing.Size(268, 59)
Me.panel1.TabIndex = 1
Me.pictureBoxForIcon.BackColor = System.Drawing.Color.Transparent
Me.pictureBoxForIcon.Location = New System.Drawing.Point(15, 15)
Me.pictureBoxForIcon.Name = "pictureBoxForIcon"
Me.pictureBoxForIcon.Size = New System.Drawing.Size(32, 32)
Me.pictureBoxForIcon.TabIndex = 8
Me.pictureBoxForIcon.TabStop = False
Me.button2.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.button2.DialogResult = System.Windows.Forms.DialogResult.OK
Me.button2.Location = New System.Drawing.Point(92, 67)
Me.button2.MinimumSize = New System.Drawing.Size(0, 24)
Me.button2.Name = "button2"
Me.button2.Size = New System.Drawing.Size(75, 24)
Me.button2.TabIndex = 3
Me.button2.Text = "OK"
Me.button2.UseVisualStyleBackColor = True
Me.button2.Visible = False
Me.button3.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
Me.button3.AutoSize = True
Me.button3.DialogResult = System.Windows.Forms.DialogResult.OK
Me.button3.Location = New System.Drawing.Point(173, 67)
Me.button3.MinimumSize = New System.Drawing.Size(0, 24)
Me.button3.Name = "button3"
Me.button3.Size = New System.Drawing.Size(75, 24)
Me.button3.TabIndex = 0
Me.button3.Text = "OK"
Me.button3.UseVisualStyleBackColor = True
Me.button3.Visible = False
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0F, 13.0F)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(260, 102)
Me.Controls.Add(Me.button3)
Me.Controls.Add(Me.button2)
Me.Controls.Add(Me.panel1)
Me.Controls.Add(Me.button1)
Me.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.FlexibleMessageBoxFormBindingSource, "CaptionText", True))
Me.MaximizeBox = False
Me.MinimizeBox = False
Me.MinimumSize = New System.Drawing.Size(276, 140)
Me.Name = "FlexibleMessageBoxForm"
Me.ShowIcon = False
Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show
Me.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent
Me.Text = "<Caption>"
AddHandler Me.Shown, New System.EventHandler(AddressOf Me.FlexibleMessageBoxForm_Shown)
DirectCast(Me.FlexibleMessageBoxFormBindingSource, System.ComponentModel.ISupportInitialize).EndInit()
Me.panel1.ResumeLayout(False)
DirectCast(Me.pictureBoxForIcon, System.ComponentModel.ISupportInitialize).EndInit()
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Private button1 As System.Windows.Forms.Button
Private panel1 As System.Windows.Forms.Panel
Private pictureBoxForIcon As System.Windows.Forms.PictureBox
Private button2 As System.Windows.Forms.Button
Private button3 As System.Windows.Forms.Button
Public FlexibleMessageBoxFormBindingSource As System.Windows.Forms.BindingSource
Public richTextBoxMessage As System.Windows.Forms.RichTextBox
#End Region
#Region "Private constants"
Private Enum BUTTON_TEXT
OK = 0
CANCEL
YES
NO
ABORT
RETRY
IGNORE
End Enum
Private Shared ReadOnly BUTTON_TEXTS_ENGLISH As [String]() = {"OK", "Cancel", "Yes", "No", "Abort", "Retry", _
"Ignore"}
Private Shared ReadOnly BUTTON_TEXTS_GERMAN As [String]() = {"OK", "Abbrechen", "Ja", "Nein", "Abbrechen", "Wiederholen", _
"Ignorieren"}
#End Region
#Region "Private members"
Private _defaultButton As MessageBoxDefaultButton
Private _visibleButtonsCount As Integer
Private _isCultureGerman As Boolean
#End Region
#Region "Private constructor"
Private Sub New()
InitializeComponent()
Me._isCultureGerman = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName.Contains("de")
End Sub
#End Region
#Region "Private helper functions"
Private Shared Function GetStringRows(ByVal message As String) As String()
If String.IsNullOrEmpty(message) Then
Return Nothing
End If
Dim messageRows = message.Split(New Char() {ControlChars.Lf}, StringSplitOptions.None)
Return messageRows
End Function
Private Function GetButtonText(ByVal buttonTextIndex As BUTTON_TEXT) As String
Return If(Me._isCultureGerman, BUTTON_TEXTS_GERMAN(Convert.ToInt32(buttonTextIndex)), BUTTON_TEXTS_ENGLISH(Convert.ToInt32(buttonTextIndex)))
End Function
Private Shared Function GetCorrectedWorkingAreaFactor(ByVal workingAreaFactor As Double) As Double
Const MIN_FACTOR As Double = 0.2
Const MAX_FACTOR As Double = 1.0
If workingAreaFactor < MIN_FACTOR Then
Return MIN_FACTOR
End If
If workingAreaFactor > MAX_FACTOR Then
Return MAX_FACTOR
End If
Return workingAreaFactor
End Function
Private Shared Sub SetDialogStartPosition(ByVal fmbForm As FlexibleMessageBoxForm, ByVal owner As IWin32Window)
If owner Is Nothing Then
fmbForm.CenterToScreen()
End If
End Sub
Private Shared Sub SetDialogSizes(ByVal fmbForm As FlexibleMessageBoxForm, ByVal text As String)
fmbForm.MaximumSize = New Size(Convert.ToInt32(SystemInformation.WorkingArea.Width * FlexibleMessageBoxForm.GetCorrectedWorkingAreaFactor(MAX_WIDTH_FACTOR)), Convert.ToInt32(SystemInformation.WorkingArea.Height * FlexibleMessageBoxForm.GetCorrectedWorkingAreaFactor(MAX_HEIGHT_FACTOR)))
Dim rowSize As Size
Dim maxTextRowWidth = 0
Dim maxTextRowHeight = 0.0F
Dim stringRows = GetStringRows(text)
Using graphics = fmbForm.CreateGraphics()
maxTextRowHeight = graphics.MeasureString("}]|)", mbFont).Height * 1.131
For Each textForRow As String In stringRows
rowSize = graphics.MeasureString(textForRow, mbFont, fmbForm.MaximumSize.Width).ToSize()
If rowSize.Width > maxTextRowWidth Then
maxTextRowWidth = rowSize.Width
End If
Next
End Using
fmbForm.Size = New Size(maxTextRowWidth + fmbForm.Width - fmbForm.richTextBoxMessage.Width, Convert.ToInt32(maxTextRowHeight * stringRows.Length) + fmbForm.Height - fmbForm.richTextBoxMessage.Height)
End Sub
Private Shared Sub SetDialogIcon(ByVal fmbForm As FlexibleMessageBoxForm, ByVal icon As MessageBoxIcon)
Select Case icon
Case MessageBoxIcon.Information
fmbForm.pictureBoxForIcon.Image = SystemIcons.Information.ToBitmap()
Exit Select
Case MessageBoxIcon.Warning
fmbForm.pictureBoxForIcon.Image = SystemIcons.Warning.ToBitmap()
Exit Select
Case MessageBoxIcon.[Error]
fmbForm.pictureBoxForIcon.Image = SystemIcons.[Error].ToBitmap()
Exit Select
Case MessageBoxIcon.Question
fmbForm.pictureBoxForIcon.Image = SystemIcons.Question.ToBitmap()
Exit Select
Case Else
fmbForm.pictureBoxForIcon.Visible = False
fmbForm.richTextBoxMessage.Left -= fmbForm.pictureBoxForIcon.Width
fmbForm.richTextBoxMessage.Width += fmbForm.pictureBoxForIcon.Width
Exit Select
End Select
End Sub
Private Shared Sub SetDialogButtons(ByVal fmbForm As FlexibleMessageBoxForm, ByVal buttons As MessageBoxButtons, ByVal defaultButton As MessageBoxDefaultButton)
Select Case buttons
Case MessageBoxButtons.AbortRetryIgnore
fmbForm._visibleButtonsCount = 3
fmbForm.button1.Visible = True
fmbForm.button1.Text = fmbForm.GetButtonText(BUTTON_TEXT.ABORT)
fmbForm.button1.DialogResult = DialogResult.Abort
fmbForm.button2.Visible = True
fmbForm.button2.Text = fmbForm.GetButtonText(BUTTON_TEXT.RETRY)
fmbForm.button2.DialogResult = DialogResult.Retry
fmbForm.button3.Visible = True
fmbForm.button3.Text = fmbForm.GetButtonText(BUTTON_TEXT.IGNORE)
fmbForm.button3.DialogResult = DialogResult.Ignore
fmbForm.ControlBox = False
Exit Select
Case MessageBoxButtons.OKCancel
fmbForm._visibleButtonsCount = 2
fmbForm.button2.Visible = True
fmbForm.button2.Text = fmbForm.GetButtonText(BUTTON_TEXT.OK)
fmbForm.button2.DialogResult = DialogResult.OK
fmbForm.button3.Visible = True
fmbForm.button3.Text = fmbForm.GetButtonText(BUTTON_TEXT.CANCEL)
fmbForm.button3.DialogResult = DialogResult.Cancel
fmbForm.CancelButton = fmbForm.button3
Exit Select
Case MessageBoxButtons.RetryCancel
fmbForm._visibleButtonsCount = 2
fmbForm.button2.Visible = True
fmbForm.button2.Text = fmbForm.GetButtonText(BUTTON_TEXT.RETRY)
fmbForm.button2.DialogResult = DialogResult.Retry
fmbForm.button3.Visible = True
fmbForm.button3.Text = fmbForm.GetButtonText(BUTTON_TEXT.CANCEL)
fmbForm.button3.DialogResult = DialogResult.Cancel
fmbForm.CancelButton = fmbForm.button3
Exit Select
Case MessageBoxButtons.YesNo
fmbForm._visibleButtonsCount = 2
fmbForm.button2.Visible = True
fmbForm.button2.Text = fmbForm.GetButtonText(BUTTON_TEXT.YES)
fmbForm.button2.DialogResult = DialogResult.Yes
fmbForm.button3.Visible = True
fmbForm.button3.Text = fmbForm.GetButtonText(BUTTON_TEXT.NO)
fmbForm.button3.DialogResult = DialogResult.No
fmbForm.ControlBox = False
Exit Select
Case MessageBoxButtons.YesNoCancel
fmbForm._visibleButtonsCount = 3
fmbForm.button1.Visible = True
fmbForm.button1.Text = fmbForm.GetButtonText(BUTTON_TEXT.YES)
fmbForm.button1.DialogResult = DialogResult.Yes
fmbForm.button2.Visible = True
fmbForm.button2.Text = fmbForm.GetButtonText(BUTTON_TEXT.NO)
fmbForm.button2.DialogResult = DialogResult.No
fmbForm.button3.Visible = True
fmbForm.button3.Text = fmbForm.GetButtonText(BUTTON_TEXT.CANCEL)
fmbForm.button3.DialogResult = DialogResult.Cancel
fmbForm.CancelButton = fmbForm.button3
Exit Select
Case Else
fmbForm._visibleButtonsCount = 1
fmbForm.button3.Visible = True
fmbForm.button3.Text = fmbForm.GetButtonText(BUTTON_TEXT.OK)
fmbForm.button3.DialogResult = DialogResult.OK
fmbForm.CancelButton = fmbForm.button3
Exit Select
End Select
fmbForm._defaultButton = defaultButton
End Sub
#End Region
#Region "Private event handlers"
Private Sub FlexibleMessageBoxForm_Shown(ByVal sender As Object, ByVal e As EventArgs)
Dim buttonIndexToFocus As Integer = 1
Dim buttonToFocus As Button
Select Case Me._defaultButton
Case MessageBoxDefaultButton.Button2
buttonIndexToFocus = 2
Exit Select
Case MessageBoxDefaultButton.Button3
buttonIndexToFocus = 3
Exit Select
Case Else
buttonIndexToFocus = 1
Exit Select
End Select
If buttonIndexToFocus > Me._visibleButtonsCount Then
buttonIndexToFocus = Me._visibleButtonsCount
End If
If buttonIndexToFocus = 3 Then
buttonToFocus = Me.button3
ElseIf buttonIndexToFocus = 2 Then
buttonToFocus = Me.button2
Else
buttonToFocus = Me.button1
End If
buttonToFocus.Focus()
End Sub
Private Sub richTextBoxMessage_LinkClicked(ByVal sender As Object, ByVal e As LinkClickedEventArgs)
Try
Cursor.Current = Cursors.WaitCursor
Process.Start(e.LinkText)
Catch generatedExceptionName As Exception
Throw
Finally
Cursor.Current = Cursors.[Default]
End Try
End Sub
#End Region
#Region "Properties (only used for binding)"
Public Property CaptionText() As String
Get
Return m_CaptionText
End Get
Set(ByVal value As String)
m_CaptionText = value
End Set
End Property
Private m_CaptionText As String
Public Property MessageText() As String
Get
Return m_MessageText
End Get
Set(ByVal value As String)
m_MessageText = value
End Set
End Property
Private m_MessageText As String
#End Region
#Region "Public show function"
Public Overloads Shared Function Show(ByVal owner As IWin32Window, ByVal text As String, ByVal caption As String, ByVal buttons As MessageBoxButtons, ByVal icon As MessageBoxIcon, ByVal defaultButton As MessageBoxDefaultButton) As DialogResult
Dim fmbForm As FlexibleMessageBoxForm = New FlexibleMessageBoxForm()
fmbForm.DoubleBuffered = True
fmbForm.ShowInTaskbar = False
fmbForm.CaptionText = caption
fmbForm.MessageText = text
fmbForm.FlexibleMessageBoxFormBindingSource.DataSource = fmbForm
SetDialogButtons(fmbForm, buttons, defaultButton)
SetDialogIcon(fmbForm, icon)
fmbForm.Font = mbFont
fmbForm.richTextBoxMessage.Font = mbFont
SetDialogSizes(fmbForm, text)
Return fmbForm.ShowDialog(owner)
End Function
#End Region
End Class
#End Region
End Class
|