Windows经常使用GDI进行文本输出。在一定意义上,任何内容都可以看成图形实体
图形和文本并没有明显的界限
使用定义好的与设备无关的字体集,Windows就能维护它的设备无关性,提供“所见即所得”的好处,即屏幕所见与设备输出的文本是一样的
先要获得文本句柄
文本操作设置字体、字符大小、字符颜色等有关属性将这些属性选入设备环境
1
5.1 设置文本的设备环境描述所要显示的文本的大小、类型和外形Win 系统提供了七种基本字体物理字体是为特殊设备设计的,因而是设备相关的字体逻辑字体定义的字符集是设备无关的,它可以精确标度,因此得到广泛应用字体ANSI_FIXED ANSI_VARDEFAULT_GUIOEM_FIXED DEVICE_DEFAULTSYSTEM_FIXEDSYSTEM 说明ANSI标准的固定宽度的字体ANSI标准的可变宽度的字体当前GUI的缺省字体由标准原设备制造商(OEM)提供当前图形设备的字体Windows的标准固定宽度的字体Windows提供的可变宽度的字体常作为缺省字体Win用它作为系统界面字体2选择系统字体的步骤(1) 定义字体句柄变量:HFONT hF; //hF为字体的句柄(2) 调函数GetStockObject获得系统字体句柄它返回的是系统的缺省字体hF= GetStockObject( ):(3) 调用函数SelectObject将字体选入设备环境SelectObject(hdc,hF);35.1.2 创建自定义字体
若需要定义系统以外的字体,可以调用函数GreateFont自行创建HFont=CreateFont (int nHeight, //字体高度,0采用系统缺省值,使用逻辑单位int nWidth,//字体宽度,取0则由系统根据高宽比取最佳值int nEscapement, //每行文字相对于页底的角度,单位为0.1度int nOrienation, //每个文字相对于页底的角度,单位为0.1度DWORD nWeight, //字体粗细度,范围为0~1000可选的系统字符集:DWORD Dwltalic, //如果要求字体倾斜,则取非零ANSI_CHARSETOEM_CHARSETDWORD dwUnderline,//如果要求下划线,则取非零SYMBOL_CHARSETDWORD dwStrikeout,//如果要求中划线,则取非零DEFAULT_CHARSETSHIFTJIS_CHARSETDWORD dwCharset, //字体所属字符集DWORD dwOutputPrecision,//输出精度,一般取缺省值OUT_DEFAULT_PRECISDWORD dwClipPrecision, //剪裁精度,常取缺省值CLIP_DEFAULT_PRECISDWORD dwQuality,//输出质量,一般取缺省值DEFAULT_QUALITYDWORD dwPitchAndFamily, //字体名4) 5.1.3 设置字体和背景颜色字体及背景颜色的设置在开发过程中非常重要设置字体颜色:SetTextColor(hdc,crColor);设置背景颜色:SetBkColor(hdc,crColor);crColor为设置的颜色55.2 文本的输出过程
获取字体信息
文本输出过程
确定后续文本坐标
格式化文本
确定换行时文本坐标调用函数输出文本
6
获取字体信息输出文本之前要获取字体的信息,如字符高度等,以确定输出格式和下一行字符的位置GetTextMetrics (hdc,&tm);//tm为TEXTMETRICS结构获取当前使用字体信息调用该函数时,系统将当前字体的信息拷贝到tm标识的TEXTMETRICS结构中7系统定义的TEXTMETRICS的结构如下:
typedef struct tagTEXTMETRIC {//tmLONG tmHeight; //字符高度LONG tmAscent;//字符基线以上高度LONG tmDescent; //字符基线以下高度LONG tmInternalLeading;//tmHeight制订的字符高度顶部的控件LONG tmExternalLeading;//行与行之间的间隔LONG tmAveCharWidth;//平均字符宽度LONG tmMaxCharWidth;//最大字符宽度LONG tmWeight; //字符的粗细度LONG tmOverhang;//合成字体间附加的宽度LONG tmDigitizedAspectX; //为输出设备设计的X轴尺寸LONG tmDigitizedAspectY; //为输出设备设计的Y轴尺寸BCHAR tmFirstChar;//字体中第一个字符值BCHAR tmLastChar; //字体中最后一个字符值BCHAR tmDefaultChar; //代替不在字体中字符的字符BCHAR tmBreakChar;//作为分割符的字符BYTE tmItalic; //非0则表示字体为斜体BYTE tmUnderlined; //非0则表示字体有下划线BYTE tmStruckOut; //非0则表示字符为删除字体BYTE tmPitchAndFamily; //字体间距和字体族BYTE tmCharSet; //字符集}TEXTMETRIC
8
格式化文本需要格式化处理的情况在文本行中确定后续文本的坐标换行时确定下一行文本的坐标(1) 确定后续文本坐标确定后续文本的坐标,应先获取当前的字符串的宽度,该工作由GetTextExtentPoint32函数完成,并把它存储于一个SIZE结构中。BooL GetTextExtentPoint32(HDC hdc,LPCTSTR lpszString,//指定的字符串int nLength, //字符串中的字符数LPSIZE lpSize//返回字符串宽度及高度的SIZE数据结构的地址)例如,X轴起始坐标为cx0,后续文本起始坐标cx1为:cx1=cx0+size.cx;SIZE数据结构的定义typedef struct tagSIZE{ LONG cx;LONG cy;} SIZE;9(2)确定换行时文本坐标
通过计算当前行文本字符的高度与行间隔之和,即可得到换行时文本的起始坐标
字符的高度与行间隔均存储在tm指向的TEXTMETRICS结构中,换行时Y轴上文本的起始坐标cy为:
cy=tm.tmHeight+tm.tmExternalLeading;
10
文本输出
常用的文本输出函数TextOut原型如下:BOOL TextOut(HDC hdc, int X, int Y,//X, Y为用户区中字符串的起始坐标LPCTSTR lpstring, //lpstring为显示的字符串int nCount//nCount为字符串中的字节数);TextOut以坐标X,Y为起点,输出字节数为nCount、名为lpstring中的字符串11
5.3 文本操作实例【例4-1】在用户窗口上输出几行字符串,当窗口接收到WM_PAINT消息后,显示的文本每次都被重新刷新。#include int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow) { MSG Message; if(!InitWindowsClass(hInstance))return FALSE;if(!InitWindows(hInstance,nCmdShow))return FALSE;while(GetMessage(&Message,0,0,0))//消息循环 { TranslateMessage(&Message);DispatchMessage(&Message); } return Message.wParam; } 13 //消息处理函数long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam){static long nXChar,nCaps,nYChar;HDC hDC; //定义指向设备上下文的句柄short x;TEXTMETRIC tm;short LnCount=6;PAINTSTRUCT PtStr; //定义指向包含绘图信息的结构体变量static char *textbuf[]={\"This is the First line\\"This is the second line\输出的文\"This is the third line\本内容\"This is the fourth line\\"This is the fifth line\\"This is the sixth line\"14};switch(iMessage) //处理消息{case WM_CREATE://处理窗口创建消息 hDC=GetDC(hWnd) ; //获取当前设备表句柄GetTextMetrics(hDC,&tm); //获取字体信息nXChar=tm.tmAveCharWidth; //获取字符宽度nYChar=tm.tmHeight+tm.tmExternalLeading;nCaps=(tm.tmPitchAndFamily&1?3:2)*nXChar/2;ReleaseDC(hWnd,hDC); //释放当前设备句柄return 0;case WM_PAINT: //处理重画消息 hDC=BeginPaint(hWnd,&PtStr); //开始绘画for(x=0;x EndPaint(hWnd,&PtStr);return 0; case WM_DESTROY: //结束应用程序 PostQuitMessage(0);return 0;default://其他消息处理程序 return(DefWindowProc(hWnd,iMessage,wParam,lParam)) ;}} 15 BOOL InitWindowsClass(HINSTANCE hInstance){WNDCLASS WndClass; …………; WndClass.style=CS_HREDRAW|CS_VREDRAW;return RegisterClass(&WndClass); } {HWND hWnd; hWnd=CreateWindow(\"WinText\生成窗口 \"文本显示示例程序\WS_OVERLAPPEDWINDOW,…….;NULL); if(!hWnd)return FALSE;hWndMain=hWnd; ShowWindow(hWnd,nCmdShow); //显示窗口 //初始化窗口类 BOOL InitWindows(HINSTANCE hInstance,int nCmdShow)//初始化窗口 UpdateWindow(hWnd);return TRUE; } 16 【例4-2】本程序通过在窗口中分五行分别显示五行文本,以说明在窗口的用户区中输出文本的方法。 17 本例题的源代码如下:#include LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow){ HWND hwnd;MSG Msg; WNDCLASS wndclass; char lpszClassName[] = \"文本输出\"; char lpszTitle[]= \"EXAMPLE FOR THE TEXT OUTPUT\";wndclass.style = 0;…………; 18 wndclass.lpszClassName = lpszClassName; if( !RegisterClass( &wndclass)) { MessageBeep(0);return FALSE;} hwnd = CreateWindow ( lpszClassName,lpszTitle, WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);ShowWindow( hwnd, nCmdShow);UpdateWindow(hwnd); while( GetMessage(&Msg,NULL,0,0)) {TranslateMessage(&Msg);DispatchMessage(&Msg);}return Msg.wParam; 19 } LRESULT CALLBACK WndProc(HWND hwnd,UINT message, WPARAM wParam,LPARAM lParam) { HDC hdc; HFONT hF_black,hF_big;//定义两种字体句柄PAINTSTRUCT ps;TEXTMETRIC tm;//定义一个TEXTMETRIC结构,用以记录字体信息char lpsz_1[]=这是一行红色的、字体为SYSTEM_FONT的文字,红色代表未来。\";char lpsz_2[]=现在显示的是自定义字体,颜色为绿色,绿色代表生机勃勃。\";char lpsz_3[]=现在展现在您面前的是蓝色的粗体字,蓝色代表广阔的海洋和天空。\";char lpsz_4[]=\"当前字体为大号、斜体并带有下划线的文字。\";char lpsz_5[]=\"现在您掌握了字体的操作了吗?\";char lpsz_6[]=\"祝您成功!\";int X=0,Y=0;SIZE size; //定义一个SIZE类型的结构 20 switch(message){case WM_PAINT: hdc=BeginPaint(hwnd,&ps); SetTextColor(hdc,RGB(255,0,0));//设置文本颜色为红色GetTextMetrics(hdc,&tm); //获取缺省字体,写入tm结构中TextOut(hdc,X,Y,lpsz_1,strlen(lpsz_1));//用当前字体输出文本Y=Y+tm.tmHeight+100*tm.tmExternalLeading; //计算换行时下一行文本的输出坐标 hF_black=CreateFont(//创建自定义字体20,//字体的高度0,//由系统根据高宽比选取字体最佳宽度值0,//文本的倾斜度为0,表示水平0,//字体的倾斜度为0FW_HEAVY,//字体的粗度,FW_HEAVY为最粗0,//非斜体字0,//无下划线0,//无删除线ANSI_CHARSET,//表示所用的字符集为ANSI_CHARSETOUT_DEFAULT_PRECIS,//输出精度为缺省精度CLIP_DEFAULT_PRECIS,//剪裁精度为缺省精度DEFAULT_QUALITY,//输出质量为缺省值 21DEFAULT_PITCH|FF_DONTCARE,//字间距和字体系列使用缺省值 \"粗体字\" );//字体名称 SetTextColor(hdc,RGB(0,255,0));SelectObject(hdc,hF_black); //设置文本颜色为绿色 //将自定义字体选入设备环境 GetTextMetrics(hdc,&tm); //获取字体的信息,写入tm结构中TextOut(hdc,X,Y,lpsz_2,strlen(lpsz_2));//用当前字体输出文本 //换行继续输出文本,计算新行的起始Y坐标位置Y=Y+tm.tmHeight+10*tm.tmExternalLeading; GetTextExtentPoint32(hdc,lpsz_2,strlen(lpsz_2),&size); //获取字符串/的宽度 SetTextColor(hdc,RGB(0,0,255)); //设置文本颜色为蓝色 TextOut(hdc,X,Y,lpsz_3,strlen(lpsz_3));//当前字体输出文本X=0; //计算下一行文本的输出起始坐标 22Y=Y+tm.tmHeight+20*tm.tmExternalLeading; hF_big=CreateFont//引入新字体 (30,//字体高度0,0,0, FW_NORMAL,1,//定义斜体1,//定义输出时带下划线0, ANSI_CHARSET,//所使用的字符集OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY, DEFAULT_PITCH|FF_DONTCARE,\"大号字\"); 23 SelectObject(hdc,hF_big);//将自定义字体选入设备环境SetTextColor(hdc,RGB(155,155,155));//设置文本颜色Y=Y+tm.tmHeight+20*tm.tmExternalLeading; TextOut(hdc,X,Y,lpsz_4,strlen(lpsz_4));//输出文本SetTextColor(hdc,RGB(255,0,0));//设置文本颜色为红色X=0;//设定输出文本的X坐标位置Y=Y+tm.tmHeight+30*tm.tmExternalLeading; TextOut(hdc,X,Y,lpsz_5,strlen(lpsz_5)); //输出文本//在该行继续输出文本 GetTextExtentPoint32(hdc,lpsz_5,strlen(lpsz_5),&size); //获取字符串的宽度 X=X+size.cx;//获取起始坐标 TextOut(hdc,X,Y,lpsz_6,strlen(lpsz_6)); //输出文本EndPaint(hwnd,&ps); 24 break; case WM_DESTROY: DeleteObject(hF_black);//退出窗口时删除自定义字体DeleteObject(hF_big);PostQuitMessage(0);break; default: return DefWindowProc(hwnd,message,wParam,lParam);} return 0; } 25 【4-3】在窗口中显示出26个英文字母,从左向右字母依次位置提高10个象素单位,并且颜色变为红色,然后回到正常位置;当到达最右端后改变方向从右向左依次变成红色并位置提高10个象素单位。在窗口的第二行显示26个字母,字体从正常到斜体,颜色从黑色到天蓝色不断变换。如图所示。用nChar标志红色跳起字母在26个字母的位置用bRight,bLeft标志当前移动方向,初始化bRight=TRUE,bLeft=FALSE26 本例题要解决动态显示问题: WM_CREATE消息处理程序调用SetTimer(…)创建定时器WM_TIMER调用InvalidateRect(…)刷新消息处理程序用户区发送WM_PAINT消息实现动态显示首先处理第一行字符:在WM_PAINT消息处理程序中,在得到了设备环境句柄hDC后,调用用户自定义的函数 CreateFont(hDC,nHeight,bItalic),第一个参数hDC是设备环境句柄,第2个参数nHeight是字体高度,第3个参数bItalic是斜字 27体的标志变量 下面这段程序按照黑色的字体输出从字符串开头到当前位置的字符串:Y=tm.tmExternalLeading+10;//设置输出字符的Y坐标for(i=0;i TextOut(hDC,X,Y,&lpsz_1[i],1);//输出从第0个到第nChar-1个字符}下面输出当前位置上的字符,当前位置的字符位置提高10个象素单位,字体颜色为红色: SetTextColor(hDC,RGB(255,0,0));//设置字体的颜色为红色X=X+tm.tmAveCharWidth*2;//设置输出字符的X,Y坐标Y=tm.tmExternalLeading;//提高10个像素hF = CreateFont(hDC,40,0);//创建字体SelectObject(hDC,hF);//选入字体 TextOut(hDC,X,Y,&lpsz_1[nChar],1);//输出第nChar个字符Y=tm.tmExternalLeading+10;for(i=nChar+1;i 下面设置bRight和bLeft的值。 if(nChar == nCharlen)//当输出到最后的一个字符时{ bRight = FALSE;//改变红色字移动的方向为向左bLeft = TRUE;} else(nChar == 0)//当输出到第一个字时{ bRight = TRUE;//改变红色字移动的方向为向右bLeft = FALSE;} if(bRight == TRUE) nChar++; else nChar--;如果nChar==等于字符串长度=〉已到了字符串末尾,将bRight置为True字符长度==0时,已到了最左端,将bLeft置为True; 当bRight=True时字符位置标志nChar加1,当bLeft=True时,字符位置标 29 志变量减1。 下面输出第2行字符:在WM_PAINT处理程序中,加入下列代码: hF = CreateFont(hDC,40,bItalic);//创建字体.大小为40SelectObject(hDC,hF);//选入字体X = tm.tmAveCharWidth*2;//设置输出位置Y = tm.tmHeight*2;if(bItalic == TRUE) SetTextColor(hDC,RGB(0,0,0));else SetTextColor(hDC,RGB(0,255,255)); TextOut(hDC,X,Y,lpsz_1,strlen(lpsz_1));//输出if(bItalic == TRUE) bItalic=FALSE;else bItalic=TRUE;调用用户自定义函数CreateFont(…)创建斜体字,确定输出位置根据bItalic的状态设置字体的颜色。 当bItalic为真时,输出斜体天蓝色字符;为假时,输出正常黑色字体最后对bItalic取反,在下一次显示与此次不同的另一种效果。30 【例4-4】将一首四句的古诗从右到左竖排输出。要求窗口每次接收到WM_PAINT消息时都刷新显示的文本。 31 #include long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam);BOOL InitWindowsClass(HINSTANCE hInstance); BOOL InitWindows(HINSTANCE hInstance,int nCmdShow);HWND hWndMain; //主函数 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MSG Message; if(!InitWindowsClass(hInstance))return FALSE;if(!InitWindows(hInstance,nCmdShow))return FALSE;while(GetMessage(&Message,0,0,0))//消息循环 {TranslateMessage(&Message); DispatchMessage(&Message);} return Message.wParam;32 } long WINAPI WndProc(HWND hWnd,UINT iMessage,UINT wParam,LONG lParam)1. { static long nXChar,nCaps,nYChar;2. int pointx,pointy,int i,j;3. HDC hDC; //定义指向设备环境的句柄4. TEXTMETRIC tm;//存放字体各种属性的结构体变量5. PAINTSTRUCT PtStr; //指向包含绘图信息的结构体变量6. static char *textbuf[4]={{\"故人西辞黄鹤楼\烟花三月下扬州\ {\"孤帆远影碧空尽\唯见长江天际流\ 7. switch(iMessage) //处理消息8. {case WM_CREATE://处理窗口创建消息9.hDC=GetDC(hWnd) ; //获取当前设备表句柄10.GetTextMetrics(hDC,&tm); //获取字体信息11.nXChar=tm.tmAveCharWidth; //获取字符宽度12. nYChar=tm.tmHeight+tm.tmExternalLeading;//字符高度13.nCaps=(tm.tmPitchAndFamily&1?3:2)*nXChar/2;//字间距14.ReleaseDC(hWnd,hDC); return 0;//释放当前设备句柄15.case WM_PAINT: //处理重画消息16.hDC=BeginPaint(hWnd,&PtStr); //开始绘图17.for(i=4;i>0;i--) 18.{for(j=0;j<7;j++)//输出文本19.{ pointx=100+i*nXChar*5;pointy=50+j*(nYChar+nCaps);20.TextOut(hDC,pointx,pointy,textbuf[4-i]+j*2,2); } }21. EndPaint(hWnd,&PtStr); return 0; //结束绘图22.case WM_DESTROY: //结束应用程序 33PostQuitMessage(0);return 0; 23.default:return(DefWindowProc(hWnd,iMessage,wParam,lParam));}} 创建自定义字体的例题程序。在窗口中显示“自定义的字体”,字体颜色为红色,背景色为蓝色。其运行结果应如下图所示: 34 LRESULT CALLBACK WndProc( HWND hwnd,UINT message, WPARAM wParam,LPARAM lParam) 1. {HDC hdc ;//设备句柄2.PAINTSTRUCT ps ;//画刷结构3.int Xchar,Ychar;4.SIZE size; 5.LPCTSTR *pstring= “自定义的字体”;6.RECTrect ;//无效矩形区7.HFONT holdFont,hnewFont;8.switch (message)//消息处理函数9.{case WM_CREATE:return 0; //窗口创建10.case WM_PAINT://绘制消息11.hnewFont=CreateFont //创建一种新的逻辑字体12.( ,0, 0, 0, 500,0,0,0,13.GB2312_CHARSET, 14. OUT_DEFAULT_PRECIS,15.CLIP_DEFAULT_PRECIS,16.DEFAULT_QUALITY, 17. DEFAULT_PITCH & FF_DONTCARE,3518.“黑体”); 19.hdc=BeginPaint (hwnd, &ps);//得到设备环境句柄20. GetClientRect (hwnd, &rect);//得到需要绘制的客户区21.holdFont=(HFONT)SelectObject(hdc,hnewFont); //选择新的字体22.SetTextColor(hdc,RGB(255,0,0));//设置文本颜色23.SetBkColor(hdc,RGB(0,0,255));//设置背景颜色24. GetTextExtentPoint32(hdc,pstring,12,&size);25.Xchar=(rect.right-rect.left)/2-size.cx/2; 26. Ychar=(rect.bottom-rect.top)/2-size.cy/2;27. TextOut(hdc,Xchar,Ychar,pstring,12);28. SelectObject(hdc,holdFont);//保存原来的字体格式29. DeleteObject(hnewFont);//删除新的字体格式30.EndPaint (hwnd, &ps) ;//结束绘制 return 0 ; case WM_DESTROY://退出消息PostQuitMessage (0) ;return 0 ; } return DefWindowProc(hwnd,message,wParam,lParam) ; 36 } 因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- igat.cn 版权所有 赣ICP备2024042791号-1
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务