Using Win32 functions in Visual FoxPro Image Gallery
Memory Management
..msdn
CopyMemory
FillMemory
GetProcessHeap
GetProcessHeaps
GlobalAlloc
GlobalFree
GlobalLock
GlobalMemoryStatus
GlobalReAlloc
GlobalSize
GlobalUnlock
HeapAlloc
HeapCompact
HeapFree
HeapLock
HeapReAlloc
HeapSize
HeapUnlock
HeapValidate
HeapWalk
LocalAlloc
LocalFree
LocalSize
VirtualAllocEx
VirtualFreeEx
ZeroMemory
Code examples:
Adding and deleting Scheduled Tasks using NetScheduleJob API functions
Adding and deleting User Accounts
Adding printer to the list of supported printers for the specified server
Adding user-defined items to the Control Menu of VFP form (requires VFP9)
Attaching menu to a top-level form
Browsing Windows Known Folders (Special Folders)
Changing pitch and speed of a wave file
Class for sound recording
Compressing and decompressing files with Windows API Runtime Library routines
Converting command-line string to a set of Unicode argument strings (WinNT only)
Copying strings through the global memory block
Creating the Open dialog box to specify the drive, directory, and name of a file to open
Creating the Save dialog box to specify the drive, directory, and name of a file to save
Custom HttpRequest class (WinHTTP)
Deleting files into the Recycle Bin
Displaying dimmed window behind VFP top-level form
Displaying standard progress dialog box when copying files
Displaying system dialog that selects a folder
Dynamic strings implemented through VFP Custom class
Enhanced GetFont dialog
Enumerating forms supported by a specified printer
Enumerating network resources
Enumerating ports that are available for printing on a specified server
Enumerating print jobs and retrieving information for default printer (JOB_INFO_1 structures)
Enumerating printer drivers installed
Extensible Storage Engine class library
FindText -- the hopeless and useless Common Dialog
GDI+: reading and writing metadata in JPEG and TIFF files
How to assemble an array of strings and pass it to external function
How to browse and connect to printers on a network (WinNT)
How to convert a bitmap file to monochrome format (1 bpp)
How to delete IE cookies, clear IE history and delete files in Temporary Internet Files directory
How to display a user-defined icon in the MessageBox dialog
How to display advanced Task Dialog (Vista)
How to display the Print property sheet
How to display the Properties dialog box for a file (ShellExecuteEx)
How to enumerate cookies and URL History entries in the cache of the local computer
How to enumerate, add and delete shares on the local computer (WinNT/XP)
How to prevent users from accessing the Windows Desktop and from switching to other applications
How to print a bitmap file
How to print FoxPro form
How to remove a directory that is not empty
How to write and read Window Properties for the specified window
Loading a string resource from an executable file
MapiSendMail class for Visual FoxPro application
Mapping and disconnecting network drives
Obtaining addresses for the adapters on the local computer (Win XP/2003/Vista)
Obtaining list of tables stored in an ODBC Data Source
Passing data records between VFP applications via the Clipboard
Playing WAV sounds simultaneously
Printing Image File, programmatically set print page orientation to landscape
Quering Audio Mixer Device
Reading entries from Event logs
Reading the structure of VFP main menu
Sending email messages with Simple MAPI
Shortcut Menu Class
Simple printer queue monitor: deletes, pauses, resumes print jobs for local printer
Starting a dialog box for connecting to network resources and passing input parameters
Storing content of the Clipboard to a bitmap file
Storing screen shot of a form to bitmap file
Subclassing CommandButton control to create BackColor property
URL: splitting into its component parts
Using Change Notification Objects to monitor changes to the printer or print server
Using EnumPrinters function to enumerate locally installed printers
Using FillMemory
Using the ChooseColor function
Using WM_COPYDATA for interprocess communication (VFP9)
Verifying a file using the Authenticode policy provider
Vertical Label control
WAV file player
Windows Shell Icons displayed and exported to ICO files (Vista)
Winsock: connecting to a news server (NNTP, port 119)
Writing entries to custom Event Log
GDI+: reading and writing metadata in JPEG and TIFF files

User rating: 0/10 (0 votes)
Rate this code sample:
  • ~
More code examples    Listed functions    Add comment     W32 Constants      Translate this page Printer friendly version of this code sample
Before you begin:
Most of JPEG files contain some metadata, especially files created with digital cameras.
Here is an example:



MIcrosoft SDK includes GdiplusImaging.h header file with definitions of many (not all) PropertyItem IDs. For example:
#define PropertyTagImageDescription 0x010E
#define PropertyTagEquipMake 0x010F
#define PropertyTagEquipModel 0x0110
...
#define PropertyTagExifShutterSpeed 0x9201
#define PropertyTagExifAperture 0x9202
#define PropertyTagExifBrightness 0x9203
#define PropertyTagExifExposureBias 0x9204
#define PropertyTagExifMaxAperture 0x9205
...


The following code shows how to read this data from JPEG and TIFF image files. PNG files have limited support of this functionality. BMP and GIF files, afaik, do not support metadata storage.

The code is based on custom GDI+ class. Download the class module first and save it in gdiplus.prg file.
 
#DEFINE PropertyTagPropComments     0x9C9C
#DEFINE PropertyTagImageDescription 0x010E
 
#DEFINE PropertyTagTypeByte  1
#DEFINE PropertyTagTypeASCII 2
#DEFINE PropertyTagTypeShort 3
#DEFINE PropertyTagTypeLong 4
#DEFINE PropertyTagTypeRational 5
#DEFINE PropertyTagTypeUndefined 7
#DEFINE PropertyTagTypeSLONG 9
#DEFINE PropertyTagTypeSRational 10
 
SET PROCEDURE TO gdiplus ADDITIVE
 
PRIVATE gdip, src
gdip = CREATEOBJECT("gdiplusinit_")
 
* load source file into memory
src = CREATEOBJECT("gdiimage_", "c:\temp\img001.jpg")
IF src.errorcode <> 0
    ? "Could not load source image file"
    RETURN
ENDIF
 
DO ListPropertItems
*= AddMemo("White and Black on Green", "c:\temp\temp.jpg")
* end of main
 
PROCEDURE ListPropertItems
    LOCAL propertyitem As ImagePropertyItem
 
    src.GetPropertyItems
    IF src.propertyitems.Count = 0
        ? "The file contains no property items."
    ELSE
        CREATE CURSOR cs (propid C(10), proptype I,;
            proplen I, propvalue M)
 
        FOR EACH propertyitem IN src.propertyitems
            WITH propertyitem
                INSERT INTO cs VALUES (TRANSFORM(.propid,"@0"),;
                    .proptype, LEN(.propvalue), .propvalue)
            ENDWITH
        ENDFOR
        GO TOP
        BROWSE NORMAL NOWAIT
    ENDIF
 
PROCEDURE AddMemo(cMemo, cNewFilename)
* adds description to the image object
* and saves it to another file
    LOCAL nPropertyTag, nPropertyType
*    nPropertyTag = PropertyTagImageDescription
    nPropertyTag = PropertyTagPropComments
 
    nPropertyType = PropertyTagTypeByte
*    nPropertyType = PropertyTagTypeASCII
 
    * convert to Unicode if PropertyTagTypeByte used
    * no convertion is required for PropertyTagTypeASCII
    IF nPropertyType = PropertyTagTypeByte
        cMemo = STRCONV(cMemo+CHR(0), 5)
    ENDIF
 
    WITH src
        IF NOT .SetPropertyItem(nPropertyTag, nPropertyType, m.cMemo)
            ? "SetPropertyItem error:", .errorcode
            RETURN .F.
        ENDIF
        IF NOT .SaveToFile(cNewFilename)
            ? "SaveToFile error:", .errorcode
            RETURN .F.
        ENDIF
    ENDWITH
RETURN .T.
 
DEFINE CLASS gdiplusinit_ As gdiplusinit
* subclassed to add few more DECLARE statements
PROCEDURE declare
    DODEFAULT()
    DECLARE INTEGER GlobalAlloc IN kernel32 INTEGER wFlags, INTEGER dwBytes
    DECLARE INTEGER GlobalFree IN kernel32 INTEGER hMem
 
    DECLARE INTEGER GdipGetPropertyIdList IN gdiplus;
        INTEGER img, LONG numOfProperty, STRING @lst
 
    DECLARE INTEGER GdipGetPropertyCount IN gdiplus;
        INTEGER img, LONG @numOfProperty
 
    DECLARE INTEGER GdipGetPropertyItemSize IN gdiplus;
        INTEGER img, INTEGER propId, LONG @sze
 
    DECLARE INTEGER GdipGetPropertyItem IN gdiplus;
        INTEGER img, INTEGER propId, LONG propSize, STRING @buffer
 
    DECLARE INTEGER GdipSetPropertyItem IN gdiplus;
        INTEGER img, STRING @itm
 
    DECLARE INTEGER GdipRemovePropertyItem IN gdiplus;
        INTEGER img, INTEGER propId
ENDDEFINE
 
DEFINE CLASS gdiimage_ As gdiimage
* subsclassed to add reading PropertyItems functionality
    propertyitems=0
 
PROCEDURE RemovePropertyItem(propId)
    IF VARTYPE(m.propId)="O"
        THIS.errorcode =;
            GdipRemovePropertyItem(THIS.himage, propId.propId)
    ELSE
        THIS.errorcode =;
            GdipRemovePropertyItem(THIS.himage, m.propId)
    ENDIF
