LaVolpe
Apr 4th, 2010, 01:48 PM
What is the .Render (http://msdn.microsoft.com/en-us/library/aa244163(v=VS.60).aspx) method of the stdPicture object and how does one use it.
FYI: a stdPicture object is either an object declared as stdPicture or any VB .Picture/.Image property, including those of forms, image controls, pictureboxes, etc. Some other properties may be stdPicture objects too, like a command button's .DisabledPicture property or a form's .Icon property.
:rolleyes: The .Render method has all the benefits of VB's PaintPicture method, except one, and has a few additional benefits that VB's PaintPicture does not. In short, you have some more flexibility with .Render, but its usage is not widely known or understood.
:confused: What does PaintPicture do that .Render cannot? It can render a stdPicture object with different raster operations, i.e., vbSrcPaint, vbSrcErase, etc. The .Render method cannot by itself. SetROP2 (http://msdn.microsoft.com/en-us/library/aa453651.aspx) API can do the job though.
:thumb: What does .Render do that PaintPicture cannot? A few things
1. It can render to any DC, memory DC, DC returned by API, or VB .hDC property (major advantage)
2. It can render transparent GIFs, maintaining transparency (minor advantage)
3. It is faster because less VB overhead is involved
;) What APIs do PaintPicture & .Render replicate? BitBlt, StretchBlt, DrawIcon, DrawIconEx and metafile rendering. So you see, you have some powerful API replication in some common VB methods.
:( Why is .Render not understood well? Because it is harder to use and PaintPicture can suffice a vast majority of the time and is easier to use. To understand .Render, you need to understand a bit about bitmaps and .Render's parameter requirements
a. Destination parameters for .Render are in pixels
b. Source parameters for .Render are in himetrics
c. stdPicture objects are DIBs, stored upside down. So source parameters must be flipped vertically when rendering.
:cool: Knowing the above, one can build a custom Render function using a stdPicture object. The following includes options for: stretching, scaling, offsetting, centering, partial rendering, and user-defined scalemodes.
Simply copy & paste to your project. Commented well in the code.
Tip: To make copying easier, hit the "Quote" button below & copy from that window.
Private Function RenderStdPicture(theTarget As Variant, thePic As StdPicture, _
Optional ByVal destX As Long, Optional ByVal destY As Long, _
Optional ByVal destWidth As Long, Optional ByVal destHeight As Long, _
Optional ByVal srcX As Long, Optional ByVal srcY As Long, _
Optional ByVal srcWidth As Long, Optional ByVal srcHeight As Long, _
Optional ByVal ParamScaleMode As ScaleModeConstants = vbUser, _
Optional ByVal Centered As Boolean = False, Optional ByVal ZoomFactor As Single = 1&) As Boolean
' Return Value [out]
' If no errors occur, return value is True. If error or invalid parameters passed, value is False
' Parameters [in]
' theTarget: a VB form, picturebox, usercontrol or a valid hDC (no error checking for valid DC)
' ... If Object, then it must expose a ScaleMode and hDC property
' ... and if centering and an object, must also expose ScaleWidth & ScaleHeight properties
' thePic: a VB ImageControl, stdPicture object, or VB .Picture property
' destX: horizontal offset on theTarget where drawing begins, default is zero
' destY: vertical offset on theTarget where drawing begins, default is zero
' destWidth: rendered image width & will be multiplied against ZoomFactor; default is thePic.Width
' destHeight: rendered image height & will be multiplied against ZoomFactor; default is thePic.Height
' srcX: horizontal offset of thePic to begin rendering from; default is zero
' srcY: vertical offset of thePic to begin rendering from; default is zero
' srcWidth: thePic width that will be rendered; default is thePic.Width
' srcHeight: thePic height that will be rendered; default is thePic.Height
' ParamScaleMode: Scalemode for passed parameters.
' If vbUser, then theTarget scalemode is used if theTarget is an Object else vbPixels if theTarget is an hDC
' Centered: If True, rendered image is centered in theTarget, offset by destX and/or destY
' If theTarget is a DC, then Centered is ignored. You must pass the correct destX,destY values
' ZoomFactor: Scaling option. Values>1 zoom out and Values<1||>0 zoom in
' Tip: To stretch image to a picturebox dimensions, pass destWidth & destHeight
' as the picturebox's scalewidth & scaleheight respectively and ZoomFactor of 1
If thePic Is Nothing Then Exit Function ' sanity checks first
If thePic.Handle = 0& Then Exit Function
If ZoomFactor <= 0! Then Exit Function
Dim Width As Long, Height As Long, destDC As Long
' the stdPicture.Render method requires vbPixels for destination and vbHimetrics for source
Width = ScaleX(thePic.Width, vbHimetric, vbPixels) ' image size in pixels
Height = ScaleY(thePic.Height, vbHimetric, vbPixels)
On Error Resume Next
If IsObject(theTarget) Then ' passed object? If so, set scalemode if needed
If theTarget Is Nothing Then Exit Function
If ParamScaleMode = vbUser Then ParamScaleMode = theTarget.ScaleMode
destDC = theTarget.hDC
ElseIf IsNumeric(theTarget) Then ' passed hDC? If so, set scalemode if needed
If ParamScaleMode = vbUser Then ParamScaleMode = vbPixels
destDC = Val(theTarget)
Centered = False ' only applicable if theTarget is a VB object
Else
Exit Function ' unhandled; abort
End If
If Err Then ' checks above generated an error; probably passing object without scalemode property?
Err.Clear
Exit Function
End If
If destWidth Then ' calculate destination width in pixels from ParamScaleMode
destWidth = ScaleX(destWidth, ParamScaleMode, vbPixels) * ZoomFactor
Else
destWidth = Width * ZoomFactor
End If
If destHeight Then 'calculate destination height in pixels from ParamScaleMode
destHeight = ScaleY(destHeight, ParamScaleMode, vbPixels) * ZoomFactor
Else
destHeight = Height * ZoomFactor
End If
' get destX,destY in pixels from ParamScaleMode
If destX Then destX = ScaleX(destX, ParamScaleMode, vbPixels)
If destY Then destY = ScaleY(destY, ParamScaleMode, vbPixels)
If Centered Then ' Offset destX,destY if centering
destX = (ScaleX(theTarget.ScaleWidth, theTarget.ScaleMode, vbPixels) - destWidth) / 2 + destX
destY = (ScaleY(theTarget.ScaleHeight, theTarget.ScaleMode, vbPixels) - destHeight) / 2 + destY
End If
' setup source coords/bounds and convert to vbHimetrics
If srcX Then srcX = ScaleX(srcX, ParamScaleMode, vbHimetric)
If srcY Then srcY = ScaleY(srcY, ParamScaleMode, vbHimetric)
If srcWidth Then srcWidth = ScaleX(srcWidth, ParamScaleMode, vbHimetric) Else srcWidth = thePic.Width
If srcHeight Then srcHeight = ScaleY(srcHeight, ParamScaleMode, vbHimetric) Else srcHeight = thePic.Height
If Err Then ' passed bad parameters or
Err.Clear ' passed object that has no ScaleMode property (i.e., VB Frame)
Else
With thePic ' render, the "Or 0&" below are required else mismatch errors occur
.Render destDC Or 0&, destX Or 0&, destY Or 0&, destWidth Or 0&, destHeight Or 0&, _
srcX Or 0&, .Height - srcY, srcWidth Or 0&, -srcHeight, ByVal 0&
End With ' return success/failure
If Err Then Err.Clear Else RenderStdPicture = True
End If
On Error GoTo 0
End Function
Edited: Short version, no resizing, scaling, positioning, or any other options. Just draw picture at 0,0 coordinates on any DC
' destDC can be any DC
Dim thePic As stdPicture
Set thePic = LoadPicture("C:\Images\Screenshots\image1002.jpg")
With thePic
.Render destDC Or 0&, 0&, 0&, ScaleX(.Width, vbHimetric, vbPixels), ScaleY(.Height, vbHimetric, vbPixels), _
0&, .Height, .Width, -.Height, ByVal 0&
End With
FYI: a stdPicture object is either an object declared as stdPicture or any VB .Picture/.Image property, including those of forms, image controls, pictureboxes, etc. Some other properties may be stdPicture objects too, like a command button's .DisabledPicture property or a form's .Icon property.
:rolleyes: The .Render method has all the benefits of VB's PaintPicture method, except one, and has a few additional benefits that VB's PaintPicture does not. In short, you have some more flexibility with .Render, but its usage is not widely known or understood.
:confused: What does PaintPicture do that .Render cannot? It can render a stdPicture object with different raster operations, i.e., vbSrcPaint, vbSrcErase, etc. The .Render method cannot by itself. SetROP2 (http://msdn.microsoft.com/en-us/library/aa453651.aspx) API can do the job though.
:thumb: What does .Render do that PaintPicture cannot? A few things
1. It can render to any DC, memory DC, DC returned by API, or VB .hDC property (major advantage)
2. It can render transparent GIFs, maintaining transparency (minor advantage)
3. It is faster because less VB overhead is involved
;) What APIs do PaintPicture & .Render replicate? BitBlt, StretchBlt, DrawIcon, DrawIconEx and metafile rendering. So you see, you have some powerful API replication in some common VB methods.
:( Why is .Render not understood well? Because it is harder to use and PaintPicture can suffice a vast majority of the time and is easier to use. To understand .Render, you need to understand a bit about bitmaps and .Render's parameter requirements
a. Destination parameters for .Render are in pixels
b. Source parameters for .Render are in himetrics
c. stdPicture objects are DIBs, stored upside down. So source parameters must be flipped vertically when rendering.
:cool: Knowing the above, one can build a custom Render function using a stdPicture object. The following includes options for: stretching, scaling, offsetting, centering, partial rendering, and user-defined scalemodes.
Simply copy & paste to your project. Commented well in the code.
Tip: To make copying easier, hit the "Quote" button below & copy from that window.
Private Function RenderStdPicture(theTarget As Variant, thePic As StdPicture, _
Optional ByVal destX As Long, Optional ByVal destY As Long, _
Optional ByVal destWidth As Long, Optional ByVal destHeight As Long, _
Optional ByVal srcX As Long, Optional ByVal srcY As Long, _
Optional ByVal srcWidth As Long, Optional ByVal srcHeight As Long, _
Optional ByVal ParamScaleMode As ScaleModeConstants = vbUser, _
Optional ByVal Centered As Boolean = False, Optional ByVal ZoomFactor As Single = 1&) As Boolean
' Return Value [out]
' If no errors occur, return value is True. If error or invalid parameters passed, value is False
' Parameters [in]
' theTarget: a VB form, picturebox, usercontrol or a valid hDC (no error checking for valid DC)
' ... If Object, then it must expose a ScaleMode and hDC property
' ... and if centering and an object, must also expose ScaleWidth & ScaleHeight properties
' thePic: a VB ImageControl, stdPicture object, or VB .Picture property
' destX: horizontal offset on theTarget where drawing begins, default is zero
' destY: vertical offset on theTarget where drawing begins, default is zero
' destWidth: rendered image width & will be multiplied against ZoomFactor; default is thePic.Width
' destHeight: rendered image height & will be multiplied against ZoomFactor; default is thePic.Height
' srcX: horizontal offset of thePic to begin rendering from; default is zero
' srcY: vertical offset of thePic to begin rendering from; default is zero
' srcWidth: thePic width that will be rendered; default is thePic.Width
' srcHeight: thePic height that will be rendered; default is thePic.Height
' ParamScaleMode: Scalemode for passed parameters.
' If vbUser, then theTarget scalemode is used if theTarget is an Object else vbPixels if theTarget is an hDC
' Centered: If True, rendered image is centered in theTarget, offset by destX and/or destY
' If theTarget is a DC, then Centered is ignored. You must pass the correct destX,destY values
' ZoomFactor: Scaling option. Values>1 zoom out and Values<1||>0 zoom in
' Tip: To stretch image to a picturebox dimensions, pass destWidth & destHeight
' as the picturebox's scalewidth & scaleheight respectively and ZoomFactor of 1
If thePic Is Nothing Then Exit Function ' sanity checks first
If thePic.Handle = 0& Then Exit Function
If ZoomFactor <= 0! Then Exit Function
Dim Width As Long, Height As Long, destDC As Long
' the stdPicture.Render method requires vbPixels for destination and vbHimetrics for source
Width = ScaleX(thePic.Width, vbHimetric, vbPixels) ' image size in pixels
Height = ScaleY(thePic.Height, vbHimetric, vbPixels)
On Error Resume Next
If IsObject(theTarget) Then ' passed object? If so, set scalemode if needed
If theTarget Is Nothing Then Exit Function
If ParamScaleMode = vbUser Then ParamScaleMode = theTarget.ScaleMode
destDC = theTarget.hDC
ElseIf IsNumeric(theTarget) Then ' passed hDC? If so, set scalemode if needed
If ParamScaleMode = vbUser Then ParamScaleMode = vbPixels
destDC = Val(theTarget)
Centered = False ' only applicable if theTarget is a VB object
Else
Exit Function ' unhandled; abort
End If
If Err Then ' checks above generated an error; probably passing object without scalemode property?
Err.Clear
Exit Function
End If
If destWidth Then ' calculate destination width in pixels from ParamScaleMode
destWidth = ScaleX(destWidth, ParamScaleMode, vbPixels) * ZoomFactor
Else
destWidth = Width * ZoomFactor
End If
If destHeight Then 'calculate destination height in pixels from ParamScaleMode
destHeight = ScaleY(destHeight, ParamScaleMode, vbPixels) * ZoomFactor
Else
destHeight = Height * ZoomFactor
End If
' get destX,destY in pixels from ParamScaleMode
If destX Then destX = ScaleX(destX, ParamScaleMode, vbPixels)
If destY Then destY = ScaleY(destY, ParamScaleMode, vbPixels)
If Centered Then ' Offset destX,destY if centering
destX = (ScaleX(theTarget.ScaleWidth, theTarget.ScaleMode, vbPixels) - destWidth) / 2 + destX
destY = (ScaleY(theTarget.ScaleHeight, theTarget.ScaleMode, vbPixels) - destHeight) / 2 + destY
End If
' setup source coords/bounds and convert to vbHimetrics
If srcX Then srcX = ScaleX(srcX, ParamScaleMode, vbHimetric)
If srcY Then srcY = ScaleY(srcY, ParamScaleMode, vbHimetric)
If srcWidth Then srcWidth = ScaleX(srcWidth, ParamScaleMode, vbHimetric) Else srcWidth = thePic.Width
If srcHeight Then srcHeight = ScaleY(srcHeight, ParamScaleMode, vbHimetric) Else srcHeight = thePic.Height
If Err Then ' passed bad parameters or
Err.Clear ' passed object that has no ScaleMode property (i.e., VB Frame)
Else
With thePic ' render, the "Or 0&" below are required else mismatch errors occur
.Render destDC Or 0&, destX Or 0&, destY Or 0&, destWidth Or 0&, destHeight Or 0&, _
srcX Or 0&, .Height - srcY, srcWidth Or 0&, -srcHeight, ByVal 0&
End With ' return success/failure
If Err Then Err.Clear Else RenderStdPicture = True
End If
On Error GoTo 0
End Function
Edited: Short version, no resizing, scaling, positioning, or any other options. Just draw picture at 0,0 coordinates on any DC
' destDC can be any DC
Dim thePic As stdPicture
Set thePic = LoadPicture("C:\Images\Screenshots\image1002.jpg")
With thePic
.Render destDC Or 0&, 0&, 0&, ScaleX(.Width, vbHimetric, vbPixels), ScaleY(.Height, vbHimetric, vbPixels), _
0&, .Height, .Width, -.Height, ByVal 0&
End With