CFont
CFont
CFont類封裝了一個Windows圖形設備介面(GDI)字體,並為操作字體提供了成員函數。
Windows提供了多種與設備無關的不同尺寸的字體。有效地使用這些Windows字體,不用在編程時下很大功夫,就可以明顯地增強各種應用程序的功能。字體是Windows GDI必要的組成部分,這意味字體的使用與其他GDI對象一樣。它們可以縮放和剪切,可以像選取畫筆或者畫刷一樣選取設備環境。所有關於撤消選中和刪除的GDI規則都適用於字體。
為了使用CFont對象,首先構造一個CFont對象,再通過調用CreateFont、CreateFontIndirect、CreatePointFont或CreatePointFontIndirect使一個Windows字體與此CFont對象關聯,然後使用此CFont對象的成員函數就可以操作字體了。
一般使用CreatePointFont或CreatePointFontIndirect比使用CreateFont或CreateFontIndirect要更簡便,因為前兩者會自動的把字體高度的單位由點轉換為邏輯單位。
註:“點”是傳統計量字大小的單位,是從英文Point來的,註:“點”是傳統計量字大小的單位,是從英文Point來的,一般用小寫p表示,俗稱“磅”。其換算關係為:1p=0.35146mm≈0.35mm,1英寸=72p。一般用小寫p表示,俗稱“磅”。其換算關係為:1p=0.35146mm≈0.35mm,1英寸=72p。
1、CFont( );
構造一個CFont對象。此對象在使用之前應該先使用CreateFont、CreateFontIndirect、CreatePointFont或CreatePointFontIndirect初始化。
1、
BOOL CreateFont(
int nHeight,
int nWidth,
int nEscapement,
int nOrientation,
int nWeight,
BYTE bItalic,
BYTE bUnderline,
BYTE cStrikeOut,
BYTE nCharSet,
BYTE nOutPrecision,
BYTE nClipPrecision,
BYTE nQuality,
BYTE nPitchAndFamily,
LPCTSTR lpszFacename
);
通過指定的一些特徵初始化CFont對象。下面分別介紹每個參數:
nHeight:指定字體高度(邏輯單位)。有三種取值:>0,字體映射器將高度值轉換為設備單位,並與可用字體的字元元高度進行匹配;=0,字體映射器使用默認的高度值;<0,字體映射器將高度值轉換為設備單位,用其絕對值與可用字體的字元高度進行匹配。nHeight轉換后的絕對值不應超過16384個設備單位。
nWidth:指定字體中字元的平均寬度(邏輯單位)。
nEscapement:指定偏離垂線和顯示界面X軸之間的角度,以十分之一度為單位。偏離垂線是穿過一行文本中第一個字元和最後一個字元的直線。
nOrientation:指定每個字元的基線和設備X軸之間的角度,以十分之一度為單位。
nWeight:指定字體磅數(每1000點中墨點像素數)。可取0到1000之間的任意整數值。
bItalic:指定字體是否為斜體。
bUnderline:指定字體是否帶有下劃線。
bStrikeOut:指定字體是否帶有刪除線。
nCharSet:指定字體的字符集。預定義的字符集:
ANSI_CHARSET;BALTIC_CHARSET;CHINESEBIG5_CHARSET;DEFAULT_CHARSET;EASTEUROPE_CHARSET; GB2312_CHARSET; GREEK_CHARSET;HANGUL_CHARSET; MAC_CHARSET; OEM_CHARSET; RUSSIAN_CHARSET; SHIFTJIS_CHARSET;SYMBOL_CHARSET; TURKISH_CHARSET。韓國Windows:JOHAB_CHARSET;中東地區Windows:HEBREW_CHARSSET,ARABIC_CHARSET;泰國Windows:THAI_CHARSET。應用程序可以使用DEFAULT_CHARSET以允許字體名和大小完全指定邏輯字體,如果指定的字體名不存在則可能會用任意字符集的字體來代替,所以為避免不可預料的結果,應謹慎使用DEFAULT_CHARSET。
nOutPrecision:指定輸出精度。輸出精度定義了輸出與要求的字體高度、寬度、字元方向、移位和間距等的接近程度。它的取值及含義如下(只能取其一):
OUT_CHARACTER_PRECIS;未用。
OUT_DEFAULT_PRECIS:指定預設的字體映射器狀態。
OUT_DEVICE_PRECIS:在當系統里有多種字體使用同一個名字時指示字體映射器選擇一種設備字體。
OUT_OUTLINE_PRCIS:在Windows NT中此值指示字體映射器從TrueType和其他基於邊框的字體中選擇。
OUT_RASTER_PRECIS:在當系統里有多種字體使用同一個名字時指示字體映射器選擇一種光柵字體。
OUT_STRING_PRECIS:此值沒有被字體映射器使用,但是當列舉光柵字體時它會被返回。
OUT_STROKE_PRECIS:沒有被字體映射器使用,但是當列舉TrueType字體、其他基於邊框的字體和向量字體時它會被返回。
OUT_TT_ONLY_PRECIS:指示字體映射器僅從TrueType字體中選擇,如果系統中沒有安裝TrueType字體,則字體映射返回預設狀態。
OUT_TT_PRECIS:在當系統里有多種同名的字體時指示字體映射器選擇一種TrueType字體。當操作系統含有多種與指定名字同名的字體時,應用程序可以使用OUT_DEVICE_PRECIS,OUT_RASTER_PRECIS和OUT_TT_PRECIS值來控制字體映射器如何選擇一種字體,例如,如果操作系統含有名字Symbol的光柵和TrueType兩種字體,指定OUT_TT_PRECIS使字體映射器選擇TrueType方式(指定OUT_TT_ONLY_PRECIS強制字體映射器選擇一種TrueType字體,儘管這會給TrueType字體換一個名字)。
nClipPrecision:指定裁剪精度。裁剪精度定義了怎樣裁剪部分超出裁剪區域的字元。它的取值及含義如下(可取一個或多個值):
CLIP_DEFAULT_PRECIS:指定預設裁剪狀態。
CLIP_CHARACTER_PRECIS:未用。
CLIP_STROKE_PRECIS:未被字體映射器使用,但是當列舉光柵字體、向量字體或TrueType字體時它會被返回。在Windows環境下,為保證兼容性,當列舉字體時這個值總被返回。
CLIP_MASK:未用。
CLIP_EMBEDDED:要使用嵌入式只讀字體必須使用此標誌。
CLIP_LH_ANGLES:當此值被使用時,所有字體的旋轉依賴於坐標系統的定位是朝左的還是朝右的。如果未使用此值,設備字體總是逆時針方向旋轉,但其他字體的旋轉依賴於坐標系統的定向。
CLIP_TT_ALWAYS:未用。
nQuality:指定字體的輸出質量。輸出質量定義了GDI將邏輯字體屬性匹配到實際物理字體的細緻程度。它的各個取值及含義如下(取其一):
DEFAULT_QUALITY:字體的外觀不重要。
DRAFT_QUALITY:字體外觀的重要性次於使用PROOF_QUALITY時,對GDI光柵字體,縮放比例是活動的,這意味著多種字體大小可供選擇,但質量可能不高,如果有必要,粗體、斜體、下劃線、strikeout字體可被綜合起來使用。
PROOF_QUALITY:字元質量比精確匹配邏輯字體字體屬性更重要。對GDI掃描字體,縮放比例是活動的,並選擇最接近的大小。儘管當使用PROOF_QUALITY時,選擇字體大小並不完全匹配,但字體的質量很高,並沒有外觀上的變形。如果有必要,粗體、斜體、下劃線、strikeout字體可被綜合起來使用。
nPitchAndFamily:指定字體間距和字體族。低2位用來指定字體的間距,可取下列值中的一個:DEFAULT_PITCH,FIXED_PITCH,VARIABLE_PITCH。高4位指定字體族,取值及含義如下(取其一):
FF_DECORATIVE:新奇的字體,如老式英語(Old English)。
FF_DONTCARE:不關心或不知道。
FF_MODERN:筆劃寬度固定的字體,有或者無襯線。如Pica、Elite和Courier New。
FF_ROMAN:筆劃寬度變動的字體,有襯線。如MS Serif。
FF_SCRIPT:設計成看上去象手寫體的字體。如Script和Cursive。
FF_SWISS:筆劃寬度變動的字體,無斜線。如MS Sans Serif。
應用程序可以用運算符OR將字元間距和字體族組合起來給nPitchAndFamily賦值。
字體族描述一種字體的普通外觀,當所有的精確字樣都不能使用時,可用它們來指定字體。
lpszFacename:指定字體的字樣名的字元串。此字元串的長度不應超過30個字元。Windows函數EnumFontFamilies可以枚舉出當前所有可用字體的字樣名。如果lpszFacename為NULL,則GDI使用一種與設備無關的字體。
返回值:此函數成功則返回TRUE,否則返回FALSE。
CreateFont函數初始化CFont對象后,此字體就能夠被選作任何設備上下文的字體了。此函數並不會創建一個新的Windows GDI字體,只是從GDI的物理字體中選擇了一個最匹配的字體。在創建一個邏輯字體時,大部分參數可以使用默認值,但一般情況下都會給出參數nHeight和lpszFacename的指定值,如果沒有給nHeight和lpszFacename參數設定取值,則創建的邏輯字體與設備相關。當使用CreateFont函數初始化一個CFont對象完成後,就能夠使用CDC::SelectObject函數來為設備上下文選擇字體了,並且還能夠在不再使用此CFont對象時刪除它。
2、BOOL CreateFontIndirect(const LOGFONT* lpLogFont);
通過一個LOGFONT結構體變數給出的特徵來初始化CFont對象。參數lpLogFont是指向LOGFONT結構體變數的指針,此LOGFONT結構體變定義了邏輯字體的特徵。LOGFONT結構體的定義可以參見VS2010/MFC編程入門之十八(對話框:字體對話框)。
3、BOOL CreatePointFont(int nPointSize,LPCTSTR lpszFaceName,CDC* pDC = NULL);
此函數提供了一種由指定字樣和點數創建字體的簡單方式。參數的意義如下:
nPointSize:指定字體高度,以十分之一點為單位。例如,nPointSize為120則表示是12點的字體。
pDC:指向CDC對象,用來將nPointSize指定的高度轉換為邏輯單位,如果為NULL,則使用屏幕設備上下文進行轉換。
4、BOOL CreatePointFontIndirect(const LOGFONT* lpLogFont,CDC* pDC = NULL);
此函數是通過指定的字樣和點數創建字體的間接方式。參數lpLogFont指向一個LOGFONT結構體變數,此LOGFONT變數定義了邏輯字體的特徵,它的lfHeight成員以十分之一點為單位,而不是邏輯單位。參數pDC指向CDC對象,用來將lfHeight表示的高度轉換為邏輯單位,如果為NULL,則使用屏幕設備上下文進行轉換。
此函數與CreateFontIndirect很相似,但區別是LOGFONT變數中lfHeight成員的單位是十分之一點而不是邏輯單位。
由Windows GDI字體的HFONT句柄獲得相應的CFont對象指針。參數hFont是一個Windows字體的HFONT句柄。成功則返回CFont對象的指針,否則返回NULL。
1、int GetLogFont(LOGFONT * pLogFont);
獲取CFont對象的LOGFONT結構體的拷貝。參數pLogFont指向用來接收字體信息的LOGFONT結構體變數。成功則返回非零值,否則返回零。
(一)顯示傾斜的文字
上文中的圖一顯示了通過顯示一系列的傾斜字元串來實現環繞顯示的效果,下面來詳細說明如何實現這個效果。
實現上述的效果其實很容易,只要使用CFONT類和LOGFONT結構來靈活的創建字體,設置字體的屬性,就可以實現傾斜文字的效果。LOGFONT結 構中包含了所要創建的字體中的全部信息,其中的ifEscapement 成員制定了所創建的字體與水平方向所傾斜的角度,需要讀者注意的是該成員變數角度的單位是十分之一度而不是度,例如,如果ifEscapement定義為 450,它表示字體的傾斜角度為45度。為了保證所有的字體按照一個方向旋轉,一定要設置ifEscapenent的CLIP_LH_ANGLES位,否 則字體有可能向反方向旋轉。
如同使用其它GDI(圖形用戶界面介面)對象一樣,在使用你定義的字體以前,必須要將創建的字體選入DC中(設備上下文)。
(二)實現3D文字
計算機屏幕是平面二維的,我們之所以能欣賞到真如實物般的三維圖像,是因為顯示在計算機屏幕上時色彩灰度的不同而使人眼產生視覺上的錯覺,而將二維的計 算機屏幕感知為三維圖像。基於色彩學的有關知識,三維物體邊緣的凸出部分一般顯高亮度色,而凹下去的部分由於受光線的遮擋而顯暗色。這一認識被廣泛應用於 網頁或其他應用中對按鈕、3D線條的繪製。對於本文所要繪製的3D文字同樣也適用,即在原始位置顯示高亮度顏色,而在左下或右上等位置用低亮度顏色勾勒出 其輪廓,這樣在視覺上便會產生3D文字的效果。具體實現時,可用完全一樣的字體在不同的位置分別繪製兩個不同顏色的2D文字,只要使兩個文字的坐標合適,就完全可以在視覺上產生出不同效果的3D文字。
具體實現的思想是通過CDC::SetTextColor()分別設置文字的顏色為高亮(3DHILIGHT)和陰影(3DSHADOW)的狀態下顯示文字;同時注意在兩次顯示文字時要錯開幾個像素,這樣才能達到預期的效果。實現的效果上文的圖二所示。
(三)文字的漸變效果
為了實現文字的漸變效果,需要設置一個定時器(使用SetTimer()函數),在定時器響應函數處理過程中,通過調用CDC: SetTextColor()函數不斷改變設備上下文中文本的顯示顏色,從而實現文字的漸變效果。文本的顏色是通過RGB(紅、綠、蘭)三種基本顏色的混 合所形成的最終結果,RGB三基色的變化範圍都是(0,255),R=G=B時,顏色的效果是灰色的,所謂灰色,就是在純白和純黑之間的一種過渡色,當R =G=B=0時,顏色為黑色,當R=G=B=255時,顏色為純白色,可以定義一個修正變數,不斷的對該三基色進行遞增或遞減,從而實現文字的漸變顯示。這裡僅僅給出實現的思路,讀者自己可以很容易的實現代碼。
(四)其它
另外,還可以通過設置路徑對象來對普通的文字進行輪廓勾勒,使之具備特殊的效果。路徑是Win32中新增的一個GDI對象,下面先從概念上談起。
1)路徑的概念
在Windows 95/NT 這樣的Win32操作系統中,除了已有的點陣圖,畫筆,畫刷,字體,調色板和區域之外,還增加了一個新的GDI對象:路徑。路徑是可以被填充,畫出輪廓或同 時被畫出輪廓並填充的一個或多個圖形。路徑的引入,大大地豐富了Windows的圖形功能,使得應用程序可以方便地建立複雜區域,繪製和填充不規則圖形。這裡說的不規則圖形是指由直線和貝塞爾曲線組成的圖形(相對於矩形,多邊形,橢圓等規則圖形)。
2)路徑的使用
與其它原有的GDI對象不同的是,MFC類庫沒有專門用一個C++類來封裝路徑對象(或許在以後的版本中會得到支持)。有關路徑的定義和使用等各種操作都必須通過調用API函數(或CDC類中對應的成員函數)來實現。路徑的使用過程大致如下:
(1)調用BeginPath()函數開始路徑定義;
(2)調用GDI繪圖函數來定義路徑;在Win32中,可以用於定義路徑的GDI繪圖函數包括:AngleArc()、 Arc()、 ArcToChord()、Ellipse ()、LineTo()、TextOut()等函數;
(3)調用EndPath()函數結束路徑定義;
完成路徑定義后,所定義的路徑即被同時選進設備描述表,設備描述表中原有的路徑對象在調用BeginPath()函數開始路徑定義時即被廢棄。
(4)使用路徑對象。
完成路徑定義工作之後,應用程序便可以利用有關GDI函數來使用路徑,這些函數包括繪製路徑輪廓StrokePath(),填充路徑FillPath (),繪製輪廓並填充StrokeAndFillPath(),把路徑轉換成區域PathToRegion(),把路徑直線化FlattenPath (),提取路徑數據GetPath(),加寬路徑WidenPath()和設置裁剪路徑SelectClipPath()等。這些函數的具體使用方法可參 閱有關的SDK文檔。
下面的代碼演示了如何實現字體的空心效果
////////////////////////////////////// 應用程序主窗口的重繪函數
void CMyWnd::OnPaint()
{
// 獲得窗口的客戶區設備上下文句柄
CPaintDC dc(this); // 更改當前字體
LOGFONT lf;
dc.GetCurrentFont()- >GetLogFont(&lf);
CFont font;
CFont *pOldFont; // 保存設備上下文最初使用的字體對象
lf.lfCharSet=134;
lf.lfHeight=-150;
lf.lfHeight=-150;
lf.lfWidth=0;
strcpy(lf.lfFaceName, "隸書");
font.CreateFontIndirect( &lf);
pOldFont=dc.SelectObject( &font);
dc.SetBkMode(TRANSPARENT); // 更改當前畫筆
CPen pen(PS_SOLID, 1, RGB(255, 0, 0));
CPen *pOldPen;
pOldPen=dc.SelectObject( &pen); // 開始一個路徑
dc.BeginPath();
dc.TextOut(10, 10, "空心字");
dc.EndPath(); // 繪製路徑
dc.StrokePath();
//可以用dc.StrokeAndFillPath()函數來代替,不過該函數會使用當前刷子填充路徑的內部。
dc.SelectObject(pOldFont);
dc.SelectObject(pOldPen);
}