Getting Started
Introduction
Sample Programs
IDEs
History
Advice
Mini-Tutorial
Tutorials
Code Snippets

Resources
Web Sites
More Tutorials
Forums
Vendors/Tools
Books
Magazines
Newsletters
NewsGroups
User Groups
Talk Shows
Blogs

Controls
Overview
Button
Check3State
Checkbox
ComboBox
Frame
Graphic
Image
ImageX
ImgButton
ImgButtonX
Label
Line
ListBox
ListView
Option
Progress Bar
Scrollbar
StatusBar
TAB
TextBox
Toolbar
TreeView

GBIC >> PowerBASIC >> Tutorials >> Objects

PowerBASIC Information Center Tutorials
These tutorials were written to help you get a quick, but thorough, understanding of PowerBASIC - the scope of the language as well as it's specific capabilities.

Introduction       Projects       Language           Messages       Functions           Advanced
  • Overview
  • Examples
  • IDE
  • Compilation
  • Distribution
  • Project Files
  • DDT Windows
  • Controls
  • Menus
  • Dialogs  
  • Help Files
  • Resources  
  • Templates  
  • Project Shell  
  • Syntax
  • Operators
  • Data Types
  • Variables
  • Scope
  • Declarations  
  • Procedures
  • Flow Control
  • Windows
  • Messages
  • Callbacks
  • Mouse
  • Keyboard
  • Dialogs
  • Controls
  • Subclassing
  • Arithmetic
  • Trig  
  • Strings
  • Arrays
  • Date/Time
  • Printing
  • Files
  • Folders
  • Keyboard
  • Mouse
  • Sound
  • System
  • Error Traps
  • Debugging
  • Objects
  • Graphics
  • Databases
  • API
  • DLLs
  • ASM
  • Threads
  • Common Object Model (COM)
    In 1993, Microsoft released the first Common Object Model (COM) specification, which defined how two applications could communicate with one another - where one acts as a COM-aware client (such as a PowerBASIC application) and the other acts as a COM-compliant provider of services (COM server). COM encompasses the key concepts of classes, objects, interfaces, properties, and methods - all of which PowerBASIC supports.

    PowerBASIC creates objects which are fully compliant with COM specifications. It can also create COM-aware applications - which can access COM-compliant objects in other components.

    PowerBASIC provides two groups of function which enable programmers to work with objects, their interfaces (methods and properties) and the classes from which they are derived.

    The first group allows programmers to define a class (the Class/End Class statements and everything in-between). The second group enables the use of a class to create and manage objects within a PowerBASIC application (outside the Class/End Class code blocks).

    The two groups are presented next, followed by a discussion of how all of these functions play together.

    First, here are the PowerBASIC functions for defining a class.

      • Basic Structure
       Class, Instance, Interface, Inherit, Method
      • Properties
       Object Get, Object Set, Object Let

    And here are the PowerBASIC functions for using a class within an application to create and manage objects.

      • GUID
       GUID$, GUIDTXT$, CLSID$, PROGID$, IDISPINFO 
      • Creation
       ObjResult, ObjResult$
      • Properties
       Property Get, Property Set
      • Events
       RaiseEvent
      • Variant
       VariantVT, Variant$, Variant#, Reset
      • UCode
       UCode$, ACode$ 
      • Tests
       IsInterface, IsNothing, IsObject
      • Using Objects
       Let (w/Object), Let (w/Variants), Me, 
       MyBase, ObjPtr, ObjActive
      
      • Compiler Directives
       #COM DOC, #COM HELP, #COM NAME, #COM GUID

    Objects
    The "Object" in COM refers to a special code library which consists of both variables and procedures. In COM terminology, variables and procedures are called properties and methods. Some of the variables/procedures are exposed - meaning that they may be called by applications outside the code library. Other variables/procedures are private and may only be accessed within the code library.

    A COM object is simply an object (code library - collection of properties and methods) which conforms to the Microsoft COM specification. COM objects are kept in files, usually called COM components or COM servers, similar to the way in which DLL files are used to store libraries of code. These files may contain more than one object.

    However, DLLs are typically "in-process" libraries, which means they are loaded into the address space of the calling application. COM components do not share the address space of the calling application, and are referred to as "out-of-process".

    Classes
    What COM components actually contain are the blueprints for objects - the compiled source code that will be loaded into memory for actual use. When a copy of the blueprint is loaded into memory it becomes available for use by the calling program. The working copy is called an "object". Multiple copies of the blueprint (code) can be loaded into memory, creating multiple objects, each of which are totally independent of one another.

    The blueprint for an object, the compiled code found in the COM component file, is called a "class". A class contains both properties (variables) and methods (procedures). As noted above, some of the properties and methods may be called from outside the object, while others may only be used within the object.

    Each object (a copy of a class, loaded into memory, and usually associated with an object variable) is called an "instance" of the class. Each instance is totally separate from all other instances, meaning it's properties can be changed independently of properties values in other instances.

    The complete set of exposed properties and methods are called an object's "interface", referring to the way in which code outside an object can interface with the code inside the object. Note that not all methods within an object are exposed, and hence not all are part of an object's interface.

    Home Schooling
    Note that a PowerBASIC application may include objects of its own. In general, objects do not have to be in a separate file, nor do they have to be COM-compliant (there are competing interprocess communication models), although all PowerBASIC objects are COM-compliant.

    Syntax - Using Objects
    Before getting into more detail about object, classes, and interfaces, let's take a quick look at some simple source code that accesses an object. Consider an object whose interface includes a Print method and a Status property. The commands for creating an object are discussed later, but here's a quick look at the syntax for using an object and its interface.

        MyObject.Print "hello"       'method "Print", with a text argument
        a$ = MyObject.Status         'property "Status", assigned to a variable
    

    This notation is similar to UDT structures, except that an object has both procedures and properties, rather than just the properties of a UDT.

    Properties Are Methods
    Even though the property example above might be interpreted as accessing a variable with MyObject called "Status", the command "MyObject.Status" is actually running a method (procedure) called "Status" within MyObject. The return value of the procedure is what is passed to the variable a$. More on this later.

    More on Interface
    The interface is the key information about an object that a programmer must know in order to use an existing object in a program. Creating an object requires even more in-depth understanding of how objects work, particularly in defining and managing the object's interface.

    In general, there are two basic interfaces supported by the COM specification - direct and dispatch. With direct, a table is built of pointers for all methods exposed by the object and the calling program uses the pointers to jump immediately to the memory location and to execute the method found there. The table is called a virtual function table (VFT or VTBL). PowerBASIC handles creation of the table, so its use is transparent to programmers.

    With a dispatch interface, the calling program simply passes a text string containing the name of the method. Though simpler, this approach is somewhat slower so most programmers avoid it entirely.

    The COM specification also allows an object to support BOTH the direct and dispatch interfaces. Also, a class may have more than one direct interface, but only one DUAL or dispatch interface.

    GUID
    Classes, objects and interfaces are assigned unique numbers which differentiate them from any other class/object/interface in the world. The technique for generating a GUID is based on a randomly generated 128-bit string. Windows supplies API for GUID generation.

    In addition to a numerical assignment, many programmers also assign a PROGID$, which is simply a more user-friendly name for classes, objects, and interfaces. PROGID$ names are not necessarily unique.

    Object Methods
    The COM specification requires that all objects provide three common methods AddRef(), Release() and QueryInterface(). Together, these three methods are known as the IUNKNOWN interface. PowerBASIC automatically handles the creation of these methods by the inclusion of an INHERIT IUNKNOWN statement, as shown in an example below.

    In addition to the three IUNKNOWN methods, there are several other methods which programmers commonly include in objects, as shown in the following table.

    • AddRef - part of the IUNKNOWN interface
    • Release - part of the IUNKNOWN interface
    • QueryInterface - part of the IUNKNOWN interface
    • Constructor - create an object (an instance of a class)
    • Destructor - erase an object (deallocate memory)
    • DllRegisterServer - register standalone COM components (Windows registry)
    • DllUnRegisterServer - unregister standalone COM components

    Note that PowerBASIC uses "Create" as a synonym for "Constructor". It also uses "Destroy" as a synonym for "Destructor". The synonyms may be used as the method names in a class.

    Automation Methods
    ... definition

    Automation methods must use the following data types for parameters, return values, and assignment variables.

        BYTE    INTEGER    SINGLE    CURRENCY
        WORD    LONG       DOUBLE    OBJECT
        DWORD   QUAD       STRING    VARIANT
    

    Automation Methods return a hidden result code, called hResult. It reports the success/failure of a call to a property or method.

    Example Class Source Code
    Writing the code to create classes and COM components is much like writing any other application code. However, the terminology is somewhat different and there are over a dozen special commands to learn.

    Here's the source code for creating a simple class, consisting of a single method.

        CLASS MyClass
          INSTANCE Counter AS LONG      ' defines variable Counter
          INTERFACE MyInterface         ' defines 1 inteface (can be >1)
            INHERIT IUNKNOWN            ' inherit the base class
            METHOD BumpIt(Inc AS LONG) AS LONG
              Temp& = Counter + Inc
              INCR Counter
              METHOD = Temp&
            END METHOD
          END INTERFACE
          ' more interfaces could be implemented here
        END CLASS
    

    And here is the code which creates an object using the class and then uses one of the object's methods.

        FUNCTION PBMAIN()
          DIM Stuff AS MyInterface
          LET Stuff = CLASS "MyClass"
          x& = Stuff.BumpIt(77)
        END FUNCTION
    

    Example COM Component Source Code
    ... in work

    
    
    

    Object/Class Function Summary
    These function are provided in alphabetical order.

    • ACODE$ - convert Unicode to ANSI
    • CLASS/END CLASS - includes data/code for class definition
    • EVENTS - attach/detach event handler to/from an event source
    • CLSID$ - get 16-byte (128-bit) CLSID
    • GUID$ - get 16-byte (128-bit) GUID
    • GUIDTXT$ - get 38-byte human-readable GUID string
    • IDISPINFO - set/return Dispatch Status Code from OBJRESULT
    • INSTANCE - create INSTANCE variables unique to each object
    • INTERFACE (Direct) - define direct interface properties/methods
    • INTERFACE (IDBind) - define dispatch interface properties/methods
    • ISINTERFACE - check object for support of a particular interface
    • ISNOTHING - get current status of object variable
    • ISOBJECT - get current status of object variable
    • LET (with Objects) - set object reference to object variable.
    • LET (with Variants) - set variable or variant value
    • ME - references the current object
    • METHOD - define procedure within a class
    • MYBASE - references the inherited parent object
    • OBJACTIVE - state of COM EXE object (True/False)
    • OBJECT GET - get Dispatch Interface member Property
    • OBJECT LET - set/get Dispatch Interface member Property
    • OBJECT SET - set/get Dispatch Interface member Property
    • OBJECT CALL - run method of Dispatch Interface
    • OBJECT RAISEEVENT - run method event Dispatch Interface
    • OBJPTR - get object variable pointer
    • OBJRESULT - get result of OBJECT
    • OBJRESULT$ - get OBJRESULT (hResult) code
    • PROGID$ - get PROGID string (text) of CLSID
    • PROPERTY GET - get object data value
    • PROPERTY SET - set object data value
    • RAISEEVENT - Call Event Handler code
    • RESET - set variant to empty (%VT_EMPTY)
    • UCODE$ - convert ANSI to Unicode
    • VARIANT# - get variant numeric value
    • VARIANT$ - get variant string value
    • VARIANTVT - get data type variant data

    Object Function Reference
    Here's a quick reference of the available object functions, in alphabetical order.

    ... in work

    • ACODE$ - convert Unicode to ANSI
          ACode$
      

    • CLASS/END CLASS - includes data/code for class definition
          Class/End Class
      

    • EVENTS - attach/detach event handler to/from an event source
          Events
      

    • CLSID$ - get 16-byte (128-bit) CLSID
          ClsID$
      

    • GUID$ - get 16-byte (128-bit) GUID
          Guid$
      

    • GUIDTXT$ - get 38-byte human-readable GUID string
          GuidTXT$
      

    • IDISPINFO - set/return Dispatch Status Code from OBJRESULT
          IDIspInfo
      

    • INSTANCE - create INSTANCE variables unique to each object
          Instance
      

    • INTERFACE - define direct interface properties/methods
          Interface
      

    • ISINTERFACE - check object for support of a particular interface
          IsInterface
      

    • ISNOTHING - get current status of object variable
          IsNothing
      

    • ISOBJECT - get current status of object variable
          IsObject
      

    • LET (with Objects) - set object reference to object variable.
          Let
      

    • LET (with Variants) - set variable or variant value
          Let
      

    • ME - references the current object
          Me
      

    • METHOD - define procedure within a class
          Method
      

    • MYBASE - references the inherited parent object
          MyBase
      

    • OBJACTIVE - state of COM EXE object (True/False)
          ObjActive
      

    • OBJECT GET - get Dispatch Interface member Property
          Object Get
      

    • OBJECT LET - set/get Dispatch Interface member Property
          Object Let
      

    • OBJECT SET - set/get Dispatch Interface member Property
          Object Set
      

    • OBJECT CALL - run method of Dispatch Interface
          Object Call
      

    • OBJECT RAISEEVENT - run method event Dispatch Interface
          Object RaiseEvent
      

    • OBJPTR - get object variable pointer
          ObjPTR
      

    • OBJRESULT - get result of OBJECT
          ObjResults
      

    • OBJRESULT$ - get OBJRESULT (hResult) code
          ObjResult$
      

    • PROGID$ - get PROGID string (text) of CLSID
          ProgID$
      

    • PROPERTY GET - get object data value
          Property GET
      

    • PROPERTY SET - set object data value
          Property SET
      

    • RAISEEVENT - Call Event Handler code
          RaiseEvent
      

    • RESET - set variant to empty (%VT_EMPTY)
          ReSet
      

    • UCODE$ - convert ANSI to Unicode
          UCode$
      

    • VARIANT# - get variant numeric value
          Variant#
      

    • VARIANT$ - get variant string value
          Variant$
      

    • VARIANTVT - get data type variant data
          VariantVT
      

    If you have any suggestions or corrections, please let me know.