WINDOWS 程序设计教程(6章)_第1页
WINDOWS 程序设计教程(6章)_第2页
WINDOWS 程序设计教程(6章)_第3页
WINDOWS 程序设计教程(6章)_第4页
WINDOWS 程序设计教程(6章)_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第6章输出在多任务环境下,屏幕,打印机等硬件设备都是许多应用程序共享的,因此,任何一个应用程序都不能任意地进行输出操作,所有的输出,如屏幕,打印机,绘图机等,都必须通过GDI(图形设备接口(GRAPHISCDEVICEINTERFACE)函数来完成输出.本章表面上是讨论的字符串输出,实际上是讨论与设备无关的程序设计基础。本章例举了三个例程来说明应用程序的输出。6.1客户区的绘制和更新Windows是通过发送WM_PAINT消息給窗口函数,使得窗口显示输出。在初始化阶段都要调用函数UpdateWindow,执行这个函数的结果是Windows向窗口函数发送第一个WM_PAINT消息。其他还有很多情况下Windows向窗口函数发送WM_PAINT消息,使得被覆盖的部分客户区得以重新绘制。

发送WM_PAINT的情况P1026.1客户区的绘制和更新有效矩形和无效矩形1:Windows内部为每个窗口保存一个「绘图信息结构」,这个结构包含了包围无效区域的最小矩形的坐标以及其它信息,这个矩形就叫做「无效矩形」,有时也称为「无效区域」。如果在窗口消息处理程序处理WM_PAINT消息之前显示区域中的另一个区域变为无效,则Windows计算出一个包围两个区域的新的无效区域(以及一个新的无效矩形),并将这种变化后的信息放在绘制信息结构中。Windows不会将多个WM_PAINT消息都放在消息队列中。6.1客户区的绘制和更新有效矩形和无效矩形2:窗口消息处理程序可以通过呼叫InvalidataRect使显示区域无效.3:在处理WM_PAINT消息处理期间,窗口消息处理程序在呼叫了BeginPaint之后,整个显示区域即变为有效。程序也可以通过呼叫ValidateRect函数使显示区域内的任意矩形区域变为有效。如果这呼叫具有令整个无效区域变为有效的效果,则目前队列中的任何WM_PAINT消息都将被删除。6.1客户区的绘制和更新InvalidateRect只是增加重绘区域,在下次WM_PAINT的时候才生效,InvalidateRect函数中的参数TRUE表示系统会在你画之前用背景色将所选区域覆盖一次,默认背景色为白色,可以通过设置BRUSH来改变背景色。InvalidateRect(hWnd,&rect,TRUE);向hWnd窗体发出WM_PAINT的消息,强制客户区域重绘制,rect是你指定要刷新的区域,此区域外的客户区域不被重绘,这样防止客户区域的一个局部的改动,而导致整个客户区域重绘而导致闪烁,如果最后的参数为TRUE,则还向窗体发送WM_ERASEBKGND消息,使背景重绘,当然在客户区域重绘之前。UpdateWindow只向窗体发送WM_PAINT消息,在发送之前判断GetUpdateRect(hWnd,NULL,TRUE)看有无可绘制的客户区域,如果没有,则不发送WM_PAINT。如果希望立即刷新无效区域,可以在调用InvalidateRect之后调用UpdateWindow,如果客户区的任一部分无效,则UpdateWindow将导致Windows用WM_PAINT消息调用窗口过程(如果整个客户区有效,则不调用窗口过程)。这一WM_PAINT消息不进入消息队列,直接由WINDOWS调用窗口过程。窗口过程完成刷新以后立刻退出,WINDOWS将控制返回给程序中UpdateWindow调用之后的语句。6.2GDI简介所有输出都要通过GDI函数,当执行GDI函数输出时,可得到与设备无关的输出,其实现是源于Windows系统中为每一个设备建立一个数据结构,这个结构记录了设备输出时的详细要求,例如,输出时文字的颜色,线条的宽度,画图的坐标,…以及输出时调用的驱动程序等,这个数据结构称为设备描述表,简称DC。Windows系统中使用设备就抽象成使用DC。这种把设备抽象成为DC是实现设备无关性的关键。每个输出用的GDI函数其第1个参数就是hdc,hdc是指向DC的指针,GDI函数通过设备进行输出就变成通过DC进行输出。同样,要输出都得要考虑在那个窗口上输出,为此要为每个输出窗口建立一个数据结构--绘图信息结构(PAINTSTRUCT)注意:取得DC,必须释放DC且必须写到同一消息处理分支中例:P1056.2.2获得hDC代号的方法。1.利用GetDC(hWnd)取得窗口hDC.

hdc=GetDC(hwnd);

注意:GetDC不会使任何无效区域变为有效,可以使用validateRect(hwnd,NULL)使整个客户区有效。

ReleaseDC(hWnd,hdc);

2.处理WM_PAINT消息期间用

BeginPaint获得hDC的方法。

PAINTSTRUCTps

hdc=BeginPaint(hwnd,&ps);

TextOut(hdc,0,0,“Hello,Windows!”,15);

EndPaint(hwnd,&ps);

.

6.2.3绘图信息结构(PAINTSTRUCT)绘图信息结构(PAINTSTRUCT)typedef

struct

tagPAINTSTRUCT{ HDC hdc;//输出设备的设备描述表代号

BOOL fErase;//画图区域的背景要否擦去

RECT rcPaint;//画图区域坐标,无效矩形的边界,

BOOL fRestore;//操作系统用

BOOL fIncUpdate;//操作系统用

BYTE rgbReserved[32];//操作系统用}PAINTSTRUCT;通过PAINTSTRUCTps;定义变量,程序调用BeginPaint时,返回值是hDC,Windows会把它填入PAINTSTRUCT中。用户程序只使用画图信息结构的前三个条款,其他条款由Windows操作系统内部使用。hdc条款是BeginPaint的返回值。fErase被标志为FALSE(0),这意味著Windows已经擦除了无效矩形的背景。rcPaint

是一个结构指针,指向RECT结构,RECT结构记录着画图区域坐标,无效矩形的边界。6.2.3绘图信息结构(PAINTSTRUCT)在调用BeginPaint後PAINTSTRUCT结构的fErase条款将成为TRUE(非零)

PAINTSTRUCT结构的rcPaint条款是RECT类型的结构,RECT结构定义了一个无效矩形的边界坐标6.2.3绘图信息结构(PAINTSTRUCT)BOOLInvalidateRect(HWNDhWnd,//handleofwindowwithchangedupdateregionCONSTRECT*lpRect,//addressofrectanglecoordinatesBOOLbErase//erase-backgroundflag);

其中InvalidateRect(hwnd,NULL,true);重画时将擦除背景。InvalidateRect(hwnd,NULL,false);重画时不擦除背景6.3TextOut函数。TextOut是在屏幕上显示文字的最常用的GDI函数。语法是:TextOut(hdc,x,y,psText,iLength)hdc--屏幕也是设备。

1.hDC就是屏幕的设备描述表代号

2.x,y是客户区内输出字符串的开始地址,x是水平地址,y是垂直地址,

3.psText参数是指向需要在窗口显示的字符串的指针,

4.iLength是输出字符串中字符的个数6.4重画区域的设定WM_PAINT窗口消息并非只来源于Windows系统,它们可以使用InvalidateRect或InvalidateRgn函数直接产生并送消息队列。一般是先设定一个重画区,然后再用它们中的一个送WM_PAINT消息到消息队列,再排队进入窗口函数并在这个分支中进行重画。InvalidateRect设定的重画区是矩形,InvalidateRgn函数设定的重画区为不规则区域。6.4重画区域的设定InvalidateRect函数(MSDN)6.5系统字体字体的基本概念等宽字体和变宽字体6.5.1系统字体字体参数存贮在TEXTMETRIC类型的结构typedef

struct

tagTEXTMETRIC{ LONGtmHeight; LONGtmAscent; LONGtmDescent; LONGtmInternalLeading; LONGtmExternalLeading; LONGtmAveCharWidth;LONGtmMaxCharWidth;

其他结构条款}TEXTMETRIC系统定义的TEXTMETRICS的结构如下:typedefstructtagTEXTMETRIC

{ //tmLONGtmHeight; //字符高度LONGtmAscent; //字符基线以上高度LONGtmDescent; //字符基线以下高度LONGtmInternalLeading; //tmHeight制订的字符高度顶部的控件LONGtmExternalLeading; //行与行之间的间隔LONGtmAveCharWidth; //平均字符宽度LONGtmMaxCharWidth; //最大字符宽度LONGtmWeight; //字符的粗细度LONGtmOverhang; //合成字体间附加的宽度LONGtmDigitizedAspectX; //为输出设备设计的X轴尺寸LONGtmDigitizedAspectY; //为输出设备设计的Y轴尺寸BCHARtmFirstChar; //字体中第一个字符值BCHARtmLastChar; //字体中最后一个字符值BCHARtmDefaultChar; //代替不在字体中字符的字符BCHARtmBreakChar; //作为分割符的字符BYTEtmItalic; //非0则表示字体为斜体BYTEtmUnderlined; //非0则表示字体有下划线BYTEtmStruckOut; //非0则表示字符为删除字体BYTEtmPitchAndFamily; //字体间距和字体族BYTEtmCharSet; //字符集}TEXTMETRIC6.5.2系统字体用五个参数表示字体尺寸格式化文本(1)确定后续文本坐标换行时确定下一行文本的坐标需要格式化处理的情况在文本行中确定后续文本的坐标确定后续文本的坐标,应先获取当前的字符串的宽度,

该工作由GetTextExtentPoint32函数完成,并把它存储于一个SIZE结构中。BOOLGetTextExtentPoint32(

HDChdc,

LPCTSTRlpszString,//指定的字符串

int

nLength, //字符串中的字符数

LPSIZElpSize

//返回字符串宽度及高度的SIZE数据结构的地址)SIZE数据结构的定义typedefstructtagSIZE{LONGcx;

LONGcy;

}SIZE;例如,X轴起始坐标为cx0,后续文本起始坐标cx1为:

cx1=cx0+size.cx;

GetTextExtentPoint32(hDC,

Text,

lstrlen(Text),

size)

(2)确定换行时文本坐标字符的高度与行间隔均存储在tm指向的TEXTMETRIC结构中,换行时Y轴上文本的起始坐标cy为:

cy=tm.tmHeight+tm.tmExternalLeading;通过计算当前行文本字符的高度与行间隔之和,即可得到换行时文本的起始坐标6.5.3格式化文字下面是取得系统字体的字符宽度和高度的WM_CREATE程序码:caseWM_CREATE:hdc=GetDC(hwnd);//取得窗口的DCGetTextMetrics(hdc,&tm);//通过DC取得字体的尺寸信息存入tm结构cxChar=tm.tmAveCharWidth;//从tm结构中得到平均宽度cyChar=tm.tmHeight+tm.tmExternalLeading;//从tm结构中有关参数祘出总高度ReleaseDC(hwnd,hdc);//释放DC return0;6.5.3格式化文字int

iLength;//定义变量存放长度TCHARszBuffer[40];//宽字符数组,存放sprintf-wsprintf的格式化输出程序如下:iLength=wsprintf(szBuffer,TEXT("Thesumof%iand%iis%i"),

iA,iB,iA+iB);//TEXT把字符串输出,wsprintf将它存进szbufferTextOut(hdc,x,y,szBuffer,iLength);文本操作实例【例】在用户窗口上输出几行字符串,当窗口接收到WM_PAINT消息后,显示的文本每次都被重新刷新。#include<windows.h>#include<stdlib.h>#include<string.h>longWINAPIWndProc(

HWNDhWnd,

UINTiMessage,

UINTwParam,

LONGlParam

);BOOLInitWindowsClass(HINSTANCE

hInstance);BOOLInitWindows(HINSTANCE

hInstance,int

nCmdShow);//主函数intWINAPIWinMain(

HINSTANCEhInstance,

HINSTANCEhPrevInstance,

LPSTRlpCmdLine,

intnCmdShow){

MSGMessage;

if(!InitWindowsClass(hInstance)) returnFALSE;

if(!InitWindows(hInstance,nCmdShow))returnFALSE;

while(GetMessage(&Message,0,0,0))//消息循环

{

TranslateMessage(&Message);

DispatchMessage(&Message);

}

returnMessage.wParam;}//消息处理函数longWINAPIWndProc(HWND

hWnd,UINT

iMessage,UINT

wParam,LONG

lParam){

staticlongnXChar,nYChar;

HDChDC;//定义指向设备上下文的句柄

shortx;

TEXTMETRICtm;

shortLnCount=6;

PAINTSTRUCTPtStr;//定义指向包含绘图信息的结构体变量

staticchar*textbuf[]= {

"ThisistheFirstline",

"Thisisthesecondline",

"Thisisthethirdline",

"Thisisthefourthline",

"Thisisthefifthline",

"Thisisthesixthline"

};输出的文本内容switch(iMessage)//处理消息

{caseWM_CREATE: //处理窗口创建消息

hDC=GetDC(hWnd); //获取当前设备表句柄

GetTextMetrics(hDC,&tm); //获取字体信息

nXChar=tm.tmAveCharWidth; //获取字符宽度

nYChar=tm.tmHeight+tm.tmExternalLeading;

ReleaseDC(hWnd,hDC); //释放当前设备句柄

return0;

caseWM_PAINT: //处理重画消息

hDC=BeginPaint(hWnd,&PtStr); //开始绘画

for(x=0;x<LnCount;x=x+1) //输出文本

TextOut(hDC,nXChar,nYChar*(1+x),textbuf[x],lstrlen(textbuf[x]));

EndPaint(hWnd,&PtStr); return0;

caseWM_DESTROY: //结束应用程序

PostQuitMessage(0); return0;default: //其他消息处理程序

return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}}BOOLInitWindowsClass(HINSTANCE

hInstance) //初始化窗口类{

