例如,可由前面所讲的文字路径(空心字符串)来构造文字区域,并进行鼠标点是否区域内的测试。代码如下(参见图13-9):
// 在视图类中定义区域指针类变量 #include
class CGdipDrawView : public CView { }
// 在视图类的(自己添加的重写型)初始化实例函数中,创建字符串路径和区域 void CGdipDrawView::OnInitialUpdate() { }
// 在视图类的OnDraw函数中绘制
void CGdipDrawView::OnDraw(CDC* pDC) { }
// 在视图类的左鼠标键松开的消息响应函数中,判断当前鼠标位置是否在文字区域中 void CGdipDrawView::OnLButtonUp(UINT nFlags, CPoint point) {
??
Region *m_pRgn;
CView::OnInitialUpdate(); FontFamily ff(L\隶书\GraphicsPath path;
path.AddString(L\文字区域\
Point(0, 0), NULL);
m_pRgn = new Region(&path);
……
Graphics graph(pDC->m_hDC);
graph.FillRegion(&SolidBrush(Color::Green), m_pRgn);
// TODO: 在此添加消息处理程序代码和/或调用默认值 if(m_pRgn->IsVisible(point.x, point.y))
MessageBox(L\鼠标在区域内\
else MessageBox(L\鼠标在区域外\
16
}
// 在视图类的析构函数中,删除所创建的区域对象 CGdipDrawView::~CGdipDrawView() { }
delete m_pRgn;
图13-9 击中测试
13.3 变换
变换(transform)是GDI+新增加的一种强大功能,包括图形对象的简单变换和基于矩阵的坐标变换、图形变换、图像变换、色彩变换、路径变换和区域变换等。
13.3.1 图形对象变换
GDI+的核心——图形类Graphics,提供了3个方法,可以对其所绘制的图形进行平移(translate)、旋转(rotate)和伸缩(scale,比例尺/缩放)等基本的图形变换(与纹理刷类中对应方法的原型是一样的):
Status TranslateTransform(REAL dx, REAL dy, MatrixOrder order = MatrixOrderPrepend); Status RotateTransform(REAL angle, MatrixOrder order = MatrixOrderPrepend); Status ScaleTransform(REAL sx, REAL sy, MatrixOrder order = MatrixOrderPrepend);
其中的最后一个输入参数为矩阵相乘的顺序,取值为矩阵顺序枚举类型MatrixOrder中的符号常量,默认值都为MatrixOrderAppend(左乘):
typedef enum {
MatrixOrderPrepend = 0, // 矩阵左乘(预先序,前置) MatrixOrderAppend = 1 // 矩阵右乘(追加序,后缀) } MatrixOrder
17
这些变换都可以用矩阵表示,而且要与图形对象已经设置的现有变换矩阵进行合成(相当于两个变换矩阵进行乘法运算)。
在图形对象的这三种基本变换中,最常用的是第一种——平移变换。我们在前面曾多次使用,避免了重复绘制(有坐标平移的)图形区域的麻烦。
1.平移变换
平移变换方法TranslateTransform,将所绘制图形的坐标(x, y)全部平移一个增量(dx, dy): Status TranslateTransform(REAL dx, REAL dy, MatrixOrder order = MatrixOrderPrepend); 即坐标变换:
x'?x?dx?x'??x??dx?,相当于矩阵变换:??y'?????y?????dy??,为了与旋转和伸缩等其y'?y?dy??????他变换合成,矩阵变换一般写为如下的齐次坐标形式:
?x'??10dx??x???????y'?01dy?????y? ?1??001??1???????例如(参见图13-10):
Graphics graph(pDC->m_hDC);
Rect rectSquare(10, 10, 100, 100),
rectCircle(120, 10, 100, 100);
graph.DrawRectangle(&Pen(Color::Green), rectSquare); graph.DrawEllipse(&Pen(Color::Green), rectCircle); graph.TranslateTransform(30, 20);
graph.DrawRectangle(&Pen(Color::Red), rectSquare); graph.DrawEllipse(&Pen(Color::Red), rectCircle);
图13-10 平移(30, 20)
图13-11 旋转30度
18
图13-12 旋转文本
2.旋转变换
旋转变换方法RotateTransform,将所绘制图形的坐标(x, y)全部(相对于[默认位于左上角的]坐标原点)旋转一个角度α= angle(单位为度):
Status RotateTransform(REAL angle, MatrixOrder order = MatrixOrderPrepend);
即:
x'?xcos??ysin??x'??cosα?sinα??x?????,相当于矩阵变换?或齐次坐标形式: ????????y'?xsin??ycos??y'??sinαcosα??y??x'??cosα?sinα0??x????????y'???sinαcosα0??y? ?1??0??01??????1?注意,旋转都是相对于坐标原点来进行的,为了使你的图形可以自由旋转,必须相对于原点来绘图。例如(参见图13-11):
Graphics graph(pDC->m_hDC);
Rect rectSquare(80, 10, 100, 100),
rectCircle(190, 10, 100, 100);
graph.DrawRectangle(&Pen(Color::Green), rectSquare); graph.DrawEllipse(&Pen(Color::Green), rectCircle); graph.RotateTransform(30.0f);
graph.DrawRectangle(&Pen(Color::Red), rectSquare); graph.DrawEllipse(&Pen(Color::Red), rectCircle);
又例如(旋转文本,参见图13-12):
Graphics graph(pDC->m_hDC); CRect crect;
GetClientRect(&crect);
PointF cp(REAL(crect.CenterPoint().x),
REAL(crect.CenterPoint().y));
Font font(L\宋体\
SolidBrush textBrush(Color::Red); StringFormat stringFormat;
stringFormat.SetLineAlignment(StringAlignmentCenter);
19
graph.TranslateTransform(cp.X, cp.Y); // 旋转中心 for (int i = 0; i < 360; i += 30) { }
graph.RotateTransform(30.0); // 旋转相对角度 //graph.RotateTransform(REAL(i)); // 旋转绝对角度 graph.DrawString(L\旋转文本测试\
PointF(20.0f, 0.0f), &stringFormat, &textBrush);
//graph.RotateTransform(REAL(-i)); // 还原
3.伸缩变换
伸缩变换方法ScaleTransform,将所绘制图形的形状在x和y方向上按指定比例sx和sy进行缩放:
Status ScaleTransform(REAL sx, REAL sy, MatrixOrder order = MatrixOrderPrepend); 即:
x'?sx?xy'?sy?y,相当于矩阵变换???x'??sx0??x??????0sy????y??或齐次坐标形式: y'???????x'??sx00??x???????y'?0sy0?????y? ?1??001??1???????例如(参见图13-13):
Graphics graph(pDC->m_hDC);
Rect rectSquare(10, 10, 100, 100),
rectCircle(120, 10, 100, 100);
graph.DrawRectangle(&Pen(Color::Green), rectSquare); graph.DrawEllipse(&Pen(Color::Green), rectCircle); graph.ScaleTransform(1.5f, 0.5f);
graph.DrawRectangle(&Pen(Color::Red), rectSquare); graph.DrawEllipse(&Pen(Color::Red), rectCircle);
还可以用负值参数来调用伸缩方法,达到镜像输出图形的效果。例如(镜像文本,参见图13-14):
20