?? 4.輸出文字.txt
字號(hào):
字符大小
要用TextOut顯示多行文字,就必須確定字體的字符大小,可以根據(jù)字符的高度來定位字符的后續(xù)行,以及根據(jù)字符的寬度來定位字符的后續(xù)列。
系統(tǒng)字體的字符高度和平均寬度是多少?這個(gè)問題取決于視訊顯示器的圖素大小。Windows需要的最小顯示大小是640×480,但是許多使用者更喜歡800×600或1024×768的顯示大小。另外,對(duì)于這些較大的顯示尺寸,Windows允許使用者選擇不同大小的系統(tǒng)字體。
程序可以呼叫GetSystemMetrics函數(shù)以取使用者接口上各類視覺組件大小的信息,呼叫GetTextMetrics取得字體大小。GetTextMetrics傳回設(shè)備內(nèi)容中目前選取的字體信息,因此它需要設(shè)備內(nèi)容句柄。Windows將文字大小的不同值復(fù)制到在WINGDI.H中定義的TEXTMETRIC型態(tài)的結(jié)構(gòu)中。TEXTMETRIC結(jié)構(gòu)有20個(gè)字段,我們只使用前七個(gè):
typedef struct tagTEXTMETRIC
{
LONG tmHeight ;
LONG tmAscent ;
LONG tmDescent ;
LONG tmInternalLeading ;
LONG tmExternalLeading ;
LONG tmAveCharWidth ;
LONG tmMaxCharWidth ;
其它結(jié)構(gòu)字段
}
TEXTMETRIC, * PTEXTMETRIC ;
這些字段值的單位取決于選定的設(shè)備內(nèi)容映像方式。在內(nèi)定設(shè)備內(nèi)容下,映像方式是MM_TEXT,因此值的大小是以圖素為單位。
要使用GetTextMetrics函數(shù),需要先定義一個(gè)結(jié)構(gòu)變量(通常稱為tm):
TEXTMETRIC tm ;
在需要確定文字大小時(shí),先取得設(shè)備內(nèi)容句柄,再呼叫GetTextMetrics:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
ReleaseDC (hwnd, hdc) ;
此后,您就可以查看文字尺寸結(jié)構(gòu)中的值,并有可能保存其中的一些以備將來使用。
文字大小:細(xì)節(jié)
TEXTMETRIC結(jié)構(gòu)提供了關(guān)于目前設(shè)備內(nèi)容中選用的字體的豐富信息。但是,字體的縱向大小只由5個(gè)值確定,其中4個(gè)值如圖4-3所示。
圖4-3 定義字體中縱向字符大小的4個(gè)值
最重要的值是tmHeight,它是tmAscent和tmDescent的和。這兩個(gè)值表示了基準(zhǔn)在線下字符的最大縱向高度。「間距」(leading)指打印機(jī)在兩行文字間插入的空間。在TEXTMETRIC結(jié)構(gòu)中,內(nèi)部的間距包括在tmAscent中(因此也在tmHeight中),并且它經(jīng)常是重音符號(hào)出現(xiàn)的地方。tmInternalLeading字段可被設(shè)成0,在這種情況下,加重音的字母會(huì)稍稍縮短以便容納重音符號(hào)。
TEXTMETRIC結(jié)構(gòu)還包括一個(gè)不包含在tmHeight值中的字段tmExternalLeading。它是字體設(shè)計(jì)者建議加在橫向字符之間的空間大小。在安排文字行之間的空隙時(shí),您可以接受設(shè)計(jì)者建議的值,也可以拒絕它。在系統(tǒng)字體中tmExternalLeading可以為0,因此我沒有在圖4-3中顯示它。(盡管我不想告訴你們,圖4-3確實(shí)就是Windows在640×480的顯示分辨率中使用的系統(tǒng)字體。)
TEXTMETRICS結(jié)構(gòu)包含有描述字符寬度的兩個(gè)字段,即tmAveCharWidth(小寫字母加權(quán)平均寬度)和tmMaxCharWidth(字體中最寬字符的寬度)。對(duì)于定寬字體,這兩個(gè)值是相等的(圖4-3中這些值分別為7和14)。
本章的范例程序還需要另一種字符寬度,即大寫字母的平均寬度,這可以用tmAveCharWidth乘以150%大致計(jì)算出來。
必須認(rèn)識(shí)到,系統(tǒng)字體的大小取決于Windows所執(zhí)行的視訊顯示器的分辨率,在某些情況下,取決于使用者選取的系統(tǒng)字體的大小。Windows提供了一個(gè)與設(shè)備無(wú)關(guān)的圖形接口,但程序?qū)懽髡哌€是有事情要處理的。不要想當(dāng)然耳地猜測(cè)字體大小來寫作Windows程序,也不要把值定死,您可以使用GetTextMetrics函數(shù)取得這一信息。
格式化文字
Windows啟動(dòng)后,系統(tǒng)字體的大小就不會(huì)發(fā)生改變,所以在程序執(zhí)行過程中,程序?qū)懽髡咧恍枰艚幸淮蜧etTexMetrics。最好是在窗口消息處理程序中處理WM_CREATE消息時(shí)進(jìn)行此呼叫,WM_CREATE消息是窗口消息處理程序接收的第一個(gè)消息。在WinMain中呼叫CreateWindow時(shí),Windows會(huì)以一個(gè)WM_CREATE消息呼叫窗口消息處理程序。
假設(shè)要編寫一個(gè)Windows程序,在顯示區(qū)域顯示幾行文字,這需要先取得字符寬度和高度。您可以在窗口消息處理程序內(nèi)定義兩個(gè)變量來保存平均字符寬度(cxChar)和總的字符高度(cyChar):
static int cxChar, cyChar ;
變量名的前綴c代表「count」,在這里指圖素?cái)?shù),與x和y結(jié)合,分別指寬和高。這些變量定義為static靜態(tài)變量,因?yàn)樗鼈冊(cè)诖翱谙⑻幚沓绦蛑刑幚砥渌ⅲㄈ鏦M_PAINT)時(shí)也應(yīng)該是有效的。如果變量在函數(shù)外面定義,則不需要定義為static。
下面是取得系統(tǒng)字體的字符寬度和高度的WM_CREATE程序代碼:
case WM_CREATE:
hdc = GetDC (hwnd) ;
GetTextMetrics (hdc, &tm) ;
cxChar = tm.tmAveCharWidth ;
cyChar = tm.tmHeight + tm.tmExternalLeading ;
ReleaseDC (hwnd, hdc) ;
return 0 ;
注意我在計(jì)算cyChar時(shí)包括了tmExternalLeading字段,雖然該字段在系統(tǒng)字體中為0,但是因?yàn)樗沟梦淖值目勺x性更好,所以還是應(yīng)該把它包括進(jìn)去。沿著窗口向下每隔cyChar圖素就會(huì)顯示一行文字。
您會(huì)發(fā)現(xiàn)常常需要顯示格式化的數(shù)字跟簡(jiǎn)單的字符串。我在第二章講到過,您不能使慣用的工具(可愛的printf函數(shù))來完成這項(xiàng)工作,但是可以使用sprintf和Windows版的sprintf-wsprintf。這些函數(shù)與printf相似,只是把格式化字符串放到字符串中。然后,可以用TextOut將字符串輸出到顯示器上。非常方便的是,從sprintf和wsprintf傳回的值就是字符串的長(zhǎng)度。您可以將這個(gè)值傳遞給TextOut作為iLength參數(shù)。下面的程序代碼顯示了wsprintf與TextOut的典型組合:
int iLength ;
TCHAR szBuffer [40] ;
其它行程序
iLength = wsprintf (szBuffer, TEXT ("The sum of %i and %i is %i"),
iA, iB, iA + iB) ;
TextOut (hdc, x, y, szBuffer, iLength) ;
對(duì)于這樣簡(jiǎn)單的情況,可以將nLength的定義值與TextOut放在同一條敘述中,從而無(wú)需定義iLength:
TextOut (hdc, x, y, szBuffer,
wsprintf (szBuffer, TEXT ("The sum of %i and %i is %i"),
iA, iB, iA + iB)) ;
雖然這樣子寫起來不好看,但是功能與前者是一樣的。
綜合使用
現(xiàn)在,我們似乎已經(jīng)具備了在屏幕上顯示多行文字所需要的所有知識(shí)。我們知道如何在WM_PAINT消息處理期間取得一個(gè)設(shè)備內(nèi)容句柄,如何使用TextOut函數(shù)以及如何根據(jù)字符大小來安排字距,剩下的就是顯示一點(diǎn)有意義的東西了。
在前一章里,我們大概知道從Windows的GetSystemMetrics函數(shù)中取得的信息是很有意義的,該函數(shù)傳回Windows中不同視覺組件的大小信息,如圖標(biāo)、光標(biāo)、標(biāo)題列和滾動(dòng)條等。它們的大小因顯示卡和驅(qū)動(dòng)程序的不同而有所不同。GetSystemMetrics是在程序中完成與設(shè)備無(wú)關(guān)圖形輸出的重要函數(shù)。
該函數(shù)需要一個(gè)參數(shù),叫做「索引」,在Windows表頭文件定義了75個(gè)整數(shù)索引標(biāo)識(shí)符(標(biāo)識(shí)符的數(shù)量隨著每個(gè)版本的Windows的發(fā)布而不斷地增加,在Windows 1.0的程序?qū)懽髡呶募袃H列出了26個(gè))。GetSystemMetrics傳回一個(gè)整數(shù),這個(gè)整數(shù)通常就是參數(shù)中指定的圖形組件大小。
讓我們來編寫一個(gè)程序,顯示一些可以從GetSystemMetrics呼叫中取得的信息,顯示格式為每種視覺組件一行。如果我們建立一個(gè)表頭文件,在表頭文件中定義一個(gè)結(jié)構(gòu)數(shù)組,此結(jié)構(gòu)包含GetSystemMetrics索引對(duì)應(yīng)的Windows表頭文件標(biāo)識(shí)符和呼叫所傳回的每個(gè)值對(duì)應(yīng)的字符串,這樣處理起來要容易一些。表頭文件名為SYSMETS.H,如程序4-1所示。
程序4-1 SYSMETS.H
/*---------------------------------------------------------
SYSMETS.H -- System metrics display structure
-----------------------------------------------------------*/
#define NUMLINES ((int) (sizeof sysmetrics / sizeof sysmetrics [0]))
struct
{
int Index ;
TCHAR * szLabel ;
TCHAR * szDesc ;
}
sysmetrics [] =
{
SM_CXSCREEN, TEXT ("SM_CXSCREEN"),
TEXT ("Screen width in pixels"),
SM_CYSCREEN, TEXT ("SM_CYSCREEN"),
TEXT ("Screen height in pixels"),
SM_CXVSCROLL, TEXT ("SM_CXVSCROLL"),
TEXT ("Vertical scroll width"),
SM_CYHSCROLL, TEXT ("SM_CYHSCROLL"),
TEXT ("Horizontal scroll height"),
SM_CYCAPTION, TEXT ("SM_CYCAPTION"),
TEXT ("Caption bar height"),
SM_CXBORDER, TEXT ("SM_CXBORDER"),
TEXT ("Window border width"),
SM_CYBORDER, TEXT ("SM_CYBORDER"),
TEXT ("Window border height"),
SM_CXFIXEDFRAME,TEXT ("SM_CXFIXEDFRAME"),
TEXT ("Dialog window frame width"),
SM_CYFIXEDFRAME,TEXT ("SM_CYFIXEDFRAME"),
TEXT ("Dialog window frame height"),
SM_CYVTHUMB, TEXT ("SM_CYVTHUMB"),
TEXT ("Vertical scroll thumb height"),
SM_CXHTHUMB, TEXT ("SM_CXHTHUMB"),
TEXT ("Horizontal scroll thumb width"),
SM_CXICON, TEXT ("SM_CXICON"),
TEXT ("Icon width"),
SM_CYICON, TEXT ("SM_CYICON"),
TEXT ("Icon height"),
SM_CXCURSOR, TEXT ("SM_CXCURSOR"),
TEXT ("Cursor width"),
SM_CYCURSOR, TEXT ("SM_CYCURSOR"),
TEXT ("Cursor height"),
SM_CYMENU, TEXT ("SM_CYMENU"),
TEXT ("Menu bar height"),
SM_CXFULLSCREEN,TEXT ("SM_CXFULLSCREEN"),
TEXT ("Full screen client area width"),
SM_CYFULLSCREEN,TEXT ("SM_CYFULLSCREEN"),
TEXT ("Full screen client area height"),
SM_CYKANJIWINDOW,TEXT ("SM_CYKANJIWINDOW"),
TEXT ("Kanji window height"),
SM_MOUSEPRESENT, TEXT ("SM_MOUSEPRESENT"),
TEXT ("Mouse present flag"),
SM_CYVSCROLL,TEXT ("SM_CYVSCROLL"),
TEXT ("Vertical scroll arrow height"),
SM_CXHSCROLL,TEXT ("SM_CXHSCROLL"),
TEXT ("Horizontal scroll arrow width"),
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -