中國人自古就有自右至左、從上到下書寫漢字的習慣。而當我們在自己所編寫的應用程序中使用輸出函數輸出的總是自左至右的橫排文字。有沒有可能在我們的應用程序中實現豎寫漢字的效果呢?筆者偶然發現了一種利用VC實現豎寫漢字效果的方法,現在就把它介紹給大家。
Windows系統內置了許多名稱以“@”開頭的字集,這些字集有一個共同的特點,即其所包含的文字全都是平躺着的(字頭朝左,字底朝右)。如果我們能將這些字逆時針旋轉270度后再顯示出來,就可以達到實現豎寫漢字效果的目的了。
要使文字發生旋轉,我們只需創建一個邏輯字體並設定該邏輯字體的顯示角度,再設定其字體名稱為一個以“@”開頭的字集的名稱即可。我們可以采用兩種方式創建邏輯字體。
其一,用CFont類的成員函數CreateFont直接創建邏輯字體。CreateFont的參數定義如下:
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 //字體名稱
);
其中nEscapement單位為0.1角度,方向為逆時針,所以為了使平躺的字立起來應設定其值為2700,lpszFacename則賦以“@”開頭的字集的名稱,如“@system”。
其二,利用LOGFONT結構,將該結構作為參數調用CFont類的成員函數CreateFontIndirect創建邏輯字體。LOGFONT結構通常被用來描述一種邏輯字體,結構內的各變量分別代表邏輯字體的各個屬性,這些變量與函數CreateFont的參數相同。其結構如下:
typedef struct tagLOGFONT { // lf
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]; //字體名稱
} LOGFONT;
下面我們就以一個示例來說明豎寫漢字的實現方法:
1.建立一個MFC AppWizard(exe)應用工程CHNfont。在MFC AppWizard向導的第一步中選擇Single Document,再點擊按鍵Finish->OK完成工程的建立。
2.在CMainFrame::OnCreate函數中添加如下代碼,使窗體最大化。AfxGetMainWnd()->ShowWindow(SW_SHOWMAXIMIZED);
3.添加如下代碼實現豎寫功能。
void CChildView::OnPaint()
{
CPaintDC dc(this);// device context for painting
/////// 利用CFont::CreateFont(...)函數實現豎寫漢字////////
CFont myFont; //創建字體對象
//創建邏輯字體
myFont.CreateFont(
56, //字體高度(旋轉后的字體寬度)=56
20, //字體寬度(旋轉后的字體高度)=20
2700, //字體顯示角度=270°
0, //nOrientation=0
10, //字體磅數=10
FALSE, //非斜體
FALSE, //無下划線
FALSE, //無刪除線
DEFAULT_CHARSET, //使用缺省字符集
OUT_DEFAULT_PRECIS, //缺省輸出精度
CLIP_DEFAULT_PRECIS,//缺省裁減精度
DEFAULT_QUALITY, //nQuality=缺省值
DEFAULT_PITCH, //nPitchAndFamily=缺省值
"@system"); //字體名=@system
CFont *pOldFont=dc.SelectObject(&myFont);//選入設備描述表
CRect rtClient;
GetClientRect(rtClient); //獲取客戶區尺寸、位置信息
//在客戶區適當位置輸出文字
dc.TextOut(rtClient.Width()/2+30,rtClient.Height()/8,
"無邊落木蕭蕭下");
dc.SelectObject(pOldFont); //將myFont從設備環境中分離
myFont.DeleteObject(); //刪除myFont對象
/////////// 利用LOGFONT結構實現豎寫漢字//////////////
LOGFONT lf; //定義字體結構
lf.lfWeight=10; //字體磅數=10
lf.lfHeight=56; //字體高度(旋轉后的字體寬度)=56
lf.lfWidth=20; //字體寬度(旋轉后的字體高度)=20
lf.lfUnderline=FALSE; //無下划線
lf.lfStrikeOut=FALSE; //無刪除線
lf.lfItalic=FALSE; //非斜體
lf.lfEscapement=2700; //字體顯示角度=270°
lf.lfCharSet=DEFAULT_CHARSET; //使用缺省字符集
strcpy(lf.lfFaceName,"@system"); //字體名=@system
CFont myLogFont; //定義字體對象
myLogFont.CreateFontIndirect(&lf); //創建邏輯字體
pOldFont=dc.SelectObject(&myLogFont);//選入設備描述表
//在客戶區適當位置輸出文字
dc.TextOut(rtClient.Width()/2-30,rtClient.Height()/8,
"不盡長江滾滾來");
dc.SelectObject(pOldFont); //將myFont從設備環境中分離
myLogFont.DeleteObject(); //刪除myLogFont對象
}
4.編譯連接,運行。
或者
CString m_text;
CSize sz = pdc->GetTextExtent("效");
CRect rtCal; //要輸出字符串的矩形區域。其寬度稍大於字符寬度。
rtCal.Width = sz.cx + 2;
int midhei=pDC->DrawText(m_text,&rtCal,flag | DT_CALCRECT | DT_WORDBREAK| DT_NOCLIP);
或者只是簡單的用:
for (i=0;i<m_text.GetLength();i++){
pDC->TextOut(10,y,m_Text.GetAt(i));
y+= sz.cy;
}
----------------------------------------------------------------------------------
CreateFont 參數說明:
1、nHeight:指定字體的字符單元或字符的邏輯單位高度,字符的高度值(也被稱為em高度)是指字符單元高度值減去內部標頭值。字體映射器以如下方式解釋nHeight指定的值,各值含義為:
>0:字體映射器轉換這個值以設備單位,並和已有字體的單元高度相匹配。
0:字體映射器轉換在選擇匹配時用一個缺省的高度值。
<0:字體映射器轉換這個值到設備單位,並將它的絕對值和已有字體的字符高度相匹配。
比較所有的高度,字體映射器選擇不超過要求大小的最大字體。
此映射當字體第一次被使用時發生。
對於MM_TEXT映射方式,可以用下面的公式為一種指定了點大小的字體確定高度:
nHeight=-MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY),72)
2、nWidth:指定所要求字體的字符的邏輯單位的平均寬度。如果此值為0,字體映射器選擇一個closest match值,closest match值是由比較當前設備的特征系數與可使用字體的數字化特征系數之差的絕對值而確定的。
3、nEscapement:指定移位向量和設備X軸之間的一個角度,以十分之一度為單位。移位向量平行於正文行的基線。
Windows NT:當圖形設備設置為GM_ADVANCED時,可以不依賴字符串的字符的定位角而指定字符串的移位角。
當圖形模式被設置為GM_COMPATIBLE時,nEscapement同時指定移位角和定位角,可以設置nEscapement和nOrientation為相同的值。
Windows 95:nEscapement同時指定移位角和定位角,可設置nEscapement和nOrientation為相同的值。
4、nOrientation:指定每個字符的基線和設備X軸之間的角度。
5、FnWeight:在0到1000之間指定字體的權值,如400表示標准體,700表示黑(粗)體,如果此值為0,則使用缺省的權值。
FW_DONTCARE:0;FW_THIN;100;FW_EXTRALIGHT;200;FW_ULTRALIGHT;200;FW_LIGHT;300;
FW_NORMAL:400;FW_MEDIUM;500;FW_SEMIBOLD;600;FW_DEMIBOLD;600;FW_BOLD:700;FW_EXTRABOLD;800;FW_BLACK;900。
6、fdwItalic:如果設置為TRUE,則字體設置為斜體。
7、fdwUnderline:如果設置為TRUE,則字體增加下划線。
8、fdwStrikeOut:如果設置為TRUE,則字體增加刪除線。
9、fdwCharSet:指定字符集,下列值是預定義的:
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
OEM_CHARSET指定的字符集與操作系統有關。
可以使用DEFAULT_CHARSET值來允許字體的名字和大小來充分描述邏輯字體。如果指定的字體名不存在,任何字符集的字體都可以替代指定的字體,所以應該小心地用DEFAULT_CHARSET來避免不期望的結果出現。
函數原型
參數
DT_BOTTOM 將正文調整到矩形底部。此值必須和DT_SINGLELINE組合。
DT_CALCRECT 決定矩形的寬和高。
如果正文有多行,DrawText使用lpRect定義的矩形的寬度,並擴展矩形的底部以容納正文的最后一行。
如果正文只有一行,則DrawText改變矩形的右邊界,以容納下正文行的最后一個字符。
出現上述任何一種情況,DrawText返回格式化正文的高度,而不是繪制正文。
DT_CENTER 使正文在矩形中水平居中。
DT_EDITCONTROL 復制多行編輯控制的正文顯示特性。
特殊地,為編輯控制的平均字符寬度是以同樣的方法計算的,此函數不顯示只是部分可見的最后一行。
DT_END_ELLIPSIS 對於顯示的文本,如果結束的字符串的范圍不在矩形內,它會被截斷並以省略號標識。
如果一個字母不是在字符串的末尾處超出了矩形范圍,它不會被截斷並以省略號標識。
字符串不會被修改,除非指定了DT_MODIFYSTRING標志。
DT_EXPANDTABS 擴展制表符,每個制表符的缺省字符數是8。
DT_WORD_ELLIPSIS, DT_PATH_ELLIPSIS和DT_END_ELLIPSIS不能和此參數一起使用
DT_EXTERNALLEADING 在行的高度里包含字體的外部標頭,通常,外部標頭不被包含在正文行的高度里。
DT_HIDEPREFIX 忽略正文中的前綴字符(&),並且前綴字符后面的字母不會出現下划線。其它前綴字符的調用方式不受影響。
輸入的字符串: "A&bc&&d"
正常: "Abc&d"
DT_HIDEPREFIX: "Abc&d"
DT_INTERNAL 用系統字體來計算正文度量。
DT_LEFT 正文左對齊。
DT_MODIFYSTRING 修改給定的字符串來匹配顯示的正文。
此標志必須和DT_END_ELLIPSIS 或 DT_PATH_ELLIPSIS同時使用。
DT_NOCLIP 無裁剪繪制。當DT_NOCLIP使用時DrawText的使用會有所加快。
DT_NOFULLWIDTHCHARBREAK 在寬字符的字符串中防止行斷開,因此折行規則相當於單字符的字符串。
例如,我們可以用在棒子版的windows中,為圖標標簽提供更好的可讀性。
除非指定DT_WORDBREAK,否則此值沒有作用。
DT_NOPREFIX 關閉前綴字符的處理。
通常DrawText解釋助記前綴字符,&為給其后的字符加下划線,解釋&&為顯示單個&。指定DT_NOPREFIX,這種處理被關閉。
DT_PATH_ELLIPSIS 對於顯示的正文,替換字符串在橢圓中的字符,以確保結果能在合適的矩形內。
如果該字符串包含反斜杠(\)字符,DT_PATH_ELLIPSIS盡可能的保留最后一個反斜杠之后的正文。
字符串不會被修改,除非指定了DT_MODIFYSTRING標志。
DT_PREFIXONLY 僅僅在(&)前綴字符的位置下繪制一個下划線。不繪制字符串中的任何其他字符。
輸入的字符串: "A&bc&&d"
正常: "Abc&d"
DT_PREFIXONLY:" _ "
DT_RIGHT 正文右對齊。
DT_RTLREADING 當選擇進設備環境的字體是希伯來文或阿拉伯文字體時,為雙向正文安排從右到左的閱讀順序都是從左到右的。
DT_SINGLELINE 顯示正文的同一行,回車和換行符都不能折行。
DT_TABSTOP 設置制表,參數uFormat的15"C8位(低位字中的高位字節)指定每個制表符的字符數,每個制表符的缺省字符數是8。
注意:DT_CALCRECT, DT_EXTERNALLEADING, DT_INTERNAL,
DT_NOCLIP, DT_NOPREFIX值不能和DT_TABSTOP值一起使用。
DT_TOP 正文頂端對齊。
DT_VCENTER 使正文在矩形中垂直居中。
(DreamSmart注:此值必須和DT_SINGLELINE連用,否則GDI無法計算目的矩形)
DT_WORDBREAK 斷開字。當一行中的字符將會延伸到由lpRect指定的矩形的邊框時,此行自動地在字之間斷開。一個回車一換行也能使行折斷。
DT_WORD_ELLIPSIS 截短不符合矩形的正文,並增加省略號。
參考文章:http://baike.baidu.com/link?url=2fdO6RtuvbmsKEghtK036hqN4sE9JIs6AdNHYRBYAMWNm8lxyxDoYRLG2foEaeo4u8KnILAacYOiT32x1h6EGa
原文地址:http://www.cnblogs.com/gxceo/archive/2011/03/11/1980466.html