Click or drag to resize

LoadPicture Function

X#
-- todo --
Creates an object reference for a bitmap, icon, or Windows meta file.

Namespace:  XSharp.VFP
Assembly:  XSharp.VFP (in XSharp.VFP.dll) Version: 2.21
Syntax
 FUNCTION LoadPicture(
	cFileName
) AS Object CLIPPER
Request Example View Source

Parameters

cFileName (Optional)
Type: Usual
Specifies the image file on disk for which an object is created.
The supported images are listed in the remarks section

Return Value

Type: Object
Object LoadPicture() function returns a Picture type COM object reference that can be assigned to ActiveX controls and VFP’s Image object’s PictureVal property. However, the real primary interface iPicture only can be retrieved using code like this:br  
X#
1oIPicture = GETINTERFACE(LoadPicture(GetPict()), "iPicture")
Remarks
Supported Image Types
Image Type GroupsFilename Extensions
bitmaps.bmp, .jpg, .jpeg, .jpe, .jfif, .gif, .giff, .gfa
icons.ico
windows metafiles.wmf
windows enhanced metafiles.emf
cursor.cur
The following restrictions (tested with VFP 9 SP2 and OlePro32.dll Version 6.0.6002.18005) exist:
Known Limitations
Image Type GroupsRestrictions & Issues
bitmaps Loading these .tif and .png formats will cause an OLE error.
icons Icons are allowed with sizes up to 128x128 and must not have more than 256 colors. Even if there is more than one icon stored in the icon file, always only the smallest icon gets displayed. The icon file may contain much more icons - even with more colors and larger sizes - as long as there is at least one that complies with the rules above, then no exception is thrown.
cursor Cursor files must not have more than 1K of file size, otherwise an OLE error is generated. Cursor files containing 16 color cursors can be loaded flawlessly, but only monochrome output is supported. Loading an animated cursor (.ani) causes an OLE error to be raised.
Null Picture Support If cFileName is omitted, the "null picture" is returned. You can include GetPict( ) as cFileName to display the Open dialog from which you can choose a bitmap file.

Picture objects provide a language-neutral abstraction for bitmaps, icons, and metafiles. As with the standard font object, the system provides a standard implementation of the picture object. Its primary interfaces are iPicture and iPictureDisp. A picture object is created with OleCreatePictureIndirect and supports both the iPicture and the iPictureDisp interfaces. The OLE-provided picture object implements the complete semantics of the iPicture and iPictureDisp interfaces. In other words, there’s no need to use another interface than iPicture!
LoadPicture( ) Function internally wraps the OleCreatePictureIndirect() function implemented in OleAut32.dll. Thus, all you can read about that function (above and online) is also true for VFP’s LoadPicture() function. LoadPicture( ) Function was added to VFP’s vocabulary to make it easier to load images with COM interfaces that many presentation properties of ActiveX controls require for their settings.
For example, the ActiveX Outline control has a PictureOpen property that requires a COM object image reference for its setting. The COM object returned by LoadPicture( ) Function hides its primary interface iPicture. In contrast to the reference returnd by LoadPicture( ) Function, the OLE-image’s primary iPicture interface is the only fully functional one. In other words, only iPitcure can be used in VFP programms without generating any OLE errors. Because iPicture is a superset of Picture it may be, better, it should be used everywhere instead of the one returnd by LoadPicture( ) Function!
Example #1 in the examples section below proves that it makes no difference which OLE image interface gets assigned to a oIMAGE.PICTUREVAL property. The IID of the iPicture interface is defined as “{7BF80980-BF32-101A-8BBB-00AA00300CAB}”.

The following two lines of code both create a null picture OLE image object:
X#
1oIPicture1 = GETINTERFACE(LoadPicture(), "iPicture")
2oIPicture2 = CreateObjectEx("StdPicture","","{7BF80980-BF32-101A-8BBB-00AA00300CAB}")
Interfacemembers The following table summarizes the PEMs iPicture interface.
iPicture Interface Members
PEMNameUsed forValueTypeRead/Writable
propertyAttributesThe current set of the picture's bit attributes.DWORD (int)readonly
propertyCurDCThe current device context into which this picture is selected.HDC (long)readonly
propertyHandleHandle to the picture managed within this picture object.OLE_Handle (int)readonly
propertyHeightThe current height of the picture in the picture object.OLE_XSIZE_HIMETRIC (long)readonly
propertyhPalThe current palette of the picture (if any).OLE_Handle (int)read/writable
propertyKeepOriginalFormatThe current value of the picture object's KeepOriginalFormat property.Boolread/writable
propertyTypeThe current type of the picture.Short (int)readonly
propertyWidthThe current width of the picture in the picture object.OLE_XSIZE_HIMETRIC (long)readonly
methodPictureChanged()Notifies the picture object that its picture resource changed.
methodRender()Draws the specified portion of the picture onto the specified device context, positioned at the specified location.
methodSaveAsFile()Saves the picture's data into a stream in the same format that it would save itself into a file.
methodSelectPicture() Selects a bitmap picture into a given device context, returning the device context in which the picture was previously selected as well as the picture's handle.
The Attributes property is said to hold the picture’s bit attributes. Actually, there are only two, which can be set alone, or additive. The following table lists both possible values:
iPicture.Attributes Enumeration
ConstantDescriptionValue
PICTURE_SCALABLE The picture object is scalable, such that it can be redrawn with a different size than was used to create the picture originally. Metafile-based pictures are considered scalable; icon and bitmap pictures, while they can be scaled, do not express this attribute because both involve bitmap stretching instead of true scaling. 1
PICTURE_TRANSPARENT The picture object contains an image that has transparent areas, such that drawing the picture will not necessarily fill in all the spaces in the rectangle it occupies. Metafile and icon pictures have this attribute; bitmap pictures do not. 2
The following table lists all possible values of the iPicture.Type property:
ConstantDescriptionValue
PICTYPE_UNINITIALIZEDThe picture object is currently uninitialized. This value is never be returned within VFP.-1
PICTYPE_NONEA new picture object is to be created without an initialized state. This value is returned from VFP if LoadPicture() is used without a parameter.0
PICTYPE_BITMAPThe picture type is a bitmap.1
PICTYPE_METAFILEThe picture type is a metafile.2
PICTYPE_ICONThe picture type is an icon.3
PICTYPE_ENHMETAFILEThe picture type is an enhanced metafile.4
The most interesting method of the COM image object’s iPicture interface is render() which also works flawlessly only when called on the iPicture interface. The following table summarises the parameters of the render() method:
ParameterUsed forScale unit
hdcA handle of the device context on which to render the image.
xThe horizontal coordinate in hdc at which to place the rendered image (X-position of upper left corner of output rectangle).pixel
yThe vertical coordinate in hdc at which to place the rendered image (X-position of upper left corner of output rectangle).pixel
cxThe horizontal dimension (width) of the destination rectangle (with of output rectangle).pixel
cyThe vertical dimension (height) of the destination rectangle (height of output rectangle).pixel
xSrcThe horizontal offset in the source picture from which to start copying.HiMetric
ySrcThe vertical offset in the source picture from which to start copying.HiMetric
cxSrcThe horizontal extent to copy from the source picture (width of image source’s clipping region AND direction of readout).HiMetric
cySrcThe vertical extent to copy from the source picture (height of image source’s clipping region AND direction of readout).HiMetric
lprcWBounds If hdc is a metafile device context, the lprcWBounds parameter points to a RECTL structure specifying the bounding rectangle in the underlying metafile. The rectangle structure contains the window extent and window origin. These values are useful for drawing metafiles. The rectangle indicated by lprcBounds is nested inside this lprcWBounds rectangle; they are in the same coordinate space. If hdcDraw is not a metafile device context, lprcWBounds will be NULL. If hdcDraw is a metafile device context, lprcWBounds cannot be NULL!
The method returns standard values like E_FAIL, E_INVALIDARG and E_OUToFMEMORY, as well as S_OK, E_POINTER and CTL_E_INVALIDPROPERTYVALUE. These values are described on MSDN. applications The render function has plenty of parameters. Some of them passing in pixel values, others HiMetric values.
Example #3 has some useful conversions as well as other supporting functions and definitions.
To figure out how render() works try the VFP code below; type it in line by line into VFP’s command window:
Direct input into VFP’s command window
X#
 1* locate an image with round about 100 x 100 pixels
 2goPic = LoadPicture(GetPict())
 3gIP = GETINTERFACE(m.goPic, "iPicture")
 4goForm = CreateObject("Form")
 5goForm.Show()
 6* declare access to the _client_area_ of a window
 7DECLARE Integer GetDC IN User32 integer HWnd
 8* hDC should be  0 (otherwise that's an error)!
 9hDC = GetDC(goForm.HWnd)
10* render your image directly onto form's client area
11gIP.Render(m.hDC,0,0,100,100,0,gIP.Height,gIP.Width,- gIP.Height,NULL)
12* declare release function
13DECLARE Integer ReleaseDC IN User32 integer HWnd, integer hDC
14* next line should print 1 on the form's background >> "Okay"
15? ReleaseDC(m.goForm.HWnd, m.hDC)
16* declare access to the _whole_ window
17DECLARE Integer GetWindowDC IN User32 integer HWnd
18* hDC now references form's caption an border areas as well!
19hDC = GetWindowDC(goForm.HWnd)
20* render out partially overwriting form's border and caption
21gIP.Render(m.hDC,0,0,100,100,0,gIP.Height,gIP.Width,- gIP.Height,NULL)
22* never forget to free an allocated device context
23? ReleaseDC(m.goForm.HWnd, m.hDC)
iPicture.Render() qualifies for painting on otherwise unreachable form regions, like the TitleBar or WindowBorders. Another interesting application for direct rendering stems from the fact that no VFP object reference is necessary for painting. The render() method solely uses a common windows handle. Thus, one can render on any known device context.br If one encounters the so-called hourglass problem, working with a COM-based image can be the preferred workaround. The hourglass mouse cursor gets displayed by the operation system during lengthy disk accesses. Sometimes VFP does not reset the hourglass mouse cursor correctly. Thus, the user still sees the “busy working” icon although VFP already is idle, as long she doesn’t touch the mouse. Most often these disk accesses stem from refreshing pictures loaded into native Image-Objects using the Image.Picture property. Storing a COM memory-based object to the Image-Object’s .PictureVal property instead, never causes any disk access. Thus, no more hourglass mouse cursor will appear after a refresh! DrawbackiPicture.Render() does its work outside of - and unnoticed by – the VFP engine itself. That’s why VFP has no idea of what was painted “between the lines”. Each time VFP refreshes the form’s area (we’ve just rendered our picture onto), will clear out our image. To make rendered output persistent measures have to be taken against VFP wiping it out! There is another BUG one has to be aware of, when employing the hourglass workaround described above!br To see what happens, try the following code:
X#
 1LOCAL lnLoop, oComPic1, oComPic2
 2oComPic1 = LoadPicture(GetFile())
 3oComPic2 = LoadPicture(GetFile())
 4TRY
 5_Screen.Addobject("oImage","IMAGE")
 6CATCH
 7FINALLY
 8_Screen.oImage.Visible = .T.
 9ENDTRY
10For lnLoop = 1 to 100
11_Screen.oImage.PictureVal = m.oComPic1
12_Screen.oImage.PictureVal = m.oComPic2
13Next
14*// 
15*\\ whereas the next loop will break somewhere down the road:
16For lnLoop = 1 to 100
17_Screen.oImage.PictureVal = m.oComPic1
18_Screen.oImage.PictureVal = m.oComPic1
19_Screen.oImage.PictureVal = m.oComPic1
20_Screen.oImage.PictureVal = m.oComPic2
21Next
One can see, that the first loop executes flawlessly, the second one breaks after only a few loops with a “Property value is invalid” error message! This bug is hard to track and occurs only in cases when someone tries to assign the same COM-reference more than once in a row! The workaround for this is to keep track which COM-reference is actually assigned to the Image’s PictureVal property. Never ever then reassign the same reference a second time (overwriting the first one with a copy of itself)! BTW: It doesn’t matter what interface you are using. The error seems to stem from VFP’s Image class instance.
Examples
The following example shows that both interfaces (Picture and IPicture) of a COM image instance can be assigned to VFP’s Image.PictureVal property:
X#
 1PUBLIC goPic AS Object, goIPic AS Object
 2goPic = LoadPicture(GetPict())
 3goIPic = GETINTERFACE(m.goPic, "iPicture")
 4_SCREEN.AddObject("oPic1","IMAGE")
 5_SCREEN.AddObject("oPic2","IMAGE")
 6WITH _SCREEN.oPic1
 7.VISIBLE = .T.
 8.PICTUREVAL = m.goPic // "Picture"-Interface
 9ENDWITH
10WITH _SCREEN.oPic2
11.LEFT = 110
12.VISIBLE = .T.
13.PICTUREVAL = m.goIPic // "IPicture"-Interface
14ENDWITH
15HIDE WINDOWS ALL
16WAIT "Press any key..."
17_SCREEN.RemoveObject("oPic1")
18_SCREEN.RemoveObject("oPic2")
19STORE NULL TO goPic, goIPic
20Clear
21SHOW WINDOWS ALL
The following example shows how to query the iPicture interface of a COM image instance. Intentionally, there are no Try…Catch…Endtry sections in this demo code, so that OLE errors may occur. You have to run the code snippet multiple times with different image types to see them.
X#
 1goPic = LoadPicture(GetPict())
 2IF VARTYPE(m.goPic) == "O"
 3goIPic = GETINTERFACE(m.goPic, "iPicture")
 4IF VARTYPE(m.goIPic) == "O"
 5Clear // just some informal output:
 6WITH m.goIPic
 7?
 8? "Properties of 'IPicture'-Interface:"
 9? "Attributes"        ,.Attributes
10*\\ next line will fail if an ICOn loaded
11? "CurDC"    ,.CurDC
12? "Handle"    ,.Handle
13? "Height"    ,.Height
14*\\ next line will fail if an ICOn loaded
15? "hPal"    ,.hPal
16? "KeepOriginalFormat",.KeepOriginalFormat
17? "Type"    ,.Type
18? "Width"    ,.Width
19?
20ENDWITH
21ENDIF
22ENDIF
The following code is a collection of supporting functions and declarations that come in handy while programming OLE image objects.
X#
 1* Supporting Functions & DEFINEs
 2#DEFINE INCH2MILLIMETER 25.4 // 1 Inch = 25.4 millimeters
 3#DEFINE INCH2HIMETRICS (INCH2MILLIMETER * 100) // 1 HIMETRIC = 0.01
 4FUNCTION PXL2HIME(tnPixel AS Integer) AS Integer
 5* Pixel to HiMetric conversion
 6LOCAL lnPixelsOnOneHiMetricUnit AS Integer
 7lnPixelsOnOneHiMetricUnit = INCH2HIMETRICS / GetDPI()
 8RETURN ROUND(lnPixelsOnOneHiMetricUnit * m.tnPixel, 0)
 9ENDFUNC
10FUNCTION HIME2PXL(tnHimetric AS Integer) AS Integer
11* HiMetric to Pixel conversion
12LOCAL lnPixelsOnOneHiMetricUnit AS Integer
13lnPixelsOnOneHiMetricUnit = INCH2HIMETRICS / GetDPI()
14RETURN ROUND(m.tnHimetric / m.lnPixelsOnOneHiMetricUnit, 0)
15ENDFUNC
16FUNCTION GetDPI(tnHDC AS Integer) AS Integer
17* retrieve dots per inch resolution
18* for VFP's _SCREEN device context
19DECLARE Integer GetDeviceCaps IN GDI32 integer hdc, integer nIndex
20DECLARE Integer GetWindowDC IN User32 integer HWnd
21DECLARE Integer ReleaseDC IN User32 integer HWnd, integer hDC
22* For simplicity, we assume X- and Y- dimensions
23* using the same DPI resolution.
24#DEFINE LOGPIXELSX 88 // Logical pixels/inch in X
25#DEFINE LOGPIXELSY 90 // Logical pixels/inch in Y
26* Get VFP's _Screen-hDC to calculate resolution:
27LOCAL lhDC AS Integer, lnDPI AS Integer
28STORE 0 TO lhDC, lnDPI
29lhDC = GetWindowDC(_Screen.HWnd)
30IF NOT m.lhDC = 0
31lnDPI = GetDeviceCaps(m.lhDC, LOGPIXELSX)
32ELSE
33lnDPI = 96 // default to 96 DPI
34ENDIF
35* Free device context
36= ReleaseDC(_Screen.HWnd, m.lhDC)
37RETURN m.lnDPI
38ENDFUNC
39FUNCTION GetCanvas(tnHWND AS Integer, tlChild AS Boolean) AS Integer
40* Retrieve hDC (handle DeviceContext) of window handle
41* tlChild = TRUE  := Use GetDC()
42* tlChild = FALSE := Use GetWindowDC()
43DECLARE Integer GetDC IN User32 integer HWnd
44DECLARE Integer GetWindowDC IN User32 integer HWnd
45LOCAL lnHDC AS Integer
46IF m.tlChild
47lnHDC = GetDC(m.tnHWND)
48ELSE
49lnHDC = GetWindowDC(m.tnHWND)
50ENDIF
51RETURN m.lnHDC
52ENDFUNC
53FUNCTION ReleaseCanvas(tnHWND AS Integer, tnHDC AS Integer) AS Integer
54* Releases a borrowed hDC
55DECLARE Integer ReleaseDC IN User32 integer HWnd, integer hDC
56RETURN ReleaseDC(m.tnHWND, m.tnHDC)
57ENDFUNC
58* The following function is not bullert-proof, as it fails on forms with scrollbars (oForm.Scrollbars > 0)
59FUNCTION GetChildAreaCanvas(tnhWnd AS Integer) AS Integer
60* VFP ‘TopLevelForms’ (oForm.ShowWindow = 2) have
61* a secondary window inside the outer one.
62* This is also true for forms showing scrollbars!
63LOCAL lnVfpHANDLE AS Integer, lnClienthWnd AS Integer, lnHDC AS Integer
64* Convert the given Windows hWnd to an internal VFP WHANDLE
65lnVfpHANDLE = SYS(2326, m.tnhWnd)
66* Retrieve the Windows hWnd for a client window
67* (WCLIENTWINDOW) of a specified X# parent window
68lnClienthWnd = SYS(2325, m.lnVfpHANDLE)
69* Check if there is a WCLIENTWINDOW
70IF lnClienthWnd = lnVfpHANDLE
71* No such WCLIENTWINDOW, return child’s client area
72lnHDC = GetCanvas(m.tnhWnd, .T.)
73ELSE
74* There IS a WCLIENTWINDOW!
75* Get the device context handle for the
76* whole client area of that window:
77lnHDC = GetCanvas(lnClienthWnd)
78ENDIF
79RETURN m.lnHDC
80ENDFUNC
See Also