+ All Categories
Home > Documents > Stingray 2006.2 Objective Grid ActiveX UserGuide

Stingray 2006.2 Objective Grid ActiveX UserGuide

Date post: 21-Apr-2015
Category:
Upload: yancha1973
View: 528 times
Download: 15 times
Share this document with a friend
212
User’s Guide Objective Grid for ActiveX Version 11.0.0
Transcript
Page 1: Stingray 2006.2 Objective Grid ActiveX UserGuide

User’s Guide

Objective Grid for ActiveX

Version 11.0.0

Page 2: Stingray 2006.2 Objective Grid ActiveX UserGuide

OBJECTIVE GRID FOR ACTIVEX USER’S GUIDE

PRODUCT TEAM

Development: Terry Crook, Clayton Dean, Boris Meltreger, David NoiDocumentation: Marcia SteeleDirector of Stingray Development: Amit JindalProduct Manager: Shannon LewisSupport: Tim Adams, Terry Crook, Jessica LeBeck, Boris Meltreger, Nikki Sharma

THIS MANUAL

© Copyright 2006 Quovadx, Inc. All Rights Reserved.

Rogue Wave and Stingray are registered trademarks of Quovadx, Inc. in the United States and other countries. All other trademarks are the property of their respective owners.

ROGUE WAVE SOFTWARE, A QUOVADX™ DIVISION.

Address: 5500 Flatiron Parkway, Boulder, CO 80301 USAProduct Information: (303) 473-9118

(800) 487-3217Fax: (303) 473-9137Web: http://www.roguewave.com

For information on technical support, please see the Technical Support section in Chapter 1 of this User's Guide.

Page 3: Stingray 2006.2 Objective Grid ActiveX UserGuide

Contents

1Chapter 1 Introduction to Objective Grid for ActiveX

1.1 Welcome to Objective Grid for ActiveX 1

1.2 Product Features 2

1.2.1 Frequently Asked Questions 3

1.3 Supported Platforms 4

1.3.1 Objective Grid for ActiveX (OGX) and VC.NET 41.3.2 OGX and XP 5

1.4 Installed Files 5

1.5 Product Documentation 6

1.6 Using This Manual 7

1.6.1 Type Conventions 81.6.2 Glossary 8

1.7 Rogue Wave Solution Services 10

1.8 Technical Support 10

PART I USER’S GUIDE

2Chapter 2 Quick Start Guide

2.1 Introduction 13

2.2 Brief Introduction to ActiveX/Visual Basic 14

Contents iii

Page 4: Stingray 2006.2 Objective Grid ActiveX UserGuide

2.2.1 Creating a User Interface 142.2.2 Methods, Properties, and Events 222.2.3 Adding Code 232.2.4 Role of Objects 26

2.3 Using Objective Grid for ActiveX Controls 28

2.3.1 Cell Types 35

2.4 Additional Tasks 37

2.4.1 Changing Text in Column Headers 372.4.2 Assigning a Value to a Range of Cells 372.4.3 Changing behavior of the Enter key 37

3Chapter 3 Controls

3.1 Introduction 39

3.2 Control Types 39

3.3 Code Sample 43

3.4 Customization 54

3.4.1 Run time Changing of Dropdown List 543.4.2 Activate and De-activate Scrollbars 56

4Chapter 4 Tab Control Tutorial

4.1 Introduction 57

4.2 The Tab Sample 57

4.3 Important Notes 61

4.3.1 Sorting Columns 614.3.2 Manipulate functions when ActiveTab is changing 62

5Chapter 5 Database Tutorial

5.1 Register a Database 63

5.1.1 File Data Source 645.1.2 System Data Source 71

5.2 Important Terms 74

iv Objective Grid for ActiveX User’s Guide

Page 5: Stingray 2006.2 Objective Grid ActiveX UserGuide

5.3 ODBC control 75

5.4 Objective Grid DAO control 83

5.5 Objective Grid ADO control 83

5.5.1 Steps 84

6Chapter 6 Objective Grid Designer

6.1 Introduction 87

6.1.1 What is the Objective Grid Designer? 876.1.2 Stand-Alone Mode of Operation 87

6.2 Starting the Objective Grid Designer 88

6.3 Grid Designer Components 90

6.3.1 Grid Interface 906.3.2 General Settings 916.3.3 Cell Settings 97

6.4 Creating a Sample Layout File 98

6.5 Initializing a Control Using .ogl File 99

7Chapter 7 Samples

7.1 Introduction 101

7.2 Internet (CAB) Sample 102

7.3 Visual Basic Samples 102

7.4 Troubleshooting 106

7.4.1 CAB Sample 1067.4.2 General 107

8Chapter 8 Redistribution

8.1 Introduction 109

8.2 Naming Conventions 110

v

Page 6: Stingray 2006.2 Objective Grid ActiveX UserGuide

8.3 Distributing Objective Grid for ActiveX Applications 110

8.3.1 File Redistribution 1108.3.2 Registering a Component 1118.3.3 Licensing 112

9Chapter 9 Objects

9.1 Architecture Introduction 113

9.2 Parameter object 117

9.3 Style Object 117

9.3.1 Style object creation 1189.3.2 Setting style properties 1189.3.3 Style Inheritance 1199.3.4 User attributes 1219.3.5 Style Constants/Modes 1219.3.6 Virtual mode 1229.3.7 Style Implementation 1239.3.8 Virtual Functions 124

9.4 Range Object 125

9.4.1 Creating ranges 1269.4.2 Initializing ranges 1279.4.3 Retrieving a selected range 127

9.5 Range List 129

9.6 Brush Object 129

9.7 Data Object 130

9.8 Font Object 130

9.9 Stylesmap 131

9.10 Print info Object 132

9.11 Properties Object 132

9.12 State Object 132

vi Objective Grid for ActiveX User’s Guide

Page 7: Stingray 2006.2 Objective Grid ActiveX UserGuide

10Chapter 10 Advanced Topics

10.1 Undo/Redo Architecture 135

10.2 Adding Border to Cells 135

10.3 Number of Currently Visible Rows 136

10.4 Determining selected rows/cells 136

10.5 Clear the cells of the grid without selecting the grid 137

PART II VISUAL C++ USER’S GUIDE

11Chapter 11 Class Summary

11.1 Introduction 141

11.2 Understanding the OGX Source Code 141

11.2.1 Functionality as implemented 142

11.3 Control Classes 147

11.3.1 COGOleControl 147

11.4 Object Classes 148

12Chapter 12 Using OGX Control in Visual C++

12.1 Introduction 153

12.2 Pre-Requisites 153

12.3 Using the Control In VC++ 153

12.4 Calling Methods 161

12.5 Generating a Wrapper Class 167

12.6 Handling Events 168

vii

Page 8: Stingray 2006.2 Objective Grid ActiveX UserGuide

12.7 Advanced Property Manipulation 171

13Chapter 13 Building OCX Controls

13.1 Introduction 173

13.2 Building the OG ActiveX controls 173

13.3 Build Instructions 176

13.3.1 Visual C++ 6.0/7.0 176

13.4 Troubleshooting 177

13.4.1 Unresolved externals when compiling the OGX 17713.4.2 Link error 17713.4.3 Registration Fails 17713.4.4 Missing OG Header File gxall.h 177

14Chapter 14 Object Implementation in a DLL

14.1 Introduction 179

15Chapter 15 AppWizard Tutorial

15.1 Deriving Grid Control from Base Control 181

15.2 Deriving from a grid base class other than CGXGridCore 185

15.2.1 Adding methods/properties/events 186

16Chapter 16 Error Handling

16.1 Introduction 187

17Chapter 17 Interfaces

17.1 Introduction 189

17.2 Brief Introduction to COM 189

17.2.1 Evolution of COM from Dynamic Link Library (DLL) architecture 19017.2.2 OLE/COM References 192

viii Objective Grid for ActiveX User’s Guide

Page 9: Stingray 2006.2 Objective Grid ActiveX UserGuide

17.3 Adding Controls to the Tool Palette 192

17.4 Interfaces 193

ix

Page 10: Stingray 2006.2 Objective Grid ActiveX UserGuide

x Objective Grid for ActiveX User’s Guide

Page 11: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 1 Introduction to Objective Grid for ActiveX

THIS CHAPTER INCLUDES: Welcome to Objective Grid for ActiveX Product Features

Supported Platforms Installed Files Product Documentation Using This Manual Rogue Wave Solution Services Technical Support

1.1 Welcome to Objective Grid for ActiveX

Objective Grid for ActiveX is a full-featured grid control built completely from object-oriented technology. OGX can be extended quickly and easily and it pro-vides support for embedding grid objects virtually anywhere that a window can be embedded. It includes a comprehensive set of controls to embed in cells and allows you to add your own using Visual C++. Using OGX, you can bind to nearly any data source, including ODBC, DAO, and ADO.

NOTE—Before you build and register the OCXs and supporting DLLs, please read Chapter 13, “Building OCX Controls.”

OGX controls are an object-oriented wrapper (COleControl-based set of classes) around the Stingray Objective Grid C++ class library. These classes wrap the func-tionality of the grid as stand-alone ActiveX components. Since these classes are COleControl-based, you can derive new classes from them or modify the existing classes, just as you can with any other C++ class library.

OGX’s functionality is similar to that of Objective Grid for MFC. In fact, most APIs have a one-to-one correspondence. The object-oriented nature of Objective Grid is also largely carried over to the ActiveX controls, due to the use of Automation objects (an object model comprised of these objects). In short, if you have previous experience with Objective Grid for MFC, you will only need a few minutes to get going with the ActiveX version. If you do not have previous experience with the grid in C++, this User’s Guide will have you up and running quickly.

For details on the OGX Automation Objects, please refer to Chapter 9, “Objects.”

Chapter 1 Introduction to Objective Grid for ActiveX 1

Page 12: Stingray 2006.2 Objective Grid ActiveX UserGuide

1.2 Product Features

Objective Grid for ActiveX provides ActiveX developers with a feature-rich grid control (a user interface component that displays data in rows and columns).

OGX can be used as a view or as a window, enabling the user to embed grid con-trols in other windows, such as dialogs and pop-ups. The OGX control comes in a variety of configurations:

Base grid (without database support)

Tab control (with and without database support)

ADO grid

DAO grid

ODBC grid

Popular features of Objective Grid for ActiveX include:

Granular implementation - The Build Wizard and Control Factory Wizard give you the ability to exclude unwanted functionality from the compiled OGX libraries.

Wide range of built-in cell types - OGX offers more than 25 cell types, ranging from simple edit controls to formatted date-time and currency controls.

Database connectivity - OGX ships with built-in support for ODBC, DAO, and ADO databases. It also provides the ability to create new browser grids for unsupported or proprietary databases.

Undo/Redo - OGX fully supports undo/redo for built-in grid operations, including transactions and rollbacks. The architecture can be easily extended to include application-specific operations.

Printing and print preview - OGX supplies print and print preview support for grids.

Find/Replace - OGX provides support for finding and replacing cell data.

Cut/Copy/Paste - OGX supports cut/copy/paste using the Windows clipboard as well as an internal direct cut/copy/paste.

Pre-built style dialogs - A set of pre-built dialog boxes is supplied to allow your end user access to the styles architecture. These dialogs enable the end user to make changes to the grid’s appearance.

Object-oriented cell architecture - OGX uses a control sharing architecture in which each type of cell shares a single control with all similar types. Cell

2 Objective Grid for ActiveX User’s Guide

Page 13: Stingray 2006.2 Objective Grid ActiveX UserGuide

data is stored separately from the cell control. This system saves space and resources.

Excel-like interface - OGX enables the programmer to mimic many of the user interface features in Microsoft Excel.

Floating and merged cells - OGX provides support for both floating and merged cells. Floating cells are cells that automatically grow over adjacent cells to accommodate text too large for a single cell. Merged cells are adjacent cells that contain the same value and are drawn as a single large cell.

Formula support - The OGX formula engine ships with more than 200 built-in worksheet functions. If that's not enough, the formula engine can be extended with your own custom worksheet functions.

Objective Grid for ActiveX has Excel-like tabs.

Ships with full source code - OGX ships with full C++ source code.

1.2.1 Frequently Asked Questions

Before we proceed any further, let us answer some of the most frequently asked questions about this product.

Do I have to write any additional C++ code to use Objective Grid for ActiveX?

No, you do not have to write any additional C++ code to be able to use the OG ActiveX controls. The base grid control and the DAO/ODBC/ADO controls can be compiled out of the box. We also ship release builds of all these controls. You can use these out of the box without the need to do any C++ builds. Only if you need to make any modifications to the control do you need to use the OG ActiveX source inside Visual C++ and either mod-ify or derive from the provided classes.

Part II, “Visual C++ User’s Guide,” contains advice for C++ programmers using this product.

Does OG for ActiveX ship with the full source code?

Yes, Objective Grid for ActiveX ships with full source code.

Do I need the Objective Grid MFC libraries?

Yes, you will need to have the Objective Grid MFC libraries. Remember, OG ActiveX is a wrapper around Objective Grid and, therefore, needs the Objective Grid libraries to be functional.

Chapter 1 Introduction to Objective Grid for ActiveX 3

Page 14: Stingray 2006.2 Objective Grid ActiveX UserGuide

Does OGX implement a workbook interface?

OG ActiveX implements a full workbook interface, similar to that of Microsoft Excel. The worksheet tabs can be data bound with ODBC, DAO, or ADO or they can be unbound.

What types of data binding does Objective Grid for ActiveX implement?

OG ActiveX implements ODBC, DAO, and ADO-based data binding, based on the functionality provided by Objective Grid class library. The ADO control can also be used for data access across the Internet.

Does Objective Grid for ActiveX require previous OLE/ActiveX experience?

All of this functionality is available to you even if you have no previous experience with OLE/ActiveX. You do not have to be familiar with any OLE concepts or have any previous OLE experience to use the ActiveX ver-sion. We have included all the required information in the OG ActiveX User’s Guide. If you expect to significantly modify the functionality pro-vided by the ActiveX version, then you will require some exposure to basic OLE control programming using MFC. Most books on MFC programming have a few chapters on this and any such short introduction should be all you need.

Section 17.2, “Brief Introduction to COM,” discusses some of the basic aspects of the Component Object Model (COM) and Object Linking and Embedding (OLE). It also suggests some essential reading that may give you a better understanding of this product. The brief introduction to OLE and COM is designed to provide a starting point for those OG ActiveX users who have had little or no exposure to COM.

1.3 Supported Platforms

For a list of supported operating systems and compilers, see:

http://www.roguewave.com/support/matrices/

1.3.1 Objective Grid for ActiveX (OGX) and VC.NET

The procedures for building and using VC.NET OGX components are the same as those for building and using VC6 OGX components. The solution files are required for building OGX. OGX components that are built under VC.NET can be still used under VB6 and VB.NET.

4 Objective Grid for ActiveX User’s Guide

Page 15: Stingray 2006.2 Objective Grid ActiveX UserGuide

1.3.2 OGX and XP

Objective Grid for ActiveX can be compiled under both VC6 and VC.NET on Win-dows XP. On Windows XP, OGX can take advantage of XP visual styles. All the samples for OGX in VB.NET are enabled for XP visual styles. This is done by including a manifest file in the application. The visual styles applied to controls depend on the Windows theme enabled in the system.

NOTE—Refer to Microsoft Windows XP and .NET documentation, for fur-ther details on using visual styles and enabling them in applications.

For OGX to function correctly when visual styles are enabled, VB and VC applica-tions should use the Unicode versions of the OGX components. Objective Grid (OG) subclasses the common controls and uses them. When the application points to comctrl32.dll version 6.0, the subclassed control will work only with the Uni-code version of the libraries. Since OGX control classes wrap the functionality of the OG as stand-alone ActiveX components, the above-mentioned limitation of OG is also applicable to OGX. However, if the windows themes are disabled on the windows XP machine, the ANSI versions of the OGX components can be used without any problems—if the manifest file is removed from the applications.

1.4 Installed Files

When installation is complete you should see the following directories installed under the installation directory that you selected:

Table 1 – Installation Directories

Directory Definition

Appwiz Contains appwiz.awx.

Basectl This directory contains all the Base grid control code. The base grid control imple-ments all the core grid functionality in the OLE control.

Bin This folder contains the OG Designer exe-cutables as well as folders (ado, dao, db, and nodb) into which the pre-built ocxs, supporting dlls, and lic files are installed. All the controls have to be registered (using regsvr32.exe) before they can be used.

Chapter 1 Introduction to Objective Grid for ActiveX 5

Page 16: Stingray 2006.2 Objective Grid ActiveX UserGuide

1.5 Product Documentation

Documentation is located in the Docs subdirectory of your Objective Grid for ActiveX directory. The following documents are available:

User's Guide - This manual. The Objective Grid for ActiveX User's Guide is an introductory how-to manual for Objective Grid for ActiveX. Its main focus is to introduce the user to Objective Grid for ActiveX and to provide a foundation for using Objective Grid for ActiveX “out-of-the-box.” There are several tutorials included to help new Objective Grid for ActiveX users learn how to create Objective Grid for ActiveX applications quickly. This document is available in both HTML Help (ogxug.chm) and Portable Document Format (ogxug.pdf) formats.

Build Contains project, workspace, and make files.

Docs This directory contains the OG ActiveX User's Guide and other documentation.

Links This directory contains important and use-ful web page links.

ogadoobjects Supporting ADO objects DLL.

ogdaoobjects Supporting DAO objects DLL.

ogdbobjects Supporting ODBC objects DLL.

ogobjects This directory has the implementation of the supporting automation objects DLL.

Redistribution A .dep file (ogocxgrd.dep) is provided in the Redistribution folder of your installa-tion for use with the VB wizard.

samples This directory contains the samples that ship with the product. There are sample projects for use of the OG ActiveX con-trols in both Visual Basic and Visual C++.

Tools Several useful batch files and utilities are included in this directory.

Table 1 – Installation Directories (Continued)

Directory Definition

6 Objective Grid for ActiveX User’s Guide

Page 17: Stingray 2006.2 Objective Grid ActiveX UserGuide

Class Reference - The Objective Grid for ActiveX Class Reference (ogxref.chm, ogx.hlp) is a detailed description of the properties, methods, and events in Objective Grid for ActiveX.

Printed documentation - The Objective Grid for ActiveX User’s Guide may also be available as a bound printed documentation for an additional charge. For information, please contact the Rogue Wave Sales department by phone at (800) 924-4223 or by e-mail at [email protected].

Samples - Objective Grid for ActiveX ships with a wide variety of samples (located in the samples subdirectory of your Objective Grid for ActiveX installation directory).

1.6 Using This Manual

This manual is divided into two parts:

Part I serves as a user’s guide for Visual Basic programmers. All of the information you need to get started with Objective Grid for ActiveX is included in this part of the User’s Guide.

Part II will be more useful to Visual C++ programmers who need to customize the Objective Grid for ActiveX controls or who want to use the ActiveX controls in a C++ program.

NOTE—The material in Part II is provided for informational purposes only, because we do not support using the ActiveX control in this way. (If you are a C++ programmer, you may want to consider using the MFC version of Objective Grid. C++/MFC programmers are better served using the MFC version of Objective Grid. )

Chapter 1 Introduction to Objective Grid for ActiveX 7

Page 18: Stingray 2006.2 Objective Grid ActiveX UserGuide

1.6.1 Type Conventions

Throughout this document, a set of typographical conventions are used to define elements and references to Objective Grid for ActiveX items. Familiarity with these conventions will help your understanding of the topics covered.

1.6.2 Glossary

Following are definitions for several important terms that you will encounter in this User’s Guide. Check the index at the back of the book to locate further infor-mation about any of these topics.

Base Style - Base styles are grid-wide styles that make it possible to group specific kinds of cells and give them similar attributes. The predefined base styles are: row-header-style, column-header-style and standard-style. A cell in a particular row

Table 2 – Documentation conventions

Example Description

myfunc() Library routines have parenthesis '()' as a suffix.

CGXGridView Class names declared in the grid compo-nent contain the prefix 'CGX'.

GXPatB Library routines declared in the grid com-ponent begin with 'GX'.

GX_UPDATENOW Definitions and constants begin with 'GX_'

Expression Words in italics indicate placeholders for information you must supply, such as a vari-able or parameters for methods.

#include <io.h> Courier font is used for code examples.

dim str as string...str=txtName.Text

A column or row of three dots (also known as an ellipsis) indicates that part of an example program has been intentionally omitted.

ENTER

CTRL+ENTER

Words in small caps indicate names of keys on the keyboard. A plus sign (+) between two key names indicates that you should hold down the first key while pressing the second.

Menu|Menu Item Bold font is used for menu commands.

8 Objective Grid for ActiveX User’s Guide

Page 19: Stingray 2006.2 Objective Grid ActiveX UserGuide

inherits attributes from its row base style. Row header cells inherit their attributes from row-header-style. Column headers inherit from column-header-style. Stan-dard-style is the base style for all cells in the grid.

Cell - Cells display information in the grid. Each cell has a unique coordinate (row, column). Cells are associated with a control and a style object. The control is responsible for handling user events and drawing the information provided through the style object.

Control - Controls handle the interface between the end user and the grid. Each cell is associated with a control. The control interprets user events and is responsi-ble for drawing the cell.

Control Child - Controls can have small children in the cell. For example, the spin control has an up-arrow button child and a down-arrow button child. The control child is normally a small rectangular area in the parent control's area.

Covered Cells - Objective Grid for ActiveX lets you cover cells. This means that one cell can span several other cells. This is very useful for headings in reports.

Current Cell - The grid manages the current cell as the user navigates through the grid by clicking or using arrow keys. The current cell lets the user modify the cell's contents through its associated control. The end user can interact directly with the control.

Data source - Data source is a general term that can mean either an ODBC/DAO/ADO query result, a database, or any other external data structure or medium.

ODBC-Open DataBase Connectivity-A standard database access.

DAO-Data Access Objects-Objects that work with the Jet database engine. DAO are created with Visual Basic. A DAO can be accessed and manipulated by any application using the Jet engine.

ADO-ActiveX Data Object’s-Will eventually replace DAO.

Properties - Properties are settings in the grid that can be modified with pre-built dialogs and can be loaded/archived using the registry/profile. Properties are maintained by the CGXProperties class.

Range - A range defines a rectangular area of cells in the grid. A range is specified through a top and bottom row, and left and right columns. Ranges can represent a selection of cells, columns, rows, or all cells.

Style - A style contains all the information necessary for formatting a cell. A style consists of several attributes such as text color, borders, control type, and font. Each cell determines the style information at run time and passes this information to the control for drawing the cell.

Chapter 1 Introduction to Objective Grid for ActiveX 9

Page 20: Stingray 2006.2 Objective Grid ActiveX UserGuide

Workbook - A workbook lets the user switch between several views connected to the same document by clicking on a tab at bottom-left of the window.

Worksheet - Worksheet is used to refer to each of the individual views displayed in a workbook.

1.7 Rogue Wave Solution Services

The Rogue Wave Solution Services Group offers training and mentoring for all levels of project development, from analysis and design to implementation. For information on Solution Services for Stingray products, contact us at:

Telephone: (303) 473-9118 or (800) 487-3217E-mail: [email protected]: www.roguewave.com/solutions

1.8 Technical Support

Before contacting Rogue Wave Support Services for the first time, you must regis-ter with our support system. To do this, go to http://www.roguewave.com/youraccount/private/register and follow the instructions. If you would like to register an additional product, just use the Back button on your Web browser to return to the registration form.

After registering, you may then access the online technical support area with your e-mail address (or Rogue Wave ID) and password.

