| Click here to support our advertisers

SOFTWARE FOR SALE
BOOKS FOR SALE
SEARCH CENTRAL
JOB BANK
CLASSIFIEDS
DIRECTORIES
REFERENCE Online Library
LEARNING CENTER
JOURNAL
NEWS CENTRAL
DOWNLOADS
COMMUNITY
CALENDAR
ABOUT US
Journal:
Get the weekly email highlights from the most popular journal for developers! Current issue
> developer.com developerdirect.com htmlgoodies.com javagoodies.com jars.com intranetjournal.com javascripts.com | All Categories : C/C++ vcg09.htm Organizing the Data Behind a Decision-Support Application Specifying the Datasources Determining the Level of Detail Required Maintaining Performance and Data Consistency with Rollups Query Strategies Persistent Versus Impersistent Queries Designing Rollup Queries Implementing Ad Hoc Queries Designing the User Interface Optimizing Application Usability Striving for Simplicity Maintaining Consistency Identifying Toolbar Button Functions Creating and Using Toolbars Obtaining and Modifying Button Bitmaps Using the Image Editor Application to Create Button Bitmaps Generating Bitmaps with Desktop Publishing Packages Displaying Detail Data with the WinWidgets HGrid Control Summary # - 9 - Designing a Decision-Support Application It's likely that your first production-database application that uses Visual C++ will be used for decision-support purposes. Industry sources estimate that decision-support applications constitute 75 percent or more of all of the database applications in use today. Also, decision-support applications are often easy to write and maintain. When you create a decision-support application for use with an existing relational database, you need not be concerned with database design, maintaining referential and domain integrity, or concurrency problems. (You do, however, need to take consistency issues into account if you're summarizing data.) The purpose of a decision-support application is to transform raw data into useful information. Your primary task is to provide the users of your application with a simple, straightforward method of obtaining the data they need. This chapter begins by discussing how to organize the data you're converting to useful information with decision-support applications. It also discusses designing the user interface to make your application easy to understand and provides examples of forms that display information in graphical and tabular format. Finally, this chapter reviews examples of the Visual C++ code needed to create the graph, chart, and grid objects that display selected information to the user. Visual C++ doesn't support these display objects directly, so you will learn about a number of alternative add-in products that may be used for this purpose. ### Organizing the Data Behind a Decision-Support Application The objective of most of today's decision-support applications is to replace printed reports with on-screen presentations of information. A successful decision-support application supplies "Information at Your Fingertips" (a Microsoft-trademarked corporate slogan). For mid-level managers and below, the video display unit (VDU) of a PC is the most common presentation platform. At the vice-presidential and higher rungs of the corporate ladder, the information often is displayed on large-screen or projection video systems acting as a VDU for one PC in a conference setting. #### Specifying the Datasources Typical relationships of datasources and information systems for a typical manufacturing company appear in the hierarchical structure shown in Figure 9.1. Data-entry and transaction-processing activities primarily are confined to the lowest level of the hierarchy, operational databases. (The operational database level of the hierarchy often is called "the trenches.") The levels above the operational databases involve little or no data entry; these upper levels in the hierarchy are referred to as information systems (IS) or management information systems (MIS). Figure 9.1 divides the information systems category into functional information systems at the directorate and vice-presidential level and planning and forecasting information systems that are used by top management and corporate staff. Figure 9.1. The hierarchy of information systems and databases for a manufacturing firm. Depending on the size of the company and the type of computer hardware the firm uses, the operational databases may be located in a centralized mainframe system or distributed across several database servers in a client-server RDBMS environment. Combinations of mainframe and client-server environments are common for firms that are in the process of downsizing and distributing their operational databases. A small manufacturing firm might have all its operational databases in the form of multiple .DBF files that reside on a single file server. If you're developing database applications for a firm with $10 million or more in annual sales, be prepared to deal with the connectivity issues raised by a wide variety of network operating systems and database management systems, including legacy (a synonym for "obsolete" among proponents of client-server RDBMSs) network and hierarchical DBMS. It's not uncommon for developers of database front ends to spend more time solving connectivity problems, both DBM- and network-related, than they spend designing, coding, and testing the entire front-end application. You also might need to integrate data from online datasources into your database front-end application. Credit information from Dun and Bradstreet and TRW, stock prices from the Dow Jones News Service, and real estate transaction data from Damar are just a few of the uses for the data communication features of Visual C++. Another nontraditional datasource that you might need to incorporate in your applications is the CD-ROM. Virtually all the 1990 census data is available from the U.S. Bureau of the Census in .DBF format on CD-ROMs. Fortunately, ODBC lets developers work with .DBF format files. ##### Determining the Level of Detail Required Before the advent of the RDBMS and client-server computing technology, the principal source of functional information, as well as planning and forecasting information, was a multitude of printed reports. Each report was the product of a batch operation that required a program, usually written in COBOL, to execute the Embedded SQL or other instructions that create a formatted report. In many cases, reports were created with more than the optimal level of detail because of a lack of programming resources to write, test, and deploy production programs to summarize the data. The capability of users of client applications to create their own ad hoc queries with whatever degree of detail they desire is the driving force behind the front-end application generator market. Generally, a management report that is more than two pages in length probably presents too much detail. Unless you're dealing with data that has been rolled up (the subject of the next section), your decision-support front-end application will be accessing tables in operational databases. The level of detail you provide in a decision-support application usually varies inversely with the position of the users in the organizational hierarchy. As you progress upward in the corporate "food chain," tabular data gives way to graphs and charts for trend analysis, and the frequency of reporting slows from daily to monthly. Here are the three basic categories of decision-support applications: Executive summaries and planning information consist of graphs and charts that depict financial performance versus internal projections, versus prior fiscal periods, and often versus the results reported by competitors. This category of report is the most likely to require integration of data from online sources operated by data utilities, such as Dialog Information Services, or from firms that specialize in providing online econometric data. Functional summaries, such as reports of orders for the director of sales or daily cash-flow reports from the director of finance, are usually run weekly. At the directorate level, tabular data is the rule. The data from the directors' reports usually is consolidated into monthly reports issued at the vice-presidential level. Graphs compare current operating results with recent historical data, usually for a one-year period or shorter. Operational data summaries are required by supervisory personnel to evaluate day-to-day performance at the departmental or regional level. Credit managers need real-time access to the payment histories of customers placing new orders. Exception-reporting applications that are used on the shop floor, such as applications that identify parts shortages or quality control problems, may need to run on an hourly or shift basis. Tabular formats, rather than graphic presentations, are most common at the operational level. Figure 9.2 shows the layers of information that constitute typical marketing decision-support applications corresponding to the three categories in the preceding list. The executive summary for the vice president of marketing consolidates sales of all products in all regions. The functional summary for the director of sales includes sales of a particular product line in all regions. The operational data viewed by the regional sales manager reports sales in one region for all products. Figure 9.2. Levels of information detail in summary and operational decision-support applications. One of the principal objections of management personnel to MIS reports, whether displayed online or in the form of computer printouts, is excessive detail. If you use a 9-point MS Sans Serif font with a tightly spaced Visual C++ list box, you can display several times as much data on a VDU as is possible with a character-based DOS application. Running at higher resolutions (such as 1024x768) allows a large amount of data to be presented to the user. You have similar potential with today's laser printers. For management, it's the aggregate data that is important, together with exception highlighting. If you need to provide one or two levels of detail behind the summary data, first offer the detail behind the exceptions and then make additional detail information an option. ##### Maintaining Performance and Data Consistency with Rollups Impatience is another personal trait that increases with the level of authority and responsibility in an organization. Operatives in the trenches might be satisfied with an application that takes a minute or more to present a screen of data, because a 3270 terminal on an overtaxed mainframe might take several minutes to update a session. If your summary queries (especially crosstab queries) need to traverse tens of thousands of records containing line items for a year's collection of invoices, you're certain to face an unsatisfied client when you deliver your production front end. The traditional (and still the best) approach to maintaining adequate performance for time-series decision-support applications is to consolidate time-based detail data into new tables. This process is called rolling up data, a process that should be familiar to all mainframe COBOL programmers. Consolidating data, other than creating monthly and yearly rollups for accounting purposes, has been relatively uncommon in PC-based database applications. High-speed 66 to 100 MHz Intel 80486 and Pentium PCs now have become the most popular CPUs for database servers, and the cost of fixed disk storage has broken the $.20-per-megabyte barrier (no, that's not a misprint—20 cents a megabyte, and by the first quarter of 1996, it might be even lower!). Thus, the economic disincentive of replicating data is minimal. Although rolling up data violates the no-duplicated-data rule for relational databases (because rolled up data is derived from existing tables), you'll probably want to aggregate data when your summary queries need to process more than a few thousand records. Here are some guidelines for how and when to roll up data: Avoid cascading rollups when possible. A cascading rollup is a rollup operation that summarizes data that has been rolled up at a greater detail level. If a retroactive change to the underlying detail occurs, you need to re-aggregate each level in the process. Roll up data at intervals that are likely to be the least subject to retroactive changes. An example is three-month rollups for corporations whose quarterly financial reports are subject to independent audit. Monthly rollups may be necessary to achieve acceptable application performance, but monthly rollups shouldn't be cascaded into quarterly aggregations because retroactive changes may be made in the underlying operational databases. Quarterly rollups are based on records in the operational databases. Never roll up data at the operational-database record level. An example of rolling up data at the operational level is the Order Amount field of the Orders table of the Northwind Traders database. The value in the Order Amount field is the sum of the product of the Order Quantity and Unit Price fields of the line item records in the Order Details table for a single order. Changes that occur in the Order Details table, including partial shipments, must be immediately rolled into records in the Orders table to maintain data consistency. Rollups should be executed on a real-time basis. Roll up data during periods of transaction-processing inactivity, such as nights or weekends. One of the advantages of rolling up data is the elimination of consistency errors that can occur when you aggregate detail information that is being updated simultaneously. You can write a stored procedure that runs unattended on the server to roll up data at predetermined intervals if your application uses Microsoft or Sybase SQL Server or another client-server RDBMS that supports stored procedures. In the typical information-system hierarchy illustrated in Figure 9.1, rollups of sales, manufacturing, purchasing, finance, and human resources operational databases occur at the director level. Another rollup further consolidates data for the vice presidents of marketing, operations, and administration. The performance improvement you can achieve by rolling up data lets you design Visual C++ decision-support applications that replace slide shows created with Microsoft PowerPoint or similar Windows presentation applications. Using a presentation application to export and re-create graphs and tables in the form of slides is an inefficient, time-consuming process. Many firms now prepare monthly or weekly presentations by transferring summary data to presentation slides. A well-designed Visual C++ decision-support application can return its development cost many times by eliminating the data import and conversion steps. Your Visual C++ presentation application needs to be totally bulletproof, and you'll probably want to store the rolled up data on a local fixed disk to avoid the embarrassment that accompanies the appearance of blank screens or messages that read Unable to connect to server during the presentation. #### Query Strategies After you've identified your datasources, you need to implement a query strategy. The following sections discuss some of the issues you need to resolve before you commit to a particular strategy to obtain the recordset objects on which to base your decision-support applications. ##### Persistent Versus Impersistent Queries Decision-support applications that consist of a fixed feature set are likely candidates for the use of persistent QueryDef objects. You can store QueryDef objects in Access databases only, but if you're planning to roll up data from client-server or mainframe databases, an Access database is the most appropriate database type in which to store the rolled-up data, because you can attach foreign tables to an Access database if you want to. You can pretest your SQL statements by using the MS Query application to create and store QueryDef objects for rollup or direct queries. MS Query's output windows give you a chance to preview the result of your query and to fine-tune the SQL statement that creates the QueryDef. An alternative method of testing your SQL statements is to use Access. Like MS Query, Access can display the results of a given query for you in tabular format. Also, both MS Query and Access permit you to estimate how long a given query will take. Alternatively, you can write the Access SQL statement for a query, then pass the value of the SQL statement as a char * variable to the szSqlStr argument of a call to the SQLPrepare() function in your code. The SQL statements of persistent QueryDef objects are stored after the Access database engine parses and optimizes them. To optimize your application's performance, you need to test both persistent and impersistent versions of your queries. MS Query doesn't offer an exact method of timing different queries; however, manual timing techniques might suffice for large queries. ##### Designing Rollup Queries Rollup queries are make-table queries that you execute from within a Visual C++ application. Rollup queries use the SQL aggregate SUM() function to total numeric values contained in tables of operational databases. Typically, a rollup query creates a new table with the following fields: Period: One or more fields that identify the range of dates for which the operational data is summed. You can use separate fields for the year and subperiod (quarter, month, or week). You also can combine these two fields with a coding system, such as 1994Q4 (the fourth quarter of 1994), 199412 (December 1994), or 1994W52 (the last week of 1994). As a rule, you'll find that using separate fields for the year and subperiod makes subsequent record selection simpler. Attribute: One or more optional fields that describe an object class or object. Attributes include categories of products, individual products, geographic regions, or persons (individual salespeople, for instance). Value: One or more numeric fields that contain the result of the summation of the values of operational database records for the period. If you use more than one value field in the rollup table, the operational database table must contain each of the fields. For example, you can sum both the Quantity and [Unit Price]*Quantity values of a table containing invoice line items to obtain total units sold and total sales, and then divide total sales by total units sold to obtain average unit price. The easiest method of developing rollup queries is to create a group of summary make-table SQL QueryDef objects in an Access database with Access. Then you write a simple Visual C++ application to execute the QueryDef objects that you created. If necessary, your Visual C++ application can perform the data summarization. The program shown in Figure 9.3 does just that (this example is simple), summarizing data to create a bar chart of sales by month. The DEC_SUPT.MDB sample database that is included on the CD and that provides the rolled-up data required by the sample decision-support forms in the section "Displaying Detail Data with the WinWidgets HGrid Control" contains several make-table QueryDef objects. An Access SQL statement of the qryMonthlySalesRollup QueryDef object is as follows:
>     SELECT Format(Orders.[Shipped Date],"yyyy") AS Year,

