用"旋轉(zhuǎn)字體"美化界面
發(fā)表時(shí)間:2024-06-14 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]如何使自己設(shè)計(jì)的程序具有漂亮和友好的界面,是程序員間永恒的話題。這里,筆者向您介紹一種非常簡(jiǎn)單的技巧,使文字旋轉(zhuǎn)起來。 這里的“旋轉(zhuǎn)字體”指的是讓一行字體的水平基線(baseline)轉(zhuǎn)過一定的角度。正如您所看到的,旋轉(zhuǎn)字體會(huì)產(chǎn)生輕松、活潑的視覺效果,可以給觀者以特殊的聯(lián)想,是一種行之有效的顯示特...
如何使自己設(shè)計(jì)的程序具有漂亮和友好的界面,是程序員間永恒的話題。這里,筆者向您介紹一種非常簡(jiǎn)單的技巧,使文字旋轉(zhuǎn)起來。
這里的“旋轉(zhuǎn)字體”指的是讓一行字體的水平基線(baseline)轉(zhuǎn)過一定的角度。正如您所看到的,旋轉(zhuǎn)字體會(huì)產(chǎn)生輕松、活潑的視覺效果,可以給觀者以特殊的聯(lián)想,是一種行之有效的顯示特技。
有一種很容易想到的辦法可以實(shí)現(xiàn)旋轉(zhuǎn)字體,即首先生成文字的點(diǎn)陣(位圖),然后利用坐標(biāo)旋轉(zhuǎn)變換生成新的位圖再輸出到屏幕或打印機(jī)上。這種辦法思路清晰,不但可以用于字體的旋轉(zhuǎn),也可以用于其他種種字體變形,如同WinWord中的WordArt或中文之星的“藝術(shù)漢字”。但這種辦法實(shí)現(xiàn)起來比較麻煩,需要一些計(jì)算機(jī)繪圖學(xué)方面的知識(shí),而且位圖變換過程中需要占用較多的內(nèi)存。而我們所要介紹的方法,可以有效地解決這些問題,而且不需要什么專門的知識(shí),而是充分地利用Windows API已有的功能實(shí)現(xiàn)旋轉(zhuǎn)字體的效果。
我們知道,邏輯字體是一類非常重要的Windows GDI對(duì)象。我們正是通過選擇不同的邏輯字體來輸出各種秀美的字體的。而所謂“旋轉(zhuǎn)字體”不過是一類特殊的邏輯字體。如同其他的GDI對(duì)象(如畫筆、畫刷、調(diào)色板)一樣,字體對(duì)象不但具有固有的字體,我們也可以建立自己的邏輯字體。建立字體可以使用Windows API的CreateFontIndirect()函數(shù)。在調(diào)用該函數(shù)之前,我們將字體的特征放入LOGFONT結(jié)構(gòu)變量中。LOGFONT結(jié)構(gòu)是這樣定義的:
Type LOGFONT
lfHeight As Integer ' 字體的高度
lfWidth As Integer ' 字體的寬度
lfEscapement As Integer ' 字體旋轉(zhuǎn)的角度
lfOrientation As Integer
lfWeight As Integer ' 字體的輕重
lfItalic As String * 1 ' 是否為斜體
lfUnderline As String * 1 ' 是否有下劃線
lfStrikeOut As String * 1 ' 是否有強(qiáng)調(diào)線
lfCharSet As String * 1 ' 字符集
lfOutPrecision As String * 1 ' 輸出精度
lfClipPrecision As String * 1 ' 剪裁精度
lfQuality As String * 1 ' 輸出質(zhì)量
lfPitchAndFamily As String * 1 ' 間距和字體族
lfFaceName As String * LF_FACESIZE ' 字體名,如“宋體”
End Type
利用這個(gè)數(shù)據(jù)結(jié)構(gòu),你可以方便地設(shè)置各種字體參數(shù),比如高度、寬度等。該結(jié)構(gòu)中同我們所要討論的問題關(guān)系最大的是lfEscapement,它表示字符的基線同坐標(biāo)的X軸之間的旋轉(zhuǎn)角度,從X軸正方向開始沿逆時(shí)針方向旋轉(zhuǎn),以十分之一度為單位(圖2)。蔡明志先生著的《Windows程序設(shè)計(jì)?繪圖篇--使用Borland C++ for Windows》一書(科學(xué)出版社1993年9月出版)的482頁上指出旋轉(zhuǎn)角度以十度為單位,為此筆者查閱了SDK手冊(cè),其英文原文為:“measured in tenths of a degree”,似應(yīng)為以十分之一度為單位。
lfFaceName指明字體的名稱,如“宋體”、“行楷”。需要指出的是,個(gè)別字體不支持字體旋轉(zhuǎn),主要是字體寬度不可變的種類,如FixedSys就不支持字體旋轉(zhuǎn),好在這樣的字體只有一兩種。
具體的實(shí)現(xiàn)參見文后所附的程序(用Visual Basic 3.0編寫),其中RotPrint過程用來輸出旋轉(zhuǎn)字體。其步驟如下:首先,利用GetObject()函數(shù)獲得當(dāng)前字體的LOGFONT結(jié)構(gòu),修改lfEscapement,設(shè)置旋轉(zhuǎn)角度,然后調(diào)用CreateFontIndirect()函數(shù)建立邏輯字體并選用之。接下來,調(diào)用TextOut()函數(shù)輸出字符串。使用TextOut()函數(shù)可以使那些不支持Print方法的控制(如標(biāo)簽),同樣可以輸出旋轉(zhuǎn)字體。最后,用DeleteObject()函數(shù)刪除建立的邏輯字體并恢復(fù)原字體。
您可以通過示例程序的“選擇”菜單中的“字體”項(xiàng)來嘗試不同的字體效果,從中選出令人滿意的組合。
附錄:源程序
ROTFONT.BAS文件:
DefInt A-Z
' 邏輯字體
Global Const LF_FACESIZE = 32 ' 最長(zhǎng)的字體名稱
Global Const SYSTEM_FONT = 13
Type LOGFONT
lfHeight As Integer
lfWidth As Integer
lfEscapement As Integer
lfOrientation As Integer
lfWeight As Integer
lfItalic As String * 1
lfUnderline As String * 1
lfStrikeOut As String * 1
lfCharSet As String * 1
lfOutPrecision As String * 1
lfClipPrecision As String * 1
lfQuality As String * 1
lfPitchAndFamily As String * 1
lfFaceName As String * LF_FACESIZE
End Type
'字體的族
Global Const FF_DONTCARE = 0 ' 無所謂
Global Const FF_ROMAN = 16 ' 字體寬度可變,Times Roman, Century ' Schoolbook等
Global Const FF_SWISS = 32 ' 寬度可變,帶襯線,如Helvetica, Swiss等
Global Const FF_MODERN = 48 ' 具有規(guī)定的寬度,襯線可有可無,
' 如Pica, Elite, Courier等等.
Global Const FF_SCRIPT = 64 ' 手寫體,如Cursive
Global Const FF_DECORATIVE = 80 ' 特殊字體,如Old English
' GDI字體函數(shù)
Declare Function CreateFontIndirect Lib "GDI" (lpLogFont As LOGFONT) As Integer
Declare Function SelectObject Lib "GDI" (ByVal hDC%, ByVal Object%) As Integer
Declare Sub DeleteObject Lib "GDI" (ByVal Object%)
Declare Function GetStockObject Lib "GDI" (ByVal nIndex As Integer) As Integer
Declare Sub GDIGetObject Lib "GDI" Alias "GetObject" (ByVal hObject As Integer, ByVal nCount As Integer, lpObject As Any)
Declare Sub TextOut Lib "GDI" (ByVal hDC As Integer, ByVal X As Integer, ByVal Y As Integer, ByVal lpString As String, ByVal nCount As Integer)
ROTFONT.FRM文件:
VERSION 2.00
Begin Form frmRotDemo
Caption = "旋轉(zhuǎn)字體演示"
ClientHeight = 4980
ClientLeft = 1095
ClientTop = 1785
ClientWidth = 4380
FontBold = -1 'True
FontItalic = 0 'False
FontName = "Courier New"
FontSize = 18
FontStrikethru = 0 'False
FontUnderline = 0 'False
Height = 5670
Left = 1035
LinkTopic = "Form1"
ScaleHeight = 332
ScaleMode = 3 'Pixel
ScaleWidth = 292
Top = 1155
Width = 4500
Begin CommonDialog CMDialog1
Flags = 257
Left = 0
Top = 0
End
Begin Menu mnuOption
Caption = "選擇(&O)"
Begin Menu mnuFont
Caption = "字體(&F)..."
Shortcut = ^F
End
Begin Menu mnuS1
Caption = "-"
End
Begin Menu mnuExit
Caption = "退出(&X)"
Shortcut = ^X
End
End
End
Option Explicit
Sub Form_Paint ()
Dim nAngle%
Cls
For nAngle% = 20 To 80 Step 10
ForeColor = QBColor(nAngle% / 10 - 2)
RotPrint hDC, "熱情技術(shù)技巧 旋轉(zhuǎn)字體", 10, 290, nAngle%
Next
End Sub
Sub mnuExit_Click ()
End
End Sub
Sub mnuFont_Click ()
' 初始化對(duì)話框控制
CMDialog1.FontName = FontName
CMDialog1.FontSize = FontSize
CMDialog1.FontItalic = FontItalic
CMDialog1.FontBold = FontBold
CMDialog1.FontUnderLine = FontUnderLine
CMDialog1.FontStrikeThru = FontStrikeThru
On Error GoTo ErrHandle
CMDialog1.Action = 4
' 設(shè)置窗體的字體屬性
FontName = CMDialog1.FontName
FontSize = CMDialog1.FontSize
FontItalic = CMDialog1.FontItalic
FontBold = CMDialog1.FontBold
FontUnderLine = CMDialog1.FontUnderLine
FontStrikeThru = CMDialog1.FontStrikeThru
Refresh
ErrHandle:
End Sub
Sub RotPrint (ByVal hDestDC As Integer, Text$, x As Integer, y As Integer, LineAngle As Integer)
Dim hFont As Integer, hOldFont As Integer, r%
Dim Font As LOGFONT
hOldFont = SelectObject(hDestDC, GetStockObject(SYSTEM_FONT))
GDIGetObject hOldFont, Len(Font), Font
' 填充LOGFONT結(jié)構(gòu)
Font.lfEscapement = LineAngle * 10 ' 輸出字體行與水平頁底間的角度(以1/10度為單位)
' 必須是可變點(diǎn)字體
Font.lfPitchAndFamily = Chr$(VARIABLE_PITCH Or FF_DONTCARE)
' 創(chuàng)建字體
hFont = CreateFontIndirect(Font)
' 選擇旋轉(zhuǎn)字體
r% = SelectObject(hDestDC, hFont)
' 顯示字體
TextOut hDestDC, x, y, Text$, Len(Text$)
' 恢復(fù)原字體
hFont = SelectObject(hDestDC, hOldFont)
' 刪除創(chuàng)建的字體
DeleteObject hFont
End Sub