Oracle AppWizard for Microsoft Visual C++
Release 8.1.5 for Windows NT
A67160-01

Library

Product

Contents

Index

PrevNext

4
Tutorial

This chapter walks you through the creation and customization of an application generated by Oracle AppWizard for Microsoft Visual C++. All of the customization lessons presented in this tutorial are based on information described in Chapter 3, "Understanding Your Application's Code." The tutorial introduces each lesson with an explanation of what you will have learned after you complete it.

By working through all the lessons of this tutorial, you will have mastered how to create and customize an Oracle AppWizard starter application. This chapter is organized as follows:

Introduction

A store owner must keep accurate records of all customers and their purchases. And a database application is perfect for this job.

In this tutorial, you will develop a custom purchase order application for Nicole's Sporting Goods called "Order." This business must track information about sales orders, the items sold, and to which of the store's customers. You will create and examine the structure of the database tables, then create and customize the application to manage that information. The application you develop will allow Nicole and her employees to create, update, and view purchase orders for her sporting goods store.

Each main section of the tutorial corresponds to a version number for Order, with each successive lesson building on what was learned in the last one. When you finish working through the final lesson, you will have programmed a completely customized purchase order system for Nichole's Sporting Goods.

You may access the files for the tutorial in the following location:

 
ORACLE_HOME\APPWIZARD\VC++\TUTORIAL\ORDER[1-5]

These files show you what you should have built by the end of each lesson. The Order1 file corresponds to Lesson 1, Order2 corresponds to Lesson 2, and so on. Therefore, to see the set of completed files for Lesson 1, access:

ORACLE_HOME\APPWIZARD\VC++\TUTORIAL\ORDER1

 

Before You Start

Before you can create any application, you must set up your database tables, so that the application has information to process. Because Nicole needs to keep track of information about sales orders, the items sold, the store's customers, and the products sold, you must structure the tables to reflect those needs.

To create this purchase order system, you must set up the following database tables to interact with each other:

If you need to create the user DEMO and the above tables, search for DEMO.SAL in the %ORACLE_HOME%\RDBMS\ADMIN directory and execute it within Server Manager or SQL*Plus. The DEMO.SAL file will create user DEMO and will call the SQL script BDEMOBLD.SQL to create the above tables for you.

The following illustrates the data models for the tables you will construct.

Sales_Order table:
   Name                            Null?    Type
   ------------------------------- -------- ----
   ORDER_ID                        NOT NULL NUMBER(4)
   ORDER_DATE                               DATE
   CUSTOMER_ID                              NUMBER(6)
   SHIP_DATE                                DATE
   TOTAL                                    NUMBER(8,2)


Item table:

   Name                            Null?    Type
   ------------------------------- -------- ----
   ORDER_ID                        NOT NULL NUMBER(4)
   ITEM_ID                         NOT NULL NUMBER(4)
   PRODUCT_ID                               NUMBER(6)
   ACTUAL_PRICE                             NUMBER(8,2)
   QUANTITY                                 NUMBER(8)
   TOTAL                                    NUMBER(8,2)
Customer table:
   Name                            Null?    Type
   ------------------------------- -------- ----
   CUSTOMER_ID                     NOT NULL NUMBER(6)
   NAME                                     VARCHAR2(45)
   ADDRESS                                  VARCHAR2(40)
   CITY                                     VARCHAR2(30)
   STATE                                    VARCHAR2(2)
   ZIP_CODE                                 VARCHAR2(9)
   AREA_CODE                                NUMBER(3)
   PHONE_NUMBER                             NUMBER(7)
   SALESPERSON_ID                           NUMBER(4)
   CREDIT_LIMIT                             NUMBER(9,2)
   COMMENTS                                 LONG
Product table:
   Name                            Null?    Type
   ------------------------------- -------- ----
   PRODUCT_ID                      NOT NULL NUMBER(6)
   DESCRIPTION                              VARCHAR2(30)

Lesson 1: Creating the Starter Application

In Lesson 1, you form the basis of the purchase order application for Nicole's Sporting Goods. In this lesson, you learn how to quickly complete a starter application as explained in Chapter 2, "Creating a Starter Application." The application you create using Oracle AppWizard for Microsoft Visual C++ is then ready for customization.

When you are finished with this section of the tutorial, you will understand how to use Oracle AppWizard for Microsoft Visual C++ to create a starter application.

Lesson 1 consists of the following parts:


 

Part 1: Working with Oracle AppWizard for Microsoft Visual C++

Starting the Oracle AppWizard for Microsoft Visual C++

  1. Start Microsoft Visual C++.
  2. Choose New from the File menu.

  3. The New dialog box appears.
  4. Click the Projects tab.
  5. Select Oracle AppWizard for MFC (exe) from the list of project types.
  6. Type the path for where you want to locate the application.
  7. Type "Order" in the Project Name box. This is the name of the application that you will create.

  8. Make sure that "Create New Workspace" is selected.
  9. Click OK.

  10. Oracle AppWizard for Microsoft Visual C++ starts.

 

Welcome

The Welcome window welcomes you to the Oracle AppWizard.
Click Next to continue.
 

Connecting to the Oracle Database

  1. Type DEMO in the User Name box.
  2. Type DEMO in the Password box.
  3. If connecting to a remote database, type the database alias in the Database Alias box.
  4. When you are done, click Next.


 

Naming and Specifying the Type of Form

  1. Type the name of the form: Order.
  2. Select Master-Detail Display Form.
  3. Click the Add, Change, and Delete checkboxes.
  4. Click Next.


 

Selecting Master Tables and Columns

From ORACLE DB/Users/DEMO:

  1. Select the SALES_ORDER table. This will be the master table.

  2. By default, all columns under SALES_ORDER are selected.
  3. Accept the default and click Next.


 

Selecting Detail Tables and Columns

From ORACLE DB/Users/DEMO:

  1. Select the ITEM table from the list. This will be the detail table.

  2. By default, all columns under ITEM are selected.
  3. Accept the default and click Next.

 


 

Building Join Clauses Between Tables

The next window displays the columns from the master and the detail tables you have selected and the default join clause that Oracle AppWizard has created. Oracle AppWizard creates the default join it bases on the primary and foreign keys of the master and detail tables.

