| **Navigation:**  [[introduction.htm|Language Reference]] > App A - DDE, OLE, and OCX > Object Linking and Embedding >====== OLE Container Properties ====== | [[ole overview.htm|{{btn_prev_n.gif|Previous page}}]][[introduction.htm|{{btn_home_n.gif|Return to chapter overview}}]][[oledirectory get list of installed ole ocx .htm|{{btn_next_n.gif|Next page}}]] | | || __**Contents:**__ [[ole container properties.htm#oleattributeprops|Attribute Properties]] [[ole container properties.htm#oleundeclaredprops|Undeclared Properties]] [[ole container properties.htm#oleexampleprogram|Example Program]] [[ole container properties.htm#oleinterfaceprops|Interface Properties]] [[ole container properties.htm#oleclarion ole ocx library and object hierarchies|Clarion OLE/OCX library and object hierarchies]] There are a number of properties associated with an OLE container control that deal only with OLE objects (not .OCX controls). **Attribute Properties** | PROP:Create | The CREATE attribute (blank if none). (WRITE ONLY) | | PROP:Open | The OPEN attribute (blank if none). (WRITE ONLY) | | PROP:Document | The DOCUMENT attribute (blank if none). (WRITE ONLY) | | PROP:Link | The LINK attribute (blank if none). (WRITE ONLY) | | PROP:Clip | The CLIP attribute. A toggle attribute. Assigning a null string ('') or zero turns it off, and '1' or 1 turns it on. (WRITE ONLY) | | PROP:Stretch | The STRETCH attribute. A toggle attribute. Assigning a null string ('') or zero turns it off, and '1' or 1 turns it on. (WRITE ONLY) | | PROP:Autosize | The AUTOSIZE attribute. A toggle attribute. Assigning a null string ('') or zero turns it off, and '1' or 1 turns it on. (WRITE ONLY) | | PROP:Zoom | The ZOOM attribute. A toggle attribute. Assigning a null string ('') or zero turns it off, and '1' or 1 turns it on. (WRITE ONLY) | | PROP:Compatibility | The COMPATIBILITY attribute (blank if none). (WRITE ONLY) | **Undeclared Properties** | PROP:Blob ||||| Convert an object to and from a blob. (READ/WRITE) | | PROP:SaveAs ||||| Saves the object to an OLE Compound Storage file. (WRITE ONLY) The syntax for placing the object in the file is '//filename//\!//component//' For example: | | ||||| **?controlx{PROP:SaveAs} = 'myfile\!objectx'** | | PROP:DoVerb ||||| Executes an OLE doverb command from the following set of commands (WRITE ONLY): | | | DOVERB:Primary (0) | Calls the object's primary action. The object, not the container, determines this action. If the object supports in-place activation, the primary verb usually activates the object in-place. | \\ | \\ | | | DOVERB:Show (-1) | Tells the object to show itself for editing or viewing. Called to display newly inserted objects for initial editing and to show link sources. This is usually an alias for some other object-defined action. | \\ | \\ | | | DOVERB:Open (-2) | Tells the object to open itself for editing in a separate window from its container (this includes objects that support in-place activation). If the object does not support in-place activation, this has the same action as DOVERB:Show. | \\ | \\ | | | DOVERB:Hide (-3) | Tells the object to remove its user interface. This applies only to objects activated in-place. | \\ | \\ | | | DOVERB:UIActivate (-4) | Activates the object in place, along with its full set of user-interface tools, including menus, toolbars, and its name in the title bar of the container window. | \\ | \\ | | | DOVERB:InPlaceActivate (-5) | Activates the object in-place without displaying the tools (menus and toolbars) that end-users need to change the behavior or appearance of the object. | \\ | \\ | | | DOVERB:DiscardUndoState (-6) | Tells the object to discard any undo state that it may be maintaining without deactivating the object. | \\ | \\ | | | DOVERB:Properties (-7) | Invokes the modal system property browser for the object to allow the user to set its properties. | \\ | \\ | | PROP:Deactivate | Deactivates an in-place active OLE object. (READ/WRITE/EXECUTE) | | PROP:Update | Tells the OLE object to update itself. (READ/WRITE/EXECUTE) | | PROP:CanPaste | Can you paste the object in the clipboard? (READ ONLY) | | PROP:Paste | Pastes an object from the clipboard to an OLE container control. (READ/WRITE/EXECUTE) | | PROP:CanPasteLink | Can the object in the clipboard be pasted as a link? (READ ONLY) | | PROP:PasteLink | Pastes and links an object from the clipboard to an OLE container control. (READ/WRITE/EXECUTE) | | PROP:Copy | Copies an object in an OLE container control to the clipboard. (READ/WRITE/EXECUTE) | | PROP:ReportException | Report OLE exceptions (for debug). (WRITE ONLY) | | PROP:OLE | Is there an OCX or OLE object in the container? (READ ONLY) | | PROP:Language | The number for the language used for OLE Automation or OCX Method. The number for US English is 0409H, and other language numbers can be computed from the data in the WINNT.H file in the MS Windows SDK. (READ/WRITE) | **Example Program:** ** PROGRAM** ** MAP** **  INCLUDE('OCX.CLW')** **SelectOleServer  PROCEDURE(OleQ PickQ),STRING** ** END** ** INCLUDE 'XL.CLW'          !Constants that Excel uses** ** INCLUDE 'ERRORS.CLW'      !Include errorcode constants ** **SaveLinks  FILE,DRIVER('TopSpeed'),PRE(SAV),CREATE** **Object     BLOB** **Record     RECORD** **LinkType    STRING(1)      !F = File, B = BLOB** **LinkFile    STRING(64)     !OLE Compound Storage file name and object** **           END** **          END** **i      LONG                !Loop counters** **j      LONG** **ResultQ  QUEUE             !Queue to hold return from OLEDIRECTORY** **Name      CSTRING(64)** **CLSID     CSTRING(64)** **ProgID    CSTRING(64)** **         END** **MainWin WINDOW('OLE Demo'),AT(,,350,200),STATUS(-1,-1),SYSTEM,GRAY,RESIZE,MAX,TIMER(1)** **         MENUBAR** **          MENU('&File')** **           ITEM('e&xit'),USE(?exit)** **          END** **          MENU('&Objects')** **           ITEM('Create Object'),USE(?CreateObject)** **           ITEM('Paste Object'),USE(?PasteObject)** **           ITEM('PasteLink Object'),USE(?PasteLinkObject)** **           ITEM('Save Object to BLOB'),USE(?SaveObjectBlob),DISABLE** **           ITEM('Save Object to OLE File'),USE(?SaveObjectFile),DISABLE** **           ITEM('Retrieve Saved Object'),USE(?GetObject),DISABLE** **          END** **          MENU('&Activate')** **           ITEM('&Spreadsheet'),USE(?ActiveExcel)** **           ITEM('&Any OLE Object'),USE(?ActiveOLE),DISABLE** **          END** **        END** **       ****OLE****,AT(5,10,160,100),COLOR(0808000H),USE(?ExcelObject)** **         MENUBAR** **          MENU('&Clarion App')** **           ITEM('&Deactivate Excel'),USE(?DeactExcel)** **          END** **         END** **       ****END** **       ****OLE****,AT(170,10,160,100),USE(?AnyOLEObject),AUTOSIZE** **         MENUBAR** **          MENU('&Clarion App')** **           ITEM('&Deactivate Object'),USE(?DeactOLE)** **          END** **         END** **       ****END** **       END** ** CODE** ** OPEN(SaveLinks)           ** ** IF ERRORCODE()                               !Check for error on Open** **  IF ERRORCODE() = NoFileErr                  !if the file doesn't exist** **   CREATE(SaveLinks)                          !then create it** **   IF ERRORCODE() THEN HALT(,ERROR()) END** **   OPEN(SaveLinks)                            !then open it for use** **   IF ERRORCODE() THEN HALT(,ERROR()) END** **  ELSE** **   HALT(,ERROR())** **  END** ** END** ** OPEN(MainWin)** ** ?ExcelObject{PROP:Create} = 'Excel.Sheet.5'  !Create an Excel spreadsheet object** ** DO BuildSheetData                            !populate it with some random data** ** IF RECORDS(SaveLinks)                        !Check for existing saved record** **  SET(SaveLinks)                              !and get it** **  NEXT(SaveLinks)** **  POST(EVENT:Accepted,?GetObject)             !and display it** **  DO MenuEnable** ** ELSE** **  ADD(SaveLinks)                              !or add blank record** ** END** ** IF ERRORCODE() THEN HALT(,ERROR()) END** ** ACCEPT** **  CASE EVENT()** **  OF EVENT:CloseWindow** **   ?ExcelObject{PROP:Deactivate}             !Deactivate the OLE Server applications** **   ?AnyOLEObject{PROP:Deactivate}** **  OF EVENT:Timer** **   IF CLIPBOARD()** **    IF ?AnyOLEObject{PROP:CanPaste}          !Can Paste object from the clipboard?** **     IF ?PasteObject{PROP:Disable}** **      ENABLE(?PasteObject)** **     END** **    ELSIF NOT ?PasteObject{PROP:Disable}** **     DISABLE(?PasteObject)** **    END** **    IF ?AnyOLEObject{PROP:CanPasteLink}      !Can PasteLink object from clipboard?** **     IF ?PasteLinkObject{PROP:Disable}** **      ENABLE(?PasteLinkObject)** **     END** **    ELSIF NOT ?PasteLinkObject{PROP:Disable}** **     DISABLE(?PasteLinkObject)** **    END** **   END** **  OF EVENT:Accepted** **   CASE FIELD()** **   OF ?Exit** **    POST(EVENT:CloseWindow)** **   OF ?CreateObject** **    OLEDIRECTORY(ResultQ,0)                  !Get a list of installed OLE Servers** **    ?AnyOLEObject{PROP:Create} = SelectOleServer(ResultQ)  !Let the user pick one** **    ?AnyOLEObject{PROP:DoVerb} = 0           !Activate OLE Server in its default mode** **    DO MenuEnable** **   OF ?PasteObject** **    ?AnyOLEObject{PROP:Paste}                !Paste the object ** **    SETCLIPBOARD('Paste Completed')          !Assign non-object text to clipboard** **    DO MenuEnable** **   OF ?PasteLinkObject        ** **    ?AnyOLEObject{PROP:PasteLink}            !PasteLink the object ** **    SETCLIPBOARD('PasteLink Completed')      !Assign non-object text to clipboard** **    DO MenuEnable** **   OF ?SaveObjectBlob                        !Save object to BLOB** **    SAV:Object{PROP:Handle} = ?AnyOLEObject{PROP:Blob}** **    SAV:LinkType = 'B'** **    PUT(SaveLinks)** **    IF ERRORCODE() THEN STOP(ERROR()) END** **   OF ?SaveObjectFile                        !Save to OLE Compound Storage file** **    ?AnyOLEObject{PROP:SaveAs} = 'TEST1.OLE\!Object'** **    SAV:LinkFile = 'TEST1.OLE\!Object'** **    SAV:LinkType = 'F'** **    PUT(SaveLinks)** **    IF ERRORCODE() THEN STOP(ERROR()) END** **   OF ?GetObject** **    IF SAV:LinkType = 'F'                    !Saved to OLE Compound Storage file?** **     ?AnyOLEObject{PROP:Open} = SAV:LinkFile** **    ELSIF SAV:LinkType = 'B'                 !Saved to BLOB?** **     ?AnyOLEObject{PROP:Blob} = SAV:Object{PROP:Handle}** **    END** **    DISPLAY** **   OF ?ActiveExcel** **    ?ExcelObject{PROP:DoVerb} = 0            !In-place activate Excel** **   OF ?ActiveOLE** **    ?AnyOLEObject{PROP:DoVerb} = 0           !Activate OLE Server in its default mode** **   OF ?DeactExcel** **    ?ExcelObject{PROP:Deactivate}            !Return to the Clarion application** **   OF ?DeactOLE** **    ?AnyOLEObject{PROP:Deactivate}           !Return to the Clarion application** **   END !CASE FIELD()** **  END  !CASE EVENT0()** ** END   !ACCEPT** **BuildSheetData   ROUTINE                     !Use OLE Automation to build spreadsheet** ** ?ExcelObject{PROP:ReportException} = TRUE   !Excel will report any errors** ** ?ExcelObject{'Application.Calculation'} = xlManual  !turn off auto recalc** ** LOOP i = 1 TO 3                             !Fill Sheet with some values** **  LOOP j = 1 TO 3** **   ?ExcelObject{'Cells(' & i & ',' & j & ').Value'} = Random(100,900)** **  END** **  ?ExcelObject{'Cells(4,' & i & ').Value'} = 'Sum'** **  ?ExcelObject{'Cells(5,' & i & ').FormulaR1C1'} = '=SUM(R[-4]C:R[-2]C)'** **  ?ExcelObject{'Cells(6,' & i & ').Value'} = 'Average'** **  ?ExcelObject{'Cells(7,' & i & ').FormulaR1C1'} = '=AVERAGE(R[-6]C:R[-4]C)'** ** END** ** !turn auto recalc back on** ** ?ExcelObject{'Application.Calculation'} = xlAutomatic** ** DISPLAY** **MenuEnable  ROUTINE                          !Enable menu items** **   ENABLE(?ActiveOLE)** **   ENABLE(?SaveObjectBlob,?GetObject)** **SelectOleServer PROCEDURE(OleQ PickQ)** **window WINDOW('Choose OLE Server'),AT(,,122,159),CENTER,SYSTEM,GRAY** **        LIST,AT(11,8,100,120),USE(?List),HVSCROLL, |** **        FORMAT('146L~Name~@s64@135L~CLSID~@s64@20L~ProgID~@s64@'),FROM(PickQ)** **        BUTTON('Select'),AT(42,134),USE(?Select)** **       END** ** CODE** ** OPEN(window)** ** SELECT(?List,1)** ** ACCEPT** **  CASE ACCEPTED()** **  OF ?Select** **   GET(PickQ,CHOICE(?List))** **   IF ERRORCODE() THEN STOP(ERROR()) END** **   POST(EVENT:CloseWindow)** **  END** ** END** ** RETURN(PickQ.ProgID)** __**Interface Properties**__ | PROP:Object | Gets the Dispatch interface for the object. (READ ONLY) | | | In VB the toolbar and tree control use the image-list control to show icons in the tree control and on the buttons on the toolbar. To associate an image control with a toolbar, use the following code: | | | **?toolbar{'ImageList'} = ?imagelist{prop:object}** | | | | | PROP:SelectInterface | Selects the interface to use with the object. (WRITE ONLY) | | | | | | **?x{PROP:SelectInterface} = 'x.y'** | | | **?x{'z(1)'} = 1** | | | **?x{'z(2)'} = 2** | | | | | | **has the same meaning as** | | | | | | **?x{'x.y.z(1)'} = 1** | | | **?x{'x.y.z(2)'} = 2** | | | | | PROP:AddRef | Increments the reference count for an interface. (WRITE ONLY) | | PROP:Release | Decrements the reference count for an interface. (WRITE ONLY) | __**Clarion OLE/OCX library and object hierarchies:**__ At the time of the design and implementation of the Clarion OLE library, the lack of access to secondary objects created by a primary object (example from excel: ExcelUse{'Application.Charts.Add'}), was not considered a problem as there were other ways of accessing the object(ExcelUse {'Application.Charts(Chart1).ChartWizard(' &?ex{'Range(A5:C5)'}&','&xl3DPie&',7,1,0,0,2,,,,)'}) At the time there was only one known instance where this was not the case. This is probably still true today as the OLE standard states that an object implement a collection, must also implement a method for accessing the objects by indexing. Due to the special case mentioned above, when an object was created by one control and passed onto an other object as a parameter, a method which would be more or less transparent to the user, was implemented. Calling a method which returns an IDispatchInterface is converted into a special representation (a '`' followed by a number of digits). This special representation is recognized in a couple of places in the OLE library. The place that you will find most useful is, when the special representation is in the place where an interface could occur in the property syntax it will replace any previous interface in the access of the properties or methods of the object. For example: **x=y{'charts.add()')** **y{x&'p(7)'}** where y is an ole object and x is a cstring. This is an example of a method returning an interface and later this interface is used to access a method p with the parameter 7. In this context a further complication arises form the reference counting used in OLE. Which means that if the object are used more than once it must have it's reference count increased before use. **x=y{'charts.add()')** **y{PROP:AddRef}=x** **y{x&'p(7)'}** **y{x&'p(7)'} ;last use of x**