Technical support for Objective Grid for ActiveX products is provided through the Rogue Wave Web site. See our support page (http://www.roguewave.com/support) for access to the Knowledge Base, the online technical support form, downloadable upgrades, and technical support.

Before entering a support request, check the online Knowledge Base. In many cases, your technical support question has already been answered in the Knowl-edge Base. This valuable resource is provided as a convenience for our customers, and provides technical answers to many frequently asked questions.

If you have any difficulty accessing support online, please contact Rogue Wave Support Services at (800) 404-4767 or (303) 545-3205, or send e-mail to [email protected].

10 Objective Grid for ActiveX User’s Guide

Page 21: Stingray 2006.2 Objective Grid ActiveX UserGuide

PART I

User’s Guide

Page 22: Stingray 2006.2 Objective Grid ActiveX UserGuide

12 Objective Grid for ActiveX User’s Guide

Page 23: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 2 Quick Start Guide

THIS CHAPTER INCLUDES: Introduction Brief Introduction to ActiveX/Visual Basic Using Objective Grid for ActiveX Controls Additional Tasks

2.1 Introduction

Objective Grid for ActiveX is a suite of full-featured ActiveX controls that are spe-cially designed to take full advantage of the ActiveX environment that is provided by advanced ActiveX control containers such as Microsoft Visual Basic and Microsoft office applications.

The OG ActiveX controls are listed below, along with a brief description of what makes them unique.

Objective Grid base control (ogocxgrd.ocx): This is the control to use if you are interested in plain grid functionality and are not interested in any kind of database support (unbound mode).

Objective Grid ADO data control (ogadogrd.ocx): Use this control if you intend to access data with ADO (ActiveX Data Objects). We recommend that you use this approach for new projects. Using ADO has the added advantage that deploying your data over the Web becomes a snap. With the ADO control, samples are provided that let you deploy your data over the Internet with very little programming effort.

Objective Grid DAO data control (ogdaogrd.ocx): Use this control to access DAO (Data Access Objects) data sources. Accessing DAO-friendly data sources (such as MS Access) with this control might be faster than using ODBC.

Objective Grid ODBC data control (ogdbgrd.ocx): This is the control to use for accessing ODBC (Open DataBase Connectivity) data sources with the grid interface as the front end. This control can bind to an ODBC data source, using very little code.

Objective Grid tab control (ogocxtab.ocx): This control gives you the default Excel workbook look and feel. Multiple grid tabs are supported. Tabs can be easily inserted and removed at run time.

Chapter 2 Quick Start Guide 13

Page 24: Stingray 2006.2 Objective Grid ActiveX UserGuide

Later in this chapter we will look at using the OGX controls. First, however, we’ll take a look at Visual Basic.

2.2 Brief Introduction to ActiveX/Visual Basic

We begin with a brief introduction to the premier OLE Automation controller, Microsoft Visual Basic. Users who do not intend to use the OGX product within Microsoft Visual Basic will still benefit from reading this very brief introduction.

NOTE—Seasoned VB users may skip this introduction to VB, as it contains only the most basic terms. If you already have a basic understanding of Visual Basic and ActiveX, you might choose to skip this section.

2.2.1 Creating a User Interface

Microsoft Visual Basic was one of the first development environments to introduce the concept of visual development of Windows applications. Visual Basic ships with its own palette of controls that can be dropped onto a form and then custom-ized for application-specific needs. Figure 1 shows the Toolbox for Visual Basic 7.0.

14 Objective Grid for ActiveX User’s Guide

Page 25: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 1 – Visual Basic.NET Toolbox

The Toolbox contains many of the common controls used in the Windows environ-ment, including text boxes, labels, buttons, list boxes, and combo boxes. To use one of these controls:

Double-click on the control icon in the toolbar and an instance of the control appears on the Windows form.

or

Chapter 2 Quick Start Guide 15

Page 26: Stingray 2006.2 Objective Grid ActiveX UserGuide

Click once on the icon and then place and size the control on the form.

After you place an instance of the control on your form, you can proceed to modify the control as you see fit, using the properties provided by the control designer. All this is done without writing code. Once the user interface is complete, you can pro-ceed to interact with the control in more complex ways (using VB code).

For example, let’s say that we want to have a simple input form that will receive and use input from users. The text box control is capable of receiving text input from the user. The following steps demonstrate how to configure this user interface:

1. Create a new Visual Basic project (CTRL+SHIFT+N).

Figure 2 – New Project Dialog

2. If the Toolbox is not visible, click Toolbox on the View menu.

or

Click the Toolbox button on the Standard toolbar to display it.

16 Objective Grid for ActiveX User’s Guide

Page 27: Stingray 2006.2 Objective Grid ActiveX UserGuide

3. Locate the TextBox control on the Toolbox:

Double-click the text box icon on the VB Toolbox to create an instance of this control.

4. Click the text box to select it and drag to move it around on the form. Drag handles to resize it as necessary.

5. Select the text control and press F4 to display the Properties window (if necessary).

6. Use the Properties window to set the ForeColor property to yellow.

Chapter 2 Quick Start Guide 17

Page 28: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 3 – Properties Window

7. Set the BackColor property to blue. The result would be a control on a form that looks like the one in Figure 4.

18 Objective Grid for ActiveX User’s Guide

Page 29: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 4 – Text input control with ForeColor and BackColor properties set

8. Change the Name (property) of the text control to ’txtName’.

Chapter 2 Quick Start Guide 19

Page 30: Stingray 2006.2 Objective Grid ActiveX UserGuide

9. Clear out the Text property of the txtName text box. (This is so the text box will be blank when the form initially appears at run time.)

10. Add a label control to the left of the text box.

A label is also capable of displaying text but, unlike the text box, will not let the user change its contents.

11. Change the label’s Caption property to Name: and its TextAlign to TopRight.

20 Objective Grid for ActiveX User’s Guide

Page 31: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 5 – Caption and Alignment Properties of Label set

12. Add another TextBox control to the Windows form.

13. Change the (Name) property to nameStr.

Chapter 2 Quick Start Guide 21

Page 32: Stingray 2006.2 Objective Grid ActiveX UserGuide

The resulting form looks like the figure below.

2.2.2 Methods, Properties, and Events

Now we have the user interface required to get the user’s name. If the name of the text box is ’txtName’, we can write code like this:

Dim str as string 'Declare a string variablestr = txtName.text

The preceding code allows us to collect the name entered into the txtName text box by the user in a string variable (str). We can use or store the string in any manner that we choose. (The control can also be bound to a database so that it writes the entered values directly into the database without any work on our part.)

The key point is that the text box is seen as an object having some defined proper-ties that the programmer can manipulate at design time and/or run-time (and in some cases the user can manipulate them at run-time). The BackColor, the Fore-Color, and the Name are three text box properties, just as the text itself is one of these properties (Text). How the control changes the BackColor when we ask it to do so does not concern us. It is up to the control implementers to take care of such details. We benefit from the higher-level functionality of these controls, because they are very easy to use.

More complex controls would also have several methods. Methods are different from properties in that they often cause some action to be taken on the control.

22 Objective Grid for ActiveX User’s Guide

Page 33: Stingray 2006.2 Objective Grid ActiveX UserGuide

Properties describe the control, while methods describe and effect changes to the control. Methods can also change properties.

Events are actions of interest that happen to the control. The programmer can choose to react to or ignore them. For example, a button control can have a Click event. The control will call this event (which is often just a function) whenever the user clicks on the button. The programmer can choose to react to this event and display an acknowledgment to the user, for instance.

Other events associated with a command button control include: Leave and Enter. In addition to these, other events associated with a text box include: DoubleClick (double-click), TextChanged, Validated, and KeyPress.

2.2.3 Adding Code

Let’s try this out by creating an event procedure.

1. Change the name of your form to frmGetUserInfo and the form’s Caption to User Information.

NOTE—Caption and Text properties can have spaces or even be blank, but the name of a control cannot.

2. If the Solution Explorer window is not already visible, from the View menu choose Solution Explorer (or press CTRL+R).

3. Click the View Code button in the Project Explorer window to view the Code Window.

Chapter 2 Quick Start Guide 23

Page 34: Stingray 2006.2 Objective Grid ActiveX UserGuide

or

Double-click on the form (or on a control on it) to display the Code Window.

or

Choose Code from the View menu.

24 Objective Grid for ActiveX User’s Guide

Page 35: Stingray 2006.2 Objective Grid ActiveX UserGuide

4. Click the down-arrow to the right of the Object box. The drop-down menu contains a list of the available objects. Choose the txtName object:

5. Click the down-arrow to the right of the Procedure box. The drop-down menu contains a list of the available events. Choose the DoubleClick event.

6. Edit the txtName_DoubleClick() event procedure as follows:

Private Sub txtName_DoubleClick(ByVal sender As Object, ByVal System.EventArgs) Handles txtName.DoubleClick 'This code executes when text box is double-clicked Dim str As String 'Declare a string variable str = txtName.Text 'Store the text the User has typed nameStr.Text = "Your name is " + str + "!"End Sub

7. Run the program (F5).

8. Type a name in the text box.

9. Double-click on the text box.

Chapter 2 Quick Start Guide 25

Page 36: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 6 – Testing the User Information Input System

10. Click the Stop Debugging button to stop the program.

This simple program accepts user input and displays it back in another TextBox control. To make the program more transparent to users, you could also choose to have users click a command button labeled “Push Here” (instead of having them double-click the text box) to display the output. You could also write code that would write the data to a data storage unit (a file or a database, for example).

2.2.4 Role of Objects

We take a brief aside here to explain the use of objects in a scenario like this.

While properties, methods and events form a powerful interface that allows us to benefit from the functionality of controls, sometimes working with them can be difficult. This is especially true with complex controls. Take a grid control, for

26 Objective Grid for ActiveX User’s Guide

Page 37: Stingray 2006.2 Objective Grid ActiveX UserGuide

example. If we wanted to set the ForeColor, the BackColor, and the Font of cell 1, 1 in a grid control, we could have methods like these:

NOTE—These methods (SetForeColor, SetBackColor, SetFont, SetStyle) are used for demonstration purposes only; they are not real methods.

gridControl.SetForeColor(1,1,color1)gridControl.SetBackColor(1,1,color2)gridControl.SetFont(font1)

Now if cell 2, 2 were to have the same BackColor and Font but a different Fore-Color, then we would have to call these methods as follows:

gridControl.SetForeColor(2,2,color3)gridControl.SetBackColor(2,2,color2)gridControl.SetFont(font1)

As you can see, these calls can add up very quickly. An object-oriented grid like Objective Grid provides objects that define the cells. With objects, things become much simpler. For example, Objective Grid defines a style object that defines these properties and more.

Now the code will look like:

style.SetFont(font1)style.SetForeColor(color1)style.SetBackColor(color2)

And we can tell the grid to use this style object to set these values.

gridControl.SetStyle(1,1, style)

To change the forecolor for cell 2,2:

style.SetForeColor(color3)gridControl.SetStyle(2,2,style)

If we want to change the font, we could just say:

style.SetFont(font2)gridControl.SetStyle(2,2, style)

This sort of object-defined behavior can make things much simpler when dealing with complex controls. Most controls on the market today do not offer this kind of interface.

Chapter 2 Quick Start Guide 27

Page 38: Stingray 2006.2 Objective Grid ActiveX UserGuide

2.3 Using Objective Grid for ActiveX Controls

We will first walk through a sample that shows how Objective Grid can be used in a Visual Basic application. After this introductory session, we will look at some special controls in Chapter 3.

Adding OGX to a VB application is no different from adding any other ActiveX control.

1. Create a new Visual Basic project.

Figure 7 – New Project Dialog

2. To add the OGX control to your project, click Customize Toolbox on the Tools menu.

NOTE—You can also right-click on the Toolbox and choose Customize Toolbox to display the Customize Toolbox window.

28 Objective Grid for ActiveX User’s Guide

Page 39: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 8 – Tools Menu

Chapter 2 Quick Start Guide 29

Page 40: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 9 – Components window COM Components Tab

3. Scroll down until you locate the Objective Grid components (in alphabeti-cal order) and select Objective Grid.

NOTE—Type O to jump there quickly.

30 Objective Grid for ActiveX User’s Guide

Page 41: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 10 – Selecting the Objective Grid Control

4. Click OK.

The icon for the Objective Grid component appears on your VB.NET toolbox.

Figure 11 – GridocxCtrl Icon

5. Click the Gridocx icon.

6. Click your Windows form and drag the cross-hair mouse pointer to form a rectangle, thereby creating and sizing an instance of an OGX control on your VB form. (Or double-click to place a grid of a default size. Then you can move it around and resize it.)

7. Change the Name property for OGX control to Gridocx1.

8. Choose Code from the View menu.

Chapter 2 Quick Start Guide 31

Page 42: Stingray 2006.2 Objective Grid ActiveX UserGuide

9. Click the down-arrow to the right of the Class Name.

The drop-down menu contains a list of the available objects.

10. Choose (Base Class Events).

11. Click the down-arrow to the right of the Method Name box.

This drop-down contains a list of available events.

12. Choose Load Event, and replace the code with the following:

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim range As Object range = Gridocx1.CreateRangeObject() range.InitRange(1,1,1,1)

Dim style As Object style = Gridocx1.CreateStyleObject() style.SetValue("Hello")

'now call SetStyleRange to apply this value to range (1,1) Gridocx1.SetStyleRange(range,style, GRIDOCXLib.constantdefs.gxCopy)

'now change the values range.InitRange(2,1,2,1)

'change the value in the style object

32 Objective Grid for ActiveX User’s Guide

Page 43: Stingray 2006.2 Objective Grid ActiveX UserGuide

style.SetValue("World")

'call SetStyleRange to apply this value to range (2,1,2,1) Gridocx1.SetStyleRange(range,style, GRIDOCXLib.constantdefs.gxCopy)End Sub

13. Press F5 to run the project.

14. Try entering text in various cells. Use the Tab key or the arrow keys to move from cell to cell.

NOTE—When you are editing a cell, the default action is for the Enter key to create a new line in the active cell. This can be changed using the SetAllowEnter and SetEnterkeyAction methods of the grid param object. See Section 2.4.3 for details.

Figure 12 – Running the application.

15. Click the Stop Debugging button to stop the program.

Chapter 2 Quick Start Guide 33

Page 44: Stingray 2006.2 Objective Grid ActiveX UserGuide

As you can see from the above exercise, the API is very simple and makes use of the previously discussed style object, as well as the range object.

We merely set the range to apply the style to, change the style object to reflect the changes that we want made, and then apply this style to this range with a call to SetStyleRange().

This simple interface can be used to change every aspect of the cell. One of the objectives of providing an API such as this is to maintain consistency between set-tings. For example, much of the code above can be reused in changing say the interior color of the cells.

Shown below is some sample code that changes the interior color for cells A1 and B1. Replace the current Form1_Load() code with the following:

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)Handles MyBase.Load Dim range As Object range = Gridocx1.CreateRangeObject() range.InitRange(1,1,1,1)

Dim style As Object style = Gridocx1.CreateStyleObject() style.SetValue("Hello") style.SetInterior(RGB(0,255,0))

'now call SetStyleRange to apply this value to this range (1,1) Gridocx1.SetStyleRange(range,style, GRIDOCXLib.constantdefs.gxCopy)

'now change the values range.InitRange(2,1,2,1)

'change the value in the style object style.SetValue("World") style.SetInterior(RGB(255,0,0))

'call SetStyleRange to apply this value to range (2,1,2,1) Gridocx1.SetStyleRange(range,style, GRIDOCXLib.constantdefs.gxCopy)End Sub

As you can see from the above code, the interface for making the calls remains the same. All that was required to change the cells’ colors was one additional call to SetInterior() on the style object.

Now that we understand the basics of using the grid control, let’s add a different cell type (a combo box).

34 Objective Grid for ActiveX User’s Guide

Page 45: Stingray 2006.2 Objective Grid ActiveX UserGuide

2.3.1 Cell Types

The default cell type in an Objective Grid control is an Edit control. Typically this lets you edit a cell just as a plain edit control would. Objective Grid ships with sev-eral other controls. Depending on your needs you will be using one or more of these child controls as cell styles.

To illustrate using these controls, let’s add a simple ComboBox that displays a choice list and lets users select from this list.

1. Make sure that your grid is large enough so that you can see cell C3.

NOTE—Resize both the form and the grid, if necessary.

2. Add this code to the bottom of your Form1_Load() event procedure:

'code to display a combo boxstyle.SetControl(GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_DROPDOWN)range.InitRange(3,3,3,3)style.SetChoiceList("choice one" + Chr(10) + "choice two" + Chr(10) + "choice three" + Chr(10)).SetValue("choice one")

'the same callGridocx1.SetStyleRange range, style, gxCopy

3. Run the application (F5) to see the result.

Chapter 2 Quick Start Guide 35

Page 46: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 13 – Combo Box

4. Test the combobox. (You might want to resize column C.)

From the code above, we can see two new calls that are applied on the style object: SetControl() and SetChoiceList().

SetControl() sets the control type for the cell and the style to be a combobox. Each of the control types have predefined constants. Just making this call changes the control type that is used for this cell. GX_IDS_CTRL_CBS_DROPDOWN is the setting used to create an MFC Style Combo Box.

NOTE—SetChoiceList() is commonly used for all controls that need more than one value. With the exception of the PushButton control, with which you must use SetChoiceList() instead, one value can be set with SetValue().

As discussed in detail in Chapter 3, there are many more OGX cell types to choose from. A comprehensive list of all of the available Settings for all control types is documented in Table 4 in Chapter 3 and under the SetControl() method infor-mation in the OGX Class Reference (ogxref.chm).

36 Objective Grid for ActiveX User’s Guide

Page 47: Stingray 2006.2 Objective Grid ActiveX UserGuide

2.4 Additional Tasks

This section contains a few addtional things you might want to try as you experi-ment with the grid. Refer to Chapter 10, “Advanced Topics,” for more advanced How-To information.

2.4.1 Changing Text in Column Headers

You can remove the headers completely using the following code:

Gridocx1.GetGridParam.GridSetNumberedColHeaders(False)

You can treat the column/row headers like any other cell in the grid. In order to change the text of the headers, you can use the SetStyleRange method of the Grid object. The following code sets the text for the first two column headers:

Dim range As ObjectDim style As Objectstyle = Gridocx1.CreateStyleObject()range = Gridocx1.CreateRangeObject()style.SetValue(“Name”)range.InitRange(1,0,1,0)Gridocx1.SetStyleRange(range,style,GRIDOCXLib.constantdefs.gxOverride)style.SetValue("Customer ID")range.InitRange(2,0,2,0)Gridocx1.SetStyleRange(range,style,GRIDOCXLib.constantdefs.gxOverride)

2.4.2 Assigning a Value to a Range of Cells

The following code assigns a value to a specific range of cells:

range = Gridocx1.CreateRangeObjectrange.InitRange(1, 1, 5, 5)style = Gridocx1.CreateStyleObjectstyle.SetInterior(RGB(0, 255, 0))style.SetValue("Shirley")Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxCopy)

2.4.3 Changing behavior of the Enter key

When you are editing a cell, the default action is for the Enter key to create a new line in the active cell. This can be changed using the SetAllowEnter method (set to

Chapter 2 Quick Start Guide 37

Page 48: Stingray 2006.2 Objective Grid ActiveX UserGuide

False) of the grid style object and the SetEnterKeyAction method of the grid param object. The GX_DOWN parameter in the following code will cause the active cell to move down one row after the Enter key is pressed:

Dim param As Object Dim prop As Object Dim style As Object Dim range As Object style = Gridocx1.CreateStyleObject range = Gridocx1.CreateRangeObject range.SetTable() style.SetAllowEnter(False) Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxOverride) param = Gridocx1.GetGridParam()param.SetEnterKeyAction(GRIDOCXLib.GXDirectionType.GX_DOWN)

Table 3 lists all of the possible settings for changing the behavior of the Enter key.

Table 3 – Settings for Enter Key Action

Setting Description

0 The current cell will not change.

GX_UP The current cell should move up one row.

GX_LEFT The current cell should move left one column.

GX_RIGHT The current cell should move right one column.

GX_DOWN The current cell should move down one row.

38 Objective Grid for ActiveX User’s Guide

Page 49: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 3 Controls

THIS CHAPTER INCLUDES: Introduction Control Types Code Sample Customization

3.1 Introduction

Control types are set using the SetControl method of the OGStyle object. For example:

style.SetControl(GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_DROPDOWN)

This chapter summarizes each of the available control types and in many cases includes information on customizing their behavior.

3.2 Control Types

The following table lists all of the possible control types:

Table 4 – Control Types

Control Looks Like Setting

Edit Control

GX_IDS_CTRL_EDIT

Static Text Control

GX_IDS_CTRL_STATIC

Push Button

GX_IDS_CTRL_PUSHBTN

Radio Button

GX_IDS_CTRL_RADIOBTN

Chapter 3 Controls 39

Page 50: Stingray 2006.2 Objective Grid ActiveX UserGuide

CheckBox GX_IDS_CTRL_CHECKBOX

Edit with Hot Spot

GX_IDS_CTRL_HOTSPOT

Edit Con-trol With Spinner

GX_IDS_CTRL_SPINEDIT

Header GX_IDS_CTRL_HEADER

Edit with Scrollbar

GX_IDS_CTRL_SCROLLEDIT

ListBox GX_IDS_CTRL_LISTBOX

CheckBox, 3D Effect

GX_IDS_CTRL_CHECKBOX3D

Radio But-ton, 3D Effect

GX_IDS_CTRL_RADIOBTN3D

Combo Box No Text Fit

GX_IDS_CTRL_COMBOBOX

Combo Box Text Fit

GX_IDS_CTRL_TEXTFIT

Table 4 – Control Types (Continued)

40 Objective Grid for ActiveX User’s Guide

Page 51: Stingray 2006.2 Objective Grid ActiveX UserGuide

Combo Box Zero Based

GX_IDS_CTRL_ZEROBASED

Combo Box, Dis-play Choice, Zero Based

GX_IDS_CTRL_ZEROBASED_EX

Combo Box One Based

GX_IDS_CTRL_ONEBASED

Combo Box Dis-play Choice, One Based

GX_IDS_CTRL_ONEBASED_EX

Windows (MFC Style) Combo Box

GX_IDS_CTRL_CBS_DROPDOWN

Windows (MFC Style) Drop Down List

GX_IDS_CTRL_CBS_DROPDOWNLIST

MFC Style Tabbed Combo Box

GX_IDS_CTRL_CBS_TABBED_DROPDOWN

Table 4 – Control Types (Continued)

Chapter 3 Controls 41

Page 52: Stingray 2006.2 Objective Grid ActiveX UserGuide

MFC Style Tabbed Drop Down List

GX_IDS_CTRL_CBS_TABBED_DROPDOWNLIST

Check List Combo Box

GX_IDS_CTRL_CHECKLIST_COMBOBOX

Date Time Control With Calendar

GX_IDS_CTRL_DATETIME

Date Time Control Without Calendar

GX_IDS_CTRL_DATETIMENOCAL

Table 4 – Control Types (Continued)

42 Objective Grid for ActiveX User’s Guide

Page 53: Stingray 2006.2 Objective Grid ActiveX UserGuide

3.3 Code Sample

The following code is used in the gridapp sample to create a number of different controls:

Public Sub Controls_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles ControlsTypes.Click ' initialize some state variables bValidate = False IsOwnerDraw = False IsVirtual = False

' some useful values Dim strTab As String Dim strLinef As String

strTab = Chr(System.Windows.Forms.Keys.Tab) strLinef = Chr(10)

'This page displays and demonstrates the usage of some of the more commonly used controls.

' refer styles_click for more details on sharing parameter objects and a step wise explanation of the

Currency Control

GX_IDS_CTRL_CURRENCY

Masked Edit Control

GX_IDS_CTRL_MASKEDIT

Table 4 – Control Types (Continued)

Chapter 3 Controls 43

Page 54: Stingray 2006.2 Objective Grid ActiveX UserGuide

' calls made here and elsewhere Dim b As Boolean Dim range As Object Dim Style As Object Dim strTabbedChoice As String Dim nSelIndex As Short Dim styleStandard As Object If (controlBool = False) Then controlParam = Gridocx1.CreateParamObject() Gridocx1.SetParam(controlParam, False)

Gridocx1.InitializeGrid()

’ The parameter object has been created controlBool = True

b = Gridocx1.LockUpdate(True)

Gridocx1.SetRowCount(0) Gridocx1.SetColCount(0)

Gridocx1.SetRowCount(35) Gridocx1.SetColCount(10)

Gridocx1.InteriorColor = System.Drawing.ColorTranslator.FromOle(RGB(255, 255, 255))

'shows the OG controls 'create an object of type Range range = Gridocx1.CreateRangeObject()

'All aspects of the cells can be manipulated with the style 'objects 'declare an object 'create a CGXStyle object Style = Gridocx1.CreateStyleObject()

range.InitRange(1, 1, 1, 1) Gridocx1.SetValueRange(range, "Cell Types", 2)

range.InitRange(1, 2, 1, 2) Gridocx1.SetValueRange(range, "Edit control", 2)

'call setStyleRange to set the style object on this range Style.SetControl(GRIDOCXLib.constantdefs.GX_IDS_CTRL_EDIT) Style.SetValue("Edit control") range.InitRange(3, 2, 3, 2) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

44 Objective Grid for ActiveX User’s Guide

Page 55: Stingray 2006.2 Objective Grid ActiveX UserGuide

range.InitRange(1, 3, 1, 3) Gridocx1.SetValueRange(range, "Static control", 2)

'call setStyleRange to set the style object on this range Style.SetControl(GRIDOCXLib.constantdefs.GX_IDS_CTRL_STATIC) range.InitRange(3, 3, 3, 3) Style.SetValue("Static Text") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 4, 1, 4) Gridocx1.SetValueRange(range, "Push Button", 2)

'call setStyleRange to set the style object on this range Style.SetControl (GRIDOCXLib.constantdefs.GX_IDS_CTRL_PUSHBTN) range.InitRange(3, 4, 3, 4) Style.SetChoiceList("Push") Style.SetInterior(GetSysColor(COLOR_BTNFACE)) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 5, 1, 5) Gridocx1.SetValueRange(range, "Radio Button", 2)

'call setStyleRange to set the style object on this range Style.Free() Style.SetControl (GRIDOCXLib.constantdefs.GX_IDS_CTRL_RADIOBTN) range.InitRange(3, 5, 3, 5) ' the list of choices for the radio button group Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

Gridocx1.ResizeRowHeightsToFit(range)

range.InitRange(1, 6, 1, 6) Gridocx1.SetValueRange(range, "CheckBox", 2)

'call setStyleRange to set the style object on this range Style.Free() Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CHECKBOX) range.InitRange(3, 6, 3, 6) Style.SetValue("CheckBox") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

Chapter 3 Controls 45

Page 56: Stingray 2006.2 Objective Grid ActiveX UserGuide

range.InitRange(1, 7, 1, 7) Gridocx1.SetValueRange(range, "Edit with Hot Spot", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_HOTSPOT) range.InitRange(3, 7, 3, 7) Style.SetValue("Try me!") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 8, 1, 8) Gridocx1.SetValueRange(range, "Edit Control With Spinner", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_SPINEDIT) range.InitRange(3, 8, 3, 8) Style.SetValue("Try me!") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 9, 1, 9) Gridocx1.SetValueRange(range, "Bitmap Button", 2)

'Bitmap button 'Dim pathStr As String 'Please hard code the path if this call fails due to an incorrect path 'pathStr = StingRegOcx1.GetInstalledPath + "\samples\images\"

' we use two bitmaps one for regular position and one to be displayed when clicked on ' Both can be the same Gridocx1.RegisterBitmapControl(2000, "..\sad.bmp", "..\happy.bmp", CStr(0)) Style.SetBitmap(2000) range.InitRange(3, 9, 3, 9) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 10, 1, 10) Gridocx1.SetValueRange(range, "Edit with Scrollbar", 2)

'call setStyleRange to set the style object on this range Style.SetControl(

46 Objective Grid for ActiveX User’s Guide

Page 57: Stingray 2006.2 Objective Grid ActiveX UserGuide

GRIDOCXLib.constantdefs.GX_IDS_CTRL_SCROLLEDIT) range.InitRange(3, 10, 3, 10) Style.SetValue("Try me! As you can see I have a scrollbar") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride) Gridocx1.SetRowHeight(10, 10, 55)

range.InitRange(1, 11, 1, 11) Gridocx1.SetValueRange(range, "ListBox", 2)

’call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_LISTBOX) range.InitRange(3, 11, 3, 11) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride) Gridocx1.ResizeRowHeightsToFit(range)

range.InitRange(1, 12, 1, 12) Gridocx1.SetValueRange(range, "3D CheckBox", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CHECKBOX3D) range.InitRange(3, 12, 3, 12) Style.SetValue("Check Me!") Style.SetChoiceList("3D checkbox") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 13, 1, 13) Gridocx1.SetValueRange(range, "3D Radio Button", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_RADIOBTN3D) range.InitRange(3, 13, 3, 13) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride) Gridocx1.ResizeRowHeightsToFit(range)

range.InitRange(1, 14, 1, 14) Gridocx1.SetValueRange(range, "Combobox No Text Fit", 2)

Chapter 3 Controls 47

Page 58: Stingray 2006.2 Objective Grid ActiveX UserGuide

'call setStyleRange to set the style object on this range 'We call free whenever we have to re initialize the style Style.Free() Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_DROPDOWN) range.InitRange(3, 14, 3, 14) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("Choice one") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 15, 1, 15) Gridocx1.SetValueRange(range, "Combobox Text Fit", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_TEXTFIT) range.InitRange(3, 15, 3, 15) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("Choice two") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride) Gridocx1.ResizeRowHeightsToFit(range)

range.InitRange(1, 16, 1, 16) Gridocx1.SetValueRange(range, "ComboBox Zero Based", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_ZEROBASED) range.InitRange(3, 16, 3, 16) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("1") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 17, 1, 17) Gridocx1.SetValueRange(range, "ComboBox Zero Based Ex", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_ZEROBASED_EX) range.InitRange(3, 17, 3, 17) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("1")

48 Objective Grid for ActiveX User’s Guide

Page 59: Stingray 2006.2 Objective Grid ActiveX UserGuide

Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 18, 1, 18) Gridocx1.SetValueRange(range, "ComboBox One Based", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_ONEBASED) range.InitRange(3, 18, 3, 18) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("1") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 19, 1, 19) Gridocx1.SetValueRange(range, "ComboBox One Based Ex", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_ONEBASED_EX) range.InitRange(3, 19, 3, 19) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("1") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 20, 1, 20) Gridocx1.SetValueRange(range, "Windows Combobox", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_DROPDOWN) range.InitRange(3, 20, 3, 20) Style.SetChoiceList("choice one" & Chr(10) & "choice two" & Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("Choice one") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 21, 1, 21) Gridocx1.SetValueRange(range, "Windows Drop Down List", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_DROPDOWNLIST) range.InitRange(3, 21, 3, 21) Style.SetChoiceList("choice one" & Chr(10) & "choice two" &

Chapter 3 Controls 49

Page 60: Stingray 2006.2 Objective Grid ActiveX UserGuide

Chr(10) & "choice three" & Chr(10)).SetValue("0") Style.SetValue("Choice one") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

range.InitRange(1, 22, 1, 22) Gridocx1.SetValueRange(range, "Tabbed Combo box", 2)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_TABBED_DROPDOWN) range.InitRange(3, 22, 3, 22)

' line 1: On the same line choices are seperated by tabs strTabbedChoice = "A01" & strTab & "FISH" & strTab & "One" & strLinef strTabbedChoice = strTabbedChoice & "A02" & strTab & "Pork" & strTab & "Two" & strLinef strTabbedChoice = strTabbedChoice & "A03" & strTab & "Beef" & strTab & "Three" & strLinef strTabbedChoice = strTabbedChoice & "A04" & strTab & "Prawn" & strTab & "Four" & strLinef strTabbedChoice = strTabbedChoice & "A05" & strTab & "Yum!" & strTab & "Five" & strLinef

Style.SetChoiceList(strTabbedChoice) Style.SetValue("Choice one")

' here is a good place to illustrate user attributes

' Reason for having user attributes: ' Throughout the grid code we have been careful to provide ' a consistent programming interface ' For example the value of a string in a text box is also ' accessed and set with Set/GetValue ' and so is the value of a checkbox though both are ' different in more ways than one ' This does not however hold good always and with more ' complex control there have to be other variables ' that define aspects of the control ' User attributes provide this interface. They are ' specific to each control, yet they can be accessed ' through a ' consistent programming interface

' In the case of the tabbed combo box, we have two user ' attributes that we use here ' GX_IDS_UA_TABLIST_KEYCOL: Denotes the column that will

50 Objective Grid for ActiveX User’s Guide

Page 61: Stingray 2006.2 Objective Grid ActiveX UserGuide

' be used as the value (Get/SetValue will deal with this) ' GX_IDS_UA_TABLIST_TEXTCOLL Denotes the column that will ' be displayed. This is usually for the benefit of the user ' For example all of the above meats have their own codes. ' But to the user these are displayed with the descriptive ' name in column 1

Style.SetUserAttribute( GRIDOCXLib.constantdefs.GX_IDS_UA_TABLIST_KEYCOL, 0) Style.SetUserAttribute( GRIDOCXLib.constantdefs.GX_IDS_UA_TABLIST_TEXTCOL, 1) Style.SetValue("A01") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

' tabbed MFC combobox range.InitRange(1, 23, 1, 23) Gridocx1.SetValueRange(range, "MFC Style Tabbed Combo box", GRIDOCXLib.constantdefs.gxCopy)

'call setStyleRange to set the style object on this range Style.SetControl( GRIDOCXLib.constantdefs. GX_IDS_CTRL_CBS_TABBED_DROPDOWNLIST) range.InitRange(3, 23, 3, 23) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

' check list combobox range.InitRange(1, 24, 1, 24) Gridocx1.SetValueRange(range, "Check List Combo box", GRIDOCXLib.constantdefs.gxCopy)

' declare an integer and set the bits ' Selection for this special control is through bitwise ' flags ' In this case to set the first two entries we have to set ' the lower two bits as shown below nSelIndex = (&H1S Or &H2S)

'call setStyleRange to set the style object on this range Style.SetChoiceList("State Choice" & strLinef & "South Carolina" & strLinef & "Georgia" & strLinef & "Alabama" & strLinef & "North Carolina") Style.SetValue(nSelIndex) Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CHECKLIST_COMBOBOX) range.InitRange(3, 24, 3, 24)

Chapter 3 Controls 51

Page 62: Stingray 2006.2 Objective Grid ActiveX UserGuide

Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

' the date time control complete with drop down calendar range.InitRange(1, 25, 1, 25) Gridocx1.SetValueRange(range, "Date time control with calendar", GRIDOCXLib.constantdefs.gxCopy)

'call setStyleRange to set the style object on this range ' set the date Style.SetValue("4/5/71") Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_DATETIME) range.InitRange(3, 25, 3, 25) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

' we can also use this control in several formats and ' without the calendar ' the date time control without drop down calendar

range.InitRange(1, 26, 1, 26) Gridocx1.SetValueRange(range, "Date time control without calendar", GRIDOCXLib.constantdefs.gxCopy) 'call setStyleRange to set the style object on this range ' set the date

Style.SetValue("4/5/71") Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_DATETIMENOCAL) range.InitRange(3, 26, 3, 26) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

' the currency control with calculator

range.InitRange(1, 27, 1, 27) Gridocx1.SetValueRange(range, "Currency control", GRIDOCXLib.constantdefs.gxCopy)

'call setStyleRange to set the style object on this range ' set the date Style.SetValue("100") Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CURRENCY) ' the number of fractional digits allowed Style.SetUserAttribute( GRIDOCXLib.constantdefs.GX_IDS_UA_CURNUMFRACT, "6") ' the number of decimal digits allowed

52 Objective Grid for ActiveX User’s Guide

Page 63: Stingray 2006.2 Objective Grid ActiveX UserGuide

Style.SetUserAttribute( GRIDOCXLib.constantdefs.GX_IDS_UA_CURNUMDECIMALS, "6") ' the seperatot betwen two groups Style.SetUserAttribute( GRIDOCXLib.constantdefs.GX_IDS_UA_CURSEP, " .") ' the monetary symbol Style.SetUserAttribute( GRIDOCXLib.constantdefs.GX_IDS_UA_CURMON, "$") ' this user attribute controls several aspects of the ' currency control ' Please refer to the documentation for more details Style.SetUserAttribute(\ GRIDOCXLib.constantdefs.GX_IDS_UA_CURRENCYDEF, "11 1")

' there are user attributes for controlling the number of ' decimals and fractions etc

range.InitRange(3, 27, 3, 27) Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

'Masked edit control

range.InitRange(1, 28, 1, 28) Gridocx1.SetValueRange(range, "Masked Edit control", GRIDOCXLib.constantdefs.gxCopy)

range.InitRange(3, 28, 3, 28) Style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_MASKEDIT) 'set the mask and the prompt 'SS number mask, Prompt

Style.SetMask("###-##-####", "_") Style.SetValue("999999999") Gridocx1.SetStyleRange(range, Style, GRIDOCXLib.constantdefs.gxOverride)

'Resize the titles column range.InitRange(1, 1, 1, 35) Gridocx1.ResizeColWidthsToFit(range)

Gridocx1.SetColWidth(3, 3, 150)

Chapter 3 Controls 53

Page 64: Stingray 2006.2 Objective Grid ActiveX UserGuide

range.SetTable() Gridocx1.ResizeRowHeightsToFit(range)

'make the bitmap button a little bigger Gridocx1.SetRowHeight(9, 9, 75)

' some fancy colors for the table styleStandard = Gridocx1.StandardStyle() styleStandard.SetTextColor(RGB(0, 0, 255))

Gridocx1.LockUpdate(b)

Gridocx1.RedrawGrid( GRIDOCXLib.constantdefs.GX_INVALIDATE)

Else ' reuse the parameter object that we created earlier Gridocx1.SetParam(controlParam, False) Gridocx1.RedrawGrid( GRIDOCXLib.constantdefs.GX_INVALIDATE) End If

End Sub

3.4 Customization

3.4.1 Run time Changing of Dropdown List

To change the content of the drop-down list, you need to use the SetChoiceList method of the style object and re-apply the style to the cell that contains the Drop-DownList control.

The following code demonstrates how to add an additional item to the choicelist at run time. It also shows how you can display sorted dropdown lists.

Dim ChoiceList(20) As StringDim ChoiceString As StringDim NumberOfChoices As Integer

Private Sub Gridocx1_OnGridInitialUpdate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Gridocx1.OnGridInitialUpdate Dim n As Integer

ChoiceList(0) = "aa" ChoiceList(1) = "bb"

54 Objective Grid for ActiveX User’s Guide

Page 65: Stingray 2006.2 Objective Grid ActiveX UserGuide

ChoiceList(2) = "cc" NumberOfChoices = 2 ChoiceString = ""

For n = 0 To NumberOfChoices ChoiceString = ChoiceString & ChoiceList(n) + Chr(10) Next n

SetListOfChoices()End Sub

Private Sub SetListOfChoices() Dim style As Object Dim range As Object

style = Gridocx1.CreateStyleObject range = Gridocx1.CreateRangeObject

style.SetControl( GRIDOCXLib.constantdefs.GX_IDS_CTRL_CBS_DROPDOWNLIST) range.InitRange(1, 1, 1, 1)

style.SetChoiceList(ChoiceString).SetValue("aa")

Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxOverride)End Sub

Private Sub Button1_Click(ByVal sender As Object, ByVal e AsSystem.EventArgs) Handles Button1.Click Dim n As Integer ChoiceString = "" NumberOfChoices = NumberOfChoices + 1 ChoiceList(NumberOfChoices) = Text1.Text

For n = 0 To NumberOfChoices ChoiceString = ChoiceString & ChoiceList(n) + Chr(10) Next n

SortItems()

End Sub

Private Sub SortItems() Dim flag As Boolean Dim temp As String Dim n As Integer

Do flag = False

Chapter 3 Controls 55

Page 66: Stingray 2006.2 Objective Grid ActiveX UserGuide

For n = 0 To NumberOfChoices - 1 If ChoiceList(n) > ChoiceList(n + 1) Then temp = ChoiceList(n) ChoiceList(n) = ChoiceList(n + 1) ChoiceList(n + 1) = temp flag = True End If Next n Loop While flag = True

ChoiceString = "" For n = 0 To NumberOfChoices ChoiceString = ChoiceString & ChoiceList(n) + Chr(10) Next n

SetListOfChoices()

End Sub

3.4.2 Activate and De-activate Scrollbars

The control method SetScrollBarMode bar, mode allows you to control the vis-ibility of the scrollbars in the grid.

Here, bar is 0 (SB_HORZ), 1 (SB_VERT) or 3 (SB_BOTH). The mode is either 0 (dis-abled and hidden) or 1 (enabled and visible).

Gridocx1.SetScrollBarMode(3,0) 'disable both bars

Gridocx1.SetScrollBarMode(1,1) 'enable vertical scrollbar

56 Objective Grid for ActiveX User’s Guide

Page 67: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 4 Tab Control Tutorial

THIS CHAPTER INCLUDES: Introduction The Tab Sample Important Notes

4.1 Introduction

In most cases, using grid tab controls is the same as using regular grids. There are two main differences between the tab control and the regular OGX control.

The tab control's methods and properties are always delegated to the Active Tab. This Active Tab need not be the tab with which the user is interacting. You have to set the Active Tab first. The Active Tab can be changed with a call to ActiveTab. You should always call ActiveTab to ensure that you get the expected results.

When in a event, you should call GetCurrentEventFirer to get the index of the tab that is firing this event. Once you have this index, you will normally set the active tab to be this index and then interact with the control as you would interact with a regular OGX control.

NOTE—Because the GridPrintPreview method is not exposed in the GridTab control, the print preview functionality is not available when using the Tab version of the Grid.

4.2 The Tab Sample

Figure 14 shows the tab control in action. The exercise in this tab tutorial comes from the Tab sample included with your OGX installation. Follow these directions to duplicate the Tab sample’s functionality.

Chapter 4 Tab Control Tutorial 57

Page 68: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 14 – Tab Sample

1. Create a new VB project.

2. Add the Objective Grid Tab Control to the Toolbox.

3. Place a tab control on the form: Gridocxtab.

4. Add two command buttons, as shown in Figure 14:

cmdAddTab

cmdRemoveTab

58 Objective Grid for ActiveX User’s Guide

Page 69: Stingray 2006.2 Objective Grid ActiveX UserGuide

5. Add the following code:

Private Sub cmdAddTab_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdAddTab.Click Dim b As Boolean Static nCount As Short

nCount = nCount + 1

b = Gridocxtab1.InsertTab(0, "COGTabGrid", "Insert" & Str(nCount))

' initialize the inserted tab Dim iCurrentTab As Short iCurrentTab = Gridocxtab1.ActiveTab

Gridocxtab1.ActiveTab = 0

Gridocxtab1.NumRows = 100 Gridocxtab1.NumCols = 10

Dim style As Object Dim range As Object

style = Gridocxtab1.CreateStyleObject() range = Gridocxtab1.CreateRangeObject()

range.InitRange(1, 1, 1, 1) style.SetValue("New Tab")

Gridocxtab1.SetStyleRange(range, style, GRIDTABLib.constantdefs.gxOverride)

Gridocxtab1.ActiveTab = iCurrentTab

End Sub

Private Sub cmdRemoveTab_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdRemoveTab.Click Dim b As Boolean

If (Gridocxtab1.NumberOfTabs > 1) Then b = Gridocxtab1.RemoveTab(0) End If

End Sub

Chapter 4 Tab Control Tutorial 59

Page 70: Stingray 2006.2 Objective Grid ActiveX UserGuide

Private Sub Gridocxtab1_PreInitialUpdate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Gridocxtab1.PreInitialUpdate

Gridocxtab1.ActiveTab = 0 Gridocxtab1.EnableAsDropTarget() Gridocxtab1.EnableGridAsOleSource(0)

Dim retval As Object ' This is an example for the tab control. There are only ' two differences between the tab control ' and the regular control. ' 1) ' The tab control's methods and properties are always ' delegated to what is called the Active Tab ' This tab need not be the tab that the users is ' interacting with and can be changed with a ' call to ActiveTab. Always call ActiveTab to ensure ' that you get the expected results ' 2) ' When in a event call GetCurrentEventFirer to get the ' index of the tab that is firing this event ' Once you have this index you will normally set the ' active tab to be this index and then ' interact with the control as you would interact with a ' regular OGX ActiveX control

' The sample code shown below illustrates this simple ' mechanism for ineracting with the tabs

' special note: use this event only for initializing ' original tabs ' Initialize inserted tabs after inserting them

retval = Gridocxtab1.GetCurrentEventFirer()

Dim iCurrentTab As Short

If (retval = 0) Then iCurrentTab = Gridocxtab1.ActiveTab Gridocxtab1.ActiveTab = 0 Gridocxtab1.NumRows = 100 Gridocxtab1.NumCols = 10 Gridocxtab1.ActiveTab = iCurrentTab End If

If retval = 1 Then

60 Objective Grid for ActiveX User’s Guide

Page 71: Stingray 2006.2 Objective Grid ActiveX UserGuide

g_bInitTab = False iCurrentTab = Gridocxtab1.ActiveTab Gridocxtab1.ActiveTab = 1 Gridocxtab1.NumRows = 10 Gridocxtab1.NumCols = 100 Gridocxtab1.ActiveTab = iCurrentTab End If

End Sub

6. Run the project (F5) and test the buttons.

4.3 Important Notes

4.3.1 Sorting Columns

In most cases, using grid tabs is the same as using regular grids (except that you have to set the ActiveTab first). However, the SortCols method that is used to sort columns in regular grids does not exist for GridTabs. As a result, you must use a different technique to enable sorting. You have several options:

You can use multiple instances of the 'nodb' base control, installed on the panels of a tab control. The 'nodb' base control provides full sorting support.

You can implement a sorting function in VB, which programmatically re-order the rows of the grid with the needed criteria.

You can use HorizontalSorting and VerticalSorting to give the user the abiliy to sort the grid by double-clicking. Fortunately both of these methods are exposed in the TabGrid control.

The 'HorizontalSorting' and the 'VerticalSorting' properties of the Gridocx object do not have any visual effect on the grid, but they enable/disable the feature of sorting the grid when the user double-clicks on a row/column header. On the double-click, the grid gets sorted based on the selected row/column.

Put the following code in the PreInitialUpdate event handler for the Gri-docxTab control to enable sorting:

Private Sub Gridocxtab1_PreInitialUpdate(ByVal sender As Object, ByVal e As System.EventArgs) HandlesGridocxtab1.PreInitialUpdateDim retval As Integerretval = Gridocx1.GetCurrentEventFirer()

Chapter 4 Tab Control Tutorial 61

Page 72: Stingray 2006.2 Objective Grid ActiveX UserGuide

Dim iCurrentTab As IntegerIf (retval = 0) Then iCurrentTab = Gridocx1.ActiveTab Gridocx1.ActiveTab = 0 Gridocx1.NumRows = 10 Gridocx1.NumCols = 10 Gridocx1.HorizontalSorting = True Gridocx1.ActiveTab = iCurrentTab End If If (retval = 1) Then iCurrentTab = Gridocx1.ActiveTab Gridocx1.ActiveTab = 1 Gridocx1.NumRows = 10 Gridocx1.NumCols = 10 Gridocx1.HorizontalSorting = True Gridocx1.ActiveTab = iCurrentTab End If

When you double-click on a column header, the grid gets sorted based on the values contained in the cells of these columns.

4.3.2 Manipulate functions when ActiveTab is changing

The architecture of the tab control allows you to have only one instance of the grid object and multiple tabs with different views. The tab's control methods and prop-erties are always delegated to the active tab. So, to perform a search on a single view, you need to activate that view. You can perform a search only on the spread-sheet of the tab currently active.

All events on a gridtab have to be handled sequentially. A non-active tab can fire the events, but it is not possible to perform an action on a view of the TabGrid object and, at the same time, to handle an event fired by another view.

The 'GetCurrentEventFirer' allows you to retrieve the tab of the spreadsheet that is firing an event. A specific spreadsheet can fire an event only if it is activated. With this architecture, the idea of running a search on a tab and receiving notification of an event from another tab is not applicable.

62 Objective Grid for ActiveX User’s Guide

Page 73: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 5 Database Tutorial

THIS CHAPTER INCLUDES: Register a Database Important Terms ODBC control Objective Grid DAO control Objective Grid ADO control

5.1 Register a Database

In order to access a database as a data source you must first register it as a data-source. Use the ODBC Data Source Administrator to register the \Rogue Wave\Objective Grid for ActiveX\samples\Northwind.mdb database. You’ll need to register this data source before continuing with the ODBC tutorial.

NOTE—This section gives you step by step instructions. If you don’t need the details, skip this section.

1. Locate the Northwind.mdb file in the \Rogue Wave\Objective Grid for ActiveX\samples\ folder. Make sure your copy of Northwind.mdb is not read-only.

2. If you are using Windows 2000 or Windows XP, start the ODBC Data Source Administrator by double-clicking the Data Sources (ODBC) icon in the Control Panel\Administrative Tools.

NOTE—If your machine is running a different operating system, you may need to search around a bit to locate the icon for the ODBC Data Source Administrator.

3. Click the tab corresponding to the category of data source you want to register.

For example, an ODBC File data source allows you to connect to a data pro-vider. File DSNs can be shared by users who have the same drivers installed. An ODBC System data source is visible to all users on the machine, including NT services. Figure 15, Figure 16, and Figure 17 explain the difference between the three different categories of ODBC data sources.

Chapter 5 Database Tutorial 63

Page 74: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—You must use a System DSN instead of a FileDSN if you plan to have your application open the data source automatically with a con-nect string.

Figure 15 – User Data Source

Figure 16 – System Data Source

Figure 17 – File Data Source

5.1.1 File Data Source

NOTE—You must use a System DSN instead of a FileDSN if you plan to have your application open the data source automatically with a con-nect string.

1. After starting the ODBC Data Source Administrator, select the File DSN tab.

64 Objective Grid for ActiveX User’s Guide

Page 75: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 18 – File DSN Tab

2. Click the Add button.

Chapter 5 Database Tutorial 65

Page 76: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 19 – Creating a new data source

3. Select the driver that corresponds to Access (*.mdb).

4. Click Next.

5. In the Create New Data Source dialog, type MyODBCDataSource as the Data Source Name.

66 Objective Grid for ActiveX User’s Guide

Page 77: Stingray 2006.2 Objective Grid ActiveX UserGuide

6. Click Next.

Chapter 5 Database Tutorial 67

Page 78: Stingray 2006.2 Objective Grid ActiveX UserGuide

7. Click Finish.

68 Objective Grid for ActiveX User’s Guide

Page 79: Stingray 2006.2 Objective Grid ActiveX UserGuide

8. Click Select.

9. Navigate to the samples folder and select the name of the database (Northwind.mdb).

Figure 20 – Selecting the Database

10. Click OK.

Chapter 5 Database Tutorial 69

Page 80: Stingray 2006.2 Objective Grid ActiveX UserGuide

11. Confirm that the correct database is selected.

12. Click OK.

70 Objective Grid for ActiveX User’s Guide

Page 81: Stingray 2006.2 Objective Grid ActiveX UserGuide

13. Make sure the MyODBCDataSource database shows up correctly.

Figure 21 – Database has been correctly registered

14. Click OK.

NOTE—You have now successfully registered the Northwind database as a data source. This data source can be used for the ODBC tutorial in this chapter.

5.1.2 System Data Source

NOTE—You must use a System DSN instead of a FileDSN if you plan to have your application open the data source automatically with a con-nect string.

Chapter 5 Database Tutorial 71

Page 82: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 22 – System DSN Tab

1. Select the System DSN tab.

2. Click the Add button.

72 Objective Grid for ActiveX User’s Guide

Page 83: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 23 – Creating a new data source

3. Select the driver that corresponds to Access (*.mdb).

4. Click Finish.

5. In the ODBC Microsoft Access Setup dialog, type Northwind as the Data Source Name. (You don’t need to add a description.)

6. Click Select.

7. Navigate to the samples folder and select the name of the database (Northwind.mdb).

8. Click OK.

9. Make sure the Northwind database shows up correctly.

10. Click OK.

Chapter 5 Database Tutorial 73