In our example, Oracle AppWizard has created a default join, based on the primary and foreign keys:

Sales.Order.Order_ID joined with Item.Order_ID

 
 
  1. Click Next to use the default join.

  2. Oracle AppWizard prompts you: 
      Would you like to create another form?
  3. Click No.

 

Specifying the Application Type and User Language

In the next window:

  1. Select Single document interface.
  2. Accept the current default language. In this tutorial, we use English [United States].
  3. Click Next.

 
 
 

Completing the Remaining Steps

  1. Accept the default options for the remaining steps by clicking Next on each window. You can also click Finish and Oracle AppWizard will accept the defaults for you.
  2. In the last window, the Next button is disabled, as shown in the following diagram.
In this window, Oracle AppWizard displays the classes it will create for your application.
  1. Click Finish to allow Oracle AppWizard to create the starter application.

  2. The New Project Information window appears. This window shows you the specifications that Oracle AppWizard used to create the Order application.
  3. Examine the information in the New Project Information window for accuracy.
  4. When done, click OK.

  5.  

 
 

Oracle AppWizard for Microsoft Visual C++ creates the source, header, and resource files for your Order application and takes you automatically to the Microsoft Developer Studio with Workspace "Order" open.


 

Part 2: Exploring Generated Classes and Files

Now that you have created the Order application using Oracle AppWizard for Microsoft Visual C++, you can customize it to better suit your needs. In order to be able to customize this application, you need know about the classes and files it has created for this purpose, illustrated in Table 4-1, "Files and classes created for the "Order" application by Oracle AppWizard".

Table 4-1 Files and classes created for the "Order" application by Oracle AppWizard

Files Class Description Derived From...

AboutDlg.cpp
AboutDlg.h 

CAboutDlg 

dialog class for About Order
dialog box 

CDialog 

ConnDialog.cpp
ConnDialog.h 

CConnDialog 

dialog class for Connect to Oracle dialog box 

CDialog 

MainFrame.cpp
MainFrame.h 

CMainFrame 

frame window class 

CFrameWnd 

ORADC.cpp
ORADC.h 

CORADC 

data control class 

CWnd 

OrderApp.cpp
OrderApp.h 

COrderApp 

application class 

CWinApp 

OrderDynasetDetail.cpp
OrderDynasetDetail.h 

COrderDynasetDetail 

dynaset class for Sales Order table 

ODynaset 

OrderDynasetMaster.cpp
OrderDynasetMaster.h 

COrderDynasetMaster 

dynaset class for Item table 

ODynaset 

OrderView.cpp
OrderView.h 

COrderView 

form view class 

CFormView 

OrderDoc.cpp
OrderDoc.h 

COrderDoc 

document class 

CDocument 

OrderUtil.cpp
OrderUtil.h 

Not applicable 

stand alone functions:
Process OO4OError(), DDX_Field Text(), ... 

 

Part 3: Viewing the ReadMe.txt for the Generated Project

Oracle AppWizard creates a ReadMe.txt file for the generated Order project. This ReadMe.txt file describes the source, header, and resource files that Oracle AppWizard has created.

To view the contents of the ReadMe.txt file:

  1. Select FileView.
  2. In the Workspace of the dialog box, click the name of your project, Order, to open it.
  3. Click the ReadMe.txt file to open it.

  4.  

The following illustration shows what the ReadMe.txt file for Order should look like.
 
 

Part 4: Building and Running the Application

In this section you use Microsoft Developer Studio to build and run the executable files Oracle AppWizard for Microsoft Visual C++ has created.

To build the application:

To run the application:

  1. Choose Execute Order.exe from the Build menu.

  2. The Connect to Oracle dialog box appears.

 
  1. Type DEMO in the User Name box and DEMO in the Password box. If connecting to a remote database, type the database alias in the Database Alias box.
  2. Click Connect.

  3. The Order application appears.


 

Notice and try using the following features:

Lesson 2: Adding Customer Information to a Purchase Order

In this first customization task, you learn how to add specific detailed information about customers which should appear on any purchase order for the Order application. To accomplish this task, complete the following parts of this lesson:

To see the set of completed files for Lesson 2, access:

ORACLE_HOME\APPWIZARD\VC++\TUTORIAL\ORDER2

Note: Some parts of this lesson require you to add or
modify code in the application. The code that must be added or modified is in bold print.

 
 

Part 1: Creating a Dynaset Class for the Customer Table

To display customer information on your purchase order form for an active order, you must first create an ODynaset class to represent the CUSTOMER table. To do this, create a new generic class called COrderCustomerDynaset, which is derived from the ODynaset class.

The ODynaset class is a class in Oracle Objects for OLE C++ class library. It creates, manages, and accesses records of data from the database.

To create a dynaset for the CUSTOMER table:

  1. In Class view of Microsoft Developer Studio, right-click Order class and select New Class.
  2. The New Class dialog box appears.
  3. From the Class Type list, select Generic Class.
  4. Under Class Information, type the following in the Name text box:
    1. COrderDynasetCustomer
  5. In the Base Class(es) list, type the following under the column heading Derived From:
    1. ODynaset
  6. Accept the default entry, "public" under the As column heading.

  7. This is how the New Class dialog box should look before you click OK.


  1. Click OK.

  2. Microsoft Developer Studio displays the following message:
      The New Class Wizard could not find the appropriate header file(s) to include for the base class(es) ODynaset...
  3. Click OK.
This message occurs because the definition of the ODynaset class is not included in the generated file. Therefore, you must manually include the header file that defines the ODynaset class, ORACL.H in the OrderDynaSetCustomer.h file. You can locate the header file in
ORACLE_HOME\0040\cpp\include
a ORACLE_HOME\0040\cpp\include
Oracle AppWizard generates both an OrderDynasetCustomer.cpp and an OrderDynasetCustomer.h file for the COrderDynasetCustomer class with the following contents:
The OrderDynasetCustomer.h file contains:
   //OrderDynasetCustomer.h: interface for the COrderDynasetCustomer Class//
   //////////////////////////////////////////////////////////
   class COrderDynasetCustomer : public ODynaset
   {
   public:
   COrderDynasetCustomer();
   };
   