WNDCLASSWndClass; …………;

WndClass.style=CS_HREDRAW|CS_VREDRAW;

returnRegisterClass(&WndClass);}BOOLInitWindows(HINSTANCE

hInstance,int

nCmdShow)//初始化窗口{

HWNDhWnd;

hWnd=CreateWindow("WinText",//生成窗口

"文本显示示例程序", WS_OVERLAPPEDWINDOW, …….; NULL);

if(!hWnd) returnFALSE;

ShowWindow(hWnd,nCmdShow); //显示窗口

UpdateWindow(hWnd);

returnTRUE;}【例】将一首四句的古诗从右到左竖排输出。要求窗口每次接收到WM_PAINT消息时都刷新显示的文本。

#include<windows.h>#include<stdlib.h>#include<string.h>longWINAPIWndProc(HWND

hWnd,UINT

iMessage,UINT

wParam,LONG

lParam);BOOLInitWindowsClass(HINSTANCE

hInstance);BOOLInitWindows(HINSTANCE

hInstance,int

nCmdShow);

//主函数intWINAPIWinMain(HINSTANCE

hInstance,HINSTANCEhPrevInstance, LPSTRlpCmdLine,int

nCmdShow){ MSGMessage;

if(!InitWindowsClass(hInstance)) returnFALSE;

if(!InitWindows(hInstance,nCmdShow)) returnFALSE; while(GetMessage(&Message,0,0,0)) //消息循环

{TranslateMessage(&Message);

DispatchMessage(&Message); } returnMessage.wParam;}longWINAPIWndProc(HWND

hWnd,UINT

iMessage,UINTwParam,LONGlParam)1.{staticlongnXChar,nCaps,nYChar;2.int

pointx,pointy,i,j;3.HDChDC; //定义指向设备环境的句柄 4.TEXTMETRICtm; //存放字体各种属性的结构体变量5.PAINTSTRUCTPtStr; //指向包含绘图信息的结构体变量6.staticchar*textbuf[4]={{"故人西辞黄鹤楼"},{"烟花三月下扬州"}, {"孤帆远影碧空尽"},{"唯见长江天际流"}};7.switch(iMessage) //处理消息8.{ caseWM_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);return0; //释放当前设备句柄15. caseWM_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);return0; //结束绘图22. caseWM_DESTROY://结束应用程序

PostQuitMessage(0); return0;23. default: return(DefWindowProc(hWnd,iMessage,wParam,lParam));}}6.6字体显示的综合使用SYSMETS1.c