Page 84: Stingray 2006.2 Objective Grid ActiveX UserGuide

5.2 Important Terms

ODBC data sources are typically abstracted in most environments using databases and recordsets. The database typically represents the connection and the recordset represents the actual data. We will now see how we can create and use these objects in the context of Objective Grid.

Your Visual Basic application can communicate with a database through an OGX control. The name of the database object in this example is database (declared as a global object). The following code demonstrates how this is done:

'database is a global objectDim database As Object

database = GridocxOdbc1.CreateDatabaseObject() database.Open("", False, False, "", False)

A recordset is a “virtual” table created by an SQL statement. In our example recset is the name of the recordset object declared in the PreInitialUpdate procedure.

Dim recset As Objectrecset = GridocxOdbc1.CreateRecordsetObject()

The connection between the recordset and database is created with the following code:

recset.setdatabase(database)GridocxOdbc1.SetRecordset(recset)

The Northwind database has a table called Customers. We’ll be retrieving the data from this table to display in our grid.

The GridOpenRecordset method of the Gridocx object requires the following steps before you will be able to call it:

1. Open a registered database using the CreateDatabaseObject method and the Open method of the OGDatabase object.

2. Create a new recordset using CreateRecordsetObject and assign the database to the recordset with the SetDatabase method of the OGRecord-set object.

3. Create a query on the recordset using the Query method of the OGRecord-set object.

4. Assign the recordset to the grid using the GridOpenRecordset method of the Gridocx object.

74 Objective Grid for ActiveX User’s Guide

Page 85: Stingray 2006.2 Objective Grid ActiveX UserGuide

In the next section we’ll add code to view a data source. Try the following tutorial to see how all of this fits together.

5.3 ODBC control

1. Create a new Visual Basic project.

2. Name the form frmODBCQuery.

3. Select Customize Toolbox from the Tools menu.

4. Select Objective Grid ODBC control.

5. Click OK.

6. Click the GridocxOdbc icon and create an instance of this control on the form.

7. Change the name of the OGX control to GridocxOdbc.

8. To add a menu, double click the MainMenu component in the Toolbox.

9. Using Table 5 as reference, add a menu control as follows:

Chapter 5 Database Tutorial 75

Page 86: Stingray 2006.2 Objective Grid ActiveX UserGuide

Table 5 – Menu Items

Caption Name

New SQL Query NewQuery

Requery Requery

Print preview ppview

Exit Exit

76 Objective Grid for ActiveX User’s Guide

Page 87: Stingray 2006.2 Objective Grid ActiveX UserGuide

10. Choose Project|Add Windows Form to create a second form (frmQuery) as follows:

Name the text box txtQuery.

Name the buttons cmdOK and cmdCancel.

11. Add the following code for frmQuery:

Private Sub cmdOK_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdOK.Click Me.Hide()End Sub

Private Sub cmdCancel_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdCancel.Click Query.Text = "" Me.Hide()End Sub

Private Sub frmQuery_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load 'Default query. Shows all fields from the Customers table. txtQuery.Text = "SELECT * FROM Customers"End Sub

12. Enter code as follows for frmODBCQuery:

Dim database As ObjectPrivate Sub GridocxOdbc_PreInitialUpdate(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles GridocxOdbc.PreInitialUpdate Dim recset As Object database = GridocxOdbc.CreateDatabaseObject()

Chapter 5 Database Tutorial 77

Page 88: Stingray 2006.2 Objective Grid ActiveX UserGuide

database.Open("", False, False, "", False)

recset = GridocxOdbc.CreateRecordsetObject() recset.setdatabase(database)

Dim q1 As New frmQuery() q1.ShowDialog() If (q1.txtQuery.Text = "") Then q1 = Nothing Exit Sub End If

recset.SetSqlQuery(q1.txtQuery.Text) 'specify the connect string to open without the DSN dialog 'recset.SetConnectString("ODBC;DSN=Northwind")

GridocxOdbc.SetRecordset(recset)

End Sub

Public Sub NewQuery_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles NewQuery.Click Dim recset As Object database = GridocxOdbc.CreateDatabaseObject() database.Open("", False, False, "", False)

recset = GridocxOdbc.CreateRecordsetObject() recset.setdatabase(database)

Dim q1 As New frmQuery() q1.ShowDialog() If (q1.txtQuery.Text = "") Then q1 = Nothing Exit Sub End If

recset.SetSqlQuery(q1.txtQuery.Text)

GridocxOdbc.SetRecordset(recset) GridocxOdbc.GridOpenRecordset() End Sub

Public Sub Requery_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles Requery.Click GridocxOdbc.GridRequery() End Sub

Public Sub ppview_Click(ByVal eventSender As System.Object,

78 Objective Grid for ActiveX User’s Guide

Page 89: Stingray 2006.2 Objective Grid ActiveX UserGuide

ByVal eventArgs As System.EventArgs) Handles ppview.Click GridocxOdbc.GridPrintPreview(Me.GridocxOdbc) End Sub

Public Sub ExitApp_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles ExitApp.Click EndEnd Sub

Private Sub GridocxOdbc_OnGridInitialUpdate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GridocxOdbc.OnGridInitialUpdate 'SetGridColHeaderText(GridocxOdbc, 1, "column01") 'SetGridColHeaderText(GridocxOdbc, 2, "column02") 'SetGridColHeaderText(GridocxOdbc, 3, "column03")End Sub

Public Sub SetGridColHeaderText(ByRef grid AsAxGRIDOCXODBCLib.AxGridocxOdbc, ByRef Col As Short, ByRef HeaderText As String) Dim range As Object Dim style As Object

range = grid.CreateRangeObject() style = grid.CreateStyleObject()

range.InitRange(Col, 0, Col, 0) style.SetValue(HeaderText)

grid.SetStyleRange(range, style, GRIDOCXODBCLib.constantdefs.gxOverride)

End Sub

NOTE—Notice the code in the PreInitialUpdate() event. This code is typically placed in the PreInitialUpdate() event for the ActiveX control. While this is not required, it is recommended, since it gives the control the opportunity to initialize itself when it first appears.

13. Press F5 to run the program.

Chapter 5 Database Tutorial 79

Page 90: Stingray 2006.2 Objective Grid ActiveX UserGuide

The ODBC control also supports changing the query.

14. Change the SQL statement if desired or leave the default to extract all fields and all records. (Customers is the name of the table from which we are retrieving data.) The code involved in changing the query is shown below.

Private Sub NewQuery_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) HandlesNewQuery.Click Dim recset As Object database = GridocxOdbc.CreateDatabaseObject() database.Open("", False, False, "", False)

recset = GridocxOdbc.CreateRecordsetObject() recset.setdatabase(database)

Dim q1 As New frmQuery() q1.ShowDialog() If (q1.txtQuery.Text = "") Then q1 = Nothing Exit Sub End If

recset.SetSqlQuery(q1.txtQuery.Text)

GridocxOdbc.SetRecordset(recset) GridocxOdbc.GridOpenRecordset()End Sub

15. Click OK.

80 Objective Grid for ActiveX User’s Guide

Page 91: Stingray 2006.2 Objective Grid ActiveX UserGuide

16. If you do not specify the connect string the ODBC select DSN dialog (Figure 24) will be displayed.

Figure 24 – Select Data Source

17. Click the Machine Data Source tab.

Chapter 5 Database Tutorial 81

Page 92: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 25 – Machine Data Sources

18. Select the data source and click OK.

19. If you run the application you should see the data source in grid form as shown Figure 26. The data source can be edited too, if this is allowed.

20. Test the ODBC Query|New SQL Query feature by modifying the SQL statement to select records from either the Employees table or the Products table.

82 Objective Grid for ActiveX User’s Guide

Page 93: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 26 – OG ActiveX control in a Windows form displaying an ODBC Source

NOTE—If you are displaying static data (snapshots) and wish to have the grid updated to reflect the latest updates, you can use the Requery() method.

21. Uncomment the following line to allow the use of a connect string so that you don’t need to select the database each time you run the application:

recset.SetConnectString("ODBC;DSN=Northwind")

5.4 Objective Grid DAO control

Using the DAO control is not very different from using the ODBC control.

5.5 Objective Grid ADO control

Objective Grid makes use of ADO and RDS (Remote Data Service) to enable edit-ing of data in a user friendly grid format across the Internet. This section deals

Chapter 5 Database Tutorial 83

Page 94: Stingray 2006.2 Objective Grid ActiveX UserGuide

with the steps involved in using Objective Grid's ADO support to access data across the Internet.

First let us identify the three basic participants involved when accessing data in this manner:

Database server — This is the server machine on which the database resides. The database itself can be anything (Access, SQL server, Oracle etc) that can be setup as an ODBC source.

IIS server machine — This machine is typically a machine where the IIS Server is running.

Client machine — This is any machine on the Internet that had IE4.01 (or later) installed. (Users of earlier IE versions will have to install the RDS run time.) The user does not have to have any other components installed.

5.5.1 Steps

Now let us look at the steps involved.

5.5.1.1 On the IISServer

1. Install RDS, if not already installed, on the IIS Server machine. Please check www.microsoft.com/data for more details and downloading.

Please follow the instructions in the documentation that ships with RDS and make sure that RDS is properly installed on your machine.

Register adodll.dll using regsvr32.exe. The files required for building this VB ActiveX dll are installed under VB6//Samples//adodll. The com-piled binary is available under vb6//samples//adodll/bin.

After the above have been successfully registered, locate the file safe.reg in your OGX installation (installed under \\samples\\VB6\\adodll). Double-click this file to enter the information that it has in the registry. This registry file marks the adodll.dll file as safe for scripting and also adds an entry in the registry such that the dll can be used to create components from a client machine.

NOTE—You need administrative rights to be able to enter this in the registry.

2. Create a virtual directory under your IIS root directory. You can name this anything you want. You have to set the proper security for this directory. For this choose properties. Set the security that is appropriate for your context.

84 Objective Grid for ActiveX User’s Guide

Page 95: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—Refer to the RDS documentation for more information on this. A chapter called "Getting a Recordset to the Client" in the RDS docu-mentation is particularly useful for understanding this.

3. Copy the asp file, ogrid.asp from the samples\\vb6\\adodll\bin direc-tory to the virtual directory that you created in step2.

4. Create an ODBC data conection. Modify the ogrid.asp file so that the cor-rect connect string and SQL string are specified. The file only has a placeholder by default.

5.5.1.2 On the Client Machine

Use regsvr32.exe to register the OGX Ado grid control. (The grid does not need to be registered on the server. It is only required if you want to do any local test-ing.) You can alternatively package the control in a cab file for download and installation on an as-needed basis.

5.5.1.3 Testing

Run IE from the client machine and point it to the server (http:\\my server) and to the ogrid.asp file in your virtual directory setup on that machine. The page should display the grid with data from your database.

Chapter 5 Database Tutorial 85

Page 96: Stingray 2006.2 Objective Grid ActiveX UserGuide

86 Objective Grid for ActiveX User’s Guide

Page 97: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 6 Objective Grid Designer

THIS CHAPTER INCLUDES: Introduction Starting the Objective Grid Designer Grid Designer Components Creating a Sample Layout File Initializing a Control Using .ogl File

6.1 Introduction

6.1.1 What is the Objective Grid Designer?

The Objective Grid Designer is a tool that lets you design the layout of a grid and save this layout to a file. This layout file can be loaded at run time in order to ini-tialize grids in your application.

For example, if you are designing a dialog with a grid where the user should enter data, you can specify the initial cell contents, parameter object settings, row heights and column widths with the grid designer. This layout can be loaded into your grid with one API call. There is no need to specify all the formatting of the grid with code.

You can also use a mixed approach, in which you load the layout and still apply certain formatting with code (for example, if you want to load a large choice list from another text file).

6.1.2 Stand-Alone Mode of Operation

When the Objective Grid Designer is used in stand-alone mode, the designer is started as a separate executable (C:\Program Files\Rogue Wave\Objective Grid for ActiveX\Bin\ogdesign.exe) and is run stand-alone. The output of the designer is saved to a binary .ogl file.

With this in mind, let us proceed to look at how we can use the designer.

Chapter 6 Objective Grid Designer 87

Page 98: Stingray 2006.2 Objective Grid ActiveX UserGuide

6.2 Starting the Objective Grid Designer

You can find the designer in the \\Bin directory of your Objective Grid for ActiveX installation.

NOTE—The Objective Grid 9.X (for MFC ) setup program also adds a Grid Designer icon to the program group.

1. Start the Grid Designer in stand-alone mode by launching \Rogue Wave\Objective Grid for ActiveX\Bin\ogdesign.exe.

2. Choose Layout.

3. Click OK.

4. The Objective Grid Designer window appears.

88 Objective Grid for ActiveX User’s Guide

Page 99: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 27 – Objective Grid Designer

5. To customize the window layout, double-click on any Title Bar border to undock that window. You can move and/or resize undocked windows.

Chapter 6 Objective Grid Designer 89

Page 100: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 28 – Double-click Borders to Undock

6.3 Grid Designer Components

There are three essential components (i.e. windows) in the Objective Grid Designer interface.

Grid Interface

General Settings

Cell Settings

6.3.1 Grid Interface

The main component (shown in Figure 29) is the grid interface. This is the as will be model. (It reflects the grid that will be created when you use the layout file in your application.)

90 Objective Grid for ActiveX User’s Guide

Page 101: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 29 – Objective Grid Designer - Grid Interface

6.3.2 General Settings

Figure 30 shows the property page for General Settings. General settings are set-tings that can be applied to the whole grid.

Chapter 6 Objective Grid Designer 91

Page 102: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 30 – Objective Grid Designer - General Settings

The General Settings property page has six different tabs, corresponding to the fol-lowing categories:

Data

Use the data property page (see Figure 30) to set the row count and column count. For example, you can set the row count to 30 rows and the column count to 10. You can also set the number of frozen rows and frozen columns with this property page. Notice that the grid view updates immediately to reflect the changed grid interface. Some of the other options that you can set on this page include header-specific details and whether or not the row and column header should be numbered.

User Actions

The user actions page controls many aspects of how the user will interact with the grid. This interface can be very useful for usability testing of your grid interface. You can configure the grid to suit the needs of users. You can specify whether the grid should support rearranging columns, allow resiz-ing rows and columns, and the minimum size of row and columns, among other settings. Try changing the settings and interacting with the grid. Notice that, at the bottom of the list, you can also specify whether the grid should add support for sorting. Usually you will want to turn on sorting.

92 Objective Grid for ActiveX User’s Guide

Page 103: Stingray 2006.2 Objective Grid ActiveX UserGuide

Selection

Often it may be difficult to decide on the various selection modes that your grid interface should support. You should take the time to select every option on this page to see how the grid interface interacts with each setting. This will give you a good feel for the selection interface that the grid sup-ports and how this can be best customized to suit your needs. There is also support for some specific Excel emulation features. You should try all of these to see if there is some setting that your application cannot do without! Another important aspect of this page is that it supports setting the grid in list box mode. You can choose between multiple and single selection list boxes.

Check out how the grid list box modes interact with the selection modes. There is no end to the amount of prototyping that you can do with the designer!

Chapter 6 Objective Grid Designer 93

Page 104: Stingray 2006.2 Objective Grid ActiveX UserGuide

Sheet

Once you are content with the settings for the selection page, move to the Sheet page, which also has several interesting features, including support for features such as merge cells and floating cells. Check out the Undo/Redo buffer as well. Look at optimizing this value. If you have memory constraints, you should look at the undo/redo stack that is correct for your applications. And what better way to test this than with the Objective Grid designer!

94 Objective Grid for ActiveX User’s Guide

Page 105: Stingray 2006.2 Objective Grid ActiveX UserGuide

Display

The display property page can be used to change the color of the grid lines, the tracking lines, dragging lines, and other aspects of the grid. You can also specify whether or not these lines should be displayed.

Chapter 6 Objective Grid Designer 95

Page 106: Stingray 2006.2 Objective Grid ActiveX UserGuide

Printing

The printing section specifies all printer-related settings. You can change the settings, choose print preview (from the main grid frame), and get instant feedback on how the layout would appear when printed.

96 Objective Grid for ActiveX User’s Guide

Page 107: Stingray 2006.2 Objective Grid ActiveX UserGuide

6.3.3 Cell Settings

The property page for cell settings is shown in Figure 31. This property page allows you to work on the current cell or a group of cells and allows you to cus-tomize any aspect of these.

Chapter 6 Objective Grid Designer 97

Page 108: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 31 – Objective Grid Designer - Cell Settings

Most of the attributes on this page are self-explanatory. However, a beginning user might find some of the attributes (such as the role of user attributes and how they fit into the grid framework) to be a bit more obscure. Notice that this page includes support for setting these attributes.

6.4 Creating a Sample Layout File

In this section we will show you some of the steps involved in creating a sample layout file and in the following section we’ll show you how this can be integrated into your application.

1. Start the Objective Grid Designer, as described in Section 6.2.

98 Objective Grid for ActiveX User’s Guide

Page 109: Stingray 2006.2 Objective Grid ActiveX UserGuide

2. You will see the designer and the property pages pop up.

3. Select a couple of cells (A1:A2) and use the cell type attribute on this page to set the type of control (choose the cell type to be a spin edit control).

NOTE—You don’t need to select the check box to the left of the setting. Once you choose the correct cell type from the drop-down list, the check box will be selected automatically.

4. Scroll down the Cell Settings window (half way down the list) and you will see two user attributes, SpinBound Max Value and SpinBound Min Value. Set these to 100 and 10, respectively.

You will observe that the spin edit control now validates the input in the cell between these two boundaries. Because it ’knows’ about these user attributes, it always checks to see if they have any meaningful values and acts accordingly.

Similarly, several other controls have user attributes that they know about. These user attributes are presented on the page and can be used to control several aspects of the controls that know them. Remember user attributes pertain only to one control. SpinBound Max Value will validate only a spin control and not say, an edit control.

You are now ready to create a fully functional grid program without writ-ing much code.

5. Save this ogl file (myfirstlayout.ogl), noting the path to it.

6. Exit the Designer.

6.5 Initializing a Control Using .ogl File

If you are running the Designer in stand-alone mode, you can initialize the control from the saved .ogl file, as shown below. To test this out, simply:

1. Create a new VB project with a simple OGX grid control, as described in Section 2.3, “Using Objective Grid for ActiveX Controls.”

Chapter 6 Objective Grid Designer 99

Page 110: Stingray 2006.2 Objective Grid ActiveX UserGuide

2. Add the following code in the Form1_Load procedure:

Private Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim layoutfile As String layoutfile = "c:\vbprojectfolder\MyFirstLayout.ogl" Gridocx1.InitFromLayout(layoutfile)End Sub

3. Run the program.

4. Test the spin edit control buttons. Just for fun, try to exceed the 10-100 range.

Figure 32 – Grid Layout From a Layout File

Important notes on using the designer:

To set properties use either the designer or the ActiveX property interface. Using both can be confusing and counter-productive.

Objective Grid Designer is a tool for programmers. It is not advanced enough to be given out to end users. The end-user will probably not understand all the settings you can specify with the property sheets.

NOTE—This kind of direct linking with the designer is currently sup-ported only for the base grid control and not for the tab and databound grid controls.

100 Objective Grid for ActiveX User’s Guide

Page 111: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 7 Samples

THIS CHAPTER INCLUDES: Introduction Internet (CAB) Sample Visual Basic Samples Troubleshooting

7.1 Introduction

NOTE—SeeSection 4.6.1, “Sample Distribution and Reorganization,” in the Getting Started User's Guide.

comes with several samples that you can use to learn about the functionality of the product. Figure 33 shows the location of several Visual Basic 6 and Visual Basic 7 samples. You can find these samples under the \\Rogue Wave\Objective Grid for ActiveX\samples folder.

Figure 33 – Samples

NOTE—Before running any of the samples, register the OGX controls with regsvr32.exe.

Chapter 7 Samples 101

Page 112: Stingray 2006.2 Objective Grid ActiveX UserGuide

7.2 Internet (CAB) Sample

To load the grid.htm file and display the Objective Grid control you will need to locate this line in the grid.htm file and edit it:

CODEBASE="ogocx.cab"

Change this to point to the location of ogocx.cab on your machine (\Rogue Wave\Objective Grid for ActiveX\samples\Internet\cab sample).

... <OBJECT ID="Gridocx1" WIDTH=825 HEIGHT=591 CLASSID="CLSID:6937B443-6494-11CF-97D0-524153480000" CODEBASE="C:\Program Files\Rogue Wave\Objective Grid for ActiveX\samples\Internet\cab sample"> <PARAM NAME="_Version" VALUE="131072"> <PARAM NAME="_ExtentX" VALUE="5948"> <PARAM NAME="_ExtentY" VALUE="7694"> <PARAM NAME="_StockProps" VALUE="0"> <PARAM NAME="SmartResize" VALUE="1"> <PARAM NAME="NumCols" VALUE="10"> <PARAM NAME="NumRows" VALUE="10"> </OBJECT></BODY></HTML>

NOTE—If you are running a Web server you can make this file available on a virtual directory and point to that path.

After making the above change, you should be able to see the Objective Grid Con-trol displayed inside of your browser when you open grid.htm.

NOTE—\\Rogue Wave\Objective Grid for ActiveX\sample\Internet\cab sampleVC.NET contains a cab file which has the OGX controls and the supporting dlls built with the VC.NET compiler.

The \samples\Internet\cab sampleVC7 directory contains a cab file which has prebuilt VC.NET OGX components and all supporting dlls.

7.3 Visual Basic Samples

AdoQuery

102 Objective Grid for ActiveX User’s Guide

Page 113: Stingray 2006.2 Objective Grid ActiveX UserGuide

This sample illustrates ADO-based data access (local and remote). Please refer to Section 5.5, “Objective Grid ADO control,” for more information on this sample.

Formula

This is a formula-enabled sample that includes some text on formula sup-port in the grid. This text is stored in a layout file (main.ogf). A list of mathematical functions is stored in math.ogf. You can view both of these layout files in the Objective Grid Designer.

The following code shows how formula support can be enabled in a grid.

Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load Gridocx1.EnableFormulaSupport() Gridocx1.InitFromLayout(“..\main.ogf”)End Sub

The OGF file is a formula spreadsheet configuration that you can create using the Objective Grid Designer in stand-alone modality. The InitFromLayout method allows retrieving the OGL/OGF file, specifying the path where the file is installed. If you use the grid with the Formula Engine enabled, you need to create an OGF file using the Grid Designer.

You do not need to create an OGF file if you do not need to initialize/re-ini-tialize your formula spreadsheet at run-time. The OGF file is the equivalent of the OGL file and it gets created when you choose the Formula configuration from the Grid Designer used in stand-alone mode. The OGF file contains the initialization style and values for the grid and you can load it at run-time using the InitFromLayout method of the grid object.

Gridapp

This sample illustrates most of the generic ways in which the control can be used. It also shows how the events generated (for example GetStyleRowCol) can be used as a virtual handler WRT grid. This sample also illustrates the use of different parameter objects for the different views presented. Refer to Chapter 3, “Controls,”for more information about this sample.

Chapter 7 Samples 103

Page 114: Stingray 2006.2 Objective Grid ActiveX UserGuide

ODBC

This sample illustrates ODBC-based data access.

104 Objective Grid for ActiveX User’s Guide

Page 115: Stingray 2006.2 Objective Grid ActiveX UserGuide

Preview

This sample illustrates printing and print pre-view.

TabBase

This sample illustrates basic usage of the tab control. The important proper-ties are ActiveTab, tab captions and classnames. The class names will be

Chapter 7 Samples 105

Page 116: Stingray 2006.2 Objective Grid ActiveX UserGuide

parsed to set the number of tabs and also to create the correct class of tab. Tabs can also be inserted and removed at run time.

7.4 Troubleshooting

7.4.1 CAB Sample

If you are unable to see the control because of security:

106 Objective Grid for ActiveX User’s Guide

Page 117: Stingray 2006.2 Objective Grid ActiveX UserGuide

Change the security to Medium or Low (please read associated precau-tions). This control is not signed.

If the control downloads but does not display itself:

It is possible that one or more supporting dlls are available on the target machine, but are not in the current system path. Check for the presence of all the dlls listed in the cce.inf file and see if they are in an accessible path.

7.4.1.1 How can I create my one cab file?

1. You can obtain the cab signing files from Microsoft. (They are also on the Visual Studio CD.)

2. Once you have these files on your machine you can use cce.inf as a tem-plate to create your own .inf file.

3. Add any files that may be specific to your application.

4. After you have edited your inf file, open cabnew.bat. This simply runs cabarc with the following command line:

cabarc -s 6144 n ogocx.cab mfc70.dll msvcr70.dll olepro32.dll og90nodbas.dll ogc90r.dll ogocxgrd.ocx cce.inf

5. Change this batch file to include files that are specific to your application. (cce.lpk was generated by LPK_TOOL.exe, which ships with VB.)

6. Change the n option to change the name of the resultant cab file.

7. Save the changed batch file and run it to generate your new cab file.

7.4.1.2 More Information

For more information, please refer to Design, Test, and Deployment of ActiveX Con-trols and Documents Over the Internet, presented by Ken Spencer and available on MSDN.

7.4.2 General

The samples rely on a registry entry that specifies where the files were installed, to get at the sample layout files, bitmaps, etc. If you moved files around after the installation or if the registry was not properly updated during installation, it is possible that one or more of the files cannot be located when running the samples. The key that should have the path name is:

Chapter 7 Samples 107

