一般来说,大家都会使用PlgBlt进行图像旋转,其实系统还提供了另一种旋转方式——坐标转换,为了演示使用坐标转换进行图象旋转的方法,我编了一个通用的图象旋转类,代码如下: '建立一个CDC.cls的名文件,将下面代码粘贴进去即可。 '* ******************************************************* * '* 程序名称:CDC.cls '* 程序功能:利用坐标转换旋转图形 '* 作者:lyserver '* ******************************************************* * Option Explicit '数据类型定义 Private Type POINTAPI X As Long Y As Long End Type Private Type RECT Left As Long Top As Long Right As Long Bottom As Long End Type Private Type BITMAP '14 bytes bmType As Long bmWidth As Long bmHeight As Long bmWidthBytes As Long bmPlanes As Integer bmBitsPixel As Integer bmBits As Long End Type Private Type XFORM eM11 As Single eM12 As Single eM21 As Single eM22 As Single eDx As Single eDy As Single End Type 'API声明 Private Declare Function SetRect Lib "user32" (lpRect As RECT, ByVal X1 As Long, ByVal Y1 As Long, ByVal X2 As Long, ByVal Y2 As Long) As Long Private Declare Function CopyRect Lib "user32" (lpDestRect As RECT, lpSourceRect As RECT) As Long Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA" (ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hDC As Long) As Long Private Declare Function CreateCompatibleDC Lib "gdi32" (ByVal hDC As Long) As Long Private Declare Function DeleteDC Lib "gdi32" (ByVal hDC As Long) As Long Private Declare Function CreateCompatibleBitmap Lib "gdi32" (ByVal hDC As Long, ByVal nWidth As Long, ByVal nHeight As Long) As Long Private Declare Function SelectObject Lib "gdi32" (ByVal hDC As Long, ByVal hObject As Long) As Long Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long Private Declare Function BitBlt Lib "gdi32" (ByVal hDestDC As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hSrcDC As Long, ByVal xSrc As Long, ByVal ySrc As Long, ByVal dwRop As Long) As Long Private Declare Function SetGraphicsMode Lib "gdi32" (ByVal hDC As Long, ByVal iMode As Long) As Long Private Const GM_ADVANCED = 2 Private Declare Function GetWorldTransform Lib "gdi32" (ByVal hDC As Long, lpXform As XFORM) As Long Private Declare Function SetWorldTransform Lib "gdi32" (ByVal hDC As Long, lpXform As XFORM) As Long Private Declare Function DPtoLP Lib "gdi32" (ByVal hDC As Long, ByVal lpPoint As Long, ByVal nCount As Long) As Long '自定义常量 Private Const PI As Single = 3.14159265358979 '自定义模块级变量 Dim m_hSrcDC As Long Dim m_hSrcBmp As Long, m_hOldSrcBmp As Long Dim m_rcSrc As RECT '绑定指定的图片 Public Function Bind(ByVal Pic As StdPicture) As Boolean Dim bm As BITMAP Dim hBitmap As Long Dim clrBackground As Long Dim maxWidth(1) As Long, maxHeight(1) As Long Dim fRadian As Double, fSin As Double, fCos As Double Dim hDesktopDC As Long '释放内存资源 Call Class_Terminate '如果Pic为Nothing,直接退出 If TypeName(Pic) = "Nothing" Then Exit Function '获得源图像信息 If GetObjectAPI(Pic.Handle, Len(bm), bm) = 0 Then Exit Function SetRect m_rcSrc, 0, 0, bm.bmWidth, bm.bmHeight '获得桌面DC hDesktopDC = GetDC(0) '创建内存DC m_hSrcDC = CreateCompatibleDC(hDesktopDC) '创建内存位图 m_hSrcBmp = CreateCompatibleBitmap(hDesktopDC, m_rcSrc.Right, m_rcSrc.Bottom) m_hOldSrcBmp = SelectObject(m_hSrcDC, m_hSrcBmp) '释放桌面DC ReleaseDC 0, hDesktopDC '绘制源图像 Pic.Render CLng(m_hSrcDC), 0, 0, CLng(m_rcSrc.Right), CLng(m_rcSrc.Bottom), 0, Pic.Height, Pic.Width, -Pic.Height, 0 '设置返回值 Bind = True End Function '在指定的DC上旋转图像 Public Sub Rotate(ByVal hDC As Long, Optional ByVal lAngle As Long = 0) Static myXFORM As XFORM Static rcDraw As RECT Static startPt As POINTAPI Static lGraphicsMode As Long, lMapMode As Long Static fRadian As Single, fSin As Single, fCos As Single '如果DC非法则退出 If (m_hSrcDC = 0) Or (hDC = 0) Then Exit Sub '修改绘图模式和坐标 lGraphicsMode = SetGraphicsMode(hDC, GM_ADVANCED) fRadian = PI * lAngle / 180 '角度转换为弧度 fSin = Sin(fRadian) fCos = Cos(fRadian) myXFORM.eM11 = Round(fCos, 4) myXFORM.eM12 = Round(fSin, 4) myXFORM.eM21 = Round(-fSin, 4) myXFORM.eM22 = Round(fCos, 4) myXFORM.eDx = 0 myXFORM.eDy = 0 Call SetWorldTransform(hDC, myXFORM) '转换设备坐标为逻辑坐标 rcDraw.Top = 0 rcDraw.Left = 0 rcDraw.Right = m_rcSrc.Right rcDraw.Bottom = m_rcSrc.Bottom Call DPtoLP(hDC, ByVal VarPtr(rcDraw), 2) '计算旋转后的起始坐标 startPt.X = (rcDraw.Right - m_rcSrc.Right) / 2 startPt.Y = (rcDraw.Bottom - m_rcSrc.Bottom) / 2 '在旋转后的DC复制图像 BitBlt hDC, startPt.X, startPt.Y, m_rcSrc.Right, m_rcSrc.Bottom, m_hSrcDC, 0, 0, vbSrcCopy '恢复绘图模式和坐标 'SetWorldTransform hDC, m_oldXFORM 'SetGraphicsMode hDC, lGraphicsMode End Sub '释放内存资源 Private Sub Class_Terminate() If m_hSrcBmp <> 0 Then DeleteObject SelectObject(m_hSrcDC, m_hOldSrcBmp) End If DeleteDC m_hSrcDC End Sub 二?调用代码: Option Explicit Dim m_lDegree As Long Dim m_DC As CDC Private Sub Form_Load() Set m_DC = New CDC m_DC.Bind LoadPicture("c:/temp/temp1.jpg") '绑定到1幅400*300的图像上 End Sub Private Sub Form_Unload(Cancel As Integer) Set m_DC = Nothing End Sub Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 1 Then m_lDegree = CalcAngle(X, Y, True) '初始化角度 End If End Sub Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = 1 Then '随鼠标旋转图像 m_lDegree = CalcAngle(X, Y) m_DC.Rotate Picture1.hDC, m_lDegree End If End Sub Private Sub Picture1_Paint() m_DC.Rotate Picture1.hDC, m_lDegree End Sub '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ' 计算鼠标移动的角度 ' 由于数学全忘了,此函数从http://www.tenlin.com/read.php/161.htm中的VC代码改编而来 Public Function CalcAngle(ByVal X As Single, ByVal Y As Single, Optional ByVal bReset As Boolean) As Long Static old_X As Single, old_Y As Single Dim tmp_X As Single, tmp_Y As Single, dist As Double Const PI As Single = 3.14159265358979 '重置原来的鼠标位置 If bReset Or (old_X = 0 And old_Y = 0) Then old_X = X old_Y = Y Exit Function End If '计算鼠标移动的距离 tmp_X = (X - old_X) ^ 2 tmp_Y = (Y - old_Y) ^ 2 dist = Sqr(tmp_X + tmp_Y) '计算鼠标移动的角度 tmp_X = Abs(X - old_X) tmp_Y = Abs(Y - old_Y) If Y > old_Y Then If X > old_X Then CalcAngle = Cos(tmp_X / dist) * 180 / PI + 90 ElseIf X = old_X Then CalcAngle = 180 Else CalcAngle = -Atn(tmp_Y / tmp_X) * 108 / PI + 90 End If ElseIf Y < old_Y Then If X > old_X Then CalcAngle = Sin(tmp_X / dist) * 180 / PI ElseIf X = old_X Then CalcAngle = 0 Else CalcAngle = -Atn(tmp_X / tmp_Y) * 180 / PI End If Else If X > old_X Then CalcAngle = 90 ElseIf X = old_X Then CalcAngle = 0 Else CalcAngle = -90 End If End If old_X = X old_Y = Y End Function '>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>