GDI+学习及代码总结之------区域

在GDI+中,对于区域的部分基本上使用了GDI的区域构造函数与合并方法,所以我们先看看GDI中的区域是如何构造与操作的。

GDI中区域构建与操作

一、基本函数

创建矩形区域:

HRGN CreateRectRgnIndirect(CONST RECT *lprc);
HRGN CreateRectRgn(
				   int nLeftRect,   // left点坐标(X)
				   int nTopRect,    //top点坐标值(Y)
				   int nRightRect,  //right点坐标值(X)
				   int nBottomRect  //bottom点坐标值(Y)
				   );
创建椭圆区域:

HRGN CreateEllipticRgnIndirect(
							   CONST RECT *lprc   // bounding rectangle
							   );
HRGN CreateEllipticRgn(
					   int nLeftRect,   // x-coord of upper-left corner of rectangle
					   int nTopRect,    // y-coord of upper-left corner of rectangle
					   int nRightRect,  // x-coord of lower-right corner of rectangle
					   int nBottomRect  // y-coord of lower-right corner of rectangle
					   );
创建多边形区域:

HRGN CreatePolygonRgn(
					  CONST POINT *lppt,  // array of points
					  int cPoints,        // number of points in array
					  int fnPolyFillMode  // polygon-filling mode
					  );
合并区域:

int CombineRgn(
  HRGN hrgnDest,      // handle to destination region
  HRGN hrgnSrc1,      // handle to source region
  HRGN hrgnSrc2,      // handle to source region
  int fnCombineMode   // region combining mode
);
对于CombinMode有四个取值:
RGN_COPY:原样复制hrgnSrc1中的区域,一般不用这个,没太大意义;
RGN_AND:合成的区域是hrgnSrc1和hrgnSrc2的重叠部分;
RGN_DIFF:合成的区域是hrgnSrc1中不包含hrgnSrc2的部分;
RGN_OR:合成的区域同时包含hrgnSrc2和hrgnSrc2;
RGN_XOR:合成的区域同时包含hrgnSrc2和hrgnSrc2,但不包含hrgnSrc2和hrgnSrc2的重叠部分;

区域的句柄可用的4个绘图函数:

FillRgn(hdc, hRgn, hBrush);// 类似FillRect
FrameRgn(hdc, hRgn, hBrush, xFrame, yFrame);// 类似FrameRect
InverRgn(hdc, hRgn); //类似InvertRect
PaintRgn(hdc, hRgn);// 用设备描述表中的当前画刷填充所指的区域。
所有这些函数都假设区域是逻辑坐标定义的
删除一个区域
DeleteObject(hRgn);
//Windows的2个作用于区域而不是矩形的函数
InvalidateRgn(hwnd, hRgn, bErase); //类似于InvalidateRect
ValidateRgn(hwnd, hRgn); //类似于ValidateRect
上面两个函数也会以WM_PAINT消息作出反应
剪裁区域
首先是创建剪裁区域
SelectObject(hdc, hRgn);
SelectClipRgn(hdc, hRgn);
上面两个函数都是将一个区域选进设备描述表来创建自己的剪裁区域,这个剪裁区域使用设备坐标。
对剪裁区域的操作函数:
ExcludeClipRect 用于将一个矩形从剪裁区域里排除掉
IntersectClipRect 用于创建一个新的剪裁区域,他是前一个剪裁区域与一个矩形的交集
OffsetClipRgn 用于将剪裁区域移动到客户区的另一部分
注意:
GDI会为剪裁区域创建一个副本,所以在将新创建的区域选进设备描述表后,用户可以删除这个区域。
CombineRgn(hDestRgn, hSrcRgn1, hSrcRgn2, iCombine); 中使用的3个区域句柄必须都是有效的,即都要是创建了的。
在调用CombineRgn函数后,源区域即可以删除了,删除不会影响新合成的区域

看在GDI中使用区域函数的一个示例:(区域抠图)

原理:先用图片大小的矩形构造一个目的区域,所以这个区域的大小就是整个图片的大小,然后从图片的左上角(0,0)开始,按照从上到下、从左到右的顺序形成长宽都为1的矩形(就是一个像素大小),如果矩形中的背景是白色,将之从目的区域中去除,所以最终剩下的区域就是主画面的区域了。这就是“抠”出主界面区域的关键思路所在。

先看下原来的图片:

抠图代码:

Bitmap photo(L"wlh.bmp");
//得到相框尺寸
INT iWidth=photo.GetWidth();
INT iHeight=photo.GetHeight();

graphics.DrawImage(&photo,0,0,iWidth,iHeight);
//将绘图平面右移,设置新的绘图原点
graphics.TranslateTransform(iWidth+10,0);

Color color,colorTemp;
HRGN endRgn=CreateRectRgn(0,0,iWidth,iHeight);
//依次获取相框的每一个相素
for(int iRow=0;iRow<iHeight;iRow++){
	for(int iColumn=0;iColumn<iWidth;iColumn++){
		photo.GetPixel(iColumn,iRow,&color);
		//如果像素为白色,从原有区域中去除当前区域点
		if(color.GetR()==255&&color.GetG()==255&&color.GetB()==255){
			HRGN tempRgn=CreateRectRgn(iColumn,iRow,iColumn+1,iRow+1);
			CombineRgn(endRgn,tempRgn,endRgn,RGN_XOR);
		}//if--end
	}
}
//创建GDI+区域变量
Region fillrgn(endRgn);
graphics.FillRegion(&SolidBrush(Color::Green),&fillrgn);

GDI+中的区域构建与操作

一、构造函数(Region):

Region() 
Region(path) //从路径构建
Region(hRgn) //从GDI中的HRGN句柄构建
Region(Rect& rect) //从矩形构建
Region(RectF& rect) 
Region(regionData, size) //使用区域数组信息创建
这里有两个非常重要的构建函数,要说明一下:

Region(hRgn) //从GDI中的HRGN句柄构建
Region(Rect& rect) //从矩形构建
对于Region(hRgn):我们很多时候,可以用GDI中区域函数构建区域;然后使用这个构建函数,构建Regin变量,然后使用GDI+中的函数fillRegion啥啥的;
对于Region(Rect):Region类只提供了这么一个矩形构造函数,没有GDI中的椭圆、多边形区域的构建方法,所以当我们构建椭圆、多边形区域时,就是使用GDI了。

二、区域操作(构建区域)

对于GDI中的操作,我们知道CombineRgn的最后一个参数,可以实现对区域的RGN_AND、RGN_DIFF、RGN_OR、RGN_XOR

在GDI+中,Regin类中,也有对区域的操作函数,同样实现了GDI中的区域操作功能,它们分别是:

Region::Intersect(region)//求区域A和区域B的共有部分(交集)
Region::Union(region)//求同时包含区域A和区域B的区域(并集)
Region::Xor(region)//求不包含区域A和区域B相交部分的区域(异并集,又称为对称差)
Region::Complement(region)//求区域B中不含区域A的区域(A的补集)
Region::Exclude(region)//求区域A中不含区域B的区域(B的补集)
//异并集(集合的对称差):设A、B为任意两个集合,A和B的对称差为集合S,其元素或属于A,或属于B,但不能即属于A又属于B,这样的集合S称为集合A与B的对称差

简单的看一个示例吧,(异并集的)

Region rgn1(RectF(25,10,50,100));
Region rgn2(RectF(0,50,100,30));

Pen pen1(Color::Red,2);
Pen pen2(Color::Blue,2);
SolidBrush brush(Color::Green);

rgn1.Xor(&rgn2);
graphics.TranslateTransform(20,0);//转变绘制原点,这里这句并不是必须的,我只是为了让大家记住这个函数
graphics.FillRegion(&brush,&rgn1);
graphics.DrawRectangle(&pen1,RectF(25,10,50,100));
graphics.DrawRectangle(&pen2,RectF(0,50,100,30));

三、用矩形表示区域

对于特定的区域,我们都可以使用多个矩形来表示其大致形状。事实上,如果矩形足够小,一定数量的矩形就能够精确表示区域的形状,也就是说,一定数量的矩形所合成的形状,也可以代表区域的形状。Region类的GetRegionScans函数,实现了获取组成区域的矩形集的功能,其调用格式如下:

GetRegionScans(Matrix* matrix, Rect* rects, INT* count) 
GetRegionScans(Matrix* matrix, RectF* rects, INT* count) 
参数:
matrix:[in]绘制平面上的坐标变换矩阵
rects:[out]代表矩形集的数组
count:[out]矩形集的数量,该值可以通过GetRegionScansCount函数获取。

