CSDN论坛vb版中有一个@L_301_0@,在此我贴出解决代码。
代码原理原本就简单,所以注释也很简单。
希望能帮助到苦苦思索的朋友们。(魏滔序原创,转帖请注明出处。)
首先要下载一个IStream库,用该库可以减少代码量,如果直接全部用API也未尝不可。
IStream下载地址:IStream.zip
下面是代码,可以贴在一个模块中:
Option Explicit '常量声明 Private Const ClsidJPEG As String = "{557CF401-1A04-11D3-9A73-0000F81EF32E}" Private Const EncoderParameterValueTypeLong As Long = 4& Private Const EncoderQuality As String = "{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}" Private Const GdiPlusVersion As Long = 1& '结构声明 Private Type GUID Data1 As Long Data2 As Integer Data3 As Integer Data4(0 To 7) As Byte End Type Private Type IID Data1 As Long Data2 As Integer Data3 As Integer Data4(0 To 7) As Byte End Type Private Type PICTDESC cbSizeOfStruct As Long picType As Long hgdiobj As Long hPalOrXYExt As Long End Type Private Type EncoderParameter GUID As GUID NumberOfValues As Long Type As Long Value As Long End Type Private Type EncoderParameters Count As Long Parameter(15) As EncoderParameter End Type Private Type GDIPlusStartupInput GdiPlusVersion As Long DebugEventCallback As Long SuppressBackgroundThread As Long SuppressExternalCodecs As Long End Type Private Type GdiplusStartupOutput NotificationHook As Long NotificationUnhook As Long End Type '枚举声明 Private Enum Status OK = 0 GenericError = 1 InvalidParameter = 2 OutOfMemory = 3 ObjectBusy = 4 InsufficientBuffer = 5 NotImplemented = 6 Win32Error = 7 WrongState = 8 Aborted = 9 FileNotFound = 10 ValueOverflow = 11 AccessDenied = 12 UnknownImageFormat = 13 FontFamilyNotFound = 14 FontStyleNotFound = 15 NotTrueTypeFont = 16 UnsupportedGdiplusVersion = 17 GdiplusNotInitialized = 18 PropertyNotFound = 19 PropertyNotSupported = 20 ProfileNotFound = 21 End Enum 'API声明 Private Declare Function GdipCreateBitmapFromHBITMAP Lib "gdiplus" (ByVal hbm As Long,ByVal hpal As Long,ByRef bitmap As Long) As Status Private Declare Function GdipCreateHBITMAPFromBitmap Lib "gdiplus" (ByVal bitmap As Long,ByRef hbmReturn As Long,ByVal Background As Long) As Status Private Declare Function GdipDisposeImage Lib "gdiplus" (ByVal image As Long) As Status Private Declare Function GdipLoadImageFromStream Lib "gdiplus" (ByVal Stream As IUnknown,ByRef image As Long) As Status Private Declare Function GdiplusShutdown Lib "gdiplus" (ByVal token As Long) As Status Private Declare Function GdiplusStartup Lib "gdiplus" (ByRef token As Long,ByRef lpInput As GDIPlusStartupInput,ByRef lpOutput As GdiplusStartupOutput) As Status Private Declare Function GdipSaveImageToStream Lib "gdiplus" (ByVal image As Long,ByVal Stream As IStream,ByRef clsidEncoder As GUID,ByRef encoderParams As Any) As Status Private Declare Function CLSIDFromString Lib "ole32" (ByVal Str As Long,ByRef id As GUID) As Long Private Declare Function CreateStreamOnHGlobal Lib "ole32.dll" (ByRef hGlobal As Any,ByVal fDeleteOnRelease As Long,ByRef ppstm As Any) As Long Private Declare Sub OleCreatePictureIndirect Lib "oleaut32.dll" (ByRef lpPictDesc As PICTDESC,ByRef riid As IID,ByVal fOwn As Boolean,ByRef lplpvObj As Object) '根据版本初始化GDI+ Private Function StartUpGDIPlus(ByVal GdipVersion As Long) As Long Dim GdipToken As Long Dim GdipStartupInput As GDIPlusStartupInput Dim GdipStartupOutput As GdiplusStartupOutput GdipStartupInput.GdiPlusVersion = GdipVersion If GdiplusStartup(GdipToken,GdipStartupInput,GdipStartupOutput) = OK Then StartUpGDIPlus = GdipToken End If End Function '从图像转换为流 Public Function PictureToStream(ByVal Picture As StdPicture,Optional ByVal JpegQuality As Long = 85) As IStream Dim picStream As IStream Dim lBitmap As Long Dim tGUID As GUID Dim bytBuff() As Byte Dim tParams As EncoderParameters Dim lngGdipToken As Long lngGdipToken = StartUpGDIPlus(GdiPlusVersion) '检查JPG压缩比率 If JpegQuality > 100 Then JpegQuality = 100 If JpegQuality < 0 Then JpegQuality = 0 '创建Bitmap If GdipCreateBitmapFromHBITMAP(Picture.Handle,lBitmap) = OK Then '创建Stream If CreateStreamOnHGlobal(ByVal 0,False,picStream) = 0 Then '转换GUID If CLSIDFromString(StrPtr(ClsidJPEG),tGUID) = 0 Then '设置JPG相关参数值 tParams.Count = 1 With tParams.Parameter(0) CLSIDFromString StrPtr(EncoderQuality),.GUID .NumberOfValues = 1 .Type = EncoderParameterValueTypeLong .Value = VarPtr(JpegQuality) End With '将Bitmap数据保存到流(JPG格式) If GdipSaveImageToStream(lBitmap,picStream,tGUID,tParams) = OK Then Set PictureToStream = picStream End If End If Set picStream = Nothing End If End If GdipDisposeImage lBitmap '本行代码乃后期修正 GdiplusShutdown lngGdipToken End Function '从流转换为图像 Public Function StreamToPicture(ByVal Stream As IStream) As StdPicture Dim picStream As IStream Dim lBitmap As Long Dim hBitmap As Long Dim lngGdipToken As Long Dim tPictDesc As PICTDESC Dim IID_IPicture As IID Dim oPicture As IPicture lngGdipToken = StartUpGDIPlus(GdiPlusVersion) Set picStream = Stream '从Stream加载Bitmap If GdipLoadImageFromStream(picStream,lBitmap) = OK Then '根据Bitmap创建hBitbmp If GdipCreateHBITMAPFromBitmap(lBitmap,hBitmap,0) = OK Then With tPictDesc .cbSizeOfStruct = Len(tPictDesc) .picType = vbPicTypeBitmap .hgdiobj = hBitmap .hPalOrXYExt = 0 End With ' 初始化IPicture With IID_IPicture .Data1 = &H7BF80981 .Data2 = &HBF32 .Data3 = &H101A .Data4(0) = &H8B .Data4(1) = &HBB .Data4(3) = &HAA .Data4(5) = &H30 .Data4(6) = &HC .Data4(7) = &HAB End With Call OleCreatePictureIndirect(tPictDesc,IID_IPicture,True,oPicture) Set StreamToPicture = oPicture End If End If Set picStream = Nothing GdipDisposeImage lBitmap '本行代码乃后期修正 GdiplusShutdown lngGdipToken End Function
示例:
'示例 Private Sub Command1_Click() Dim s As IStream Set s = PictureToStream(Me.Picture1.Picture) Set Me.Picture2.Picture = StreamToPicture(s) End Sub