【发布时间】:2013-10-06 02:03:05
【问题描述】:
有没有一种简单的方法可以为 MessageBox 显示自定义字体?
对于“简单的方法”,我的意思是使用 WinAPI 或其他技术,但不是从头开始编写整个消息框。
我见过很多自定义消息框,但大多数只是不保留默认消息框附加参数的表单,其他自定义消息框的大小/边界错误,因此“确定”按钮被剪切或不正确对齐,并且其他自定义消息框有自己的问题/错误。
我希望是否可以添加一个通用参数来实例化这个很棒的自定义消息框设置所需的字体:
原始代码是 @Hans Passant 的 C# 自定义消息框类,我很久以前从这里 Winforms-How can I make MessageBox appear centered on MainForm? 获取并使用在线翻译器对其进行了翻译:
' [ Centered Messagebox ]
'
' Examples :
'
' Using New MessageBox_Centered(Me)
' MessageBox.Show("Test Text", "Test Title", MessageBoxButtons.OK)
' End Using
#Region " Centered MessageBox Class"
Imports System.Runtime.InteropServices
Imports System.Text
Class MessageBox_Centered
Implements IDisposable
' P/Invoke
Public Class NativeMethods
Delegate Function EnumThreadWndProc(hWnd As IntPtr, lp As IntPtr) As Boolean
<DllImport("user32.dll")> _
Shared Function EnumThreadWindows(tid As Integer, callback As EnumThreadWndProc, lp As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll")> _
Shared Function GetCurrentThreadId() As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Shared Function GetClassName(hWnd As IntPtr, buffer As StringBuilder, buflen As Integer) As Integer
End Function
<DllImport("user32.dll")> _
Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As RECT) As Boolean
End Function
<DllImport("user32.dll")> _
Shared Function MoveWindow(hWnd As IntPtr, x As Integer, y As Integer, w As Integer, h As Integer, repaint As Boolean) As Boolean
End Function
Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
End Class
Private mTries As Integer = 0
Private mOwner As Form
Public Sub New(owner As Form)
mOwner = owner
owner.BeginInvoke(New MethodInvoker(AddressOf findDialog))
End Sub
Private Sub findDialog()
' Enumerate windows to find the message box
If mTries < 0 Then Return
Dim callback As New NativeMethods.EnumThreadWndProc(AddressOf checkWindow)
If NativeMethods.EnumThreadWindows(NativeMethods.GetCurrentThreadId(), callback, IntPtr.Zero) Then
If System.Threading.Interlocked.Increment(mTries) < 10 Then
mOwner.BeginInvoke(New MethodInvoker(AddressOf findDialog))
End If
End If
End Sub
Private Function checkWindow(hWnd As IntPtr, lp As IntPtr) As Boolean
' Checks if <hWnd> is a dialog
Dim sb As New StringBuilder(260)
NativeMethods.GetClassName(hWnd, sb, sb.Capacity)
If sb.ToString() <> "#32770" Then Return True
' Got it
Dim frmRect As New Rectangle(mOwner.Location, mOwner.Size)
Dim dlgRect As NativeMethods.RECT
NativeMethods.GetWindowRect(hWnd, dlgRect)
NativeMethods.MoveWindow(hWnd, frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) \ 2, frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) \ 2, dlgRect.Right - dlgRect.Left, dlgRect.Bottom - dlgRect.Top, True)
Return False
End Function
Public Sub Dispose() Implements IDisposable.Dispose
mTries = -1
End Sub
End Class
#End Region
更新:
试图适应@Pete 假设的解决方案,但我做不到。
Class MessageBox_Centered : Implements IDisposable
Public Class NativeMethods
Delegate Function EnumThreadWndProc(hWnd As IntPtr, lp As IntPtr) As Boolean
Delegate Function EnumWindowsProc(hWnd As IntPtr, lp As IntPtr) As Boolean
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function EnumThreadWindows(tid As Integer, callback As EnumThreadWndProc, lp As IntPtr) As Boolean
End Function
<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function GetCurrentThreadId() As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function GetClassName(hWnd As IntPtr, buffer As StringBuilder, buflen As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function GetWindowRect(hWnd As IntPtr, ByRef rc As RECT) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function MoveWindow(hWnd As IntPtr, x As Integer, y As Integer, w As Integer, h As Integer, repaint As Boolean) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function EnumChildWindows(hwndParent As IntPtr, lpEnumFunc As EnumWindowsProc, lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Shared Function SendMessage(hWnd As IntPtr, Msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
Structure RECT
Public Left As Integer
Public Top As Integer
Public Right As Integer
Public Bottom As Integer
End Structure
End Class
Private mTries As Integer = 0
Private mOwner As Form
Public Sub New(owner As Form)
mOwner = owner
owner.BeginInvoke(New MethodInvoker(AddressOf findDialog))
End Sub
Private Sub findDialog()
' Enumerate windows to find the message box
If mTries < 0 Then Return
Dim callback As New NativeMethods.EnumThreadWndProc(AddressOf checkWindow)
If NativeMethods.EnumThreadWindows(NativeMethods.GetCurrentThreadId(), callback, IntPtr.Zero) Then
If System.Threading.Interlocked.Increment(mTries) < 10 Then
mOwner.BeginInvoke(New MethodInvoker(AddressOf findDialog))
End If
End If
End Sub
Private Function checkWindow(hWnd As IntPtr, lp As IntPtr) As Boolean
' Checks if <hWnd> is a dialog
Dim sb As New StringBuilder(260)
NativeMethods.GetClassName(hWnd, sb, sb.Capacity)
If sb.ToString() <> "#32770" Then
Return True
End If
' Got it
Dim frmRect As New Rectangle(mOwner.Location, mOwner.Size)
Dim dlgRect As NativeMethods.RECT
NativeMethods.GetWindowRect(hWnd, dlgRect)
NativeMethods.MoveWindow(hWnd, frmRect.Left + (frmRect.Width - dlgRect.Right + dlgRect.Left) \ 2, frmRect.Top + (frmRect.Height - dlgRect.Bottom + dlgRect.Top) \ 2, dlgRect.Right - dlgRect.Left, dlgRect.Bottom - dlgRect.Top, True)
' Dim wndText As New StringBuilder()
' NativeMethods.GetWindowText(hWnd2, wndText, 1000)
' SendMessage(hWnd2, WM_SETFONT, f.ToHfont(), new IntPtr(1))
Return False
End Function
Public Sub Dispose() Implements IDisposable.Dispose
mTries = -1
End Sub
End Class
更新 2:
这是对我需要做的事情的解释。
以@Hans Passant 的代码 sn-p 为中心的消息框,我需要使用自定义字体启动它(实例化它)。
一个例子可能是创建一个通用函数到居中的消息框可能使用类的“新”块来传递所需的字体作为参数,然后用该字体做必要的事情来显示消息框居中 + 自定义字体。
所以我需要通过添加使用自定义字体的可能性来扩展类。
【问题讨论】:
-
您违反了本网站的许可,您不能在没有署名的情况下复制某人的答案。我已经回答了这个问题,你复制了错误的代码。
-
@Hans Passant 我不敢相信你对我说的话,代码是我很久以前在我的这个问题中发布的一个 sn-p:stackoverflow.com/questions/ 15904610/show-a-messagebox-centered-in-form ,该代码不是我的,但显然我不知道原始代码是哪个,我无法知道代码是否来自 StackOverflow 答案或者谁是作者,你认为我需要搜索整个谷歌结果才能找到sn-p的作者吗?只是我不敢相信,我太尊重你了,但这并不严重。原谅我的英语。
-
链接到您也违反了许可的另一个帖子是不够的。显然,您最初找到代码没有问题,它在该问题中作为重复链接。你必须纠正这些错误。
-
哦,我现在明白你在说什么了,我看到我已经翻译了你的代码,当然你需要明白从很久以前我做这个问题到今天,我我不记得你或其他任何人是作者,我当然会汇总你的归属,因为现在我通过阅读我链接的帖子的 cmets 知道了。请原谅我的英语并理解我所说的话
-
我明白了。它发生了。简单地指出,始终将代码归于个人用途是一种很好的做法,因为您永远不知道何时需要这些信息。我总是将 URL 放在评论中,而且我经常发现自己使用这些 URL 来返回源代码。
标签: .net vb.net winforms fonts messagebox