The OrderDynasetCustomer.cpp file contains:
   //OrderDynasetCustomer.cpp: implmentation of the COrderDynasetCustomer class.
   //
   //////////////////////////////////////////////////////////
   #include "stdafcx.h"
   #include "Order.h"
   #include "OrderDynasetCustomer.h"
   COrderDynasetCustomer:COrderDynasetCustomer()
   {
   
   }
   COrderDynasetCustomer:~COrderDynasetCustomer()
   {
   
   }

Adding Member Variables to the COrderDynasetCustomer Class

COrderDynasetCustomer class is derived from the ODynaset class. This class will contain member variables that store information about a SQL statement to query the database. This class will also store information to represent columns in the USER.DEMO.CUSTOMER table. These are shown in Table 4-2, " COrderDynasetCustomer Data Members".

Table 4-2 COrderDynasetCustomer Data Members
Member Variables Type Type Description

m_strSQLQuery 

CString 

Query to be sent to the database 

m_strSQLSelect 

CString 

Select clause of the SQL statement 

m_strSQLFilter 

CString 

Where clause of the SQL statement 

m_strSQLSort 

CString 

Order clause of the SQL statement 

m_Column1 

OField 

CUSTOMER_ID column of CUSTOMER table 

m_NAME 

OField 

NAME column of CUSTOMER table 

m_ADDRESS 

OField 

ADDRESS column of CUSTOMER table 

m_CITY 

OField 

CITY column of CUSTOMER table 

m_STATE 

OField 

STATE column of CUSTOMER table 

m_ZIP_CODE 

OField 

ZIP column of CUSTOMER table 

m_AREA_CODE; 

OField 

AREA_CODE column of CUSTOMER table 

m_PHONE_NUMBER 

OField 

TELEPHONE_NUMBER column of CUSTOMER table 

m_SALESPERSON_ID 

OField 

SALESPERSON_ID column of CUSTOMER table 

m_CREDIT_LIMIT 

OField 

CREDIT_LIMIT column of CUSTOMER table 

m_COMMENTS 

OField 

COMMENTS column of CUSTOMER table 


 

To add member variables for the COrderDynasetCustomer class, enter the following code in the COrderDynasetCustomer.h file:

class COrderDynasetCustomer : public ODynaset
{
...
public:
 
 

COrderDynasetCustomer();
virtual ~COrderDynasetCustomer();
 


public:
// strings needed for creating the queries
 
 

CString m_strSQLQuery;  // the query to be sent to the database
CString m_strSQLSelect; // the select portion
CString m_strSQLFilter; // the where portion
CString m_strSQLSort;   // the order by portion

 

// Field/Param Data
 
 

OField m_CUSTOMER_ID;
OField m_NAME;
OField m_ADDRESS;
OField m_CITY;
OField m_STATE;
OField m_ZIP_CODE;
OField m_AREA_CODE;
OField m_PHONE_NUMBER;
OField m_SALESPERSON_ID;
OField m_CREDIT_LIMIT;
OField m_COMMENTS;
 

...
};


Adding Member Functions and Implementation Details to the COrderDynasetCustomer Class

Adding the member functions shown in Table 4-3, "COrderDynaset Customer Member Functions" to the COrderDynaset customer class will allow you to create a query statement, have the database process it, then retrieve and store information.

Table 4-3 COrderDynaset Customer Member Functions

Member Functions Descriptions

OpenQuery 

Starts a query and retrieves the information from the database. 

CreateSQLSelect 

Creates the default query (SELECT) statement. 

AddFilter 

Adds a condition to the query statement. 

ResetToDefaultFilter 

Resets the condition clause for the query. 

RefreshQuery 

Refreshes the query to be executed. 

To declare member functions for the COrderDynasetCustomer class, add the following code to the OrderDynasetCustomer.h file:

      class COrderDynasetCustomer : public ODynaset
{
      
      ...
      
      public:
      
      
      COrderDynasetCustomer();
      virtual ~COrderDynasetCustomer();
      
      
      
      
      // Operations
      public:
      void OpenQuery(ODatabase theDB);
      void CreateSQLSelect();
      void AddFilter(CString strFilter);
      void ResetToDefaultFilter();
      void RefreshQuery();
      ...
      
      
      };
      
 
To initialize the value in the member variables, add the following code to the constructor method of COrderDynasetCustomer Class in the OrderDynasetCustomer.cpp file:
 
COrderDynasetCustomer::COrderDynasetCustomer()
{
 

m_strSQLQuery.Empty();
m_strSQLSelect.Empty();
m_strSQLFilter.Empty();
m_strSQLSort.Empty();
 


 

// Create the default select clause of the
 

statement m_strSQLSelect
 


  CreateSQLSelect();
 

}

To create the default SQL statement, enter the following code in COrderDynasetCustomer class::CreateSQLSelect() method in the OrderCustomer.cpp file:
// Creates the default select
      void COrderDynasetCustomer::CreateSQLSelect()
      
      
      {
      
      
      m_strSQLSelect = "select CUSTOMER_ID, NAME, 
          ADDRESS, CITY, STATE, \
          ZIP_CODE, AREA_CODE, PHONE_NUMBER, \
          SALESPERSON_ID, CREDIT_LIMIT, COMMENTS \
          from DEMO.CUSTOMER";
      
      
      }
 
To create a query statement, to process the query, and to retrieve information from the database, enter the following code to the COrderDynasetCustomer class::OpenQuery() method in the OrderCustomer.cpp file:
      // opens the query
      void COrderDynasetCustomer::OpenQuery(ODatabase theDB)
      {
      
      
      oresult dbresult;
      // create a query statement
      
      
      m_strSQLQuery = m_strSQLSelect;
      if (m_strSQLFilter)
            m_strSQLQuery += m_strSQLFilter;
      if (m_strSQLSort)
            m_strSQLQuery += m_strSQLSort;
      
      
      
            // query the database
      
      
      dbresult = Open(theDB, m_strSQLQuery);
      
      
      
            // retreive/store information from the database
      
      
      m_CUSTOMER_ID = GetField("CUSTOMER_ID");
      m_NAME = GetField("NAME");
      m_ADDRESS = GetField("ADDRESS");
      m_CITY = GetField("CITY");
      m_STATE = GetField("STATE");
      m_ZIP_CODE = GetField("ZIP_CODE");
      m_AREA_CODE = GetField("AREA_CODE");
      m_PHONE_NUMBER = GetField("PHONE_NUMBER");
      m_SALESPERSON_ID = GetField("SALESPERSON_ID");
      m_CREDIT_LIMIT = GetField("CREDIT_LIMIT");
      m_COMMENTS = GetField("COMMENTS");
      
      
      
            // display the first record from the Customer table
      
      
      dbresult = MoveFirst();
      
      
      }
      
 