Page 118: Stingray 2006.2 Objective Grid ActiveX UserGuide

HKEY_LOCAL_MACHINE\SOFTWARE\Stingray\Grid for ActiveX

The keyname is InstallDir and the value is the path of your OGX root install. For example, if you installed the OGX to C:\Program Files\Rogue Wave\Objective Grid for ActiveX, then this key will look like this:

InstallDir "C:\Program Files\Rogue Wave\Objective Grid for ActiveX"

Add this key if it is not present.

108 Objective Grid for ActiveX User’s Guide

Page 119: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 8 Redistribution

THIS CHAPTER INCLUDES: Introduction Naming Conventions Distributing Objective Grid for ActiveX Applications

8.1 Introduction

Please read the license agreement that was shipped with your Objective Grid for ActiveX package. You are bound by the licensing restrictions contained in that doc-ument. Do not use this product unless you can accept all the terms of the license agreement.

You can use all the files accompanying this product for development of an applica-tion. You can distribute the Objective Grid for ActiveX Dynamic Link Libraries (DLLs) according to the terms of the license agreement. Your applications can also statically link to the grid, in which case you do not need to redistribute any Objec-tive Grid for ActiveX files.

There is no restriction where the Grid CCE DLLs need to be installed.The control looks for the DLLs in the same directory where the OCX is located before and then, if it cannot find them, in the system path. The CCE.LIC file must not be redistributed because it would allow a third party user to use the Grid CCE con-trol at design time.

Chapter 8 Redistribution 109

Page 120: Stingray 2006.2 Objective Grid ActiveX UserGuide

8.2 Naming Conventions

The library naming conventions are illustrated below for the default library names.

Figure 34 – Library Naming Conventions

8.3 Distributing Objective Grid for ActiveX Applications

8.3.1 File Redistribution

The following files can be shipped with your application when needed:

Table 6 – Redistributable Files

File Remarks Platform MFC Version

OGas*.dll Grid Classes

Win32 Depends on build. PostFix is added based on supported version.

OGaus*.dll Grid Classes

Win32 Unicode

As above

110 Objective Grid for ActiveX User’s Guide

Page 121: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—You may not redistribute Objective Grid for ActiveX header files, source files, or sample files. You also may not expose the Objective Grid for ActiveX programming interface in your program (e.g. a DLL or OCX/ActiveX that lets a user create a grid).

The og90*.dll names that are given above are taken from the configurations that we ship with OGX. We ship the prebuilt release dlls for these configurations, as well as the prebuilt Unicode Release OGX components that take advantage of XP Visual Styles. The build wizard files for these are also available in case you wish to rebuild these libraries.

8.3.2 Registering a Component

To distribute applications you create with the OGX control, you must install and register it on the user's computer. The Package and Deployment Wizard, an Add-In provided with Visual Basic, provides tools to help you do that.

A deployment file (ogocxgrd.dep) is provided in the Redistribution folder of your installation for use with the VB6 Package and Deployment Wizard.

Table 7 – DLLs to Distribute

MFC DLLs System DLLs

mfc70.dll olepro32.dll

msvcr70.dll

Table 8 – OGX Dlls to Distribute

No data base support

DAO support ADO support ODBC support

Your ocx Your ocx Your ocx Your ocx

ogc90r.dll ogc90.dll ogc90r.dll ogc90r.dll

og90nodbas.dll ogd90r.dll oga90r.dll ogo90r.dll

og90daoas.dll og90adas.dll og90dbas.dll

Chapter 8 Redistribution 111

Page 122: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—Please refer to your Visual Basic manual for details on using the Package and Deployment Wizard.

NOTE—Make sure that the version of OGC90r.dll that you ship links to the same version of the Objecive Grid DLL that your control links to.

If you are using the pre-built version, follow the same pattern as with the OG ActiveX version and install these dlls into the same folder as the controls that use them.

The Objective Grid ActiveX control can also be used with Microsoft Internet Explorer. You can create a cab file for automatic download and installation.

8.3.3 Licensing

All of the pre-built controls are licensed and require that the cce.lic file be installed into the same directory as the controls— on any system that is to be used in design mode.

NOTE—Please do not distribute the cce.lic file to end users.

Table 9 – Version numbers for ogc90r.dll

Support Version

ADO support 9.0.0.0

DAO support 9.0.0.0

ODBC support 9.0.0.0

No DB support 9.0.0.0

112 Objective Grid for ActiveX User’s Guide

Page 123: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 9 Objects

THIS CHAPTER INCLUDES: Architecture Introduction Parameter object Style Object Range Object Range List Brush Object Data Object Font Object Stylesmap Print info Object Properties Object State Object

9.1 Architecture Introduction

Objective Grid for ActiveX has an object-oriented architecture. When working with Objective Grid for ActiveX for the first time, you might find useful this brief overview of some of these objects and their place in the Objective Grid for ActiveX world.

Three essential basic automation objects form the core of the Objective Grid for ActiveX architecture:

The Style object (OGStyle)

The Range object (OGRange)

The Parameter object (OGGridParam, OGAdoParam, OGDaoParam, OGDbParam)

NOTE—OGGridParam is the parameter object for either the base con-trol or the tab control.

All of these objects (as well as several others) are discussed in detail in this chapter. Figure 35 lists all of the OGX Automation objects, while Table 10 lists the OGX objects, their class names, and the methods used to create them.

Chapter 9 Objects 113

Page 124: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 35 – OGX Automation Objects

114 Objective Grid for ActiveX User’s Guide

Page 125: Stingray 2006.2 Objective Grid ActiveX UserGuide

Table 10 – Objects

Object Equivalent OG/MFC Class

Note Method to Create

OGGridParam CGXGrid-Param

for base grid or tab control

CreateParamObject

OGDbParam CGXDb-Param

ODBC databound control specific

CreateDbParamObject

OGAdoParam CGXA-doParam

ADO databound control specific

CreateAdoParamOb-ject

OGDaoParam CGXDao-Param

DAO databound control specific

CreateDaoParamOb-ject

OGStyle CGXStyle CreateStyleObject

OGStylesMap CGXStyles-Map

CreateStylesMapObject

OGRange CGXRange CreateRangeObject

OGRangeList CGXRange-List

CreateRangeListObject

OGBoolState CreateBoolStateObject

OGBrush CGXBrush CreateBrushObject

OGBStrState state object CreateBStrStateObject

OGDoubleState state object CreateDoubleStateOb-ject

OGLongState state object CreateLongStateObject

Chapter 9 Objects 115

Page 126: Stingray 2006.2 Objective Grid ActiveX UserGuide

OGDaoDatabase DAO databound control specific

CreateDaoData-baseObject

OGDatabase ODBC databound control specific

CreateDatabaseObject

OGRecordset ODBC databound control specific

CreateRecordsetOb-ject

OGDaoRecord-set

DAO databound control specific

CreateDaoRecordse-tObject

OGData CGXData CreateDataObject

OGFont CGXFont CreateFontObject

OGHint CreateHintObject

OGPen CGXPen CreatePenObject

OGPoint CreatePointObject

OGPrintInfoOGPINFO

CreatePrintInfoObject

OGProperties CGXProper-ties

CreatePropertiesOb-ject

OGRect CreateRectObject

OGSize CreateSizeObject

OGSortInfo CreateSortInfoObject

Table 10 – Objects (Continued)

Object Equivalent OG/MFC Class

Note Method to Create

116 Objective Grid for ActiveX User’s Guide

Page 127: Stingray 2006.2 Objective Grid ActiveX UserGuide

9.2 Parameter object

The parameter object (OGGridParam, OGAdoParam, OGDaoParam, OGDb-Param) is the data object for the whole grid. Internally this object stores all the style objects that the grid control has. We do not normally have to interact with this object directly. However, there are certain instances where interacting with this object may be useful. For example, if you wish to quickly initialize the grid control with different data, it is possible to create and initialize different parameter objects. These objects can then be used to initialize the grid. Please refer to the gridapp sample for an example of this approach.

The parameter object is similar to the document in the MFC document/view para-digm. The parameter object contains or points to all necessary data for persisting the state of the grid object. Parameter objects can be stored in documents and seri-alized or can be used as members of other classes. Parameter objects can also be shared between grid objects.

The OGGridParam object maintains attributes and objects being shared by several grid views of the same data. It has references to the styles map with the grid-wide base styles, the properties object, the data object with the cell contents, the undo/redo list, selected ranges, and covered cells. By default, the parameter object - an instance of OGGridParam - is created in the grid's OnGridInitialUpdate method. Each grid must have a valid parameter object, and it owns an associated flag which indicates whether the parameter object should be deleted when the grid is closed. The parameter object can be maintained either by the application or by the grid itself. That means you can declare an object in the application (typically a global object) and simply pass the object to the grid (using SetParam).

9.3 Style Object

Cells in a grid are defined by internally stored style objects. The style object (OGStyle) is a data object that completely describes a cell in Objective Grid. The style object forms the core for formatting cells in the grid and can be seen as an object that completely defines a cell. This means that the style object has all the information (such as the font, font size, interior color, value displayed, and control type) necessary for the grid object to draw the cell and manage its interaction with users.

Changing the style object for a cell is equivalent to changing the cell. Style objects for each cell are stored internally by the grid and can be modified and stored with calls to SetStyleRange().

Style.SetInterior() returns a reference to the style object, making it possible for us to call Style.SetInterior().SetValue() all in one stroke.

Chapter 9 Objects 117

Page 128: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—If you want to remove only the changed background color for a cell style put in place with a SetInterior() call, you can simply call SetIncludeInterior(FALSE).

9.3.1 Style object creation

Style objects are created with a call to CreateStyleObject.

Dim style As Objectstyle = gridocx1.CreateStyleObject()

9.3.2 Setting style properties

Objective Grid for ActiveX controls have a different model than most ActiveX con-trols. Most ActiveX controls have a set of methods and properties. Using these methods and properties the control user sets and gets data and interacts with the control. The controls also have an event set that can be used as hooks to listen in to any incidents of interest to the control. This approach works quite well but becomes cumbersome for large controls. Objective Grid ActiveX controls are Object Oriented and support several helper objects that ease interaction with grid controls.

Grid properties are typically set by creating and initializing objects. For example, to set the font for a column with Objective Grid for ActiveX we would create a font object and then initialize its various properties. Once these are initialized, we apply this to the grid. Since these objects maintain state, we can easily change one setting and apply the same font object (with one setting changed) to another row. If we had to do that with a traditional control we would end up having to make all the calls that initialize the font yet again. Here is some pseudo code that drives this home:

Create the fontSet 10 font properties (SetFaceName, SetSize etc.,)Apply to the first columnChange one property (say FaceName)Apply to the second column

Using a traditional control:

Initialize 10 font properties on the first column (SetFaceNameRowCol etc.,)Initialize 10 font properties on the second column (SetFaceNameRowcol etc.,)

118 Objective Grid for ActiveX User’s Guide

Page 129: Stingray 2006.2 Objective Grid ActiveX UserGuide

You can see that the calls add up very quickly, making the use of a traditional con-trol far more complicated than the use of the OGX control. Besides, since the objects are grouped logically (for example, the font object deals with font proper-ties), mastering the API of the Grid ActiveX controls is far easier than mastering a typical monolithic control that has a few hundred methods and properties.

Style objects have a method set that can be used to set each and every aspect of the cell. For example, call the SetValue method to set the value of a cell.

Style.SetValue(“This is a test”)

The style object is also capable of initializing itself from other objects, each with a specific function. For example, the font object defines all font-specific attributes.

Some special methods take other objects, for example a font object:

Style.SetFont(font)

where font is a font object that was previously created and initialized.

Style and Range objects can be used to change the appearance of cells and the grid control.

SetStyleRange(range,style,GRIDOCXLib.constantdefs.gxCopy)

where range and style are previously created objects and gxCopy is a constant that will be explained in Section 9.3.5.

9.3.3 Style Inheritance

Objective Grid cells are described completely by style objects. These style objects are normally stored on a cell by cell basis. But Objective Grid also has styles that belong to the whole grid or to rows and columns.

Objective Grid for ActiveX divides the styles into several categories:

A system-wide standard style.

A set of user-defined base styles (Row/Col and Table-wide styles).

Cell-specific styles.

When the grid draws a cell, it gets the style data in a certain order.

1. The cell-specific style is obtained. The cell-specific style settings override all other style settings.

2. The row and column styles are used to fill any attributes left empty by the cell-specific style.

Chapter 9 Objects 119

Page 130: Stingray 2006.2 Objective Grid ActiveX UserGuide

3. The table-wide style is used to fill any attributes left empty by the row or column styles.

4. The standard grid style is used to continue filling holes.

5. If any base styles are available, they are applied. It is important to note that base style settings will always override the grid-wide styles.

The more specific a style is, the more overriding power it has. Suppose the grid system interior color is white and a base style specifies an interior color of red. The base style color will override the standard style. In short, this architecture allows the grid to have a default initialization hierarchy that is very flexible. This is the basis of the grid virtual mode of operation. The process of gathering these styles is loaded with virtuals that can be overridden to handle the style initialization in a dynamic manner. This is what drives the virtual mode.

The style inheritance hierarchy is shown in Figure 36.

Figure 36 – OG ActiveX style inheritance hierarchy

The Standard Style is the object that defines the default appearance of the grid. For example, if the Standard Style interior color is set to Red then all cells that do not have either base, row, column, or specific styles set to have an interior color value will use this value. This architecture provides us with several advantages:

We can have a default look and feel without wasting a whole lot of memory to store duplicate information.

We can effect a grid-wide change with a single line of code.

120 Objective Grid for ActiveX User’s Guide

Page 131: Stingray 2006.2 Objective Grid ActiveX UserGuide

We can hook in and change the manner in which the style is composed. For example let us say that the grid is drawing cell 2,2. It will first use the Standard Style to compose the basic attributes, then apply any base styles.

9.3.4 User attributes

User attributes are pieces of data that can be stored by the grid on a cell wise basis. These are identified by a double value and can be retrieved on demand.

9.3.5 Style Constants/Modes

One style object can be applied on another style object in several ways. A brief explanation of each of these modes is given below.

After the base styles are applied with gxOverride, row and column styles are applied. Lastly the specific style is applied. The specific style is the style that gets stored when we make explicit calls to SetStyleRange(), SetValueRange(), etc.

This makes it possible to store all the formatting in column styles (since database columns typically contain the same type of defined data). After this we can hook in at display time and fill in with the required values. This is what data-bound grids do. They initialize the column styles from the database schema and after that read

Table 11 – Style Modes

Constant Description

gxApplyNew Applying only new attributes

Only those attributes that are included in the source style and not yet included in the destination style are copied from the source style to the destination style.

gxCopy Copying the style

All attributes are copied from the source style to the desti-nation style. Attributes that are not included in the source style will be removed from the destination style.

gxOverride Overriding attributes

Attributes that are included in the source style are copied from the source style to the destination style, regardless of whether or not they are included in the destination style.

gxExclude Resetting attributes

Attributes that are included in the source style will be removed from the destination style.

Chapter 9 Objects 121

Page 132: Stingray 2006.2 Objective Grid ActiveX UserGuide

the record source whenever the value is to be displayed. We thus avoid having to store a specific value in each cell. Refer to the online reference on GetStyleRowCol() and OnLoadCellStyle() for more information on this aspect of the style architecture. Supplying values in this mode is called Virtual Mode.

Regular unbound grids also have row, column, and base styles. However, they have no built-in mechanism to read an external data source. We can choose to change the values of cells in an unbound grid with calls to SetStyleRange() or choose to operate the grid in virtual mode (as is the default with bound grids).

9.3.6 Virtual mode

All of the data-bound controls operate in virtual mode. This means that they access data as needed on a cell by cell basis. This approach has tremendous advantages when it comes to memory consumption as well as the loading and displaying of huge result sets. It also requires us to remember that no data is stored in the grid on a cell by cell basis. The format for a field is stored on a column by column basis.

Basically there are two ways to populate the grid:

Store the value in the grid itself and allow it to display the value when required

In this more commonly used method, the grid stores a copy of the data and uses it to display the value when required. This is what happens when we use SetStyleRange or SetValueRange. The data that is given to the grid is internally stored by the grid (in the parameter and data objects) and is used to display the values when required. Formula grids require this method of storage.

Supply data on demand

This mode of operation is called Virtual Mode. The grid does not store data. (There are no calls to SetValueRange and SetStyleRange.) Instead we handle (override in C++ terms) the GetStyleRowCol event and supply data there. This data can be accessed from within an external data source or can be generated on demand. A brief example of using the grid in virtual mode is shown below.

Changes made when the grid is in virtual mode are typically written back to the data source by handling the StoreStyleRowCol event. This event will be called when a changed cell's value needs to be stored.

Private Sub Gridocx1_GetStyleRowCol(ByVal eventSender As System.Object, ByVal eventArgs As AxGRIDOCXLib._DGridocxEvents_GetStyleRowColEvent) Handles Gridocx1.GetStyleRowCol

122 Objective Grid for ActiveX User’s Guide

Page 133: Stingray 2006.2 Objective Grid ActiveX UserGuide

If eventArgs.nType <> 0 Then Exit Sub End If If eventArgs.nRow = 0 Or eventArgs.nCol = 0 Then Exit Sub End If ' set the value from the generated values stored in the ' global data array (g_data) eventArgs.style.Setvalue(g_data(eventArgs.nRow, eventArgs.nCol)) ' do the simple check to see under which range these values ' fall and set the base style accordingly If g_data(eventArgs.nRow, eventArgs.nCol) < 75 Then eventArgs.style.SetBaseStyle(g_nStyleLow) ElseIf g_data(eventArgs.nRow, eventArgs.nCol) > 75 And g_data(eventArgs.nRow, eventArgs.nCol) < 150 Then eventArgs.style.SetBaseStyle(g_nStyleNormal) Else eventArgs.style.SetBaseStyle(g_nStyleHigh) End If ' Remember it is very easy to change each of these base ' styles too! ' Take a look at the styles sample for details on using ' ChangeBaseStyle

' tell the grid we have modified the style

eventArgs.bModified.Value = GRIDOCXLib.ogBoolean.ogTrue

End Sub

9.3.7 Style Implementation

Styles are the key to the display of the grid and also define most of its behavior. The style object contains all the information necessary for formatting a cell. A style consists of several attributes, such as text color, borders, control type, and font.

A very important feature of the style object is support for combining style objects. For example, you can copy only those attributes from one style to a second style that are not initialized in the second style. Objective Grid for ActiveX uses this fea-ture to enable a kind of inheritance. By specifying a base style, you can tell

Chapter 9 Objects 123

Page 134: Stingray 2006.2 Objective Grid ActiveX UserGuide

Objective Grid for ActiveX that it should inherit attributes from a base style at run time.

Attributes in the CGXStyle class are combined with an include bit. This include bit is TRUE when an attribute is initialized. If it is FALSE, the attribute is not initialized. When drawing the grid, Objective Grid for ActiveX fills up all uninitialized attributes of the cell style object with values inherited from the base styles.

CGXStyle also supports user-defined style attributes. You can also extend the CGXStyle class with additional attributes. Each style object maintains a map of user attributes and provides a method to change their values.

Style objects are created for those cells that should be drawn and initialized at run time in the CGXGridCore member function ComposeStyleRowCol(). ComposeStyleRowCol() takes a row, a column, and a pointer to a style object as arguments. ComposeStyleRowCol() first calls the GetStyleRowCol() function to get any cell specific style attributes. ComposeStyleRowCol() adds to the style object any inherited attributes from the row, the column, and the entire grid. Finally, the styles map is checked for any base styles.

9.3.8 Virtual Functions

Virtual functions allow users of an Object to hook in and change certain behavior of these objects. The Object implementor decides which of these functions are changeable or hookable in this manner. For example, let us say that we have an object that draws an icon on the screen. Let us assume that it holds the handle to the icon that it is supposed to render and renders it when required.

Now let us say that we want to be able to add a small logo at the bottom while retaining the rest of the cool functionality that this object provides. If the object implementor had made the drawing function ’virtual’ we could then hook in and simply supply our own implementation that would call the default version to do the basic drawing and then do our custom drawing. With C++ this is supported as part of the language and adding this feature to a base class becomes very easy. The implementor will only have to specify the ’virtual’ keyword. With ActiveX controls this is normally not available. With OGX, however, very similar functionality is available. We make use of the ActiveX event mechanism (connection points) to implement this. For example in the scenario above we would have a ’Draw’ event that would be called by the object each time it is drawn. If there is no code in the Draw handler (in the container) drawing would take place as desired (by the base object code). If we desire to change this drawing entirely or add to it, we can do so. To avoid calling the base class, we can set a special boolean object parameter to ogTrue (to call) or ogFalse (to not call) the base class code.

With Objective Grid MFC there are many virtual functions that let users hook in and customize all parts of the grid. OGX provides much of that functionality in the ActiveX space using the event mechanism.

124 Objective Grid for ActiveX User’s Guide

Page 135: Stingray 2006.2 Objective Grid ActiveX UserGuide

9.4 Range Object

The range object (OGRange) defines a rectangular range of cells in the grid. It can be set to represent a single cell, an entire column, an entire row, or the entire table. Explicit coordinates can also be initialized with the top, bottom, left, and right members of the range object.

Use one of the following methods to specify the range of cells.

Use SetRows() to specify a range of rows.

Use SetCols() to specify a range of columns.

Use SetTable() to specify the full table.

Use SetCells() to specify individual cells.

Use InitRange() to set the range to a specific cell.

One common point of confusion is the difference between the SetCells() call and the SetRows(), SetCols(), and SetTable() calls. SetCells() defines a rectan-gular region with well defined top-left and bottom-right cells. This is very similar to defining a rectangular region on the screen using CRect.

SetRows(), SetCols(), and SetTable() define regions without a definite top-left or bottom-right cell. Instead they define the range as being entire rows, entire col-umns, or the entire table, independent of the actual grid dimensions. This means that as the dimensions of the grid grow or shrink, the realized dimensions of the range will grow or shrink. For example, let's say there is a grid with 10 rows and 10 columns, and a range has been defined using SetCols(2,4). The realized coordi-nates of this range are top = 0, bottom = 10, left = 2, and right = 4.

Another common misconception is that you can combine calls to SetRows() and SetCols() to define a cell or range of cells. This is not true. Calling SetRows() defines the range as the specified rows. Following up with a call to SetCols() redefines the range as the specified columns. It does not take the union of the two ranges. To define a cell or range of cells, you must explicitly use SetCells().

Chapter 9 Objects 125

Page 136: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 37 – OG ActiveX control in a Windows form with a selected range of cells

Shown above is a range of cells with boundaries 1,1 to 2,2.

9.4.1 Creating ranges

Range objects are created with a call to CreateRangeObject() on the control. If the name of the control is gridocx1, the necessary code would look like this:

Dim range As Objectrange = gridocx1.CreateRangeObject()

126 Objective Grid for ActiveX User’s Guide

Page 137: Stingray 2006.2 Objective Grid ActiveX UserGuide

9.4.2 Initializing ranges

Range objects can be initialized in several ways. Some of the most common ways are listed below:

With a call to InitRange:

Range.InitRange(1,1,2,2)

By directly setting the top, left, bottom, and right properties:

Range.top = 1Range.left = 1Range.bottom = 2Range.right = 2

By calling SetCols:

Range.SetCols(1)

SetCols will assign the complete column area to this range object.

By calling SetRows:

Range.SetRows(1)

SetRows will assign the complete row area to this range object.

9.4.3 Retrieving a selected range

There are several ways to retrieve a range

Single cell

Range

Multiple ranges

Covered ranges

Merged ranges

Private Sub Gridocx1_OnGridInitialUpdate(ByVal sender As Object, ByVal e As System.EventArgs) Handles Gridocx1.OnGridInitialUpdate Gridocx1.NumCols = 2 Gridocx1.NumRows = 5End Sub

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

Chapter 9 Objects 127

Page 138: Stingray 2006.2 Objective Grid ActiveX UserGuide

Dim RangeListObj As Object RangeListObj = Gridocx1.CreateRangeListObject

Gridocx1.CopyRangeList(RangeListObj, True)

MsgBox("GetCount = " & RangeListObj.GetCount) If (RangeListObj.GetCount >= 1) Then Dim Range As Object For Each Range In RangeListObj MsgBox("Range = " & Range.Top & "-" & Range.Left & "-" & Range.Bottom & "- " & Range.Right) Next End If

End Sub

Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click Dim nRow As Object Dim nCol As Object

nRow = Gridocx1.CreateDoubleStateObject nCol = Gridocx1.CreateDoubleStateObject

Gridocx1.GetCurrentCell(nRow, nCol) MsgBox(nRow.Value & " " & nCol.Value)

End Sub

128 Objective Grid for ActiveX User’s Guide

Page 139: Stingray 2006.2 Objective Grid ActiveX UserGuide

9.5 Range List

COGRangeList maintains a list of range objects. For example, ranges of cells selected by the user are stored in a COGRangeList.

You can iterate through the range list as shown below:

Dim rangelist As Objectrangelist = Gridocx1.CreateRangeListObject()Gridocx1.CopyRangeList(rangelist, True)If (rangelist.GetCount >= 1) Then Dim range As Object For Each range In rangelist ' Iterate through each element. If (range.IsCells = True) Then Gridocx1.SetCoveredCellsRowCol(range.Top, range.Left, range.bottom, range.Right) End If

NextEnd If

9.6 Brush Object

The OGBrush class is a wrapper for the Windows LOGBRUSH structure. OGBrush also adds support for 33 predefined patterns you can use in your grid. The follow-ing attributes are provided by the OGBrush class:

Style - Specifies the brush type.

Hatch - Specifies the hatch type.

Pattern - Specifies the pattern type. Objective Grid offers 33 predefined patterns.

Pattern Color - This is the foreground color of the pattern. If the brush is solid, the cell will be filled with this color.

Background Color - This is the background of the pattern. If the pattern is empty, the cell will be filled with this color. Normally, a OGBrush object is used to specify the interior brush of a cell.

Chapter 9 Objects 129

Page 140: Stingray 2006.2 Objective Grid ActiveX UserGuide

9.7 Data Object

The COGData class maintains the cell contents of the grid and the row and col-umn base styles. The grid component creates an instance of the data object in OnGridInitialUpdate and attaches it to the parameter object. COGData provides a public interface for setting the number of rows and columns, storing and reading cells, and removing, inserting and moving rows and columns. The names for these methods are the same as in the control.

All of the data objects are called from the control when you change the grid by call-ing MoveRows or InsertRows, for example. If you want to initialize data outside the grid you should call the OGData methods directly.

9.8 Font Object

The COGFont class encapsulates a LOGFont structure. Font objects can be com-posed. Each attribute of LOGFont is associated with an include bit. When an attribute is initialized, its include bit is TRUE. If the include bit is FALSE, an attribute is invalid. When drawing the grid, Objective Grid fills up all uninitialized attributes of a cell's style object with the base style's attributes. If the GetInclude... methods return FALSE, Objective Grid will try to initialize this attribute with the base style's setting. If the GetInclude method returns TRUE, the specific setting will be used for drawing. The following attributes have an include bit in COGFont class:

Font Weight (Bold, Normal)

Italic Style

Underline Style

StrikeOut Style

Font Size

Face Name

Each attribute is associated with four attribute methods. An example is the font size:

'returns the include-bitBOOL GetIncludeSize() const

'changes the include-bit.COGFont SetIncludeSize(BOOL bInclude)

130 Objective Grid for ActiveX User’s Guide

Page 141: Stingray 2006.2 Objective Grid ActiveX UserGuide

'returns the font size.LONG GetSize() const

'changes the font size.COGFont SetSize(LONG size)

This method automatically calls SetIncludeSize(TRUE).

SetIncludeSize and SetSize return the this-pointer, and therefore the program-mer can easily initialize several attributes with one statement. Normally, COGFont objects are used in styles. The following example illustrates the formatting of some columns.

Dim Gridfont As Object Gridfont = Gridocx1.CreateFontObject()Gridfont.SetFaceName("Times New Roman")Gridfont.setsize(24)

'set the interior and text color of this objectstyle.SetInterior(RGB(0, 0, 255)).SetTextColor(RGB(255, 0,0)).SetFont(font, GRIDOCXLib.constantdefs.gxOverride)

NOTE—When you change the font for the standard style in the grid, the row heights and column widths will grow or shrink proportionally with the font size. If you need to know the new row heights and column widths immediately after changing the font size, you should call UpdateFontMetrics.

9.9 Stylesmap

The COGStylesMap class maintains grid-wide styles that make it possible to group specific kinds of cells and make them have similar attributes. The pre-defined base styles are: row-header-style, column-header-style and standard-style.

Row header cells inherit their attributes from row-header-style. Column headers inherit their attributes from column-header-style. Standard-style is the base style for all cells in the grid.

COGStylesMap also maintains controls and user-attributes to be used in the grid. COGStylesMap data can be written to the application profile and loaded from it. Each base style has a unique id. This name is the key for the style-object and can be used in COGStyle::SetBaseStyle to specify the base style. The following attributes specify the ids for the default styles:

wStyleStandard specifies the Standard-style.

Chapter 9 Objects 131

Page 142: Stingray 2006.2 Objective Grid ActiveX UserGuide

wStyleRowHeader specifies the Row Header-style.

wStyleColHeader specifies the Column Header-style.

These styles are called system styles, which means that the user cannot delete them. The programmer can add more system styles that cannot be deleted by the user. Non-system styles can be added and removed at run time through the styles-dialog.

9.10 Print info Object

The Print info object (OGPINFO) is just a helper structure that contains useful information on the current print job. Each of its attributes either controls the print-ing process or provides information on it.

9.11 Properties Object

The COGProperties class maintains display and print properties of a grid, such as margins, header/footer, and colors of grid lines. Objective Grid offers some pre-defined dialog classes which allow the end user to modify these settings at run time.

When a grid is initialized, it checks (in OnGridInitialUpdate) if there is an exist-ing property object. If this is not the case, a property-object will be created, and default data will be loaded from the profile.

The property-object is maintained by the parameter-object. The COGParam object owns a reference to a property-object and provides accessor methods (GetProperties / SetProperties).

9.12 State Object

State objects (OGBoolState, OGBStrState, OGDoubleState) are simple objects that maintain the state of a particular type of object. For example OGBoolState objects hold a single Boolean property. They are used instead of simple values wherever parameters are passed by reference (i.e. where they are declared and passed in and are expected to be modified inside the method or event).

This is required to be compatible with scripts such as VB Script and J Script that do not correctly handle by ref parameters.

132 Objective Grid for ActiveX User’s Guide

Page 143: Stingray 2006.2 Objective Grid ActiveX UserGuide

In usage, instead of setting:

boolValue = True

You would set:

boolValue.Value = GRIDOCXLib.ogBoolean.ogTrue

Chapter 9 Objects 133

Page 144: Stingray 2006.2 Objective Grid ActiveX UserGuide

134 Objective Grid for ActiveX User’s Guide

Page 145: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 10 Advanced Topics

THIS CHAPTER INCLUDES: Undo/Redo Architecture Adding Border to Cells Number of Currently Visible Rows Determining selected rows/cells Clear the cells of the grid without selecting the grid

10.1 Undo/Redo Architecture

Objective Grid supports multiple level Undo/Redo. The grid also supports trans-actions. You can use GridBeginTrans to begin a transaction and then use GridCommitTrans to commit it. You can also roll back with a call to GridRollBack.

Gridocx1.GridBeginTrans("Trans1") 'call grid commands ' SetValueRange ' SetStyleRange ' any other grid command if Check if we need to rollback then Gridocx1.GridRollBack() Else Gridocx1.GridCommitTrans() End if

10.2 Adding Border to Cells

The following code allows adding a border to a specific range of cell.

Dim prop As Object prop = Gridocx1.GetProperties Dim Pen As Object Pen = Gridocx1.CreatePenObject()

Pen.SetColor(RGB(255, 0, 0))

Pen.SetWidth(2) Dim style As Object

Chapter 10 Advanced Topics 135

Page 146: Stingray 2006.2 Objective Grid ActiveX UserGuide

style = Gridocx1.CreateStyleObject Dim range As Object range = Gridocx1.CreateRangeObject

style.SetBorders(GRIDOCXLib.constantdefs.gxBorderTop, Pen) range.InitRange(2, 2, 4, 2) Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxOverride)

style.Free()

style.SetBorders(GRIDOCXLib.constantdefs.gxBorderBottom, Pen) range.InitRange(2, 7, 4, 7) Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxOverride)

style.Free()

style.SetBorders(GRIDOCXLib.constantdefs.gxBorderLeft, Pen) range.InitRange(2, 2, 2, 7) Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxOverride)

style.Free()

style.SetBorders(GRIDOCXLib.constantdefs.gxBorderRight, Pen) range.InitRange(4, 2, 4, 7) Gridocx1.SetStyleRange(range, style, GRIDOCXLib.constantdefs.gxOverride)

10.3 Number of Currently Visible Rows

There is not any method exposed in the Gridocx control that allows retrieving the number of rows currently shown when the Grid scroolbars are visible. However, you can implement your own solution using the CalcSumOfRowHeights and the Heights methods of the Gridocx object.

You can iterate the CalcSumOfRowHeights method on the rows of the grid until the returned value is greater than the value provided by the Heights method.

10.4 Determining selected rows/cells

You can determine which rows/cells have been selected in a grid either as they are being selected or (better) after the fact by querying the grid.

136 Objective Grid for ActiveX User’s Guide

Page 147: Stingray 2006.2 Objective Grid ActiveX UserGuide

If you need to retrieve the current cell, you may want to use the 'GetCurrentCell' method of the Gridocx object. The following code shows how to use this method:

Dim nRow As ObjectDim nCol As Object

nRow = Gridocx1.CreateDoubleStateObjectnCol = Gridocx1.CreateDoubleStateObject

Gridocx1.GetCurrentCell(nRow, nCol)MsgBox(nRow.Value & " " & nCol.Value)

In order to retrieve a selected range or a multiple selection, you may want to use the following code:

Dim RangeListObj As Object RangeListObj = Gridocx1.CreateRangeListObject

Gridocx1.CopyRangeList(RangeListObj, True)

MsgBox("GetCount = " & RangeListObj.GetCount) If (RangeListObj.GetCount >= 1) Then Dim Range As Object For Each Range In RangeListObj MsgBox("Range = " & Range.Top & "-" & Range.Left & "-" & Range.Bottom & "-" & Range.Right) Next End If

10.5 Clear the cells of the grid without selecting the grid

The method gridclear only succeeds at clearing the whole grid when the grid is selected beforehand. If you are using the grid in the singleSeletion Special mode, it is not possible to select the whole grid. Another possible way is with clearCells method, but in this case a rangelist is necessary.

You can use the following code implementation to clear the whole grid without selecting it. It also works when the GX_MODELBOX_SS Special Mode is selected.

Dim objRangeList As ObjectDim objRange As ObjectobjRangeList = Gridocx1.CreateRangeListObjectobjRange = Gridocx1.CreateRangeObjectobjRange.SetTable()objRangeList.AddTail(objRange)

Chapter 10 Advanced Topics 137

Page 148: Stingray 2006.2 Objective Grid ActiveX UserGuide

Gridocx1.ClearCells(objRangeList, True)

138 Objective Grid for ActiveX User’s Guide

Page 149: Stingray 2006.2 Objective Grid ActiveX UserGuide

PART II

Visual C++ User’s Guide

Page 150: Stingray 2006.2 Objective Grid ActiveX UserGuide

140 Objective Grid for ActiveX User’s Guide

Page 151: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 11 Class Summary

THIS CHAPTER INCLUDES: Introduction Understanding the OGX Source Code Control Classes Object Classes

11.1 Introduction

NOTE—This chapter will be of interest primarily to users who wish to cus-tomize the OG ActiveX controls. If you are planning to use the controls without modifying them, you may skip this chapter.

Before we look at the Objective Grid for ActiveX class summary, this brief descrip-tion should help you better understand the source.

11.2 Understanding the OGX Source Code

NOTE—This section requires some basic understanding of ActiveX devel-opment using the MFC.

Containers can take advantage of the several interfaces (see Chapter 17) typically implemented by ActiveX controls. The idea behind this scheme is to ensure a com-ponent-based system that would allow interaction between binary objects that have no special knowledge of each other (other than through the published interfaces).

The latest ActiveX specifications only require that ActiveX controls implement the IUnknown interface. (All other interfaces are optional and are derived from IUn-known.) However, most controls implement a plethora of interfaces to provide some functionality. A control that implements only IUnknown would not be very useful.

Thus control writers have to code certain generic published interfaces besides their implementation logic. This can often lead to tens of thousands of lines of boiler plate code. Class libraries like MFC have filled in, allowing developers to concen-

Chapter 11 Class Summary 141

Page 152: Stingray 2006.2 Objective Grid ActiveX UserGuide

trate on their application-specific logic rather than having to worry about generic container handling interfaces. Objective Grid for ActiveX can be seen as a library that fills in this ’boiler plate code’ for the Objective Grid class library.

To fill in this boiler plate code and to make the Objective Grid libraries fully func-tional as OLE controls, we had to make some design decisions. To gain a greater understanding of these issues and a better understanding of the product itself, consider some of the original design goals listed below:

The ActiveX Grid component should be object-oriented. By being object-oriented, Objective Grid does much to ease the tedium of working with a complex grid control. Over the course of several releases, it has proven to be easily extensible and maintainable— in large measure due to the object-oriented nature of the library.

Objective Grid for ActiveX should implement the full grid API as OLE automation methods.

Objective Grid for ActiveX should provide a mechanism that would, through OLE, enable a functionality that is akin to virtual functions inside C++. Virtual functions are essential to a C++ implementation and we wanted to carry over this tremendous functionality into the ActiveX world (if we could find a good way).

There should be automation-based properties that would provide a ready interface to some of the more frequently used grid interface features such as the font, the interior color and such. This is common with most controls and we wanted to be in line with the pack.

OGX should provide a variety of data binding options.

11.2.1 Functionality as implemented

11.2.1.1 Object Oriented Grid component

Objective Grid does not have a VBX legacy. This gave us the freedom to start work with a component that was written from the ground up with the MFC as its back-bone and with object-oriented design as one of its driving factors. To wrap around this component would mean that we would have to retain the object-oriented nature of the Grid to carry its power into the ActiveX environment.

To achieve this, we wrapped each of the objects that the grid uses inside C++ as an automation object. These objects are available as floating entities, which can be cre-ated by the grid control.

We will now proceed to briefly look at how this is accomplished in code. Let us take the example of two objects that are very commonly used by Objective Grid,

142 Objective Grid for ActiveX User’s Guide

Page 153: Stingray 2006.2 Objective Grid ActiveX UserGuide

the style object and the range object. Inside the ActiveX version, both of these very useful objects are available as OLE automation objects. We create them as shown below:

Figure 38 – Object Creation

When automation calls are made from the controller, the enclosing object simply directs these calls to the embedded instance. We get the functionality of the object in question using this form of containment.

11.2.1.2 Objective Grid API

Objective Grid for ActiveX implements almost the entire Grid API as automation methods. This part of the source is pretty straight forward and simply delegates to the MFC grid source in many cases. The only part that requires a little explanation is when we use IDispatch pointers. To pass objects to the ActiveX control, we often resort to wrapping these in automation wrappers as explained above and then these pointers are dereferenced to get the actual object that is then used in the call. This helps us to maintain an interface that is almost identical to the Objective Grid C++ interface. For example, SetStyleRange() still looks like this:

SetStyleRange(range object, styleobject, flags)

Let us look at some source that dereferences an automation object IDispatch, uses the resulting object to get at the actual object, and uses it in the source code.

// You can pass either an ODBC or DAO recordset from VBA. This// method will assign the contained recordset pointer to the bound// grid. This pointer will be used in the call to SetRecordset in// the grid's OnInitialUpdate

// To do-- add place holder for vbrecordset wrappervoid COGOleCtrl::SetRecordset(LPDISPATCH recordset) {

Chapter 11 Class Summary 143

Page 154: Stingray 2006.2 Objective Grid ActiveX UserGuide

#ifdef _CCETABGRID DELEGATE_BROWSEMETHOD(SetRecordset(recordset))#endif

#if defined(_CCEDAOGRID) || defined(_CCEODBCGRID) try { // We have to add ref this since VB will release this // object when it wants. We will call release on it later. recordset->AddRef(); COGVBRecordsetPlace* pVBRecset = (COGVBRecordsetPlace*)FromIDispatch(recordset); // We will store the IDispatch pointer here so that we can call // release later from ReleaseObjects. The reason that we have // to do this is that we have to prevent VBA from releasing the // object at its fancy if (m_recordsetWrapper) m_recordsetWrapper->Release();

m_recordsetWrapper = recordset;

COGRecordsetPlace* pRecset = pVBRecset->GetRecordset(); //#if defined(_CCEDAOGRID) pRecset->m_bCheckCacheForDirtyFields = FALSE;#endif //ASSERT(pRecset->IsKindOf(RUNTIME_CLASS(CGXRecordsetPlace))); DELEGATE_BROWSEMETHOD(SetRecordset(pRecset)) if (m_pCtrlRecordset != NULL && m_bOwnRecSet) delete m_pCtrlRecordset; m_pCtrlRecordset = pRecset; m_bOwnRecSet = FALSE; } catch (CMemoryException e) { TRACE(_T("Memory allocation failed in SetRecordset\n")); ThrowError(CTL_E_OUTOFMEMORY, IDS_OG_VBOUTOFMEMORY); } catch(...) { ThrowError(GXCTL_E_INTERNALERROR, IDS_OG_VBINTERNALERROR); }#else return;#endif

144 Objective Grid for ActiveX User’s Guide

Page 155: Stingray 2006.2 Objective Grid ActiveX UserGuide

//unused recordset;}

The essential code in this code block is:

COGVBRecordsetPlace* pVBRecset = (COGVBRecordsetPlace*)FromIDispatch(recordset);

We get an object that we can then use from the IDispatch pointer and go from there.

11.2.1.3 Implementation of (pseudo) virtual functions

Anyone who has worked with C++ will agree that one of the most powerful and useful features of the language is the availablity of virtual functions. Objective Grid makes extensive use of this mechanism inside C++ to work the way it does and to provide the ultimate level of customization. We used the ActiveX connec-tion point mechanism to simulate this feature. Any automation controller will provide a way to recognize and implement source interfaces from the control. This interface is not predefined by the controller in any manner and is pretty open to the control implementor.

NOTE—For more information on the connection point mechanism, please refer to the OLE documentation on Connection points and connection point containers. Inside OLE has a very good explanation of this, too.

Essentially when a virtual function is called in the C++ source, we simply fire an event that will be handled by the container. The event will have the exact same sig-nature (conceptually) as the virtual function that generates the event. We also pass any pertinent objects to the controller through this mechanism. The controller (user provided code) will then modify the parameters or handle the function itself and let us know whether we should call the default code (base class) or not through an additional boolean state parameter that is added to the function signature.

In the context of Objective Grid, a simple example that would illustrate this mech-anism would be GetStyleRowCol. This is a virtual function that gets called just before the grid displays a cell. The style object that will be used to draw this cell is passed to this virtual function. The C++ programmer has the option of changing these parameters based on dynamic data to get a ’Just in Time’ display. With an automation controller we would simply fire a GetStyleRowCol event that would be handled by the automation controller provided event code (in the case of Visual Basic, for example, this would be the event-handling code that the VB programmer writes for this event). In the same way that the C++ programmer could modify the style object, the automation controller code could too, giving the automation pro-grammer the same kind of flexibility that the C++ programmer enjoys.

Chapter 11 Class Summary 145

Page 156: Stingray 2006.2 Objective Grid ActiveX UserGuide

One issue involves optimization. If we were to copy each object that is passed to the virtual override into an automation object, the cost of this would make it pro-hibitive. Therefore, we simply switch pointers in contained captive automation objects. After each IDispatch call is completed, we switch back the parameters like within a stack.

/////////////////////////////////////////////////////////////////////////////////// The OCX wrapper for GetStyleRowCol ////////////////////////////////////////////// This event enables virtual binding in VBA /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// When we have to pass objects to VBA during an event call (like// when the style object gets passed everytime GetStyleRowCol gets// called) we implement an effecient interface that sets the// contained pointer in the automation wrapper to the address of// the object being passed. We reset the pointer after the call is// made. Each of the objects (one of) is declared as a member// variable and is preallocated to have maximum performance.// The first few implementations have the complete code and// thereafter we have macros that do the same thing.

BOOL COGOleCtrl::GetStyleRowCol(ROWCOL nRow, ROWCOL nCol, CGXStyle& style, GXModifyType mt, int nType){ BOOL bRetval(FALSE); try { bRetval = COGOleGrid::GetStyleRowCol(nRow, nCol, style, mt, nType); } catch(COGSEH_Exception& e) { FireGridError(eventidGetStyleRowCol,e.getSeHNumber(),!e.getExceptionFlags()); return FALSE; } m_vbStyle->SetStylePtr(&style); LPDISPATCH lpdispatch = m_vbStyle->GetIDispatch(FALSE);

FireGetStyleRowCol(nRow, nCol, &lpdispatch, GetValFrommt(mt), nType, &bRetval);

m_vbStyle->ResetStylePtr();

146 Objective Grid for ActiveX User’s Guide

Page 157: Stingray 2006.2 Objective Grid ActiveX UserGuide

return bRetval;}

NOTE—The code above shows a style member m_vbStyle. The actual OG ActiveX implementation uses a manager object that will return and manage these objects. This is not shown for simplicity.

The OBJECT_DISPATCH and the OBJECTEND_DISPATCH macros wrap most of this functionality. (Please refer to ogolemac.h in \basectl\include for this file.)

The remaining part of this chapter provides an overview of the following groups of MFC extension classes:

Control Classes – Objective Grid for ActiveX provides COleControl-derived control classes that form the backbone of the ActiveXs/OCXs.

Object Classes – Objective Grid ActiveXs are supported by automation objects that mirror the objects available inside the MFC version of Objective Grid. These classes provide the same functionality inside automation controllers. All of these classes are CCmdTarget-derived.

11.3 Control Classes

Figure 39 contains the hierarchy for the Objective Grid ActiveX control classes.

Figure 39 – Objective Grid ActiveX control class hierarchy

This class hierarchy diagram may be a little different from most you have seen. That’s because Objective Grid for ActiveX, like Objective Grid, uses C++ multiple inheritance (which is not used in MFC). The sections below describe each class in detail and explain why Objective Grid ActiveX uses these classes the way it does.

11.3.1 COGOleControl

COGOleControl derives from COleControl and also from grid-specific classes such as CGXGridCore. The inheritance on the right side is special in that COGOle-

Chapter 11 Class Summary 147

Page 158: Stingray 2006.2 Objective Grid ActiveX UserGuide

Control will define this side based on the control that is being compiled. Objective Grid ActiveX uses the same code body to generate the controls for basic grid sup-port, ADO support, DAO support, and ODBC support. If you are familiar with the Objective Grid class hierarchy, you will immediately realize that we have to derive from CGXGridCore (for the basic grid) and from CGXAdoGrid (for example) for the ADO control class. This is exactly what the right-side inheritance hierarchy does. Based on preprocesssor switches, this will be defined as CGXGridCore, CGXAdoGrid, etc. The essential fact is that this class on the right side is like a cha-meleon and acts as a placeholder for the class that best fits the need.

The primary implementation of the control class deals with these areas.

Implementation of all OLE automation methods, events, and properties.

Implementation of the essential drawing code that takes care of both design and run time representation. This class also takes care of rendering the grid to a metafile if required.

Implementation of any special code that the control needs to implement features such as ToolTips.

Implementation of helper classes that provide a convenient interface between OLE and the grid classes.

This kind of inheritance helps us avoid code duplication when dealing with multi-ple grid classes.

11.4 Object Classes

As mentioned earlier, we support many of the objects that Objective Grid depends on as automation objects that are available inside any automation controller. In MFC terms this means that the object will have to be wrapped in a CCmdTarget-derived class. We chose not to rely on multiple inheritance. Instead, we chose con-tainment and delegation. There were a couple of reasons for this:

Using multiple inheritance would have meant that we would have had to contend with the possibility of CObject appearing on both sides of the inheritance tree (and all the associated problems).

One of the goals of the Objective Grid for ActiveX project was to transfer much of the flexibility that Objective Grid affords inside a C++ environment to the automation controller environment. To this end, we decided to employ events to simulate virtual functions. For example, with

148 Objective Grid for ActiveX User’s Guide

Page 159: Stingray 2006.2 Objective Grid ActiveX UserGuide

the event handling implementation in OGX, it is possible to write code such as this inside an automation controller like Visual Basic.

Private Sub Gridocx1_GetStyleRowCol(ByVal sender As Object, ByVal eventArgs As AxGRIDOCXLib._DGridocxEvents_GetStyleRowColEvent) Handles Gridocx1.GetStyleRowCol

'Simply modify the style object as you see fit!

If (eventArgs.nType <> 0) Then Exit Sub End If

Dim pen As Object

Select Case eventArgs.nCol Case 1 If (eventArgs.nRow <> 0) Then 'The style object can be modified in several ways 'and at the same time. No repeated calls on the 'object

eventArgs.style.SetValue("Virtual Col1").SetInterior(RGB(255, 0, 0)) eventArgs.bModified = 1 End If Case 2 If (eventArgs.nRow <> 0) Then 'You can change every aspect of each cell on demand. 'Here we set the color at runtime. Everything is 'object oriented. Each object can be customized in 'several ways, with endless combinations possible.

pen = Gridocx1.CreatePenObject() pen.SetColor(RGB(0, 0, 255)) eventArgs.style.SetBorders(4, pen) eventArgs.style.SetValue("Virtual Col2") eventArgs.bModified = 1 End If Case Else eventArgs.bModified = 0 Select

End Sub

This is not very different from what you would expect to do inside C++ to achieve the same end. The containment and delegation that we use for the automation objects make possible this kind of functionality. In our automation objects we have an embedded pointer to the real live objects. For example, if we have an automa-

Chapter 11 Class Summary 149

Page 160: Stingray 2006.2 Objective Grid ActiveX UserGuide

tion style object (COGStyle), we would then have an embedded instance of CGXStyle (the C++ style class that is part of Objective Grid/MFC). All the behav-ior that is exhibited by the the automation object (COGStyle) is essentially a function of this embedded pointer.

This gives us the opportunity to switch the embedded pointer at run time (moving the original pointer to a temporary location) and thereby change the contained object.