RETURN (THIS.errorcode=0)
 
PROCEDURE SetPropertyItem(p1, p2, p3)
    LOCAL propertyitem, cBuffer
    IF VARTYPE(m.p1)="O"
        propertyitem=m.p1
    ELSE
        propertyitem = CREATEOBJECT("ImagePropertyItem", m.p1, m.p2, m.p3)
    ENDIF
 
    cBuffer = propertyitem.ToString()
    THIS.errorcode = GdipSetPropertyItem(THIS.himage, @cBuffer)
    IF THIS.errorcode=0
        THIS.GetPropertyItems
    ENDIF
RETURN (THIS.errorcode=0)
 
PROCEDURE GetPropertyItems
* populates collection with existing property items 
    THIS.propertyitems = CREATEOBJECT("Collection")
 
    LOCAL nCount, nIndex, cIDs, nId, nItemSize, cItemBuffer
    STORE 0 TO nCount
    = GdipGetPropertyCount(THIS.himage, @nCount)
 
    cIDs = REPLICATE(CHR(0), nCount*4)
    = GdipGetPropertyIdList(THIS.himage, nCount, @cIDs)
 
    FOR nIndex=0 TO nCount-1
        nId = buf2dword(SUBSTR(cIDs, nIndex*4+1, 4))
        nItemSize=0
        = GdipGetPropertyItemSize(THIS.himage, nId, @nItemSize)
        cItemBuffer = REPLICATE(CHR(0), nItemSize)
        = GdipGetPropertyItem(THIS.himage, nId, nItemSize, @cItemBuffer)
 
        LOCAL nProplen, PropertyItem As ImagePropertyItem
        nProplen = buf2dword(SUBSTR(cItemBuffer, 5,4))
 
        PropertyItem = CREATEOBJECT("ImagePropertyItem",;
            buf2dword(SUBSTR(cItemBuffer, 1,4)),;
            buf2dword(SUBSTR(cItemBuffer, 9,4)),;
            SUBSTR(cItemBuffer, 17, nProplen))
 
        THIS.propertyitems.Add(PropertyItem,;
            TRANSFORM(PropertyItem.propid))
    ENDFOR
ENDDEFINE
 
DEFINE CLASS ImagePropertyItem As Session
PROTECTED hData
    propid=0
    proptype=0
    propvalue=""
 
PROCEDURE Init(p1, p2, p3)  && id, type, buffer
    THIS.propid=m.p1
    THIS.proptype=m.p2
    THIS.propvalue=m.p3
    THIS.hData=0
 
FUNCTION GetPropertyValue
* converts the buffer to appropriate FoxPro data type
    LOCAL vtype
    vtype = VARTYPE(THIS.propvalue)
 
    DO CASE
    CASE m.vtype <> "C"
        RETURN THIS.propvalue
    CASE m.vtype=PropertyTagTypeShort AND LEN(THIS.propvalue)=2
        RETURN buf2word(THIS.propvalue)
    CASE m.vtype=PropertyTagTypeLong AND LEN(THIS.propvalue)=4
        RETURN buf2dword(THIS.propvalue)
    CASE m.vtype=PropertyTagTypeRational AND LEN(THIS.propvalue)=4
        RETURN float2int(buf2dword(THIS.propvalue))
    CASE m.vtype=PropertyTagTypeSLONG AND LEN(THIS.propvalue)=4
        RETURN buf2dword(THIS.propvalue)
    CASE m.vtype=PropertyTagTypeSRational AND LEN(THIS.propvalue)=4
        RETURN float2int(buf2dword(THIS.propvalue))
    OTHERWISE
    * the value stays in form of string (array of bytes)
        RETURN THIS.propvalue
    ENDCASE
 
PROCEDURE Destroy
    THIS.ReleaseData
 
PROTECTED PROCEDURE ReleaseData
    IF THIS.hData <> 0
        = GlobalFree(THIS.hData)
        THIS.hData=0
    ENDIF
 
PROCEDURE ToString
    THIS.ReleaseData
 
    LOCAL propvalue, proplen
    propvalue = THIS.propvalue
 
    IF VARTYPE(m.propvalue) = "N"
        DO CASE
        CASE INLIST(THIS.proptype,;
            PropertyTagTypeRational, PropertyTagTypeSRational)
            propvalue = num2dword(int2float(m.propvalue))
        CASE THIS.proptype = PropertyTagTypeShort
            propvalue = num2word(m.propvalue)
        CASE THIS.proptype = PropertyTagTypeByte
            propvalue = CHR(BITAND(m.propvalue, 0x00ff))
        OTHERWISE
            propvalue = num2dword(m.propvalue)
        ENDCASE
    ENDIF
    proplen = LEN(THIS.propvalue)
 
    DECLARE RtlMoveMemory IN kernel32 As StrToMem;
        INTEGER Dest, STRING Src, INTEGER nLength
 
    THIS.hData = GlobalAlloc(0, m.proplen)
    = StrToMem(THIS.hData, m.propvalue, m.proplen)
 
