Custom button captions in .NET messagebox?

后端 未结 8 1653
没有蜡笔的小新
没有蜡笔的小新 2020-12-03 05:24

Is there an easy way to display a messagebox in VB.NET with custom button captions? I came across What is an easy way to create a MessageBox with custom button text in

8条回答
  •  一整个雨季
    2020-12-03 05:47

    MessageBox uses a plain window that can be messed with like any other window. This has been possible in Windows for a very long time, well over 20 years already. The techniques are getting obscure though, too many friendly class wrappers that hide the native winapi and don't expose everything you can do with it. So much so that programmers now automatically assume that this isn't possible, as you can tell from the upvoted answers. It is the kind of programming that Petzold taught us in his seminal "Programming Windows" book. Replacing MessageBox with a custom Form or Window is actually fairly hard to do, it does non-trivial automatic layout to fit the text and supports localization without help. Although that's exactly what you don't seem to like :)

    Anyhoo, the message box window is easy to find back. It is owned by the UI thread and has a special class name that makes it unique. EnumThreadWindows() enumerates the windows owned by a thread, GetClassName() lets you check the kind of window. Then just poke the text into the button with SetWindowText().

    Add a new class to your project and paste the code shown below. Invoke it with code like this:

    Nobugz.PatchMsgBox(New String() {"Da", "Njet"})
    MsgBox("gack", MsgBoxStyle.YesNo)
    

    Here's the code:

    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
    

提交回复
热议问题