有没有一种简单的方法在VB.NET中显示带有自定义按钮标题的消息框?我遇到了在托管C++中使用自定义按钮文本创建MessageBox的简单方法是什么?,在Stack Overflow存档中,但它适用于托管C++.
不,
你必须制作自定义表格FormBorderType = FixedDialog
.
这是一个小教程:
由James D. Murray于2007年6月12日,在70-526之间
Microsoft认证考试:70-526(MCTS)
目标:在Windows窗体应用程序中创建和使用自定义对话框.
语言:Visual Basic 2005(单击此处查看此条目的C#版本)
我记得我第一次需要在.NET应用程序中创建一个用C#编写的对话框.作为一名长期的Visual Basic程序员,我认为这可以通过使用Visual Studio.NET附带的对话框模板轻松完成.令我惊讶的是,没有这样的表单模板存在于C#中,尽管有一个用于Visual Basic 2005.在浏览了几本充满Windows Forms 2.0编程信息的书籍和网页之后,我手动转换了一组基本步骤.将.NET表单转换为Windows对话框:
步骤1:向.NET项目添加一个表单并将其命名为"DialogBoxForm".
第2步:在Form的右下角区域放下两个按钮,并将它们命名为"OKButton"和"CancelButton".
步骤3:更改窗体的以下属性以将其外观和行为调整为标准对话框:
Property Value Description ----------------------------------------------------------------------------------------------------------------------------- AcceptButton OK button instance Causes form to return value DialogResult.OK. Only used on modal dialog boxes. CancelButton Cancel button instance Causes form to return value DialogResult.Cancel. Only used on modal dialog boxes. FormBorderStyle FixedDialog Create a non-sizable form with no control box on the title bar. HelpButton True The Help button appears in the caption bar next to the Close button. The ControlBox property must be True for these buttons to be visible. MaximizeBox False Hide the Maximize button in the title bar. MinimizeBox False Hide the Minimize button in the title bar. ShowIcon False The title bar icon is not visible in a dialog box. ShowInTaskBar False Do not indicate the presence of the form on the Windows Task Bar. Start Position CenterParent The initial position of a dialog box is over its parent form. Size As Needed The fixed size needed for the dialog box.
可以使用表单的"属性"窗口或使用表单的"加载"事件中的代码来设置这些属性:
Me.AcceptButton = OKButton Me.CancelButton = CancelButton Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedDialog Me.HelpButton = True Me.MaximizeBox = False Me.MinimizeBox = False Me.ShowInTaskbar = False Me.ShowIcon = False Me.StartPosition = FormStartPosition.CenterParent
第4步:将以下按钮单击事件处理程序添加到窗体:
Private Sub OKButton_Click(ByVal sender As Object, _ByVal e As EventArgs) ' User clicked the OK button Me.DialogResult = Windows.Forms.DialogResult.OK End Sub Private Sub CancelButton_Click(ByVal sender As Object, _ByVal e As EventArgs) ' User clicked the Cancel button Me.DialogResult = Windows.Forms.DialogResult.Cancel End Sub
步骤5:添加将数据移入和移出对话框所需的属性,就像添加任何表单一样:
Private _LoginName As String Private _LoginPassword As String Public Property LoginName() As String Get Return _LoginName End Get Set(ByVal value As String) _LoginName = value End Set End Property Public Property LoginPassword() As String Get Return _LoginPassword End Get Set(ByVal value As String) _LoginPassword = value End Set End Property
步骤6:通过调用表单的ShowDialog()以模态方式显示对话框:
Public Sub ShowDialogBox() Dim dialog As New DialogBoxForm dialog.LoginName = "JDMurray" dialog.LoginPassword = String.Empty If dialog.ShowDialog() = Windows.Forms.DialogResult.OK Then Debug.WriteLine("Login Name: " & dialog.LoginName) Debug.WriteLine("Password: " & dialog.LoginPassword) Else ' User clicked the Cancel button End If End Sub
步骤7:要无模式显示对话框,请调用DialogBoxForm的Show()方法.您需要向DialogBoxForm的Close事件添加事件处理程序,以了解用户何时关闭对话框:
Public Sub ShowDialogBox() Dim dialog As DialogBoxForm = New DialogBoxForm dialog.LoginName = "JDMurray" dialog.Password = String.Empty AddHandler dialog.FormClosed, AddressOf dialog_FormClosed dialog.Show() ' The Show() method returns immediately End Sub Private Sub dialog_FormClosed(ByVal sender As Object, _ ByVal e As FormClosedEventArgs) ' This method is called when the user closes the dialog box End Sub
MessageBox使用一个可以像任何其他窗口一样混淆的普通窗口.Windows已经有很长一段时间了,已经有20多年了.这些技术越来越模糊,太多的友好类包装器隐藏了原生的winapi并且没有公开你可以用它做的一切.所以程序员现在自动认为这是不可能的,正如你可以从upvoted答案中看出来的那样.这是Petzold在其开创性的"编程Windows"一书中教给我们的一种编程.用自定义窗体或窗口替换MessageBox实际上很难做到,它可以实现非平凡的自动布局以适应文本并支持本地化而无需帮助.虽然这正是你似乎不喜欢的:)
Anyhoo,消息框窗口很容易找回.它由UI线程拥有,并具有一个特殊的类名,使其独一无二.EnumThreadWindows()枚举一个线程拥有的窗口,GetClassName()允许您检查窗口的类型.然后用SetWindowText()将文本戳到按钮中.
在项目中添加一个新类并粘贴下面显示的代码.用这样的代码调用它:
Nobugz.PatchMsgBox(New String() {"Da", "Njet"}) MsgBox("gack", MsgBoxStyle.YesNo)
这是代码:
Imports System.Text Imports System.Runtime.InteropServices Public Class Nobugz Private Shared mLabels() As String '' Desired new labels Private Shared mLabelIndex As Integer '' Next caption to update Public Shared Sub PatchMsgBox(ByVal labels() As String) ''--- Updates message box buttons mLabels = labels Application.OpenForms(0).BeginInvoke(New FindWindowDelegate(AddressOf FindMsgBox), GetCurrentThreadId()) End Sub Private Shared Sub FindMsgBox(ByVal tid As Integer) ''--- Enumerate the windows owned by the UI thread EnumThreadWindows(tid, AddressOf EnumWindow, IntPtr.Zero) End Sub Private Shared Function EnumWindow(ByVal hWnd As IntPtr, ByVal lp As IntPtr) As Boolean ''--- Is this the message box? Dim sb As New StringBuilder(256) GetClassName(hWnd, sb, sb.Capacity) If sb.ToString() <> "#32770" Then Return True ''--- Got it, now find the buttons mLabelIndex = 0 EnumChildWindows(hWnd, AddressOf FindButtons, IntPtr.Zero) Return False End Function Private Shared Function FindButtons(ByVal hWnd As IntPtr, ByVal lp As IntPtr) As Boolean Dim sb As New StringBuilder(256) GetClassName(hWnd, sb, sb.Capacity) If sb.ToString() = "Button" And mLabelIndex <= UBound(mLabels) Then ''--- Got one, update text SetWindowText(hWnd, mLabels(mLabelIndex)) mLabelIndex += 1 End If Return True End Function ''--- P/Invoke declarations Private Delegate Sub FindWindowDelegate(ByVal tid As Integer) Private Delegate Function EnumWindowDelegate(ByVal hWnd As IntPtr, ByVal lp As IntPtr) As Boolean Private Declare Auto Function EnumThreadWindows Lib "user32.dll" (ByVal tid As Integer, ByVal callback As EnumWindowDelegate, ByVal lp As IntPtr) As Boolean Private Declare Auto Function EnumChildWindows Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal callback As EnumWindowDelegate, ByVal lp As IntPtr) As Boolean Private Declare Auto Function GetClassName Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal name As StringBuilder, ByVal maxlen As Integer) As Integer Private Declare Auto Function GetCurrentThreadId Lib "kernel32.dll" () As Integer Private Declare Auto Function SetWindowText Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal text As String) As Boolean End Class
没有方法可以访问或重定向Messagebox的默认按钮文本.
唯一的方法是编写自己的代码,或者只使用互联网中许多免费的代码之一:
免费MsgBoxGo!