资源描述:
《VC6屏幕绘图(GDI)基础.doc》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库。
VC6屏幕绘图(GDI)基础在VC6中,屏幕绘图是通过设备环境(DeviceContext)实现的,它是GDI的的关键元素。一、设备环境获取的一些函数:WINUSERAPIHDCWINAPIGetDC(HWNDhWnd);〃获取窗口的设备环境WINUSERAPIHDCWINAPIGetWindowDC(HWNDhWnd);WINGDIAPIHDCWINAPICreateCompatibleDC(HDC);二、设备环境的坐标:(1)、设备坐标:指的是显示设备或者打印设备坐标系下的坐标。这种坐标以设备上的像素点为坐标单位,通常情况下,它的原点在窗口客户区的左上角。(2)、逻辑坐标:指的是各种映射模式下的坐标。(3)、物理坐标:指的是开发人员白定义的坐标。三、设备环境的颜色COLORREF数据类型,用8位十六进制值OxOObbggrr表示一个RGB(红、绿、蓝)值,每个颜色分量的最大值为Oxff0获取一个COLORREF变量的各分量颜色值的宏:BYTEGetRValue(DWORDrgb);〃取得红色分量值BYTEGetGValue(DWORDrgb);〃取得绿色分量值BYETGetBValue(DWORDrgb);〃取得蓝色分量值COLORREFRGB(BYTEred,BYTEgreenzBYTEblue);四、使用GDI对象定义GDI对象后,要用SelectObject()函数把定义的GDI对象选择用在当前的环境中。例如:HDChdc;HBRUSHhbr;hdc=GetDC(hwnd);hbr=CreateSolidBrush(RGB(255,0,0));SelectObject(hdc,hbr);五、使用画刷I曲刷(HBRUSH)可以用来填充指定区域的特性。画刷通常包括填充颜色、填充图案、填充样式3种属性。〃创建实心曲刷HBRUSHCreateSolidBrush(COLORREF);〃创建填充画刷HBRUSHCreateHatchBrush(intindex,COLORREF);〃创建用位图作为填充的画刷HBRUSHCreatePatternBrush(HBITMAP);填充画刷参数index指定的填充样式如下:HS_BDIAGONALHS_CROSSHS_DIAGCROSSHS_FDIAGONAL〃从左到右往下的45度斜线〃十字线//45度交叉线〃从左到右往上的45度斜线 HS_HORIZONTALHS_VERTICAL〃水平线〃垂直线位图填充参数hbmp一般由下面函数获取:〃创建单色位图HBITMAPCreateBitmap(intwidthjntheight,UINTnc,UINTcolorbits,CONSTVOID*bitmapdata);〃连接图像HANDLELoadlmage(HINSTANCEhinstance,LPCTSTRimagename,UINTimagestyle,intwidthjntheight,UINT);目走义位須图1、白定义位图填充图像intbit[]={0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x96,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x96,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9巳0x23,0x56,0x8&0x33,0x48,0x61,0x85,0x96,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,0x33,0x48,0x61,0x85,0x9e,0x23,0x56,0x88,};intbitl[]={0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5”0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5,0x33e5,0x48e5,0x61e5,0x85e5,0x9ee5,0x23e5,0x56e5,0x88e5, intbit2[]={0x33e51a,0x48e51a,0x6:le5:laQx85e51a,0x9ee51aQx23e51a,0x56e5:La,0x88e51a,0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51a,0x48e51a,0x61e51%0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51aQx48e52a,0x61e51a’0x85e52aQx9ee52aQx23e52aQx56e51aQx88e5160x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,0x33e51aQx48e51a,0x6:le5:laQx85e5:la,0x9ee5:la'0x23e5:la,0x56e5:la‘0x88e5:la'0x33e51a,0x48e51a,0x61e51aQx85e5:la,0x9ee51a'0x23e5:la,0x56e51a’0x88e51a'0x33e51a,0x48e51a,0x61e51a,0x85e51a,0x9ee51a,0x23e51a,0x56e51a,0x88e51a,};voidpatternbitmap(intx」nty,intwidthjntheight,!ntpsw,intpshjntpattern[]」ntbits){HDChdc;hdc=GetDC(m_hwnd);HBITMAPhbmp=CreateBitmap(psw,psh/l,bits,pattern);HBRUSHhp=CreatePatternBrush(hbmp);SelectObject(hdc,hp);Rectangle(hdc,x“x+width,y+height);DeleteObject(hbmp);DeleteObject(hp);DeleteDC(hdc);}patternbitmap(50/50/100/100/8/8/bit/32);patternbitmap(200/50/100/100/8/8/bitlz32);patternbitmap(350/50z100/100/8,8zbit2z32);上面代码是图1的数据定义和实现过程。六、使用画笔(1)画笔的线型PS_DASHPS_DASHDOTPS_DASHDOTDOTPS_DOTPS_INSIDEFRAMEPS_NULLPS_SOLID(2)创建画笔函数HPENCreatePen(int例如:I曲笔(HPEN)是(GDI)提供用来绘制直线或Illi线的工具,価笔分为修饰画笔和儿何旳笔两种。一个画笔通常具有线型、宽度、颜色3种属性。线型为虚线点划线双点划线点线内框线,线的宽度不超过图形的框架线型为空实线nPenstle,intnWidth,COLORREFcrColor);HDChdc;HPENpen;hdc=GetDC(hwnd);pen=CreatePen(PS_SOLIDzlzRGB(0,0/255));SelectObject(hdc,pen); Arc(hdc,130,130,230,230,230,130,230,130);DeleteObject(pen);DeleteDC(hdc);程序结果见下图:图2、绘制圆形七、作用字体Windows的字体数据结构在LOGFONT:typedefstructtagLOGFONTALONGIfHeight;字体高度LONGIfWidth;字体宽度LONGIfEscapement;绘制文木时相对于X轴的倾斜角度LONGIfOrientation;字符基准线与X轴之间的夹角(1/10度为单位)LONGIfWeight;字体的粗细程度,取值范围从0到1000BYTEIfltalic;非零表示斜体BYTEIfUnderline;非零表示字体带有下划线BYTEIfStrikeOut;非零表示字体带有删除线BYTEIfCharSet;字体字符集BYTEIfOutPrecision;字符输出精度BYTEIfClipPrecision;字符裁减精度BYTEIfQuality;字体输出质量(外观相似度) BYTEIfPitchAndFamily;字符间距和字体类型CHARlfFaceName[LF_FACESIZE];字体名称通常用以下预定义字符集:标准字符集默认字符集中国国标码符号字符集}LOGFONTA,*PLOGFONTA/NEAR*NPLOGFONIA,FAR*LPLOGFONTA;IfCharSet表示字符集,ANSI_CHARSETDEFAUUT_CHARSETGB2312_CHARSETSYMBOL_CHARSET字体的创建函数:HFONTCreateFont(int,int,int,int,int,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,LPCTSTR);例如:HFONTmFont=CreateFont(-16/0/0/0,400/0/0,0zGB2312_CHARSET;0/0,0/FF_MODERN,"宋体”);上面代码声明了一个用屮国国标码字体大小为16的宋体字体变量。'.使用字体回WindowScreenCreateFontWindowScreenCreateFont欢迎使用Windows字体图3、屏幕绘制字体文木输出函数BOOLTextOut(HDC,int,intzLPCTSTR,int);第1个参数HDC输出设备第2和第3个参数分别是输出字体的X轴和Y轴坐标第4个参数是要输出的字体字符串第5个参数是要输出的字体字符串的长度设置文木字体颜色的函数COLORREFSetTextColor(HDC,COLORREF);设置文木字体背景颜色的函数COLORREFSetBkColor(HDC,COLORREF);设置文本背景模式的函数intSetBkMode(HDCJnt);第2个参数为模式值:TRANSPARENT(透明模式)和0PAQUE 例如:HFONTmFont二CreateFont(・16,OQO,40000,0,GB2312_CHARSEl;0O0,FF_M0DERN,”宋体”);HDChdc;hdc=GetDC(m_hwnd);SelectObject(hdc,mFont);SetTextColor(hdc,RGB(255z0,0));SetBkMode(hdcJRANSPARENT);TextOut(hdc50,30,"WindowScreenCreateFont"/24);DeleteObject(mFont);DeleteDC(hdc);八、GDI绘图函数1、绘制像素点的函数COLORREFSetPixeKHDCJntjntCOLORREF);BOOLSetPixelV(HDC,int,int,COLORREF);第1个参数HDC输出设备第2和第3个参数分别是输岀字体的X轴和Y轴坐标第4个参数是像素点颜色例如:voidputbitmap(intx,inty,char*filename){FILE*fp;fp=fopen(filename,”rb”);if(fp==NULL)return;intw,h,i,k;fseek(fp,18,SEEK_SET);fread(&wz4,lzfp);fread(&h,4,l,fp);unsignedchar*t;COLORREFmt;k=(w)*3;while(k%4)k++;t=newunsignedchar[k*h];fseek(fpz54,SEEK_SET);fread(t,k*h/l,fp);fclose(fp);HDChdc;hdc=GetDC(m_hwnd);for(i=k*h-l;i>2;i-=3)SetPixelV(hdc/x+(i%k)/3/h+y-i/k,mt); }DeleteDC(hdc);delete[]t;}putbitmap(0,0,”F:〃fj01.bmp”);Bitmap图4、用SetPixelV()绘制位图SetPixelV()不需要返回值,而SetPixel()要返回一个颜色值,因此SetPixelV()绘制速度更快。2、获取像素点颜色值的函数COLORREFGetPixeKHDCJntJnt);3、绘制折线的函数BOOLPolyline(HDC,CONSTPOINT*,int);第1个参数HDC输出设备第2个参数是一个坐标点数组第3个参数是表示数组中点的个数例如:voidrectangle(intxl,intylzintx2,inty2){POINTrt[5];HDChdc;HPENpen;hdc=GetDC(m_hwnd);pen=CreatePen(PS_SOLID,l,rn_color);rt[O].x=xl;rt[O].y=yl;rt[l].x=x2;rt[l].y=yl;rt[2].x=x2;rt[2].y=y2;rt[3].x=xl;rt[3].y=y2;rt[4].x=xl;rt[4].y=yl;SelectObject(hdc,pen);Polyline(hdc,rtz5);DeleteObject(pen);::DeleteDC(hdc);} rectangle(40,30,270,200);图5、绘制折线(Polyline)4、绘制圆弧的函数BOOLArcfHDCJntjntJntjntJntJntjntjnt);第1个参数HDC输出设备第2、3、4、5个参数定义了圆弧的外切矩形第6、7个参数指定了圆弧的起始点第&9个参数指定了圆弧的终止点Arc()函数可用来绘制圆形或椭圆形和开I」圆弧。例如:HDChdc=GetDC(hwnd);HPENpen=CreatePen(PS_SOLIDzl,RGB(OzOz130));SelectObject(hdc,pen);Arc(hdc,40,30,270,90,270,60,270,60);Arc(hdc,40,150,270,220,100,0,300,250);DeleteObject(pen);DeleteDC(hdc); 图6、绘制圆弧5、绘制Bezier曲线的函数BOOLPolyBezier(HDC,CONSTPOINT*,DWORD);第1个参数HDC输出设备第2个参数是一个坐标点数组笫3个参数是表示数组屮点的个数例如:POINTbBezier[]={{30,30}/{30/200}/{280,30},{280,200}};HDChdc=GetDC(hwnd);HPENpen=CreatePen(PS_SOUD,l/RGB(0A130));SelectObject(hdczpen);PolyBezier(hdc,bBezier,4);DeleteObject(pen);DeleteDC(hdc);图7、绘制Bezier曲线6、绘制矩形的函数BOOLRectanglefHDCJntjntjntJnt);BOOLRoundRect(HDC,int/int/int/int/int/int); RoundRect()绘制圆角矩形,第6、7个参数表示绘制圆角的椭圆大小。例如:HDChdc=GetDC(hwnd);HPENpen=CreatePen(PS_SOLIDzl,RGB(130/55,120));HBRUSHhp=CreateSolidBrush(RGB(130/55/120));SelectObject(hdc,hp);SelectObject(hdc,pen);RoundRect(hdcz40,30,270,200,60,60);DeleteObject(pen);DeleteObject(hp);DeleteDC(hdc);图8、绘制圆角矩形7、绘制多边形的函数BOOLPolygon(HDC,CONSTPOINT*,int);第1个参数HDC输出设备第2个参数是一个坐标点数组第3个参数是表示数组中点的个数例如:POINTpl[]={{20/60}/{50z50}/{120/110}/{70/90}/{100/150}/{60/200}/{20/100}};POINTps[]={{250,50},{200,200}/{300z100}/{160/100}/{300/200}}; HDChdc=GetDC(hwnd);HPENpen=CreatePen(PS_SOLIDJ,RGB(30,55」60));HBRUSHhp二CreateSolidBrush(RGB(30,55,160));SelectObject(hdc,hp);SelectObject(hdc,pen);Polygon(hdc,pl,7);Polygon(hdc,ps,5);DeleteObject(pen);DeleteObject(hp);DeleteDC(hdc);Polygon图9、绘制任意多边形8、绘制弦和扇形的函数BOOLChordfHDCJntJntJntJntJntJntJntJnt);BOOLPiefHDCJntJntjntJntJntJntJntJnt);第1个参数HDC输出设备第2、3、4、5个参数定义了圆弧的外切矩形第6、7个参数指定了圆弧的起始点第8、9个参数指定了圆弧的终止点用法和Arc()函数一样。9、绘制椭圆的函数(填充型)BOOLEllipsefHDCJntJntJntJnt);第2、3、4、5个参数是椭圆外切圆的参数。10、区域绘制图形函数HRGNCreateRectRgn(int/int,int/int);HRGNCreateRectRgnlndirect(CONSTRECT*);HRGNCreateEllipticRgnfintJntJntJnt);HRGNCreateEllipticRgnlndirect(CONSTRECT*);HRGNCreateRoundRectRgnfintJntjntjntjntjnt);例如:HDChdc=GetDC(hwnd);HRGNrgnl/rgn2/rgn3,rgn4;rgnl=CreateEllipticRgn(100/0/200,110);rgn2=CreateEllipticRgn(20z70/160z140);rgn3=CreateEllipticRgn(100,80,200,210);rgn4=CreateEllipticRgn(140/70,280,140);CombineRgn(rgnl/rgnl/rgn2,RGN_OR);CombineRgn(rgnljgnl,rgn3,RGN_OR); CombineRgn(rgnl/rgnl,rgn4,RGN_OR);HBRUSHhp=CreateSolidBrush(RGB(175z55/160));SelectObject(hdc,hp);FrameRgnfhdc^gnl,hp,2,2);//HBRUSHhat=CreateSolidBrush(RGB(190z160,180));//SelectObject(hdc,hat);//FillRgn(hdc,rgnlzhat);〃FloodFill(hdc,16(U00,RGB(175,55,160));DeleteObject(hp);//DeleteObject(hat);DeleteDC(hdc);图10、区域绘图(进行合并或操作) 注:合并区域图形的函数intCombineRgn(HRGN,HRGN,HRGN,in);勾画区域图形轮廓的函数BOOLFrameRgn(HDC,HRGN,HBRUSH/int/int);填充区域图形的函数BOOLFilIRgn(HDC,HRGN,HBRUSH);填充任意封闭图形的函数BOOLFloodFillfHDCJntJntXOLORREF);图11、填充区域图形11.使用位图(双缓存技术绘图)一般在屏幕里绘制图形时,如果是静止的,屏幕显示效果都不会变;如果是编写游戏稈序要在屏幕里不断的连续画图时,屏幕显示就会不断的闪烁。因为图形间颜色的茅异,绘制速度过快,人的眼睛观感跟不上,所以看到的是闪烁的图形。在相同的时间内减少绘图次数对屏幕闪烁有所缓解。为了解决屏幕闪烁问题,现在要用到位图,即双缓存绘制法。其基木原理是把要在屏幕里绘制的图形先绘制到一个和屏幕相兼容的位图缓存区,然麻再把缓存区里的位图复制到屏幕上。双缓存技术使川函数HDCGetDC(HWND);HDCCreateCompatibleDC(HDC);HBITMAPCreateCompatibleBitmap(HDC,int,int);HGDIOBJSelectObject(HDC,HGDIOBJ); BOOLBitBlt(HDC,int,int,int,int,HDC,int,int,DWORE);实现双缓存绘制图形过稈如下:HDChdc;HDCcompatibledc;HBITMAPhbmp;hdc=GetDC(hwnd);compatibledc=CreateCompatibleDC(hdc);hbmp=CreateCompatibleBitmap(hdc,320/250);SelectObjectfcompatibled^hbmp);HBRUSHhp,hb;HPENpen,pn;hp=CreateSolidBrush(RGB(33,165/90));pen=CreatePen(PS_SOLIDzl,RGB(33,165z90));SelectObject(compatibledc’hp);SelectObject(compatibledc,pen);Rectangle(compatibledc/50/30,270,200);DeleteObject(hp);DeleteObject(pen);hb=CreateSolidBrush(RGB(0,0,180));pn=CreatePen(PS_SOLID/lzRGB(0/0/180));SelectObject(compatibledc’hb);SelectObject(compatibledc,pn);Rectangle(compatibledcz100,80,220,160);DeleteObject(hb);DeleteObject(pn);BitBlt(hdc,0Q320,250,compatibledc,OQSRCCOPY);DeleteObject(hbmp);DeleteDC(hdc);DeleteDC(compatibledc); 图12、双缓存绘图技术图13、屏幕绘图图12和图13两图是用键盘上屏幕截图键摘下的上段代码生成的屏幕截图,图13里没有绘制的图形是因为屏幕闪烁的原因(即绘制速度过快,截屏功能没有捕捉到绘制屏幕图形颜色的信息所致)。把程序中的compatibledc改为hdc截图结果为图13的效果。12、使用位图填充oi刷HBRUSHCreatePatternBrush(HBITMAP);〃连接图像HANDLELoadlmage(HINS17NCEhinstance,LPCTSTRimagename,UINTimagestylejntwidthjntheight,UINT);用位图填充画刷可以快速的把一幅文件位图绘制到屏幕ffU例如:voiddrawbitmap(char*filename) FILE*fp;fp=fopen(filename,”rb”);if(fp==NULL)return;intw,h;fseek(fpz18,SEEK_SET);fread(&w,4J,fp);fread(&h,4,l,fp);fclose(fp);HDChdc;hdc=GetDC(m_hwnd);HBITMAPhbmp=(HBITMAP)Loadlmage(NULL/filenamezIMAGE_BITMAP,0/0/LR_LOADFROMFILE);HBRUSHhp=CreatePatternBrush(hbmp);SelectObject(hdczhp);Rectangle(hdczO,O,w,h);DeleteObject(hbmp);DeleteObject(hp);DeleteDC(hdc);}drawbitmap("F://fj01.bmp");”■使用墮冠画刷[=「图14、绘制文件位图注:drawbitmap(闲putbitmap()同是把文件位图绘制到屏幕上,前者是用填充位图I出i刷绘制位图,而后者是用像索点的形式绘制位图。两者的区别是前者的绘制速度快,它的输出位置必须是窗口的原点或是位图大小的整倍数移动,否则绘制的位图将出错;后者是绘制速度慢,但输出位置不受限制。第二部分建立Windows应用稈序前面简单介绍了VC6屏幕绘制图形的一些基础知识,要实现绘图还要建立一个Windows应用程序,申请一个可执行绘图的窗口。 —、打开VC6选择“文件”、“新建”二、按下图步骤建立.cpp文件三、编写代码#ineludevwindows.h>HWNDm_hwnd;HDChdc;HDCcompatibledc;HBITMAPhbmp;HWNDinitgraph(char*windname,intwidth,intheight);LRESULTCALLBACKWndProc(HWNDhwndzUINTmessage,WPARAMwparam,LPARAMIparam);voiddrawfunction(voidfunc());intgetmaxx()RECTrc;GetClientRect(m_hwnd,&rc);returnrc.right;}intgetmaxy(){ RECTrc;GetClientRect(m_hwnd,&rc);returnrc.bottom;}voiddraw()hdc=GetDC(m_hwnd);compatibledc=CreateCompatibleDC(hdc);hbmp=CreateCompatibleBitmap(hdc/getmaxx()/getmaxy());SelectObject(compatibledc,hbmp);HBRUSHhp二CreateSolidBrush(RGB(230,230,230));HPENpn=CreatePen(PS_SOLID/l,RGB(230/230z230));SelectObject(compatibledc/hp);SelectObjectfcompatibled^pn);Rectangle(compatibledc,0,0,getmaxx()尼etmaxy());DeleteObject(hp);DeleteObject(pn);〃在此处添加任何绘图代码(HDC用compatibledc—兼容设备de)BitBlt(hdc,0,0,getmaxx(),getmaxy(),compatibledcOO,SRCCOPY);DeleteObject(hbmp);DeleteDC(hdc);DeleteDC(compatibledc);HDChdc=GetDC(m_hwnd);}intmain(){initgraph("绘图框架程序",400,300);drawfunction(draw);return0;}voiddrawfunction(voidfunc())MSGmsg;BOOLfmsg;PeekMessage(&msg,NULL/OU,OU/PM_NOREMOVE);while(msg.message!=WM_QUIT){fmsg=PeekMessage(&msgzNULL/OU,OU,PM_REMOVE);if(fmsg){TranslateMessage(&msg);DispatchMessage(&msg);} elsefunc();}}HWNDinitgraph(char*windnamejntwidth,intheight){charstrTitle[255];GetConsoleTitlefstrTitle,255);HWNDhw=FindWindow("ConsoleWindowClass"/strTitle);CloseWindow(hw);WNDCLASSwc;HINSTANCEth=NULL;wc.style=CS_HREDRAW|CS_VREDRAW|CS_OWNDC;wc.lpfnWndProc=(WNDPROC)WndProc;wc.cbClsExtra=O;wc.cbWndExtra=O;wc.hbrBackground=HBRUSH(2);wc.hlnstance=th;wc.hCursor=LoadCursor(NULL,IDC_ARROW);wc.hlcon=NULL;wc」pszMenuName=NULL;wc」pszClassName="lspztiml";if(RegisterClass(&wc)==O)returnFALSE;m_hwnd二CreateWindow(”lspztiml”,windname,WS_MINIMIZEBOX|WS_SYSMENUQO,width,height,NULL,NULL,th,NULL);讦(m_hwnd==FALSE)returnFALSE;ShowWindow(m_hwnd,SW_SHOWDEFAULT);UpdateWindow(m_hwnd);returnm_hwnd;}LRESULTCALLBACKWndProc(HWNDhwndzUINTmessage,WPARAMwparam,LPARAMIparam)switch(message)caseWM_DESTROY:PostQuitMessage(O);break;}return(DefWindowProc(hwnctrnessage,wparam」param));} 图15、绘图框架稈序运行效果框架程序实现了双缓存绘图模式。结束语:GDI屏幕绘图是Windows应用程序里报基木的绘图,它不会过时,因为在VS2008里面的VC类一样有,用法基木一致,只是有些函数的变量定义类型有一些差异。那是因为VS2008是一个开发工具的集合,它兼容了以前备版本的环境,为了区分而改变。