示例:

SolidBrush solidBrush(Color::Red);
Pen pen(Color::Green);
GraphicsPath path;
Matrix matrix;
Rect *rects=NULL;
INT count=0;

path.AddEllipse(10,0,80,120);
Region patchRegion(&path);
graphics.FillRegion(&solidBrush,&patchRegion);

graphics.GetTransform(&matrix);
count=patchRegion.GetRegionScansCount(&matrix);
//为矩形集分配空间
rects=(Rect*)malloc(count*sizeof(Rect));

patchRegion.GetRegionScans(&matrix,rects,&count);
graphics.TranslateTransform(140,0);
for(INT j=0;j<count;j++){
	graphics.DrawRectangle(&pen,rects[j]);
}
free(rects);

四、击中测试区域(判断点是否在区域内)

击中测试(HitTest),简单地说就是判断一个点是否位于指定的区域内。Region类的成员函数IsVisible提供了这样一个功能。而且还提供了扩展:不仅可以测试一个点是否位于指定的区域中,还可以测试两矩形区域是存否在交集。IsVisible的调用格式为:

IsVisible(Point& point, Graphics* g) 
IsVisible(PointF& point, Graphics* g) 
IsVisible(Rect& rect, Graphics* g) 
IsVisible(RectF& rect, Graphics* g) 
IsVisible(INT x, INT y, Graphics* g) 
IsVisible(REAL x, REAL y, Graphics* g) 
IsVisible(INT x, INT y, INT width, INT height, Graphics* g) 
IsVisible(REAL x, REAL y, REAL width, REAL height, Graphics* g) 
参数说明:
g:[in]绘图平面;
point:[in]点坐标;
rect及x,y,width,height:[in]定义欲测试的矩形区间;

示例:
考虑这样一个应用,当鼠标移动到指定区域时,输出字符串“yes”,否则擦掉这个字符串(擦除操作是用填充背景颜色完成的);

在View类中的OnMouseMove(UINT nFlags, CPoint point)添加如下代码:

	Graphics graphics(this->GetDC()->m_hDC);

	FontFamily ff(L"Arial");
	Font font(&ff,15,FontStyleRegular,UnitPixel);

	Region rgn(RectF(10,10,100,200));
	bool binrgn=rgn.IsVisible(point.x,point.y,&graphics);
	graphics.DrawRectangle(&Pen(Color::Green,2),RectF(10,10,100,200));
	if(binrgn){
		graphics.DrawString(L"yes",-1,&font,PointF(200,10),&SolidBrush(Color::Red));
	}else{
		graphics.FillRectangle(&SolidBrush(Color::White),RectF(200,10,100,100));
	}




 



  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
易语言是一种基于Windows操作系统的编程语言,其可以使用GDI(图形设备接口)来进行图像处理操作。在使用GDI进行内存转换图像格式时,可以借助凌晨孤星.rar这个插件来实现。 凌晨孤星.rar是一个易语言的第三方插件,其中包含了一些用于图像处理的函数和方法。通过引用这个插件,我们可以在易语言中调用其中的函数来实现对图像格式的转换。 具体步骤如下: 1. 首先,需要下载并解压凌晨孤星.rar插件文件。 2. 打开易语言的开发环境,创建一个新的项目文件。 3. 在该项目文件中,点击菜单栏的“插件”选项,然后选择“插件管理器”。 4. 在插件管理器中,点击“添加”按钮,并选择之前解压的凌晨孤星.rar文件。 5. 添加成功后,可以在插件管理器中看到凌晨孤星插件的名称。 6. 在项目中,通过代码调用插件中的相关函数来完成图像格式的转换操作。可以参考插件提供的文档或示例代码来使用。 7. 在代码中,可以使用插件提供的函数来加载图像文件、转换图像格式,并将结果保存到内存中。 8. 在转换完成后,可以通过插件提供的函数来获取转换后的图像数据,并按需进行后续处理或展示。 总之,凌晨孤星.rar插件提供了易语言中使用GDI进行内存转换图像格式的功能。通过引用该插件,并根据插件提供的函数调用方式,我们可以在易语言中实现图像格式的转换操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值