我已经编写了一个VBA函数来返回给定字体和字符串中字符串的宽度。点大小为300dpi。我不是一个非常有经验的程序员,这是我第一次使用Windows API。我希望宽度随着字体大小逐渐减小,但不是那么渐进。
例如:
磅值=返回宽度(字体Arial中的字符串“Text”)
14 = 99
13.5 = 95
13 = 91
12.5 = 90
12 = 84
11.5 = 83
11 = 75
因此,将字体大小减小0.5会将宽度改变为4> 4> 1> 6> 1> 8。我想了解为什么字体大小和返回宽度之间存在非线性关系。我知道字体渲染有些迷惑,但我猜这不是整个故事,特别是不是300dpi?
就像我说的那样,我不是 - 相当 - 新手,所以请随意说“Google [关键字],擦洗!”
上下文:与大多数GetTextExtent的使用不同,我没有尝试适合的对象。最终目标是一个函数,当以300dpi的字体F打印时,返回X点处的字符串A是否比Y点处的字符串B宽。
这是我的代码折叠为一个函数...
Option Explicit
Private Declare PtrSafe Function CreateDC Lib "gdi32.dll" Alias "CreateDCA" (ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, ByVal lpInitData As Long) As Long
Private Declare PtrSafe Function CreateFont Lib "gdi32.dll" Alias "CreateFontA" (ByVal nHeight As Integer, ByVal nWidth As Integer, ByVal nEscapement As Integer, ByVal nOrientation As Integer, ByVal fnWeight As Integer, ByVal fdwItalic As Long, ByVal fdwUnderline As Long, ByVal fdwStrikeOut As Long, ByVal fdwCharSet As Long, ByVal fdwOutputPrecision As Long, ByVal fdwClipPrecision As Long, ByVal fdwQuality As Long, ByVal fdwPitchAndFamily As Long, ByVal lpszFace As String) As Long
Private Declare PtrSafe Function SelectObject Lib "gdi32.dll" (ByVal hDC As Long, ByVal hObject As Long) As Long
Private Declare PtrSafe Function GetTextExtentPoint32 Lib "gdi32.dll" Alias "GetTextExtentPoint32A" (ByVal hDC As Long, ByVal lpctStr As String, ByVal c As Integer, ByRef sz As SIZE) As Boolean
Private Declare PtrSafe Function DeleteDC Lib "gdi32.dll" (ByVal hDC As Long) As Long
Private Declare PtrSafe Function DeleteObject Lib "gdi32.dll" (ByVal hObject As Long) As Long
Private Type SIZE
x As Long
y As Long
End Type
Function GetPrintedWidth(strToTest As String, strFontName as String, sngFontSize As Single)
'Create the device context. (Documents are rendered to PDF before printing, so I'm using the Adobe PDF printer driver. Mistake?)
Dim DC As Long: DC = CreateDC(0, "Adobe PDF", 0, 0)
'Convert sngFontSize points to logical units. Final print is @300dpi.
'Most examples I've seen use MulDiv, but it converts sngFontSize to long before calculating.
Dim nHeight As Long: nHeight = sngFontSize * 300 / 72
'Create the font.
Dim fnt As Long: fnt = CreateFont(nHeight, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, strFontName & Chr$(0))
'Select font into DC.
DeleteObject SelectObject(DC, fnt)
'Get string dimensions.
Dim sz As SIZE: GetTextExtentPoint32 DC, strToTest, Len(strToTest), sz
'Return width.
GetPrintedWidth = sz.x
'Clean up.
DeleteObject fnt
DeleteDC DC
End Function
我非常对基本代码更正开放,我还在学习!
你们都是最好的,谢谢你们的一切:)
更新
增加nHeight可以解决问题。我得到了几乎线性的结果:
nHeight = sngFontSize * 300 / 72
为:
nHeight = sngFontSize * 3000 / 72
所以...我猜它只是一个字体缩放问题,但我完全不知道为什么。 AFAIK的nHeight公式应为
FontSize * PointsPerLogicalInch / 72
... ergo 300dpi打印机应该有300 PointsPerLogicalInch,没有?
更新2
GetDeviceCaps LOGPIXELSY通常用于获取PointsPerLogicalInch。我测试了我的可用打印机:
Adobe PDF打印驱动程序返回1200
我的桌面打印机返回600
顺便说一下,LOGPIXELSX返回了相同的
所以300应该是正确的,或者我已经搞砸了。