17.8 利用GDI+实现翻页效果(3)
翻转过程完整代码如下:
- 01 void CMyBookDlg::RightTurn()
- 02 {
- 03 Graphics g(dcMemory.m_hDC); //内存设备
- 04 Image bk_image(L"背景\\bg002.bmp"); //载入背景图像
- 05 Image image(L"001.jpg");
- 06 g.DrawImage(&bk_image,m_bkRect.left,m_bkRect.top,
- 07 m_bkRect.Width(),m_bkRect.Height());
- 08 Color clrPen(255,0,0,0); //定制画刷画笔
- 09 Pen penDraw(clrPen,1 );
- 10 SolidBrush solidBrush(Color(255, 255, 255, 255));
- 11 double a = 45 + ((45 * m_x) /(m_pPage[0]->GetWidth()));
- 12 double radians = a * (PI / 180.0);
- 13 double pageUndersideRotationAngle = (180 - (2 * a));
- //计算区域3翻转角度
- 14 double calculated_y = 0;
- 15 double calculated_x = 0;
- 16 calculated_y = (m_x)* (tan(radians)); //calculated_y就是h
- 17 int width = m_pPage[0]->GetWidth(); //图像宽度
- 18 int height = m_pPage[0]->GetHeight(); //图像高度
- 19 if (m_x >= width) //翻页完成
- 20 { //直接绘制图像3和图像4
- 21 g.DrawImage(m_pPage[2],m_photoFrameLeft,m_photoFrameTop,
- 22 m_pPage[2]->GetWidth(),m_pPage[2]->GetHeight());
- 23 g.DrawImage(m_pPage[3],
- 24 m_photoFrameLeft + m_pPage[2]->GetWidth(),
- 25 m_photoFrameTop,m_pPage[3]->GetWidth(),
- 26 m_pPage[3]->GetHeight());
- 27 PostMessage(WM_MY_TURN,0,0);
- 28 if(m_bTOnce)
- 29 m_bTOnce = false;
- 30 }
- 31 else
- 32 { //首先将图像1和图像2完全绘制出来
- 33 g.DrawImage(m_pPage[0],m_photoFrameLeft,m_photoFrameTop,
- 34 m_pPage[0]->GetWidth(),m_pPage[0]->GetHeight());
- 35 g.DrawImage(m_pPage[1],
- 36 m_photoFrameLeft + m_pPage[0]->GetWidth(),
- 37 m_photoFrameTop,m_pPage[1]->GetWidth(),
- 38 m_pPage[1]->GetHeight());
- 39 GraphicsPath gpLeft,gpRight;
- 40 int undersideOffset = width;
- 41 if(calculated_y < height)
- 42 { //计算三角形时区域2的路径
- 43 gpLeft.AddLine( PointF(abs(width - m_x + undersideOffset),
- height),
- 44 PointF(width + undersideOffset, height));
- 45 gpLeft.AddLine( PointF(width + undersideOffset, height),
- 46 PointF(width + undersideOffset,
- 47 (height - (float)calculated_y)));
- 48 }
- 49 else
- 50 { //计算梯形时区域2的路径
- 51 gpLeft.AddLine(PointF(abs(width - m_x + undersideOffset), height),
- 52 PointF(width + undersideOffset, height));
- 53 gpLeft.AddLine(PointF(width + undersideOffset, height),
- 54 PointF(width + undersideOffset, 0));
- 55 calculated_x = height / tan(radians);
- 56 gpLeft.AddLine( PointF(width + undersideOffset, 0),
- 57 PointF(abs(width - (m_x - (float) calculated_x) +
- 58 undersideOffset),0));
- 59 }
- 60 gpLeft.CloseFigure();
- 61 Matrix PathTranslationMatrix;
- 62 PathTranslationMatrix.Translate((float)m_photoFrameLeft,
- 63 (float)m_photoFrameTop);//移动原点
- 64 gpLeft.Transform(&PathTranslationMatrix);
- 65 Region oldRegion;
- 66 g.GetClip(&oldRegion); //保存原属性
- 67 g.SetClip(&gpLeft); //设置路径
- 68 g.DrawPath(&penDraw,&gpLeft);
- 69 g.DrawImage(m_pPage[3],
- 70 m_photoFrameLeft + m_pPage[3]->GetWidth(),
- 71 m_photoFrameTop,m_pPage[3]->GetWidth(),
- 72 m_pPage[3]->GetHeight()); //绘制区域2
- 73 g.SetClip(&oldRegion); //回复原属性
- 74 //图像3的画板
- 75 Bitmap pageUndersideImage(width,height);
- 76 undersideOffset = width;
- 77 if(calculated_y < height)
- 78 { //计算三角形时区域3的路径
- 79 gpRight.AddLine( PointF(abs(width - m_x - undersideOffset), height),
- 80 PointF(width - undersideOffset, height));
- 81 gpRight.AddLine( PointF(width - undersideOffset, height),
- 82 PointF(width - undersideOffset,
- 83 (height - (float)calculated_y)));
- 84 }
- 85 else
- 86 { //计算梯形时区域3的路径
- 87 gpRight.AddLine(PointF(abs(float(width) - m_x – underside-
- Offset), height),
- 88 PointF(width - undersideOffset, height));
- 89 gpRight.AddLine(PointF(width - undersideOffset, height),
- 90 PointF(width - undersideOffset, 0));
- 91 //绘制对称线
- 92 calculated_x = height / tan(radians);
- 93 gpRight.AddLine( PointF(width - undersideOffset, 0),
- 94 PointF(abs(width - (m_x - (float)
- calculated_x) –
- 95 undersideOffset), 0));
- 96 }
- 97 Graphics ug(&pageUndersideImage);
- 98 ug.SetClip(&gpRight); //设置图像3的路径
- 99 ug.DrawPath(&penDraw,&gpRight);
- 100 ug.DrawImage(m_pPage[2], 0,0,m_pPage[3]->GetWidth(),
- 101 m_pPage[3]->GetHeight()); //绘制图像3
- 102 Matrix PathTranslationMatrix1;
- 103 PathTranslationMatrix1.Translate(m_photoFrameLeft +
- 104 m_pPage[3]->GetWidth()*2 - m_x,
- 105 m_photoFrameTop +
- 106 m_pPage[3]->GetHeight());
- //移动原点
- 107 //将图像3的画板旋转pageUndersideRotationAngle度
- 108 PathTranslationMatrix1.Rotate((float)(pageUndersideRotation-
- Angle ));
- 109 g.SetTransform(&PathTranslationMatrix1);
- 110 //绘制区域3
- 111 g.DrawImage(&pageUndersideImage, -int(m_x) ,-height ,width,
- height );
- 112 }
- 113 PageInit();
- 114 }
【代码解析】
第3~7行设置内存设备环境,并将背景图像绘制到内存设备上。第8~10行定制画笔和画刷。第11~13行计算对称线角度及区域3需要旋转的角度。第14~18行计算图像的高度,宽度及h(h的含义见上面的分析过程)的值。当整个翻页过程完成后在,第21~26行直接绘制图像3和图像4,此时图像1和图像2已经被完全覆盖,无须再绘制。在翻页过程没有完成时,第33~38行将先绘制图像1和图像2。第44~59行计算区域2的路径,其中第44~48行计算的是三角形时区域2的路径(见图17.21),第50~59行计算的是梯形时区域2的路径(见图17.22)。第60~73行将原点移到图像1的左上角(也就是相册的左上角,这样便于绘图)后,根据区域2的路径,绘制图像4。第77~96行定义了一个区域3的临时画板,并计算出区域3在临时画板上的路径(也是分三角形和梯形计算)。第97~101行根据计算的路径将图像3绘制到新画板上。第102~111行将坐标原点移动到翻动轴点,坐标系旋转pageUndersideRotationAngle后,绘制图像3的临时画板。