1.建立字體handle
請(qǐng)先看CreateFont函數(shù)的原型:
- HFONT hFont = CreateFont(int nHeight,
- int nWidth,
- int nEscapement,
- int nOrientation,
- int fnWeight,
- DWORD fdwItalic,
- DWORD fdwUnderline,
- DWORD fdwStrikeOut,
- DWORD fdwCharSet,
- DWORD fdwOutputPrecision,
- DWORD fdwClipPrecision,
- DWORD fdwQuality,
- DWORD fdwPitchAndFamily,
- LPCTSTR lpszFace
- );
真嚇人,共有十四個(gè)參數(shù),盡管你能記得設(shè)定字體要有哪些參數(shù),但你也未必能記清楚每個(gè)參數(shù)的位置。CreateFont函數(shù)會(huì)傳回HFONT字體handle,這是最直接、最快、算是最易用的字體函數(shù)了。
當(dāng)中,字體高度和寬度是電腦邏輯長(zhǎng)度,可用以下公式計(jì)算:
- nHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
當(dāng)中PointSize就是字體的大小(這數(shù)字就是在Microsoft Word中設(shè)定字體大小的數(shù)字)。
你亦可跟隨Charles Petzold的計(jì)算方法,不過會(huì)比以上方法較復(fù)雜難明,但這方法也是最準(zhǔn)確的方法(能準(zhǔn)確計(jì)算字體的邏輯高度):
- FontSize = 120;
- hFont = CreateFont(
- -(int)(fabs(FontSize*GetDeviceCaps(hdc,LOGPIXELSY)/72)/10.0+0.5),
- 0,0,0,500,FALSE,FALSE,FALSE,0,0,0,0,0,"標(biāo)楷體");
- SelectObject(hdc,hFont);
- TextOut(hdc,100,100,"標(biāo)楷體12點(diǎn)字體",8);
- DeleteObject(SelectObject(hdc,hFont);
從以上例子可見,我們建立了十二點(diǎn)、中等粗細(xì)、非斜體、沒加底線、沒加刪線的「標(biāo)楷體」向量字型,利用 (點(diǎn)數(shù) x 10 x 系統(tǒng)邏輯高度 / 72 + 0.5) 的絕對(duì)整數(shù)值 這公式就能計(jì)算字體的實(shí)際顯示大小。
另外,我們利用SelectObject來載入字體handle,以后的文字輸出均以該字體顯示,直至DeleteObject為止,我們絕大部份時(shí)間都以上述程式碼來設(shè)定字體。
第二種呼叫字體的方法
我們有CreateFont函數(shù),亦有CreateFontIndirect函數(shù)來間接建立字體,但別以為這函數(shù)能簡(jiǎn)化你呼叫字體的步驟,這函數(shù)只可讓你填入字體的外觀資料到LOGFONT結(jié)構(gòu)體,才建立字體,而不需直接把十四個(gè)參數(shù)輸入CreateFont,先看看LOGFONT結(jié)構(gòu):
- LOGFONT {
- LONG lfHeight;
- LONG lfWidth;
- LONG lfEscapement;
- LONG lfOrientation;
- LONG lfWeight;
- BYTE lfItalic;
- BYTE lfUnderline;
- BYTE lfStrikeOut;
- BYTE lfCharSet;
- BYTE lfOutPrecision;
- BYTE lfClipPrecision;
- BYTE lfQuality;
- BYTE lfPitchAndFamily;
- TCHAR lfFaceName[LF_FACESIZE];
- }
十四個(gè)參數(shù)一個(gè)不漏地呈現(xiàn)在LOGFONT結(jié)構(gòu)中,把資料填入這結(jié)果,然后呼叫CreateFontIndirect就行了:
- LOGFONT lf;
- HFONT hFont;
- ...
- ...
- hFont = CreateFontIndirect(&lf);
LOGFONT結(jié)構(gòu)詳解
在此,我們不妨說說LOGFONT結(jié)構(gòu)。剛才也說明過lfHeight是邏輯高度,而lfWidth就是邏輯寬度,需要呼叫GetDeviceCaps來取得屏幕的DPI(每一吋有多少pixel),通常我們都會(huì)把lfWidth置零,置零代表字體寬度會(huì)跟隨lfHeight來調(diào)整,以取得最合適最美觀的長(zhǎng)寬比例,當(dāng)然你也可以自行設(shè)定lfWidth。
lfEscapement是字體斜度,以0.1度位單位,這角度是escapement vector和X軸的角度,而escapement vector是平行于底線的。與lfEscapement一樣,lfOrientation也是設(shè)定斜度,應(yīng)與lfEscapement的設(shè)定值一樣(但在Windows NT/2000上,若繪圖模式被設(shè)定為GM_ADVANCED,Orientation和Escapement是兩回事,由于涉及復(fù)雜計(jì)計(jì)算,在此不作詳談)。
lfWeight是字體粗細(xì),由0至900,其設(shè)定值必需為100的倍數(shù),一般來說400是正常粗細(xì),而700就是粗體,若該值設(shè)為0則代表以預(yù)計(jì)粗細(xì)顯示文字。
隨后的三個(gè)值lfItalic、lfUnderline、lfStrikeOut就是Microsoft Word讓使用者設(shè)定為斜體、加底線和加刪線的功能,填入TRUE則開啟選項(xiàng),F(xiàn)ALSE則關(guān)閉。
lfCharSet則讓人設(shè)定字元集,例如我們想顯示簡(jiǎn)體字,就會(huì)設(shè)定為GB2312_CHARSET,希臘符號(hào)就設(shè)定為SYMBOL_CHARSET,大五碼為CHINESEBIG5_CHARSET,ANSI為ANSI_CHARSET等等,若本值設(shè)零則為DEFAULT_CHARSET,預(yù)設(shè)值在中文視窗中是CHINESEBIG5_CHARSET。
lfOutPrecision是設(shè)定字型顯示的精確度,當(dāng)大家設(shè)定了繁體的字體斜度粗細(xì)之后,精密的raster operation總會(huì)有點(diǎn)差錯(cuò),這些差錯(cuò)可以靠修正部份字體設(shè)定來減輕,但不能消除,這時(shí)候你要決定舍棄字體的輪廓還是清晰度。因?yàn)槲覀冇玫亩际荰TF,所以我們都會(huì)把此值設(shè)為0,在TTF的世界不需要考慮字型會(huì)失真。
lfClipPrecision是設(shè)定部份字型被其他圖像或框架覆蓋時(shí)的顯示精確度,和lfOutPrecision一樣,我們一般都把此值設(shè)0。
lfQuality就關(guān)系到TTF,這是決定GDI處理字體顯示的精確度,與字體的性質(zhì)無關(guān),在大部份情況也會(huì)設(shè)0代表使用預(yù)設(shè)值,我們也可設(shè)為PROOF_QUALITY使字體顯示更精確,但運(yùn)算時(shí)間也較長(zhǎng);你也可算擇DRAFT_QUALITY來取得最乎合比例的字型,運(yùn)算時(shí)間亦較短(別以為字體的運(yùn)算時(shí)間是多不重要,大家用過Windows 2000的Notepad后就會(huì)認(rèn)同我這番話)。
lfPitchAndFamily設(shè)定字型的端點(diǎn)和字系,假若你所選擇的字體并未能在你的電腦上找到,這個(gè)參數(shù)就會(huì)找出補(bǔ)充語系來顯示所需文字。
請(qǐng)留意,絕大部份情況下,我們都不需要刻意設(shè)定lfCharSet、lfOutPrecision、lfClipPrecision、lfQuality和lfPitchAndFamily,我們把它設(shè)為0或預(yù)計(jì)值便可
|