鄒雪峰,張 翔
劉琳琳
(遼河油田曙光技術(shù)處作業(yè)一大隊(duì),遼寧 盤錦 124109)
VC插入漢字文本塊的編程方法
鄒雪峰,張 翔
劉琳琳
(遼河油田曙光技術(shù)處作業(yè)一大隊(duì),遼寧 盤錦 124109)
一般的繪圖軟件如Surfer、Graph等只支持英文和數(shù)字的文本輸出,給圖形資料解釋說(shuō)明帶來(lái)不方便。采用VC編程實(shí)現(xiàn)了對(duì)漢字文本塊輸出,并設(shè)計(jì)了相應(yīng)的獨(dú)立文本類CText,對(duì)漢字雙字節(jié)作了校正處理,杜絕了斷字和亂碼的出現(xiàn)。同時(shí),該類實(shí)現(xiàn)了位置、顏色、大小等屬性設(shè)置功能,在實(shí)際的矢量繪圖軟件中,應(yīng)用效果良好。
文本框;文本塊;矢量繪圖;字符串繪制;鼠標(biāo)交互
常用的矢量繪制圖形的軟件中,圖形的文字介紹和說(shuō)明具有相當(dāng)重要的意義,如繪圖曲線類型說(shuō)明、繪圖標(biāo)題以及坐標(biāo)單位等描述在圖形繪制中是必須具備的[1]。因此,矢量繪圖軟件的開發(fā)過(guò)程中,大部分開發(fā)人員直接采用字符串輸出功能。但是,這些文本塊實(shí)現(xiàn)的功能只在通用的英文和數(shù)字等單字節(jié)字符文本有效,缺乏對(duì)中文這種雙字節(jié)字符的文本功能實(shí)現(xiàn)。為此,筆者針對(duì)實(shí)際工作中的需求,在單字節(jié)字符文本的基礎(chǔ)上,采用VC編程解決了雙字節(jié)字符文本繪制功能,設(shè)計(jì)了獨(dú)立文本類CText,實(shí)現(xiàn)了對(duì)文本功能的完善和開發(fā)[2-3]。
將文本塊當(dāng)作軟件繪圖的對(duì)象,并在視圖中繪制出來(lái),無(wú)論是各種圖形或者是很熟悉的文字,都是用畫筆畫出來(lái)的,在視圖中嵌入文本塊,要求在視圖中畫出一個(gè)有效矩形框(矩形框的寬度和高度要超過(guò)一定的大小),實(shí)現(xiàn)在有效矩形中畫出一個(gè)個(gè)的文字,據(jù)此可把所要執(zhí)行的功能列出如下[4]:①在視圖中繪制一個(gè)有效的文本矩形框,同時(shí)就生成一個(gè)文本塊對(duì)象;②在當(dāng)前的文本矩形框中繪制閃爍的光標(biāo),使文本塊處于等待文字輸入的狀態(tài);③每次輸入一個(gè)字符,判斷該字符是單字節(jié)還是雙字節(jié),同時(shí)把剛輸入一個(gè)字符輸出在視圖中,光標(biāo)隨著文字走動(dòng),處于輸出字符的后面,然后再輸入下一個(gè)字符;④當(dāng)文本塊中輸出的文字超過(guò)文本矩形框的寬度后,自動(dòng)換行;⑤文本塊能移動(dòng)、放大、縮??;⑥文本塊里的文字字體、大小、顏色能設(shè)置。
2.1文本矩形框的畫法
文本矩形框的繪制函數(shù)為void m_DrawText(CDC*pDC),思路如下:鼠標(biāo)左鍵點(diǎn)擊,記錄第1次點(diǎn)擊點(diǎn)的邏輯坐標(biāo),鼠標(biāo)處于繪制文本框的狀態(tài),移動(dòng)鼠標(biāo),鼠標(biāo)左鍵第2次點(diǎn)擊,記錄第2次點(diǎn)擊點(diǎn)的邏輯坐標(biāo),調(diào)用函數(shù)繪制文本矩形框。為保證光標(biāo)的初始位置顯示在文本框左上頂點(diǎn),對(duì)矩形框繪制做出如下的改進(jìn):將這2個(gè)點(diǎn)橫縱坐標(biāo)作比較,橫縱坐標(biāo)值較小的組成左上頂點(diǎn),同理橫縱坐標(biāo)值較大的組成右下頂點(diǎn),保持在矩形繪圖函數(shù)中第1個(gè)頂點(diǎn)的橫縱坐標(biāo)值都要小于第2個(gè)點(diǎn)的橫縱坐標(biāo)值。
2.2光標(biāo)的畫法
筆者對(duì)光標(biāo)的繪制作了改進(jìn),向當(dāng)前的文本框中插入一個(gè)光標(biāo)形式的字符,并讓字符閃爍,字符輸入后,關(guān)閉字符的閃爍,具體作法如下:①得到當(dāng)前所繪字符的高度,設(shè)置插光標(biāo)字符的長(zhǎng)度為所得到字符的高度;②得到要繪制字符邏輯坐標(biāo)值,設(shè)置插入字符的位置;③設(shè)置光標(biāo)字符閃爍;④關(guān)閉光標(biāo)的閃爍。光標(biāo)繪制的部分代碼如下:
//根據(jù)當(dāng)前字體,設(shè)置插入符/光標(biāo)
pView→LPtoDP(&size);
pView→CreateSolidCaret(2,size.cx);
//設(shè)置光標(biāo)位置
pView→SetCaretPos(caretPos);
//設(shè)置閃爍
pView→ShowCaret();
2.3字符的輸入
得到當(dāng)前文本框的指針后,在視圖中響應(yīng)系統(tǒng)函數(shù)OnChar,對(duì)該文本框進(jìn)行字符的輸入操作,在文本框中的添加字符輸入函數(shù)v_Onchar,鍵盤上輸入的字符都是以ansi值輸入,通過(guò)ansi值把輸入的字符分成3類,然后對(duì)這3類分別處理。具體做法如下:①將輸入的字符分成3種情況,一種是正常的輸入,如“數(shù)字、大小寫字母、空格、漢字”;一種是回車鍵的輸入;還有一種是刪除鍵的輸入。②定義用來(lái)記輸入字符個(gè)數(shù)的變量v_i_PointerLoc,用來(lái)存儲(chǔ)輸入字符的字符串變量v_TextStr,當(dāng)正常輸入時(shí),字符串變量就存儲(chǔ)這個(gè)字符,字符個(gè)數(shù)變量加1,回車鍵輸入時(shí),字符串變量記錄一個(gè)字符“ ”, 字符個(gè)數(shù)變量加1,刪除鍵輸入時(shí),字符串變量就刪除一個(gè)字符,且字符個(gè)數(shù)變量減1[5-6]。
2.4字符的輸出
字符串中漢字字符是占2個(gè)字節(jié),其他的字符占1個(gè)字節(jié),得到存儲(chǔ)在字符串v_TextStr中字符每1個(gè)字節(jié)的ansi值,與字符的輸入相反的是,如果ansi值是大小寫字母、標(biāo)點(diǎn)符號(hào)、數(shù)字,按1個(gè)字節(jié)讀出當(dāng)前字符,如果ansi值是漢字的值(ansi>127),按2個(gè)字節(jié)讀出當(dāng)前的字符,讀出字符的函數(shù)是CString中的Mid(int nFirst,int nCount),nFirst是從字符串中的第幾個(gè)字節(jié)開始讀取,nCount是讀幾個(gè)字節(jié)。如ansi>127,nCount的值等于2,因?yàn)閍nsi>127判斷該字節(jié)是1個(gè)漢字,漢字占2個(gè)字節(jié),需要讀取2個(gè)字節(jié)得到該漢字,所以nCount值取2。具體的步驟如下:①得到整個(gè)字符串的字節(jié)長(zhǎng)度,設(shè)定1個(gè)無(wú)字符型的變量,把讀進(jìn)來(lái)的字符轉(zhuǎn)化成無(wú)字符型的ansi值。②判段ansi值,如果ansi?‘9’ 且ansi?‘0’,說(shuō)明該字符是數(shù)字,就按1個(gè)字節(jié)得到該字節(jié)表示的字符;同理,大小寫字母也按一個(gè)字節(jié)得到該字節(jié)表示的字符;如果是回車鍵,不需要得到字符,把字符串的輸出點(diǎn)的X值歸到文本框最左邊,Y的值加1個(gè)字符的高度;如果 ansi>127,說(shuō)明該字節(jié)是漢字,該字節(jié)與其后面的1個(gè)字節(jié)組成1個(gè)漢字,Mid函數(shù)中的nCount值等于2。③每得到1個(gè)字符,調(diào)用函數(shù)TextOut(x,y,str)來(lái)輸出該字符,X的值變化為每輸出1個(gè)字符后,加上該字符的寬度,當(dāng)X的值大于文本矩形最右邊的值后,做自動(dòng)換行處理,X的值回到文本矩形最左邊的值,Y的值加1個(gè)字符的高度。每輸出一個(gè)字符后,都記錄輸出后的位置,為繪制光標(biāo)提供坐標(biāo)值。部分代碼如下:
unsigned char ansi;
ansi = v_pView→v_Chart.m_CurrentText→v_TextStr[i];
//---------------如果字符是數(shù)字小寫字母大寫字母----------------
if ((ansi?‘9’ && ansi ?‘0’)|| (ansi?‘z’ && ansi ?‘a(chǎn)’)|| (ansi?‘Z’ && ansi ?‘A’) )
{
W = v_pView→v_Chart.m_CurrentText→v_TextStr.Mid(i,1);
single.cx = v_pView→v_Chart.m_CurrentText→v_i_FontW;
}
//---------------如果字符是漢字----------------------
else if (ansi > 127)
{
W =v_pView→v_Chart.m_CurrentText→v_TextStr.Mid(i,2);
i++;
single.cx = 2*v_pView→v_Chart.m_CurrentText→v_i_FontW;
}
2.5文本框交互操作
圖1 文本區(qū)域劃分圖
文本塊繪制完成后,應(yīng)用戶的需要,調(diào)整框的大小和位置,設(shè)計(jì)的思路如下:①將文本矩形框劃分成4個(gè)矩形,如圖1所示。②分別對(duì)文本框的4個(gè)矩形建立相應(yīng)的區(qū)域矩形,鼠標(biāo)左鍵點(diǎn)擊點(diǎn)落在1號(hào)區(qū)域時(shí),選中文本框,鼠標(biāo)移動(dòng)可以拖動(dòng)文本框改變文本框的位置;鼠標(biāo)左鍵點(diǎn)擊點(diǎn)落在2號(hào),3號(hào),4號(hào)區(qū)域時(shí),選中文本框,鼠標(biāo)移動(dòng)改變文本框的大小。下面是建立的2號(hào)區(qū)域部分代碼:
//----------建立文本框水平拉動(dòng)區(qū)域------------------
v_MoveHorz.cy = v_TextRect.Height()-(v_Rgn.cy/2);
v_MoveHorz.cx = v_Rgn.cx;
v_HorzPoint.x = v_TextRect.right-(v_Rgn.cx/2);
v_HorzPoint.y = v_TextRect.top;
CRect HorzText(v_HorzPoint,v_MoveHorz);
CRgn MoveHorz;
pView→LPtoDP(HorzText);
MoveHorz.CreateRectRgnIndirect(HorzText);
③再添加鼠標(biāo)的移動(dòng)和左鍵彈起等操作,改變文本框的位置及大小,進(jìn)行文本塊重畫。
2.6設(shè)置文本框?qū)傩詫?duì)話框
圖2 實(shí)例文本框繪制
文本塊作為標(biāo)題和注釋等解釋時(shí),文本框中字體大小會(huì)有所不同,甚至對(duì)顏色都有要求,所以設(shè)計(jì)對(duì)話框?qū)ξ谋究蛑械奈淖謱傩宰鱿鄳?yīng)的修改,如字體的大小,字體的顏色。選中要修改的文本塊,選擇字體菜單得到新的字體對(duì)象,賦值給文本塊對(duì)象,調(diào)用視圖的重畫函數(shù)。
用VC++6.0 具體實(shí)現(xiàn)了在視圖中插入文本塊的編程方法,并應(yīng)用于項(xiàng)目團(tuán)隊(duì)開發(fā)的三維可視化的軟件中,在該軟件中實(shí)現(xiàn)了文本塊功能,解決了以往軟件只能輸入英文文本的問題,實(shí)現(xiàn)了2個(gè)文本框,并實(shí)現(xiàn)英文大小寫和漢字和數(shù)字輸入、字符換行、字體顏色設(shè)置及大小變化等功能(見圖2)。
[1]王永茂,彭維平,王玉琨.用VC++實(shí)現(xiàn)矢量圖形的無(wú)極縮放[J].福建電腦,2006(6) :182-183.
[2]姜照林.用VC實(shí)現(xiàn)Word文檔自動(dòng)化[J].嘉信學(xué)院學(xué)報(bào),2007,3(5):68-71.
[3]王姍姍,李海晟.給DIB位圖添加文本的方法[J].電腦編程技巧與維護(hù),2008(4):16-25.
[4]石虎山,裘雪紅.在滾動(dòng)視圖中嵌入局部文本編輯[J].微機(jī)發(fā)展,2003,13(9):13-15.
[5]李霞.VC++編程實(shí)現(xiàn)“畫”文本[J].編程語(yǔ)言,2006(9):19-22.
[6]李霞.視圖中插入文本塊的編程方法[J].廣州大學(xué)學(xué)報(bào)(自然科學(xué)版),2002,13(9):57-59.
[編輯] 洪云飛
10.3969/j.issn.1673-1409(N).2012.12.033
TP391.41
A
1673-1409(2012)12-N102-03
長(zhǎng)江大學(xué)學(xué)報(bào)(自科版)2012年34期