>         Format(Orders.[Shipped Date],"mm") AS Month,

>         SUM([Order Details].[Unit Price]*[Order Details].Quantity *

>         (1-[Order Details].Discount)) AS Sales

>         INTO tblSalesRollupMonth

>         FROM Orders, [Order Details]

>         WHERE Orders.[Order ID]=[Order Details].[Order ID]

>         GROUP BY Format(Orders.[Shipped Date],"yyyy"),

>         Format(Orders.[Shipped Date],"mm")

>         HAVING Format([Orders].[Shipped Date],"yyyy"))="1991";
> The Access SQL statement differs from ANSI SQL syntax in the use of the Access SQL Format() function to return parts of dates (in the Year and Month fields) and in the GROUP BY and HAVING clauses. If this query were executed with the SQL pass-through option, you would replace the Format() function with the appropriate ODBC SQL scalar function, YEAR() or MONTH(). The GROUP BY aggregations you use must correspond exactly to the corresponding SELECT descriptors in your SQL statement. The SUM() SQL aggregate function totals the net sale amount, taking into account the discount, if any, offered to the customer on a particular product. The INTO statement identifies the name of the table that is created by the query. The initial GROUP BY criterion that groups orders by the year in which the order was shipped is included in the GROUP BY clause because you might want to specify more than one year in the HAVING clause with an AND operator. If the tblSalesRollupMonth table doesn't exist, the query creates the table. If the tblSalesRollupMonth table exists, the existing table is deleted before the new table is created. Most of the other make-table QueryDef objects in DEC_SUPT.MDB are more complex than the qryMonthlySalesRollup query. You can examine the syntax of each QueryDef object by opening the QueryDef object in the MS Query application. ##### Implementing Ad Hoc Queries One of the incentives for purchasing database front-end application generators is that their users can generate their own ad hoc queries against large databases. The intensity of the desire to create ad hoc queries usually is inversely proportional to the individual's position in the corporate hierarchy. In the upper corporate echelons, executives want the click of a single button to deliver the summary information they need. At the operational level, managers and supervisors want the opportunity to choose from a multiplicity of record-selection options. When an unhindered user executes a SELECT * query against large mainframe or client-server databases, it can bring even the highest performance RDBMS to its knees. Accidentally or intentionally returning all of the records in a monster table can cause severe network congestion, at least until the user's RAM and disk swapfile space are exhausted. The worst-case scenario is the accidental creation of a Cartesian product by the omission of a join condition when more than one table is involved in a query. This can create a very large result set. Some RDBMSs detect this condition and refuse to execute the query. Others, such as applications that use the Access database engine, attempt to return every combination of records in the tables. Don't create decision-support applications that let users enter their own SQL SELECT statements against production databases. Use combo boxes or list boxes to restrict the fields to be displayed and to add required WHERE clause record-selection criteria. This chapter concentrates on designing simple decision-support applications that use preprepared queries. Chapter 10, "Creating Your Own Data Access Controls," describes how to design queries that give users more freedom to define the data they want to summarize or display in detail. Chapter 15, "Designing Online Transaction-Processing Applications," shows you how to design a general-purpose query tool for generating user-defined queries that won't overtax your RDBMS or local area network. ### Designing the User Interface Microsoft Windows achieved its commercial success because Windows 3.x has a graphic interface that many users prefer to the DOS command-line prompt. Windows applications now dominate the PC software market because they use design elements that, at least in most cases, conform to the Common User Access (CUA) architecture developed by IBM in the 1980s. The CUA specification describes the design and operation of menus and other common control objects, such as check boxes, radio (now "option") buttons, and message dialog boxes. Standards for the design of Windows applications appear in a Microsoft publication titled The Windows Interface: An Application Design Guide (1991), which is available in most large bookstores. The sample applications in this book employ the principles embodied in The Windows Interface. Windows 95's new set of user interface standards must be followed if you wish to have the Windows 95 logo on a Windows 95 product that will be resold. Because the logo can be a valuable selling point, this fact must be taken into consideration when creating your applications. The primary objective of the CUA specification is to create uniformity in the overall appearance and basic operational characteristics of computer applications. CUA principles apply to character-based DOS applications executed on PCs and to mainframe sessions running on 3270 terminals. The user interface of Windows 3.x and Windows 95, Windows NT and OS/2 for PCs, X Window and Motif for UNIX systems, and System 7.x for Macintosh computers conforms in most respects to IBM's basic CUA specification. Thus, if you're accustomed to Microsoft Word for the Macintosh, you can quickly adapt to using Microsoft Word for Windows on the PC. The following sections describe some of the basic requirements of the user interface for database decision-support applications designed for use at the upper-management level. Subsequent chapters in this book provide similar guidance for more flexible decision-support applications and data-entry (transaction-processing) applications. #### Optimizing Application Usability The usability of mainstream Windows applications ultimately determines the products' success in the software market. Feature-list comparisons in product advertising and magazine reviews might influence the purchasing decisions of individual users, but the primary purchasers of Windows applications are large corporations. The objective of these corporate purchasers is to minimize the time and training expenses that are required for their personnel to learn to use the applications effectively. Thus, applications are rated by their usability, a wholly subjective attribute. An application that one user finds intuitive and easy to use might be totally incomprehensible to another. Testing applications for usability is an art, not a science—and it's a primitive art at best. Commercial firms that conduct usability tests on major software products charge $100,000 or more for testing relatively simple Windows applications. Microsoft has invested millions of dollars in usability testing of its Windows applications. It's quite unlikely that the applications you create will undergo commercial usability tests. Instead, your client might simply inform you that he or she doesn't understand how to use your application without reading the manual. When that happens, your application has failed the ultimate usability test. A simple method of determining an application's usability is to talk to your customer support staff. They will often be able to quickly point out shortcomings in the user interface and in other areas of the application. The following sections describe characteristics of applications that achieve high usability ratings and show you how to implement these characteristics in the forms that constitute a simple executive-level decision-support application. ##### Striving for Simplicity When you design decision-support applications, your watchword is simplicity. You achieve application simplicity by applying the following rules to your application design: Remember: You're writing the application for the client, not for yourself! Do what the client wants and needs, and put your desires to the side. Don't add features to an application that aren't needed to accomplish the client's fundamental objective. When in doubt, don't implement a feature that isn't in the minimum capabilities list. Wait for the client to request additional features. If you need special features to test the application, hide these features from other users. Don't attempt to display more than one type of information on a single form. For example, don't combine graphs and tabular information on the same form. Instead, hide the graph window and show the window with the tabular data. These three rules are especially important for executive-summary decision-support applications because top executives are unlikely to be PC power users. A simple, intuitive user interface and a limited feature list are the two primary characteristics of professional-quality executive-summary applications. Figure 9.3 illustrates the first form of a hypothetical executive-summary decision-support application that displays sales information for a one-year period. A toolbar is the application's primary navigation device. This toolbar lets the user make the following choices: Display total corporate sales by month using a line graph. Display total corporate sales by month using a bar chart. Display sales by product for the year to date or for a particular quarter or month in pie chart format. Attach the current object or parts of the object displayed by the form to an e-mail message that requests additional data about a particular element of an object. The graph, chart, or selected cells of a grid control in the window is copied to the clipboard and then pasted into an e-mail message. Create an e-mail message that requests information about, or that makes comments on, the object pasted into a message. Save the current data, messages, and annotations in a file for future reference. Exit the application when finished with the review of the current data. Figure 9.3. The opening form of an executive-summary decision-support application. The datasource for the forms for Figure 9.3 is NorthWind.MDB, which is supplied with Access. Data for the year 1994 is shown in these examples because 1994 is the latest year for which 12 months of data is available in NorthWind.MDB. If you installed NorthWind in a location other than the default directory (usually \MSOffice\Access\Samples), you need to change the values in the code that point to the datasource (or be sure that your definition of the NorthWind datasource is the same as the one used here). The following list describes the design principles embodied in the decision-support form shown in Figure 9.3. The form uses a white background to present a contrast with colored objects. Large areas of white or vivid colors are distracting to the user of an application. Avoid dark-colored backgrounds. The preferred background is light gray. There is no opening form or splash screen. A splash screen is a form or design element that identifies the application. (An example of a splash screen is the copyright message that appears when you first launch Word for Windows, Excel, or other mainstream Windows applications.) You might need an initial login window to obtain the password required to start the application and to log the user into a secure database. NOTE If your application is copyrighted, you might need to include a splash screen to display the program's copyright information. You should consult with your legal advisor for the requirements you must follow to protect your copyright. The buttons present large targets for the mouse. Each button has an icon and an optional caption to explain the purpose of the button. In the status bar, a single line of help is provided for each of the toolbar buttons. Toolbars that substitute for common menu choices are common in today's Windows applications. The toolbar in Figure 9.3 is modeled on the Microsoft Mail application, which is an example of a Windows application with a simple and attractive user interface. Three-dimensional group pushbuttons, provided by Visual C++, are used to indicate the user's current display choice or other operation. Disabled buttons are indicated by replacing colored bitmap elements with a grayscale image that, except for color, is identical to the icon when the button is enabled. A menu is provided to let the user make choices that aren't implemented by buttons. In production applications, a menu choice duplicates the action of each button. Enabling and disabling menu choices follows the same pattern as that employed for the corresponding buttons. The form is designed to occupy much of the display area in normal mode. If you're designing the application for presentation, set the size of the form to the entire display area. The preferred user interface for decision-support applications is a single document interface (SDI) form that displays a single document (a graph, a chart, or a table) with common menus and toolbars. Showing and hiding objects on a single form is typical in this type of application. The form shown in Figure 9.3 serves as the foundation of the form designs for the majority of the decision-support sample applications presented in this book. I have created only bar charts for this chapter. If you want to, you can add line and pie charts yourself. ##### Maintaining Consistency According to Ralph Waldo Emerson, "A foolish consistency is the hobgoblin of little minds." However, this doesn't apply to computer applications. Having both internal and external consistency of the user interface is a principal requirement of a properly designed Windows application. Internal (endogenous) consistency implies that the appearance of all of the forms and the behavior of all of the controls on the forms that constitute your application are similar. If the behavior of a button or menu choice needs to differ under certain conditions, change the appearance of the icon (change a color, for example) or alter the caption for the menu choice. External (exogenous) consistency means that the appearance and behavior of your application is similar to other mainstream Windows applications. If, for example, your client primarily uses Microsoft applications, the appearance and operational characteristics of your application should be modeled on the current version of Excel, Word for Windows, Microsoft Mail, or Microsoft Access. You need to meet the following criteria to maintain internal consistency: All the forms that constitute the application should have a similar appearance. Background colors, typeface families, and the size of display elements should remain constant throughout the application. It's easier to read serif fonts, such as Times New Roman and MS Serif, than fonts without serifs (sans serif), such as Arial and MS Sans Serif. Use the bold attribute for label captions, graph and chart labels and legends, and numerical values in grid controls. Use standard TrueType fonts that are supplied with Windows 95 or Windows NT; let users change the fonts to their own favorites if they want to. The location and sequence of navigation devices should remain constant for all places. Buttons and menu choices that appear in more than one place always appear in the same sequence and in the same position (where feasible). Icons that are used to identify objects or operations should have the same appearance in all places. If the images you use for icons adequately represent and distinguish the objects or operations, you can eliminate captions in second-level dialog boxes where you need more buttons than will fit in a single row if the buttons have captions. Here are the rules for maintaining external application consistency: Choose a mainstream Windows application as the model for your application's toolbar. Microsoft Word and Microsoft Mail are good choices as model for toolbar forms, and Excel's standard toolbar represents a good starting point for forms that need more than eight buttons. Buttons with icons that are identical to or similar to icons found in other mainstream applications should perform the same or similar functions in your application. Using as much of Visual C++'s default toolbar buttons as possible will lead to a consistent application. When creating 32-bit applications with Visual C++ 4 (and later versions), implement the toolbar tool tips features to allow the application's user to navigate the toolbar. Use a consistent font for button captions if you create a toolbar with big, captioned buttons. Microsoft uses the 8.25-point MS Sans Serif Roman font for most button captions and as the default typeface for numeric values; your application should follow suit. Roman is the term for a font with no attributes—for example, not bold, not italic, and not underlined. MS Sans Serif is a bitmapped font that closely resembles Linotype Corp.'s Helvetica typeface family. Use a common menu and toolbar on an MDI parent form and employ MDI child forms to present graphs, charts, and grid controls based on your application's queries. Microsoft common dialog boxes (used for opening and saving files, as well as for other common operations) and message boxes usually have a sculpted appearance and a light gray background. You need to declare and use the functions contained in CTL3DV2.DLL to add the Microsoft style to your common dialog boxes and message boxes when you write applications for earlier versions of Windows, such as Windows 3.1x. Borland International's products use stylized OK, Cancel, and Help buttons for message boxes. If you want to duplicate Borland's button style, you'll need to create your own custom bitmapped buttons. (Windows applications that were created with the Borland C++ compiler have stylized OK buttons with an adjacent shadowed check mark that Borland includes in its resources library.) #### Identifying Toolbar Button Functions Visual C++ supports the identification of toolbar buttons (and menu selections) in the status bar's output area. When you design the menu items, you need to provide only a prompt string, as shown in Figure 9.4. The part of the prompt string following the \n is the tooltip text. Figure 9.4. A prompt for a menu item that includes tooltip information. It's difficult to create a collection of small icons (about 24x24 pixels) that unambiguously represents a variety of operations. Figure 9.5 illustrates the use of pop-up labels (usually called tooltips) that appear when the mouse pointer is positioned on the surface of the button. Tooltips are supported by Visual C++ 4's MFC 4. Figure 9.5. Using a pop-up label to identify the purpose of a small toolbar button. Placing a pop-up label adjacent to the button with which it is associated is a better method of identifying the purpose of a button than displaying the same information in a status bar at the bottom of a form. No eye movement is necessary to read the adjacent label caption, whereas substantial eye movement is required to traverse the VDU from the top toolbar to the bottom status bar. Minimizing the eye movement required to accomplish each of the application's tasks is one of the principles of good user interface design, as shown in Figure 9.5. ### Creating and Using Toolbars The documentation that accompanies Visual C++ describes how to use the graphics capabilities of Visual C++ but provides little or no practical advice for adding images to toolbar buttons and bitmap pushbutton controls. The following sections describe how to obtain the bitmapped images you need for your toolbar buttons, how to create Windows bitmap (.BMP) files with Windows Paint, and how to add the image contained in a .BMP file to a bitmap button. #### Obtaining and Modifying Button Bitmaps Visual C++ includes a plethora of icons and bitmaps, shown in Figure 9.6, that you can use to decorate conventional and 3-D command and group pushbuttons. Some of these bitmaps will seem familiar because they are found in Microsoft's word processors and other applications. You can find these files in the \MSVC20\SAMPLES\MFC\CLIPART directory on the Visual C++ 2 CD or the \MSDEV\SAMPLES\MFC\GENERAL\CLIPART folder on the Visual C++ 4 CD. Figure 9.6. The contents of the TOOLBAR_.BMP file. Each of the images in the TOOLBAR_.BMP file can be copied (using the clipboard) to an application's toolbar. NOTE These files aren't available with Visual C++ 4.0. If you have the subscription edition of Visual C++, you might want to retain your prior CDs. ##### Using the Image Editor Application to Create Button Bitmaps Visual Basic 4.0 includes a bitmap editing tool called Image Editor, located on the Visual Basic CD in the \Tools\Imagedit folder. (You might need to manually copy this folder from the CD to your hard disk.) You need to transfer the data in icon (.ICO) files to Windows Paint using the Windows clipboard, because you can't open an .ICO file in Windows Paint. The Image Editor, however, does permit you to directly open and edit .ICO files. Figure 9.7 shows the sample Mail.bmp file being edited in the Image Editor application. Figure 9.7. The Image Editor application displaying the sample Mail.bmp file. Select Edit | Copy in the Image Editor to copy the entire icon to the clipboard in .BMP format. Open Paint, add a light gray background with the paint roller tool, and choose Edit | Paste to add the icon to your Paint image. You can alter the button bitmap's appearance using either the Image Editor or Paint's toolkit. In general, you might find it easiest to use the Image Editor, which automatically magnifies the .BMP or .ICO image you're working with. ##### Generating Bitmaps with Desktop Publishing Packages Many full-featured vector-based drawing packages are available. Most include a variety of clip-art images that you can use (or adapt for use) as button faces in your applications. Some desktop publishing applications have several thousand clip art images on their CDs. In addition, you can purchase CDs packed with nothing but various clip-art images. When you open an icon or clip-art image in a commercial publishing package, the image is typically much larger than you need or want for a button bitmap. Generally, you must reduce the image to create a bitmap that is approximately .25-inch high. Add a light gray background to the image so that the background matches the default background color of Visual Basic buttons. You'll probably have to export the image from its original clip-art format, which is usually some type of vector drawing format rather than a bitmap. Export the image to a 16-color Windows bitmap (.BMP) file. NOTE The CD that comes with this book has an application called Paint Shop Pro, a full-featured graphics editor. Paint Shop Pro can work as well as some of the higher-priced products for most Visual C++ programmers. ### Displaying Detail Data with the WinWidgets HGrid Control The WinWidgets HGrid control lets Visual C++ display tabular detail with a graphical presentation. NOTE It may well be easier to use the ListView Win32 Common Control to display tabular data. Another alternative is the grid OLE Custom Control, which is also shipped with Visual C++ 4. Each method presents advantages and disadvantages to the programmer. The HGrid control can't be linked to a recordset object directly. However, you can write a simple Visual C++ routine to display data created by the qryMonthlyProductSalesParam query from the Products table and the qryMonthlyProductSalesCrosstab query of DEC_SUPT.MDB. The SQL statements used to create the two QueryDef objects that you use to generate a Dynaset object (which you manipulate to supply data to the grid) are as follows:
>     TRANSFORM Sum(tblProductRollupMonth.Sales) AS SumOfSales