RETURN num2dword(THIS.propid) + num2dword(m.proplen) +;
        num2dword(THIS.proptype) + num2dword(THIS.hData)
ENDDEFINE
 
 

User rating: 0/10 (0 votes)
Rate this code sample:
  • ~
6631 bytes  
Created: 2004-07-28 13:39:30  
Modified: 2011-08-15 20:34:40  
Visits in 7 days: 107  
Listed functions:
GdipGetPropertyCount
GdipRemovePropertyItem
GdipSetPropertyItem
GlobalAlloc
GlobalFree
Printer friendly API declarations
My comment:
There are several PropertyTag IDs not included in GdiplusImaging.h header file:

#DEFINE PropertyTagPropTitle 0x9c9b
#DEFINE PropertyTagPropComments 0x9c9c
#DEFINE PropertyTagPropAuthor 0x9c9d
#DEFINE PropertyTagPropKeywords 0x9c9e
#DEFINE PropertyTagPropSubject 0x9c9f

This picture shows corresponding properties:



So with GDI+ you can scan JPEG and TIFF image files and check, for example, keywords or author name included. As you can see from this particular example, it is possible to add or modify metadata in image files.

Some links I saved for later on:
  • http://www.php-websource.com/php436/source-exif.htm
  • http://www.opensource.apple.com/darwinsource/10.3/apache_mod_php-12/php/ext/exif/exif.c

    And how do you like that:
    /* Olympus specific tags */
    #define TAG_OLYMPUS_SPECIALMODE 0x0200
    #define TAG_OLYMPUS_JPEGQUAL 0x0201
    #define TAG_OLYMPUS_MACRO 0x0202
    #define TAG_OLYMPUS_DIGIZOOM 0x0204
    #define TAG_OLYMPUS_SOFTWARERELEASE 0x0207
    #define TAG_OLYMPUS_PICTINFO 0x0208
    #define TAG_OLYMPUS_CAMERAID 0x0209

    /* end Olympus specific tags */


    * * *
    Naturally you would like to open image file, add or change property, then close the file saving the updates. It does not work this way for current GDI+ version.

    You may create gdiplus image object from a disk file and add new or change existing property item for this object. But you have to save it to another image file to keep this new property. The original file can not be rewritten until this inherited image object is released.

    Save comments and descriptions using either PropertyTagPropComments or PropertyTagImageDescription property ids (some other ids may suit too). For saving Unicode strings use PropertyTagTypeByte type, for regular ASCII the PropertyTagTypeASCII is Ok.

    #kwd: sln_gdiplus.
  • Word Index links for this example:
    Translate this page:
      Spanish    Portuguese    German    French    Italian  
    FreeTranslation.com offers instant, free translations of text or web pages.
    User Contributed Notes:
    There are no notes on this subject.


    Copyright © 2001-2013 News2News, Inc. Before reproducing or distributing any data from this site please ask for an approval from its owner. Unless otherwise specified, this page is for your personal and non-commercial use. The information on this page is presented AS IS, meaning that you may use it at your own risk. Microsoft Visual FoxPro and Windows are trade marks of Microsoft Corp. All other trademarks are the property of their respective owners. 

    Privacy policy
    Credits: PHP (4.4.9), an HTML-embedded scripting language, MySQL (5.1.55-log), the Open Source standard SQL database, AceHTML Freeware Version 4, freeware HTML Editor of choice.   Hosted by Korax Online Inc.
    Last Topics Visited (50.16.108.167)
    6 sec.Function: 'ImageList_Add'
    Function group: 'Windows Controls'
    1.63 hrs.
    Function group: 'HTTP Functions (WinHTTP)'
     Example: 'How to create MD-5 and SHA-1 hash values from a string'
    2.17 hrs.Function: 'JetDetachDatabase'
    Function group: 'Extensible Storage Engine (ESE, Jet Blue)'
     Function: 'BitBlt'
     Example: 'Adding and deleting User Accounts'
    5.77 hrs.Example: 'Retrieving top-child window for the VFP form'
    5.78 hrs.Example: 'Retrieving list of Global Atom names'
    7.6 hrs.Function: 'GetTextExtentPoint32'
     Example: 'Creating a clipping region from the path selected into the device context of a form'
    Google
    Advertise here!