To get this in perspective, let us look at an example. In the case of CGXGridCore::GetStyleRowCol (a virtual funtion called by the grid to gather style information from the underlying data structures as well as from code just before the grid displays this data), this would simply mean that we switch the pointer in the captive style object. (The control class has captive objects of every type —managed by state manager objects—so that it can allocate them when required. It allocates them at startup and then frees them up when done.)

The automation object that gets passed to the VB event then has the actual CGXStyle pointer (that we would ordinarily modify inside the C++ virtual GetStyleRowCol). If the VB programmer modifies this style object, then he sets the value of a boolean to TRUE to indicate that he has changed the object passed (this is required since events cannot return values in this case). Back inside C++, we check whether the value has been changed and use the changed value if required. Thus, we accomplish essentially the same kind of change that would be possible inside C++ and offer the same kind of flexibility.

Here is the C++ code that accomplishes this, just to give you a feel for our approach:

///////////////////////////////////////////////////////////////////// The OCX wrapper for GetStyleRowCol ///////////////////////////////////////////////////////////////////// This event enables virtual binding in VBA ///////////////////////////////////////////////////////////////////// When we have to pass objects to VBA during an event call (like// when the style object gets passed every time GetStyleRowCol gets// called), we implement an efficient interface that sets the// contained pointer in the automation wrapper to the address of// the object being passed. We reset the pointer after the call is// made. Each of the objects (one of each class) is declared as a// member variable and is preallocated to have maximum performance// The first few implementations have the complete code and// thereafter we have macros that do the same thing

150 Objective Grid for ActiveX User’s Guide

Page 161: Stingray 2006.2 Objective Grid ActiveX UserGuide

BOOL COGOleCtrl::GetStyleRowCol(ROWCOL nRow, ROWCOL nCol, CGXStyle& style, GXModifyType mt, int nType){ BOOL bRetval(FALSE); try { bRetval = COGOleGrid::GetStyleRowCol(nRow, nCol, style, mt, nType); } catch(COGSEH_Exception& e) { FireGridError(eventidGetStyleRowCol,e.getSeHNumber(),!e.getExceptionFlags()); return FALSE; } m_vbStyle->SetStylePtr(&style); LPDISPATCH lpdispatch = m_vbStyle->GetIDispatch(FALSE);

FireGetStyleRowCol(nRow, nCol, &lpdispatch, GetValFrommt(mt), nType, &bRetval);

m_vbStyle->ResetStylePtr();

return bRetval;}

As you can see, we just switch pointers at run time. This method has the calls listed. Most methods have macros (e.g. STYLE_DISPATCH) that do the same thing.

This kind of interface is very efficient and also enables us to provide the ultimate in flexibility.

Figure 40 depicts the layout of the Objective Grid ActiveX object classes. Note how the Automation Object acts as a wrapper around the actual object. Automa-tion calls are made to a visible interface from the automation controller application, such as VB or Access. Because all calls are delegated by proxy, the object class does all the work.

Chapter 11 Class Summary 151

Page 162: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 40 – The Objective Grid ActiveX object classes layout

The automation objects that ship with Objective Grid for ActiveX are described in the online help file as well as in the object reference. There are 25 objects, several of which mirror an Objective Grid MFC extension class. Others are helper classes.

152 Objective Grid for ActiveX User’s Guide

Page 163: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 12 Using OGX Control in VisualC++

THIS CHAPTER INCLUDES: Introduction Pre-Requisites Using the Control In VC++

Calling Methods Generating a Wrapper Class Handling Events Advanced Property Manipulation

12.1 Introduction

The Objective Grid for ActiveX control is designed to be used in the Visual Basic environment. It wraps the MFC Objective Grid control in an ActiveX control and exposes an API that enables VB developers to use many of the Objective Grid fea-tures. However, some MFC developers want to use the ActiveX version (instead of the MFC version) in their applications. This chapter is for those developers. How-ever, as a general rule, MFC developers will see better performance if they use the MFC version of Objective Grid.

You need to install the OG libraries. If you also use the MFC version of Objective Grid, you need to make sure that the correct of version of the libraries are installed.

12.2 Pre-Requisites

Objective Grid’s ActiveX controls incorporate several ActiveX features that typical ActiveX controls do not use. While this gives our controls unmatched flexibility and extensibility, it also requires that you understand the basics of classes such as COleDispatchDriver. We strongly recommend that you read the MFC documenta-tion on COleDispatchDriver before reading this document or before using the control inside Visual C++.

12.3 Using the Control In VC++

1. Choose File|New|Project.

Chapter 12 Using OGX Control in Visual C++ 153

Page 164: Stingray 2006.2 Objective Grid ActiveX UserGuide

2. Choose Visual C++ Projects from Project Types, and select MFC Applica-tion from the Templates: frame..

3. Give your project the name MFC Sample.

4. Select Dialog based as the Application type.

5. Check the Application settings by clicking User Interface Features in the AppWizard.

6. Check the Advanced settings by clicking Advanced Features and check the Class names by selecting Generated Classes in the AppWizard.

154 Objective Grid for ActiveX User’s Guide

Page 165: Stingray 2006.2 Objective Grid ActiveX UserGuide

Chapter 12 Using OGX Control in Visual C++ 155

Page 166: Stingray 2006.2 Objective Grid ActiveX UserGuide

7. Select Overview in the AppWizard to check Application Settings.

156 Objective Grid for ActiveX User’s Guide

Page 167: Stingray 2006.2 Objective Grid ActiveX UserGuide

8. Click Finish.

Chapter 12 Using OGX Control in Visual C++ 157

Page 168: Stingray 2006.2 Objective Grid ActiveX UserGuide

9. Right-click on the dialog to display a short-cut menu.

158 Objective Grid for ActiveX User’s Guide

Page 169: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 41 – Short cut Menu

10. Select Insert ActiveX Control.

11. Scroll down until you can select Objective Grid Control.

NOTE—There are different controls to choose from, depending on how you want to use the control.

Chapter 12 Using OGX Control in Visual C++ 159

Page 170: Stingray 2006.2 Objective Grid ActiveX UserGuide

12. Click OK.

Figure 42 – OGX Control

13. Click a sizing handle and drag to resize the control.

160 Objective Grid for ActiveX User’s Guide

Page 171: Stingray 2006.2 Objective Grid ActiveX UserGuide

14. Build the solution (CTRL+SHIFT+B).

15. Run the program (CTRL+F5).

16. Type something in several cells to try it out.

Figure 43 – Working MFC App with OGX Control

12.4 Calling Methods

Objective Grid ActiveX methods can be classified as those that require objects as part of the call and those that do not require objects as part of the call.

GetGridRowCount() does not require any objects, while the following call takes a range object and a style object as part of its parameter list:

SetStyleRange(LPDISPATCH range, LPDISPATCH style, short mt)

No additional work is required for calling methods that do not require any objects. You can simply call these on the grid OCX as shown below:

// Get a pointer to the OCX CGridocx* pOcx = (CGridocx*)GetDlgItem(IDC_GRIDOCXCTRL1);

Chapter 12 Using OGX Control in Visual C++ 161

Page 172: Stingray 2006.2 Objective Grid ActiveX UserGuide

Here IDC_GRIDOCXSTRL1 is the ID of the control on the dialog.

// Set the color back to white from the Ambient of the environment// this method does not require any objectspOcx->SetInteriorColor(RGB(255,255,255));

1. Select Class View from the View menu.

2. Select Add Class from the Project menu after selecting the name of the project in Class View.

Figure 44 – Starting the ClassWizard

162 Objective Grid for ActiveX User’s Guide

Page 173: Stingray 2006.2 Objective Grid ActiveX UserGuide

3. Select MFC Class From TypeLib from the Templates: frame.

Figure 45 – Adding a class

Chapter 12 Using OGX Control in Visual C++ 163

Page 174: Stingray 2006.2 Objective Grid ActiveX UserGuide

4. Select File under Add class from to provide the location of the file contain-ing the type library.

Figure 46 – Importing from a type library using Class Wizard

5. Point the Add Class From Typelib Wizard to the location of your OGX ActiveX control supporting dll ogc*.*

Figure 47 – Finding the dll

164 Objective Grid for ActiveX User’s Guide

Page 175: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—Normally this will be ogc90d.dll or ogc90r.dll unless you are using database support. This file can be found under the bin folder of your OGX installation.

Figure 48 – Import from Type Library

6. Click Save.

7. You will then be prompted with a dialog that shows you all the automation classes that the OGX control servers expose.

8. Select the ones that you want. Select all the classes if you are unsure about what you need and what you don’t need.

Chapter 12 Using OGX Control in Visual C++ 165

Page 176: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 49 – Automation classes in the extension dlls that the OGX version uses

9. Click Finish and the selected classes will be generated for you.

Please remember that the classes that Class Wizard generates are COleDispatch-Driver-based and are generated so that you can make the calls to the objects easily. They are always to be mapped to the corresponding COG* classes for referring to the documentation.

Let us proceed to look at a few simple calls using the generated objects:

// Declare a style object

IOGStyle style; style = pOcx->CreateStyleObject();

// Declare and create a range object IOGRange range;

range = pOcx->CreateRangeObject();

166 Objective Grid for ActiveX User’s Guide

Page 177: Stingray 2006.2 Objective Grid ActiveX UserGuide

Please remember that these objects map to COGStyle and COGRange in the documentation.

NOTE—If you use any of the GX_* constants you will have to include gxall.h in your stdafx.h file. Please add _GXNOAUTOLIB to the preprocessor set-tings to avoid linking with the grid libraries.

// Set the control to a 3D radio button

Please refer to the documentation on COGStyle for more information on SetControl, SetChoiceList, etc.

style.SetControl(GX_IDS_CTRL_RADIOBTN3D); // 3D radio button control style.SetChoiceList(_T("One\nTwo")); // Set this control for the second column range.SetCols(2);

The following code shows the actual call:

// Two ways of calling. If the parameter is LPDISPATCH // we call the function like this pOcx->SetStyleRange(range, style, 1); pOcx->ResizeRowHeightsToFit(range);

range.SetCols(1); pOcx->SetValueRange(range, _T("Hello!"), 0);

That is all there is to calling methods on the Objective Grid for ActiveX control.

12.5 Generating a Wrapper Class

To generate a wrapper class for the OGX control:

1. On the ResourceView tab, double-click the IDD_MFCSAMPLE_DIALOG resource.

2. In the Dialog Editor, right click the OGX control and select Add Variable from the shortcut menu.

Chapter 12 Using OGX Control in Visual C++ 167

Page 178: Stingray 2006.2 Objective Grid ActiveX UserGuide

3. Type m_grid as the name of the member variable.

4. Click Finish.

12.6 Handling Events

To handle events in an OGX control, please follow the following steps:

1. From Class View, select CMFCSampleDlg.

2. Click Events from the Properties window and select the control ID (IDC_GRIDOCXCTRL1).

168 Objective Grid for ActiveX User’s Guide

Page 179: Stingray 2006.2 Objective Grid ActiveX UserGuide

You will be presented with a list of events that the control supports as shown:

Figure 50 – Handling events using Class Wizard

3. Select the events that you want (for example, select GetStyleRowCol) and from the drop down list box select <Add> GetStyleRowColGridocxctrl1.

Chapter 12 Using OGX Control in Visual C++ 169

Page 180: Stingray 2006.2 Objective Grid ActiveX UserGuide

4. The wizard will add the following code for event GetStyleRowCol:

BEGIN_EVENTSINK_MAP(CMFCSampleDlg, CDialog)ON_EVENT(CMFCSampleDlg, IDC_GRIDOCXCTRL1, 1, GetStyleRowColGridocxctrl1, VTS_R8 VTS_R8 VTS_DISPATCH VTS_I2 VTS_I4 VTS_DISPATCH)END_EVENTSINK_MAP()