To add a conditional clause for the query, enter the following code to the COrderDynasetCustomer class::AddFilter() method in the OrderCustomer.cpp file:
      // adds a condition to the where clause
      
      
      void COrderDynasetCustomer::AddFilter(CString strFilter)
      {
      
      
      m_strSQLFilter += m_strSQLFilter.IsEmpty() ? " 
          WHERE " : " AND ";
      m_strSQLFilter += strFilter;
      
      
      }
 
To reset the conditional clause for the query, enter the following code to the COrderDynasetCustomer class::ResetToDefaultFilter() method in the OrderCustomer.cpp file:
      // resets the filter to the default value
      void COrderDynasetCustomer::ResetToDefaultFilter()
      {
      
      
        m_strSQLFilter.Empty();
      
      
      }
      
To refresh the query to be executed, add the following code to COrderDynasetCustomer class::RefreshQuery() method in the OrderCustomer.cpp file:
      void COrderDynasetCustomer::RefreshQuery()
      {
      
      
      oresult dbresult;
      
      
      
    // create a query statement
      
      
      m_strSQLQuery = m_strSQLSelect;
      if (m_strSQLFilter)
          m_strSQLQuery += m_strSQLFilter;
      if (m_strSQLSort)
          m_strSQLQuery += m_strSQLSort;
      
      
      // set the query statement to be used
      
      
      dbresult = SetSQL(m_strSQLQuery);
      dbresult = Refresh();
      
      
      }

Part 2: Adding Customer Information to a Purchase Order

To display customer information for a purchase order, add the customer dynaset to the COrderView class and COrderDoc class.
 

Add a member variable called m_pDynasetCustomer in COrderView class. This member variable is a pointer to the type COrderCustomerDynaset class.

      class COrderView : public CFormView
      {
      
      
      ...    
      COrderDynasetMaster *m_pDynasetMaster;
      COrderDynasetDetail *m_pDynasetDetail;
      COrderDynasetCustomer *m_pDynasetCustomer;
      ...
      
      
      }
      
Initialize the variable, m_pDynasetCustomer, to NULL in the constructor method of COrderView class.
      COrderView::COrderView()
      
      
      : CFormView(COrderView::IDD)
      
      
      {
      
      
      ...
      m_pDynasetMaster = NULL;
      m_pDynasetDetail = NULL;
      m_pDynasetCustomer = NULL;
      ...
      
      
      }
      
 
Add a member variable called m_OrderDynasetCustomer in the COrderDoc class. This is an object of COrderCustomerDynaset class.
 class COrderDoc : public CDocument
 {
      
      
      ...
      COrderDynasetMaster m_OrderDynasetMaster;
      COrderDynasetDetail m_OrderDynasetDetail;
      COrderDynasetCustomer m_OrderDynasetCustomer;
      ...
      
      
      }
      
Include the header file, OrderDynaserCustomer.h, in Order.cpp, OrderDoc.h, and OrderView.h to define the COrderDynasetCustomer class.

 
 

Part 3: Displaying Customer Information for a Purchase Order

This section demonstrates how to display customer information for each purchase order.

Add 10 edit controls to display customer information in the IDD_ORDER_FORM dialog box with the Control IDs shown in Table 4-4, "Mapping edit control IDs to OField member variables in the COrderDynasetCustomer class".

Table 4-4 Mapping edit control IDs to OField member variables in the COrderDynasetCustomer class

Control ID Member Variables for COrderDynasetCustomer Class

IDC_CUST_NAME 

m_NAME 

IDC_CUST_ADDRESS 

m_ADDRESS 

IDC_CUST_CITY 

m_CITY 

IDC_CUST_STATE 

m_STATE 

IDC_CUST_ZIP_CODE 

m_ZIP_CODE 

IDC_CUST_AREA_CODE 

m_AREA_CODE 

IDC_CUST_PHONE_NUMBER 

m_PHONE_NUMBER 

IDC_CUST_SALESPERSON_ID 

m_SALESPERSON_ID 

IDC_CUST_CREDIT_LIMIT 

m_CREDIT_LIMIT 

IDC_CUST_COMMENTS 

m_COMMENTS 

After you add these edit controls, the IDD_ORDER_FORM dialog box will appear similar to this one shown below. This illustration serves only as a sample. Yours may look slightly different.
 


 
 

To bind these edit controls with the OField members in the COrderDynasetCustomer class, call the DDX_FieldText() method for each customer edit control in the COrderView class::DoDataExchange() method. The OField members represent the columns in the Customer table. Bind this with an OField member variable of the COrderDynasetCustomer class, as shown in Table 4-4, "Mapping edit control IDs to OField member variables in the COrderDynasetCustomer class".

For example, when you use DDX_FieldText() to bind the edit control
IDC_CUST_NAME with the m_NAME member variable of COrderDynasetCustomer class, it appears as follows:

   DDX_FieldText(pDX, IDC_CUST_NAME, m_pDynasetCustomer->m_Name, 
   
   
   m_pDynasetCustomer);
   
   
   where m_pDynasetCustomer is a member variable in COrderView class
   
To bind the customer edit controls with the OField members in the COrderDyaset Customer class, enter the following code in COrderView:DoData Exchange in the OrderView.app file.
   void COrderView::DoDataExchange(CDataExchange* pDX)
   {
   
   ...
   CFormView::DoDataExchange(pDX);
   ...
   // for customer dynaset
   DDX_FieldText(pDX, IDC_CUST_NAME, 
   
   m_pDynasetCustomer->m_NAME, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_ADDRESS, 
   
   m_pDynasetCustomer->m_ADDRESS, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_CITY, m_pDynasetCustomer->m_CITY, 
   
   m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_STATE,
   
   m_pDynasetCustomer->m_STATE, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_ZIP_CODE, 
   
   m_pDynasetCustomer->m_ZIP_CODE, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_AREA_CODE,
   
   m_pDynasetCustomer->m_AREA_CODE, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_PHONE_NUMBER,
   
   m_pDynasetCustomer->m_PHONE_NUMBER, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_CREDIT_LIMIT, 
   
   m_pDynasetCustomer->m_CREDIT_LIMIT, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_SALESPERSON_ID,
   
   m_pDynasetCustomer->m_SALESPERSON_ID, m_pDynasetCustomer);
   
   DDX_FieldText(pDX, IDC_CUST_COMMENTS, 
   
   m_pDynasetCustomer->m_COMMENTS, m_pDynasetCustomer);
   
   ...
   
   
   }
   
To initialize the customer dynaset when the view is attached to the document, add the following code to COrderView::OnInitialUpdate() method in OrderView.cpp.
   void COrderView::OnInitialUpdate()
   {
   
   
   CString strJoin;
   ...
   m_pDynasetMaster = &GetDocument()->m_OrderDynasetMaster;
   m_pDynasetDetail = &GetDocument()->m_OrderDynasetDetail;
   m_pDynasetCustomer = &GetDocument()->m_OrderDynasetCustomer;
   
      m_pDynasetMaster->OpenQuery(GetDocument()->m_database);
   
   
   }
   
In order to retrieve customer information for a purchase order, you must next perform a join operation between the CUSTOMER_ID column of the SALES_ORDER table and the CUSTOMER_ID column of the ITEM table.
// create a join based on CUSTOMER_ID 
   // between the Customer table and 
   // the Sales.Order table. 
   m_pDynasetCustomer->ResetToDefaultFilter();
   strJoin = "CUSTOMER_ID = " + 
   
   
   (CString)m_pDynasetMaster->m_Column1;
   
   
   m_pDynasetCustomer->AddFilter(strJoin);
   // create, process the query
   m_pDynasetCustomer->OpenQuery(GetDocument()->m_database);
   ...
   
   
   CFormView::OnInitialUpdate();
   
   
   m_dataControl.SetRecordset((LPDISPATCH)(m_pDynasetDetail->Internal()));
   ...
   }
   
To update the customer dynaset after a move operation has been performed, enter the following code to the PerformMove() method of the COrderView class in OrderView.h.
   void COrderView::PerformMove(int nCommand)
   
   {
   
   ...
   // Update Customer information
   m_pDynasetCustomer->ResetToDefaultFilter();
   strJoin = "CUSTOMER_ID = " + 
   
   (CString)m_pDynasetMaster->m_Column1;
   
   
   
   
   
   m_pDynasetCustomer->AddFilter(strJoin);
   m_pDynasetCustomer->RefreshQuery();
   
      UpdateData(FALSE);
   }
   
Build and run the application. This is how the application should look when you are done:

 

Lesson 3: Enabling Users to Add Products to a Purchase Order

Nicole's employees need to be able to add products to a purchase order. Therefore, Lesson 3 demonstrates how to customize your application to do the following:

Lesson 3 contains the following parts:

To see the set of completed files for Lesson 3, access:

ORACLE_HOME\APPWIZARD\VC++\TUTORIAL\ORDER3

Note: Some parts of this lesson require you to add or
modify code in the application. The code that must be added or modified is in bold print.:

 

Part 1: Displaying a List of Items from the PRODUCT Table

Nicole's Sporting Goods carries a wide variety of products. Many of them, however, have similar names and descriptions. To insure data integrity, it's best to display a list of the product items in the purchase order application window. This will allow Nicole's employees to select the items that customers have purchased from the list.

In this part, you will add a list box that displays the available products in the IDD_ORDER_FORM dialog box.

  1. Add a list box with a control ID = IDC_PRODUCTLIST that allows multiple selections. This enables users to select multiple purchased items, which can then be added to a purchase order, all at one time.
  2. Create a member variable, m_prodList, for the list box in COrderView class.
  3. The variable m_prodList is a control handler of type CListBox. It is used to store the list of product items from the PRODUCT table.
  4. To display a list of available products from the PRODUCT table in the list box, add the following code to COrderView::OnInitialUpdate() method of in the OrderView.cpp file:
  5.       void COrderView::OnInitialUpdate()
          {
          
          
          ...
          CFormView::OnInitialUpdate()
          
          
          ...
          
          // Put list of sales items into the listbox
          ODynaset oProdList;
          oProdList.Open(GetDocument()->m_database, 
               "SELECT PRODUCT_ID,
               FROM DEMO.PRODUCT ORDER BY PRODUCT_ID");
          int index = 0;
          while (!oProdList.IsEOF())
          
          
          {
          
          
             m_prodList.InsertString(index,   
                 (CString)oProdList.GetField(0) + " - " + 
                  oProdList.GetField(1));
          
          
          
                
          
          m_prodList.SetItemData(index,     
                 (long)oProdList.GetField(0));
          oProdList.MoveNext();
          index++;
          
          
          }
          
          
          }

Part 2: Adding the Selected Products to the Purchase Order

When Nicole's employees add a purchased item from the product list box to a purchase order, a new record for the purchased item will be inserted into the ITEM table. Nicole would like the TOTAL column in the SALES_ORDER table to be re-calculated to reflect the amount added from the purchased item to the purchase order. Content in the detail table control and the master table control should also be updated accordingly.

To have the TOTAL column in the SALES_ORDER table updated when a purchased item is added to a purchase order, the SALES_ORDER table should be updated. To allow the updating of the SALES_ORDER table, remove the third parameter, ODYNASET_READONLY, from the Open() function call in the COrderDynasetMaster::OpenQuery() method.

Change:
      dbresult = Open(theDB, m_strSQLQuery, ODYNASET_READONLY);
To:
      dbresult = Open(theDB, m_strSQLQuery);
      
      
      
In the IDD_ORDER_FORM dialog, create a button that handles the event of adding a purchase item. The button should have the following properties:

Table 4-5 Button Properties

Button Control ID Button Caption Event Event Handler Function

IDC_ADDITEMS 

Add to Order 

BN_Clicked 

OnAdditems 


 

To process the updates in the SALES _ORDER table, the ITEM table, the master table controls, and the detail table control when purchase items are added to a purchase order, enter the following code to COrderView::OnAddItems() method in the OrderView.cpp file:

 
      void COrderView::OnAdditems() 
      {
      
      
      int *pAddIndices;
      int nSelCount;
      oresult r;
      nSelCount = m_prodList.GetSelCount();
      pAddIndices = new int[nSelCount];
      m_prodList.GetSelItems(nSelCount, pAddIndices);
      for (int i = 0; i < nSelCount; i++)
      {
      
      
      char szProdID[8];
      char szItemID[8];
      itoa(m_prodList.GetItemData(pAddIndices[i]), szProdID,        
           10);
      itoa(m_pDynasetDetail->GetRecordCount() + 1, szItemID, 
           10);
      CString strInsert = "INSERT INTO DEMO.ITEM (ORDER_ID, 
           PRODUCT_ID, ITEM_ID, QUANTITY, 
           ACTUAL_PRICE, TOTAL) SELECT " +
             CString)m_pDynasetMaster->m_Column3 + ", " 
           + szProdID +", " + szItemID +
             ", 1, LIST_PRICE, LIST_PRICE FROM            
           DEMO.PRICE WHERE PRODUCT_ID = " +
           szProdID + " AND ((SYSDATE BETWEEN 
           START_DATE AND END_DATE) OR " +
         "(SYSDATE > START_DATE AND END_DATE IS NULL))";
      r = GetDocument()->m_database.ExecuteSQL(strInsert);
      if (r == OFAILURE)
      ProcessOO4OError(&GetDocument()->m_database);
      m_pDynasetDetail->Refresh();
      
      
      }
      TotalOrder();
      m_prodList.SelItemRange(FALSE, 0, m_prodList.GetCount());
      delete pAddIndices;
      }
The function TotalOrder() is being called in COrderView::OnAdditems() method. It is a member function for COrderView class. It re-calculates the total amount for a purchase order and updates the TOTAL column in the SALES_ORDER table.
 
 

To declare TotalOrder() in COrderView class, enter the following code in COrderView class in the OrderView.h file:

      public:
     void TotalOrder();
     
Add the following code to COrderView::TotalOrder() method in the OrderView.cpp file:
      void COrderView::TotalOrder()
      {
      
      
      ODynaset oTotal;
      OTotal.Open(GetDocument()->m_database, "SELECT SUM(TOTAL) FROM 
      
      
      DEMO.ITEM WHERE ORDER_ID = " +
      (CString)m_pDynasetMaster->m_Column3);
      
      
      m_pDynasetMaster->StartEdit();
      m_pDynasetMaster->
      
      
      m_Column5.SetValue((double)oTotal.GetField(0));
      
      
      m_pDynasetMaster->Update();
      UpdateData(FALSE);

   }
Build and run the application. The application will look similar to the one below.
 


 

Lesson 4: Enabling Users to Update a Purchase Order

This section allows you to make changes in the detail table control for the Order application. When the value in the QUANTITY column or the ACTUAL_PRICE column in the detail table changes, the application should update the appropriate changes to the ITEM table, the SALES_ORDER table, the content in the master detail controls and the detail table control accordingly.

This section consists of the following parts:

To see the set of completed files for Lesson 4, access:

ORACLE_HOME\APPWIZARD\VC++\TUTORIAL\ORDER4

Note: Some parts of this lesson require you to add or modify code in the application. The code that must be added or modified is in bold print.

 

Part 1: Allowing the Detail Table Control to Handle "AfterColUpdate", "AfterUpdate" and "AfterDelete" Events

Modify the detail table control (ID = IDC_DATAGRID) in the IDD_ORDER_FORM Dialog that handles event types with specified event handler functions. These functions and handlers are listed in Table 4-6, " Mapping event type to event handler function for the detail table control".

Table 4-6 Mapping event type to event handler function for the detail table control
Event Type Event Handler

AfterColUpdate 

OnAfterColUpdateDatagrid 

AfterUpdate 

OnAfterUpdateDatagrid 

AfterDelete 

OnAfterDeleteDatagrid 

Create a member variable, m_datagrid, for the detail table control in COrderView class. The variable, m_datagrid, is a control handler of type CMsDgridCtrl. It represents the detail table and allows for update or retrieve data.
 

Part 2: Adding Implementation Details to the Event Handler Function

When the Actual Price or the Quantity sold for a purchased item has been changed, the total price for this item should change. To have the application do this, additions must be made to the code.

To update the TOTAL column for the detail table control when the ACTUAL_PRICE column or the QUANTITY column in the detail table control changes, add the following code to COrderView::OnAfterColUpdateDatagrid() method in the OrderView.cpp file:

 
      // recalcuates the TOTAL column in the detail table when the value
      // in the ACTUAL_PRICE or QUANTITY column changes
      void COrderView::OnAfterColUpdateDatagrid(short ColIndex) 
      {
      
      
        if (ColIndex == 4 || ColIndex == 0)
        {
      
      
                CString strText = m_datagrid.GetText();
                CString strTotal;
                char *stopString;
                char szTotal[15];
                long quantity;
                double price;
      
                      // QUANTITY column is updated
                if (ColIndex == 4)
                {
                  quantity = strtol(strText, &stopString, 10);
                  m_datagrid.SetCol(0);
                  strText = m_datagrid.GetText();
                  price = strtod(strText, &stopString);
                  m_datagrid.SetCol(4);
                }
                else // PRICE column is updated
                {
                  price = strtod(strText, &stopString);
                  m_datagrid.SetCol(4);
                  strText = m_datagrid.GetText();
                  quantity = strtol(strText, &stopString, 10);
                  m_datagrid.SetCol(0);
                }
      
                      sprintf(szTotal, "%f", quantity * price);
                strTotal = szTotal;
                m_datagrid.SetCol(5);
                m_datagrid.SetText((LPCTSTR)strTotal);
      
      
        }
      
      
      } 
      
To update the TOTAL column for the master table controls when the ACTUAL_PRICE column or the QUANTITY column in the detail table change , add the following codes to the COrderView::OnAfterUpdateDatagrid() method in the OrderView.cpp file:
      void COrderView::OnAfterUpdateDatagrid() 
      {
      
      
      // Calculates the total amount for a purchase order
      TotalOrder();
      
      
      }
       
      
 
To update the TOTAL column for the master table controls when the a record has been deleted from the detail table control, add the following codes to the COrderView::OnAfterDeleteDatagrid() method OrderView.cpp file:
void COrderView::OnAfterDeleteDatagrid()
      {
      
      
      // Calculates the total amount for a purchase order
      TotalOrder();
      
      
      }
      

Lesson 5: Enabling Users to Add, Commit, or Cancel a New Purchase Order

This section shows you how to allow Nicole's employees to create a new purchase order for a customer. When you have completed this last customization, her employees will also be able to commit or cancel the creation of a new purchase order.

This section consists of the following parts:

To see the set of completed files for Lesson 5, access:

ORACLE_HOME\APPWIZARD\VC++\TUTORIAL\ORDER5

Note: Some parts of this lesson require you to add or modify code in the application. The code that must be added or modified is in bold print.

 

Part 1: Creating a Customer List Dialog Box

Many of Nicole's customers have similar names. To ensure that the each customer gets the correct merchandise, the Order application will have a dialog box with a list of customers. Nicole's employees can then pick the appropriate name from the list when they create a new purchase order.

Create a dialog box with control ID = IDD_SELCUSTOMER. Customize the dialog box so that it contains a OK Button, Cancel Button and a List Box with control ID = IDC_CUSTLIST.
The customer list dialog box should look similar to the one shown below. The list box will display a list of customers from the CUSTOMER table.


 

Part 2: Creating a New Class to Handle Events for the Customer Dialog Box

Create a new MFC class, CSelectCustomer, that is derived from CDialog. This class handles events occurring in the customer dialog box.

 

Allow the CSelectCustomer class to handle the events shown in Table 4-7, " CSelectCustomer Class Events".

Table 4-7 CSelectCustomer Class Events
Object ID Event Event Handler Function

CSelectCustomer 

WM_INITDIALOG 

OnInitDialog 

IDOK 

BN_CLICKED 

OnOK 

Create a member variable, m_CustomerList, for the customer list box in CSelectCustomer class. The variable, m_CustomerList, is a control handler of type CListBox. It enables users to select a customer from the customer list box for a purchase order.

To implement the events for the Customer dialog box, add the following member declarations to CSelectCustomer class in SelectCustomer.h file:
 

      public:
      long GetSelection();             // obtain the selected customer from the
                                            // customer list box.
      int DoModal(ODatabase *db);  // involve the customer dialog box
      long m_nSelection;              // nth location of the selected customers 
                                           // in the customer list.
      ODatabase * m_Database;       // the database

 

Include the header file ORACL.H in the SelectCustomer.h file.
 