视觉元件信息表struct

{

int Index;//索引

TCHAR* szLabel;//指向宽字符的指针

TCHAR* szDesc;//指向宽字符的指针}sysmetrics;//这是定义的结构名,sysmetrics[]//此结构数组用作视觉元件信息表P1156.7SYSMETS1.c

SYSMETS1.c程序例子:6\SYSMETS1.c6.7SYSMETS1.cSYSMETS1.c窗口函数的分析。

SYSMETS1.c程序存在问题。6.8滚动条的使用滚动条的范围和地址6.8滚动条的使用滚动条的范围BOOLSetScrollRange(HWND

hWnd,//handletowindowwithscrollbarint

nBar,//scrollbarflagint

nMinPos,//minimumscrolling positionint

nMaxPos,//maximumscrollingpositionBOOL

bRedraw//redrawflag);

nBar:SB_HORZSetstherangeofawindow'sstandardhorizontalscrollbar.SB_VERTSetstherangeofawindow'sstandardverticalscrollbar.SetScrollRange()6.8滚动条的使用滚动条的地址int

SetScrollPos(HWND

hWnd,//handletowindowwithscrollbarint

nBar,//scrollbarflagint

nPos,//newpositionofscrollboxBOOL

bRedraw//redrawflag);

GetScrollPos()6.8滚动条的使用如果设置滚动范围为0到46.8滚动条的使用滚动条消息WM_VSCROLL(供上下移动)和WM_HSCROLL(供左右移动)消息。通知码的解释(MSDN中WM_VSCROLL)P123-124(注意)6.8滚动条的使用在SYSMETS1.C中加入滚动功能

(例子\6\SYSMETS2.C.doc)

6.8滚动条的使用

WM_VSCROLL消息分支中更新客户区的方法。6.9建立更好的滚动在使用滚动条功能时,如果要设置它的范围和位置可以用以前的函数,例如:SetScrollRange()、

SetScrollPos()、GetScrollRange(

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论