?? 10.4 字體對話框.txt
字號:
10.4 字體對話框
下面為 Graphic程序添加字體對話框應用,該對話框類似于我們已經在對話框資源的屬性對話框中
所看到的字體對話框,如圖 10.15所示。
與上面的顏色對話框一樣,字體對話框的創建也很簡單,因為 MFC也提供了一個相應的類 :
CFontDialog.該類的派生層次結構如圖 10.16所示,由此可知該類派生于 CDialog.所以,其也是一
個對話框類。
圖 10.15字體對話框
CFontDialog類的構造函數如下所示:
CFontDialog(
LPLOGFONT lplflnitial = NULL ,
DWORD dwFlags = CF_EFFECTS I CF_SCREENFONTS ,
CDC* pdcprinter = NULL ,
CWnd* pParentWnd = NULL
.
該函數有四個參數,含義分別如下所述:
. lpltinitial
指向LOGFONT結構體的指針,允許用戶設置一些字體的特征。
. dwFlags
主要設置一個或多個與選擇的字體相關的標記。
. pdcPrinter
指向打印設備上下文的指針。
. pParentWnd
指向字體對話框父窗口的指針。
由 CFontDialog類的構造函數的聲明可知,它的參數都有默認值,因此在構造字體對話框時可以不
用指定任何參數。
字體對話框的創建與前面的顏色對話框的一樣,首先構造一個字體對話框對象,然后調用該對象的
DoModal函數顯示這個對話框即可。因此再為Graphic程序增加一個菜單項用來顯示字體對話框,將
其ID設置為: IDM_FONT, Caption設置為:字體。接著為其增加一個命令響應,并選擇 CGraphicView
類對此菜單項命令做出響應。然后在此響應函數
中添加創建井顯示字體對話框的代碼,結果如例 10-19所示。
例10-19
圖 10.16 CFontDialog類的派生層次結構圖
void CGraphicview: :OnFont()
CFontDialog dlg;
dlg.DoModal() ;
下面我們要實現這樣的功能:當用戶通過字體對話框選擇某種字體后,程序應該把當
前選擇保存起來,然后在 CGraphicView類中利用此字體將用戶選擇的字體名稱顯示出來。例如如果
用戶選擇的是黑體,那么在程序中就創建黑體這種字體,再利用這種字體把字體名稱:"黑體"顯示出
來。
CFontDialog類有一個 CHOOSEFONT結構體類型的數據成員: m_cf CHOOSEFONT 結構體的定義如例
10-20所示。
例 10-20
typedef struct { DWORD lStructSizei HWND hwndOwner i HDC hDCi LPLOGFONT lpLogFonti INT
iPointSizei DWORD Flagsi COLORREF rgbColorsi LPARAM lCustDatai LPCFHOOKPROC lpfnHooki
LPCTSTR lpTemplateNamei HINSTANCE hlnstancei LPTSTR lpszStylei WORD nFontTypei 工 NT
nSizeMini 工 NT nSizeMaxi
1 CHOOSEFONT, *LPCHOOSEFONTi
其中成員 lpLogFont是指向邏輯字體 (LOGFONT類型)的指針。 LOGFONT結構的定義如例 10-21所示。
例 10-21
typedef struct tagLOGFONT { // lf
LONG lfHeight i
LONG lfWidthi
LONG lfEscapementi
LONG lfOrientationi
LONG lfWeighti
BYTE l fItalic;
BYTE lfUnderlinei
BYTE lfStrikeOuti
BYTE lfCharSeti
BYTE lfOutPrecisioni
BYTE lfClipPrecisioni
BYTE lfQualitYi
BYTE lfPitchAndFamilYi
TCHAR lfFaceName[LF_FACESIZE]i
} LOGF咱 ONTi
其中成員lfFaceName中存放的就是字體的名稱。也就是說,可以通過此成員得到宇
字體的名稱。
至于字體對象的創建,首先可以利用CFont類構造一個字體對象,然后利用CFont類的
CreateFontIndirect成員函數根據指定特征的邏輯字體 (LOGFONT類型〉來初始化這個字體對象。該
函數的聲明形式如下所示:
BOOL CreateFontIndirect(const LOGFONT* lpLogFont);
CreateFontIndirect函數的功能就是利用參數 lpLogFont指向的LOGFONT結構體中的一些特征來初
始化CFont對象。
為了保存用戶選擇的字體,首先為 Graphic工程的 CGraphicView類增加一個 CFont成員變量: m
font,再增加一個CString類型的成員: m s位FontName,用來保存所選字體的名稱,井將這兩個變
量的訪問權限都設置為私有的。然后在 CGraphicView類的構造函數中將m strFontName變量初始化
為空,代碼如下所示:
m_strFontName="";
說明:讀者在練習時,可以對m_font變量也進行初始化,為它創建一種默
認的字體。
然后在CGraphicView類的 OnFont函數中進行判斷,如果用戶單擊的是字體對話框的 OK按鈕,就用
所選字體信息初始化m font對象,井保存所選字體的名稱。具體代碼如例 10-22所示。
例IJ 10-22
1. void CGraphicView : :OnFont()
2. {
3. CFontDialog dlg ;
4. if (IDOK==dlg . DoModal () )
5. {
6. m_font.CreateFontlndirect(dlg.m_cf.lpLogFont);
7. m_strFontName=dlg.m_cf.lpLogFont->lfFaceName;
8. }
9. }
接下來,在視類窗口中把字體名稱用選擇的字體顯示出來。這可以在 CGraphicView 類的OnDraw函
數中實現,因此在上述OnFont函數中,在第7行代碼之后需要調用Invalidate函數讓窗口無效,這樣
當下一次發生WM PAINT消息時,窗口就會進行重繪。 CGraphicView類OnDraw函數的最終代碼如例
10-23所示。
例 10-23
void CGraphicview: :OnDraw(CDC* pDC)
{ CGraphicDoc* pDoc = GetDocument() ; ASSERT_VALID(pDoc) ; // TODO : add draw code for nat
ive data here
CFont *pOldFont=pDC->SelectObject (τtn-font);
pDC->TextOut (O, O, ffi_strFont Name) ;
pDC->SelectObject (pOldFont) ;
在上述例 10-23所示代碼中,首先把用戶選擇的新字體選入設備上下文,然后在窗口的(0, 0)處顯
示所選字體的名稱,最后再把先前的字體選入設備上下文。
Build井運行 Graphic程序。選擇【繪圖\字體】菜單項,這時將打開字體對話框,可以選擇任一種
字體、字形,還可以指定字體的大小。例如字體選擇隸書,字形選擇粗體,大小指定為20 (如圖 10.17
所示),然后單擊字體對話框的OK按鈕,這時在視類窗口中就可以看到用選定的字體、字形和大小輸
出了所選字體的名稱:"隸書",如圖 10.18所示。
圖 10.17選定字體 圖 10.18用選定的字體顯示所選字體名稱
可是當再次選擇【繪圖飛字體】菜單項后,程序將出現非法操作。這是因為當第一次選擇字體后,
OnFont函數中就把m font對象與這種字體資源相關聯了(上述例 10-22所示 OnFont函數第6行代碼
的結果〉。當再次選擇一種字體后, OnFont函數又會試圖把m_font對象與新字體資源相關聯,這時
當然就會出錯。因此,程序中應該進行一個判斷,如果 m font對象已經與一個字體資源相關聯了,
首先就需要切斷這種關聯,釋放該字體資源,然后才能與新資源相關聯。
要想釋放先前的資源,可以利用CGdiObject類 (CPen, CFont, CBitmap, CBrush都派生于該類)的
DeleteObject成員函數來實現。該函數通過釋放所有為WindowsGDI對象所分配的資源,從而刪除與
CGdiObject對象相關聯的WindowsGDI對象,同時與CGdiObject對象相關的存儲空間并不會受此調用
影響。這句話的意思是要讀者注意區分Windows GDI 和CGdiObject對象。后者是一個類的對象,而
前者是一種資源對象,就好像窗口類的對象和窗口的關系一樣,例如視類對象和視類窗口,它們之
間的聯系在于視類對象有一個數據成員: m hWnd保存了窗口資源的句柄值。同樣地, CGdiObject
類的對象和Windows GDI 資源對象是兩個不同的概念,它們之間也是通過一個數據成員來維系的。
當刪除Windows GDI資源對象后,對于CGdiObject類所定義的對象來說,并不受影響,只是它們之間
的聯系被切斷了。
如果想判斷 m font對象是否已經與某個字體資源相關聯了,最簡單的方法就是利用 CGdiObject對
象的數據成員m_hObject來判斷,該變量保存了與CGdiObject對象相關聯的 Windows GDI資源的句
柄。如果己經有關聯了,則調用DeleteObject釋放這個字體資源,
382 .
因此,在上述如例 10-22所示OnFont函數的第6行代碼前添
加下述代碼:
然后再與新的資源相關聯。
if(~font.ID_hObject)
ID_font.DeleteObject();
解
詳
一叫
再次運行Graphic程序,這時可以發現多次打開字體對話框選擇字體,程序一切正確。
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -