提出問題:
根據文本文件的內容,用CWin的子類對控制進行動態創建。在Create方法中,根據用戶在顯示屬性對話框中選擇的消息文本字體,用下列代碼創建所有的控制:
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);
m_DefaultFont.CreateFontIndirect(&ncm.lfMessageFont);
獲得字體以後,接下來的問題是如何才能確定靜態控制的高度與寬度以便顯示完整的文本?
首先應該明確的是所謂顯示屬性對話框即在桌面單擊右鍵,選擇“屬性”菜單項,再選擇“外觀”屬性頁出現的對話框(圖一)。
圖一
用戶可以在這個對話框中選擇活動窗口、消息框以及文字的顏色和字體。你可以調用SystemParametersInfo函數,用SPI_GETNONCLIENTMETRICS作為第一個參數來查出用戶選擇了什麼字體;SystemParametersInfo 函數將你需要的信息填寫到NONCLIENTMETRICS 結構中:
// NONCLIENTMETRICS 結構(winuser.h)
//
struct NONCLIENTMETRICS
{
UINT cbSize;
int iBorderWidth;
int iScrollWidth;
int iScrollHeight;
int iCaptionWidth;
int iCaptionHeight;
LOGFONT lfCaptionFont;
int iSmCaptionWidth;
int iSmCaptionHeight;
LOGFONT lfSmCaptionFont;
int iMenuWidth;
int iMenuHeight;
LOGFONT lfMenuFont;
LOGFONT lfStatusFont;
LOGFONT lfMessageFont;
};
這個結構含有用於菜單、消息及其它字體的LOGFONT結構。一旦你有了字體,那如何知道顯示給定的文本串需要多大的屏幕空間?這是Windows編程的一個共同問題。所幸的是,Windows中有一個專門的函數,用它可以在屏幕的任何地方顯示文本,這個函數就是 DrawText。在Windows中這是一個基本的文本顯示函數。它的功能是在指定的屏幕坐標上顯示(或者說繪制)文本串。
CDC dc = ...;
CRect rc = ...;
CString str = "Hello";
dc.DrawText(str, &rc, 0);
DrawText 在你指定的矩形框中顯示文本-但是如果你不知道這個矩形應該是多大,該怎麼辦呢?這時有一個很容易的辦法來計算矩形大小:
CRect rc(0,0,0,0);
dc.DrawText(str, &rc, DT_CALCRECT);
DrawText實際上並不繪制文本,而是計算出文本需要多少空間。DrawText改變傳入矩形的大小以便適應文本的寬度和高度。調用DrawText之後,rc.Widtrh和rc.Height將返回文本的寬度和高度。你可以用希望的左上角坐標初始化CRect,即(rc.left,rc.top)代替(0,0)。然後DrawText將根據文本寬度和高度產生有下腳坐標。
當然,前面的代碼段假設字體的設備上下文已經選定。僅僅用LOGFONT怎能行呢?如果你已經有一個DC,因為MFC把它傳給你了(例如,當MFC調用視圖的CView::OnDraw或宿主繪畫項的CWnd::OnDrawItem時),你可以使用提供的DC作為你的設備上下文;否則,你必須調用下面的兩個CDC創建函數之一。
// 創建客戶DC
CClientDC dc(pMyWnd);
或者
// 創建window DC
CWindowDC dc(pMyWnd);
因為你不想真的畫任何東西,所以使用那個設備上下文並不重要。只要你是創建屏幕DC-相對於打印機或者其它的設備而言,調用任何的CDC創建函數都行(除非你想要一個打印機的設備上下文)。
一旦你有了設備上下文,你就得創建字體對象並將它選進DC。這是標准的Windows圖形編程。
// 創建字體
CFont font;
font.CreateFontIndirect(&ncm.lfMessageFont);
// 將字體選進DC
CFont* pOldFont = dc.SelectObject(&font);
// 計算文本大小
dc.DrawText(str, rc, DT_CALCRECT);
// 回復舊字體-這是必須的
dc.SelectObject(pOldFont);
(完)