void CMFCSampleDlg::GetStyleRowColGridocxctrl1(double nRow, double nCol, LPDISPATCH style, short mt, long nType, LPDISPATCH bModified){ // TODO: Add your message handler code here}

5. Let us now do something useful in this override:

void CMFCSampleDlg::GetStyleRowColGridocxctrl1(double nRow, double nCol, LPDISPATCH style, short mt, long nType, LPDISPATCH bModified){ if(nType == -1) {

170 Objective Grid for ActiveX User’s Guide

Page 181: Stingray 2006.2 Objective Grid ActiveX UserGuide

COGStyle pDriver(style); pDriver.SetValue(_T("Test"));

COleDispatchDriver dr(bModified); dr.SetProperty(0x1, VT_I2, 1); dr.m_bAutoRelease = FALSE; }}

We create an COGSTYLE object to drive the raw IDispatch pointer that gets passed in to this method. Remember that these events inside the Objective Grid ActiveX behave very much like C++ virtual functions.

We can change the value and this will change the value in the grid’s inter-nal structures as the grid is drawn. (GetStyleRowCol is an event that is generated when the grid is about to be drawn. The style object represents almost all aspects of the cell including its value, etc. These attributes can be changed very easily at run time— based on dynamic conditions by overrid-ing GetStyleRowCol as shown above).

12.7 Advanced Property Manipulation

The only other area that needs to be covered is the manipulation of properties that are driven by the dispatch mechanism. One such property is the font property.

//changing the font// Method 1 can be used to change the default font for the entire// grid// 1. Changing the default font CFontHolder f(NULL); FONTDESC font = { sizeof(FONTDESC), OLESTR("MS Sans Serif"), FONTSIZE( 10 ), FW_BOLD, ANSI_CHARSET, FALSE, FALSE, FALSE }; f.InitializeFont(&font);

pOcx->SetDefaultFont(f.GetFontDispatch());

Properties such as these are typically meant for end user manipulation with prop-erty sheets and such. As shown above, manipulating them in C++ code is verbose but quite simple.

NOTE—If you notice that your VC application does not Terminate properly on termination, look for code that returns an IDispatch pointer.

Chapter 12 Using OGX Control in Visual C++ 171

Page 182: Stingray 2006.2 Objective Grid ActiveX UserGuide

For example:

COGStyle::SetIncludeBorders returns an IDispatch pointer to the object itself. This allows us to have code like this in Visual Basic.

Style.SetIncludeBorders.SetValue(…)

With Visual Studio.NET, Wizard will generate code similar to the code shown below:

LPDISPATCH COGStyle::SetIncludeBorders(BOOL b){ LPDISPATCH result; static BYTE parms[] = VTS_BOOL ; InvokeHelper(0x11, DISPATCH_METHOD,VT_DISPATCH, (void*)&result, parms, b); return result;}

The problem with the above code is that when we make a call like the one below, the resulting temporary LPDispatch ID returned by the ActiveX as a correctly AddRef ’ed pointer.

pStyle->SetIncludeBorders(…);

What happens is that this object does not get released. We can remedy this situa-tion by one of the following methods.

Replace all occurances of LPDispatch return values with smart pointer wrappers that call Release when they are destroyed. This method has the disadvantage that AppWizard generated files will need to be modified.

Have an LPDispatch that always sits on the LHS and correctly calls Release. This approach makes your code more readable, easier to follow, and in keeping with the traditions of COM, too.

LPDispatch pDispatch = pStyle->SetIncludeBorders(..); if (pDispatch) pDispatch->Release();

172 Objective Grid for ActiveX User’s Guide

Page 183: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 13 Building OCX Controls

THIS CHAPTER INCLUDES: Introduction Building the OG ActiveX controls Build Instructions Troubleshooting

13.1 Introduction

NOTE—This chapter is of interest to users who wish to build custom ver-sions of the OG ActiveX controls. If you are planning to use the controls without customization you may skip this chapter.

Objective Grid for ActiveX ships with pre-built controls. We also ship several pre-built versions of the OG 9.0 dll based on the configuration that was used to build the control. You no longer have to build the controls to use the product.

Before building custom versions of the controls, decide which controls you require.

Build the base control if you require just plain grid functionality. Build the ODBC, ADO, or DAO controls, depending on which of these you need in your applica-tion. If you need your control to access data across the Web, use the ADO control.

13.2 Building the OG ActiveX controls

Before building the OG ActiveX controls you should have installed Objective Grid/MFC 9.0. Refer to the Grid/MFC documentation for details on the MFC grid build process as well as information on the Build Wizard.

The Build Wizard configuration files that the OG ActiveX version uses are all avail-able under the \\Tools directory of your OG ActiveX installation. These files have the extension .bwc.

Chapter 13 Building OCX Controls 173

Page 184: Stingray 2006.2 Objective Grid ActiveX UserGuide

The configurations that the ActiveX Grid uses fall under the following categories:

Out of the box we support only the four configurations specified above. In general it is possible to support other configurations (This may require additional work on your part).

Objective Grid version 9.x has a plug-in architecture that makes it possible to include and exclude functionality based on need. Each of these generated sets is called a configuration. We can run the build wizard and specify a configuration and store the information in a .bwc file. We can use this configuration to let the Build Wizard generate the correct make file and build the correct .dll (with just the required components).

Some Important Notes:

Do not attempt to use any combination of DAO, ODBC, and ADO in the same control. The tab control no longer supports combining DAO and ODBC in the same control.

In general link with the minimum OG DLL that your ActiveX will need (the default builds do this). For example, do not link the base DLL that does not support database connectivity with a grid DLL that supports database connectivity.

When doing a batch build, do not combine controls that link to different variants of the grid DLL. Consequently there are no 'Release all' and 'Debug all' configurations.

In short select the component one at a time and build it. If you use the default con-figurations, you do not have to do any extra work and the build process will link to

Table 12 – Build Wizard Files Under Tools Folder

Control Build Wizard Con-figuration Filename

Definition

ADO grid controlOgadogrd.ocx

ogado.bwc Only ADO Database Support

Dao grid controlOgdaogrd.ocx

ogdao.bwc Only DAO Database Support

ODBC grid control Ogdbgrd.ocx

ogdb.bwc Only ODBC Database Support

Base grid control (ogocxgrd.ocx) or the tab control (ogocxtab.ocx) with no database support

ognodb.bwc No Database Support

174 Objective Grid for ActiveX User’s Guide

Page 185: Stingray 2006.2 Objective Grid ActiveX UserGuide

the correct DLL (for example, the no database connectivity control will link with the no database connectivity grid DLL).

All of the above configurations create the same ogobjects dll, but these dlls are not binary compatible. When you ship these controls make sure that you ship the cor-rect dll.

NOTE—Before building the OG ActiveX you need to have installed and properly built the Objective Grid MFC libraries. OG ActiveX version 9.0 will build with Objective Grid 9.0. It may not build with earlier version of Objec-tive Grid. Also, you have to make sure that all the Objective Grid configurations that you will link to have been built.

The following table provides information about the supported dlls that need to be built before building ANSI Release OGX components.

NOTE—When you install the product the OG ActiveX environment wizard should have added the following entries to the include directories in Visual C++ 6/7. Be sure to delete/move down any earlier entries that pertain to earlier versions.

Include directories added:--------------------------\\Basectl\include\\ogobjects\include\\ogadoobjects\include\\ogdaoobjects\include\\ogdbobjects\include

Lib:----\\ogobjects\lib

Table 13 – Supported dlls for ANSI Release OGX components

Control OG Supporting DLL

ADO grid control Og90adas.dll

Dao grid control Og90daoas.dll

ODBC grid control Og90dbas.dll

Base grid control or the Tab control with no database support

Og90nodbas.dll

Chapter 13 Building OCX Controls 175

Page 186: Stingray 2006.2 Objective Grid ActiveX UserGuide

Src:----\\Basectl\Src\\ogadoobjects\Src\\ogdaoobjects\Src\\ogdbobjects\Src\\ogobjects\Src

exe:----\\ogobjects\lib

13.3 Build Instructions

13.3.1 Visual C++ 6.0/7.0

NOTE—Please do not build the ActiveX controls from the projects in the basectl directory. These are shipped for reference. Use them only if you wish to browse the source.

To build, use buildw.sln located in the \build directory. The make file always makes sure that the correct supporting DLLs are built. We have all possible config-uration combinations under this make file. You can build any control from this one project.

1. Open buildw.sln.

2. Select the configurations that you wish to build and do a batch build. The possible configurations are

WIN32 and UNICODE builds for

The Base gridThe ADO controlThe Dao controlThe ODBC controlThe Tab control

For example if you want to build the DEBUG version of the base grid, you would choose Win32 Debug configuration.

The tab control does not support ADO, DAO and ODBC.

176 Objective Grid for ActiveX User’s Guide

Page 187: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—If you wish to build the ADO control you should build the Objec-tive Grid 9.0 ADO libraries. To build the ADO libraries you need to have the OLE DB SDK installed: (www.microsoft.com/data).

13.4 Troubleshooting

This section lists some of the common build/installation problems:

13.4.1 Unresolved externals when compiling the OGX

Remove all the text from the corresponding def files. (The def file name is the same as that of the DLL being built. Only the extension is different.) The file itself needs to be there, but it should be empty. This should resolve these errors.

13.4.2 Link error

An error such as the following:

LINK : fatal error LNK1104: cannot open file "og90nodbas.lib"NMAKE : fatal error U1077: 'link.exe' : return code '0x450'Stop.

indicates that you have not built the Objective Grid DLLs for the specific configu-ration (ognodb in this case) that this control links to. Please build this configuration and then build the control.

13.4.3 Registration Fails

If registration fails, please check to see if all the supporting DLLs are built and in the path. For a list of all the DLLs that a control depends on, refer to the Chapter 8, “Redistribution.”

13.4.4 Missing OG Header File gxall.h

Gxall.h is an Objective Grid header file. If this file is not found on your system then you have to install Objective Grid. If this file exists on your system but is not accessible to your build, then check the include directories under tools\\options in DevStudio to see if the Objective Grid files are in the path.

Chapter 13 Building OCX Controls 177

Page 188: Stingray 2006.2 Objective Grid ActiveX UserGuide

178 Objective Grid for ActiveX User’s Guide

Page 189: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 14 Object Implementation in aDLL

14.1 Introduction

NOTE—This chapter is of interest to users who wish to customize the OG ActiveX controls. If you are planning to use the controls without modifica-tion you may skip this chapter.

All the OLE Automation objects are implemented in an extension DLL. That leaves us with one issue. How do we get objects implemented inside an extension DLL to be used inside an OLE controller (that knows nothing about MFC extension DLLs)? The solution is to use a regular DLL server for these objects.

In earlier OG ActiveX versions this was a separate server. With the present version of OGX, the objects are creatable only by the control itself, i.e., the control acts as the server for these objects.

With some earlier versions, to create a COGRange object we would write :

Dim range as objectSet range = CreateObject(“CGXRange”)

In the current version, this needs to be changed to:

range = Gridocx1.CreateRangeObject()

With earlier versions, control registration and maintenance was considerably more complicated and was done using a configuration wizard. Now you can use regsvr32 to register the controls.

Chapter 14 Object Implementation in a DLL 179

Page 190: Stingray 2006.2 Objective Grid ActiveX UserGuide

180 Objective Grid for ActiveX User’s Guide

Page 191: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 15 AppWizard Tutorial

THIS CHAPTER INCLUDES: Deriving Grid Control from Base Control Deriving from a grid base class other than CGXGridCore

15.1 Deriving Grid Control from Base Control

NOTE—This chapter is of interest to users who wish to customize the ActiveX controls. If you are planning to use the controls without modifica-tion, you may skip this chapter.

NOTE—Under VC.NET, the OGX AppWizard generates applications with the character set defined as Unicode (to take advantage of XP visual styles). This requires AppWizard-generated applications to link with the Unicode libraries of OGX and OG. If the applications are generated under Windows 2000, NT, or 98, the default character set can be changed back to ANSI.

The Microsoft Knowledge Base article number Q141489 gives details on how an OLE control that is COleControl-based can be derived from another control. We strongly recommend this Knowledge Base article before continuing to read this chapter, which does not repeat information from this article. We have also pro-vided a wizard that will generate a skeletal template you can use for this purpose. The main areas of change are in the dispatch maps and the IDs used for derived controls.

You can use the AppWizard that ships with the ActiveX version to generate a skel-etal control that derives from the base grid control. This wizard is installed on your system when you install the OG ActiveX version. When you select File|New|Project to create a new Workspace, you will see the Objective Grid for ActiveX App Wizard. This wizard only helps with generating base control derived controls. If you wish to generate data bound controls, you can still use this wizard but will have to manually perform many of the steps given below.

1. Launch Visual Studio.NET and choose File|New|Project .

Chapter 15 AppWizard Tutorial 181

Page 192: Stingray 2006.2 Objective Grid ActiveX UserGuide

2. Select the GridXWiz70.

3. Type the name of your project and click OK.

182 Objective Grid for ActiveX User’s Guide

Page 193: Stingray 2006.2 Objective Grid ActiveX UserGuide

Figure 51 – Objective Grid ActiveX AppWizard – Step 1 of 1

4. Select Settings from the OG ActiveX Application Wizard.

Chapter 15 AppWizard Tutorial 183

Page 194: Stingray 2006.2 Objective Grid ActiveX UserGuide

5. Now click on the Change Path button and proceed to change the path with the displayed dialog.

Figure 52 – Objective Grid ActiveX AppWizard –Select directory

6. Please ensure that the root folder of your ActiveX installation appears in the ’Chosen…’ Combo box.

7. Click Open.

8. After you have changed the path, you can click Finish button in the App-Wizard dialog to generate the files.

Please note that the wizard does not validate the path that you have speci-fied. If you specify an incorrect path, it would generate files just the same. When building, the build would complain that one or more files cannot be found. You can correct the path and point to the files at this point, too.

NOTE—If you copy the generated project to a different machine or if your OG ActiveX installation changes, you will have to make sure that absolute paths in the .cpp files that are generated are updated.

184 Objective Grid for ActiveX User’s Guide

Page 195: Stingray 2006.2 Objective Grid ActiveX UserGuide

15.2 Deriving from a grid base class other than CGXGridCore

You can start with the wizard and generate the base set of files. The right side of the inheritance hierarchy for COGOleCtrl is defined in ogolebase.h. This just does a typedef based on pre-processor settings.

#ifndef _OGOLEBASE_H#define _OGOLEBASE_H

#if defined(_CCEBROWSER) typedef CGXBrowserGrid COGOleGrid; typedef CGXBrowseParam COGGridParamPlace; typedef COGBrsParam COGGridVBParamPlace;#elif defined(_CCEDAOGRID) typedef CGXDaoGrid COGOleGrid; typedef CGXDaoParam COGGridParamPlace; typedef COGDaoParam COGGridVBParamPlace; typedef COGIntDaoRecordset COGRecordsetPlace; typedef COGDaoRecordset COGVBRecordsetPlace; typedef COGDaoDatabase COGDatabasePlace;#elif defined(_CCEODBCGRID) typedef CGXODBCGrid COGOleGrid; typedef CGXDbParam COGGridParamPlace; typedef COGDbParam COGGridVBParamPlace; typedef CGXDynamicRecordset COGRecordsetPlace; typedef COGRecordset COGVBRecordsetPlace; typedef COGDatabase COGDatabasePlace;#elif defined(_CCEADOGRID) typedef CGXAdoGrid COGOleGrid; typedef CGXAdoParam COGGridParamPlace; typedef COGAdoParam COGGridVBParamPlace; typedef ADORecordset COGRecordsetPlace;#elif defined(_CCEDATACONTROL) typedef CGXBrowserGrid COGOleGrid; typedef COGOleParam COGGridParamPlace;#else#ifndef _COREUSED #define _COREUSED#endif typedef CGXGridCore COGOleGrid; typedef CGXGridParam COGGridParamPlace; typedef COGParam COGGridVBParamPlace; typedef CGXGridWnd COGOleGridWnd;#endif

#endif //_OGOLEBASE_H

Chapter 15 AppWizard Tutorial 185

Page 196: Stingray 2006.2 Objective Grid ActiveX UserGuide

As you can see from the above code, changing the base class just involves changing the typedef. For example, to change the base class to a browser grid, just add _CCEBROWSER to the pre-processor settings.

NOTE—Based on the base class you use, there will be additional work required to implement the complete control.

Typical scenarios for deriving from the OG ActiveX controls:

You want to add a new control type.

You want to add a method.

You want to add a property.

You want to add an event.

Controls types cannot be added in Visual Basic code. For example, if you subclass CGXEditControl, you can then derive your own control that can use this derived CGXEditControl, instead of the default CGXEditControl.

The MFC grid supports hosting any arbitrary CWnd-based control inside the grid using CGXWndWrapper. This can be done inside the OG ActiveX controls only by deriving from them and then registering the window wrapper control in the derived code.

15.2.1 Adding methods/properties/events

In general, adding methods to the derived control using Class Wizard is not sup-ported. You can however use a different dummy project and copy the generated code over to this control. Please refer to the MFC documentation for details on adding methods, properties and events to this derived control. It is no different from adding these to any other COleControl-based control.

186 Objective Grid for ActiveX User’s Guide

Page 197: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 16 Error Handling

16.1 Introduction

We have implemented different kinds of error handling for automation methods and events. For automation methods, our default error handling uses the COle-Control function ThrowError, which halts execution of the offending function and enables easy tracking of errors in methods. For example:

DECLARE_ROWCOL(nCol) short s(0); try { DELEGATE_BROWSEMETHOD_RETVAL(s, GetFieldFromCol(xnCol)) } catch(...) { ThrowError(GXCTL_E_INTERNALERROR, IDS_OG_VBINTERNALERROR); } return s;

For events, however, this kind of error handling is not advisable. One reason is that events are almost always fired by the object in a manner that is beyond the control of the program. If we were to pop up a dialog when an error occurred in GetStyleRowCol, many message boxes would appear in succession (FireError does not halt execution).

Instead, we decided to use Structured Exception Handling (SEH). Using SEH we simply fire an error event that will be handled at the discretion of the VB program-mer. The severity of the error is also passed on as a parameter.

Typical error handling code for events is shown below.

try { if (xbool) return COGOleGrid::OnGridSysDeadChar(nChar, nRepCnt, nFlags); else return TRUE; } catch(COGSEH_Exception& e) {

Chapter 16 Error Handling 187

Page 198: Stingray 2006.2 Objective Grid ActiveX UserGuide

// Generate a custom error event and leave it to the discretion of// the VB programmer FireGridError(eventidOnGridSysDeadChar,e.getSeHNumber(),!e.getExceptionFlags()); return FALSE; }

188 Objective Grid for ActiveX User’s Guide

Page 199: Stingray 2006.2 Objective Grid ActiveX UserGuide

CHAPTER 17 Interfaces

THIS CHAPTER INCLUDES: Introduction Brief Introduction to COM Adding Controls to the Tool Palette Interfaces

17.1 Introduction

NOTE—You can skip this chapter if you have a working knowledge of COM/ActiveX controls.

17.2 Brief Introduction to COM

The Component Object Model (COM) is a binary standard that specifies how soft-ware components (i.e., objects) inter-operate and communicate. Under COM, a software component must implement predefined means by which a client applica-tion can know about the component’s interfaces, query for them, let the server component know that it is using them and when it is done using them. In addition to documentation, a component can provide a type library describing all of its inter-faces and calling conventions.

OLE Automation refers to a technology that provides a way to manipulate binary objects defined by an application or library from outside the application in a lan-guage-independent manner that is laid out based on COM principles. The objects exposed by an application or programming tool are called OLE Automation objects. An OLE Automation controller, such as Microsoft Visual Basic, can access these objects to get or set properties, invoke methods, etc. A controller can also retrieve a pointer to an active object (in VB, this is implemented by the GetObject function) or create a new object (CreateObject). It is important to note that the controller and the object are not really connected in any manner and their interaction is somewhat intelligent—based on COM principles. In effect this means that the con-troller can use a later version of any component without having any modifications done to itself.

Chapter 17 Interfaces 189

Page 200: Stingray 2006.2 Objective Grid ActiveX UserGuide

Because COM is independent of any programming language, a COM object cre-ated in Visual C++ can be used by a client application written in Visual Basic (or in any other such environment), and vice versa. This makes the component far more accessible to a wider variety of applications than was earlier possible and is one giant leap further in achieving extensive code reuse.

17.2.1 Evolution of COM from Dynamic Link Library (DLL) architecture

Before we go into any further details, it will be useful to contrast the interaction mechanism that is provided by COM against the present mechanism that is pro-vided by DLLs. We chose to look at DLLs because COM draws heavily on the Windows DLL architecture and fixes some problems with this architecture.

DLLs fulfill the goals of software reuse through components. We often make use of the functionality that is provided by the C run time (or by the MFC for that matter) as DLLs. This saves us the trouble of writing all this low level code and lets us con-centrate on our application-specific logic. Because DLLs are memory efficient, easy to use, and have very little overhead in terms of loading time and such, they are very useful. However, there are some disadvantages to this kind of DLL-based architecture.

The client (application) and the server (DLL) are very tightly integrated. The client is compiled with the header file that is provided by the DLL writer. (Though it is possible to dynamically load a DLL and get a function address, usually this can be very tedious, especially when the number of functions is high and when the names are mangled). When the DLL implementation is changed, the client (in most cases) needs to be recompiled too. Often updating this DLL on a system would mean that all applications that depend on this DLL would also have to be recompiled (i.e., most version updates result in binary incompatibility). As you can see, DLLs have quite a problem with versioning issues.

Let us look at this in some detail. Let’s say that we have a function in a DLL that adds some numbers and returns a value based on the result of the addition. Now let’s say that we change the implementation of this function such that it uses a faster algorithm and is much better. With normal DLLs the client would have to be recompiled if there was any change in members (we assume the use of C++ here) in the implementation class. But if we were to encapsulate all the implementation details in the library and let the client access the server only through member func-tions, then we do not have to recompile. However, we then have to provide different .def files for all the exported functions for different compilers or different versions of the compiler. We can get around this by just exporting functions that are either not mangled (which would be very restrictive) or by exporting only functions whose signature does not change. However, these solutions are not desirable.

190 Objective Grid for ActiveX User’s Guide

Page 201: Stingray 2006.2 Objective Grid ActiveX UserGuide

If we could get rid of these dependencies in some manner, then the DLL architec-ture would not be so bad. After all, Windows itself is a set of DLLs. COM takes a kind of mixed approach to get around this scenario. This approach is best explained in C++ terms. If the header file that we are linking to is an abstract base class, the compiler would no longer look for an implementation of the members. We just export one function that creates and returns an object of a derived type. COM uses a more flexible approach; the returned object is a Class Factory, which is capable of creating objects that we need. But basically the approach is the same. We can then use the created object and the interface to which we already have access to use the object without any problems. We can also very easily load the library dynamically— using LoadLibrary— since there is only one entry point for which we need to get the address.

Anyone who has loaded huge DLLs that have a trillion entry points will under-stand the benefits that this gives us. (Loading the library dynamically helps us reduce compile time dependencies.) This is exactly how COM works. COM expects components (inproc ones) to export a function called DllGetClassObject that is capable of returning an object that can create instances of the object that the client needs. Once the client has this object it can simply use the object since it already knows that it implements a specified abstract class (in OLE terms this abstract class definition is called an Interface).

The only remaining piece in the puzzle is the manner in which COM loads the actual server. This is where there is some operating system-specific stuff that needs to be done (remember COM is not specific to Windows). The OS on which COM is implemented would provide some sort of API which, given a unique identifier (a GUID in the COM world), would load the server into memory (under Windows the information required to load the server is stored in the registry) and then call DllGetClassObject. DllGetClassObject is applicable for InProcServers only. COM also provides for out-of-process servers but these do not concern us at this point since our controls and most other ActiveX controls are InProc servers. That is all there is to it.

Fundamental to the COM mechanism is the IUnknown interface, which is imple-mented by all COM-based objects. This interface is uniquely identified on every machine by {00000000-0000-0000-C000-000000000046}. IUnknown must expose the following three methods in the order given: QueryInterface(), AddRef() and Release(). In the next chapter we will look at this important interface in more detail.

A client using a COM component first gets the component’s class identifier (CLSID). Then the client creates an instance of the component (with the help of OS-provided APIs). Now the client can probe the component to discover what interfaces it sup-ports and call the method for a desired operation. A single server can support any number of interfaces (we can think of it as inheriting from several abstract base classes in C++ terms).

Chapter 17 Interfaces 191

Page 202: Stingray 2006.2 Objective Grid ActiveX UserGuide

NOTE—An OLE object registers its CLSID in the system registration data-base (i.e., registry), so that it can be loaded and programmed by other applications. The CLSID associates the component object with a DLL or EXE file.

17.2.2 OLE/COM References

From CPP to COM. Horstmann, Markus, OLE Program Manager, Microsoft Corporation, 1995.

This article, a very good introduction to COM, is available on MSDN. It is also very useful in that it contrasts COM with the DLL architecture that Windows uses. We briefly touch on this subject in this guide, but if you would like more information, this is one place to look.

Inside OLE, 2nd edition. Brockschmidt, Kraig. Redmond, WA: Microsoft Press, 1995.

This book is considered to be the definitive reference for OLE programming.

Inside VC++. Kruglinski, David (Microsoft Press).

Though primarily a Visual C++ book, this provides a very useful introduc-tion to OLE.

Professional Visual C++ 5 ActiveX/COM Control Programming

Li, Sing and Panos Economopoulos: Wrox Press, 1997.

This highly recommended book concentrates on ActiveX controls and is less detailed than Inside OLE.

Essential COM. Box, Don. Addison Wesley, 1998.

This is a very good book on COM if you want to learn more about what makes OLE tick.

17.3 Adding Controls to the Tool Palette

We can add our own controls to the tool palette in Visual Basic or any other pro-gramming environment that supports such controls. These controls are called OLE controls or ActiveX controls.

192 Objective Grid for ActiveX User’s Guide

Page 203: Stingray 2006.2 Objective Grid ActiveX UserGuide

OLE/ActiveX controls depend on a lower-level technology called COM, which defines language-independent, binary standards for interaction among objects.

Essentially, the container (Visual Basic in this case) knows nothing about the con-trols other than that they support certain actions. It can then proceed to ask them to perform these actions.

To be good citizens of the OLE/ActiveX control world, the controls should imple-ment all the required functionality that the container can then access through predefined interfaces. For example, if the container expects controls to move as it wants them to, then it would probably require them to implement a Move inter-face through which it can call the controls and ask them to move to the location that it specifies. In broad terms though, the container and the control know noth-ing specific about each other. They can understand each other only through certain terms that are predefined (usually by Microsoft).

NOTE—You are free to define your own interfaces, but of course MS Visual Basic will not support them.

17.4 Interfaces

Let us look at interfaces in a little more detail. Interfaces are simply groups of func-tions. They can be implemented in any manner that the implementor sees fit, but they must have a predefined signature. In simple terms, COM looks at any object as a blob (binary large object) of data that can perform some actions through a pre-defined interface. The blob is capable of handing any other blob that cares to ask a pointer to a table of pointers to functions that implement defined interfaces. In C++ this table is known as the virtual function table (VTBL). Using this pointer, the blob that asked for the pointer (the client blob) can then call the object and ask it to execute the functions.

Blob1 (Server)<--------- (Do you support Interface Move?)---------------Blob2 (Client)

Blob1------------------------> Blob2 (Yes, I do. Here is my pointer to the table of functions that implement the Move interface.)

The important part is that both blob 1 and blob 2 have the same idea about the Move interface. As long as both do, they are home free, and blob 2 can manipulate blob 1 using the pointer under the terms of the Move ’contract’ interface.

In C++ terms, an interface is usually defined as an abstract class. For example, Move could be defined as class Move.

Chapter 17 Interfaces 193

Page 204: Stingray 2006.2 Objective Grid ActiveX UserGuide

By convention, interfaces begin with an ’I’. Therefore, abstract class Move would be IMove in the interface world.

class IMove{ MoveMe(int x, int y) = 0; HideMe(BOOL b) = 0;};

Now, if we were to implement a blob that implements this interface, we could derive from IMove and implement these functions.

class ImplementMove: public IMove{ MoveMe(int x, int y); HideMe(BOOL b);};

The actual implementation is up to the developer (the implementor).

When blob 2 (the client) wants to know whether we support IMove, we can say “Yes.” The manner in which we are required to say this is also predefined. In fact, any blob that has to talk to another blob must implement a Microsoft-defined interface called IUnknown. This interface has three methods:

QueryInterface - Do you support this interface?

AddRef

Release

AddRef and Release have to do with the implementation, and we will discuss the specifics a little later.

When blob 2 calls blob 1 with QueryInterface, it will ask whether it supports the interface IMove. Then blob 1 can say “Yes” and return a pointer to blob 2 that will have all the pointers to the various functions that Move needs implemented. In C++ terms, this would just be the ’this’ pointer (in this particular case).

Once blob 2 (the client) has this pointer, it can then call the functions in Move.

pointer->MoveMe(0,0);

Containers like Visual Basic (and most ActiveX containers) operate through a more complex handshaking process and also hide this completely from the programmer. But this idea is the core behind this process.

Now we know that, for blob 2 to know whether blob 1 supports IMove, all it has to do is ask through QueryInterface. But how does blob 1 (the server) get created in the first place so that blob 2 can ask about IMove? This is where COM steps in with default support (This support is OS specific as we mentioned in the previous chap-

194 Objective Grid for ActiveX User’s Guide

Page 205: Stingray 2006.2 Objective Grid ActiveX UserGuide

ter). Under Windows, COM will search the registry for information on the program that is capable of creating blob 1 when blob 2 asks it to create blob 1 (blob 2 will do this with a call to CoCreateInstance in most cases. CoCreateInstance is a COM API that is implemented on each OS that COM is supported on). There is actually a further level of indirection involved with class factories coming into the picture. Essentially COM steps in and takes care of the other work and finally can hand blob 2 a pointer to the requested interface or to IUnknown. Blob 2 can then use IUnknown to ask blob 1 about any other interfaces that it supports and so on.

Since COM takes care of loading the server that serves up blob 1, it should take care of unloading it when it is no longer needed. It is in this context that reference counting becomes important. Any pointer that the object gives out will cause an increase (reasonably so, this pointer will in all likelihood be used at some point and we do want the object to be around when the pointer is used) in the reference count (this is where AddRef comes in). The user of that pointer will then call Release when it is done with the pointer (the interface). When the reference count becomes zero, the number of users using that interface is zero. When none of the interfaces that the object supports are in use, it is then free to unload itself. DLL servers typically accomplish this through a function called DllCanUnloadNow that COM (the implementation of COM on the OS actually) calls every now and then. When the DLL server knows that it's no longer required to remain in mem-ory, it returns OK and COM unloads the server.

ActiveX controls implement several of these predefined interfaces through which containers can interact with the controls. Similarly, controls can interact with con-tainers through such defined interfaces. Thus two-way interaction between the controls and the container takes place.

Essential interfaces that controls implement. (It is no longer required that controls implement these interfaces. The only required interface is IUnknown.)

IConnectionPointContainer

IConnectionPoint

IEnumConnectionPoints

IEnumConnections

IDataObject

IOleCache

IOleControl

IOleInPlaceActiveObject

IOleObject

IPerPropertyBrowsing

Chapter 17 Interfaces 195

Page 206: Stingray 2006.2 Objective Grid ActiveX UserGuide

IPersist

IPersistMemory

IPersistStorage

IPersistStreamInit

IPersistPropertyBag

IProvideClassInfo

IProvideClassInfo2

ISpecifyPropertyPages

IViewObject

IViewObject2

These interfaces are documented in the VC online reference as well as in the refer-ence books mentioned in Section 17.2.2. A knowledge of these interfaces is not essential. However, do refer to the interface specifications as you come across them.

When developing ActiveX controls with MFC, we get a default implemetation for most of these interfaces. Therefore our work as a control implementor is largely the customization of these implementations to cater to our needs. The MFC class that implements an ActiveX control is COleControl. The OG ActiveX implementation derives from this class and adds grid funtionality (similar to the manner in which we add grid funtionality to a CWnd or a CView) .

196 Objective Grid for ActiveX User’s Guide

Page 207: Stingray 2006.2 Objective Grid ActiveX UserGuide

Index

Symbols.ogl file 99

AAppWizard 181Automation Objects 114

Bbase styles

definition 8bound mode of OG Designer 87build wizard 173building OG ActiveX controls 173

CCalcSumOfRowHeights 136cells

definition 9definition of covered 9definition of current 9

CGXGridCoreSetStyleRange() 120, 125

CGXRange 125SetCells() 125SetCols() 125SetRows() 125SetTable() 125

CGXStyle 120attributes 124

Check List Combo box 42CheckBox 40CheckBox, 3D Effect 40Client machine 84COGData 130COGFont 130

COGStylesMap 131columns,sorting 61COM 189ComboBox Display Choice, One

Based 41Combobox No Text Fit 40ComboBox One Based 41Combobox Text Fit 40ComboBox Zero Based 41ComboBox, Display Choice, Zero

Based 41comctrl32.dll 5common terms 8, 10Component Object Model 189control

definition 9control child

definition 9covered cells

definition 9CreateAdoParamObject 115CreateBoolStateObject 115CreateBrushObject 115CreateBStrStateObject 115CreateDaoDatabaseObject 116CreateDaoParamObject 115CreateDaoRecordsetObject 116CreateDatabaseObject 116CreateDataObject 116CreateDbParamObject 115CreateDoubleStateObject 115CreateFontObject 116CreateHintObject 116

Index 197

Page 208: Stingray 2006.2 Objective Grid ActiveX UserGuide

198 Obj

CreateLongStateObject 115CreateParamObject 115CreatePenObject 116CreatePointObject 116CreatePrintInfoObject 116CreatePropertiesObject 116CreateRangeListObject 115CreateRangeObject 115, 126CreateRecordsetObject 116CreateRectObject 116CreateSizeObject 116CreateSortInfoObject 116CreateStyleObject 115, 118CreateStylesMapObject 115Currency control 43current cell

definition 9

Ddata binding 4data source

definition 9Data Source, System 71Data Source,File 64Database server 84database, registering as data source 63Date time control with calendar 42Date time control without calendar 42deployment file 111documentation

conventions 8formats 7

dropdown list, changing content at run time 54

EEdit control 39Edit Control With Spinner 40Edit with Hot Spot 40Edit with Scrollbar 40Enter key, changing behavior of 37

error handling 187event, definition 23events, handling 168

FFile Data Source 64

GGetCurrentEventFirer 57glossary 8GridCommitTrans 135Gridocx object 74GridOpenRecordset 74GX_IDS_CTRL_CBS_DROPDOWN 41GX_IDS_CTRL_CBS_DROPDOWNLIS

T 41GX_IDS_CTRL_CBS_TABBED_DROP

DOWN 41GX_IDS_CTRL_CBS_TABBED_DROP

DOWNLIST 42GX_IDS_CTRL_CHECKBOX 40GX_IDS_CTRL_CHECKBOX3D 40GX_IDS_CTRL_CHECKLIST_COMBO

BOX 42GX_IDS_CTRL_COMBOBOX 40GX_IDS_CTRL_CURRENCY 43GX_IDS_CTRL_DATETIME 42GX_IDS_CTRL_DATETIMENOCAL 4

2GX_IDS_CTRL_EDIT 39GX_IDS_CTRL_HEADER 40GX_IDS_CTRL_HOTSPOT 40GX_IDS_CTRL_LISTBOX 40GX_IDS_CTRL_MASKEDIT 43GX_IDS_CTRL_ONEBASED 41GX_IDS_CTRL_ONEBASED_EX 41GX_IDS_CTRL_PUSHBTN 39GX_IDS_CTRL_RADIOBTN 39GX_IDS_CTRL_RADIOBTN3D 40GX_IDS_CTRL_SCROLLEDIT 40GX_IDS_CTRL_SPINEDIT 40

ective Grid for ActiveX User’s Guide

Page 209: Stingray 2006.2 Objective Grid ActiveX UserGuide

GX_IDS_CTRL_STATIC 39GX_IDS_CTRL_TEXTFIT 40GX_IDS_CTRL_ZEROBASED 41GX_IDS_CTRL_ZEROBASED_EX 41gxApplyNew 121gxCopy 121gxExclude 121gxOverride 121

HHeader 40HorizontalSorting 61

IIIS server machine 84InitRange 127installation directory 5Interface 191IUnknown 191

Llayout file 98licensing 112link error 177ListBox 40

MMasked Edit control 43MFC Style Tabbed Combo box 41MFC Style Tabbed Drop Down List 42

Nnaming conventions 110

OObjective Grid Designer 87

components 90Objective Grid for MFC 1ODBC Data Source Administrator 63OGAdoParam 113, 115OGBoolState 115, 132OGBrush 115, 129

OGBStrState 115OGDaoDatabase 116OGDaoParam 113, 115OGDaoRecordset 116OGData 116OGDatabase 116OGDatabase object 74OGDbParam 113, 115OGDoubleState 115OGFont 116OGGridParam 113, 115OGHint 116OGLongState 115OGPen 116OGPoint 116OGPrintInfo 116OGProperties 116OGRange 113, 115OGRangeList 115OGRecordset 116OGRecordset object 74OGRect 116OGSize 116OGSortInfo 116OGStyle 113, 115, 117OGStylesMap 115OLE Automation 189OnGridInitialUpdate 132

PParameter object 113parameter object 117PreInitialUpdate 61print preview, not available in Tab

version 57properties

definition 9properties, definition 23Push Button 39

Index 199

Page 210: Stingray 2006.2 Objective Grid ActiveX UserGuide

200 Obj

RRadio Button 39Radio Button, 3D Effect 40range

definition 9Range object 113range objects 125ranges, creating 126ranges, initializing 127recordset 74registering a component 111registration failing 177

Ssample

AdoQuery 102CAB,troubleshooting 106Formula 103Gridapp 103Internet 102ODBC 104Preview 105Tab 57TabBase 105

scrollbars, activate and de-activate 56SetCells() 125SetCols 127SetCols() 125SetControl method 39SetIncludeInterior() 118SetIncludeSize 131SetInterior() 117, 118SetRows 127SetRows() 125SetScrollBarMode 56SetSize 131SetStyleRange() 120, 125SetTable() 125Solution Services Group 10sorting columns 61Static text control 39

Structured Exception Handling. 187style

architecture 120definition 9object 120

Style object 113creation 118

style objects 117–120style properties,setting 118System Data Source 71System DSN 64

Tterms,common 8Trouble shooting 177

UUndo/Redo 135Unicode 181unresolved externals 177

VVC.NET 4, 181VerticalSorting 61virtual functions 124virtual mode 122Visual Studio.NET 4

WWindows (MFC Style) Combobox 41Windows (MFC Style) Drop Down

List 41Windows XP 5

visual styles 5workbook

definition 10worksheet

definition 10wrapper class, generating 167

ective Grid for ActiveX User’s Guide

Page 211: Stingray 2006.2 Objective Grid ActiveX UserGuide

Index 201

Page 212: Stingray 2006.2 Objective Grid ActiveX UserGuide

Index 202


Recommended