你好
我想在运行时创建一个标签和一个组合框。
如何计算 Label.Top 相对于 ComboBox.Top 的值,使两个控件的文本位于一行?
它应该适用于不同的字体和边框样式。两个控件的顶部和高度值相同并不能解决问题。
提前致谢
文本基线计算需要使用 GetTextMetrics Api:
我更习惯 VB.net :
Imports System.Runtime.InteropServices
Public Module Font_Metrics
Public Structure FontMetrics
Dim Ascent As Integer
Dim Descent As Integer
Dim Height As Integer
End Structure
Public Function GetMetrics(gfx As Graphics, fnt As Font) As FontMetrics
Dim Hdc As IntPtr = gfx.GetHdc()
Dim Hfont As IntPtr = fnt.ToHfont()
Dim Metric As TEXTMETRIC
Dim hFontDefault As IntPtr = SelectObject(Hdc, Hfont)
GetTextMetrics(Hdc, Metric)
SelectObject(Hdc, hFontDefault)
DeleteObject(Hfont)
gfx.ReleaseHdc(Hdc)
Dim fm As FontMetrics
fm.Ascent = Metric.tmAscent
fm.Descent = Metric.tmDescent
fm.Height = Metric.tmHeight
Return fm
End Function
Private Structure TEXTMETRIC
Dim tmHeight As Integer
Dim tmAscent As Integer
Dim tmDescent As Integer
Dim tmInternalLeading As Integer
Dim tmExternalLeading As Integer
Dim tmAveCharWidth As Integer
Dim tmMaxCharWidth As Integer
Dim tmWeight As Integer
Dim tmOverhang As Integer
Dim tmDigitizedAspectX As Integer
Dim tmDigitizedAspectY As Integer
Dim tmFirstChar As Char
Dim tmLastChar As Char
Dim tmDefaultChar As Char
Dim tmBreakChar As Char
Dim tmItalic As Byte
Dim tmUnderlined As Byte
Dim tmStruckOut As Byte
Dim tmPitchAndFamily As Byte
Dim tmCharSet As Byte
End Structure
<DllImport("gdi32.dll", CharSet:=CharSet.Unicode)>
Private Function SelectObject(hdc As IntPtr, hgdiobj As IntPtr) As IntPtr
End Function
<DllImport("gdi32.dll", CharSet:=CharSet.Unicode)>
Private Function GetTextMetrics(hdc As IntPtr, <Out> ByRef lptm As TEXTMETRIC) As Boolean
End Function
<DllImport("gdi32.dll", CharSet:=CharSet.Unicode)>
Private Function DeleteObject(hdc As IntPtr) As Boolean
End Function
End Module
现在您可以计算组合框的文本基线并根据它对齐标签的顶部:
Dim combo_fm As FontMetrics = GetMetrics(CreateGraphics, ComboBox.Font)
Dim label_fm As FontMetrics = GetMetrics(CreateGraphics, Label.Font)
SuspendLayout()
Label.Left = ComboBox.Left - Label.Width
Dim BaseLine_y As Integer = ComboBox.Top + (ComboBox.Height - ComboBox.ItemHeight) / 2 + combo_fm.Ascent
Label.Top = BaseLine_y - Label.Padding.Top - label_fm.Ascent
ResumeLayout()