To display a list of customer in the customer list box, add the following code to CSelectCustomer::OnInitDialog() method in the CSelectCustomer.cpp file:

 
 
      BOOL CSelectCustomer::OnInitDialog() 
      {
      
      
      ...
      CDialog::OnInitDialog();
      ODynaset oCustList;
      int index = 0;
      
            oCustList.Open(*m_pDatabase, "SELECT CUSTOMER_ID, NAME FROM 
      
      
      DEMO.CUSTOMER");
      
      
      while (!oCustList.IsEOF())
      {
      
      
      m_CustomerList.InsertString(index,      
           (CString)oCustList.GetField(0) +  
           " - " + oCustList.GetField(1));
      m_CustomerList.SetItemData(index,
           (long)oCustList.GetField(0));
      oCustList.MoveNext();
      index++;
      
      
      }
      
      
      ...
      }
      
To invoke the customer dialog box, add the following code to CSelectCustomer::DoModal() method in the SelectCustomer.cpp file:
 
      int CSelectCustomer::DoModal(ODatabase *db) 
      {
      
      
      m_pDatabase = db;
      return CDialog::DoModal();
      
      
      }
      
To obtain the selected customer for the new purchase order, add the following code to CSelectCustomer::GetSelection() method in the SelectCustomer.cpp file:
 
      long CSelectCustomer::GetSelection()
      {
      
      
      return(m_nSelection);
      
      
      }
      
To get the selected customer from the customer list box for a new purchase order when the OK button in the customer dialog box is clicked, add the following code to OnOK() method of CSelectCustomer class:
 
      void CSelectCustomer::OnOK() 
      { 
      
      
      // TODO: Add extra validation here 
      int nItem = -1; 
      
      
               
      
      
      nItem = m_CustomerList.GetCurSel(); 
      if (nItem >=0) 
      { 
      
      
      // location of selected customer in the customer list box 
m_nSelection = m_CustomerList.GetItemData(nItem); 
      CDialog::OnOK(); 
      
      
      } 
      else 
      
      
      AfxMessageBox(_T("Please select a customer.\n"), 
          MB_OK, 0); 
      
      
      }

Part 3: Creating "New Order", Commit Order", and "Cancel Order" Buttons

To allow Nicole's employees to easily add, commit, or cancel a new purchase order, create buttons in the IDD_ORDER_FORM dialog that will allow them to perform these operations.
  1. Include the header file, SelectCustomer.h, in the OrderView.h.file. This header file defines CSelectCustomer class that will be used when getting customer information for a new purchase order.
  2. Create the buttons with the following properties shown in Button Control ID and Event Handler Functions in the IDD_ORDER_FORM dialog.


 

Table 4-8 Button Control ID and Event Handler Functions

Button Control ID Button Caption Event Event Handler Function

IDC_NEWORDER 

New Order 

BN_CLICKED 

OnNeworder 

IDC_COMMITORDER 

Commit Order 

BN_CLICKED 

OnCommitorder 

IDC_CANCELORDER 

Cancel Order 

BN_CLICKED 

OnCancelorder 

These event handler functions will be added to the COrderView class when the buttons specify the event handle.
 

Part 4: Enabling Users to Add a New Purchase Order

When a new purchase order is created, a new record will be inserted into the SALES_ORDER table and the ITEM table. Content in the master table controls and detail table control will also be updated to reflect the new purchase order.

To add a new purchase order to the purchase order system, add the following code to COrderView::OnNeworder() method in OrderView.cpp file:

 
      
      #include <SelectCustomer.h> // define CSelectCustomer class 
                                     // to get customer information for 
                                 // a new purchase 
                                 // order
      
            void COrderView::OnNeworder() 
      {
      
      
      CWnd *tempWindow;
      char szCUSTOMER_ID[8];
      OField oORDER_ID;
      CSelectCustomer selectCustomer;
      result dbresult;
      
            if (selectCustomer.DoModal(&GetDocument()->m_database) == 
      
      
      IDCANCEL)
      return;
      
      
      
            
      
      if (GetDocument()->m_database.GetSession().
      
      
      BeginTransaction() == OSUCCESS &&
      m_pDynasetMaster->AddNewRecord() == OSUCCESS)
      
      
      {
      
      
           UpdateData(FALSE);
           tempWindow = GetDlgItem(IDC_Column1);
           itoa(selectCustomer.GetSelection(), 
                szCUSTOMER_ID, 10);
           tempWindow->SetWindowText(szCUSTOMER_ID);
           if (m_pDynasetMaster->GetEditMode() ==  
                ODYNASET_EDIT_NEWRECORD)
           {
      
      
                          ODynaset oSequenceDynaset;
      
                                dbresult = oSequenceDynaset.Open(
                               GetDocument()->m_database, 
                               "SELECT MAX(ORDER_ID) + 1 FROM 
                               DEMO.SALES_ORDER");
                          oORDER_ID = oSequenceDynaset.GetField(0);
                          dbresult = oSequenceDynaset.Close();
                          tempWindow = GetDlgItem(IDC_Column3);
                          tempWindow->SetWindowText
      
      
                     ((CString)oORDER_ID);
      
      
      }
      dbresult = UpdateData();
      if (m_pDynasetMaster->Update() == OFAILURE)
      {
      
      
                    ProcessOO4OError(m_pDynasetMaster);
                    return;
      }
      m_pDynasetMaster->ResetToDefaultFilter();
      m_pDynasetMaster->AddFilter("ORDER_ID = " + 
      (CString)oORDER_ID);
      m_pDynasetMaster->RefreshQuery();
      m_pDynasetCustomer->ResetToDefaultFilter();
      m_pDynasetCustomer->AddFilter("CUSTOMER_ID = " + 
      (CString)m_pDynasetMaster->m_Column1);
      m_pDynasetCustomer->RefreshQuery();
      m_pDynasetDetail->ResetToDefaultFilter();
      m_pDynasetDetail->AddFilter("ORDER_ID = " + 
      (CString)m_pDynasetMaster->m_Column3);
      m_pDynasetDetail->RefreshQuery();
      UpdateData(FALSE);
      
      
      }
      CButton *tempButton = (CButton *)GetDlgItem(IDC_NEWORDER);
      tempButton->EnableWindow(FALSE);
      tempButton = (CButton *)GetDlgItem(IDC_COMMITORDER);
      tempButton->EnableWindow(TRUE);
      tempButton = (CButton *)GetDlgItem(IDC_CANCELORDER);
      tempButton->EnableWindow(TRUE);
      
      
      }

Part 5: Enabling Users to Commit a New Purchase Order

When a new purchase order is created, users must be able to commit or cancel the change that has been made to the purchase order system.

To commit a new purchase order, add the following code to COrderView::OnCommitorder() method in OrderView.cpp file:

 
      void COrderView::OnCommitorder() 
      { 
      
      
      // TODO: Add your control notification handler code here 
      CString strORDER_DATE; 
      CString strSHIP_DATE; 
      CWnd *tempWindow; 
       
      m_pDynasetMaster->StartEdit(); 
      tempWindow = GetDlgItem(IDC_Column2); 
      tempWindow->GetWindowText(strORDER_DATE); 
      tempWindow = GetDlgItem(IDC_Column4); 
      tempWindow->GetWindowText(strSHIP_DATE); 
      m_pDynasetMaster->m_Column2.SetValue(LPCTSTR(strORDER_DATE)); 
      m_pDynasetMaster->m_Column4.SetValue(LPCTSTR(strSHIP_DATE)); 
      m_pDynasetMaster->Update(); 
       
      OSession oSess = GetDocument()->m_database.GetSession(); 
      if (oSess.Commit() == OFAILURE) 
      
      
      
            rocessOO4OError(&oSess); 
      
      
      m_pDynasetMaster->ResetToDefaultFilter(); 
      m_pDynasetMaster->RefreshQuery(); 
      UpdateData(FALSE); 
      OnMoveFirst(); 
      CButton *tempButton = (CButton *)GetDlgItem(IDC_NEWORDER); 
      tempButton->EnableWindow(TRUE); 
      tempButton = (CButton *)GetDlgItem(IDC_COMMITORDER); 
      tempButton->EnableWindow(FALSE); 
      tempButton = (CButton *)GetDlgItem(IDC_CANCELORDER); 
      tempButton->EnableWindow(FALSE); 
      
      
      }


Part 6: Enabling Users to Cancel a New Purchase Order

When a new purchase order created, users must be able to commit or cancel the change that has been made to the purchase order system.

To enable cancelling a new purchase order, add the following code to COrderView::OnCancelorder() method in OrderView.cpp file:


      void COrderView::OnCancelorder() 
      {
      
      
      // TODO: Add your control notification handler code here
      GetDocument()->m_database.GetSession().Rollback();
      m_pDynasetMaster->ResetToDefaultFilter();
      m_pDynasetMaster->RefreshQuery();
      UpdateData(FALSE);
      OnMoveFirst();
      CButton *tempButton = (CButton *)GetDlgItem(IDC_NEWORDER);
      tempButton->EnableWindow(TRUE);
      tempButton = (CButton *)GetDlgItem(IDC_COMMITORDER);
      tempButton->EnableWindow(FALSE);
      tempButton = (CButton *)GetDlgItem(IDC_CANCELORDER);
      tempButton->EnableWindow(FALSE);
      
      
      }
      
 
Build and run the application. It should look similar to the screen shown below.
 


 

Your application is now complete.


Prev Next
Oracle
Copyright © 1999 Oracle Corporation.
All Rights Reserved.
Library Product Contents Index