搞了三个月,搞不定,API的文字镜面翻转问题
背景是GradientFill填充的一个渐变
然后DrawText一个文本到中间
现在希望在文本下实现翻转特效,不是旋转,是水平或者垂直翻转,就好象水中的倒影
这个难道用GDI不能实现吗?
[最优解释]
Option Explicit
Private Declare Function BeginPath Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function EndPath Lib "gdi32" (ByVal hdc As Long) As Long
Private Declare Function TextOut Lib "gdi32" Alias "TextOutA" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As String, ByVal nCount As Long) As Long
Private Declare Function GetPath Lib "gdi32" (ByVal hdc As Long, lpPoint As POINTAPI, lpTypes As Byte, ByVal nSize As Long) As Long
Private Declare Function CreatePolyPolygonRgn Lib "gdi32" (lpPoint As POINTAPI, lpPolyCounts As Long, ByVal nCount As Long, ByVal nPolyFillMode As Long) As Long
Private Declare Function FillRgn Lib "gdi32" (ByVal hdc As Long, ByVal hRgn As Long, ByVal hBrush As Long) As Long
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function SelectClipRgn Lib "gdi32" (ByVal hdc As Long, ByVal hRgn As Long) As Long
Private Declare Function ReleaseDC Lib "user32" (ByVal hwnd As Long, ByVal hdc As Long) As Long
Private Declare Function DeleteObject Lib "gdi32" (ByVal hObject As Long) As Long
Private Declare Function GetStockObject Lib "gdi32" (ByVal nIndex As Long) As Long
Private Declare Function FlattenPath Lib "gdi32" (ByVal hdc As Long) As Long
Private Const PT_MOVETO = &H6
Private Const PT_LINETO = &H2
Private Const PT_CLOSEFIGURE = &H1
Private Const PT_BEZIERTO = &H4
Private Const BLACK_BRUSH = 4
Private Declare Function GetRgnBox Lib "gdi32" (ByVal hRgn As Long, lpRect As RECT) As Long
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Const WINDING = 2
Private Const ALTERNATE = 1
Private Type POINTAPI
x As Long
y As Long
End Type
Private Sub Command1_Click()
Me.FontSize = 48
Dim hdc As Long
hdc = GetDC(Me.hwnd)
BeginPath hdc
TextOut hdc, 50, 100, "山", 2 '为简单起见,用独体字作为例子,这样得到的路径只有一个多边形
EndPath hdc
TextOut hdc, 50, 100, "山", 2
FlattenPath hdc '为简单起见,把路径关键点强制转换为起点、终点类型,除二者之外,可能还有贝塞尔控制点等等
Dim nSz As Long
Dim pts() As POINTAPI, types() As Byte
ReDim pts(0), types(0)
nSz = GetPath(hdc, pts(0), types(0), 0) '获取路径关键点个数
ReDim pts(nSz - 1), types(nSz - 1)
GetPath hdc, pts(0), types(0), nSz 'pts存放坐标,types存放点类型,即起点6,终点2,封闭点3,一个字可能有多个多边形构成,也就有多个起点
Dim i As Long
For i = 0 To nSz - 1
pts(i).y = 320 - pts(i).y '变换坐标,这里是反转纵坐标,相当于垂直镜像
Next
Dim hRgn As Long
Dim nCounts(0 To 0) As Long
'nCounts为路径中每个多边形的点数数组,实际使用你需要自己计算数组大小和每个多边形的点数,可通过types进行
nCounts(0) = nSz
hRgn = CreatePolyPolygonRgn(pts(0), nCounts(0), 1, WINDING) '创建多边形区域
FillRgn hdc, hRgn, GetStockObject(BLACK_BRUSH) '填充区域,把变换后的字显示出来
DeleteObject hRgn
ReleaseDC Me.hwnd, hdc
End Sub
'窗体上放1个命令按钮Command1,2个图片框Picture1,Picture2
Option Explicit
Private Declare Function GetPixel Lib "gdi32 " (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long
Private Declare Function SetPixel Lib "gdi32 " (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal crColor As Long) As Long
Private Sub Command1_Click()
With Picture1
.AutoRedraw = True
.ScaleMode = vbPixels
.FontSize = 30
.ForeColor = &HFF
.CurrentX = .ScaleWidth / 4
.CurrentY = .ScaleHeight / 4
End With
Picture1.Print "不就看背面吗有什么难的 "
Picture1.Refresh
Dim x As Integer, y As Integer
Dim w As Integer, h As Integer
Dim c As Long
Dim h1 As Long, h2 As Long
w = Picture1.ScaleWidth
h = Picture1.ScaleHeight
Picture2.ScaleMode = vbPixels
Picture2.AutoRedraw = True
h1 = Picture1.hdc
h2 = Picture2.hdc
For x = 0 To w
For y = 0 To h
c = GetPixel(h1, x, y)
SetPixel h2, w - x, y, c
DoEvents
Next y
Next x
Picture2.Refresh
End Sub
Private Sub Form_Load()
Picture1.AutoRedraw = False
Picture2.AutoRedraw = False
End Sub
CurrentDC=GetDC()
StretchBit(CurrentDC,....,TempDC....,SRCCOPY)
ReleaseDC(CurrentDC)
DeleteDC(TempDC)
DeleteObject(hFont)
结果在StretchBit这句直接报错,界面出现一个Error的MsgBox
[其他解释]
给个思路,伪码:
BeginPath '开启路径
TextOut '输出文字
EndPath '结束路径
GetPath '获取路径(文字的轮廓,关键点坐标数组)
... '做你想做的变换(坐标变换而已,想干嘛都行)
CreatePolyPolygonRgn '根据变换后的文字轮廓创建区域
FillRgn '填充变换后文字区域
drawMirrorText Picture1, "ABCdefg" '镜像绘制字串(目的PictureBox,字串)
End Sub
Private Function drawMirrorText(mPic As PictureBox, mStr As String) '镜像绘制字串(目的PictureBox,字串)
Dim mRC As RECT
DrawText mPic.hdc, mStr, -1, mRC, DT_CALCRECT '取得字串宽高
mRC.Left = (mPic.ScaleWidth - mRC.Right) / 2 '左右居中
mRC.Right = mRC.Left + mRC.Right
mRC.Top = (mPic.ScaleHeight - (mRC.Bottom * 2)) / 2 '上下居中(共2行高)
mRC.Bottom = mRC.Top + mRC.Bottom
StretchBlt mPic.hdc, 0, mPic.ScaleHeight - 1, mPic.ScaleWidth, -mPic.ScaleHeight, mPic.hdc, 0, 0, mPic.ScaleWidth, mPic.ScaleHeight, vbSrcCopy '上下翻转原图形
DrawText mPic.hdc, mStr, -1, mRC, DT_SINGLELINE '绘制镜像字串
StretchBlt mPic.hdc, 0, mPic.ScaleHeight - 1, mPic.ScaleWidth, -mPic.ScaleHeight, mPic.hdc, 0, 0, mPic.ScaleWidth, mPic.ScaleHeight, vbSrcCopy '再次上下翻转图形回正向
DrawText mPic.hdc, mStr, -1, mRC, DT_SINGLELINE '绘制正向字串
mPic.Refresh
End Function
[其他解释]
感谢各位了
最近出差
结贴