>         SELECT tblProductRollupMonth.[Product ID]

>         FROM tblProductRollupMonth

>         GROUP BY tblProductRollupMonth.[Product ID]

>         PIVOT tblProductRollupMonth.Month

>         IN ("01","02","03","04","05","06","07","08","09","10","11","12");

>     PARAMETERS CategID Text;

>         SELECT Products.[Product ID], Products.[Product Name],

>         [01], [02], [03], [04], [05], [06], [07], [08], [09], [10], [11], [12]

>         FROM qryMonthlyProductSalesCrosstab, Products,

>         qryMonthlyProductSalesCrosstab RIGHT JOIN Products ON

>         qryMonthlyProductSalesCrosstab.[Product ID] =

>         Products.[Product ID]

>         WHERE Products.[Category ID]=CategID;
> The TRANSFORM (crosstab) query creates a Dynaset object that consists of the Product ID column and 12 monthly columns labeled 01 through 12. One row is created for each product. The IN predicate is added to assure that the query returns 12 columns, even if no data is available for all of the months of the year. The SQL SELECT statement uses the Dynaset object created by the Access SQL TRANSFORM statement as if the Dynaset were a persistent table. The purpose of the parameterized SELECT query is to assure that all rows for products within a category designated by the CategID parameter appear in the resulting dynaset, regardless of whether sales of the product occurred during the year, and to supply a column containing the name of the product. A RIGHT JOIN is needed to make all of the products in the category appear. You need to use Access SQL for the JOIN statement because the Access database engine doesn't recognize the ANSI SQL =* operator that designated a right join. A detailed explanation of the WinWidgets package is beyond the scope of this book, but Table 9.1 lists some of the features that this package offers. Table 9.1. Features of the WinWidgets package.
> Feature | Description
> DataEngine | A set of custom controls that format data, such as dates, time, and money, using supplied formatting.
> HBUTT | Supports button controls, including multiline text support.
> HCOMB | Support for a more powerful combo box control. Enhanced support for the programmer includes text attributes such as color and font.
> HEDIT | An edit control that is designed to let data be displayed, edited, and validated.
> HGRID | The grid control is a valuable tool that lets programmers display record data. Displayed data can be updated.
> HLIST | The HLIST list box control offers many of the features of the HCOMB combo-box control.
> HSPIN | The HSPIN control is an edit control with a pair of additional buttons that let the user increment or decrement the value displayed in the edit control. Often used with numeric data, the HSPIN control can be used with text-based data, as well (such as selecting from a list of colors).
> HSTAT | The HSTAT control is used to display bitmaps, text, icons, and frames.
> HTAB | The HTAB control lets you create a type of tabbed dialog box. Because Visual C++ already supports tabbed dialog boxes, this control isn't useful for Visual C++ programmers.
> HTOOL | The HTOOL toolbar control offers improvements over Visual C++ 1.x's toolbar support. However, users of Visual C++ 2.x and later will most likely find that the Visual C++ MFC toolbar classes are the preferred implementation.
> XTABLE | The XTABLE control provides the basic functionality of a spreadsheet. This control can be most useful when you're developing applications in which users must update records in a datasource or where any spreadsheet-type operations must be performed.
### Summary This chapter introduced you to an almost-commercial Visual C++ database application, the first such application to be presented in this book. The table rollup, query design, and user interface guidelines discussed in this chapter can start you on your way to creating production-decision support applications with Visual C++. The forms included in the UI_EXAMP application are the basis of the designs of all of the decision-support examples in the following chapters. This chapter demonstrated that you can create an attractive and quite functional Visual C++ database decision-support application with relatively little code. The next chapter shows you how to add additional functionality to your decision-support applications with data-aware control objects and more sophisticated coding techniques. Contact reference@earthweb.com with questions or comments. Copyright 1998 EarthWeb Inc., All rights reserved. PLEASE READ THE ACCEPTABLE USAGE STATEMENT. Copyright 1998 Macmillan Computer Publishing. All rights reserved. |