Go Up to Windows Developer’s Guide
The C++Builder Developer’s Guide contains information for both Delphi and C++.
- Tip: To select the language you want to see, click the Display Preferences control, located in the upper right corner of the page.
- To see C++ information only, enable the C++ checkbox and disable the Delphi checkbox, as shown here:
Contents
- 1 Part I: Programming with C++Builder
- 1.1 Developing Applications with C++Builder
- 1.2 Understanding the Component Library
- 1.3 Working with Components Index
- 1.4 Working with Controls Index
- 1.5 Building Applications, Components, and Libraries Index
- 1.6 Developing the Application User Interface Index
- 1.7 Types of Controls Index
- 1.8 Working with Graphics and Multimedia Index
- 1.9 Writing Multithreaded Applications Index
- 1.10 Exception Handling in C++Builder
- 1.11 Working with Packages and Components Index
- 1.12 Creating International Applications Index
- 1.13 Deploying RAD Studio Applications
- 2 Part II: Developing Database Applications
- 2.1 Designing Database Applications — Overview
- 2.2 Using Data Controls
- 2.3 Connecting to Databases Index
- 2.4 Understanding Datasets Index
- 2.5 Working with Field Components Index
- 2.6 Using BDE Index
- 2.7 Using Client Datasets Index
- 2.8 Using Provider Components Index
- 2.9 Creating Multi-Tiered Applications Index
- 2.10 Using XML in Database Applications Index
- 3 Part III: Writing Internet Applications
- 3.1 Creating Internet Server Applications Index
- 3.2 Using Web Broker Index
- 3.3 Using Web Services Index
- 3.4 Working with Sockets
- 4 Part IV: Developing COM-based Applications Index
- 4.1 Overview of COM Technologies
- 4.2 Working with Type Libraries
- 4.3 Creating COM Clients
- 4.4 Creating Simple COM Servers
- 4.5 Creating an Active Server Page
- 4.6 Using ActiveX Controls
- 5 Part V: Component Writer’s Guide
- 6 See Also
Part I: Programming with C++Builder
Developing Applications with C++Builder
- Integrated Development Environment
- Designing Applications
- Creating Projects
- Editing Code
- Compiling Applications
- Debugging Applications
- Deploying Applications
Understanding the Component Library
- Understanding the Component Library
- Properties, Methods, and Events
- Types of Events
- Properties, Methods, and Events
- Objects, Components, and Controls
- TObject Branch
- TPersistent Branch
- TComponent Branch
- TControl Branch
- TWinControl Branch
Working with Components Index
- Setting Properties and Events
-
- Using Property Editors
-
- Calling Methods
- Working with Events and Event Handlers
- Generating a New Event Handler
- Generating a Handler for a Component’s Default Event
- Locating Event Handlers
- Associating an Event with an Existing Event Handler
- Using the Sender Parameter
- Displaying and Coding Shared Events
- Associating Menu Events with Event Handlers
- Deleting Event Handlers
- Adding Custom Components to the Tool Palette
Working with Controls Index
- Implementing Drag and Drop in Controls
- Starting a Drag Operation
- Accepting Dragged Items
- Dropping Items
- Ending a Drag Operation
- Customizing Drag and Drop with a Drag Object
- Changing the Drag Mouse Pointer
- Implementing Drag and Dock in Controls
- Making a Windowed Control a Docking Site
- Making a Control a Dockable Child
- Controlling How Child Controls Are Docked
- Controlling How Child Controls Are Undocked
- Controlling How Child Controls Respond to Drag-and-dock Operations
- Working with Text in Controls
- Setting Text Alignment
- Adding Scroll Bars at Run-Time
- Adding the Clipboard Object
- Selecting Text
- Selecting All Text
- Cutting, Copying, and Pasting Text
- Deleting Selected Text
- Disabling Menu Items
- Providing a Pop-up Menu
- Handling the OnPopup Event
- Adding Graphics to Controls
- Indicating That a Control Is Owner-drawn
- Adding Graphical Objects to a String List
- Adding Images to an Application
- Adding Images to a String List
- Drawing Owner-drawn Items
- Sizing Owner-draw Items
- Drawing Owner-draw Items
- Screen Scaling and ChangeScale
Building Applications, Components, and Libraries Index
- Creating Applications
- GUI Applications
- User Interface Models
- SDI Applications
- MDI Applications
- Setting IDE, Project, and Compiler Options
- Console Applications
- Service Applications
- Service Threads
- Service Name Properties
- Debugging Service Applications
- Programming Templates
- GUI Applications
- Creating Packages and DLLs
- When to Use Packages and DLLs
- Using DLLs in RAD Studio (C++)
- Creating DLLs in C++Builder
- Creating DLLs Containing VCL Components (C++)
- Linking DLLs (C++)
- Writing Database Applications
- Distributing Database Applications
- Creating Web Server Applications
- Creating Web Services Applications
- Creating WebBroker Applications
- Writing Applications Using COM
- Using Data Modules
- Creating and Editing Standard Data Modules
- Naming a Data Module and Its Unit File
- Placing and Naming Components
- Using Component Properties and Events in a Data Module
- ClassGroup pseudo-property of TDataModule
- Creating Business Rules in a Data Module
- Accessing a Data Module from a Form
- Adding a Remote Data Module to an Application Server Project
- Setting the Framework Affinity for a Data Module
- Creating and Editing Standard Data Modules
- Using the Object Repository
- Sharing Items Within a Project
- Adding Items to the Object Repository
- Sharing Objects in a Team Environment
- Using an Object Repository Item in a Project
- Using Project Templates
- Modifying Shared Items
- Enabling Help in Applications
- Calling HTML Help from Applications
- Types of HTML Help
- Default Handling of F1 Help in VCL Applications
- Customizing F1 Help in VCL Applications
- Showing Help with Help Buttons
- Associating Help with Menu Commands
- Showing Help About Selected Menu Commands
- Using the Hint Property to Show Contextual Help About Screen Objects
- Help System Interfaces
- Implementing ICustomHelpViewer
- Communicating with the Help Manager
- Asking the Help Manager for Information
- Displaying Keyword-based Help
- Displaying Tables of Contents
- Implementing IExtendedHelpViewer
- Using IHelpSystem
- Implementing IHelpSelector
- Registering Help System Objects
- Using Help in a VCL Application
- How TApplication Processes VCL Help
- How VCL Controls Process Help
- Calling a Help System Directly
- Calling HTML Help from Applications
Developing the Application User Interface Index
- Developing the Application User Interface — Overview
- Controlling Application Behavior
- Working at the Application Level
- Handling the Screen
- Using the Main Form
- Hiding the Main Form
- Adding Forms
- Managing Layout
- Using Forms
- Controlling When Forms Reside in Memory
- Displaying an Auto-created Form
- Creating Forms Dynamically
- Creating Modeless Forms Such as Windows
- Creating a Form Instance Using a Local Variable
- Passing Additional Arguments to Forms
- Retrieving Data from Forms
- Retrieving Data from Modal Forms
- Retrieving Data from Modeless Forms
- Controlling When Forms Reside in Memory
- Reusing Components and Groups of Components
- Creating and Using Component Templates
- Working with Frames
- Creating Frames
- Using and Modifying Frames
- Sharing Frames
- Developing Dialog Boxes
- Using Windows Common Dialog Boxes
- Creating and Managing Menus
- Opening the Menu Designer
- Building Menus
- Naming Menus
- Naming the Menu Items
- Adding, Inserting, and Deleting Menu Items
- Adding Separator Bars
- Specifying Accelerator Keys and Keyboard Shortcuts
- Creating Submenus
- Moving Menu Items
- Adding Images to Menu Items
- Viewing the Menu
- Editing Menu Items in the Object Inspector
- Switching Between Menus at Design Time
- Using Menu Templates
- Saving a Menu as a Template
- Naming Conventions for Template Menu Items and Event Handlers
- Manipulating Menu Items at Runtime
- Merging Menus
- Specifying the Active Menu: Menu Property
- Determining the Order of Merged Menu Items: GroupIndex Property
- Importing Resource Files
- Designing Toolbars and Cool Bars
- Adding a Toolbar Using a Panel Component
- Adding a Speed Button to a Panel
- Assigning a Speed Button’s Glyph
- Setting the Initial Condition of a Speed Button
- Creating a Group of Speed Buttons
- Allowing Toggle Buttons
- Adding a Toolbar Using the Toolbar Component
- Adding a Tool Button
- Assigning Images to Tool Buttons
- Setting Tool Button Appearance and Initial Conditions
- Creating Groups of Tool Buttons
- Allowing Toggled Tool Buttons
- Adding a Cool Bar Component
- Setting the Appearance of the Cool Bar
- Responding to Clicks
- Assigning a Menu to a Tool Button
- Adding Hidden Toolbars
- Hiding and Showing Toolbars
- Adding a Toolbar Using a Panel Component
- Common Controls and XP Themes
Types of Controls Index
- Text Controls
- Edit Controls
- Memo and Rich Edit Controls
- Text Viewing Controls
- Labels
- Edit Controls
- Specialized Input Controls
- Scroll Bars
- Track Bars
- Up-down Controls
- Hot Key Controls
- Splitter Controls
- Buttons and Similar Controls
- Button Controls
- Bitmap Buttons
- Speed Buttons
- Check Boxes
- Radio Buttons
- Toolbar Controls
- Cool Bars
- List Controls
- List Boxes and Check-list Boxes
- Combo Boxes
- Tree Views
- List Views
- Grouping Controls
- Group Boxes and Radio Groups
- Panels
- Scroll Boxes
- Tab Controls
- Page Controls
- Header Controls
- Display Controls
- Status Bars
- Progress Bars
- Help and Hint Properties
- VCL Taskbars
- Grids
- Draw Grids
- String Grids
- Value List Editors
- Graphic Controls
- Images
- Shapes
- Bevels
- Paint Boxes
- Animation Control
Working with Graphics and Multimedia Index
- Working with Graphics and Multimedia — Overview
- Overview of Graphics Programming
- Refreshing the Screen
- Types of Graphic Objects
- Common Properties and Methods of Canvas
- Using the Properties of the Canvas Object
- Creating Drawing Spaces
- Colors
- Printing
- Using Pens
- Changing the Pen Color
- Changing the Pen Width
- Changing the Pen Style
- Changing the Pen Mode
- Getting the Pen Position
- Using Brushes
- Changing the Brush Color
- Changing the Brush Style
- Setting the Brush Bitmap Property
- Reading and Setting Pixels
- Using Canvas Methods to Draw Graphic Objects
- Drawing Lines and Polylines
- Drawing Lines
- Drawing Polylines
- Drawing Shapes
- Drawing Rectangles and Ellipses
- Drawing Rounded Rectangles
- Drawing Polygons
- Drawing Lines and Polylines
- Handling Multiple Drawing Objects in Your Application
- Keeping Track of Which Drawing Tool to Use
- Changing the Tool with Speed Buttons
- Using Drawing Tools
- Drawing Shapes (Code)
- Sharing Code Among Event Handlers
- Drawing On a Graphic
- Making Scrollable Graphics
- Adding an Image Control
- Placing the Control
- Setting the Initial Bitmap Size
- Drawing On the Bitmap
- Loading and Saving Graphics Files
- Loading a Picture from a File
- Saving a Picture to a File
- Replacing the Picture
- Using the Clipboard with Graphics
- Copying Graphics to the Clipboard
- Cutting Graphics to the Clipboard
- Pasting Graphics from the Clipboard
- Rubber Banding Example
- Responding to the Mouse
- What’s in a Mouse Event
- Responding to a Mouse-down Action
- Responding to a Mouse-up Action
- Responding to a Mouse Move
- Adding a Field to a Form Object to Track Mouse Actions
- Refining Line Drawing
- Tracking the Origin Point
- Tracking Movement
- Responding to the Mouse
- Working with Multimedia
- Adding Silent Video Clips to an Application
- Example of Adding Silent Video Clips
- Adding Audio or Video Clips to an Application
- Example of Adding Audio or Video Clips (VCL Only)
- Adding Silent Video Clips to an Application
Writing Multithreaded Applications Index
- Writing Multi-threaded Applications
- Defining thread objects
- Defining Thread Objects
- Initializing the Thread
- Writing the Thread Function
- Using Thread-local Variables
- Checking for Termination by Other Threads
- Handling Exceptions in the Thread Function
- Writing Clean-up Code
- Coordinating threads
- Coordinating Threads
- Avoiding Simultaneous Access
- Locking Objects
- Using Critical Sections
- Using the Multi-read Exclusive-write Synchronizer
- Other Techniques for Sharing Memory
- Waiting for Other Threads
- Waiting for a Thread to Finish Executing
- Waiting for a Task to Be Completed
- Executing thread objects
- Executing Thread Objects
- Overriding the Default Priority
- Starting and Stopping Threads
- Debugging Multi-threaded Applications
- Naming a Thread
- Converting an Unnamed Thread to a Named Thread
- Assigning Separate Names to Similar Threads
- Naming a Thread
Exception Handling in C++Builder
- Standard C++ Exception Handling
- Standard C++ Exception Handling Syntax
- Rethrowing Exceptions (C++)
- Exception Specifications (C++)
- Unwinding Exceptions (C++)
- Constructors in Exception Handling (C++)
- Handling Uncaught and Unexpected Exceptions (C++)
- Leaking C++ Exceptions into Delphi RTL
- Structured Exceptions Under Win32 (C++)
- Syntax of Structured Exceptions (C++)
- Handling Structured Exceptions (C++)
- Filtering Structured Exceptions (C++)
- Mixing Standard Exceptions with Structured Exceptions (C++)
- Defining Structured Exceptions (C++)
- Raising Structured Exceptions (C++)
- SEH Termination Blocks (C++)
- Delphi Exception Handling in C++
- C++Builder Exception Handling Compiler Options
- External Exception EEFFACE
Working with Packages and Components Index
- Working with Packages and Components — Overview
- Why Use Packages
- Packages and Standard DLLs
- Runtime Packages
- Loading Packages in an Application
- Loading Packages with the LoadPackage Function
- Deciding Which Runtime Packages to Use
- Custom Packages
- Loading Packages in an Application
- Design-time Packages
- Installing Component Packages
- Creating and Editing Packages
- Creating a Package
- Editing an Existing Package
- Understanding the Structure of a Package
- Editing Package Source Files Manually
- Compiling Packages
- Package-specific Compiler Directives
- Using the Weak Packaging Directive
- Compiling and Linking from the Command Line
- Package Files Created by Compiling
- Building Static Packages
- Deploying Packages
- Packaging Components Or Libraries Written In Classic and Clang C++ Win32 Compilers
Creating International Applications Index
- Internationalization and Localization
- Internationalizing Applications
- Enabling Application Code to Work for Different Locales
- Character Sets
- Including Bi-directional Functionality in Applications
- Locale-specific Features
- Enabling Application Code to Work for Different Locales
- Localizing Applications
- Localization Considerations in UI Design
- Text
- Graphic Images
- Formats and Sort Order
- Keyboard Mappings
- Isolating Resources
- Using Resource DLLs
- Creating Resource DLLs
- Dynamic Switching of Resource DLLs
- Localization Considerations in UI Design
- Internationalizing Applications
- Deploying Localized Applications
Deploying RAD Studio Applications
- Deploying Applications — Overview
- Deploying General Applications
- Using Installation Programs
- Identifying Application Files
- Application Files, Listed by File Name Extension
- Package Files
- Deploying ActiveX Controls
- Helper Applications
- DLL Locations
- Using Installation Programs
- Deploying Database Applications
- Deploying dbExpress Database Applications
- Deploying BDE Applications
- BDE
- Deploying Web Applications
- Programming for Varying Host Environments
- Screen Resolutions and Color Depths
- Considerations When Dynamically Resizing Forms and Controls
- Considerations When Not Dynamically Resizing
- Accommodating Varying Color Depths
- Fonts
- Operating System Versions
- Software License Requirements
Part II: Developing Database Applications
Designing Database Applications — Overview
- Using Databases
- Types of Databases
- Database Security
- Transactions
- Referential Integrity, Stored Procedures, and Triggers
- Database Architecture
- Connecting Directly to a Database Server
- Using a Dedicated File on Disk
- Connecting to Another Dataset
- Connecting a Client Dataset to Another Dataset in the Same Application
- Using a Multi-Tiered Architecture
- Combining Approaches
- Designing the User Interface
- Analyzing Data
Using Data Controls
- Using Common Data Control Features
- Associating a Data Control with a Dataset
- Changing the Associated Dataset at Runtime
- Enabling and Disabling the Data Source
- Responding to Changes Mediated by the Data Source
- Editing and Updating Data
- Enabling Editing in Controls On User Entry
- Editing Data in a Control
- Disabling and Enabling Data Display
- Refreshing Data Display
- Enabling Mouse, Keyboard, and Timer Events
- Associating a Data Control with a Dataset
- Choosing How to Organize the Data
- Displaying a Single Record
- Displaying Data as Labels
- Displaying and Editing Fields in an Edit Box
- Displaying and Editing Text in a Memo Control
- Displaying and Editing Text in a Rich Edit Memo Control
- Displaying and Editing Graphics Fields in an Image Control
- Displaying and Editing Data in List and Combo Boxes
- Displaying and Editing Data in Lookup List and Combo Boxes
- Using TDBListBox and TDBComboBox
- Handling Boolean Field Values with Check Boxes
- Restricting Field Values with Radio Controls
- Displaying Multiple Records
- Viewing and Editing Data with TDBGrid
- Using a Grid Control in Its Default State
- Creating a Customized Grid
- Creating Persistent Columns
- Deleting Persistent Columns
- Arranging the Order of Persistent Columns
- Setting Column Properties at Design Time
- Defining a Lookup List Column
- Putting a Button in a Column
- Restoring Default Values to a Column
- Displaying ADT and Array Fields
- Setting Grid Options
- Editing in the Grid
- Controlling Grid Drawing
- Responding to User Actions at Runtime
- Creating a Grid That Contains Other Data-aware Controls
- Navigating and Manipulating Records
- Choosing Navigator Buttons to Display
- Displaying Fly-over Help
- Using a Single Navigator for Multiple Datasets
Connecting to Databases Index
- Connecting to Databases — Overview
- Using Implicit Connections
- Controlling Connections
- Connecting to a Database Server
- Disconnecting from a Database Server
- Controlling Server Login
- Managing Transactions
- Specifying the Transaction Isolation Level
- Sending Commands to the Server
- Working with Associated Datasets
- Obtaining Metadata
Understanding Datasets Index
- Understanding Datasets — Overview
- Using TDataSet Descendants
- Determining Dataset States
- Opening and Closing Datasets
- Navigating Datasets
- Using the First and Last Methods
- Using the Next and Prior Methods
- Using the MoveBy Method
- Using the Eof and Bof Properties
- Marking and Returning to Records
- Searching Datasets
- Using Locate
- Using Lookup
- Displaying and Editing a Subset of Data Using Filters
- Enabling and Disabling Filtering
- Creating Filters
- Setting the Filter Property
- Writing an OnFilterRecord Event Handler
- Setting Filter Options
- Navigating Records in a Filtered Dataset
- Modifying Data
- Editing Records
- Adding New Records
- Deleting Records
- Posting Data
- Canceling Changes
- Modifying Entire Records
- Calculating Fields
- Types of Datasets
- Using Table Type Datasets
- Sorting Records with Indexes
- Obtaining Information About Indexes
- Specifying an Index with IndexName
- Creating an Index with IndexFieldNames
- Using Indexes to Search for Records
- Executing a Search with Goto Methods
- Executing a Search with Find Methods
- Specifying the Current Record After a Successful Search
- Searching On Partial Keys
- Repeating or Extending a Search
- Limiting Records with Ranges
- Understanding the Differences Between Ranges and Filters
- Specifying Ranges
- Modifying a Range
- Applying or Canceling a Range
- Creating Master-Detail Relationships
- Making the Table a Detail of Another Dataset
- Using Nested Detail Tables
- Controlling Read-Write Access to Tables
- Creating and Deleting Tables
- Emptying Tables
- Synchronizing Tables
- Sorting Records with Indexes
- Using Query-type Datasets
- Specifying the Query
- Using Parameters in Queries
- Supplying Parameters at Design Time
- Supplying Parameters at Runtime
- Establishing Master-detail Relationships Using Parameters
- Preparing Queries
- Executing Queries That Don’t Return a Result Set
- Using Unidirectional Result Sets
- Using Stored Procedure-type Datasets
- Working with Stored Procedure Parameters
- Preparing Stored Procedures
- Executing Stored Procedures That Don’t Return a Result Set
- Fetching Multiple Result Sets
Working with Field Components Index
- Working with Field Components — Overview
- Dynamic Field Components
- Persistent Field Components
- Creating Persistent Fields
- Arranging Persistent Fields
- Defining New Persistent Fields
- Defining a Data Field
- Defining a Calculated Field
- Programming a Calculated Field
- Defining a Lookup Field
- Defining an Aggregate Field
- Deleting Persistent Field Components
- Setting Persistent Field Properties and Events
- Setting Display and Edit Properties at Design Time
- Setting Field Component Properties at Runtime
- Creating Attribute Sets for Field Components
- Associating Attribute Sets with Field Components
- Removing Attribute Associations
- Controlling and Masking User Input
- Using Default Formatting for Numeric, Date, and Time Fields
- Handling Events
- Working with Field Component Methods at Runtime
- Displaying, Converting, and Accessing Field Values
- Displaying Field Component Values in Standard Controls
- Converting Field Values
- Accessing Field Values with the Default Dataset Property
- Accessing Field Values with a Dataset’s FieldByName Method
- Accessing Field Values with a Dataset’s Fields Property
- Setting a Default Value for a Field
- Working with Constraints
- Creating a Custom Constraint
- Using Server Constraints
- Using Object Fields
- Working with ADT Fields
- Working with Array Fields
- Working with Dataset Fields
- Working with Reference Fields
Using BDE Index
- BDE-based Architecture
- Using BDE
- Executing an Update Statement
- Using Multiple Update Objects
- Connecting to databases with TDatabase
- Managing database sessions
- Using BDE-enabled datasets
- Using TBatchMove
- Using the BDE to cache updates
- Using transactions with the BDE=== Working with ADO Components Index===
- Working with ADO Components
- Overview of ADO Components
- Connecting to ADO Data Stores
- Connecting to a Data Store Using TADOConnection
- Accessing the Connection Object
- Fine-tuning a Connection
- Forcing Asynchronous Connections
- Controlling Timeouts
- Indicating the Types of Operations the Connection Supports
- Specifying Whether the Connection Automatically Initiates Transactions
- Accessing the Connection’s Datasets
- ADO Connection Events
- Connecting to a Data Store Using TADOConnection
- Using ADO datasets
- Connecting an ADO Dataset to a Data Store
- Working with Record Sets
- Filtering Records Based On Bookmarks
- Filtering Multiple Rows Based On Update Status
- Fetching Records Asynchronously
- Using Batch Updates
- Loading Data from and Saving Data to Files
- Inspecting the Update Status of Individual Rows
- Opening the Dataset in Batch Update Mode
- Using TADODataSet
- Connecting an ADO Dataset to a Data Store
- Using Command Objects
- Specifying the Command
- Using the Execute Method
- Canceling Commands
- Retrieving Result Sets with Commands
- Applying the Batch Updates to Base Tables
- Canceling Batch Updates
- Handling Command Parameters=== Using dbExpress Components Index===
- Using dbExpress Datasets
- Types of dbExpress Datasets
- Connecting to a Database Server Using dbExpress
- Setting Up TSQLConnection
- Specifying What Data to Display
- Representing the Results of a Query
- Representing the Records in a Table
- Representing the Results of a Stored Procedure
- Fetching the Data
- Executing Commands That Do Not Return Records
- Specifying the Command to Execute
- Executing the Command
- Creating and Modifying Server Metadata
- Setting Up Master-Detail Linked Relationships
- Accessing dbExpress Schema Information
- Fetching Metadata into a dbExpress Dataset
- The Structure of Metadata Datasets
- Debugging dbExpress Applications
Using Client Datasets Index
- Using Client Datasets — Overview
- Working with Data Using a Client Dataset
- Navigating Data in Client Datasets
- Limiting What Records Appear
- Editing Data
- Undoing Changes
- Saving Changes
- Constraining Data Values
- Sorting and Indexing
- Adding a New Index
- Deleting and Switching Indexes
- Using Indexes to Group Data
- Representing Calculated Values
- Using Internally Calculated Fields in Client Datasets
- Using Maintained Aggregates
- Specifying Aggregates
- Aggregating over groups of records
- Obtaining Aggregate Values
- Copying Data from Another Dataset
- Assigning Data Directly
- Cloning a Client Dataset Cursor
- Adding Application-specific Information to the Data
- Using a Client Dataset to Cache Updates
- Overview of Using Cached Updates
- Choosing the Type of Dataset for Caching Updates
- Indicating What Records Are Modified
- Updating Records
- Applying Updates
- Intervening as Updates Are Applied
- Reconciling Update Errors
- Using a Client Dataset with a Provider
- Specifying a Provider
- Requesting Data from the Source Dataset or Document
- Getting Parameters from the Application Server
- Passing Parameters to the Source Dataset
- Sending Query or Stored Procedure Parameters
- Limiting Records with Parameters
- Handling Constraints from the Server
- Refreshing Records
- Communicating with Providers Using Custom Events
- Overriding the Dataset On the Application Server
- Using a Client Dataset with File-based Data
- Creating a New Dataset
- Loading Data from a File or Stream
- Merging Changes into Data
- Saving Data to a File or Stream
- Using a Simple Dataset
- When to Use TSimpleDataSet
- Setting Up a Simple Dataset
Using Provider Components Index
- Using Provider Components
- Determining the Source of Data
- Communicating with the Client Dataset
- Choosing How to Apply Updates Using a Dataset Provider
- Controlling What Information Is Included in Data Packets
- Specifying What Fields Appear in Data Packets
- Setting Options That Influence the Data Packets
- Adding Custom Information to Data Packets
- Responding to Client Data Requests
- Responding to Client Update Requests
- Editing Delta Packets Before Updating the Database
- Influencing How Updates Are Applied
- Screening Individual Updates
- Resolving Update Errors On the Provider
- Applying Updates to Datasets That do Not Represent a Single Table
- Responding to Client-generated Events
- Handling Server Constraints
Creating Multi-Tiered Applications Index
- Creating Multi-tiered Applications — Overview
- Advantages of the Multi-tiered Database Model
- Understanding Multi-tiered Database Applications
- Overview of a Three-tiered Application
- The Structure of the Client Application
- The Structure of the Application Server
- Using Transactional Data Modules (COM)
- Data Module Lifetime Management
- Choosing a Connection Protocol
- Using dbExpress Connections
- Using DCOM Connections
- Using SOAP Connections
- Using Socket Connections
- Using Web Connections
- Building a Multi-tiered Application
- Creating the Server Application
- Filtering the DataSnap Communication Stream
- Setting Up the Data Module
- Configuring DataSnap Data Module
- Configuring TDSServerModule
- Configuring TRemoteDataModule
- Configuring TMTSDataModule
- Configuring TSOAPDataModule
- Using Multiple Server Data Modules (COM)
- Extending the Interface of the Application Server (COM)
- Managing Transactions in Multi-tiered Applications (COM)
- Supporting Master/detail Relationships
- Supporting State Information in Exposed Data Modules
- Registering the Application Server
- Creating the Client Application
- Connecting to the Application Server
- Specifying a Connection Using dbExpress
- Specifying a Connection Using DCOM
- Specifying a Connection Using Sockets
- Specifying a Connection Using HTTP
- Specifying a Connection Using SOAP
- Brokering Connections
- Managing Server Connections
- Connecting to the Server
- Dropping or Changing a Server Connection
- Calling Server Interfaces
- Connecting to an Application Server That Uses Multiple Data Modules
- Connecting to the Application Server
- Writing Web-based Client Applications
- Distributing a Client Application as an ActiveX Control
- Creating an Active Form for the Client Application
- Using an XML Broker
- Distributing a Client Application as an ActiveX Control
Using XML in Database Applications Index
- Using XML in Database Applications
- Defining Transformations
- Mapping Between XML Nodes and Data Packet Fields
- Using XMLMapper
- Converting XML Documents into Data Packets
- Using an XML Document as the Source for a Provider
- Using an XML Document as the Client of a Provider
Part III: Writing Internet Applications
Creating Internet Server Applications Index
- Creating Internet Applications — Overview
- About Web Broker
- Terminology and standards
- Terminology and Standards
- Parts of a Uniform Resource Locator
- HTTP Request Header Information
- HTTP server activity
- Composing Client Requests
- HTTP Server Activity
- Responding to Client Requests
- Serving Client Requests
- Types of Web Server Applications
- Debugging server applications
- Debugging Web Applications That Are DLLs
- Debugging Server Applications
Using Web Broker Index
- Using Web Broker
- Creating Web Server Applications with Web Broker
- The Web Application Object
- The Web Module
- The Structure of a Web Broker Application
- The Web Dispatcher
- Adding Actions to the Dispatcher
- Dispatching Request Messages
- Action Items
- Determining When Action Items Fire
- The Target URL
- The Request Method Type
- Enabling and Disabling Action Items
- Choosing a Default Action Item
- Responding to Request Messages with Action Items
- Determining When Action Items Fire
- Accessing Client Request Information
- Properties That Contain Request Header Information
- Properties That Identify the Target
- Properties That Describe the Web Client
- Properties That Identify the Purpose of the Request
- Properties That Describe the Expected Response
- Properties That Describe the Content
- The Content of HTTP Request Messages
- Properties That Contain Request Header Information
- Creating HTTP Response Messages
- Filling in the Response Header
- Indicating the Response Status
- Indicating the Need for Client Action
- Describing the Server Application
- Describing the Content
- Setting the Response Content
- Sending the Response
- Filling in the Response Header
- Generating the Content of Response Messages
- Using Page Producer Components
- HTML Templates
- Specifying the HTML Template
- Converting HTML-transparent Tags
- Using Page Producers from an Action Item
- Chaining Page Producers Together
- Using Predefined HTML-transparent Tag Names
- Using Page Producer Components
- Using Database Information in Responses
- Adding a Session to the Web Module
- Representing a Dataset in HTML
- Using Dataset Page Producers
- Using Table Producers
- Specifying the Table Attributes
- Specifying the Row Attributes
- Specifying the Columns
- Embedding Tables in HTML Documents
- Using TDataSetTableProducer
- Using TQueryTableProducer ===Using IntraWeb (VCL for the Web) Index===
- Getting started with IntraWeb
- Creating Web Server Applications Using IntraWeb
- Using IntraWeb Components
- Using IntraWeb with Web Broker ===Working with XML documents===
- Working with XML Documents
- Using the Document Object Model
- Working with XML Components
- Using TXMLDocument
- Working with XML Nodes
- Abstracting XML Documents with the Data Binding Wizard
- Using the XML Data Binding Wizard
- Using Code That the XML Data Binding Wizard Generates
Using Web Services Index
- Using Web Services
- Understanding Invokable Interfaces
- Using Nonscalar Types in Invokable Interfaces
- Registering Nonscalar Types
- Using Remotable Objects
- Remotable Object Example
- Using Nonscalar Types in Invokable Interfaces
- Writing Servers that Support Web Services
- Using the SOAP Application Wizard
- Adding New Web Services
- Using the WSDL Importer
- Defining and Using SOAP Headers
- Creating Custom Exception Classes for Web Services
- Generating WSDL Documents for a Web Service Application
- Writing Clients for Web Services
- Importing WSDL Documents
- Calling Invokable Interfaces
- Processing Headers in Client Applications
Working with Sockets
- Working with Sockets
- Installing Socket Components
- Implementing Services Overview
- Understanding Service Protocols
- Services and Ports
- Types of Socket Connections
- Client Connections
- Listening Connections
- Server Connections
- Describing Sockets
- Describing the Host
- Using Ports
- Using Socket Components — Overview
- Getting Information About the Client or Server Socket Connection
- Using Client Sockets
- Specifying the Desired Server
- Forming the Connection
- Getting Information About the Client Socket Connection
- Closing the Connection
- Using Server Sockets
- Specifying the Port
- Listening for Client Requests
- Connecting to Clients
- Closing Server Connections Overview
- Responding to Socket Events
- Error Events
- Client Events
- Server Events
- Reading and Writing Over Socket Connections — Overview
- Non-blocking Connections
- Reading and Writing Events
- Blocking Connections
- Non-blocking Connections
Part IV: Developing COM-based Applications Index
Overview of COM Technologies
- Overview of COM Technologies
- C++Builder Uses DAX for ActiveX and COM
- Parts of a COM Application
- COM Interfaces
- The Fundamental COM Interface, IUnknown
- COM Interface Pointers
- COM Servers
- CoClasses and Class Factories
- In-process, Out-of-process, and Remote Servers
- The Marshaling Mechanism
- Aggregation (COM)
- COM Clients
- COM Interfaces
- COM Extensions
- Automation Servers
- Active Server Pages
- ActiveX Controls
- Active Documents
- Type Libraries
- Implementing COM Objects with Wizards
- Code Generated by Wizards
- COM+ Event And Event Subscriber Objects
Working with Type Libraries
- Working with Type Libraries — Overview
- Type Library Editor
- Parts of the Type Library Editor
- Toolbar
- Object List Pane
- Status Bar
- Pages of Type Information
- Type Library Elements
- Parts of the Type Library Editor
- Using the Type Library Editor
- Valid Types
- Using Delphi or RIDL Syntax
- RIDL File
- GenTLB.exe
- SafeArrays
- Creating a New Type Library
- Opening an Existing Type Library
- Adding an Interface to the Type Library
- Modifying an Interface Using the Type Library
- Adding Properties and Methods to the Type Library
- Adding a CoClass to the Type Library
- Adding an Interface to a CoClass
- Adding an Enumeration to the Type Library
- Adding an Alias to the Type Library
- Adding a Record or Union to the Type Library
- Adding a Module to the Type Library
- Saving and Registering Type Library Information
- Apply Updates Dialog
- Saving a Type Library
- Refreshing the Type Library
- Registering the Type Library
- Deploying Type Libraries
Creating COM Clients
- Creating COM Clients
- Importing Type Library Information
- Code Generated When You Import Type Library Information
- Controlling an Imported Object
- Using Component Wrappers
- Writing Client Code Based On Type Library Definitions
- Connecting to a Server
- Controlling an Automation Server Using a Dispatch Interface
- Controlling an Automation Server Using a Dual Interface
- Handling Events in an Automation Controller
- Creating Clients for Servers That Do Not Have a Type Library
Creating Simple COM Servers
- Creating Simple COM Servers — Overview
- Designing a COM Object
- Using the COM Object Wizard
- Using the Automation Object Wizard
- COM Object Instancing Types
- Choosing a Threading Model
- Defining a COM Object’s Interface
- Managing Events in Your Automation Object
- Automation Interfaces
- Dual Interfaces
- Dispatch Interfaces
- Custom Interfaces
- Marshaling Data
- Registering a COM Object
- Current-User Registration for ActiveX Servers
- Testing and Debugging the Application
Creating an Active Server Page
- Creating an Active Server Object
- Creating Active Server Pages — Overview
- Using the ASP Intrinsics
- Creating ASPs for In-process or Out-of-process Servers
- Registering an Active Server Object
- Testing and Debugging the Active Server Page Application
Using ActiveX Controls
- Creating an ActiveX Control
- Elements of an ActiveX Control
- Designing an ActiveX Control
- Generating an ActiveX Control from a VCL Control
- Generating an Active Form Based on a VCL Form
- Licensing ActiveX Controls
- Customizing the ActiveX Control’s Interface
- Adding Additional Properties, Methods, and Events
- Adding Events
- Adding Properties
- Enabling Simple Data Binding with the Type Library
- Adding Additional Properties, Methods, and Events
- Creating a Property Page for an ActiveX Control
- Creating a New Property Page
- Adding Controls to a Property Page
- Associating Property Page Controls with ActiveX Control Properties
- Updating the Property Page
- Updating the Object
- Connecting a Property Page to an ActiveX Control
- Registering an ActiveX Control
- Testing an ActiveX Control
- Creating a 64-bit Windows C++ ActiveX Form or ActiveX Control (C++)
Part V: Component Writer’s Guide
- Introduction to Component Creation
- Object-oriented Programming for Component Writers
- Creating Properties
- Creating Events
- Creating Methods
- Using Graphics in Components
- Using Messages
- Making Components Available at Design Time
- Modifying an Existing Component
- Creating a Graphic Component
- Customizing a Grid
- Making a Control Data Aware
- Making a Dialog Box a Component
- Extending the IDE (Tools API)
- Deploying Components
- Packaging Components Or Libraries Written In Classic and Clang C++ Win32 Compilers
See Also
- Language Support for the RAD Studio Libraries (C++)
Добавил:
Upload
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
Скачиваний:
446
Добавлен:
11.06.2015
Размер:
1.3 Mб
Скачать
БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
МЕХАНИКО-МАТЕМАТИЧЕСКИЙ ФАКУЛЬТЕТ
Кафедра численных методов и программирования
ПРОГРАММИРОВАНИЕ В С++ BUILDER
Учебное пособие по курсу «МЕТОДЫ ПРОГРАММИРОВАНИЯ»
для студентов специальностей
G31 03 01 «Математика», G31 03 03 «Механика»
Минск
2007
УДК 004.43(075.8)
ББК 32.973.26-018.1я73 Б69
А в т о р ы :
В. С. Романчик, А. Е. Люлькин
Р е ц е н з е н т ы :
старший преподаватель Н. А. Аленский, кандидат физико-математических наук, доцент, зав. кафедрой информационных технологий БГУК П. В. Гляков
кандидат физико-математических наук, доцент С. В. Суздаль
Рекомендовано Ученым советом механико-математического факультета БГУ 2006 года, протокол № ___
Программирование в C++ BUILDER: учебное пособие для студ. механико-матем. фак. / В. С. Романчик, А.Е.Люлькин. Мн.: БГУ, 2007. –126 с.
ISBN 985-485-498-1.
В пособии рассматриваются вопросы, относящиеся к использованию технологии объект- но-ориентированного программирования в системе C++ Builder. Описание методологии построения классов и использования компонентов сопровождается многочисленными примерами. Предназначено для студентов 2-го курса механико-математического факультета, изучающих курс «Методы программирования».
УДК 004.43(075.8) |
|
ББК 32.973.26-018.1я73 |
|
©Романчик В.С., |
|
ISBN 985-485-498-1 |
Люлькин А.Е. |
БГУ, 2007 |
2
ВВЕДЕНИЕ
Основные характеристики С++Builder. C++Builder включает язык
C++, компилятор, интегрированную среду разработки приложений IDE (Integrated Development Environment), отладчик и различные инструмен-
ты. C++Builder содержит комплект общих элементов управления, доступ к Windows API, библиотеку визуальных компонентов VCL (Visual Component Library), компоненты и инструменты для работы с базами данных.
C++Builder добавляет к процессу программирования на языке C++ возможность быстрой визуальной разработки интерфейса приложений.
Кроме библиотек OWL (Object Windows Library) и MFC (Microsoft Foundation Classes), он использует библиотеку VCL и позволяет включить в форму диалоги с пользователем, оставляя разработчику для реализации только функциональную часть, воплощающую алгоритм решения задачи.
C++Builder имеет общую с Delphi библиотеку классов, часть из которых осталась написанной на языке Object Pascal. Благодаря этому, а также включению в С++Builder компиляторов С++ и Object Pascal, в приложениях можно использовать компоненты и код, написанные на
Object Pascal, а также формы и модули Delphi.
Компоненты C++Builder. Создание пользовательского интерфейса приложения заключается в добавлении в окно формы объектов, называемых компонентами. C++Builder позволяет разработчику создавать собственные компоненты и настраивать Палитру компонентов.
Компоненты разделяются на видимые (визуальные) и невидимые (невизуальные). Визуальные компоненты появляются как во время выполнения, так и во время проектирования. Невизуальные компоненты появляются во время проектирования как пиктограммы на форме. Они не видны во время выполнения, но обладают функциональностью. Для добавления компонента в форму можно выбрать мышью нужный компонент в Палитре компонентов и щелкнуть левой клавишей мыши в нужном месте проектируемой формы. Компонент появится на форме, и далее его можно перемещать и изменять. Каждый компонент C++ Builder имеет три характеристики: свойства, события и методы. Инспектор объ-
3
ектов автоматически показывает свойства и события, которые могут быть использованы с компонентом. Свойства являются атрибутами компонента, определяющими его внешний вид и поведение. Инспектор объектов отображает опубликованные (published) свойства компонентов на странице свойств (properties) и используется для установки publishedсвойств во время проектирования. Для изменения свойств компонента во время выполнения приложения нужно добавить соответствующий код. Помимо published-свойств, компоненты могут иметь открытые (public) свойства, которые доступны только во время выполнения приложения.
Рис. 1. Окно Инспектора объектов
События. Страница событий (Events) Инспектора объектов показывает список событий, распознаваемых компонентом и возникающих при изменении состояния компонента. Каждый экземпляр компонента имеет свой собственный набор функций — обработчиков событий. Создавая обработчик события, вы поручаете программе выполнить указанную функцию, если это событие произойдет. Чтобы добавить обработчик события, нужно выбрать компонент, затем открыть страницу событий Инспектора объектов и дважды щелкнуть левой клавишей мыши рядом с событием. Это заставит C++ Builder сгенерировать текст пустой функции с курсором в том месте, где следует вводить код. Далее нужно ввести код, который должен выполняться при наступлении данного события.
4
Среда разработки (IDE). C++ Builder представляет собой приложение, главное окно которого содержит меню (сверху), инструментальную панель (слева) и Палитру компонентов (справа). Помимо этого при запуске C++ Builder появляются окно Инспектора объектов и окно Object TreeView (слева), а также форма нового приложения (справа). Под окном формы приложения находится окно Редактора кода.
Рис. 2. Главное окно интегрированной среды разработки
Создание приложений в С++Builder. Первым шагом в разработке приложения C++ Builder является создание проекта. Чтобы создать новый проект, нужно выбрать пункт меню File|New| Application.
C++ Builder создает файл Project.bpr, а также головной файл проекта
Project.cpp, содержащий функцию WinMain(). Функция WinMain() в Windows-приложениях используется вместо функции main(). При добавление новой формы C++ Builder обновляет файл проекта и создает следующие дополнительные файлы:
•файл формы с расширением .dfm, содержащий информацию о форме;
•файл модуля с расширением .cpp, содержащий код на C++;
•заголовочный файл с расширением .h, содержащий описание класса формы.
5
Для того чтобы откомпилировать текущий проект, нужно выбрать пункт меню Compile. Для того чтобы откомпилировать проект и создать исполняемый файл, из меню Run нужно выбрать пункт Run. В результате выполнения будет получена следующая форма:
Рис. 3. Результат выполнения приложения
Структура файла проекта. Для каждого приложения C++Builder
создается xml-файл проекта Project.bpr и файл ресурсов. Еще один файл — головной файл проекта, содержащий функцию WinMain(), генерируется при выборе пункта меню File|New Application. Первоначально по умолчанию этому файлу присваивается имя Project1.cpp. Если в процессе разработки приложения добавляются формы и модули, C++Builder обновляет файл. Для просмотра файла следует выбрать пункт меню Project|View Source.
В головном файле проекта имеется определенный набор ключевых элементов:
•Директива препроцессора #include <vcl.h> предназначена для включения заголовочного файла, ссылающегося на описания классов библиотеки VCL.
•Директива #pragma hdrstop предназначена для ограничения списка заголовочных файлов, доступных для предварительной компиляции.
•Директива USEFORM показывает модули и формы используемые
впроекте.
•Директива USERES компилятора присоединяет файлы ресурсов к выполняемому файлу. При создании проекта автоматически создается файл ресурсов .res для хранения курсоров, пиктограмм и других ресурсов.
•Application->Initialize(). Это утверждение инициализирует приложение.
6
•Application->CreateForm(). Это утверждение создает форму приложения. Каждая форма в приложении имеет свое утверждение
CreateForm.
•Application->Run(). Это утверждение запускает приложение.
•Блок try…catch используется для корректного завершения приложения в случае возникновения ошибки.
Типичный головной файл проекта имеет следующий вид:
//Project1.cpp ———————————————————
#include <vcl.h> #pragma hdrstop USERES(«Project1.res»);
USEFORM(«Unit1.cpp», Form1); //—————————————————————————
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize(); Application->CreateForm(__classid(TForm1), &Form1); Application->Run();
}
catch (Exception &exception)
{ Application->ShowException(&exception); } return 0;
}
Структура файла Project1.bpr. Файл Project1.bpr представляет XML-проект (C++Builder XML Project), содержащий описание создаваемого приложения. Это текстовый файл, содержащий указания на то, какие файлы должны компилироваться и компоноваться в проект, а также пути к используемым каталогам.
Структура модуля. Модуль содержит реализацию функциональной части объекта на языке C++ и по умолчанию представляет собой файл Unit1.cpp. Каждый такой файл компилируется в объектный файл с расширением .obj. При добавлении к проекту новой формы генерируется новый модуль.
Имя исходного файла модуля и файла формы (*.dfm) должны быть одинаковыми. При создании обработчика событий в тексте модуля генерируется шаблон функции обработчика события, в который вводится код, выполняемый при наступлении обрабатываемого события.
Ниже приводится текст модуля, генерируемый для исходной формы:
//Unit1.cpp ————————————————————
#include <vcl.h> #pragma hdrstop
7
#include «Unit1.h»
#pragma package(smart_init) #pragma resource «*.dfm»
TForm1 *Form1;//указатель на объект
//—————————————————————————
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //реализация конструктора
Структура заголовочного файла. Заголовочный файл (файл с расширением .h, по умолчанию Unit1.h) генерируется при создании нового модуля и содержит описание класса формы. Такие описания генерируются автоматически и изменяются при внесении в форму новых компонентов или генерации новых обработчиков событий. В заголовочном файле содержится интерфейс, а в самом модуле – реализация методов.
При удалении из формы компонентов их описания удаляются из заголовочного файла. При переименовании компонентов изменяются их описания в заголовочном файле, а также имена и описания обработчиков событий. Однако при этом не изменяются ссылки на эти компоненты и обработчики событий, используемые в других функциях. В связи с этим рекомендуется переименовывать компоненты и обработчики событий сразу же после их создания, пока на них не появились ссылки.
В модуле могут содержаться классы и функции, не описанные в заголовочном файле, однако видимость их в этом случае ограничивается данным модулем.
Ниже приводится заголовочный файл для исходной формы:
//Unit1.h—————————————————————————
#ifndef Unit1H #define Unit1H
//—————————————————————————
#include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp>
class TForm1 : public TForm
{ |
|
__published: |
// IDE-managed Components |
private: // User declarations |
|
public: |
// User declarations |
__fastcall TForm1(TComponent* Owner);
}; //—————————————————————————
extern PACKAGE TForm1 *Form1; #endif
//—————————————————————————
8
Файл формы. Форма является одним из важнейших элементов приложения C++ Builder. Процесс редактирования формы происходит при добавлении к форме компонентов, изменении их свойств, создании обработчиков событий. Когда к проекту добавляется новая форма, создаются три отдельных файла: 1) файл модуля (*.cpp) содержит код методов, связанных с формой; 2) заголовочный файл (*.h) содержит описание класса формы; 3) файл формы (*.dfm) содержит сведения об опубликованных (доступных в Инспекторе объектов) свойствах компонентов, содержащихся в форме.
При добавлении компонента к форме заголовочный файл и файл формы модифицируются. При редактировании свойств компонента в Инспекторе объектов эти изменения сохраняются в файле формы.
Хотя в C++ Builder файл *.dfm сохраняется в двоичном формате, его содержание можно просмотреть с помощью редактора кода. Для этого нужно нажать правую клавишу мыши над формой и из контекстного меню формы выбрать пункт View as Text.
Ниже приводится листинг файла некоторой формы:
//Unit1.dfm—————————————————————————
object Form1: TForm1 Left = 197
Top = 358
Width = 544
Height = 181 Caption = ‘Form1’ Color = clBtnFace
Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11
Font.Name = ‘MS Sans Serif’ Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13
End
Простейшее приложение. Важнейшей особенностью C++Builder является автоматическая генерация кода программы. Когда к форме добавляете компонент, в тексте файла Unit1.h появляется объявление объекта класса данного компонента. Например, перенос на пустую форму компонента кнопки TButton сгенерирует объявление объекта Button1, а определение события OnClick – объявление метода ButtonlClick , являющегося обработчиком этого события.
9
Рассмотрим простейшее приложение. Создается форма для сложения двух чисел. Используются компоненты: TEdit – для ввода чисел и отображения результата; TLabel – для вывода строк “+” и “=”; TButton – кнопка, связанная с событием OnClick, для сложения чисел.
Будем использовать следующие свойства и методы для компонентов: TEdit: Name (имя объекта), ReadOnly (режим «только чтение»), Text
(текстовое поле);
TLabel: Caption (текстовое поле);
TButton: Caption (надпись на кнопке), OnClick (событие типа нажатия кнопки).
На рис. 4 приводятся окна Инспектора объектов в процессе работы со свойствами компонентов.
Двойной щелчок по компоненту Button1 приведет к выводу окна редактирования для Unit1.cpp и предложит определить тело метода Button1Click(), которое для рассматриваемой задачи должно иметь вид:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Edit3->Text=IntToStr(StrToInt(Edit1->Text)+StrToInt(Edit2->Text));
}
Рис. 4. Работа с компонентами Edit1 и Button1
10
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
®Никита КультинLJJВозможности среды разработ Программирование графики, мультимедиа и баз данных Создание справочной системы и установочного CD+CDU„.ешное освоение среды быстрой разработки приложенийУДК 681.3.068+800.92С++ ББК 32.973.26-018.1 К90 Культин Н. Б. Самоучитель C++ Builder. — СПб.: БХВ-Петербург, 2004. 320 с.: ил. ISBN 5-94157-378-2 Книга является руководством по программированию в среде Borland C++ Builder. В ней рассматривается весь процесс разработки программы — от
® Никита Культин
LJJ
<U
Возможности среды разработ
Программированиеграфики, мультимедиаи баз данных
Созданиесправочной системыи установочного CD
+CD
„.ешное освоение средыбыстрой разработки приложений
УДК 681.3.068+800.92С++ББК 32.973.26-018.1
К90
Культин Н. Б.К90 Самоучитель C++ Builder. — СПб.: БХВ-Петербург, 2004. —
320 с.: ил.
ISBN 5-94157-378-2
Книга является руководством по программированию в среде BorlandC++ Builder. В ней рассматривается весь процесс разработки программы —от компоновки диалогового окна и написания функций обработки событийдо отладки и создания справочной системы при помощи программыMicrosoft HTML Help Workshop и установочного CD-ROM в InstallShieldExpress, разбираются вопросы работы с графикой, мультимедиа и базамиданных, приведено описание процесса создания анимации в MacromediaFlash 5. Прилагаемый к книге компакт-диск содержит проекты, приведен-ные в издании в качестве примеров.
Для начинающих программистов
УДК 681.3.068+800.92С++ББК 32.973.26-018.1
Группа подготовки издания:
Главный редактор Екатерина КондуковаЗам. главного редактора Анатолий АдаменкоЗав. редакцией Григорий ДобинРедактор Галина СмирноваКомпьютерная верстка Ольги СергиенкоКорректор • Зинаида ДмитриеваДизайн обложки Игоря ЦырулышковаЗав. производством Ника/taii Тверских
Лицензия ИД № 02429 от 24.07.00. Подписано в печать 17.11.03.Формат 70х1001/1б. Печать офсетная. Усл. печ. л. 25,8.
Тираж 4000 экз. Заказ № 1252″БХВ-Петербург», 198005, Санкт-Петербург, Измайловский пр., 29.
Гигиеническое заключение на продукцию, товар № 77.99.02.953.Д.001537.03.02от 13.03.2002 г. выдано Департаментом ГСЭН Минздрава России.
Отпечатано с готовых диапозитивовв Академической типографии «Наука» РАН
199034, Санкт-Петербург, 9 линия, 12.
ISBN 5-94157-378-2 ® Культин н. Б., 2004© Оформление, издательство «БХВ-Петербург», 2004
Содержание
Предисловие 7
C++ Builder — что это? 7Об этой книге 8
ЧАСТЬ I. СРЕДА РАЗРАБОТКИ C++ BUILDER 9
Глава 1. Начало работы 10
Глава 2. Первый проект 14
Форма 14Компоненты 18Событие и функция обработки события 26Редактор кода 30
Система подсказок 31Навигатор классов 32Шаблоны кода 33
Справочная система 35Сохранение проекта 36Компиляция 38
Ошибки 39Предупреждения и подсказки. 41
Компоновка 41Запуск программы 42Ошибки времени выполнения 42Внесение изменений 48Настройка приложения 51
Название программы 51Значок приложения 51
Перенос приложения на другой компьютер 54Структура простого проекта 56
ЧАСТЬ II. ПРАКТИКУМ ПРОГРАММИРОВАНИЯ 61
Глава 3. Графика .- 62
Холст 62Карандаш и кисть 64Графические примитивы 65
Линия… -66
4! Содержание
Ломаная линия 66Прямоугольник 67Многоугольник 68Окружность и эллипс 69Дуга 70Сектор .70
) Текст 71Точка 74
Иллюстрации 77Битовые образы 82Мультипликация 87
Метод базовой точки 87Использование битовых образов 91
Загрузка битового образа из ресурса программы 94Создание файла ресурсов 94Подключение файла ресурсов 97
Глава 4. Мультимедиа 102
Компонент Animate 102Компонент MediaPlayer. 109
Воспроизведение звука 112Просмотр видеороликов 121
Создание анимации 128
Глава 5. Базы данных 134
База данных и СУБД 134Локальные и удаленные базы данных 134Структура базы данных 135Псевдоним 136Компоненты доступа и манипулирования данными 137Создание базы данных 137Доступ к базе данных 143Отображение данных 146Манипулирование данными 150Выбор информации из базы данных 153Перенос программы управления базой данных на другой компьютер 162
Глава 6. Компонент программиста 163
Выбор базового класса 163Создание модуля компонента 164Тестирование компонента 171Установка компонента 174
Ресурсы компонента 174Установка 176
Проверка компонента 178Настройка палитры компонентов 181
Содержание
Глава 7. Консольное приложение 183
Ввод/вывод 183Функция printf. 183Функция scan/ 186
Создание консольного приложения 187
Глава 8. Справочная система 193
Создание справочной системы при помощи Microsoft Help Workshop 193Подготовка справочной информации 194Проект справочной системы 197
Вывод справочной информации 201HTML Help Workshop 202
Подготовка справочной информации 203Использование Microsoft Word 204Использование HTML Help Workshop 205
Создание файла справки 209Компиляция 214
Вывод справочной информации 215
Глава 9. Создание установочного диска 217
Программа InstallShield Express 217Новый проект 218Структура 219Выбор устанавливаемых компонентов 222Конфигурирование системы пользователя 223Настройка диалогов * 225Системные требования…. 227Создание образа установочной дискеты 228
Глава 10. Примеры программ 230
Система проверки знаний 230Требования к программе 230Файл теста 231Форма приложения 234Отображение иллюстрации 235Доступ к файлу теста 236Текст программы 238
Игра «Сапер» .» 249Правила игры и представление данных 249Форма приложения 251Игровое поле 253Начало игры 254Игра 257Справочная информация 261Информация о программе 262Текст программы 266
Очистка диска 276
б Содержание
Приложение 1. C++ Builder — краткий справочник 283
Компоненты 283Форма 283Label 284Edit. 285Button ‘. 286Memo 287RadioButton 288Checkbox 289ListBox 290ComboBox 291StringGrid 292Image 293Timer : 294Animate 295MediaPlayer 295SpeedButlon 296UpDown 298Table 298Query 299DataSource 300DBEdit, DBMemo, DBText 300DBGrid 301DBNavigator 302
Графика 304Canvas • 304Pen 306Brush 307
Функции 307Функции ввода и вывода 307Математические функции 308Функции преобразования 309Функции манипулирования датами и временем 309
События 310Исключения 311
Приложение 2. Содержимое компакт-диска 313
Рекомендуемая литература 317
Предметный указатель 318
Предисловие
C++ Builder — что это?Интерес к программированию постоянно растет. Это связано с развитием ивнедрением в повседневную жизнь информационных технологий. Если че-ловек имеет дело с компьютером, то рано или поздно у него возникает же-лание, а иногда и необходимость, научиться программировать.
Среди пользователей персональных компьютеров в настоящее время наибо-лее популярна операционная система Windows, и естественно, что тот, ктохочет программировать, хочет и писать программы, которые будут работатьв Windows.
Несколько лет назад рядовому программисту оставалось только мечтатьо создании своих собственных программ, работающих в Windows. Единст-венным средством разработки был Borland C++ for Windows, явно ориенти-рованный на профессионалов, обладающих серьезными знаниями и опытом.
Бурное развитие вычислительной техники, потребность в эффективныхсредствах разработки программного обеспечения привели к появлению нарынке целого ряда систем программирования, ориентированных на так на-зываемую «быструю разработку», среди которых особо следует отметитьMicrosoft Visual Basic и Borland Delphi. В основе систем быстрой разработки(RAD-систем, Rapid Application Development — среда быстрой разработкиприложений) лежит технология визуального проектирования и событийногопрограммирования, суть которой заключается в том, что среда разработкиберет на себя большую часть работы по генерации кода программы, остав-ляя программисту работу по конструированию диалоговых окон и написа-нию функций обработки событий. Производительность программиста прииспользовании RAD систем фантастическая!
Успех и популярность Delphi вызвал желание фирмы Borland распростра-нить методы быстрой разработки на область профессионального програм-мирования, что и привело к появлению Borland C++ Builder.
8 Предисловие
C++ Builder — это среда быстрой разработки, в которой в качестве языкапрограммирования используется язык C++ Builder (C++ Builder Language).Не вдаваясь в подробности, можно сказать, что язык C++ Builder — эторасширенный C++. Например, в C++ Builder есть строковый (AnsiString) илогический (bool) типы, которых нет в классическом C++.
В настоящее время программистам стала доступна очередная, шестая версияпакета — Borland C++ Builder 6. Как и предыдущие версии, Borland C++ Buil-der 6 позволяет создавать различные программы: от простейших одноокон-ных приложений до программ управления распределенными базами.
Borland C++ Builder может работать в среде операционных систем от Win-dows 98 до Windows XP. Особых требований, по современным меркам,к ресурсам компьютера пакет не предъявляет: процессор должен быть типаPentium или Celeron (рекомендуется Pentium II 400 МГц); объем оперативнойпамяти должен составлять не менее 128 Мбайт (рекомендуется 256 Мбайт) исвободное дисковое пространство должно быть достаточным (для полнойустановки версии Enterprise необходимо приблизительно 750 Мбайт).
Об этой книгеКнига, которую вы держите в руках, — не описание среды разработки илиязыка программирования, а руководство, учебное пособие по основам про-граммирования в C++ Builder. В ней представлена концепция визуальногопроектирования и событийного программирования, а также рассмотренпроцесс создания программы от разработки диалогового окна и функцийобработки событий до создания справочной системы и установочногоCD-ROM.
Цель этой книги — познакомить читателя с технологией визуального проек-тирования и событийного программирования и показать на конкретныхпримерах возможности среды разработки, а также дать методику созданияпрограмм. Следует обратить внимание, что хотя книга ориентирована начитателя, обладающего определенными знаниями и начальным опытомв области программирования, она вполне доступна для начинающих.
часть I
Среда разработкиC++ Builder
В первой части книги приводится краткое описание среды разработкиC++ Builder; на примере программы вычисления силы тока в электрическойцепи демонстрируется технология визуального проектирования и событий-ного программирования; вводятся основные понятия и термины.
Глава 1. Начало работы
Глава 2. Первый проект•
ГЛАВА 1
Начало работы
Запускается C++ Builder обычным образом, т. е. выбором из меню BorlandC++Builder 6 команды C++Builder 6 (рис. 1.1).
Документы
Настройка
Найти
Справка
Выполнить…
Автозагрузка
Lgj Средства Microsoft Office
l£?) Стандартные
^ Internet Explorer
ЁЭ Microsoft Word
С^З Outlook Express
ЦЙ) Adobe Acrobat 4.0
l||jj Завершение работы…
Database Desktop
Datapump
Image Editor
Register Now
SQL Explorer
SQL Monitor
XML Mapper
Рис. 1.1. Запуск C++ Builder
Вид экрана после запуска C++ Builder несколько необычен (рис. 1.2). Вместоодного окна на экране появляются пять:
^
П главное окно — C++Builder 6;
П окно стартовой формы — Forml;
П окно редактора свойств объектов — Object Inspector;
Глава 1. Начало работы
П окно просмотра списка объектов — Object TreeView;
П окно редактора кода — Unitl.cpp.
Окно редактора кода почти полностью закрыто окном стартовой формы.
ГШШВЙЖШВВЗВЗЯИИИЙШГ -inixtI Не Edit Search Щ«ч &°ject Run Component : database Tools Window Це1р j i |<None> jj i S|i •’•’•.
‘ Q В? * H в 51 ‘ i? ‘ ‘ Ф • • Slando»:l lAddilional] Win32 j Siptfeml DataAccess] DataContralsj dbExoiess] DalaSnao) BDE jJ-Jt
• ^ j „ в, … . — ^ j К 1 дГ’ bj Л Hj :™l од ] jjf (J й ^S лп-м ™ :z7′ AlJ
J гг т..гт^ • ; i •f : . . ° . a — [_. . 2 » ..У £JJK .•£J
^] Fofml
Forml
Praperties j Events |
1Г AcJiveConlml : «~»)
! Align { aMone
> AlphaBlend ; false
i AlphaBlendVali255JBAnchois ]|akLeft.akfop]
i AutoScioll iliue
i AutoSize «falseI BiOiMode ;bdLel!ToHight
iHBordedcons ilbiSyslemMetiti,
BwdetWtdth ‘0
Caption ;Foim1 j j
? ‘
__.
_i
HI i M»1
1: 1 :Modified ‘Insert i\Unitl.cpp^LJnin.hXDiagiarn/ x
‘
Рис. 1.2. Вид экрана после запуска C++ Builder
В главном окне (рис. 1.3) находится меню команд, панели инструментови палитра компонентов.
Окно стартовой формы (Forml) представляет собой заготовку главного окнаразрабатываемой программы (приложения).
if. С ч- Builder 6 — Project I
File &* Search &w Eraject Run Component Qatabase lools Wndow Help !<None> _»] ] *> ‘
D н¥’Н1в5?’1^Й>!-<^- » Slandald i Additional 1 Win32] Svslemj Data Access) Dala Connote | dbExoress| DataSnaol BDE JLL±
. . ……….^.;.. „……, ,_ p] f % A [St fc| iJ IX № И Ньшар ~= ‘El
Панели инструментов Палитра компонентов
Рис. 1.3. Главное окно
Окно Object Inspector (рис. 1.4) — окно редактора свойств объектов предна-значено для редактирования значений свойств объектов. В терминологии
12 Часть I. Среда разработки C++ Builder
Объект (имя объекта)
jJFocm
: Properties Events )
II ActiveControl
\\ Align
;f AlphaBlend
1 AJphaBlendValij
iJElAnchors
.; AutoScroll
;| AutoSize
‘ BiDiMode
\ I Э В order! cons
i BorderStjJie’
iaINone
false
255
j [akLelt.akTop]
true
‘alse
bdLeftToRight
[biSystemMenu,
IbsSizeable
0
1 Caption
} iAII shown
i Forml _rj
Свойстваобъекта
Значениясвойств
Рис. 1.4. Ma вкладке Properties перечислены свойства объекта и указаны их значения
-1Й Projectl -Classes’!& Unitl.cpp)
j //_
!#include <vcl.h>:# pragma Mr stop
^include » U n i t i . h «I / / i
‘j#prisgrtia package (g i t ia r t_ ln iE)• # p r agifla г е з о ur с e » . df ш «iTForml *Forml;i /• /
fastcaJJ. TForml: :TFonnl (TComponent» рипег): TForm(Ouner)
//-
17: 4 ‘Modified ilnsert I \U niH. cpp /U nitl .h/Diagiam/
Рис. 1.5. Окно редактора кода
визуального проектирования объекты — это диалоговые окна и элементыуправления (поля ввода и вывода, командные кнопки, переключателии др.). Свойства объекта — это характеристики, определяющие вид, поло-жение и поведение объекта. Например, свойства width и Height задают раз-
Глава 1. Начало работы 13
мер (ширину и высоту) формы, свойства тор и Left — положение формы наэкране, свойство Caption — текст заголовка. В верхней части окна указанобъект (имя объекта), значения свойств которого отражены в окне ObjectInspector.
В окне редактора кода (рис. 1.5), которое можно увидеть, отодвинув в сто-рону окно формы, следует набирать текст программы. В начале работы надновым проектом окно редактора кода содержит сформированный C++ Buil-der шаблон программы.
ГЛАВА 2
Первый проект
Для демонстрации возможностей C++ Builder и технологии визуальногопроектирования и событийного программирования займемся разработкойпрограммы, используя которую можно вычислить силу тока в электриче-ской цепи. Сила тока вычисляется по известной формуле: I = U/R, где U -напряжение источника (вольт); R — величина сопротивления (Ом). Виддиалогового окна программы во время ее работы (после щелчка на кнопкеВычислить) приведен на рис. 2.1.
J*JВведите напряжение и величину сопротивления,затем щелкните на кнопке Вычислить
Напряжение (вольт)
Сопротивление (Ом)
Ток: 1,50 А
(Вы числить]] Завершить
Рис. 2.1. Окно программы вычисления силы тока в электрической цепи
Чтобы начать разработку нового приложения (так принято называть при-кладные программы), надо запустить C++ Builder или, если C++ Builderуже запущен, в меню File выбрать команду New | Application.
ФормаРабота над новым проектом (так в C++ Builder называется разрабатываемоеприложение) начинается с создания стартовой формы — главного окна про-граммы.
Глава 2. Первый проект 15
Стартовая форма создается путем изменения значений свойств формыForml (настройки формы) и добавления к форме необходимых компонентов(полей ввода, полей вывода текстовой информации, командных кнопок).
Основные свойства формы, которые определяют ее вид и поведение во вре-мя работы программы, приведены в табл. 2.1.
Таблица 2.1. Свойства формы (объекта TForm)
Свойство Описание
Name
Caption
Width
Height
Top
Left
BorderStyle
Borderlcons
Icon
Color
Font
Имя формы. В программе имя формы используется для управле-ния формой и доступа к компонентам формы
Текст заголовка
Ширина формы
Высота формы
Расстояние от верхней границы формы до верхней границы экрана
Расстояние от левой границы формы до левой границы экрана
Вид границы. Граница может быть обычной (bsSizeable), тонкой(bsSingle) или отсутствовать (bsNone). Если у окна обычная грани-ца, то во время работы программы пользователь может при помо-щи мыши изменить размер окна. Изменить размер окна с тонкойграницей нельзя. Если граница отсутствует, то на экран во времяработы программы будет выведено окно без заголовка. Положениеи размер такого окна во время работы программы изменить нельзя
Кнопки управления окном. Значение свойства определяет, какиекнопки управления окном будут доступны пользователю во времяработы программы. Значение свойства задается путем присвоениязначений уточняющим свойствам biSystemMenu, biMinimaze,biMaximaze и biHelp. Свойство biSystemMenu определяет доступ-ность кнопки Свернуть и кнопки системного меню, biMinimaze —кнопки Свернуть, biMaximaze — кнопки Развернуть, biHelp —кнопки вывода справочной информации
Значок в заголовке диалогового окна, обозначающий кнопку выво-да системного меню
Цвет фона. Цвет можно задать, указав название цвета или привяз-ку к текущей цветовой схеме операционной системы. Во второмслучае цвет определяется текущей цветовой схемой, выбраннымкомпонентом привязки и меняется при изменении цветовой схемыоперационной системы
Шрифт. Шрифт, используемый «по умолчанию» компонентами,находящимися на поверхности формы. Изменение свойства Fontформы приводит к автоматическому изменению свойства Fontкомпонента, располагающегося на поверхности формы. То естькомпоненты наследуют свойство Font от формы (имеется возмож-ность запретить наследование)
16 Часть I. Среда разработки C++ Builder
Для изменения значений свойств объектов, в том числе и формы, использу-ется вкладка Properties (Свойства) диалогового окна Object Inspector. В ле-вой колонке этой вкладки перечислены свойства выбранного объекта, вправой — указаны значения свойств.
При создании формы в первую очередь следует изменить значение свойстваcaption (Заголовок). В нашем примере надо заменить текст Forml на Силатока. Чтобы это сделать, нужно в окне Object Inspector щелкнуть левойкнопкой мыши в строке Caption (в результате будет выделено значениесвойства и появится курсор) и ввести текст: Сила тока (рис. 2.2).
AlphaBlenoValu255|C3Anchors
AutoScfollI AutoSise
BMode
;GDBorderlconsBorderStyle
BorderWidth
|[akLeft,akTop]: false
i false
jbdLeflToRighl
llbiSyslemMenu]ibsS ingle
io
J
I Caption 1 Сила тока!
f ClientHeight J173j CJientWidth ‘[323
I Color ‘QclBlnFace _^J
iAII shown
Рис. 2.2. Изменение значения свойства Caption путем ввода значения
Аналогичным образом можно установить значения свойств Height и width,которые определяют высоту и ширину формы. Размер формы, а также раз-мер других компонентов задают в пикселах, т. е. точках экрана. СвойствамHeight и width надо присвоить значения 200 и 330, соответственно.
Форма — это обычное окно. Поэтому размер формы можно изменить точнотак же, как размер любого окна Windows, т. е. путем перетаскивания грани-цы. По окончании перемещения границы значения свойств Height и widthавтоматически изменятся. Они будут соответствовать установленному раз-меру формы.
Положение диалогового окна на экране после запуска программы соответ-ствует положению формы во время разработки, которое определяется зна-чением свойств тор (отступ от верхней границы экрана) и Left (отступ отлевой границы экрана). Значения этих свойств также можно задать путемперемещения формы при помощи мыши.
При выборе некоторых свойств, например, Borderstyle, справа от текущегозначения свойства появляется значок раскрывающегося списка. Очевидно,что значение таких свойств можно задать путем выбора из списка (рис. 2.3).
Глава 2. Первый проект 17
Некоторые свойства являются сложными, т. е. их значение определяетсясовокупностью значений других (уточняющих) свойств. Например, свойствоBordericons определяет, какие кнопки управления окном будут доступны вовремя работы программы. Значения этого свойства определяется совокуп-ностью значений СВОЙСТВ MSystemMenu, biMinimize, biMaximize И biHelp, ка-ждое из которых, в свою очередь, определяет наличие соответствующей ко-мандной кнопки в заголовке окна во время работы программы. Перед име-нами сложных свойств стоит значок «+», в результате щелчка на которомраскрывается список уточняющих свойств (рис. 2.4), значения которыхможно задать обычным образом,(ввести в поле или выбрать в списке допус-тимых значений).
I Forml ^ F<
Properties | Events |
BiDiModeBBotderlcons
| В orderS tyle
BordeiWidthCaption
ClienSHeighlClientWidth
ColorS Constraints
DI3DCursor
i DefaultMonitor
;AH shown
Рис. 2.З. Установка значениясвойства путем выбора из списка
Form»!
Properties Events
BiDiMode ……. ibdLefttoRight ~»»^\BSorderlcons [biSystemMenu]
biSystemMentrue _
biMinirnizebiMaximize
biHelpBordeiStyleBorderWidthCaptionClientH eightClientWidth
Color
All shown
false
Рис. 2.4. Изменение значенияуточняющего свойства
В результате выбора некоторых свойств (щелчка кнопкой мыши на свойст-ве), рядом со значением свойства появляется командная кнопка с тремяточками. Это значит, что задать значение свойства можно в дополнитель-ном диалоговом окне, которое появится в результате щелчка на этой кноп-ке. Например, значение сложного свойства Font можно задать в окне ObjectInspector путем ввода значений уточняющих свойств, а можно воспользо-ваться стандартным диалоговым окном Шрифт, которое появится в резуль-тате щелчка на кнопке с тремя точками (рис. 2.5).
В табл. 2.2 перечислены свойства формы разрабатываемой программы, ко-торые следует изменить. Остальные свойства формы оставлены без измене-ния и в таблице не приведены. В приведенной таблице в именах некоторыхсвойств есть точка. Это значит, что надо задать значение уточняющегосвойства.
18 Часть I. Среда разработки C++ Builder
JForml Гг’.мг^
Properties j Events]
> Cufsor icrDefault
1 DefaultMonilor drrActiveFomi1 DockS ite (false
i PragKind ‘dkDiag
: DragMode idmManual
Enabled Uiue
JEFont :1ЖЯ Z.[ FoimStyle IfsNormal
[ Height 1200
< HelpConlext :0
i HelpFile
I HelpKeywotd ;
lAII shown
il
3
3
d
Рис. 2.5. Чтобы задать свойства шрифта, щелкните на кнопке стремя точками
Таблица 2.2. Значения свойств стартовой формы
Свойство
Caption
Height
Width
BorderStyle
Borderlcpns . biMinimize
Borderlcons . biMaximize
Font . Name
Font. Size
Значение
Сила тока
200
330
bsSingle
False
False
Tahoma
10
Комментарий
Тонкая граница не позволяетразмер окна во время работымы путем захвата и перемещения
изменитьпрограм-границы
В заголовке окна нет кнопки Свернуть
В заголовке окна нет кнопкинуть
Развер-
КомпонентыПрограмма вычисления тока в электрической цепи должна получить отпользователя исходные данные — напряжение и величину сопротивления.Эти данные могут быть введены с клавиатуры в поля редактирования. По-этому в форму надо добавить поле редактирования.
Поля редактирования, поля вывода текста, списки, переключатели, команд-ные кнопки и другие элементы пользовательского интерфейса называюткомпонентами.
Глава 2. Первый проект 19
Для того чтобы в форму разрабатываемого приложения добавить поле ре-дактирования, надо в палитре компонентов, на вкладке Standard, щелкнутьна значке компонента Edit (рис. 2.6), установить курсор в ту точку формы,в которой должен быть левый верхний угол компонента, и еще раз щелк-нуть кнопкой мыши. В результате на форме появляется компонент Edit -поле редактирования (рис. 2.7).
Standard :
ITEdit
Рис. 2.6. Компонент Edit — поле редактирования
: Ji. •diti
Рис. 2.7. Результат добавления в форму компонента Edit
Каждому добавленному компоненту автоматически присваивается имя, ко-торое состоит из названия компонента и его порядкового номера. Напри-мер, если к форме добавить два компонента Edit, то их имена будут Editi иEdit2. Программист путем изменения значения свойства Name может изме-нить имя компонента. Однако в простых программах имена компонентов,как правило, не изменяют.
Основные свойства компонента Edit приведены в табл. 2.3.
Таблица 2.3. Свойства компонента Edit (объект типа TEdit)
Свойство Определяет(задает)
Name Имя компонента. Используется в программе для доступа к компонен-ту и его свойствам, в том числе к тексту, который находится в полередактирования
Text Текст, который находится в поле ввода/редактирования
Left Расстояние от левой границы компонента до левой границы формы
Тор Расстояние от верхней границы компонента до верхней границы формы
20 Часть I. Среда разработки C++ Builder
Таблица 2.3 (окончание)
Свойство Определяет(задает)
Height Высоту поля
Width Ширину поля
Font Шрифт, используемый для отображения вводимого текста
ParentFont Признак
На рис. 2.8 приведен вид формы после добавления двух полей редактирова-ния. Один из компонентов выбран (выделен), окружен восемью маленькимиквадратиками. Свойства выбранного компонента отображаются в окнеObject Inspector. Чтобы увидеть и, если надо, изменить свойства другогокомпонента, надо этот компонент выбрать, щелкнув левой кнопкой мышина изображении компонента, или выбрать имя компонента в раскрываю-щемся списке, который находится в верхней части окна Object Inspector(рис. 2.9). Компонент, свойства которого надо увидеть или изменить, можновыбрать и в окне Object TreeView (рис. 2.10).
: jlditi
I»:dit2
Рис. 2.8. Форма с двумя компонентами
Значения некоторых свойств компонента, определяющих, например, размери положение компонента на поверхности формы, можно изменить при по-мощи мыши.
Для того чтобы изменить положение компонента, необходимо установитькурсор мыши на его изображение, нажать левую кнопку мыши и, удерживаяее нажатой, переместить контур компонента в нужную точку формы, а за-тем отпустить кнопку мыши. Во время перемещения компонента (рис. 2.11)отображаются текущие значения координат левого верхнего угла компонен-та (значения свойств Left и тор).
Для того чтобы изменить размер компонента, необходимо его выделить,установить указатель мыши на один из маркеров, помечающих границу
Глава 2. Первый проект
компонента, нажать левую кнопку мыши и, удерживая ее нажатой, изме-нить положение границы компонента. Затем отпустить кнопку мыши. Вовремя изменения размера компонента отображаются его текущие размеры:высота и ширина (значения свойств Height и width) (рис. 2.12).
;S Constraints
Cursor
DiagCursor
‘ DiagKind
DiagMpde
Enabled
El Font
| Height
lAII shown
iecNormal
QclWindow
[TSizeConstraini
true
crDefault
crDrag
.dkDrag
; drriManual
;true
jfTFontl
21
Рис. 2.9. Выбор компонентав окне Object Inspector
ШШ1,Ел
Рис. 2.10. Выбор компонентав окне Object TreeView
Editl
Edit2
Ш:1128, 1041
Editl
Edit2
Рис. 2.11. Отображение значений свойствLeft и Тор при изменении
положения компонента
Рис. 2.12. Отображение значений свойствHeight и Width при изменении
размера компонента
В табл. 2.4 приведены значения свойств компонентов Editl и Edit2 разраба-тываемого приложения (значения остальных свойств оставлены без измене-ния и поэтому в таблице не приведены). Компонент Editl предназначен дляввода величины напряжения, Edit2 — для ввода величины сопротивления.Обратите внимание, значением свойства Text обоих компонентов являетсяпустая строка. В результате форма разрабатываемого приложения должнавыглядеть так, как показано на рис. 2.13.
22 Часть I. Среда разработки C++ Builder
Таблица 2.4. Значения свойств компонентов Editl и sdit2
Text
Top •
Left
Width
Компонент
Editl
48
144
65
Edit2
72
144
65
EditlEdit2
Рис. 2.13. Форма после настройки компонентов Edit
Помимо полей редактирования в окне программы находится текст — крат-кая информация о программе и назначении полей ввода.
Для вывода текста на поверхность формы используют поля вывода текста.Поле вывода текста — это компонент Label. Значок компонента Label нахо-дится на вкладке Standard (рис. 2.14). Добавляется компонент Label в формуточно так же, как и поле редактирования. Основные свойства компонентаLabel перечислены в табл. 2.5.
Standard !
Label
Рис. 2.14. Компонент Label — поле вывода текста
Таблица 2.5. Свойства компонента Label
Свойство Определяет (задает)
Name Имя компонента. Используется в программе для доступа к свойст-вам компонента
Глава 2. Первый проект 23
Таблица 2.5 (окончание)
Свойство Определяет (задает)
Caption Отображаемый текст
Font Шрифт, используемый для отображения текста
ParentFont Признак наследования шрифта родительского компонента
AutoSize Признак того, что размер поля определяется его содержимым
Left Расстояние от левой границы поля вывода до левой границы формы
Тор Расстояние от верхней границы поля вывода до верхней границыформы
Height Высоту поля вывода
Width Ширину поля вывода
Wordwrap Признак того, что слова, которые не помещаются в текущей строке,автоматически переносятся на следующую строку (значение свой-ства AutoSize должно быть false)
Если поле Label должно содержать несколько строк текста, то перед тем какввести в поле текст (изменить значение свойства Caption), нужно присвоитьсвойству AutoSize значение false, а свойству wordwrap — true. Затем надоустановить требуемый размер поля (при помощи мыши или вводом значе-ний свойств Height и width) и только после этого ввести значение свойстваCaption.
В форму разрабатываемого приложения надо добавить четыре компонентаLabel. Поле Labeii предназначено для вывода информационного сообще-ния, поля Labei2 и Labels — для вывода информации о назначении полейввода, поле Labei4 — для вывода результата расчета (величины тока в цепи).После добавления компонентов надо выполнить их настройку — установитьзначения свойств (табл. 2.6). Прочерк в таблице означает, что значениесвойства оставлено без изменения или установлено автоматически — на-пример, как результат изменения другого свойства. В результате форма раз-рабатываемого приложения должна выглядеть так, как показано на рис. 2.15.
Таблица 2.6. Значения свойств компонентов Labell — Label!
Свойство
AutoSize
Wordwrap
Компонент
Labell
false
true
Label2
true
false
Label3
true
false
Label4
false
true,
24 Часть I. Среда разработки C++ Builder
Таблица 2.6 (окончание)
Свойство
Caption
Тор •
Left
Height
Width
Компонент
Label 1
Введите напряжениеи величину сопротивле-
ния, затем щелкнитена кнопке Вычислить
8
8
33
300
Label2
Напряжение(вольт)
56
8
16
120
Labels
Сопротивление(Ом)
80
8
16
120
Label4
112
8
16
200
Labell
LabeG
LabeB •
LabeH .
. Введите напряжение и величину сопротивления,затем щелкните на кнопюз Вычислить
•Напряжение (вольт)
-Сопротивление (Ом) • I
Рис. 2.15. Вид формы после добавления и настройки полей вывода текста
Последнее, что надо сделать на этапе создания формы — это добавить вформу две командные кнопки: Вычислить и Завершить. Назначение этихкнопок очевидно.
Командная кнопка — компонент Button — добавляется в форму точно также, как и другие компоненты. Значок компонента Button находится навкладке Standard (рис. 2.16). Основные свойства компонента Button приве-дены в табл. 2.7.
| Standard :
Button
Рис. 2.16. Командная кнопка — компонент Button
Глава 2. Первый проект 25
После добавления к форме двух командных кнопок нужно установить зна-чения их свойств в соответствии табл. 2.7.
Свойство
Таблица 2.7. Свойства компонента Button (командная кнопка)
Описание
Name Имя компонента. Используется в программе для доступа к компо-ненту и его свойствам
Caption Текст на кнопке
Enabled Признак доступности кнопки. Кнопка доступна, если значение свой-ства равно true, и недоступна, если значение свойства равно false
Left Расстояние от левой границы кнопки до левой границы формы
Тор Расстояние от верхней границы кнопки до верхней границы формы
Height Высота кнопки
Width Ширина кнопки
После добавления к форме двух командных кнопок нужно установить зна-чения их свойств в соответствии с табл. 2.8.
Окончательный вид формы разрабатываемого приложения приведен нарис. 2.17.
Label»! _L Введите напряжение и величину сопротивления,i • затем щелкните на кнопке Вычислить
Label2 —i— Напряжение (вольт)
Labels
LabeW
Editl
Edit2
Forml
Buttonl Button2
Рис. 2.17. Окончательный вид формы программы «Сила тока»
Завершив работу над формой, можно приступить к созданию программы.Но перед этим рассмотрим два важных понятия: событие и функцию обра-ботки события.
—сопротивление (.им; — |
. • • •
i • •
Вычислить | :
1 •
Завершить ; ! ! : ! ‘. ‘ . ‘ . ‘ . ‘ . ‘ . ‘ . ‘ . ‘ . ‘ . ‘ , \ .
26 Часть I. Среда разработки C++ Builder
Таблица 2.8. Значения свойств компонентов Button! и Button2
Свойство
Caption
Тор
Left
Height
Width
Компонент
Buttonl
Вычислить
144
16
25
75
Button2
Завершить
144
104
25
75
Событие и функция обработки событияВид созданной формы подсказывает, как работает приложение. Очевидно,что пользователь должен ввести в поля редактирования исходные данные ищелкнуть мышью на кнопке Вычислить. Щелчок на изображении команд-ной кнопки — эти пример того, что в Windows называется событием.
Событие (Event) — это то, что происходит во время работы программы.В C++ Builder каждому событию присвоено имя. Например, щелчок кноп-кой мыши — это событие onclick, двойной щелчок мышью — событиеOnDblClick.
В табл. 2.9 приведены некоторые события Windows.
Таблица 2.9. События
Событие Происходит
Onclick При щелчке кнопкой мыши
OnDblClick При двойном щелчке кнопкой мыши
OnMouseDown При нажатии кнопки мыши
OnMouseUp При отпускании кнопки мыши
OnMouseMove При перемещении мыши
OnKeyPress При нажатии клавиши клавиатуры
OnKeyDown При нажатии клавиши клавиатуры. События OnKeyDown иOnKeyPress — это чередующиеся, повторяющиеся события, кото-рые происходят до тех пор, пока не будет отпущена удерживаемаяклавиша (в этот момент происходит событие onKeyUp)
Глава 2. Первый проект £7
Таблица 2.9 (окончание)
Событие Происходит
OnKeyUp При отпускании нажатой клавиши клавиатуры
OnCreate При создании объекта (формы, элемента управления). Процедураобработки этого события обычно используется для инициализациипеременных, выполнения подготовительных действий
OnPaint При появлении окна на экране в начале работы программы; вовремя работы программы после появления окна (или его части),которое было закрыто другим окном или свернуто
OnEnter При получении элементом управления фокуса
OnExit При потере элементом управления фокуса
Реакцией на событие должно быть какое-либо действие. В C++ Builder ре-акция на событие реализуется как функция обработки события. Таким об-разом, для того чтобы программа выполняла некоторую работу в ответ надействия пользователя, программист должен написать функцию обработкисоответствующего события. Следует обратить внимание на то, что значи-тельную часть обработки событий берет на себя компонент. Поэтомупрограммист должен разрабатывать функцию обработки события только втом случае, если реакция на событие отличается от стандартной или неопределена. Например, если по условию задачи ограничений на символы,вводимые в поле Edit, нет, то процедуру обработки события onKeypressписать не надо, т. к. во время работы программы будет использованастандартная (скрытая от программиста) процедура обработки этого события.
Методику создания функций обработки событий рассмотрим на примерефункции обработки события onclick для командной кнопки Вычислить.
Чтобы приступить к созданию функции обработки события, сначала надовыбрать компонент, для которого создается функция обработки события.Выбрать компонент можно в окне Object Inspector или щелчком на изобра-жении компонента в форме. После этого в окне Object Inspector нужно вы-брать вкладку Events (События).
В левой колонке вкладки Events (рис. 2.18) перечислены события, которыеможет воспринимать выбранный компонент (имя и тип компонента указа-ны в верхней части окна). Если для события определена функция обработ-ки, то в правой колонке рядом с именем события будет выведено имя этойфункции.
Для того чтобы создать функцию обработки события, нужно сделать двой-ной щелчок мышью в окне Object Inspector, в поле функции обработки со-ответствующего события (рис. 2.19). В результате этого откроется окно ре-
28 Часть I. Среда разработки C++ Builder
дактора кода, в которое будет добавлен шаблон функции обработки собы-тия, а в окне Object Inspector рядом с именем события появится сгенериро-ванное C++ Builder имя функции обработки события (рис. 2.19).
Properties Events
Action i i
I QnClick l II
pnContextPopc
QnDragDrop j
OnDiagOver •
OnEndDock :
OnEndDrag ;
QnEnlet
OnExit
pnKeyDqwn i
OnKeyPress -.
OnKeyUp
OnMouseDowr
OnMouseMove
OnMouseUp
OnStaitDock I
; bnStaitprag ]
PopupMenu !
[All shown
—
Событие
Функция обработки события(в данном случае не определена)
Рис. 2.18. На вкладке Events перечислены события, которые может воспринимать компонент(в данном случае — командная кнопка)
j Button! П -*& «||n>1«nnl «» . _ .. — •
Properties Events j
! Acfcn ;:j OnCick :Bu«onl Click 3
I OnCortextPopi!
[ OnDragDrop \
‘*• QnDraoQver ‘
i [ OnEndDock ;
:j OnEndOrag ;
; OrtEnter
! OnExit;i OnKeyDown ;
i OnKeiPress j
1 OnKeyUp Г»
: OnMouseDowri
1 OnMouseMove
! OnMouseUp i
i OnStarlDock j
i OnStarlDrag 1
j PopupMenu •
|Ai shown .и
№ £} Projecti -Classes , ,„., r.:
;void fastcali TForml : : ButtonlClick (TObject *Sender)
:’.:>{
I)
//
-:
•• i
1 iI — I
|
‘ J JU
ijj 1 ±1
i 20: 1 Modified :|nsert |\Un»1.cpp/UnitThTDagr«ii7
Рис. 2.19. Шаблон функции обработки события, сгенерированный C++ Builder
C++ Builder присваивает функции обработки события имя, которое состоитиз двух частей. Первая часть имени идентифицирует форму, содержащую
Глава 2. Первый проект _ _ 29
объект (компонент), для которого создана процедура обработки события.Вторая часть имени идентифицирует сам объект и событие. В нашем при-мере имя формы — Formi, имя командной кнопки — But ton 1, а имя собы-тия — Click.
В окне редактора кода между фигурными скобками можно набирать инст-рукции, реализующие функцию обработки события.
В листинге 2.1 приведен текст функции обработки события Onclick длякомандной кнопки Вычислить. Обратите внимание на то, как представленапрограмма. Ее общий вид соответствует тому, как она выглядит в окне ре-дактора кода: ключевые слова выделены полужирным шрифтом, коммента-рии — курсивом (выделение выполняет редактор кода). Кроме того, инст-рукции программы набраны с отступами в соответствии с принятыми в сре-де программистов правилами хорошего стиля.
I Листинг 2.1. Простейшая обработка события Onclick на кнопке Вычислить
void _ fastcall TForml: :ButtonlClick (TObject *Sender)
{
float u; // напряжение
float r; // сопротивление
float i; // ток
// получить данные из полей ввода
u = StrToFloat (Editl-XText) ;
г = StrToFloat (Edit2->Text) ;
// вычислить ток
i = u/i;
.// вывести результат в поле метки
Label4->Caption = «Ток : » +
FloatToStrF(i,ffGeneral,7,2) + » А»;
Функция Buttoniciick выполняет расчет силы тока и выводит результатрасчета в поле Labei4. Исходные данные вводятся из полей редактированияEditi и Edit2 путем обращения к свойству Text. Свойство Text содержитстроку символов, которую ввел пользователь. Чтобы программа работалаправильно, пользователь должен ввести в каждое поле редактирования це-лое или дробное число в правильном формате (при вводе дробного числадля разделения целой и дробной частей надо использовать запятую). Таккак поле редактирования содержит текст (свойство Text строкового типа),
30 Часть I. Среда разработки C++ Builder
необходимо выполнить преобразование строки в число. Эту задачу решаетфункция StrToFioat, которой в качестве параметра передается содержимоеполя редактирования — значение свойства Text (Editl-xrext — это содер-жимое поля Editi). Функция strToFioat проверяет символы строки, пере-данной ей в качестве параметра, на допустимость и, если все символы вер-ные, возвращает значение, соответствующее строке, полученной в качествепараметра.
После того как исходные данные будут помещены в переменные и и г, вы-полняется расчет.
Вычисленная величина силы тока выводится в поле Label4 путем присваи-вания значения свойству caption. Для преобразования числа в строкусимволов (свойство caption — строкового типа) используется функцияFloatToStrF.
В листинге 2.2 приведена процедура обработки события Onclick на команд-ной кнопке Завершить. Создается она точно так же, как и процедура обра-ботки события onclick для командной кнопки Вычислить. В результатещелчка на кнопке Завершить программа должна завершить работу. Чтобыэто произошло, надо закрыть окно программы. Делает это метод close.
| Листинг 2.2. Процедура обработки события Onclick на кнопке Завершить
void fastcall TForml::Button2Click(TObject *Sender)
{
Forml->Close();
Редактор кодаВо время набора текста программы редактор кода автоматически выделяетэлементы программы: полужирным шрифтом — ключевые слова языка про-граммирования (if, else, int, float и др.), курсивом — комментарии. Этоделает текст программы более выразительным, что облегчает восприятиеструктуры программы.
В процессе разработки программы часто возникает необходимость переклю-чения между окном редактора кода и окном формы. Сделать это можно припомощи командной кнопки Toggle Form/Unit, которая находится на панелиинструментов View (рис. 2.20), или нажав клавишу <F12>. На панели инст-рументов View находятся командные кнопки View Unit и View Form, исполь-зуя которые можно выбрать нужный модуль или форму в случае, если про-ект состоит из нескольких модулей или форм.
Глава 2. Первый проект 31
View Form
View Unit Toggle Form/Unit
Рис. 2.20. Кнопка Toggle Form/Unit позволяет быстро переключатьсямежду формой и редактором кода
Система подсказокРедактор кода поддерживает функцию контекстно-зависимой подсказки,которая во время набора текста программы автоматически выводит краткуюсправочную информацию о свойствах и методах объектов, о параметрахфункций.
Например, после того как будет набрано имя объекта (компонента) и сим-волы ->, редактор кода автоматически выведет список свойств и методовобъекта (рис. 2.21). Программисту останется только выбрать из списка нуж-ный элемент и нажать клавишу <Enter> (быстро перейти к нужному эле-менту списка или к области, где этот элемент находится, можно, нажав кла-вишу, соответствующую первому символу этого элемента).
f\ а • ClassesUniH.cpp •
float u; // яалряжеяие
float г; // сопротивление
float i; // так
// получить данные из полей ввода
u — StcToFloat (Editl->)
TBasicAction» TControl: ActionFunction void TObiect;:AlterConjlruclion ()properly TAIign TControl::Alignproperly bool TWinConttol::AlignDi»abledproperly TAnchors TControl::Anchorsproperly TAnchors TEdil::Anchon
25: 27 iModified :lmert :\Unit1.cppAUniH.»h7Diagrann/
Рис. 2.21. Редактор кода автоматически выводит список свойств и методов объекта (компонента)
Следует обратить внимание, что если список свойств и методов не появля-ется, то это значит, что в программе обнаружена ошибка (C++ Builder кон-тролирует правильность набираемого программистом текста в «фоновом»
32 Часть I. Среда разработки C++ Builder
режиме). Например, если в окне редактора кода набрать if Editi->, то спи-сок свойств и методов объекта Editi не появится, т. к. инструкция if в дан-ном случае записана с ошибкой (не поставлена открывающая скобка послеif). C++ Builder информирует программиста об обнаруженной ошибке со-общением Unable to invoke Code Completion due to errors in sourcecode, которое появляется в нижней части окна редактора кода.
После набора имени встроенной или объявленной программистом функцииредактор кода также выводит подсказку: список параметров. Параметр, ко-торый в данный момент вводит программист, в подсказке выделен полу-жирным. Например, если набрать слово FioatToStrF, которое является име-нем функции преобразования дробного числа в строку символов, и откры-вающую скобку, то на экране появится окно, в котором будет указансписок параметров функции (рис. 2.22).
§ UniU.cpp
I a • ClassesUnitlcpp I
float и ;
float i; //
// получить далльге из полем вводзu = StrToFloat (Editl->Text) ;
и = StrToFloat (Edit2->Text) ;
// вычислить токi = u/ r ;
// вывести результат в поле меткиLabel4->Caption = long double Value, TFloatFormat Formatj int Precision int Digits
FioatToStrF (I
25: 27 iModilied i\UniH.cpp/Uniri.h/Diagrani7
Рис. 2.22. Пример подсказки
Навигатор классовОкно редактора кода разделено на две части (рис. 2.23). В правой части на-ходится текст программы. Левая часть, которая называется навигатор клас-сов (ClassExplorer), облегчает навигацию по тексту (коду) программы.В иерархическом списке, структура которого зависит от проекта, над кото-рым идет работа, перечислены объекты проекта (формы и компоненты) ифункции обработки событий. Выбрав элемент списка, можно быстро перей-ти к нужному фрагменту кода, например к функции обработки события.
Глава 2. Первый проект 33
|l amperZ .cpp
Компонент —
Функцияобработкисобытия
:-: Jjj Ampei2 • ClassesЭ |$) TForml• ; г> TButton «Button! ‘
•••• i.V TButton»Button2 if TEdif Editl
: -т,! TEdil’Edit2> Т Label «Label! !
i (j TLabel’ LabeG I
, i’j TLabel» LabeO ,
;— t’t TLabel» LabeW i
‘ : ф, void В uttonl Click!, voidButton2Click(‘
2J ampei2_.cpp I
else Key =0;
return Key;
j.. voidEdit2KeyPres;J
; TFofm1(TCornpont;Functions
!// Яажатие клавиши в поле Editl
void fastcauJL TForntl: : EditlKeyPress (TObject ^Sender, cha
if ( Key =•= VK_RETURM) <
Edit2->SetFocus();
return;
// остальные клавишиKey = IsRightF(Edit l->Text,Key) ;
;.V/-
:void fastcali TForml: : Button2Click(TObject: ^Sender)
Forml->Close() ;
_>J 101: 1 Modified Insert iVampetJL.cpp/ampei2_ h/Diagram/
Навигаторклассов
Рис. 2.23. Окно ClassExplorer облегчает навигацию по тексту программы
Окно навигатора классов можно закрыть обычным образом. Если окно на-вигатора классов не доступно, то для того чтобы оно появилось на экране,нужно в меню View выбрать команду ClassExplorer.
Шаблоны кодаВ процессе набора текста удобно использовать шаблоны кода (Code Temp-lates). Шаблон кода — это инструкция программы, записанная в общем ви-де. Например, шаблон для инструкции if выглядит так:
if О
else
Редактор кода предоставляет программисту большой набор шаблонов: объ-явления КЛаССОВ, ФУНКЦИЙ, ИНСТРУКЦИЙ Выбора (if, switch), ЦИКЛОВ (for,
23ак. 1252
34 Часть I. Среда разработки C++ Builder
while). Для некоторых инструкций, например для if и while, есть нескольковариантов шаблонов.
Для того чтобы в процессе набора текста программы воспользоваться шаб-лоном кода и вставить его в текст программы, нужно нажать комбинациюклавиш <Ctrl>+<J> и из появившегося списка выбрать нужный шаблон(рис. 2.24). Выбрать шаблон можно обычным образом, прокручивая список,или вводом первых букв имени шаблона (имена шаблонов в списке вы-делены полужирным). Выбрав в списке шаблон, нужно нажать клавишу<Enter>, шаблон будет вставлен в текст программы.
1 i amper .cpp..— .•::•::—,..- .. ,..:• —;_x|
S-(&l Amper • Classes
‘ l|
ВНННШ1ВВИШ№ШБ1К ~ -V ‘ «
float u; // напряжениеfloat r; // сопротивлениеfloat i,- ‘// гок
// получить яаиные из полей вводаu = StrToFloat (Editl->Text) ;г = StrToFloat (EcUt2->Text) ;
I// сопротивление не должно бить равно яулк
class declaration (all parts) classf *1} for statement (orb\// for (no opening/dosing braces) fors
function declaration function
if (no opening/closing braces) else (no opening/closing braces) lie «
29: 5 (Modified iinsert ! \ampei_.cppXampe_.h /{Diagrani/
.101×1
2
gj
Рис. 2.24. Список шаблонов кода отображается в результате нажатия <Ctrl>+<J>
| Description: |буква русского алФаеитс|
ОК Cancel
Рис. 2.25. В поля диалогового окна надо ввести имя шаблона и его краткое описание
Программист может создать свой собственный шаблон кода и использоватьего точно так же, как и стандартный. Для того чтобы создать шаблон кода,нужно в меню Tools выбрать команду Editor Options и в окне Code Insightщелкнуть на кнопке Add. В появившемся окне Add Code Template (рис. 2.25)надо задать имя шаблона (Shortcut Name) и его краткое описание (De-
Глава 2, Первый проект 35
scription). Затем, после щелчка на кнопке ОК, в поле Code надо ввести шаб-лон (рис. 2.26).
Editor Properties
General Display Key Mappings | С
\ Automatic features ~ ~
\ f? Code completion
j f? Code parameters
1 Tooltip expression evaluation
: f? Tooltip symbol jnsight
г Code templates
ШМШЯтШ’- \ \ I ‘•••’• ‘ • xl
D|0rs Code Insight |
fielay:
1. J…, ..
0.1 sec 1.5 sec
i Templates: Narne | Description *i fidd…
whiles while (no opening/closing braces) ( iif_rus буква русского алфавита — I — i i
ч 1 >Г^ Dejete | \
Code: i± ( ( => ‘ A ‘ )
{
}
±LJ
£S ( <= ‘ Я ‘ ) ) _^j |
— !••]•’.
^ JOK Cancel . Help
Рис. 2.26. Пример шаблона кода программиста
Справочная системаВ процессе набора текста программы можно получить справку о конструк-ции языка, типе данных, классе или функции. Для этого нужно в окне ре-дактора кода набрать слово, о котором надо получить справку (например,имя функции), и нажать клавишу <F1>. Так как с запрашиваемой темой всправочной системе может быть связано несколько разделов, на экране, какправило, появляется окно Найденные разделы (рис. 2.27), в котором можновыбрать нужный раздел. Следует обратить внимание на то, что после именифункции может быть указано имя библиотеки, к которой эта функция от-носится: VCL или CLX (вспомните: библиотека VCL используется при раз-работке приложений для Windows, a CLX — при разработке кроссплатфор-менных приложений). Поэтому, выбирая раздел справочной системы, надообращать внимание на то, к какой библиотеке он относится.
Справочную информацию можно получить также, выбрав из меню Helpкоманду C++ Builder Help. В этом случае на экране появится стандартноеокно справочной системы. В этом окне на вкладке Предметный указательнужно ввести ключевое слово, определяющее тему, по которой нужна
36 Часть I. Среда разработки C++ Builder
справка. В качестве ключевого слова можно ввести, например, первые не-сколько букв имени функции, свойства или метода (рис. 2.28).
Найденные разделы
Выберите раздел и нажмэте кнопку «Показать».
Показать Отмена
Рис. 2.27. В диалоговом окне следует уточнить раздел
Содержание Предметный указатель Поиск I
1. Введите первые буквы нужного слова.
jShowme
2. Выберите термин или Фразу и нажмите кнопку «Показать».
«[Application
exampleShowMessageFmtS howM essagePosShowMethod
I DesignerShowModal
exampleTCustomFofin
ShowPopupEditorTCustomDBGrid
ShowProgressDialogТ CuslomD ataS tore
ShowRootTCuslomTreeView
ShowShottCut
Показать Отмена
Рис. 2.28. Поиск справочной информации по ключевому слову
Сохранение проектаПроект — это набор файлов, используя которые компилятор создает выпол-няемый файл программы (ехе-файл). В простейшем случае проект состав-ляют: файл описания проекта (bpr-файл), файл главного модуля (срр-файл),
Глава 2. Первый проект 37
файл ресурсов (res-файл), файл описания формы (dfm-файл), заголовочныйфайл формы (h-файл) и файл описания функций формы (срр-файл).
Чтобы сохранить проект, нужно в меню File выбрать команду Save ProjectAs. Если проект еще ни разу не был сохранен, то C++ Builder сначала пред-лагает сохранить модуль (содержимое окна редактора кода) и поэтому наэкране появляется окно Save Unitl As. В этом окне (рис. 2.29) надо выбратьпапку, предназначенную для проектов, создать в ней папку для сохраняемо-го проекта, открыть ее и ввести имя модуля. В результате щелчка на кнопке
JJ.x|
Папка: t3 Ampei 4= О Ct Ш*
Amper_1у_..,..„-.п..,ч.„…….. .,..- ….. V. — _i —
Тип Файла; |O+Buiider unit («.cppj ~3 Отмена
Справка
Рис. 2.29. Сохранение модуля
Папка: £з| Amper и*
И,мя Файла: JAmpef I!
I Тип Файла: 1О+В uilder ptoject (*.bprj ^Т] Отмена
^правка
Рис. 2.30. Сохранение проекта
38 Часть I. Среда разработки C++ Builder
OK в указанной папке будут созданы три файла: срр, h и dfm, и на экранепоявится диалоговое окно Save Projectl As (рис. 2.30), в которое надо вве-сти имя проекта.
Обратите внимание, что имена файла модуля (срр) и файла проекта (bpr)должны быть разными, т. к. C++ Builder в момент сохранения файла проек-та создает одноименный срр-файл (файл главного модуля). Кроме того, на-до учесть, что имя генерируемого компилятором выполняемого файла сов-падает с именем проекта. Поэтому файлу проекта следует присвоить такоеимя, которое, по вашему мнению, должен иметь выполняемый файл про-граммы, а файлу модуля — какое-либо другое имя, например, полученноепутем добавления к имени проекта порядкового номера модуля.
КомпиляцияПроцесс преобразования исходной программы в выполняемую состоит издвух этапов: непосредственно компиляции и компоновки. На этапе компи-ляции выполняется перевод исходной программы в некоторое внутреннеепредставление. На этапе компоновки выполняется сборка (построение) про-граммы.
После ввода текста функции обработки события и сохранения проектаможно, выбрав в меню Project команду Compile, выполнить компиляцию.Процесс и результат компиляции отражается в диалоговом окне Compiling(рис. 2.31). Если ,в программе нет синтаксических ошибок, то окно будетсодержать сообщение: Done: Compile Unit, в противном случае будет выве-дено сообщение Done: There are errors.
; Project: F:4..ACBuildetG\PraiectsSAmper(Ampa_1.cpp
! Done: Theie are errors.
i Current line: 0 \ Total lines:
[Hints: 0 i Warnings: 1 ‘Errors:
74
1
OK
Рис. 2.31. Результат компиляции: в программе есть ошибки
В случае если компилятор обнаружит в программе ошибки и неточности,диалоговое окно Compiling будет содержать информацию о количестве син-таксических (Errors) и семантических (Warnings) ошибок, а также о числеподсказок (Hints). Сами сообщения об ошибках, предупреждения и под-сказки находятся в нижней части окна редактора кода.
Глава 2. Первый проект 39
Чтобы перейти к фрагменту кода, который, по мнению компилятора, со-держит ошибку, надо выбрать сообщение об ошибке (щелкнуть в строкесообщения левой кнопкой мыши) и из контекстного меню (рис. 2.32) вы-брать команду Edit Source.
В Amper_l.tpp
Vj Amper — ClassesAmperJ.cpp
!<
float u; // напряжениеfloat r: // сопротивлениеfloat i; // ток
// получить дакньге из полей вводаu = StrToFloat(Editl->Text);г = StrToFloac(Edit2->Text) ;
// вычислить ток View sourcei « u/r
mm
// вывести результат Clear MessagesLabel4->Capcion — «Tc Save Messages…
FloatTo3trF(i,fl »«—•»
Clear All Messages
Save All Messages…/ / . „.„ „ —
View Editor
34: 48 ~ :Modilied [insert, >/ Dockable
Ctrl+V
[C++ Warning] Amper_1 ,cpp(35): W8004 V is assigned a value (hat is never used
Рис. 2.32. Переход к фрагменту программы, который содержит ошибку
Процесс компиляции можно активизировать, выбрав в меню Run командуRun, которая запускает разрабатываемое приложение. Если будет обнаруже-но, что с момента последней компиляции в программу были внесены изме-нения или программа еще ни разу не компилировалась, то будет выполненакомпиляция, затем — компоновка, и после этого программа будет запущена(естественно, только в том случае, если в программе нет ошибок).
ОшибкиКомпилятор переходит ко второму этапу генерации выполняемой програм-мы только в том случае, если исходный текст не содержит синтаксическихошибок. В большинстве случаев в только что набранной программе естьошибки. Программист должен их устранить. Процесс устранения ошибокносит итерационный характер. Обычно сначала устраняются наиболее оче-видные ошибки, например, объявляются необъявленные переменные. Послеочередного внесения изменений в текст программы выполняется повторная
40 Часть I. Среда разработки C++ Builder
компиляция. Следует обратить внимание на то, что компилятор не всегдаможет точно локализовать ошибку. Поэтому, анализируя фрагмент про-граммы, который, по мнению компилятора, содержит ошибку, нужно об-ращать внимание не только на тот фрагмент кода, на который компиляторустановил курсор, но и на тот, который находится в предыдущей строке.Например, в следующем фрагменте кода:
// вычислить токi = u/r// вывести результат в поле меткиLabel4->Caption = «Ток : » +
FloatToStrF(i,ffGeneral,7,2) + » А»;
не поставлена точка с запятой после оператора присваивания. Компиляторэто обнаруживает, выводит сообщение statement missing ,-, но выделяетстроку Labei4->caption = «ток : » + и устанавливает курсор после иденти-фикатора Label 4.
В табл. 2.10 перечислены типичные ошибки и соответствующие им сообще-ния компилятора.
Таблица 2.10. Типичные ошибки
Сообщение Ошибка
Undefined symbol(неизвестный символ)
Statement missing ;(отсутствует точка с запятой)
Unterminated string orcharacter constant(незаконченная строковаяили символьная константа)
) expected(ожидается закрывающая скобка)
if statement missing ((в инструкции if нетоткрывающей скобки)
Compound statement missing }
Используется необъявленная переменнаяИмя переменной, функции или параметра за-писано неверно. Например, в программе объ-явлена переменная Summ, а в инструкциях ис-пользуется sum
После инструкции не поставлена точка с запя-той
В конце строковой константы, например, текстасообщения, нет двойных кавычек
При записи арифметического выражения, со-держащего скобки, нарушен баланс откры-вающих и закрывающих скобок
В инструкции if условие не заключено в скоб-ки
Нарушен баланс открывающих и закрывающихфигурных скобок. Вероятно, не поставленазакрывающая фигурная скобка отмечающаяконец функции или группы инструкций, напри-мер, после условия или слова else в инструк-ции if
Глава 2. Первый проект 41
Таблица 2.10 (окончание)
Сообщение Ошибка
Extra parameter in call to Неверно записана инструкция вызова функции,(лишний параметр при вызове указан лишний параметрфункции)
Если компилятор обнаружил достаточно много ошибок, то просмотрите всесообщения и устраните сначала наиболее очевидные ошибки и выполнитеповторную компиляцию. Вполне вероятно, что после этого количествоошибок значительно уменьшится. Это объясняется особенностями синтак-сиса языка, когда одна незначительная ошибка может «тащить» за собойдовольно большое количество других.
Предупреждения и подсказкиПри обнаружении в программе неточностей, которые не являются ошибка-ми, компилятор выводит подсказки (Hints) и предупреждения (Warnings).
Например, наиболее часто выводимой подсказкой является сообщение обобъявленной, но не используемой переменной ( . . . is declared but neverused.). Действительно, зачем объявлять переменную и не использовать ее?
В табл. 2. И приведены предупреждения, наиболее часто выводимые компи-лятором.
Таблица 2.11. Предупреждения компилятора
Предупреждение Вероятная причина
. . . is declared but never used
Possibly incorrect assignment. В условии, например, инструкции if,(вероятно, инструкция присваивания вместо оператора сравнения (==) ис-некорректная) пользован оператор присваивания (=)
Possibly use of … before definition. He присвоено начальное значение(вероятно, используется переменнойнеинициализированная переменная)
КомпоновкаЕсли в программе нет ошибок, то можно выполнить компоновку. Для этогонадо в меню Compile выбрать команду Make или Build. Разница междукомандами Make и Build заключается в следующем. Команда Make обеспе-
42 Часть I. Среда разработки C++ Builder
чивает компоновку файлов проекта, а команда Build — принудительнуюперекомпиляцию, а затем — компоновку.
На этапе компоновки также могут возникнуть ошибки. Чаще всего причинаошибок во время компоновки состоит в недоступности файлов библиотекили других ранее откомпилированных модулей. Устраняются эти ошибкипутем настройки среды разработки и включением в проект недостающихмодулей. В простых проектах ошибки времени компиляции, как правило,не возникают.
Запуск программыПробный запуск программы можно выполнить непосредственно из средыразработки, не завершая работу с C++ Builder. Для этого нужно в меню Runвыбрать команду Run или щелкнуть на командной кнопке Run (рис. 2.33).
ЦкИд!! i &Iffl:Run(F9)|
Рис. 2.33. Запуск программы из среды разработки
Ошибки времени выполненияВо время работы приложения могут возникать ошибки, которые называют-ся ошибками времени выполнения (run time errors) или исключениями (excep-tions). В большинстве случаев причинами исключений являются неверныеисходные данные.
Например, если во время работы программы вычисления силы тока в полеНапряжение ввести ю.5, т. е. разделить целую и дробную часть точкой, тов результате щелчка на кнопке Вычислить на экране появится окно с сооб-щением об ошибке (рис. 2.34).
‘10.5’ is not a valid floating point value.
Рис. 2.34. Пример окна с сообщением об ошибке времени выполнения(программа запущена из Windows)
Глава 2. Первый проект 43
Причина возникновения ошибки в следующем. В тексте программы дроб-ная часть числа от целой отделяется точкой. При вводе данных в поле ре-дактирования пользователь может отделить дробную часть числа от целойточкой или запятой. Какой из этих двух символов является правильным,зависит от настройки Windows.
Если в настройке Windows указано, что разделитель целой и дробной частейчисла — запятая (для России это стандартная установка), а пользовательиспользовал точку (ввел в поле Напряжение (Editi) строку ю.5), то привыполнении инструкции
u = StrToFloat(Editl-XText);
возникнет исключение, т. к. при указанной настройке Windows содержимоеполя редактирования и, следовательно, аргумент функции strioFioat неявляется изображением дробного числа.
Если программа запущена из среды разработки, то при возникновении ис-ключения выполнение программы приостанавливается и на экране появля-ется окно с сообщением об ошибке и ее типе. В качестве примера нарис. 2.35 приведено окно сообщения о возникновении исключения, причи-на которого заключается в том, что строка, введенная пользователем в полередактирования, не является дробным числом.
Debugger Exception Notification
Project Amper.exe raised exception class EConvertError with message «10.5* is not a valid floating pointvalue’. Process stopped. Use Step or Run to continue.
Г Sew CPU Window
Рис. 2.35. Пример сообщения о возникновении исключения (программа запущена из C++ Builder)
После возникновения исключения и щелчка на кнопке ОК в диалоговомокне Debugger Exception Notification (рис. 2.35) выполнение программыможно прервать или, несмотря на возникшую ошибку, продолжить. Чтобыпрервать выполнение программы, надо в меню Run выбрать командуProgram Reset, чтобы продолжить — команду Step Over.
Обработку исключений берет на себя автоматически добавляемый в выпол-няемую программу код, который обеспечивает, в том числе, и вывод ин-формационного сообщения. Вместе с тем C++ Builder дает возможностьпрограмме самой выполнить обработку исключения.
Инструкция обработки исключения выглядит так:
try
{// здесь инструкции, выполнение которых может вызвать исключение
44 Часть I. Среда разработки C++ Builder
catch ( Тип &е)
{// здесь инструкции обработки исключения
}
где:
П try — ключевое слово, обозначающее, что далее следуют инструкции,при выполнении которых возможно возникновение исключений, и чтообработку этих исключений берет на себя программа;
О catch — — ключевое слово, обозначающее начало секции обработки ис-ключения. Инструкции этой секции будут выполнены, если в программевозникнет исключение указанного типа.
Основной характеристикой исключения является его тип. В табл. 2.12 пере-числены наиболее часто возникающие исключения и указаны причины, ко-торые могут привести к их возникновению.
Таблица 2.12. Типичные исключения
Исключение Возникает
EConvertError — При выполнении преобразования, если преобразуемаяошибка преобразова- величина не может быть приведена к требуемому типу,ния Наиболее часто возникает при преобразовании строки
символов в число
EDivByZero — При выполнении операции целочисленного деления, еслицелочисленное делитель равен нулюделение на ноль
EZeroDivide — деле- При выполнении операции деления над дробными опе-ние на ноль рандами, если делитель равен нулю
EinOutError —ошибка При выполнении файловых операций. Наиболее частойввода/вывода причиной является отсутствие требуемого файла или, в
случае использования сменного диска, отсутствие дискав накопителе
В программе вычисления силы тока исключения могут возникнуть при вы-полнении преобразования строк, введенных в поля редактирования, в числаи при вычислении величины тока. Исключение EConvertError возникнет,если пользователь неправильно введет числа в поля редактирования: на-пример, разделит целую и дробную части точкой. Исключение EZeroDivideвозникнет, если пользователь задаст величину сопротивления равной нулю.
В листинге 2.3 приведена функция обработки события Onclick на команд-ной кнопке Вычислить. В функцию включены инструкции обработки ис-ключений.
Глава 2. Первый проект _ 45
\ Листинг 2.3. Обработка исключений
void _ fastcall TForml : :ButtonlClick (TObject *Sender)
{
float u; // напряжение
float r; // сопротивление
float i; // ток
// получить данные из полей ввода
// возможно исключение — ошибка преобразования строки в число
try
{u = StrToFloat'(Editl->Text) ;
г = StrToFloat(Edit2->Text) ;
}
catch (EConvertError &e)
{
ShowMessage («При вводе дробных чисел используйте запятую.»);
return;
}
// вычислить ток
// возможно исключение — деление на ноль
try
{i = u/r;
}
catch (EZeroDivide &e)
{
ShowMessage («Величина сопротивления не должна быть равна нулю») ;
Edit2->SetFocus () ; // курсор в поле Сопротивление
return;
// вывести результат в поле метки
Label4->Caption = «Ток : » + FloatToStrFd, ff General, 7, 3) ;
В приведенной функции для вывода сообщений в случае возникновенияисключений использована функция ShowMessage, которая выводит на экранокно с текстом и командной кнопкой ОК.
Инструкция вызова функции ShowMessage выглядит так:
ShowMessage (Сообщение) ;
Часть I. Среда разработки C++ Builder
Где сообщение — строковая константа (текст, который надо вывести). Нарис. 2.36 приведен вид окна сообщения, полученного в результате выполне-ния инструкции:
ShowMessage(«Величина сопротивления не должна быть равна нулю.»);
xj
Величина сопротивления не должна быть равна нулю.
! о’к
Рис. 2.36. Сообщение, выведенное функцией ShowMessage
Следует обратить внимание на то, что в заголовке окна сообщения, выво-димого функцией ShowMessage, указывается название приложения. Названиеприложения задается на вкладке Application окна Project Options. Еслиназвание приложения не задано, то в заголовке будет имя исполняемогофайла.
Для вывода сообщений можно использовать функцию MessageDlg. ФункцияMessageDlg позволяет поместить в окно с сообщением один из стандартныхзначков, например «Внимание», задать количество и тип командных кнопоки определить, какую из кнопок нажал пользователь. На рис. 2.37 приведеноокно, выведенное в результате выполнения инструкции
MessageDlg(«Файл с:\\temp\\test.txt будет удален.»,
mtWarning, TMsgDlgButtons() « mbOK « mbCancel, 0);
Файл ci\tem\test.txt будет удален.
Рис. 2.37. Пример окна сообщения
Значение функции MessageDlg — число, проверив значение которого можноопределить, выбором какой командной кнопки был завершен диалог.
В общем виде обращение к функции MessageDlg выглядит так:
Выбор:= MessageDlg(Сообщение, Тип, Кнопки, КонтекстСправки)
где:
П1 сообщение — текст сообщения;
П тип — тип сообщения. Сообщение может быть информационным, преду-преждающим или сообщением о критической ошибке. Каждому типу со-
Глава 2. Первый проект
общения соответствует определенный значок. Тип сообщения задаетсяименованной константой (табл. 2.13);
кнопки — кнопки, отображаемые в окне сообщения. Задаются операциейвключения в множество элементов — констант (табл. 2.14).
контекстсправки — параметр, который определяет раздел справочной ин-формации, который появится на экране, если пользователь нажмет кла-вишу <F1>. Если вывод справочной информации не предусмотрен, тозначение параметра должно быть равно нулю.
Таблица 2.13. Константы, определяющие тип сообщения
Константа Тип сообщения Значок
mtWarning
mtError
Внимание
Ошибка
mt Information
mt Confirmation
Mt Custom
Информация
Подтверждение
Обычное Без значка
Таблица 2.14. Константы, определяющие кнопки в окне сообщения
Константа
mbYes
mbNo
mbOK
mbCancel
mbHelp
Кнопка
Yes
No
OK
Cancel
Help
Константа
mbAbort
mbRetry
iriblgnore
mbAll
Кнопка
Abort
Retry
Ignore
All
Кроме приведенных констант можно использовать константы mbokcancel,mbYesNoCancel и mbAbortRetryignore. Эти константы определяют наиболеечасто используемые в диалоговых окнах комбинации командных кнопок.
Значение, возвращаемое функцией MessageDig (табл. 2.15), позволяет опре-делить, какая из командных кнопок была нажата пользователем.
48 Часть I. Среда разработки C++ Builder
Таблица 2.15. Значения функции MessageDig
Значение функции MessageDig
mr Abort
mrYes
mrOk
mrRetry
mrNo
mrCancel
mrlgnore
mrAll
Диалог завершен нажатием кнопки
Abort
Yes
Ok
Retry
No
Cancel
Ignore
All
Внесение измененийПосле нескольких запусков программы «Сила тока» возникает желание усо-вершенствовать программу, внести в нее изменения. Например, такие, что-бы после ввода напряжения в результате нажатия клавиши <Enter> курсорпереходил в поле Сопротивление, а после ввода сопротивления в результатенажатия этой же клавиши выполнялся расчет. Кроме того, было бы непло-хо, чтобы пользователь мог вводить в поля редактирования только числа.
Чтобы внести изменения в программу, нужно запустить C++ Builder и от-крыть соответствующий проект. Сделать это можно обычным способом,выбрав в меню File команду Open Project. Можно также воспользоватьсякомандой Reopen из меню File. При выборе команды Reopen открываетсясписок проектов, над которыми работал программист в последнее время.
В листинге 2.4 приведена программа «Сила тока», в которую внесены изме-нения: добавлены функции обработки событий onKeypress для компонен-тов Editi и Edit2. Чтобы добавить в программу функцию обработки собы-тия, надо в окне Object Inspector выбрать компонент, для которого нужносоздать функцию обработки события, на вкладке Events выбрать событие исделать двойной щелчок в поле рядом с именем события. C++ Builderсформирует шаблон функции обработки события. После этого можно вво-дить инструкции, реализующие функцию.
: ‘ •»»• • ……;
! Листинг 2.4. Функции обработки событий на компонентах формыI программы «Сила тока»
// щелчок на кнопке Вычислить
void fastcall TForml::ButtonlClick(TObject ^Sender)
Глава 2. Первый проект 49
float u; // напряжение
float r; // сопротивление
float i; // ток
// проверим, введены ли данные в поля Напряжение и Сопротивление
if ( ( (Editl-XText) .Length () = = 0 ) || ( (Edit2->Text) .Length () = 0) )
{
MessageDlg («Надо ввести напряжение и сопротивление»,
mtlnformation, TMsgDlgButtons () « mbOK, 0) ;
if ( (Editl->Text) .Length () == 0)
Editl->SetFocus ( ) ; // курсор в поле Напряжениеelse
Edit2->SetFocus ( ) ; // курсор в поле Сопротивлениеreturn;
// получить данные из полей ввода
u = StrToFloat (Editl->Text) ;
г = StrToFloat (Edit2->Text) ;
// вычислить силу тока
try
{i = u/r;
}
catch (EZeroDivide &e)
{
ShowMessage («Величина сопротивления не должна быть равна нулю») ;
Edit2->SetFocus ( ) ; // курсор в поле Сопротивление
return;
// вывести результат в поле Label4
Label4->Caption = «Ток : » +
FloatToStrF(i,ffGeneral,7,2) + » А»;
}
// нажатие клавиши в поле Напряжение
void __ fastcall TForml : :EditlKeyPress (TObject *Sender, char &Key)
{
// коды запрещенных клавиш заменим нулем, в результате
/ I символы этих клавиш в поле редактирования не появятся
II Key — код нажатой клавиши
I I проверим, является ли символ допустимым
50 Часть I. Среда разработки C++ Builder
if ( ( Key >= ‘0’) && ( Key <= ‘9’)) // цифра
return;
// Глобальная переменная Decimalseparator
I/ содержит символ, используемый в качестве разделителя
/I при записи дробных чисел
if ( Key == Decimalseparator)
if ( (Editl->Text).Pos(Decimalseparator) != 0)
Key =0; // разделитель уже введен
return;
if (Key == VK_BACK) // клавиша <Backspace>
return;
if ( Key == VK_RETURN) // клавиша <Enter>
{Edit2->SetFocus ( ) ;
return;
// остальные клавиши запрещены
Key =0; //не отображать символ
}
/ I нажатие клавиши в поле Сопротивление
void _ fastcall TForml : :Edit2KeyDown (TObject *Sender, WORD &Key,
TShiftState Shift)
{
if ( ( Key >= ‘0’) && ( Key <= ‘9’)) // цифра
return;
if ( Key == Decimalseparator) {
if ( (Edit2->Text) .Pos (Decimalseparator) != 0)
Key =0; // разделитель уже введен
return;
if (Key == VK_BACK) // клавиша <Backspace>
return;
if ( Key == VK_RETURN) // клавиша <Enter>
{
Buttonl->SetFocus ( ) ; // переход к кнопке Вычислить
/ I повторное нажатие клавиши <Enter>
/ / активизирует процесс вычисления тока
Глава 2. Первый проект _ 57
return;
// остальные клавиши запрещены
Key =0; //не отображать символ
}
II щелчок на кнопке Завершить
void _ fastcall TForml: :Button2Click(TObject *Sender)
{
Forml->Close ( ) ; // закрыть форму приложения
Настройка приложенияПосле того как программа отлажена, необходимо выполнить ее окончатель-ную настройку: задать название программы и значок, который будет изо-бражать исполняемый файл приложения в папке, на рабочем столе и на па-нели задач, во время работы программы.
Название программыНазвание программы отображается во время ее работы в панели задачWindows, а также в заголовках окон сообщений, выводимых функциейShowMessage.
Название программы надо ввести в поле Title (рис. 2.38) вкладки Applicationдиалогового окна Project Options, которое появляется в результате выборав меню Project команды Options.
Значок приложенияЧтобы назначить приложению значок, отличный от стандартного, нужно вменю Project выбрать команду Options и в открывшемся окне на вкладкеApplication щелкнуть на кнопке Load Icon. В результате этих действий от-кроется стандартное окно, используя которое можно просмотреть каталогии найти подходящий значок (значки хранятся в файлах с расширением ico).
В состав C++ Builder входит утилита Image Editor (Редактор изображений),при помощи которой программист может создать для своего приложенияуникальный значок. Запустить Image Editor можно из C++ Builder, выбрав вменю Tools команду Image Editor, или из Windows — командой Пуск | Про-граммы | Borland C++ Builder | Image Editor.
Чтобы начать работу по созданию нового значка, нужно в меню File вы-брать команду New | Icon File (рис. 2.39).
52 Часть I. Среда разработки C++ Builder
ппжяутшнчпяяштяжж^^^
Pascal | Linker | Advanced Linker ] Directories/Conditionals
Version Info I Packages | Т asm | CORBA | CodeGuard
Poems Application Compiler j Advanced Compiler | C++-
Application settings
x|
Title: I Сила тока
Help file: ~~
Output settings
Target file extension: exe
Load Icon…
Browse…
Г Default OK Cancel Help
Рис. 2.38. Название программы надо ввести в поле Title
|PImage EditorFile Window Help
Open,.. Ctrl+0
Exit Alt+X
Resource File (, res)
Component Resource File (.dcr)
Bitmap File (,bmp)
Cursor File (,cur)
Create a new icon file
Рис. 2.39. Начало работы над новым значком
Глава 2. Первый проект
После выбора типа создаваемого файла открывается окно Icon Properties(рис. 2.40), в котором необходимо выбрать характеристики создаваемогозначка: Size (Размер) — 32×32 (стандартный размер значков Windows) иColors (Палитра) — 16 цветов. В результате нажатия кнопки ОК открывает-ся окно Iconl.ico (рис. 2.41), в котором можно, используя стандартные ин-струменты и палитру, нарисовать нужный значок.
Icon Properties
-Size—Г 16 к 16 (small icon](f 32 x 32 (standatd icon)
•Colors’ —Г 2 color(f 16 color
Cancel
Рис. 2.40. Стандартные характеристики значка
£$5 Image Editor
File Edit Text View Icon W
ГГИП117ШИiX: 032 V: 033
Рис. 2.41. Начало работы над новым значком
Процесс рисования в Image Editor практически ничем не отличается отпроцесса создания картинки в обычном графическом редакторе, например вMicrosoft Paint. Однако есть одна тонкость. Первоначально поле изображе-ния закрашено «прозрачным» цветом. Если значок нарисовать на этом фо-не, то при отображении значка части поля изображения, закрашенные «про-зрачным» цветом, примут цвет фона, на котором будет находиться значок.
54 Часть I. Среда разработки C++ Builder
В процессе создания картинки можно удалить (стереть) ошибочно нарисо-ванные элементы, закрасив их прозрачным цветом, которому на палитресоответствует левый квадрат в нижнем ряду (рис. 2.42).
Кроме «прозрачного» цвета в палитре есть «инверсный» цвет. Нарисованныеэтим цветом части рисунка при выводе на экран будут окрашены инверс-ным относительно цвета фона цветом.
«Инверсный»
ummm^mmmmmrrmrmmm*
«Прозрачный» Основные цеета
Рис. 2.42. Палитра
Чтобы сохранить нарисованный значок, надо в меню File выбрать командуSave, в открывшемся диалоговом окне раскрыть папку проекта (приложе-ния, для которого создан значок) и задать имя файла значка, которое обыч-но совпадает с именем проекта (выполняемого файла приложения).
Перенос приложения на другой компьютерНебольшую программу, которая использует только стандартные компонен-ты и представляет собой один-единственный ехе-файл, можно перенести надругой компьютер вручную, например, при помощи дискеты. Как правило,при запуске таких программ на другом компьютере проблем не возникает.Вместе с тем, необходимо обратить внимание на следующее. Программа,созданная в C++ Builder, использует DLL версию библиотеки времени вы-полнения (RTL — Runtime Library) и специачьные динамические библиоте-ки — пакеты (например, в пакете VCL60 находятся наиболее часто исполь-зуемые компоненты и системные функции). Чтобы программа могла рабо-тать на другом компьютере, помимо ехе-файла на этот компьютер надоперенести RTL-библиотеку и используемые программой пакеты или вклю-чить библиотеку и пакеты в ехе-файл (что существенно увеличит размерехе-файла). Чтобы включить в выполняемый файл RTL-библиотеку и ис-пользуемые программой пакеты, надо в меню Project выбрать командуOptions и во вкладках Linker (рис. 2.43) и Packages (рис. 2.44) сбросить со-ответственно флажки Use dynamic RTL и Build with runtime packages. Послеэтого нужно выполнить перекомпоновку программы.
Сложные программы, например те, которые используют компоненты досту-па к базам данных, перенести на другой компьютер вручную проблематич-но. Для таких программ лучше создать установочную дискету (CD-ROM).Сделать это можно, например, при помощи пакета InstallShield Express, ко-торый входит в комплект поставки C++ Builder.
Глава 2. Первый проект 55
Project Options for Amper3.exe
Version Info j Packages
Forms j Application j
Pascal Linker ft
Г Linking
! 1*7 Create debug information
‘ г fi?e *!Н5’?ЖОi Г Use debug libraries
‘ Г! Г i * ^’ file
i» Map file ‘
I (f Off
i f Segments
! i™ Publics
! С Detailed
Г» Show mangled names
F Default
Tasm | CORBA | CodeGuaid
Compiler | Advanced Compiler ] C++
dvanced Linker | Directories/Conditionals
; i Warnings
i <~ АИ
! f Selected Warnings j
PE file options
M in stack size: j 0x00002000
Max stack size: J0x001 00000-iJ ! • .
Min heap size: [0x00001 000
Max heap size: 1 0x001 00000
Image base: j 0x00400000
Subsystem major: 1 4 «7-!
Subsvslem minor: JO
OK Cancel Help
Рис. 2.43. Чтобы включить в выполняемый файл RTL-библиотеку,сбросьте флажок Use dynamic RTL
Project Options For Project 1.еке
Forms j Application | Compiler | Advanced Compiler | C++
Pascal j Linker | Advanced Linker j Directories/Conditionals
Version Info Packages j Tasm ) CORBA | CodeGuaid
n Design packages —
Й Borland ADO DB Components
S Borland Base Cached ClientDataset Component
И Borland BDE DB Components
‘SI Borland C++Builder COM Server Components Sample Package
Й Borland C++Builder Internet Explorer 5 Components Package
| f:\pragram filesSborland^cbuildere^BinSdclactGO.bpl
Add… flemove 1 Components
Ryntime packages —
Г» Build with ruriliinr! packaged
Г Default OK Cancel Help
Рис. 2.44. Чтобы включить в выполняемый файл используемые программой пакеты(специальные DLL-библиотеки), сбросьте флажок Build with runtime packages
56 Часть I. Среда разработки C++ Builder
Структура простого проектаПроект представляет собой набор программных единиц — модулей.
Один из модулей, называемый главным, содержит инструкции, с которыхначинается выполнение программы. Чтобы увидеть главный модуль, нужнов меню Project выбрать команду View Source. В качестве примера в листин-ге 2.5 приведен текст главного модуля программы «Сила тока».
! Листинг 2.5. Главный модуль (Amper.cpp)
finclude <vcl.h>
fpragma hdrstop
USEFORM(«Amper_l.cpp», Forml);
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->Title = «Сила тока»;
Application->CreateForm( classid(TForml), SForml);
Application->Run();
}
catch (Exception Sexception)
{
Application->ShowException(Sexception);
}
catch (…)
{
try
{throw Exception(«»);
}
catch (Exception sexception)
{
Application->ShowException(sexception);
}
}
return 0;
Начинается главный модуль директивами компилятору (точнее, препроцес-сору). Директива #include <vcl.h> информирует компилятор, что перед тем
Глава 2. Первый проект 57
как приступить непосредственно к компиляции, в текст главного модулянужно включить заголовочный файл библиотеки визуальных компонен-тов — vci.h. Строка usEFORM(«Amper_i.cpp», Formi) указывает, что в проектнужно включить файл модуля формы Amper_l.cpp, который содержитфункции обработки событий для формы Forml. Далее следует описаниеглавной функции программы — winMain. Функция winMain инициализируетвнутренние структуры программы, создает форму Forml и запускает про-грамму, что приводит к появлению на экране стартовой формы. Так как впроекте «Сила тока» только одна форма, то на экране именно она и появля-ется. Инструкция обработки исключений catch выполняется, если в про-грамме возникает ошибка. Таким образом, главный модуль обеспечиваетвывод стартовой формы программы, дальнейшее поведение которой опре-деляют функции обработки событий стартовой формы.
Помимо главного модуля в состав проекта входят модули формы. Для каждойформы C++ Builder создает отдельный модуль, который состоит из двухфайлов: заголовочного файла и файла кода (содержимое этих файлов отража-ется в окне редактора кода). Заголовочный файл содержит описание формы(листинг 2.6), файл кода (модуль формы) — — описание (текст) функций,в том числе и обработки событий (листинг 2.7).
! Листинг 2.6. Заголовочный файл модуля формы (Amperjl.h)
#ifndef Amper_lH
ftdefine Amper_lH
#include <Classes.hpp>
#include «Controls.hpp>
ttinclude <StdCtrls.hpp>
#include <Forms.hpp>
class TForml : public TForm
{
_published: // IDE-managed Components
TLabel *Label1;
TLabel *Label2;
TLabel *Label3;
TEdit *Editl;
TEdit *Edit2;
TButton *Buttonl;
TButton *Button2;
TLabel *Label4;
void fastcall ButtonlClick(TObject *Sender);
void fastcall Button2Click(TObject *Sender);
58 _ Часть I. Среда разработки C++ Builder
private: // User declarations
public: // User declarations
_ fastcall TForral (TComponent* Owner) ;
extern PACKAGE TForml *Forml;
#endif
Г Листинг 2.7. Модуль формы (Amper_1.cpp)
#include <vcl.h>
tpragma hdrstop
iinclude «Amper_l . h»
#pragma package (smart_init)
#pragma resource «*.dfm»
TForml *Forml;
_ fastcall TForml: : TForml (TComponent* Owner)
: TForm (Owner)
// щелчок на кнопке Вычислить
void _ fastcall TForml: :ButtonlClick (TObject *Sender)
{
float u; // напряжение
float r; // сопротивление
float i; // сила тока
// получить данные из полей ввода
// возможно исключение
try
{u = StrToFloat (Editl-XText) ;
г = StrToFloat (Edit2->Text );
}
catch (EConvertError se)
{
ShowMes sage («При вводе дробных чисел используйте запятую.»)
return;
Глава 2. Первый проект _ _ 59
// вычислить силу тока
// возможно исключение
try
{i = u/r;
}catch (EZeroDivide &e)
{
ShowMessage ( «Сопротивление не должно быть равно нулю») ;Editl->SetFocus ( ) ; // курсор в поле Сопротивление
return;
// вывести результат в поле метки
Label4->Caption = «Ток : » +
FloatToStrF(i,ff General, 7,3) ;
// щелчок на кнопке Завершитьvoid _ fastcall TForml: :Button2Click(f Object *Sender)
{Forml->Close ( ) ; // закрыть окно программы
Следует отметить, что значительное количество работы по генерации про-граммного кода выполнил C++ Builder. Он полностью сформировал глав-ный модуль (Amper.cpp), заголовочный файл модуля формы (Amper_l.h),значительную часть модуля формы (Amper_l.cpp). Кроме того, C++ Builder,анализируя действия программиста, сформировал описание формы, файлпроекта и файл ресурсов проекта.
часть II
Практикумпрограммирования
Во второй части книги демонстрируется назначение и возможности базовыхкомпонентов, на конкретных примерах показано, как, используя эти базо-вые компоненты, создать программу, обеспечивающую отображение графи-ки, воспроизведение звука и анимации. Уделено внимание разработке при-ложений работы с базами данных. Показано, как создать справочную сис-тему и установочный CD.
Глава 3. Графика
Глава 4. Мультимедиа
Глава 5. Базы данных
Глава 6. Компонент программиста
Глава 7. Консольное приложение
Глава 8. Справочная система
Глава 9. Создание установочного диска
Глава 10. Примеры программ
ГЛАВА 3
Графика
C++ Builder позволяет программисту разрабатывать программы, которыеработают с графикой. В этой главе рассказывается, что надо сделать, чтобына поверхности формы появилась картинка, сформированная из графиче-ских примитивов, или иллюстрация, созданная в графическом редактореили полученная в результате сканирования фотографии.
ХолстПрограмма может вывести графику на поверхность формы (или компонентаimage), которой соответствует свойство canvas (Canvas — холст для рисова-ния). Для того чтобы на поверхности формы или компонента image появи-лась линия, окружность, прямоугольник или другой графический элемент(примитив), необходимо к свойству canvas применить соответствующий ме-тод (табл. 3.1).
Например, оператор
Forml->Canvas->Rectangle(10,10, 50, 50) ;
рисует на поверхности формы прямоугольник.
Таблица 3.1. Методы вычерчивания графических примитивов
Метод Действие
LineTo(x,y)
Rectangle(xl,yl,x2,у2)
Рисует линию из текущей точки в точку с ука-занными координатами
Рисует прямоугольник, xl, yl и х2, у2 — коор-динаты левого верхнего и правого нижнего уг-лов прямоугольника. Цвет границы и внутрен-ней области прямоугольника могут быть раз-ными
Глава 3. Графика 63
Таблица 3.1 (окончание)
Метод Действие
FillRect(xl,yl,х2,у2)
FrameRect(xl,yl,х2,у 2)
RounRect(xl,yl,x2,y2,x3,y3)
Ellipse(xl,yl,х2,у2)
Polyline(points,n)
Рисует закрашенный прямоугольник, xl, yl, x2,у2 — определяют координаты диагональныхуглов
Рисует контур прямоугольника, xl, yl, х2, у2 —определяют координаты диагональных углов
Рисует прямоугольник со скругленными углами
Рисует эллипс или окружность (круг), xl, yl,х2, у2 — координаты прямоугольника, внутрикоторого вычерчивается эллипс или, если пря-моугольник является квадратом, окружность
Рисует ломаную линию, points— массив типаTPoint. Каждый элемент массива представля-ет собой запись, поля х и у которой содержаткоординаты точки перегиба ломаной; n — коли-чество звеньев ломаной. Метод Polyline вы-черчивает ломаную линию, последовательносоединяя прямыми отрезками точки, координа-ты которых находятся в массиве: первую совторой, вторую с третьей, третью с четвертойи т. д.
Методы вывода графических примитивов рассматривают свойство canvasкак некоторый абстрактный холст, на котором они могут рисовать (Canvasпереводится как «поверхность», «холст для рисования»). Холст состоит изотдельных точек — пикселов. Положение пиксела на поверхности холстахарактеризуется горизонтальной (X) и вертикальной (Y) координатами. Ко-ординаты возрастают сверху вниз и слева направо (рис. 3.1). Левый верхнийпиксел поверхности формы (клиентской области) имеет координаты (О, О),правый нижний — (ciientwidth, ciientHeight). Доступ к отдельному пиксе-лу осуществляется через свойство Pixels, представляющее собой дву-мерный массив, элементы которого содержат информацию о цвете точекхолста.
Следует обратить внимание на важный момент. Изображение, сформиро-ванное на поверхности формы, может быть испорчено, например, в резуль-тате полного или частичного перекрытия окна программы другим окном.Поэтому программист должен позаботиться о том, чтобы в момент появле-ния окна программа перерисовала испорченное изображение. К счастью,операционная система Windows информирует программу о необходимостиперерисовки окна, посылая ей соответствующее сообщение, в результатечего возникает событие OnPaint. Событие OnPaint возникает и в момент за-
64 Часть II. Практикум программирования
пуска программы, когда окно появляется на экране в первый раз. Такимобразом, инструкции, обеспечивающие вывод графики на поверхность фор-мы, надо поместить в функцию обработки события onPaint.
(0,0) —’
,
pFoirol
(Form1->ClientWidth,Form1->ClientHeight)
Рис. 3.1. Координаты точек поверхности формы (холста)
Карандаш и кистьМетоды вычерчивания графических примитивов обеспечивают только вы-черчивание. Вид графического элемента определяют свойства Реп (каран-даш) и Brush (кисть) той поверхности (Canvas), на которой рисует метод.
Карандаш и кисть, являясь свойствами объекта canvas, в свою очередьпредставляют собой объекты Реп и Brush. Свойства объекта Реп (табл. 3.2)задают цвет, толщину и тип линии или границы геометрической фигуры.Свойства объекта Brush (табл. 3.3) задают цвет и способ закраски областивнутри прямоугольника, круга, сектора или замкнутого контура.
Таблица 3.2. Свойства объекта Реп (карандаш)
Свойство Определяет
Color Цвет линии
width Толщину линии (задается в пикселах)
Style Вид линии (psSolid— сплошная; psDash— пунктирная, длинныештрихи; psDot — пунктирная, короткие штрихи; psDashDot — пунк-тирная, чередование длинного и короткого штрихов; psDashDotDot —пунктирная, чередование одного длинного и двух коротких штрихов;psClear — линия не отображается (используется, если не надо изо-бражать границу области — например, прямоугольника)
Глава 3. Графика
Таблица 3.3. Свойства объекта Brush (кисть)
Свойство Определяет
Color Цвет закрашивания замкнутой области
style Стиль заполнения области (bsSolid — сплошная запивка.Штриховка: bsHorizontal — горизонтальная; bsVertical — верти-кальная; bsFDiagonal — диагональная с наклоном линий вперед;bsBDlagonal — диагональная с наклоном линий назад;bsCross — в клетку; bsDiagCross — диагональная клетка
Ниже приведена функция обработки события onPain, которая рисует на по-
верхности формы олимпийский флаг.
void _ fastcall TForml: :FormPaint (TObject *Sender)
{
// полотнище флага
Canvas->Pen->Width = 1;
Canvas->Pen->Color = clBlack;
Canvas->Brush->Color = clCream;
Canvas->Rectangle (30, 30, 150, 150) ;
Canvas->Pen->Width = 2; // ширина колец
Canvas->Brush->Style = bsClear; // чтобы круг, нарисованный
I / методом Ellipse, не был закрашен
// рисуем кольца
Canvas->Pen->Color = clBlue;
Canvas->Ellipse(40,40,80,80) ;
Canvas->Pen->Color = clBlack;
Canvas->Ellipse (70, 40, 110, 80) ;
Canvas->Pen->Color = clRed;
Canvas->Ellipse (100, 40, 140, 80) ;
Canvas->Pen->Color = clYellow;
Canvas->Ellipse (55, 65, 95, 105) ;
Canvas->Pen->Color = clGreen;
Canvas->Ellipse (85, 65, 125, 105) ;
Графические примитивыЛюбая картинка, чертеж или схема могут рассматриваться как совокупностьграфических примитивов: точек, линий, окружностей, дуг и др. Таким обра-зом, для того чтобы на экране появилась нужная картинка, программа
З З а к . 1252
66 Часть II. Практикум программирования
должна обеспечить вычерчивание (вывод) графических элементов — прими-тивов, составляющих эту картинку.
Вычерчивание графических примитивов на поверхности (формы или ком-понента image — области вывода иллюстрации) осуществляется применени-ем соответствующих методов к свойству Canvas этой поверхности.
ЛинияВычерчивание прямой линии выполняет метод LineTo. Метод рисует линиюиз той точки, в которой в данный момент находится карандаш (эта точканазывается текущей позицией карандаша или просто «текущей»), в точку,координаты которой указаны в инструкции вызова метода.
Например, оператор
Canvas-XLineTo(100,200)
рисует линию в точку с координатами (100, 200), после чего текущей стано-вится точка с координатами (100, 200).
Начальную точку линии можно задать, переместив карандаш в нужную точ-ку графической поверхности. Сделать это можно при помощи методаMoveTo, указав в качестве параметров координаты точки начала линии. На-пример, операторы
CanVas->MoveTo(10,10); // установить карандаш в точку (10,10)
Canvas->LineTo(50,10); // линия из точки (10,10) в точку (50,10)
рисуют горизонтальную линию из точки (10, 10) в точку (50, 10).
Используя свойство текущей точки, можно нарисовать ломаную линию.Например, операторы
Canvas->MoveTo(10,10);
Canvas->LineTo(50,10);
Canvas-XLineTo(10,20) ;
Canvas-XLineTo(50,20);
рисуют линию, похожую на букву Z.
Ломаная линияМетод Polyline вычерчивает ломаную линию. В качестве параметров методупередается массив типа TPoint, содержащий координаты узловых точек ли-нии, и количество звеньев линии. Метод Polyline вычерчивает ломануюлинию, последовательно соединяя точки, координаты которых находятсяв массиве: первую со второй, вторую с третьей, третью с четвертой и т. д.
Глава 3. Графика ^ 67
Например, приведенный ниже фрагмент кода рисует ломаную линию, со-стоящую из трех звеньев.
TPoint p[4]; // координаты начала, конца и точек перегиба
II задать координаты точек ломаной
р[0].х = 100; р[0].у = 100; // начало
р[1].х = 100; р[1].у = 150; // точка перегиба
р[2].х = 150; р[2].у = 150; // точка перегиба
р [ 3 ] . х = 150; р[3] .у = 100; // конец
Canvas->Polyline(р,3); // ломаная из трех звеньев
Метод Polyline можно использовать для вычерчивания замкнутых контуров.Для этого надо, чтобы первый и последний элементы массива содержаликоординаты одной и той же точки.
Прямоугольник
Метод Rectangle вычерчивает прямоугольник. В инструкции вызова методанадо указать координаты двух точек — углов прямоугольника. Например,оператор
Canvas->Rectangle(10,10, 50, 50)
рисует квадрат, левый верхний угол которого находится в точке (10, 10),а правый нижний в точке (50, 50).
Цвет, вид и ширину линии контура прямоугольника определяют значениясвойства Реп, а цвет и стиль заливки области внутри прямоугольника -значения свойства Brush той поверхности, на которой метод рисует прямо-угольник. Например, следующие операторы рисуют флаг Российской Феде-рации.
Canvas->Brush->Color = clWhite; // цвет кисти — белый
Canvas->Rectangle (10,10,90,30);
Canvas->Brush->Color = clBlue; // цвет кисти — синий
Canvas->Rectangle(10,30,90,50);
Canvas->Brush->Color = clRed; // цвет кисти — красный
Canvas->Rectangle(10,50,90,70);
Вместо четырех параметров — координат двух диагональных углов прямо-угольника — методу Rectangle можно передать один параметр — структурутипа TRect, поля которой определяют положение диагональных углов пря-моугольной области. Следующий фрагмент кода демонстрирует использова-ние структуры TRect в качестве параметра метода Rectangle.
68 Часть II. Практикум программирования
TRect ret; // прямоугольная область
ret.Top = 10;
ret.Left = 10;
ret.Bottom = 50;
ret.Right = 50;
Canvas->Rectangle(rct); // нарисовать прямоугольник
Есть еще два метода, которые вычерчивают прямоугольник. Метод FiiiRectвычерчивает закрашенный прямоугольник, используя в качестве инструмен-та только кисть (Brush), а метод FrameRect — только контур и используеттолько карандаш (Реп). У этих методов только один параметр — структуратипа TRect. Поля структуры TRect содержат координаты прямоугольнойобласти/Значения полей структуры TRect можно задать при помощи функ-ции Rect.
Например:
TRect ret; // область, которую надо закрасить
ret = Rect(10,10,30,50); // координаты областиCanvas->Brush->Color = clRed; // цвет закраски
Canvas->FillRect ( re t ) ;
Метод RoundRec вычерчивает прямоугольник со скругленными углами. Ин-струкция вызова метода RoundRec в общем виде выглядит так:
Canvas->RoundRec(xl,yl,х2,у2,хЗ,уЗ)
Параметры xl, yl, x2, y2 определяют положение углов прямоугольника, апараметры хЗ и уЗ — размер эллипса, одна четверть которого используетсядля вычерчивания скругленного угла (рис. 3.2).
i хЗ« и
уЗ
\(х2,у2)
Рис. 3.2. Метод RoundRec вычерчивает прямоугольник со скругленными углами
МногоугольникМетод Polygon вычерчивает многоугольник. Инструкция вызова метода вобщем виде выглядит так:Canvas->Polygon(p, п)
Глава 3. Графика 69
где р — массив записей типа TPoint, который содержит координаты вершинмногоугольника; п — количество вершин.
Метод Polygon чертит многоугольник, соединяя прямыми линиями точки,координаты которых находятся в массиве: первую со второй, вторую стретьей, третью с четвертой и т. д. Вид границы многоугольника определяютзначения свойства Реп, а вид заливки области, ограниченной линией грани-цы, — значения свойства Brush той поверхности, на которой метод ри-сует.
Ниже приведен фрагмент кода, который, используя метод Polygon, рисуетромб,
TPoint p [ 4 ] ; // четыре вершины
// координаты вершин
р [ 0 ] . х = 50; р [ 0 ] . у = 100;р[1].х = 150; р[1].у = 75;р [ 2 ] . х = 250; р [ 2 ] . у = 100;р [ 3 ] . х = 150; р [ 3 ] . у = 125;
Canvas->Brush->Color = clRed;
Canvas->Polygon(p,3);
Окружность и эллипсНарисовать эллипс или окружность (частный случай эллипса) можно припомощи метода Ellipse. Инструкция вызова метода в общем виде выглядитследующим образом:
Canvas->Ellipse(xl,yl,x2, y2)
Параметры xi, yi, x2, y2 определяют координаты прямоугольника, внутрикоторого вычерчивается эллипс или, если прямоугольник является квадра-том, — окружность (рис. 3.3).
(х2,у2) (х2,у2)
Рис. 3.3. Значения параметров метода Ellipse определяют вид геометрической фигуры
70 Часть II. Практикум программирования
Вместо четырех параметров — координат диагональных углов прямоуголь-ника — методу Ellipse можно передать один — объект типа TRect. Следую-щий фрагмент кода демонстрирует использование объекта TRect в качествепараметра метода Ellipse.
TRect rec = Rect(10,10,50,50);
Canvas->Ellipse(rec);
Как и в случае вычерчивания других примитивов, вид контура эллипса(цвет, толщину и стиль линии) определяют значения свойства Реп, а цвет истиль заливки области внутри эллипса — значения свойства Brush той по-верхности (canvas), на которой метод чертит.
ДугаМетод Arc рисует дугу — часть эллипса (окружности). Инструкция вызоваметода в общем виде выглядит так:
Canvas->Arc(xl,yl,x2,y2,x3,уЗ,х4,у4)
Параметры xl, yi, x2, y2 определяют эллипс (окружность), частью которогоявляется дуга. Параметры хз и уз задают начальную, а х4 и у4 — конечнуюточку дуги. Начальная (конечная) точка дуги — это точка пересечения гра-ницы эллипса и прямой, проведенной из центра эллипса в точку с коорди-натами хЗ и уЗ (х4, у4). Метод Arc вычерчивает дугу против часовой стрелкиот начальной точки к конечной (рис. 3.4).
Цвет, толщина и стиль линии, которой вычерчивается дуга, определяютсязначениями свойства Реп поверхности (canvas), на которую выполняетсявывод.
(хЗ.уЗ) (х4,у4)
(х4,У4) (хЗ.уЗ)
(х2,у2) (х2,у2)
Рис. 3.4. Значения параметров метода Arc определяют дугу как часть эллипса (окружности)
СекторМетод pie вычерчивает сектор эллипса или круга. Инструкция вызова мето-да в общем виде выглядит следующим образом:
Canvas->Pie(xl,yl,x2,у2,хЗ,уЗ,х4,у4)
Глава 3. Графика 71
Параметры xi, yi, x2, y2 определяют эллипс (круг), частью которого являет-ся сектор; хЗ, уз, х4 и у4 — прямые — границы сектора. Начальная точкаграниц совпадает с центром эллипса. Сектор вырезается против часовойстрелки от прямой, заданной точкой с координатами (хЗ, уз), к прямой, за-данной точкой с координатами (х4, у4) (рис. 3.5).
(хЗ.уЗ) (х4,У4)
(х4,У4) (хЗ.уЗ)
(х2,у2)
Рис. 3.5. Значения параметров метода Pie определяют секторкак часть эллипса (окружности)
(х2,у2)
ТекстВывод текста (строк типа Ansistring) на поверхность графического объектаобеспечивает метод TextoutA. Инструкция вызова метода TextoutA в общемвиде выглядит следующим образом:
Canvas-XTextOutA(х,у,Текст)
Параметр текст задает выводимый текст. Параметры х и у определяют коор-динаты точки графической поверхности, от которой выполняется выводтекста (рис. 3.6).
G++Builder Область вывода текстазакрашивается текущимцветом кисти
Canvas — поверхность формыили компонента Image
Рис. 3.6. Координаты области вывода текста
72 Часть II. Практикум программирования
Шрифт, который используется для вывода текста, определяется значениемсвойства Font соответствующего объекта canvas. Свойство Font представляетсобой объект типа TFont. В табл. 3.4 перечислены свойства объекта TFont,определяющие характеристики шрифта, используемого методом TextOutAдля вывода текста.
Таблица 3.4. Свойства объекта TFont
Свойство Определяет
Name Используемый шрифт. В качестве значения следует использовать на-звание шрифта (например, Arial)
size Размер шрифта в пунктах (points). Пункт— это единица измеренияразмера шрифта, используемая в полиграфии. Один пункт равен1/72 дюйма
style Стиль начертания символов. Может быть: нормальным, полужирным,курсивным, подчеркнутым, перечеркнутым. Стиль задается при помо-щи следующих констант: fsBold (полужирный), fsitalic (курсив),fsUnderline (подчеркнутый), fsStrikeOut (перечеркнутый)
Свойство Style является множеством, что позволяет комбинироватьнеобходимые стили. Например, инструкция, которая устанавливаетстиль «полужирный курсив», выглядит так:
Canvas->Font->Style =TFontStyles () «fsBold«fsUnderline
Color Цвет символов. В качестве значения можно использовать константутипа TColor
При выводе текста весьма полезны методы Textwidth и TextHeight, значе-ниями которых являются соответственно ширина и высота области выводатекста, которые, очевидно, зависят от характеристик используемого .шриф-та. Обоим этим методам в качестве параметра передается строка, которуюпредполагается вывести на поверхность методом TextOutA.
Следующий фрагмент кода демонстрирует использование методов, обеспе-чивающих вывод текста на поверхность формы. Приведенная функция об-работки события OnPaint закрашивает верхнюю половину окна белым, ниж-нюю — голубым цветом, затем в центре окна, по границе закрашенныхобластей, выводит текст (рис. 3.7).
void fastcall TForral::FormPaint(TObject *Sender)
AnsiString ms = «Borland C++Builder»;
TRect aRect;
int x,y; // точка, от которой будет выведен текст
Глава 3. Графика
// верхнюю половину окна красим белым
aRect = Rect(0,0,ClientWidth,ClientHeight/2);
Canvas->Brush->Color = clWhite;
Canvas->FillRect(aRect) ;
// нижнюю половину окна красим голубым
aRect = Rect(0,ClientHeight/2,ClientWidth,ClientHeight)
Canvas->Brush->Cblor = clSkyBlue;
Canvas->FillRect(aRect);
Canvas~>Font->Name = «Times New Roman»;
Canvas->Font->Size = 24;
// Canvas->Font->Style = TFontStyles()« fsBold « fsltalic;
// текст разместим в центре окна
х = (ClientWidth — Canvas-XTextWidth(ms)) /2;
у = ClientHeight/2 — Canvas-XTextHeight(ms) /2;
Canvas->Brush->Style = bsClear; // область вывода текста
// не закрашивать
Canvas->Font->Color = clBlack;
Canvas->TextOutA(x,y,ms); // вывести текст
TextOutA Demo
Borland C++Builder
Рис. З.7. Вывод текста
Иногда требуется вывести какой-либо текст после сообщения, длина кото-рого во время разработки программы неизвестна. В этом случае необходимознать координаты правой границы области выведенного текста. Координатыправой границы текста, выведенного методом TextOutA, можно получить,обратившись к свойству penPos.
Следующий фрагмент кода демонстрирует возможность вывода строки тек-ста ПрИ ПОМОЩИ ДВУХ ИНСТРУКЦИЙ TextOutA:
Canvas->TextOutA(10,10,»Borland «);
Canvas->TextOutA(Canvas->PenPos-x, Canvas->PenPos.у, «C++Builder»);
74 _ Часть II. Практикум программирования
ТочкаПоверхности, на которую программа может осуществлять вывод графики,соответствует объект canvas. Свойство pixels, представляющее собой дву-мерный массив типа TColor, содержит информацию о цвете каждой точкиграфической поверхности. Используя свойство pixels, можно задать цветлюбой точки графической поверхности, т. е. «нарисовать» точку. Например,инструкция
Canvas->Pixels[10] [10] = clRed
окрашивает точку поверхности формы в красный цвет.
Размерность массива Pixels определяется реальным размером графическойповерхности. Размер графической поверхности формы (рабочей области,которую также называют клиентской) определяют свойства ciientwidthи ciientHeight, а размер графической поверхности компонента image -свойства width и Height. Левой верхней точке рабочей области фор-мы соответствует элемент pixels [ О Н О ] , а правой нижней -Pixels [ClientWidth — 1} [CiientHeight -1].
Следующая программа (листинг 3.1), используя свойство pixels, строитграфик функции у = 2 sm(x) e*/5. Границы диапазона изменения аргументафункции являются исходными данными. Диапазон изменения значенияфункции вычисляется во время работы программы. На основании этих дан-ных программа вычисляет масштаб, позволяющий построить график такимобразом, чтобы он занимал всю область формы, предназначенную для вы-вода графика. Для построения графика используется вся доступная областьформы, причем если во время работы программы пользователь изменитразмер окна, то график будет выведен заново с учетом реальных размеровокна.
; ……. .;•»•,.—»…•; ……….. • ……….. ••,••.-:• ……………… ••••• ……. . …….. ………………….. • …………………. • ………….. ……….. …………………………….. . …………………… …… …………….. …
I Листинг 3.1. График функции
// обработка события OnPaintvoid _ fastcall TForml : : FormPaint (TObject *Sender) \
{G r a f i k ( ) ;
// обработка события OnResize
void _ fastcall TForml: : FormResize (TObject *Sender)
{
TRect ret = Rect (0,0, ClientWidth, CiientHeight) ;
Canvas ->FillRect (ret) ; // стеретьGrafikO ;
Глава 3. Графика 75
#include «math.h» // для доступа к sin и ехр
// функция, график которой надо построитьfloat f(float x)
<return 2*sin(x)*exp(x/5);
}
void TForml::Grafik()
{
float xl, x2; // границы изменения аргумента функции
float yl, y2; // границы изменения значения функции
float x; // аргумент функции
float у; // значение функции в точке х
float dx; // приращение аргумента
int I, b; // левый нижний угол области вывода графика
int w, h; // ширина и высота области вывода графика
float mx, my; // масштаб по осям X и Y
int xO, уО; // начало координат
// область вывода графика
1 = 10; // X — координата левого верхнего угла
Ъ = Forml->ClientHeight-20; // Y — координата левого нижнего угла
h = Forml->ClientHeight-40; // высота
w = Forml->Width — 20; // ширина
xl = 0; // нижняя граница диапазона аргумента
х2 = 25; // верхняя граница диапазона аргумента
dx = 0.01; // шаг аргумента
// найдем максимальное и минимальное значение
// функции на отрезке [xl,x2]
x = xl;
yl = f(x); // минимум
у2 = f (х); // максимум
do {
у = f (х);
if ( у < yl) yl = у;
if ( у > у2) у2 = у;
х += dx;
} while (x <= х2);
// вычислим масштабту = (float)h/abs(y2-yl); // масштаб по оси Y
mx = w/abs(x2-xl); // масштаб по оси X
76 Часть II. Практикум программирования
// оси
хО = 1+abs (xl*rnx) ;
уО = b-abs (yl*my) ;
Canvas->MoveTo (xO,b) ; Canvas ->LineTo (xO,b-h) ;
Canvas ->MoveTo (l,yO) ;Canvas->LineTo (l+w,yO) ;
Canvas->TextOutA(xO+5,b-h, FloatToStrF(y2, ff General, 6,3))
Canvas->TextOutA(xO+5,b, FloatToStrF(yl, ff General, 6, 3) ) ;
// построение графика
x = xl;
do {
У = f (x);
Canvas->Pixels [xO+x*mx] [yO-y*my] = clRed;
x += dx;
} while (x <= x2) ;
Основную работу выполняет функция Graf ik (ее объявление надо поместитьв раздел private объявления формы в заголовочном файле программы).Функция Grafik сначала вычисляет максимальное (у2) и минимальное (yi)значение функции на отрезке [xl, x2J. Затем, используя информацию о ши-рине и высоте области вывода графика, она вычисляет коэффициенты мас-штабирования по осям X и Y. После этого вычисляет координату Y гори-зонтальной оси, координату X вертикальной оси и вычерчивает координат-ные оси. Затем выполняется непосредственное построение графика (рис. 3.8).
График Функции
121.156
-227.103
Рис. 3.8. График, построенный по точкам
ВЫЗОВ фуНКЦИИ Grafik ВЫПОЛНЯЮТ фуНКЦИИ обработки СОбыТИЙ OnPaint И
OnResize. Функция TFormi:: Formpaint обеспечивает вычерчивание графика
Глава 3. Графика 77
после появления формы на экране в результате запуска программы, а такжепосле появления формы во время работы программы — например, в резуль-тате удаления или перемещения других окон, полностью или частично пере-крывающих окно программы. Функция TFormi: :FormResize обеспечивает вы-черчивание графика после изменения размера формы.
Приведенная программа универсальна. Заменив инструкции в теле функцииf ( х ) , можно получить график другой функции. Причем независимо от видафункции ее график будет занимать всю область, предназначенную для вы-вода. Следует обратить внимание на то, что приведенная программа работа-ет корректно, если функция, график которой надо построить, принимаеткак положительные, так и отрицательные значения. Если функция во всемдиапазоне только положительная или только отрицательная, то в программунеобходимо внести изменения. Какие — пусть это будет упражнением длячитателя.
ИллюстрацииНаиболее просто вывести иллюстрацию, которая находится в файле с рас-ширением bmp, jpg или ico, можно при помощи компонента image, значоккоторого находится на вкладке Additional палитры компонентов (рис. 3.9).Основные свойства компонента приведены в табл. 3.5.
Additional
Image
Рис. 3.9. Значок компонента Image
Таблица 3.5. Свойства компонента image
Свойство Описание
Picture Иллюстрация, которая отображается в поле компонента
Width, Height Размер компонента. Если размер компонента меньше размераиллюстрации и значение свойств AutoSize, Strech иProportional равно false, то отображается часть иллюстрации
Proportional Признак автоматического масштабирования картинки без иска-жения. Чтобы масштабирование было выполнено, значениесвойства AutoSize ДОЛЖНО быть false
Strech Признак автоматического масштабирования (сжатия или растя-жения) иллюстрации в соответствии с реальным размером ком-понента. Если размер компонента не пропорционален размеруиллюстрации, то иллюстрация будет искажена
78 Часть II. Практикум программирования
Таблица 3.5 (окончание)
Свойство Описание
AutoSize Признак автоматического изменения размера компонента всоответствии с реальным размером иллюстрации
Center Признак определяет расположение картинки в поле компонентапо горизонтали, если ширина картинки меньше ширины полякомпонента. Если значение свойства равно false, то картинкаприжата к правой границе компонента, если true — то картинкарасполагается по центру
visible Признак указывает, отображается ли компонент и, соответст-венно, иллюстрация на поверхности формы
Canvas Поверхность, на которую можно вывести графику
Иллюстрацию, которая будет выведена в поле компонента image, можно за-дать как во время разработки формы приложения, так и во время работыпрограммы.
Во время разработки формы иллюстрация задается установкой значениясвойства Picture путем выбора файла иллюстрации в стандартном диалого-вом окне, которое становится доступным в результате щелчка на команднойкнопке Load окна Picture Editor, которое, в свою очередь, появляется в ре-зультате щелчка на кнопке с тремя точками в строке свойства Picture(рис. 3.10).
Если размер иллюстрации больше размера компонента, то свойствуProportional нужно присвоить значение true. Тогда будет выполнено мас-штабирование иллюстрации в соответствии с реальными размерами компо-нента.
Чтобы вывести иллюстрацию в поле компонента image во время работыпрограммы, нужно применить метод LoadFromFile к свойству picture, указавв качестве параметра метода файл иллюстрации. Например, инструкция
Imagel->Picture->LoadFromFile(«e:\\temp\\bart.bmp»)
загружает иллюстрацию из файла bart.bmp и выводит ее в поле компонентавывода иллюстрации (Imagel).
По умолчанию компонент image можно использовать для отображения ил-люстраций форматов BMP, ICO и WMF. Чтобы использовать компонентдля отображения иллюстраций в формате JPEG (файлы с расширением jpg),надо подключить соответствующую библиотеку (поместить в текст про-граммы директиву ttinciude <jpeg.hpp>). Обратите внимание, что если ука-занной директивы в тексте программы не будет, то компилятор не выведетсообщения об ошибке. Но во время работы программы при попытке загру-
Глава 3. Графика 79
зить jpg-файл при помощи метода LoadFromriie возникнет ошибкаКЛЮЧеНИе EInvalidGraphic.
— ис-
[imagel Т;—,-
Properties j Everts |
Enabled jtrue^Height ‘ !105
HelpContext ‘0HelpKeyword
HelpType I htContextHintInctementalDisi falseLeft J72 ‘•».Name :lrnage1Pal entShowHJH truePicturePopupMenuProportional
j ShowHintj Stretch
Г Tagг TOP ;;j Transparent
Й shown
: lalse{false: false0
Ue•false
Picture Editor
Cancel
Help
(None)
Рис. 3.10. Чтобы выбрать иллюстрацию, щелкните в строке Picture на кнопке с тремя точками,затем в окне Picture Editor— на кнопке Load
‘ Просмотр иллюстраций
Padjpg
Рис. 3.11. Диалоговое окно программы Просмотр иллюстраций
Следующая программа (вид ее окна приведен на рис. 3.11, а текст — в лис-тинге 3.2) использует компонент image для отображения JPG-иллюстраций.
80 _ Часть II. Практикум программирования
Кнопка Каталог, в результате щелчка на которой появляется стандартноедиалоговое окно Выбор папки, позволяет пользователю выбрать каталог, вкотором находятся иллюстрации. Кнопка Дальше обеспечивает отображениеследующей иллюстрации.
! Листинг 3.2. Просмотр иллюстраций
#include <jpeg.hpp> // обеспечивает работу с JPEG-иллюстрациями
ffinclude <FileCtrl .hpp> // для доступа к функции SelectDirectory
AnsiString aPath; // каталог, в котором находится иллюстрация
TSearchRec aSearchRec; // результат поиска файла
void _ fastcall TForml: : FormCreate (TObject *Sender)
{
aPath = «»; // текущий каталог — каталог, из которого
I I запущена программа
Imagel->AutoSize = false;
Imagel->Proportional = true;
Button2->Enabled = false;
FirstPicture () ; // показать картинку, которая
// есть в каталоге программы
I I щелчок на кнопке Каталог
void _ fastcall TForml: :ButtonlClick (TObject ^Sender)
{
if (SelectDirectory (
«Выберите каталог, в котором находятся иллюстрации»,
«»,aPath) != 0)
<
// пользователь выбрал каталог и щелкнул на кнопке ОК
aPath = aPath + «\\»;
FirstPicture ( ) ; // вывести иллюстрацию
// найти и вывести первую картинку
void TForml : : FirstPicture ( )
{
Imagel->Visible = false; // скрыть компонент Imagel
Button2->Enabled = false; // кнопка Дальше недоступна
Labell->Caption = «»;
if ( FindFirst (aPath+ «*.jpg», faAnyFile, aSearchRec) == 0)
Глава 3. Графика 81
Imagel->Picture->LoadFromFile(aPath+aSearchRec.Name);
Imagel->Visible = true;
Labell->Caption = aSearchRec.Name;if ( FindNext(aSearchRec) ==0) // найти след, иллюстрацию
{
II иллюстрация есть
Button2->Enabled = true; // теперь кнопка Дальше доступна
II щелчок на кнопке Дальше
void _ fastcall TForrol: :Button2Click (TObject *Sender)
{
Imagel->Picture->LoadFromFile (aPath+aSearchRec.Name) ;
Labell->Caption = aSearchRec.Name;if ( FindNext (aSearchRec) != 0) // найти след, иллюстрацию
{
II иллюстраций больше нет
Button2->Enabled = false; // теперь кнопка Дальше недоступна
Загрузку и вывод первой и остальных иллюстраций выполняют соответст-венно функции FirstPicture И NextPicture.
Функция FirstPicture вызывает функцию FindFirst для того, чтобы полу-чить имя файла первой иллюстрации. В качестве параметров функцииFindFirst передаются:
П имя каталога, в котором должны находиться иллюстрации;
П структура aSearchRec, поле Name которой, в случае успеха, будет содер-жать имя файла, удовлетворяющего критерию поиска;
П маска файла иллюстрации.
Если в указанном при вызове функции FindFirst каталоге есть хотя быодин файл с указанным расширением, то значение функции будет равнонулю. В этом случае метод LoadFromFiie загружает файл иллюстрации. По-сле загрузки первой иллюстрации функция FirstPicture вызывает функциюFindNext для поиска следующего файла иллюстрации. Если файл будет най-ден, то кнопка Дальше будет сделана доступной.
Функция обработки события Onclick на кнопке Дальше загружает следую-щую иллюстрацию, имя файла которой было найдено функцией FindNextв процессе обработки предыдущего щелчка на кнопке Дальше, и снова вы-
82_ Часть II. Практикум программирования
зывает функцию FindNext для поиска следующей иллюстрации. Если файлиллюстрации не будет найден, то кнопка Дальше станет недоступной.
Необходимо обратить внимание на следующее. Для того чтобы иллюстра-ции отображались без искажения, свойству Autosize компонента imagei на-до присвоить значение false, а свойству Proportional — значение true.Сделать это можно во время создания формы в среде разработки (устано-вить значения свойств в окне Object Inspector) или возложить задачу на-стройки компонента на саму программу. В последнем случае в функциюобработки события OnCreate ДЛЯ формы (TForml: : FormCreate) НЗДО Добавить
следующие инструкции:
Imagel->AutoSize = false;
Imagel->Proportional = true;
Кроме того, во время создания формы свойству Enabled кнопки Дальше(Button2) надо присвоить значение false. Это обеспечит корректную работупрограммы в том случае, если в каталоге, из которого запускается про-грамма, нет иллюстраций. Настройку кнопки Button2 можно возложить наФУНКЦИЮ TForml: : FormCreate. ДЛЯ ЭТОГО В фунКЦИЮ НЗДО ДобаВИТЬ ОПС-
ратор
Button2->Enabled = false
Битовые образыДля формирования сложных изображений используют битовые образы. Би-товый образ — это, как правило, небольшая картинка, которая находитсяв памяти компьютера.
Сформировать битовый образ можно путем загрузки из bmp-файла или изресурса, а также путем копирования фрагмента из другого битового образа,в том числе и с поверхности формы.
Картинку битового образа (иногда говорят просто «битовый образ») можноподготовить при помощи графического редактора или, если предполагается,что битовый образ будет загружен из ресурса программы, — при помощиредактора ресурсов (например, Borland Resource Workshop). В последнемслучае надо создать файл ресурсов и поместить в него битовый образ. Файлресурсов можно создать и при помощи утилиты Image Editor.
В программе битовый образ — это объект типа TBitmap. Некоторые свойстваобъекта TBitmap приведены в табл. 3.6.
Загрузку картинки из файла обеспечивает метод LoadFromFile, которому вкачестве параметра передается имя bmp-файла. Например, следующийфрагмент кода обеспечивает создание и загрузку битового образа из файла.
Глава 3. Графика 83
Graphics::TBitmap *Plane = new Graphics::TBitmap();
Plane->LoadFromFile(«plane. 1
В результате выполнения приведенного выше фрагмента, битовый образPlane представляет собой изображение самолета (предполагается, что в фай-ле plane.bmp находится изображение самолета).
Таблица 3.6. Свойства объекта TBitmap
Свойство Описание
Height, widtlr Размер (ширина, высота) битового образа. Значения свойствсоответствуют размеру загруженной из файла (методLoadFromFile) ИЛИ ресурса (метод LoadFromResourcelD ИЛИLoadFromResourceName)картинки
Empty Признак того, что картинка в битовый образ не загружена(true)
Transparent Устанавливает (true) режим использования «прозрачного»цвета. При выводе битового образа методом Draw элементыкартинки, цвет которых совпадает с цветом TransparentColor,не выводится. По умолчанию значение TransparentColorопределяет цвет левого нижнего пиксела
TransparentColor Задает прозрачный цвет. Элементы картинки, окрашенныеэтим цветом, методом Draw не выводятся
Canvas Поверхность битового образа, на которой можно рисовать точ-но так же, как на поверхности формы или компонента image
После того как битовый образ сформирован (загружен из файла или из ре-сурса), его можно вывести, например, на поверхность формы или компо-нента Image. Сделать ЭТО МОЖНО, Применив метод Draw К СВОЙСТВУ Canvas.В качестве параметров методу Draw надо передать координаты точки, от ко-торой будет выведен битовый образ. Например, оператор
Canvas->Draw(10,20,Plane);
выводит на поверхность формы битовый образ Plane — изображение само-лета.
Если перед применением метода Draw свойству Transparent битового образаприсвоить значение true, то фрагменты рисунка, цвет которых совпадаетс цветом левой нижней точки рисунка, не будут выведены. Такой приемиспользуется для создания эффекта прозрачного фона. «Прозрачный» цветможно задать и принудительно, присвоив соответствующее значение свой-ству TransparentColor.
Следующая программа демонстрирует работу с битовыми образами. Послезапуска программы в ее окне появляется изображение неба и двух самоле-
84 Часть II. Практикум программирования
тов (рис. 3.12). И небо, и самолеты — это битовые образы, загруженные изфайлов во время работы программы. Загрузку и вывод битовых образов наповерхность формы выполняет функция обработки события onPaint, тексткоторой приведен в листинге 3.3. Белое поле вокруг левого самолета пока-зывает истинный размер битового образа Plane. Белого поля вокруг правогосамолета нет, т. к. перед тем как вывести битовый образ второй раз, свойст-ву Transparent было присвоено значение true.
1 Два самолета — I.P х
Рис. 3.12. Присвоив свойству Transparent значение true, можно скрыть фон
I Листинг 3.3. Загрузка и вывод битовых образов на поверхность формы
void fastcall TForrol::FormPaint(TObject ^Sender)
// битовые образы: небо и самолет
Graphics::TBitmap *sky = new Graphics::TBitmap();
Graphics::TBitmap *plane = new Graphics::TBitmap();
sky->LoadFromFile(«sky.bmp»);
plane->LoadFromFile(«plane.bmp»);
Canvas->Draw(0,0,sky); // фон — небо
Canvas->Draw(20,20,plane); // левый самолет
plane->Transparent = true;
/* теперь элементы рисунка, цвет которых совпадает
с цветом левой нижней точки битового образа,
не отображаются */
Canvas->Draw(120,20,plane); // правый самолет
// уничтожить объекты
sky->Graphics::~TBitmap();
plane->Graphics::-TBitmap();
Глава 3. Графика 86
Небольшие по размеру битовые образы часто используют при формирова-нии фоновых рисунков по принципу кафельной плитки (рис. 3.13).
Фоновый рисчнок
Рис. 3.13. Фоновый рисунок и битовый образ-плитка, из которого он составлен
Следующая программа показывает, как можно получить фоновый рисунокпутем многократного вывода битового образа на поверхность формы. Фор-мирование фонового рисунка, многократный вывод битового образа на по-верхность формы выполняет функция Background. Ее объявление (прототип),а также объявление битового образа (объекта типа TBitmap) надо поместитьв секцию private объявления класса формы (листинг 3.4), которая находит-ся в заголовочном файле. Создание битового образа и загрузку картинки изфайла выполняет функция обработки события OnCreate. Функция обработкисобытия OnPaint путем вызова функции Background обеспечивает вывод фо-нового рисунка на поверхность формы (листинг 3.5).
[Листинг 3.4. Объявление битового образа и функции Background
class TForml : public TForm
_published:
void fastcall FormCreate(TObject *Sender);
void fastcall FormPaint(TObject *Sender);
void fastcall FormResize(TObject *Sender);
private:
Graphics::TBitmap *back; // элемент фонового рисунка
void fastcall Background(); // формирует фоновый рисунок на
// поверхности формы
public:
fastcall TForml(TComponent* Owner);
86 Часть II. Практикум программирования
) Листинг 3.5. Функции, обеспечивающие формирование1 и вывод фонового рисунка
// обработка события OnCreate
void _ fastoall TForml: : FormCreate (TObject *Sender)
{back = new Graphics: :TBitmap() ; // создать объект — битовый образ
// загрузить картинку
try // в процессе загрузки картинки возможны ошибки
{
Forml->back->LoadFromFile («Legal.bmp») ;
}
catch (EFOpenError &e)
{
return;
// формирует фоновый рисунок
void _ fastcall TForml: : Background ()
{
int x=0,y=0; // координаты левого верхнего угла битового образа
if ( back->Empty) // ‘битовый образ не был загружен
return;
do {
do {
Canvas->Draw(x,y,back) ;
x += back->Width;
}
while (x < ClientWidth) ;
x = 0;
у += back->Height;
)
while (y < ClientHeight) ;
}
// обработка события OnPaint
void _ fastcall TForml: :FormPaint (TObject *Sender)
{
Background ( ) ; // обновить фоновый рисунок
Глава 3. Графика 87
МультипликацияПод мультипликацией обычно понимается движущийся и меняющийся ри-сунок. В простейшем случае рисунок может только двигаться или толькоменяться.
Обеспечить перемещение рисунка довольно просто: надо сначала вывестирисунок на экран, затем через некоторое время стереть его и снова вывестиэтот же рисунок, но уже на некотором расстоянии от его первоначальногоположения. Подбором времени между выводом и удалением рисунка, атакже расстояния между старым и новым положением рисунка (шага пере-мещения), можно добиться того, что у наблюдателя будет складываться впе-чатление, что рисунок равномерно движется по экрану.
Метод базовой точкиСледующая простая программа показывает, как можно заставить двигатьсяизображение, сформированное из графических примитивов. Окно и формапрограммы приведены на рис. 3.14.
Ш Кораблик
©!
№ Кораблик
Рис. 3.14. Окно и форма программы
На поверхности формы находится один-единственный компонент Timer,который используется для генерации последовательности событий, функцияобработки которых обеспечивает вывод и удаление рисунка. Значок компо-нента Timer находится на вкладке System (рис. 3.15). Следует обратить вни-мание, что компонент Timer является невизуальным. Это значит, что во вре-мя работы программы компонент в диалоговом окне не отображается. По-этому компонент Timer можно поместить в любую точку формы. Свойствакомпонента Timer приведены в табл. 3.7.
?=©
Timer
! System !
! П* ОП В»•’
Рис. 3.15. Значок компонента Timer
88 Часть II. Практикум программирования
Таблица 3.7. Свойства компонента Timer
Свойство Определяет
Name Имя компонента. Используется для доступа к свойствам компо-нента
Interval Период возникновения события OnTimer. Задается в миллисекун-дах
Enabled Разрешение работы. Разрешает (значение true) или запрещает(значение false) возникновение события OnTimer
Компонент Timer генерирует событие OnTimer. Период возникновения собы-тия OnTimer измеряется в миллисекундах и определяется значением свойстваinterval. Следует обратить внимание на свойство Enabled. Оно дает воз-можность программе «запустить» или «остановить» таймер. Если значениесвойства Enabled равно false, то событие OnTimer не возникает.
В рассматриваемой программе вывод изображения выполняет функцияship, которая рисует на поверхности формы кораблик. В качестве парамет-ров функция ship получает координаты базовой тонки. Базовая точка (XQ, уо)определяет положение графического объекта в целом; от нее отсчитываютсякоординаты графических примитивов, образующих объект (рис. 3.16). Ко-ординаты фафических примитивов можно отсчитывать от базовой точки нев пикселах, а в относительных единицах. Такой подход позволяет легко вы-полнить масштабирование изображения.
(X0,y0-2dy)
(Х0,Уо)’
(x0+17dx, y0-3dy)
(x0+10dx, y0-2dy)/ s (x0+14dx,y0)
Рис. 3.16. Базовая точка (х0, уо) определяет положение объекта
Глава 3. Графика 89
Перед тем как нарисовать кораблик на новом месте, функция обработкисобытия от таймера стирает кораблик, нарисованный в процессе обработкипредыдущего события OnTimer. Изображение кораблика стирается путем вы-вода прямоугольника, перекрывающего его.
ФУНКЦИИ Обработки СОбыТИЯ OnTimer, фуНКЦИЯ Ship И фуНКЦИЯ FormCreate,
обеспечивающая настройку таймера, приведены в листинге 3.6
! Листинг 3.6. Простая мультипликация
int х = -68, у = 50; // начальное положение базовой точки
II рисует на поверхности формы кораблик
void fastcall TForml::Ship(int x, int y)
{
int dx=4,dy=4; // шаг сетки
I/ корпус и надстройку будем рисовать
I/ при помощи метода Polygon
TPoint pi[7]; // координаты точек корпуса
TPoint p2[8]; // координаты точек надстройки
TColor pc,bc; // текущий цвет карандаша и кисти
II сохраним текущий цвет карандаша и кисти
рс = Canvas->Pen->Color;
be = Canvas->Brush->Color;
// установим нужный цвет карандаша и кисти
Canvas->Pen->Color = clBlack;
Canvas->Brush->Color = clWhite;
// рисуем . . .
11 корпус
pl[0].x = x; pl[0].y = y;
p l [ l ] .x = x; p l [ l ] . y = y-2*dy;
pl[2] .x = x+10*dx; pi[2].у = y-2*dy;
p l [ 3 ] . x = x+ll*dx; p l [3] .y = y-3*dy;
«p l [4] .x = x+17*dx; pi[4].у =y-3*dy;
pl[5] .x = x+14*dx; p i [ 5 ] . у =у;
pl[6] .x = x; pl[6].y =y;
Canvas->Polygon(pl,6);
// надстройка
p2[0] .x = x+3*dx; p2[0].y = y-2*dy;
p 2 [ l ] . x = x+4*dx; p 2 [ l ] . y = y-3*dy;
90 _ Часть II. Практикум программирования
р2[2].х = x+4*dx; p2[2].y = y-4*dy;
р2[3].х = x+13*dx; p 2 [ 3 ] . y = y-4*dy;
р2[4].х = x+13*dx; p2[4] .y = y-3*dy;
р2[5] .х = x+ll*dx; p 2 [ 5 ] . y = y-3*dy;
р2[б] .х = x+10*dx; р 2 [ б ] . у = у-2Му;
р2[7] .х = x+3*dx; p2[7] .у = y-2*dy;
Canvas->Polygon (p2 , 7 ) ;
Canvas->MoveTo(x+5*dx,y-3*dy) ;
Canvas->LineTo (x+9*dx,y-3*dy) ;
// капитанский мостик
Canvas->Rectangle (x+8*dx, y-4*dy,x+ll*dx, y-5*dy) ;
/ / труба
Canvas->Rectangle (x+7*dx, y-4*dy,x+8*dx, y-7*dy) ;
// иллюминаторы
Canvas->Ellipse(x+ll*dx,y-2*dy,x+12*dx,y-l*dy) ;
Canvas->Ellipse(x-)-13Mx,y-2*dy,x+14*dx,y-l*dy) ;
// мачта
Canvas->MoveTo(x+10*dx,y-5*dy) ;
Canvas->LineTo (x+10*dx, y-10*dy) ;
// оснастка
Canvas->Pen->Color = clWhite;
Canvas->MoveTo(x+17*dx,y-3*dy) ;
Canvas->LineTo (x+10*dx, y-10*dy) ;
Canvas ->LineTo (x, y-2*dy) ;
// восстановим цвет карандаша и кисти
Canvas->Pen->Color = рс;
Canvas->Brush->Color = be;
// обработка события On Timer
void _ fastcall TForml: :TimerlTimer (TObject *Sender)
{
// стереть кораблик — закрасить цветом, совпадающим
// с цветом фона (формы)
Canvas->Brush->Color = Forml->Color;
Canvas->FillRect (Rect (x-l,y+l,x+68,y-40) ) ;
// вычислить координаты базовой точки
х+=3;
Глава 3. Графика
if (x > ClientWidth) {
// кораблик «уплыл» за правую границу формы
х= -70; // чтобы кораблик «выплывал» из-за левой границы формы
y=random(Forml->ClientHeight) ;
}
// нарисовать кораблик на новом месте
Ship (х, у) ;
// обработка события OnCreate для формы
void fastcall TForml::FormCreate(TObject *Sender)
/* Таймер можно настроить во время разработки программы
(в процессе создания формы) или so время работы программы. */
// настройка и запуск таймера
Timerl->Interval = 100; // период события OnTimer -0.1 сек.
Timerl->Enabled = true; // пуск таймера
}
Использование битовых образовВ последнем примере изображение формировалось из графических прими-тивов. Теперь рассмотрим, как можно реализовать перемещение заранееподготовленного при помощи графического редактора изображения.
Как и в предшествующей программе, эффект перемещения объекта (кар-тинки) достигается за счет периодической перерисовки картинки с некото-рым смещением относительно ее прежнего положения. Перед выводом кар-тинки в новой точке предыдущее изображение должно быть удалено, а фо-новый рисунок, который был перекрыт — восстановлен. Удалить (стереть)картинку и одновременно восстановить фон можно путем перерисовки всейфоновой картинки или только той ее части, которая была перекрыта объек-том. В рассматриваемой программе используется второй подход. Изображе-ние объекта выводится применением метода Draw к свойству canvas формы,а стирается путем копирования (метод copyRect) нужной части фона из бу-фера в битовый образ, соответствующий поверхности формы.
Форма программы приведена на рис. 3.17, а текст — в листинге 3.6. Компо-нент Timer используется для организации цикла удаления и вывода изобра-жения самолета.
92 Часть II. Практикум программирования
• Полет над городом
Рис. 3.17. Форма программы «Полет над городом»
! Листинг 3.7. «Полет’над городом»
void fastcall TForml::FormCreate(TObject *Sender)
// загрузить фоновый рисунок из bmp-файла
back = new Graphics::TBitraap();
back->LoadFromFile(«factory.bmp»);
// установить размер клиентской (рабочей) области формы
// в соответствии с размером фонового рисунка
ClientWidth = back->Width;
ClientHeight = back->Height;
// загрузить картинку
sprite = new Graphics::TBitmap();
sprite->LoadFromFile(«aplane.bmp»);
sprite->Transparent = true;
// исходное положение самолета
x=-20; // чтобы самолет «вылетал» из-за левой границы окна
у=20;
void fastcall TForml::FormPaint(TObject *Sender)
Canvas->Draw(0,0,back); // фон
Canvas->Draw(x,у,sprite); // рисунок
void fastcall TForml::TimerlTimer(TObject *Sender)
{
TRect badRect; // положение и размер области фона,
// которую надо восстановить
Глава 3. Графика _ 93
badRect = Rect (x,y, x+sprite->Width, y+sprite->Height) ;
// стереть самолет (восстановить «испорченный» фон)Canvas->CopyRect (badRect, back->Canvas, badRect) ;
// вычислим новые координаты спрайта (картинки)х +=2;if (х > ClientWidth)
{
// самолет улетел за правую границу формы
// изменим высоту и скорость полета
х = -20;
у = random (ClientHeight — 30); // высота полета»// скорость полета определяется периодом возникновения// события OnTimer, который, в свою очередь, зависит
// от значения свойства IntervalTimerl->Interval = random (20) + 10; // скорость «полета» меняется
// от 10 до 29}Canvas->Draw (х, у, sprite) ;
Для хранения битовых образов (картинок) фона и самолета используютсядва объекта ТИПа TBitmap, Которые создает функция TForml : : FormCreate(объявления этих объектов надо поместить в заголовочный файл проекта).Эта же функция загружает из файлов картинки фона (factory.bmp) и самоле-та (aplane.bmp).
Восстановление фона выполняется при помощи метода CopyRect, которыйпозволяет выполнить копирование прямоугольного фрагмента одного бито-вого образа в другой. Объект, к которому применяется метод CopyRect, яв-ляется приемником копии битового образа. В качестве параметров методупередаются: координаты и размер области, куда должно быть выполненокопирование; поверхность, с которой должно быть выполнено копирование;положение и размер копируемой области. Информация о положении и раз-мере восстанавливаемой (копируемой на поверхность формы) области фонанаходится в структуре badRect типа TRect.
Следует обратить внимание на то, что начальное значение переменной х,которая определяет положение левой верхней точки битового образа (дви-жущейся картинки) — отрицательное число, равное ширине битового об-раза картинки. Поэтому в начале работы программы самолет не виден икартинка отрисовывается за границей видимой области. С каждым событи-ем OnTimer значение координаты х увеличивается и на экране появляется тачасть битового образа, координаты которой больше нуля. Таким образом,
94 Часть II. Практикум программированы
у наблюдателя создается впечатление, что самолет вылетает из-за левой границы окна.
Загрузка битового образа из ресурса программыВ программе «Полет над городом» (листинг 3.7) картинки (битовые образы’фона и объекта (самолета) загружаются из файлов. Такой подход не всегдаудобен. C++ Builder позволяет поместить нужные битовые образы в испол-няемый файл программы и по мере необходимости загружать их непосред-ственно оттуда.
Битовый образ, находящийся в выполняемом файле программы, называетсяресурсом, а операция загрузки битового образа из выполняемого файла -загрузкой битового образа из ресурса.
Для того чтобы воспользоваться возможностью загрузки картинки из ресур-са, сначала надо создать файл ресурсов и поместить в него нужные картинки.
Создание файла ресурсовФайл ресурсов можно создать при помощи утилиты Image Editor, котораяпоставляется вместе с C++ Builder. Запустить Image Editor можно изC++ Builder, выбрав в меню Tools команду Image Editor, или из Windows,выбрав команду Пуск | Программы | Borland C++Builder | Image Editor.
Для того чтобы создать файл ресурсов, надо в меню File выбрать командуNew, а затем в появившемся подменю— команду Resource File (рис. 3.18).В результате выполнения команды будет создан файл ресурсов Untitledl.res(рис. 3.19), в который надо поместить необходимые ресурсы.
«pJ Image Editor
File Window Help
юизэвнннOpen.,, СЫ+0 Component Resource File (.dcr)
Bitmap File (.brnp)
Icon File (.Ico)
Cursor File (,cur)
I!— •«••••••l ггигжгияCreate a new resource file
Рис. 3.18. Чтобы создать файл ресурсов, выберите команду File | New | Resource File
Глава 3. Графика 95
r— вяпгашнвI ггигег
Рис. 3.19. Файл ресурсов создан. Теперь в него надо поместить необходимые ресурсы
Для того чтобы в файл ресурсов добавить новый ресурс, надо в менюResource выбрать команду New | Bitmap (Новый битовый образ). В результатевыполнения этой команды открывается диалоговое окно Bitmap Properties(Характеристики битового образа), в котором нужно установить размер(в пикселах) битового образа и выбрать палитру (рис. 3.20). В результатенажатия кнопки ОК в списке Contents появится новый элемент Bitmap!.соответствующий новому ресурсу, добавленному в файл ресурсов (рис. 3.21).
Bitmap Properties
г Size
| Width pii»
j Height Щ
211~ Colors
Г yonochrome [2 colors)
Г VGA (16 colors)
(f SuperVGA (256 colois)
Cancel
Рис. 3.20. В диалоговом окнеBitmap Properties надо задать характеристики
создаваемого битового образа
_ |п| х|В Contents
В Bitmap
Рис. 3.21. Окно файла ресурсовпосле добавления ресурса Bitmap
Bitmap! — это автоматически созданное имя ресурса, которое можно изме-нить, выбрав команду Resource | Rename. После этого можно приступить кредактированию (созданию) битового образа. Для этого надо в менюResource выбрать команду Edit. В результате этих действий будет активизи-рован режим редактирования битового образа.
96 Часть II. Практикум программирования
Графический редактор Image Editor предоставляет программисту стандарт-ный для подобных редакторов набор инструментов, используя которыеможно нарисовать нужную картинку. Если во время работы надо изменитьмасштаб отображения картинки, то для увеличения масштаба следует вы-брать команду View | Zoom In, а для уменьшения — команду View | ZoomOut. Увидеть картинку в реальном масштабе можно, выбрав команду View |Actual Size.
В качестве примера на рис. 3.22 приведен вид диалогового окна Image Editor,в котором находится файл ресурсов images.res для программы Flight. Файлсодержит два битовых образа FACTORY и APLANE.
gfPlmage Editor
File Edit Jexi View Bitmap Window Help
i.-j Contents
:-: Bitmap
APLANE
-•FACTORY
£)APLANE (iroeges.»»)
mmmmmmmmrmmmmmmmmmmmmmmmmmmrrmrrrmmrmmmmmmmmmmmmmmmmmm_X: 064 Y:»078
rrг г 11
Рис. 3.22. Файл ресурсов images.res содержит два битовых образа
Если нужная картинка уже существует в виде отдельного файла, то ее мож-но через буфер обмена (Clipboard) поместить в битовый образ файла ресур-сов. Делается это следующим образом.
1. Сначала надо запустить графический редактор, например Microsoft Paint,загрузить в него файл картинки и выделить всю картинку или ее часть.В процессе выделения следует обратить внимание на информацию о раз-мере (в пикселах) выделенной области (Paint выводит размер выделяемойобласти в строке состояния). Затем, выбрав команду Копировать менюПравка, необходимо поместить копию выделенного фрагмента в буфер.
2. Далее нужно переключиться в Image Editor, выбрать ресурс, в которыйнадо поместить находящуюся в буфере картинку, и установить значения
Глава 3. Графика 97
характеристик ресурса в соответствии с характеристиками картинки, на-ходящейся в буфере. Значения характеристик ресурса вводятся в полядиалогового окна Bitmap Properties, которое открывается выборомкоманды Image Properties меню Bitmap. После установки характеристикресурса можно вставить картинку в ресурс, выбрав команду Past меню Edit.
После добавления всех нужных ресурсов файл ресурса следует сохранитьв том каталоге, где находится программа, для которой этот файл создается.Сохраняется файл ресурса обычным образом, т. е. выбором команды Saveменю File. Image Editor присваивает файлу ресурсов расширение res.
Подключение файла ресурсов
Для того чтобы ресурсы, находящиеся в файле ресурсов, были доступныпрограмме, в текст профаммы надо поместить инструкцию (директиву),которая сообщит компилятору, что в исполняемый файл следует добавитьсодержимое файла ресурсов.
В общем виде эта директива выглядит следующим образом:
ipragma resource ФайлРесурсов
где ФайлРесурсов — имя файла ресурсов.
Например, для профаммы flight_l директива, обеспечивающая включениесодержимого файла ресурсов в выполняемый файл, выглядит так:
Ipragma resource «images.res»
Загрузить битовый образ из ресурса можно при помощи методаLoadFromResourceName, который имеет два параметра: идентификатор про-граммы и имя ресурса. В качестве идентификатора профаммы используетсяглобальная переменная Hinstance. Имя ресурса должно быть представленов виде строковой константы.
Например, в профамме flight_l инструкция зафузки фона из ресурса вы-глядит так:
i
back->LoadFromResourceName((int)Hinstance,»FACTORY»);
В качестве примера в листинге 3.8 приведен фрагмент профаммы flight_l -функция TFormi:: FormCreate, которая обеспечивает зафузку битовых обра-зов из ресурсов.
| Листинг 3.8. Загрузка битовых образов из ресурса
// подключить файл ресурсов, в котором находятся
II необходимые программе битовые образы
Ipragma resource «images.res»
4 Зак. 1252
98 Часть II. Практикум программирования
void fastcall TForml::FormCreate(TObject *Sender)
{
// загрузить фоновый рисунок из ресурса
back = new Graphics::TBitmap();
back->LoadFromResourceName((int)HInstance,»FACTORY»);
// установить размер клиентской (рабочей) области формы
// в соответствии с размером фонового рисунка
ClientWidth = back->Width;
ClientHeight = back->Height;
// загрузить изображение объекта из ресурса
sprite = new Graphics::TBitmap();
sprite->LoadFromResourceName((int)HInstance,»APLANE»);
sprite->Transparent = true;
// исходное положение самолета
x=-20; // чтобы самолет «вылетал» из-за левой границы окна
у=20;
>
Преимущества загрузки картинок из ресурса программы очевидны: при рас-пространении программы не надо заботиться о том, чтобы во время работыпрограммы были доступны файлы иллюстраций, т. к. все необходимые про-грамме картинки находятся в исполняемом файле.
Теперь рассмотрим, как можно реализовать в диалоговом окне программывывод баннера, представляющего собой последовательность сменяющих другдруга картинок (кадров). Кадры баннера обычно находятся в одном файлеили в одном ресурсе. В начале работы программы они загружаются в буфер(объект типа TBitmap). Вывод кадров баннера обычно выполняет функцияобработки сигнала от таймера (события OnTimer), которая выделяет очеред-ной кадр и выводит его на поверхность формы.
Вывести кадр баннера (фрагмент битового образа) на поверхность формыможно при помощи метода copyRect, который копирует прямоугольную об-ласть одной графической поверхности на другую.
Инструкция применения метода copyRect в общем виде выглядит так:
Canvasl->CopyRect(Область!, Canvas2, Область2)
где:
П Canvasi — поверхность, на которую выполняется копирование;
П Canvas2 — поверхность, с которой выполняется копирование;
П область! — структура типа TRect, которая задает положение и размер об-ласти, куда выполняется копирование (приемник);
Глава 3. Графика 99
П область2 — структура типа TRect, которая задает положение и размер об-ласти, откуда выполняется копирование (источник).
Определить прямоугольную область, заполнить поля структуры TRect можнопри помощи функции Rect или Bounds. Функции Rect надо передать в каче-стве параметров координаты левого верхнего и правого нижнего углов об-ласти, функции Bounds — координаты левого верхнего угла и размер облас-ти. Например, если надо определить прямоугольную область, то это можносделать так:
ret = Rect(x l ,y l ,x2,y2)
или так:
ret = Bounds(xl ,yl ,w,h)
где xl, yl — координаты левого верхнего угла области; х2, у2 — координатыправого нижнего угла области; w и h — ширина и высота области.
Следующая программа (ее текст приведен в листинге 3.9) выводит в диало-говое окно баннер — рекламное сообщение. На рис. 3.23 приведены кадрыэтого баннера (содержимое файла baner.bmp), а на рис. 3.24 — диалого-вое окно. Форма программы содержит один-единственный компонент —таймер.
Borland Borland
БBorland
С BuilderРис. 3.23. Кадры баннера
Borland
С Builder
Рис. 3.24. Воспроизведение баннера в окне программы
Листинг 3.9. Баннер (baner.h, baner_.cpp)
// baner.h
class TForml : public TForm
{
_published:
TTimer *Timerl;
1 00 Часть II. Практикум программирования
void _ fastcall FormCfeate (TObject *Sender) ;
void _fastcall Timer ITimer (TObject * Sender );
private :
Graphics: :TBitmap *baner; // баннер
TRect kadr; // кадр баннера
TRect scr; // область воспроизведения баннера
int w, h; // размер кадра
int с; // номер воспроизводимого кадра
public :
_ fastcall TForml (TComponent* Owner);
// baner_.qpp
#define FBANER «borland.bmp» // баннер
#define NKADR 4 // количество кадров в баннере
void _ fastcall TForml :: FormCreate (TObject Sender)
{
baner = new Graphics : :TBitmap ();
baner->LoadFromFile (FBANER) ; // загрузить баннер
h = baner->Height;
w = baner->Width / NKADR;
scr = Rect (10, 10, 10+w, 10+h) ; // положение и размер области
/ / воспроизведения баннера
kadr = Rect (0, 0, w,h) ; // положение и размер первого кадра
/ • / в баннере
// обработка события Ол Timer
void _ fastcall TForml: : TimerlTimer (TObject *Sender)
{
// вывести кадр баннера
Canvas->CopyRect (scr,baner->Canvas, kadr) ;
// подготовиться к воспроизведению следующего кадра
if (с < NKADR)
(
// воспроизводимый в данный момент
II кадр — не последний
с++;
kadr. Left += w;
kadr. Right += w;
Глава 3. Графика 101
else
С = 0;
kadr.Left = 0;
kadr.Right = w;
Программа состоит из двух функций. Функция TFormi:: Formcreate создаетобъект TBitmap и загружает в него баннер — BMP-файл, в котором находят-ся кадры баннера. Затем, используя информацию о размере загруженногобитового образа, функция устанавливает значения характеристик кадра: вы-соту и ширину.
Основную работу в программе выполняет функция обработки событияOnTimer, которая выделяет из битового образа Ьапег очередной кадр и выво-дит его на поверхность формы. Выделение кадра и его отрисовку путем ко-пирования фрагмента картинки с одной поверхности на другую выполняетметод copyRect (рис. 3.25), которому в качестве параметров передаются ко-ординаты области, куда нужно копировать, поверхность и положение облас-ти, откуда нужно копировать. Положение фрагмента в фильме, т. е. коор-дината х левого верхнего угла, определяется умножением ширины кадра наномер текущего кадра.
Rectl — область, в которойотображаются кадры баннера
Canvas2 — поверхность невидимого объекта типаTBitmap, содержит все кадры баннера
Canvasl — поверхность формы
]
— •1
Rect2 — отображаемый кадр
Рис. 3.25. Метод CopyRect копирует в область Rectl поверхности Canvasl область Rect2с поверхности Canvas2
ГЛАВА 4
Мультимедиа
Большинство современных программ, работающих в среде Windows, явля-ются мультимедийными. Такие программы обеспечивают просмотр видео-роликов и мультипликации, воспроизведение музыки, речи, звуковыхэффектов. Типичные примеры мультимедийных программ — игры и обу-чающие программы.
C++ Builder предоставляет в распоряжение программиста два компонента,которые позволяют разрабатывать мультимедийные программы:
П Animate — обеспечивает вывод простой, не сопровождаемой звуком ани-мации;
П MediaPiayer — позволяет решать более сложные задачи, напримервоспроизводить видеоролики, звук и сопровождаемую звуком анимацию.
Компонент AnimateКомпонент Animate, значок которого находится на вкладке Win32 (рис. 4.1),позволяет воспроизводить простую, не сопровождаемую звуком анимацию,кадры которой находятся в AVI-файле.
[ТAnimate
Рис. 4.1. Значок компонента Animate
Компонент Animate добавляется к форме обычным образом. После того каккомпонент будет добавлен к форме, следует выполнить его настройку -установить значения свойств. Свойства компонента Animate перечисленыв табл. 4.1.
Глава 4. Мультимедиа 103
Таблица 4.1. Свойства компонента Animate
Свойство Описание
Name Имя компонента. Используется для доступа к свойствам компонен-та и для управления его поведением
FileName Имя AVI-файла, в котором находится анимация, отображаемая припомощи компонента
FrameWidth Ширина кадров анимации
FrameHeight Высота кадров анимации
FrameCount Количество кадров анимации
AutoSize Признак автоматического изменения размера компонента в соот-ветствии с размером кадров анимации
Center Признак центрирования кадров анимации в поле компонента. Еслизначение свойства равно true и размер компонента больше раз-мера кадров (AutoSize = false), кадры анимации располагаютсяв центре поля компонента
startFrame Номер кадра, с которого начинается отображение анимации
StopFrame Номер кадра, на котором заканчивается отображение анимации
Active Признак активизации процесса отображения анимации
Color Цвет фона компонента (цвет «экрана»), на котором воспроизводит-ся анимация
Transparent Режим использования «прозрачного» цвета при отображении ани-мации
Repetitions Количество повторов отображения анимации
CommonAVl Определяет стандартную анимацию Windows (см. табл. 4.2)
Компонент Animate позволяет программисту использовать в своих програм-мах стандартные анимации Windows. Вид анимации определяется значениемсвойства CommonAvi. Значение свойства задается при помощи именованнойконстанты. В табл. 4.2 приведены некоторые константы, вид анимации иописание процессов, для иллюстрации которых используются эти ани-мации.
Таблица 4.2. Значение свойства CommonAvi определяет анимацию
Значение Анимация Процесс
aviCopyFiles Копирование файлов
104 Часть II. Практикум программирования
Таблица 4.2 (окончание)
Значение Анимация
•тaviDeleteFile
Процесс
Удаление файла
aviRecycleFile о 6 Удаление файла в корзину
Следует еще раз обратить внимание, что компонент Animate предназначендля воспроизведения AVI-файлов, которые содержат только анимацию. Припопытке записать в свойство FileName имя файла, в котором находится со-провождаемая звуком анимация, возникает исключение и C++ Builder вы-водит сообщение об ошибке Cannot open AVI.
Следующая программа (вид ее диалогового окна приведен на рис. 4.2, атекст— в листинге 4.1) демонстрирует использование компонента Animateдля просмотра анимации.
Animatel
RadioButtonl —
в
•
:
;-, Просмотр анимации
. . . . \ ,,„
-|п|х|
гФайл:; | Выбрать..
•
3* непрерывно
У^
1Вск ‘
1 »4
Щт!•: : : :
,•:’:::
— Button4
— OpenDialog!
— Button2
Buttons
Рис. 4.2. Форма программы «Просмотр анимации»
После запуска программы в форме будет выведен первый кадр анимации,которая находится в каталоге проекта. Если ни одного файла с расшире-нием avi в каталоге проекта нет, то поле компонента Animate останется пус-тым.
Имя файла, в котором находится анимация, можно ввести в поле Editi иливыбрать в стандартном диалоговом окне Открыть файл, которое становится
Глава 4. Мультимедиа _ 105
доступным в результате щелчка на кнопке Выбрать. Доступ к стандартномудиалоговому окну Открыть файл обеспечивает компонент OpenDiaiogi. Зна-чок компонента OpenDialog находится на вкладке Dialogs.
Программа «Просмотр анимации» обеспечивает два режима просмотра: не-прерывный и по кадрам. Кнопка Button! используется как для инициализа-ции процесса воспроизведения анимации, так и для его приостановки.Процесс непрерывного воспроизведения анимации инициирует процедураобработки события Onclick на кнопке Пуск, которая присваивает значениеtrue свойству Active. Эта же процедура заменяет текст на кнопке Button! с»Пуск» на «Стоп». Режим воспроизведения анимации выбирается при по-мощи переключателей RadioButtoni и RadioButton2. Процедуры обработкисобытия onclick на этих переключателях изменением значения свойстваEnabled блокируют или, наоборот, делают доступными кнопки управления:активизации воспроизведения анимации (Buttoni), перехода к следующему(Buttona) и предыдущему (Buttons) кадру. Во время непрерывного воспроиз-ведения анимации процедура обработки события onckick на кнопке Стоп(Buttoni) присваивает значение false свойству Active и тем самым останав-ливает процесс воспроизведения анимации.
: ………………………………………………………………………… …………………. ‘ ……….. ‘ ………………………….. «» ………… ‘ ………………………………………………… ‘ ……………. ‘ ………… -|
! Листинг 4.1. Использование компонента Animate
// обработка события OnCreate
void _ fastcall TForml: : FormCreate (TObject *Sender)
{TSearchRec sr-; // содержит информацию
II о файле, найденном функцией FindFirst
I I найдем AVI-файл в текущем каталогеif (FindFirst («*.avi»,faAnyFile,sr) == 0)
{Editl-XText = sr.Name;
/* если анимация содержит звук, то при
выполнении следующего оператора произойдет
ошибка, т. к. компонент Animate обеспечивает
воспроизведение только простой,
не сопровождаемой звуком анимации
try
{Animatel->FileName = sr.Name;
106 _ Часть II. Практикум программирования
catch (Exception &e)
{
return;
RadioButtonl->Enabled = true;
RadioButton2->Enabled = true;
Buttonl->Enabled = true;
// щелчок на кнопке Выбрать
void _ fastcall TForml : :Button4Click(TObject *Sender)
{
OpenDialogl->InitialDir = «»; // открыть каталог, из которого
I / запущена программа
OpenDialogl->FileName = «*.avi»; // вывести список AVI-файлов
if ( OpenDialogl->Execute () )
{
// пользователь выбрал файл и нажал кнопку Открыть
I / Компонент Animate может отображать только простую,
//не сопровождаемую звуком анимацию. Поэтому
/ I при выполнении следующей инструкции возможна ошибка
try
{Animatel->FileName = OpenDialogl->FileName;
}
catch (Exception &e)
{
Editl-XText = «»;
// сделаем недоступными кнопки управления
RadioButtonl->Enabled = false;
RadioButton2->Enabled = false;
Buttonl->Enabled = false;
Button2->Enabled = false;
Button3->Enabled = false;
// сообщение об ошибке
AnsiString msg =
«Ошибка открытия файла » +
OpenDialogl->FileName +
«ХпВозможно анимация сопровождается звуком.»;
Глава 4. Мультимедиа _ 107
ShowMessage (msg) ;
return;
}
Editl->Text = OpenDialogl->FileName; // отобразить имя файла
RadioButtonl->Checked = true;// режим просмотра — непрерывно
Buttonl->Enabled = true; // кнопка Пуск доступна
Button2->Enabled = false; // кнопка Предыдущий кадр недоступна
Button3->Enabled = false; // кнопка Следующий кадр недоступна
RadioButtonl->Enabled = true;•
RadioButton2->Enabled = true;
// щелчок на кнопке Пуск/Стоп
void _ fastcall TForml: :ButtonlClick (TObject *Sender)
{
if (Animatel->Active)
{
// анимация отображается, щелчок на кнопке Стоп
Animatel->Active = false;
Buttonl->Caption = «Пуск»;
RadioButton2->Enabled = true;
}
else // щелчок на кнопке Пуск
{I / активизировать отображение анимации
Animatel->StartFrame =1; lie первого кадра
Animatel->StopFrame = Animatel->FrameCount; // по последний кадр
Animatel->Active = true;
Buttonl->Caption = «Стоп»;
RadioButton2->Enabled = false;
// выбор режима просмотра всей анимации
void _ fastcall TForml : :RadioButtonlClick (TObject *Sender)
{
Buttonl->Enabled = true; // кнопка Пуск/Стоп доступна
1 1 сделать недоступными кнопки режима просмотра по кадрам
Button2->Enabled = false;
Button3->Enabled = false;
Animatel->Active = false;
108 Часть II. Практикум программирования
// выбор режима просмотра по кадрам
void fastcall TForml::RadioButton2Click(TObject *Sender)
{
Buttonl->Enabled = false; // кнопка Пуск/Стоп недоступна
Button2->Enabled = true; // кнопка Следующий кадр доступна
Button3->Enabled = false; // кнопка Предыдущей кадр недоступна
// отобразить первый кадр
Animatel->StartFrame =1;
Animate!->StopFrame = 1;
Animatel->Active = true;
CFrame = 1; // запомним номер отображаемого кадра
}
// щелчок на кнопке Следующий кадр
void fastcall TForml::Button2Click(TObject *Sender)
{
CFrame++;
// отобразить кадр
Animatel->StartFrame = CFrame;
Animatel->StopFrame = CFrame;
Animatel->Active = true;
if (CFrame > 1)
Button3->Enabled = true;
if (CFrame == Animatel->FrameCount) // отобразили последний кадр
Button2->Enabled = false; // кнопка Следующий кадр недоступна
// щелчок на кнопке Предыдущий кадр
void fastcall TForml::Button3Click(TObject *Sender)
i
if (CFrame == Animatel->FrameCount) // последний кадр
Button2->Enabled = true;
CFrame—;
// отобразить кадр
Animatel->StartFrame = CFrame;
Animatel->StopFrame = CFrame;
Animatel->Active = true;
if (CFrame == 1)
Button3->Enabled = false; // кнопка Следующий кадр недоступна
Глава 4. Мультимедиа 109
Компонент MediaPlayerКомпонент MediaPlayer обеспечивает воспроизведение звуковых файловразличных форматов (WAV, MID, RMI, МРЗ), полноценной, сопровож-даемой звуком анимации и видеороликов (AVI) и музыкальных компакт-дисков.
Значок компонента MediaPlayer находится на вкладке System (рис. 4.3).
MediaPlayer
Рис. 4.3. Значок компонента MediaPlayer
Компонент MediaPlayer представляет собой группу кнопок (рис. 4.4), по-добных тем, какие можно видеть на обычном аудио- или видеоплеере.Назначение этих кнопок пояснено в табл. 4.3. Свойства компонентаMediaPlayer, доступные во время разработки формы, приведены в табл. 4.4.
btPayse btNext btStep btRecord
И I
btPlay btStop btPrev btBack blEject
Рис. 4.4. Компонент MediaPlayer
Таблица 4.3. Кнопки компонента MediaPlayer
Кнопка Обозначение Действие
Воспроизведение btPlay
Пауза btPause
Стоп btstop
Следующий btNext
Предыдущий btPrev
Шаг btStep
Назад btBack
Воспроизведение звука или видео
Приостановка воспроизведения
Остановка воспроизведения
Переход к следующему кадру
Переход к предыдущему кадру
Переход к следующему звуковому фраг-менту, например, к следующей песне на CD
Переход к предыдущему звуковому фраг-менту, например, к предыдущей песне наCD
110 Часть II. Практикум программирования
Таблица 4.3 (окончание)
Кнопка
Запись
Открыть
Обозначение
btRecord
btEject
Действие
Активизирует процесс записи
Открывает CD-дисковод компьютера
Таблица 4.4. Свойства компонента MediaPlayer
Свойство Описание
Name
DeviceType
FileName
AutoOpen
Display
VisibleButtons
Имя компонента. Используется для доступа к свойствам компо-нента и для управления работой плеера
Тип устройства. Определяет конкретное устройство, котороепредставляет собой компонент MediaPlayer. Тип устройствазадается именованной константой: dtAutoSelect — тип устрой-ства определяется автоматически по расширению файла;dtVaweAudio — проигрыватель звука; dtAVivideo — видеопро-игрыватель; dtCDAudio — CD-проигрыватель
Имя файла, в котором находится воспроизводимый звуковойфрагмент или видеоролик
Признак автоматической загрузки сразу после запуска про-граммы, файла видеоролика или звукового фрагмента
Определяет компонент, поверхность которого используется вкачестве экрана для воспроизведения видеоролика (обычнов качестве экрана для отображения видео используют компо-нент Panel)
Составное свойство. Определяет видимые кнопки компонента.Позволяет сделать невидимыми некоторые кнопки
Помимо свойств, доступных в процессе разработки формы, компонентMediaPlayer предоставляет свойства, доступные во время работы программы(табл. 4.5), которые позволяют получить информацию о состоянии медиа-плеера, воспроизводимом файле или треке Audio CD. Следует обратить вни-мание, что значения свойств, содержащих информацию о длительности,могут быть представлены в различных форматах. Наиболее универсальнымформатом является формат tfMiiiiseconds, в котором длительность выража-ется в миллисекундах. Некоторые устройства поддерживают несколькоформатов. Например, если MediaPlayer используется для воспроизведенияAudio CD, то информация о воспроизводимом треке может быть представ-лена в формате tfTMSF (Track, Minute, Second, Frame — трек, минута, секун-да, кадр). Для преобразования миллисекунд в минуты и секунды надо вое-
Глава 4, Мультимедиа 111
пользоваться известными соотношениями. Если значение свойства пред-ставлено в формате tfTMSF, то для преобразования можно воспользоватьсямакросами MCI_TMSF_TRACK, MCI_TMSF_SECOND и MCI_TMSF_MINUTE. Объявление этих и других полезных макросов можно найти вфайле mmsystem.h.
Таблица 4.5. Свойства компонента MediaPlayer,доступные во время работы программы
Свойство Описание
Length Длина (время, необходимое для воспроизведения) открытого фай-ла (например, WAV или AVI) или всех треков Audio CD
Tracks Количество треков на открытом устройстве (количество компози-ций на Audio CD)
TrackLength Длина (длительность) треков. Свойство представляет собой массив
Position Позиция (время от начала) в процессе воспроизведения трека
TimeFormat Формат представления значений свойств Length, TrackLength иPosition. Наиболее универсальным является форматtfMilliseconds. Если медиаплеер представляет собой проигрыва-тель звуковых CD, то удобно использовать формат tfTMSF
Mode Состояние устройства воспроизведения. Устройство может нахо-диться в состоянии воспроизведения (mpPlaying). Процесс воспро-изведения может быть остановлен (mpStopped) или приостановлен(mpPaused). Устройство может быть не готово к работе (mpNotReady)или в устройстве (CD-дисководе) может отсутствовать носитель(mpOpen)
Display Экран — поверхность, на которой осуществляется отображениеклипа. Если значение свойства не задано, то отображение осуще-ствляется в отдельном, создаваемом во время работы программыокне
DisplayRect Размер и положение области отображения клипа на поверхностиэкрана
Компонент MediaPlayer предоставляет методы (табл. 4.6), используя которыеможно управлять работой медиаплеера из программы так, как будто это де-лает пользователь.
Таблица 4.6. Методы компонента MediaPlayer
Метод Действие
Play () Активизирует процесс воспроизведения. Действие метода аналогич-но щелчку на кнопке Play
112 Часть II. Практикум программирования
Таблица 4.6 (окончание)
Метод Действие
Stop () Останавливает процесс воспроизведения
Pause () Приостанавливает процесс воспроизведения
Next () Переход к следующему треку, например к следующей композициина Audio CD
Previous () Переход к предыдущему треку, например к следующей композициина Audio CD
step () Переход к следующему кадру
Back () Переход к предыдущему кадру
Воспроизведение звукаВ качестве примера использования компонента MediaPlayer для воспроизве-дения звука рассмотрим программу, используя которую, можно прослушатьзвуковые фрагменты, сопровождающие события Windows — такие, как на-чало и завершение работы, появление диалогового окна и др. Форма и диа-логовое окно программы «Звуки Windows» представлены на рис. 4.5, текст -в листинге 4.2, а значения свойств компонента MediaPiayeri — в табл. 4.7.
Labell —
Label2
MediaPiayeri —
с
1
ЮЯЯИВШШЕ | ,laJx)
Зыберите звуковой файл ищелкните на кнопке Play
J-!» «»•»‘ «si• — . . •• • .
«^ •
:
рЖЯ 5й£Р*»-; t,-.l
Зыберите звуковой файл ищелкните на кнопке Play
noti1y.wav
XI
chimes.wav + \chord.wavding wavtadawav
recycle, wavУТОПИЯ — очистить Корзину. WAVУТОПИЯ — стандартный звук. WAVУТОПИЯ — 3anacKWindows.WAVУТОПИЯ — выход из Windows.WAVУТОПИЯ • критическая ошибка. WAVУТОПИЯ — вопрос. WAVУТОПИЯ • восклицание. WAV
И*» !
Рис. 4.5. Форма и диалоговое окно программы «Звуки Windows»
Глава 4. Мультимедиа 113
Таблица 4.7. Значения свойств компонента Media player l
Компонент Значение
DeviceType dtAutoSelect
VisibleButtons.btNext false
VisibleButtons.BtPrev false
VisibleButtons.btStep false
VisibleButtons.btBack false
VisibleButtons.btRecord false
VisibleButtons.btEject false
Помимо компонента MediaPiayer на форме находится компонент ListBox,который используется для выбора звукового файла, и два компонента Label,первый из которых используется для вывода информационного сообщения,второй — для отображения имени файла, выбранного пользователем.
I Листинг 4.2. Использование компонента MediaPiayer; для воспроизведения звука
void fastcall TForml::FormCreate(TObject *Sender)
{char *wd; // каталог Windows
wd = (char*)AllocMem(MAX_PATH);
GetWindowsDirectory(wd,MAX_PATH);
SoundPath = wd;
// звуковые файлы находятся в подкаталоге Media
SoundPath = SoundPath + «\\Media\\»;
// сформируем список звуковых файлов
TSearchRec sr;
if (FindFirst( SoundPath + «*.wav», faAnyFile, sr) == 0)
{
// найден файл с расширением wav
ListBoxl->Items->Add(sr.Name); // добавим имя файла в список
// еще есть файлы с расширением wav?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name);
/14 Часть II. Практикум программирования
if (FindFirst( SoundPath + «*.mid», faAnyFile, sr) = 0)
// найден файл с расширением mid
ListBoxl->Items->Add(sr.Name); // добавим имя файла в список
// еще есть файлы с расширением mid?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name);
}
if (FindFirst( SoundPath + «*.rmi», faAnyFile, sr) ==0)
// найден файл с расширением rmi
ListBoxl->Items->Add(sr.Name); // добавим имя файла в список
// еще есть файлы с расширением rmi?
while (FindNext(sr) == 0)
ListBoxl->Items->Add(sr.Name);
// воспроизвести первый файл
if ( ListBoxl->Items->Count != 0)
{
Label2->Caption = ListBoxl->Items->Strings [1] ;
MediaPlayerl->FileName = SoundPath + ListBoxl->Items->Strings [1] ;
MediaPlayerl->Open ( ) ;
MediaPlayerl->Play() ;
// щелчок на элементе списка
void _ fastcall TForml: :ListBoxlClick (TObject *Sender)
{
Label2->Caption = ListBoxl->Items->Strings [ListBoxl->ItemIndex]
MediaPlayerl->FileName = SoundPath + Label2->Caption;
MediaPlayerl->Open() ;
MediaPlayerl->Play() ;
Работает программа следующим образом. Сразу после запуска функция об-работки события OnCreate формирует список звуковых файлов (WAV, MIDи RMI), которые находятся в подкаталоге Media главного каталога Windows.Так как на разных компьютерах каталог, в который установлена операцион-ная система, может называться по-разному, то для получения его именииспользуется API функция GetwindowsDirectory, значением которой являет-ся полное имя каталога Windows. Список звуковых файлов формируется
Глава 4. Мультимедиа 115
При ПОМОЩИ функций FindFirst И FindNext. ФуНКЦИЯ FindFirst обесПбЧИва-
ет поиск файла, удовлетворяющего критерию поиска, указанному при вызо-ве функции. Функция FindNext продолжает процесс поиска. Обеим функци-ям в качестве параметра передается структура типа TSearchRec, поле Nameкоторой (в случае успеха) содержит имя файла, удовлетворяющего критериюпоиска. После того как список звуковых файлов сформирован, применени-ем метода play активизируется процесс воспроизведения первого файла.
Щелчок на элементе списка обрабатывается функцией TFormi::ListBoxlclick, которая присваивает значение свойству FiieName компонентаMediaPiayeri, при помощи метода open открывает выбранный файл и при-менением метода Play активизирует процесс воспроизведения.
Следующий пример показывает, как на основе компонента MediaPiayerможно создать вполне приличный проигрыватель компакт-дисков. Видформы и диалогового окна программы приведен на рис. 4.6. Помимо ком-понентов, показанных на рисунке, в форме есть компонент MediaPiayer. Таккак кнопки компонента MediaPiayer во время работы программы не исполь-зуются (для управления плеером служат кнопки Buttoni, Button2 и Buttons),свойству visible присвоено значение false, а сам компонент находится заграницей формы.
Timerl
1© CD Player
•©! Track 0-
0:00—
• Labell
• LabeE
Buttons Buttoni Buttons
Рис. 4.6. Форма программы CD Player
Значки на кнопках управления — это текст, изображенный шрифтомWebdings. При использовании этого шрифта, например, цифре 4 соответст-вует значок Play. Соответствие значков Webdings и обычных символов от-ражает табл. 4.8.
Таблица 4.8. Изображение символов шрифта Webdings
Символ Webdings Обычный символ —например, шрифт Arial
9
4
Код символа(шестнадцатеричный)
39
34
116 Часть II. Практикум программирования
Таблица 4.8 (окончание)
Символ WebdingsОбычный символ —
например, шрифт ArialКод символа
(шестна дцатеричн ый)
ЗА
ЗС
Компонент Timer используется для организации цикла опроса состояниямедиаплеера. Во время воспроизведения CD функция обработки событияOnTimer выводит на индикатор (в поле метки Labeil) номер трека и времявоспроизведения.
Вид окна программы сразу после ее запуска в случае, если в CD-дисководенаходится Audio CD, приведен на рис. 4.7. В случае, если в CD-дисководедиска нет или диск не звуковой, вместо информации о времени воспроиз-ведения будет выведено сообщение «Вставьте Audio CD». Щелчок на кнопкеPlay (Buttoni) активизирует процесс воспроизведения. Во время воспроиз-ведения на индикаторе отражается номер и длительность воспроизводимоготрека, а также время от начала воспроизведения (рис. 4.8).
CD Player
Audio CD. Время звучания: 42:18
0:00
ft CD Player
Вставьте Audio CD
0:00
Рис. 4.7. В начале работы на индикаторе выводится информацияо времени воспроизведения CD или сообщение о необходимости вставить в дисковод Audio CD
Трек 3. Длительность 2:55
1:27
Рис. 4.8. Во время воспроизведения на индикаторе отображается информацияо воспроизводимом треке
Текст программы приведен в листинге 4.3. Следует обратить внимание насобытие Notify, которое может генерировать MediaPiayer. Событие Notifyвозникает в момент изменения состояния плеера при условии, что значениесвойства Notify равно true. В рассматриваемой программе событие Notify
Глава 4. Мультимедиа 117
используется для обнаружения факта открытия CD-дисковода пользовате-лем.
| Листинг 4.3. Проигрыватель компакт дисков
tdefine Webdings 11 на кнопках плеера стандартные символы,
II изображение которых взято из шрифта Webdings
#ifdef Webdings
// «текст» на кнопках при использовании
// шрифта Webdings
#define PLAY «4»
tdefine STOP «<«
Idefine PREVIOUS «9»
#define NEXT «:»
#else
// текст на кнопках при использовании
// обычного шрифта, например, Arial
tdefine PLAY «Play»
ttdefine STOP «Stop»
#define PREVIOUS «Previous»
tdefine NEXT «Next»
tendif
// эти макросы обеспечивают перевод интервала времени,
// выраженного в миллисекундах в минуты и секунды
Idefine MINUTE(ms) ( (ms/1000)/60)
ttdefine SECOND(ms) ( (ms/1000)%60)
// выводит в поле Label 1 информацию о текущем треке
void fastcall TForml::TrackInfo()
{int ms; // время звучания трека, мсек
AnsiString st;
Track = MCI_TMSF_TRACK(MediaPlayer->Position);
MediaPlayer-XTimeFormat = tfMilliseconds;
ms = MediaPlayer-XTrackLength[Track];
MediaPlayer->TimeFormat = tfTMSF;
st = «Трек «+ IntToStr(Track);
st = st + «. Длительность «+ IntToStr(MINUTE(ms));
st = st + «:» + IntToStr(SECOND(ms));
118 Часть II. Практикум программирования
Labell->Caption = st;
}
void fastcall TForml::FormCreate(TObject *Sender)
{
Buttonl->Caption = PLAY;
Button2->Caption = PREVIOUS;
Button3->Caption = NEXT;
MediaPlayer->Notify = true; // разрешить событие Notify
}
// изменение состояния плеера
void fastcall TForml::MediaPlayerNotifу(TObject *Sender)
{
switch ( MediaPlayer->Mode)
{case mpOpen: // пользователь открыл дисковод
{
Buttonl->Enabled = false;
Buttonl->Caption = PLAY;
Buttonl->Tag = 0;
Button2->Enabled = false;
Button3->Enabled = false;
Label2->Caption = «00:00»;
/* по сигналу от таймера будем проверять
состояние дисковода */
Timer->Enabled = True;
>}
MediaPlayer->Notify = true;
}
// щелчок на кнопке Play/Stop
void fastcall TForml::ButtonlClick(TObject *Sender)
{if ( Buttonl-XTag = = 0 ) {
// щелчок на кнопке Play
MediaPlayer->Play();
Buttonl->Caption = STOP;
Buttonl->Hint = «Стоп»;
Buttonl->Tag = 1;
Button3->Enabled = true; // доступна кнопка «следующий трек»
MediaPlayer->Notify = true;
Глава 4. Мультимедиа _ 119
Timer->Enabled = true;
Tracklnf о ( } ;
}
else {
// щелчок на кнопке Stop
Buttonl->Caption = PLAY;
Buttonl->Hint = «Воспроизведение»;
Buttonl->Tag = 0;
MediaPlayer->Notify = true;
MediaPlayer->Stop() ;
Timer->Enabled = false;
// сигнал от таймера : вывести номер трека
// и время воспроизведения
void _ fastcall TForml: :TimerTimer (TObject *Sender)
{
int trk; // трек
int min, sec; // время
AnsiString st;
if ( MediaPlayer->Mode == mpPlaying) // режим воспроизведения
(
// получить номер воспроизводимого трека
trk = MCI_TMSF_TRACK(MediaPlayer->Position) ;
if ( trk != Track) // произошла смена трека
(Tracklnf о ( ) ;
Track = trk;
if ( Track == 2)
Button2->Enabled = true; // доступна кнопка «пред. трек»
if ( Track == MediaPlayer->Tracks)
Button3->Enabled = false; // кнопка «след. трек» недоступна
// вывод информации о воспроизводимом треке
min = MCI_TMSF_MINUTE(MediaPlayer->Position) ;
sec = MCI_TMSF_SECOND(MediaPlayer->Position) ;
st.printf («%d:%.2d»,min,sec) ;
Label2->Caption = st;
return;
120 _ Часть II. Практикум программирования
/* Если дисковод открыт ими в нем нет
Audio CD, то Mode == mpOpen.
Ждем диск, т. е. до тех пор, пока не будет
Mode == mpStopped + кол-во треков > 1 */
if ( (MediaPlayer->Mode == mpStopped) &&
(MediaPlayer-XTracks > 1) )
{
// диск вставлен
Timer->Enabled = false;
Buttonl->Caption = PLAY;
Buttonl->Enabled = true;
Buttonl->Tag = 0;
MediaPlayer->Notify = true;
// получить информацию о времени звучания CD
MediaPlayer->TimeFormat = tfMilliseconds;
int ms = MediaPlayer->Length;
AnsiString st — «Audio CD. Время звучания: «;
st = st + IntToStr (MINUTE (ms) );
st = st + «:» + IntToStr (SECOND (ms) );
Labell->Caption = st;
MediaPlayer->TimeFormat = tfTMSF;
Labell->Visible ,= true;
Track = 0;
return;
// дисковод открыт или в дисководе не Audio CD
if ( ( MediaPlayer->Mode == mpOpen) | I
(MediaPlayer->Mode == mpStopped) && (MediaPlayer->Tracks == 1)
{
Labell->Caption = «Вставьте Audio CD»;
if ( Labell->Visible)
Labell->Visible = false;
else Labell->Visible = true;
// щелчок на кнопке «следующий трек»
void _ fastcall TForml: :Button3Click (TObject *Sender)
<MediaPlayer->Next ( ) ;
Глава 4. Мультимедиа _ 121
// если перешли к последнему треку, то кнопку Next
// сделать недоступной
if ( MCI_TMSF_TRACK(MediaPlayer->Position) == MediaPlayer->Tracks)
Button3->Enabled = false;
if ( ! Button2->Enabled) Button2->Enabled = true;
TracklnfoO ;
Label2->Caption = «0:00»;
// щелчок на кнопке «предыдущий трек»
void _ fastcall TForml: :Button2Click (TObject *Sender)
{
MediaPlayer->Previous () ; // в начало текущего трека
MediaPlayer->Previous () ; // в начало предыдущего трека
if ( MCI_TMSF_TRACK(MediaPlayer->Position) == 1)
Button2->Enabled = false;
if ( ! Button3->Enabled)
Button3->Enabled = true;
TracklnfoO ;
Label2->Caption = «0:00»;
// пользователь закрыл окно программыvoid _ fastcall TForml: : FormClose (TObject *Sender, TCloseAction SAction){
MediaPlayer->Stop ( ) ;
MediaPlayer->Close () ;
Просмотр видеороликовКак было сказано выше, компонент MediaPiayer позволяет просматриватьвидеоролики и сопровождаемую звуком анимацию. В качестве примера ис-пользования компонента рассмотрим программу Video Player, при помощикоторой можно просмотреть небольшой ролик или анимацию. Вид формыпрограммы Video Player приведен на рис. 4.9.
Компонент openDiaiogi обеспечивает отображение стандартного диалогово-го окна Открыть файл для выбора файла. Окно Открыть файл становитсядоступным во время работы программы в результате щелчка на кнопке Eject(speedButtoni). Следует обратить внимание, что для управления процессомвоспроизведения кнопки компонента MediaPiayeri не используются, поэто-му СВОЙСТВУ Visible компонента MediaPiayeri ПрИСВОСНО Значение false.
122 Часть II. Практикум программирования
124 Часть II. Практикум программирования
Недоступная Зафиксированная
Обычная Нажатая мышью
Рис. 4.11. Структура битового образа Glyph:картинки, соответствующие состоянию кнопки
Подготовить битовый образ для кнопки speedButton можно при помощилюбого графического редактора, в том числе и Image Editor. После запускаImage Editor надо выбрать команду File | New | Bitmap File и в появившемсяокне Bitmap Properties задать размер битового образа (например, 19×76 -если размер картинки на кнопке должен быть 19×19 пикселов). В качествепримера на рис. 4.12 приведен битовый образ для кнопки Play (speedButton2).Границы кнопок показаны условно. Обратите внимание, что изображениенажатой и зафиксированной кнопок смещены вверх и вправо относительноизображений нажатой и недоступных кнопок. Сделано это для того, чтобыво время работы программы у пользователя не создавалось впечатление, чтокнопка «ушла».
Рис. 4.12. Битовый образ для кнопки Play
В табл. 4.10 приведены значения свойств компонентов speedButtoni иspeedButton2 разрабатываемой программы. Текст программы Video Playerприведен в листинге 4.4.
Таблица 4.10. Значение свойств компонентовSpeedButtoni И SpeedButton2
Свойство
Gliph
NumGliphs
Flat
SpeedButtoni
ejbtn.bmp
4
true
SpeedButton2
plbtn.bmp
4
true
Глава 4. Мультимедиа
Свойство
AllowUp
Grouplndex
Enabled
Width
Height
ShowHint
Hint
! Листинг 4.4. Видеоплеер
SpeedButtonl
false
0
true
25
25
true
Eject
Таблица 4.10
SpeedButtoi
true
1
false
25
25
true
Play
125
(окончание)
n2
// обработка события Create
void fastcall TForml::FormCreate(TObject *Sender)
{
MediaPlayerl->Display = Forml; // отображение ролика на поверхности
11 формы
// возвращает размер кадра AVI-файла
void fastcall GetFrameSize(AnsiString f, int *w, int *h)
// в заголовке AVI-файла есть информация о размере кадра*
struct {
char RIFF[4]; // строка RIFF
long int nu_l[5]; 11 не используется
char AVIH[4]; // строка AVIH
long int nu_2[9]; //не используется
long int w; // ширина кадра
long int h; // высота кадра
} header;
TFileStream *fs; // поток (для чтения заголовка файла)
I* операторы объявления потока и его создания
можно объединить: TFileStream *fs = new TFileStream(f,fmOpenRead); */
fs = new TFileStream(f,fmOpenRead); // открыть поток для чтения
fs->Read(&header, sizeof(header)); // прочитать заголовок файла
126 _ Часть II. Практикум программирования
*w = header. w;
*h = header. h;
delete fs;
// щелчок на кнопке Eject (выбор видеоклипа)
void _ fastcall TForml: : SpeedButtonlclick (TObject *Sender)
{
OpenDialogl->Title = «Выбор клипа»;
OpenDialogl->InitialDir = «»;
OpenDialogl->FileName = «*.avi»;
if ( ! OpenDialogl->Execute () )
return; // пользователь нажал кнопку Отмена
/* При попытке открыть файл клипа, который уже открыт,
возникает ошибка. */
if ( MediaPlayerl->FileName == OpenDialogl->FileName)
return;
/* Пользователь выбрал клип. Зададим размер и положение «экрана»,
на который будет выведен клип. Для этого надо знать размер
кадров клипа. */
int fw, fh; // размер кадра клипа
int top, left; // левый верхний угол экрана
int sw, sh; // размер экрана (ширина, высота)
int mw, mh; // максимально возможный размер экрана
/ / (определяется текущим размером формы)
float kw, kh; // коэф-ты масштабирования кадра по ширине и высоте
float k; // коэфф-т масштабирования кадра
GetFrameSize(OpenDialogl->FileName, sfw, sfh);// получить размер кадра
/ / вычислим максимально возможный размер кадра
mw = Forml->ClientWidth;
mh = Forml->SpeedButtonl->Top-10;
if ( fw < mw)
kw = 1; // кадр по ширине меньше размера экрана
else kw = (float) mw / fw;
if ( fh < mh)
kh = 1; // кадр по высоте меньше размера экранаelse kh = (float) mh / fh;
Глава 4. Мультимедиа _ _ 127
II масштабирование должно быть пропорциональнымif ( kw < kh)
k = kw;
else k = kh;
// здесь масштаб определен
sw = fw * k; // ширина экрана
sh = fh * k; // высота экрана
left = (Forml->ClientWidth — sw) / 2;
top = (SpeedButtonl->Top — sh) / 2;
MediaPlayerl->FileName = OpenDialogl->FileName;
MediaPlayerl->Open() ;
MediaPlayerl->DisplayRect = Rect (left, top, sw, sh) ;
SpeedButton2->Enabled = True; // кнопка Play теперь доступна
/* если размер кадра выбранного клипа меньше размера
кадра предыдущего клипа, то экран (область формы)
надо очистить */
Forml->Canvas->FillRect (Rect (0, 0, ClientWidth, SpeedButtonl->Top) ) ;
// активизируем процесс воспроизведения
MediaPlayerl->Play () ;
SpeedButton2->Down = True;
SpeedButton2->Hint = «Stop»;
SpeedButtonl->Enabled = False;
// щелчок на кнопке Play/Stop (воспроизведение/ стоп)
void _ fastcall TForml: : SpeedButton2Click(TObject *Sender)
{if ( SpeedButton2 ->Down )
{// нажата кнопка Play
MediaPlayerl->Play() ;SpeedButton2->Hint = «Stop»;SpeedButtonl->Enabled = False; // кнопка Eject недоступна
else
// нажата кнопка Stop
MediaPlayerl->Stop() ;
SpeedButton2->Hint = «Play»;
128 Часть II. Практикум программирование
SpeedButtonl->Enabled = True; // кнопка Eject доступна
/ / сигнал от плеераvoid _ fastcall TForml : :MediaPlayerlNotify (TObject *Sender)
{if ( ( MediaPlayerl->Mode == mpStopped) && ( SpeedButton2->Down) )
{
SpeedButton2->Down = False; // «отжать» кнопку Play
SpeedButton2->Hint = «Play»;
SpeedButtonl->Enabled = True; // сделать доступной кнопку Eject
Следует обратить внимание на следующее. В качестве экрана, на которомосуществляется воспроизведение видеороликов, используется поверхностьформы. Поэтому установить значение свойства Display компонентаMediaPlayeri во время разработки формы нельзя. Кроме того, размер экранадолжен быть равен или пропорционален размеру кадров ролика. Значениесвойства Display устанавливает функция обработки события Create дляформы, а размер и положение экрана на форме — функция обработки со-бытия Click на кнопке Eject (speedButtonl). Размер экрана устанавливаетсямаксимально возможным и таким, чтобы ролик воспроизводился без иска-жения (высота и ширина экрана пропорциональны высоте и ширине кад-ров). Размер кадров ролика возвращает функция GetFrameSize, которая из-влекает нужную информацию из заголовка файла.
Создание анимацииПроцесс создания файла анимации (AVI-файла) рассмотрим на примере.Пусть надо создать анимацию, которая воспроизводит процесс рисованияэскиза Дельфийского храма (окончательный вид рисунка представлен нарис. 4.13, несколько кадров анимации — на рис. 4.14).
Для решения поставленной задачи можно воспользоваться популярной про-граммой Macromedia Flash.
В Macromedia Flash анимация, которую так же довольно часто называют»роликом» (Movie), состоит из слоев. В простейшем случае ролик представ-ляет собой один-единственный слой (Layer). Слой — это последовательностькадров (Frame), которые в процессе воспроизведения анимации выводятсяпоследовательно, один за другим. Если ролик состоит из нескольких слоев,то кадры анимации формируются путем наложения кадров одного слоя накадры другого. Например, один слой может содержать изображение фона,
Глава 4. Мультимедиа 129
на котором разворачивается действие, а другой — изображение персонажей.Возможность формирования изображения путем наложения слоев сущест-венно облегчает процесс создания анимации. Таким образом, чтобы создатьанимацию, нужно распределить изображение по слоям и для каждого слоясоздать кадры.
Рис. 4.13. Эскиз Дельфийского храма
22 23 23 37
Рис. 4.14. Кадры анимации процесса рисования Дельфийского храма
После запуска Macromedia Flash на фоне главного окна программы появля-ется окно Moviel (рис. 4.15), которое используется для создания анимации.В верхней части окна, которая называется Timeline, отражена структураанимации, в нижней части, которая называется рабочей областью, находит-ся изображение текущего кадра выбранного слоя. После запуска Macro-media Flash анимация состоит из одного слоя (Layer 1), который, в своюочередь, представляет собой один пустой (чистый) кадр.
Перед тем как приступить непосредственно к созданию кадров анимации,нужно задать общие характеристики анимации (ролика) — размер кадров искорость их воспроизведения. Характеристики вводятся в поля диалоговогоокна Movie Properties (рис. 4.16), которое появляется в результате выбора изменю Modify команды Movie. В поле Frame Rate нужно ввести скоростьвоспроизведения ролика, измеряемую в «кадрах в секунду» (fps — frame persecond, кадров в секунду), в поля Width и Height — ширину и высоту кад-ров. В этом же окне можно выбрать фон кадров (список Background Color).
После того как установлены характеристики ролика, можно приступитьк созданию кадров анимации.
Первый кадр нужно просто нарисовать. Технология создания изображенийв Macromedia Flash обычная: используется стандартный набор инструмен-тов: кисть, карандаш, пульверизатор, резинка и другие инструменты.
5 Зак. 1252
130 Часть II. Практикум программированы
&&> ш
5 ГО 15 20 25 30 s
rps f o.0s f J |
iJto Ш A .3D Я
Рис. 4.15. Окно Movie в начале работы над новой анимацией
I Movie Properties
Frame Rate: jjg fps
Width
Dimensions: J60~px
Match: Ptintet [
Background Color: f J
Ruler Units: J Pixels
Height
X J60 px
Contents J
3
•»• ‘ » .’ ‘
I «к I.
Cancel
Save Default
Help
Рис. 4.16. Характеристики ролика отображаются в окне Movie Properties
Чтобы создать следующий кадр, нужно из меню Insert выбрать командуKeyframe. В результате в текущий слой будет добавлен кадр, в который бу-дет скопировано содержимое предыдущего кадра (в большинстве случаевследующий кадр создается путем изменения предыдущего). Теперь можнонарисовать второй кадр. Аналогичным образом создаются остальные кадрыанимации.
Иногда не нужно, чтобы новый кадр содержал изображение предыдущего.В этом случае вместо команды Keyframe надо воспользоваться командойBlank Keyframe.
Глава 4. Мультимедиа 131
Если некоторое изображение должно оставаться статичным в течение вре-мени, кратного выводу нескольких кадров, то вместо того чтобы вставлять вслой несколько одинаковых кадров (Keyframe), можно сделать кадр статич-ным. Если кадр, изображение которого должно быть статичным, являетсяпоследним кадром ролика, то в окне Timeline нужно выделить кадр, до ко-торого изображение должно оставаться статичным, и из меню Insert вы-брать команду Frame. Если кадр, изображение которого должно быть ста-тичным, не является последним, то нужно выделить этот кадр и несколькораз из меню Insert выбрать команду Frame.
Можно значительно облегчить работу по созданию анимации, если разде-лить изображение на основное и фоновое, поместив каждое в отдельныйслой (именно так поступают при создании мультфильмов). Сначала надосоздать кадры слоя фона так, как было описано выше. Затем, выбрав из ме-ню Insert команду Layer, нужно добавить слой основного действия.
Следует обратить внимание, что все действия по редактированию изображе-ния направлены на текущий кадр выбранного слоя. В списке слоев выбран-ный слой выделен цветом, номер текущего кадра помечен маркером -красным квадратиком.
Чтобы выводимая анимация сопровождалась звуком, нужно сначала сделатьдоступным соответствующий звуковой файл. Для этого надо из меню Fileвыбрать команду Import и добавить в проект звуковой файл (рис. 4.17).
Папка: ^ MEDIA Hh
2] Microsoft Office 2000 <Щ RECYCLE
4JCHIMES 1|]START
<gCHORD 4|]TADA
:|s]DING <|В Звук Microsoft
JLOGOFF
^NOTIFY
Имя Файла; |TADA
Тип Файлов: ] All S ound Formats
Открыть
Отмена
Рис. 4.17. Импорт звукового файла
Затем в окне Timeline нужно выделить кадр, при отображении которогодолжно начаться воспроизведение звукового фрагмента, используя диалого-вое окно Sound (рис. 4.18), выбрать звуковой фрагмент и задать, если надо,параметры его воспроизведения. Количество повторов нужно ввести в полеLoops, эффект, используемый при воспроизведении, можно выбрать из спи-ска Effect.
132 Часть //. Практикум программированы
Sound:
22 kHz Stereo 16 Bit 1.8 s 171.0 Ш
Effect: None
Sync:! Event
Loops: ПГ
Рис. 4.18. Диалоговое окно Sound
В качестве примера на рис. 4.19 приведен вид окна Timeline в конце работынад анимацией. Анимация состоит из двух слоев. Слой Layer 2 содержитфон. Детали фона появляются постепенно, в течение 9 кадров. После этогофон не меняется, поэтому 9 кадр является статичным. Слой Layer 1 — слойосновного действия, которое начинается после того, как будет выведен фон.Вывод анимации заканчивается стандартным звуком TADA (его длитель-ность равна одной секунде). Начало воспроизведения звука совпадает с вы-водом последнего (49-го, если считать от начала ролика) кадра основногодействия, поэтому этот кадр сделан статичным в течение вывода следующих12 кадров (скорость вывода анимации — 12 кадров в секунду). Сделано этодля того, чтобы процесс вывода анимации завершился одновременно сокончанием звукового сигнала.
Рис. 4.19. Пример анимации
После того как ролик будет готов, его надо сохранить. Делается это обыч-ным образом, т. е. выбором из меню File команды Save.
Для преобразования файла из формата Macromedia Flash в AVI-форматнужно из меню File выбрать команду Export Movie и задать имя файла. За-тем в появившемся диалоговом окне Export Windows AVI (рис. 4.20) нужнозадать размер кадра (поля width и Height), из списка Video Format выбратьформат, в котором будет ‘записана видеочасть ролика, а из поля SoundFormat — формат звука.
Если установлен переключатель Compress video, то после, щелчка на кнопкеОК появится диалоговое окно, в котором можно будет выбрать один из
Глава 4. Мультимедиа 133
стандартных методов сжатия видео. При выборе видео и звукового форматанужно учитывать, что чем более высокие требования будут предъявлены ккачеству записи звука и изображения, тем больше места на диске займетAVI-файл. Здесь следует иметь в виду, что завышенные требования невсегда оправданы.
Export Windows AVI
Width Height
Dimensions: f l O O X fsS pixels
|v* Maintain aspect ratio
OK
Cancel
Video Formal: 1 24 bit color J*J
Compress video
Smooth
Sound Formal: 122kHz 16 Bit Stereo Help
Рис. 4.20. Диалоговое окно Export Windows AVI
.
ГЛАВА 5
Базы данных
В этой главе на примере базы данных «Ежедневник» показан процесс созданияприложения работы с локальной базой данных.
С точки зрения пользователя, база данных — это программа, которая обес-печивает работу с информацией. При запуске такой программы на экране,как правило, появляется таблица, просматривая которую можно найти нуж-ные сведения. Если система позволяет, то пользователь может внести изме-нения в базу данных, например, добавить новую информацию или удалитьненужную.
С точки зрения программиста, база данных — это набор файлов, в которыхнаходится информация. Разрабатывая базу данных для пользователя, про-граммист создает программу, которая обеспечивает работу с файлами данных.
В состав C++ Builder включены компоненты, используя которые програм-мист может создавать программы работы с файлами данных в форматахdBase, Microsoft Access, Infomix и Oracle и др.
База данных и СУБДБаза данных — это набор, совокупность файлов, в которых находится ин-формация. Программная система (приложение), обеспечивающая работу сбазой данных (файлами данных) называется системой управления базой дан-ных (СУБД). Следует обратить внимание, что вместо термина СУБД частоиспользуется термин база данных, при этом файлы данных и СУБД рассмат-риваются как единое целое.
Локальные и удаленные базы данныхВ зависимости от расположения программы, которая использует данные, исамих данных, а также от способа разделения данных между несколькимипользователями различают локальные и удаленные базы данных.
Глава 5. Базы данных 135
Данные локальной базы данных (файлы данных) локализованы, т. е. нахо-дятся на одном устройстве, в качестве которого может выступать диск ком-пьютера или сетевой диск (диск другого компьютера, работающего в сети).Локальные базы данных не обеспечивают одновременный доступ к инфор-мации нескольким пользователям. Для обеспечения разделения данных (дос-тупа к данным) между несколькими пользователями (программами, рабо-тающими на одном или разных компьютерах) в локальных базах данныхиспользуется метод, получивший название «блокировка файлов». Суть этогометода заключается в том, что пока данные используются одним пользова-телем, другой пользователь не может работать с этими данными, т. е. дан-ные для него закрыты, заблокированы. Несомненным достоинством ло-кальной базы данных является высокая скорость доступа к информации.Приложения работы с локальной базой данных и саму базу данных час-то размещают на одном компьютере. dBase, Paradox, FoxPro и MicrosoftAccess — это локальные базы данных.
Удаленные базы данных строятся по технологии «клиент-сервер». Програм-ма работы с удаленной базой данных состоит из двух частей: клиентской исерверной. Клиентская часть программы работает на компьютере пользова-теля и обеспечивает взаимодействие с серверной программой посредствомзапросов, передаваемых на удаленный компьютер (сервер), обеспечивая темсамым доступ к данным. Серверная часть программы, работающая на уда-ленном компьютере, принимает запросы, выполняет их и пересылает дан-ные клиентской программе. Профамма, работающая на удаленном сервере,проектируется так, чтобы обеспечить одновременный доступ к базе данныхнескольким пользователям. При этом для обеспечения доступа к даннымвместо механизма блокировки файлов используют механизм транзакций,Транзакция — это последовательность действий, которая должна быть обя-зательно выполнена над данными перед тем, как они будут переданы.В случае обнаружения ошибки во время выполнения любого из действийвся последовательность действий, составляющая транзакцию, повторяетсяснова. Таким образом, механизм транзакций обеспечивает защиту от аппа-ратных сбоев. Он также обеспечивает возможность многопользовательскогодоступа к данным. Oracle, Infomix, Microsoft SQL Server и InterBase — этоудаленные базы данных.
Структура базы данныхБаза данных — это набор однородной и, как правило, упорядоченной понекоторому критерию информации. База данных может быть представленав «бумажном» или в «компьютерном» виде.
Типичным примером «бумажной» базы данных является каталог библиоте-ки — набор бумажных карточек, содержащих информацию о книгах. Ин-формация в этой базе однородная (содержит сведения только о книгах) и
136 Часть II. Практикум программирование
упорядоченная (карточки расставлены, например, в алфавитном порядкефамилий авторов). Другими примерами «бумажной» базы данных являютсятелефонный справочник и расписание движения поездов.
Компьютерная база данных представляет собой файл (или набор связанныхфайлов), содержащий информацию, который часто называют файлом дан-ных. Файл данных состоит из записей. Каждая запись содержит информациюоб одном экземпляре. Например, каждая запись базы данных «Ежедневник»содержит информацию только об одном экземпляре — запланированноммероприятии или задаче.
Записи состоят из полей. Каждое поле содержит информацию об одной ха-рактеристике экземпляра. Например, запись базы данных «Ежедневник»может состоять из полей: «Задача», «Дата» и «Примечание «. «Задача», «Дата»и «Примечание » — это имена полей. Содержимое полей характеризует кон-кретную задачу.
Следует обратить внимание, что каждая запись состоит из одинаковых по-лей. Некоторые поля могут быть не заполнены, однако они все равно при-сутствуют в записи.
На бумаге базу данных удобно представить в виде таблицы. Каждая строкатаблицы соответствует записи, а ячейка таблицы — полю. При этом заголо-вок столбца таблицы — это имя поля, а номер строки таблицы — номерзаписи.
Информацию компьютерных баз данных обычно выводят на экран в видетаблиц. Поэтому часто вместо словосочетания «файл данных» используютсловосочетание «таблица данных» или просто «таблица».
ПсевдонимРазрабатывая программу работы с базой данных, программист не знает, накаком диске и в каком каталоге будут находиться файлы базы данных вовремя ее использования. Например, пользователь может поместить базуданных в один из каталогов диска С:, D: или на сетевой диск. Поэтому воз-никает проблема передачи в программу информации о месте нахожденияфайлов базы данных.
В C++ Builder проблема передачи в программу информации о месте нахож-дения файлов базы данных решается путем использования псевдонима базыданных. Псевдоним (Alias) — это имя, поставленное в соответствие реаль-ному, полному имени каталога базы данных. Например, псевдонимом ката-лога C:\data\Petersburg может быть имя Peterburg. Программа работы с базойданных для доступа к данным использует не реальное имя каталога, а псев-доним. Псевдоним базы данных можно создать при помощи утилиты BDEAdministrator. Информация о всех зарегистрированных в системе псевдони-мах хранится в специальном файле.
Глава 5. Базы данных 137
Компоненты доступаи манипулирования даннымиОбычно для доступа и манипулирования данными используется соответст-вующая СУБД. Однако часто возникает необходимость получить доступ кинформации, которая находится в базе данных, из прикладной программы.Решить эту задачу можно при помощи компонентов доступа к данным.
C++ Builder предоставляет в распоряжение программиста компоненты, ис-пользуя которые можно построить приложение, обеспечивающее работупрактически с любой базой данных.
Компоненты доступа к данным находятся во вкладках BDE, Data Access,ADO и InterBase. Компоненты вкладок BDE и Data Access для доступак данным используют процессор баз данных Borland Database Engine (BDE),реализованный в виде набора динамических библиотек и драйверов. Ком-поненты вкладки ADO для доступа к данным используют разработаннуюMicrosoft технологию ADO (ActiveX Data Object — ADO). Компоненты вклад-ки InterBase обеспечивают непосредственный доступ к данным InterBase.
Наиболее универсальным механизмом доступа к базам данных являетсямеханизм, реализованный на основе BDE. Драйверы, входящие в составBDE, обеспечивают доступ как к локальным базам данных (Paradox, Access,dBASE), так и к удаленным серверам баз данных (Microsoft SQL Server,Oracle, Infomix). Набор драйверов, включенных в BDE, определяется вари-антом C++ Builder.
Создание базы данныхПроцесс создания базы данных рассмотрим на примере. Создадим локаль-ную базу данных «Ежедневник», которая представляет собой одну-един-ственную таблицу в формате Paradox. Для этого воспользуемся поставляе-мой вместе с C++ Builder утилитой Database Desktop.
Запустить Database Desktop можно из C++ Builder, выбрав в меню Toolsкоманду Database Desktop, или из Windows (команда Пуск | Программы |C++Builder \ Database Desktop).
Процесс создания базы данных состоит из двух шагов: сначала надо создатьпсевдоним базы данных, затем — таблицу (в общем случае — несколько таб-лиц). Псевдоним (Alias) определяет расположение таблиц базы данных ииспользуется для доступа к ним.
Для того чтобы создать псевдоним, надо:
1. В меню Tools выбрать команду Alias Manager.
2. В появившемся диалоговом окне Alias Manager щелкнуть на кнопке New.
138 Часть II. Практикум программированы
3. Ввести в поле Database alias псевдоним создаваемой базы данных — на-пример, organizer,
4. Ввести в поле Path путь к файлам таблиц базы данных (таблицы будутсозданы на следующем шаге).
5. Щелкнуть на кнопке Keep New (рис. 5.1).
Теперь можно приступить к созданию таблицы.
Alias Manager
f/ Public alias
Database alias: organisei
(STANDARD
Defining new database alias. Enterchanges and choose Keep Newwhen done.
Path; /D:\ProiectsCe\Org S how publi£ aliases orfy
Show protgct aliases pnly
Show j.11 aliases
growse..
Keep New
Remove
Save As… Ji
OK
Cancel
Help
Рис. 5.1. Создание псевдонима базы данных
Чтобы создать таблицу, надо в меню File выбрать команду New | Table(рис. 5.2), затем в появившемся диалоговом окне Create Table — тип табли-цы (рис. 5.3).
В результате выполнения перечисленных выше действий открывается окноCreate Table, в котором надо определить структуру таблицы — задать именаполей базы данных и указать их тип и размер (рис. 5.4).
Записи базы данных «Ежедневник» состоят из двух полей: Task_F и Date_F.Поле Task_F (символьного типа) содержит название задачи (мероприятия),поле Date_F (типа Date) — дату, не позднее которой задача должна бытьвыполнена (дату проведения мероприятия).
Имена полей вводят в столбец Field Name, тип — в столбец Туре. При запи-си имени поля можно использовать латинские буквы и цифры. При этомследует учитывать, что имя поля не должно совпадать ни с одним из ключе-вых слов языка SQL (таких, например, как WHEN или SELECT). Тип поля оп-ределяет тип данных, которые могут быть помещены в поле. Задается типполя при помощи одной из приведенных в табл. 5.1 констант. Константа,
Глава 5. Базы данных 139
«* Database Desktop
> File Edit Tools Window Help
I2QQHHHD QBE Query..Open > SQL Fie
Working Directory..
Private Directory..,
G2E3
Рис. 5.2. Начало работы над новой таблицей
OK Cancel ! Help
Рис. 5.3. В списке Table type надо выбрать тип создаваемой таблицы (файла данных)
Cieate Paradox 7 Table. ( Unlilled )
Field roster:
1Field Name
2’Date-F
.Type1 Size
i A :
mm
TableBiopertie;:
(validity Checks
Г 1. Required Field
2. Minimum value:
3. Maximum value:
4. Default value:
Hight-cSck or press Spacebar to choose a field type
Рис. 5.4. В диалоговом окне Create Table надо задать структуру таблицы создаваемой базы данных
140 Часть II. Практикум программирования
определяющая тип поля, может быть введена с клавиатуры или выбором всписке, который появляется в результате нажатия клавиши «пробел» илищелчка правой кнопкой мыши.
Таблица 5.1. Тип поля определяет тип информации,которая может в нем находиться
Тип поля Константа Содержимое поля
Alpha
Number
Money
Short
Long Integer
Date
Time
Timestamp
Memo
Formated Memo
Graphic
Logical
N
$
S
I
D
Т
@M
G
I
Autoincrement +
Строка символов. Максимальная длина строкиопределяется характеристикой Size, значения ко-торой находятся.в диапазоне 1—255
Число из диапазона Ю»307—10308 с 15-ю значащи-ми цифрами
Число в денежном формате. Цифры числа делятсяна группы при помощи разделителя групп разря-дов. Так же выводится знак денежной единицы
Целое число из диапазона от —32767 до 32767
Целое число из диапазона от —2147483648до 2 147 483 647
Дата
Время, отсчитываемое от полуночи, выраженноев миллисекундах
Время и дата
Строка символов произвольной длины. Поле типаMemo используется для хранения текстовой ин-формации, которая не может быть сохранена вполе типа Alpha. Размер поля (1—240) определяет,сколько символов хранится в таблице. Остальныесимволы хранятся в файле, имя которого совпада-ет с именем файла таблицы, а расширение фай-ла— то
Строка символов произвольной длины (как у типаMemo). Имеется возможность указать тип и размершрифта, способ оформления и цвет символов
Графика
Логическое значение «истина» (true) или «ложь»(false)
Целое число. При добавлении в таблицу очеред-ной записи в поле записывается число на единицубольшее, чем то, которое находится в соответст-вующем поле последней добавленной записи
Глава 5. Базы данных 141
Таблица 5.1 (окончание)
Тип поля Константа Содержимое поля
Bytes
Binary
Двоичные данные. Поле этого типа используетсядля хранения данных, которые не могут быть ин-терпретированы Database Desktop
Двоичные данные. Поле этого типа используетсядля хранения данных, которые не могут быть ин-терпретированы Database Desktop. Как и данныетипа Memo, эти данные не находятся в файле таб-лицы. Поля типа Binary, как правило, содержатаудиоданные
Save Table As
Папка:
Имя файла [org
1ип Файла: | Paradox («. do)
Сохранить
Отмена
oiganizer «3Options: I?
Г
Рис. 5.5. Сохранение таблицы базы данных
После того как будут определены все поля, надо щелкнуть на кнопке SaveAs. На экране появится диалоговое окно Save Table As (рис. 5.5). В нем нужновыбрать (в списке Alias) псевдоним базы данных, элементом которой явля-ется сохраняемая таблица, в поле Имя файла ввести имя файла таблицы,установить переключатель Display table и щелкнуть на кнопке Сохранить.В результате в указанном каталоге (псевдоним связан с конкретным катало-гом локального или сетевого диска) будет создан файл таблицы и на экранепоявится диалоговое окно Table (рис. 5.6), в котором можно ввести данныев только что созданную таблицу (базу данных). Следует обратить внимание,что по умолчанию Database Desktop открывает таблицы в режиме просмот-ра, и для того чтобы внести изменения в таблицу (добавить, удалить или
142 Часть II. Практикум программированы
изменить запись), необходимо, выбрав в меню Table команду Edit (или на-жав клавишу <F8>), активизировать режим редактирования таблицы.
(Л Database Desktop
File £dit yiew Tjble fiecocd Joels Window
М^ШЖ! <« < 81
.2 Table: roigamzeirorg.dborg
1′ Олимпиада, физика~l!; Олимпиада, ик. яз.
3 Олимпиада, математика4 :
‘09.02.2003; 16.02.2003123,02.03
IDщади
Record Э of 4 locked
Рис. 5.6. Database Desktop можно использовать для ввода информации в базу данных
Данные в таблицу вводят обычным образом. Для перехода к следующемуполю (столбцу таблицы) нужно нажать клавишу <Enter>. Если текущее полеявляется последним полем последней строки (записи), то в результате нажа-тия клавиши <Enter> в таблицу будет добавлена строка (новая запись).
Если во время заполнения таблицы необходимо внести изменения в ужезаполненное поле, то надо, используя клавиши перемещения курсора, вы-брать это поле и нажать клавишу <F2>.
Если при вводе данных в таблицу буквы русского алфавита отображаютсяневерно, то надо изменить шрифт, который используется для отображенияданных. Для этого нужно в меню Edit выбрать команду Preferences, затем, впоявившемся диалоговом окне во вкладке General щелкнуть на кнопкеChange. В результате этих действий откроется диалоговое окно Change Font(рис. 5.7), в котором надо выбрать русифицированный шрифт TrueType.Следует обратить внимание, что в Microsoft Windows 2000 (Microsoft Win-dows XP) используются шрифты типа Open Type, в то время как программаDatabase Desktop ориентирована на работу со шрифтами TrueType. Поэтомув списке шрифтов нужно выбрать русифицированный шрифт именноTrueType. После выбора шрифта необходимо завершить работу с Database
Глава 5. Базы данных 143
Desktop, т. к. внесенные в конфигурацию изменения будут действительнытолько после перезапуска утилиты.
Change Font
font:
О Arial Narrow
Book Antique0 Bookman Old Style
-Sample
АаВЬБбФф
Шрифт TrueType. Он используется как привыводе на экран, так и при печати.
Рис. 5.7. Для правильного отображения данных в Database Desktopнужно выбрать русифицированный шрифт TrueType
Доступ к базе данныхДоступ к базе данных обеспечивают компоненты Database, Table, Query иDataSource. Значки этих компонентов находятся на вкладках Data Accessи BDE (рис. 5.8).
i Data Access
1>иш
DataSource
BDE
Table Query Database
Рис. 5.8. Компоненты вкладок Data Access и BDE обеспечивают доступ к данным
Компонент Database представляет базу данных как единое целое, т. е. каксовокупность таблиц, а компонент Table — как одну из таблиц базы дан-ных. Компонент DataSource (источник данных) обеспечивает связь междукомпонентом отображения-редактирования данных (например, компонентDBGrid) и источником данных, в качестве которого может выступать таблица
144 Часть II. Практикум программирования
(компонент Table) или результат выполнения SQL-запроса к таблице (ком-понент Query). Компонент DataSource позволяет оперативно выбирать ис-точники данных, использовать один и тот же компонент (например, DBGrid)для отображения всей таблицы (базы данных) или только результата выпол-нения SQL-запроса к этой таблице. Компоненты доступа к данным обра-щаются к базе данных не напрямую, а через процессор баз данных -Borland Database Engine (BDE).
Ядро BDE образуют динамические библиотеки, реализующие механизмыобмена данными и управления запросами. В состав BDE включены драйве-ры, обеспечивающие работу с файлами данных форматов Paradox, dBase,FoxPro. Имеется также механизм подключения драйверов ODBC. Доступк данным SQL серверов обеспечивает отдельная система драйверов — SQLLinks. С их помощью можно получить доступ к базам данных Oracle,Infomix, Sysbase и Interbase.
Механизм взаимодействия компонента отображения-редактирования дан-ных (DBGrid) С Данными (Table ИЛИ Query) Через КОМПОНСНТ DataSource ПОКа-зан на рис. 5.9.
Table
Компонентотображения-
редактированияданных (например,
DBGrid)
База данных
Query
Рис. 5.9. Взаимодействие компонентов доступа-отображения данных и BDE
В форму разрабатываемого приложения надо добавить компоненты Table иDataSource.
Свойства компонентов таЫе и DataSource приведены в табл. 5.2 и 5.3.Свойства перечислены в том порядке, в котором рекомендуется устанавли-вать их значения.
Значения свойств DatabaseName и TabieName задаются путем выбора из спи-сков. В списке DatabaseName перечислены все зарегистрированные на данномкомпьютере псевдонимы, а в списке TabieName — имена файлов таблиц, ко-торые находятся в соответствующем псевдониму каталоге.
Глава 5. Базы данных 145
Таблица 5.2. Свойства компонента Table
Свойство Определяет
DatabaseName Имя базы данных, частью которой является таблица (файл дан-ных), для доступа к которой используется компонент. В качествезначения свойства следует использовать псевдоним базы данных
TableName Имя файла данных (таблицы данных), для доступа к которомуиспользуется компонент
ТаЫеТуре Тип таблицы. Таблица может быть набором данных в форматеParadox (ttParadox), dBase (ttDBase), FoxPro (ttFoxPro) или другоготипа. По умолчанию значение свойства равно «Default — это оз-начает, что тип таблицы будет определен на основе информации,которая находится в файле таблицы
Active Признак активизации файла данных (таблицы). В результате при-сваивания свойству значения true файл таблицы будет открыт
Таблица 5.3. Свойства компонента DataSource
Свойство Определяет
Name
DataSet
Имя компонента. Используется для доступа к свойст-вам компонента
Компонент, представляющий входные данные (таблицаили запрос)
Свойство DataSet компонента DataSource обеспечивает возможность выбораисточника данных, а также связь между компонентом, представляющимданные (таблица или запрос), и компонентом отображения данных. Напри-мер, большая база данных может быть организована как набор таблиц оди-наковой структуры. В этом случае в приложении работы с базой данныхкаждой таблице будет соответствовать свой компонент Table, а выбор кон-кретной таблицы можно осуществить установкой значения свойстваDataSet.
Компоненты доступа к базе данных являются невизуальными и во времяработы программы на форме не видны. Поэтому их можно поместить в лю-бую точку формы (рис. 5.10).
Значения свойств компонентов Table! и DataSourcel приложения «Ежеднев-ник» приведены в табл. 5.4 и 5.5.
146 Часть II. Практикум программирования
Таблица 5.4. Значения свойств компонента таЫе!
Свойство Значение
Name
DatabaseName
TableName
Active
Tab!el
organizer
org.db
false
Свойство
Таблица 5.5. Значения свойств компонента Da taSourcel
Значение
Name
DataSet
DataSourcel
Tablel
• Tabiel
— DataSourcel
Рис. 5.10. Форма после добавления компонентов Table и DataSource
Отображение данныхПользователь может просматривать базу данных в режиме формы или в ре-жиме таблицы. В режиме формы можно видеть только одну запись, а в ре-жиме таблицы — несколько записей одновременно. Часто эти два режимакомбинируют. Краткая информация (содержимое некоторых ключевых по-лей) выводится в табличной форме, а при необходимости увидеть содержи-мое всех полей выполняется переключение в режим формы.
Глава 5. Базы данных 147
Компоненты, обеспечивающие отображение и редактирование полей запи-сей базы данных, находятся на вкладке Data Controls (рис. 5.11).
] Data Controls |
DBText DBMemo
DBEdit
Рис. 5.11. Компоненты отображения и редактирования полей
Компонент DBText обеспечивает отображение содержимого отдельного поля,а компоненты DBEdit и овмето — отображение и редактирование. В табл. 5.6перечислены некоторые свойства этих компонентов. Свойства перечисленыв том порядке, в котором следует устанавливать их значения.
Таблица 5.6. Свойства компонентов DBText, DBEdit и овмето
Свойство Определяет
DataSource Источник данных (компонент Table или Query)
DataField Поле записи, для отображения или редактирования которого исполь-зуется компонент
Для обеспечения просмотра базы данных в режиме таблицы используетсякомпонент DBGrid. Свойства компонента DBGridl определяют вид таблицы идействия, которые могут быть выполнены над данными во время рабо-ты программы. В табл. 5.7 перечислены некоторые свойства компонентаDBGrid.
Таблица 5.7. Свойства компонента DBGrid
Свойство Определяет
DataSource Источник данных (компонент Table или Query)
Columns Отображаемая информация (поля записей)•
Options. dgTitles Разрешает вывод строки заголовка столбцов
Options.dglndicator Разрешает вывод колонки индикатора. Во время рабо-ты с базой данных текущая запись помечается в колон-ке индикатора треугольником, новая запись — звездоч-кой, редактируемая — специальным значком
Options.dgColumnResize Разрешает менять во время работы программы ширинуколонок таблицы
148 Часть II. Практикум программирования
Таблица 5,7 (окончание)
Свойство Определяет
Options. dgColLines Разрешает выводить линии, разделяющие колонки таб-лицы
Options. dgRowLines Разрешает выводить линии, разделяющие строки таб-лицы
В диалоговом окне программы «Ежедневник» данные отображаются в режи-ме таблицы. Поэтому в форму надо добавить компонент DBGridi и устано-вить значения его свойств в соответствии с табл. 5.8.
Таблица 5.8. Значения свойств компонента DBGridi
Свойство Значение
DataSource DataSourcel
Как было сказано ранее, свойство coiunns компонента DBGrid определяетполя, содержимое которых будет отображено в таблице DBGrid. Свойствоcolumns является сложным свойством и представляет собой массив элемен-тов типа TColumn. Свойства элементов массива определяют поля, содержи-мое которых будет в таблице, а так же вид колонок (табл. 5.9).
Таблица 5.9. Свойства объекта TColumn
Свойство Определяет
FieldName Поле, содержимое которого отображается в колонке
width Ширину колонки в пикселах
Font Шрифт, используемый для вывода текста в ячейках колонки
Color Цвет фона колонки
Alignment Способ выравнивания текста в ячейках колонки. Текст можетбыть выровнен по левому краю (taLeftJustifyj, по центру(taCenter) или по правому краю (taRightJustify)
Title.Caption Заголовок колонки. Значением по умолчанию является имяполя записи
Title.Alignment Способ выравнивания заголовка колонки. Заголовок можетбыть выровнен по левому краю (taLeftJustify), по центру(taCenter) или по правому краю (taRightJustify)
Title. Color Цвет фона заголовка колонки
Title. Font Шрифт заголовка колонки
Глава 5. Базы данных 149
По умолчанию компонент DBGrid содержит одну колонку. Чтобы добавить вкомпонент DBGrid еще одну колонку, надо в окне Object Inspector выбратьсвойство Coiums компонента DBGrid, щелкнуть на кнопке с тремя точками, азатем в появившемся окне Editing — на кнопке Add New (рис. 5.12). Послеэтого, используя Object Inspector, надо установить значения свойств элемен-тов массива columns.
Выбрать настраиваемую колонку (ее свойства отражаются в окне ObjectInspector) можно в окне Editing или в окне Object TreeView.
^Editing DBGtidl >Coluram
(DBGiidl
Properties I Events I
J
: r Align:’E3 Anchors
:; BiDiModeH BorderStife
‘>. color ‘
;aNone
bdLeltToRight]bsSingle
I Columns;|Ш Constraints
i Cursor; i DataSource’ DefaultOrawrijttue
i! DiagCursoiDragKind
DragModeEnabled
i[ FixedCobr
ijEIFont
i[. Height
AD shown
lidColumns) ту
(TSizeCoristral«tiue _ccDelault
Add New (Ins)
dkDiag
drhM anualtrue
clBtnFace
(TFont)
120
Рис. 5.12. Чтобы добавить колонку в компонент DBGrid, щелкните в строке Coiumsна кнопке стремя точками, затем — на кнопке Add New
В простейшем случае для каждой колонки достаточно установить значениесвойства FieldName, которое определяет поле, содержимое которого отобра-жается в колонке, а также значение свойства Title.caption, определяющеезаголовок колонки. В табл. 5.10 приведены значения свойств компонентаDBGridi, а на рис. 5.13 — вид формы после настройки компонента.
Таблица 5.10. Значения свойств компонента
Свойство Значение
Соlumns[0].FieldName Date_F
Columns[0].TitleCaption Когда
Columns[0].Title.Font.Style.Italic true
150 Часть II. Практикум программирования
Таблица 5.10 (окончание)
Свойство Значение
Columns,!I] .FieldName Task__F
Columns[ 1 ] .TitleCaption Что
Columns[1].Title.Font.Style.Italic true
?. Ежедневник
\Когда Vro
-DBGrid!
-j Tablel
-] DataSource!
Рис. 5.13. Вид формы после настройки компонента DBGrid
Если после настройки компонента DBGrid присвоить значение true свойствуActive компонента Tablel, то в поле компонента DBGrid будет выведено со-держимое базы данных.
Манипулирование даннымиДля того чтобы пользователь мог не только просматривать базу данных (ре-шение этой задачи в рассматриваемой программе обеспечивает компонентDBGrid), но и редактировать ее, в форму приложения надо добавить компо-нент DBNavigator, значок которого находится на вкладке Data Controls(рис. 5.14). Компонент DBNavigator (рис. 5.15) представляет собой наборкомандных кнопок, обеспечивающих перемещение указателя текущей запи-си к следующей, предыдущей, первой или последней записи базы данных, атакже добавление в базу данных новой записи и удаление текущей записи.
Табл. 5.11 содержит описания действий, которые выполняются в результатещелчка на соответствующей кнопке компонента DBNavigator. Свойства ком-понента DBNavigator перечислены в табл. 5.12.
Глава 5. Базы данных 151
DBNavigator
Рис. 5.14. Значок компонента DBNavigator находится на вкладке Data Controls
X С-
Рис. 5.15. Компонент DBNavigator
Таблица 5.11. Кнопки компонента DBNavigator
Кнопка
Гй1 К первой
[VJ К предыдущей
Г*Л К следующей
!>Г1 К последней
Г+1 Добавить
fwl Удалить
Г ж 1 Редактирование
Гу1 Сохранить
Рх] Отменить
Г<«] Обновить
Обозначение
nbFirst
nbPrior
nbNext
nbLast
nblnsert
nbDelete
nbEdit
nbPost
Cancel
nbRefresh
Действие
Указатель текущей записи перемещаетсяк первой записи файла данных
Указатель текущей записи перемещаетсяк предыдущей записи файла данных
Указатель текущей записи перемещаетсяк следующей записи файла данных
Указатель текущей записи перемещаетсяк последней записи файла данных
В файл данных добавляется новая запись
Удаляется текущая запись файла данных
Активизирует режим редактирования теку-щей записи
Изменения, внесенные в текущую запись,записываются в файл данных
Отменяет внесенные в текущую запись из-менения
Записывает внесенные изменения в файл
Таблица 5. 12. Свойства компонента DBNaviga tor
Свойство
DataSource
Определяет
Компонент, являющийся источником данных. В качестве ис-
VisibleButtons
точника данных может выступать база данных (компонентDatabase), таблица (компонент Table) или результат выпол-нения запроса (компонент Query)
Видимые командные кнопки
152 Часть II. Практикум программирования
Следует обратить внимание на свойство visibleButtons. Оно позволяетскрыть некоторые кнопки компонента DBNavigator и тем самым запретитьвыполнение соответствующих операций над файлом данных. Например,присвоив значение false свойству visibleButtons.nbDeiete, можно скрытькнопку nbDeiete и тем самым запретить удаление записей.
На рис. 5.16 приведен вид формы приложения «Ежедневник» после до-бавления Компонента DBNavigator. СВОЙСТВУ DataSource КомпонентаDBNavigatorl СЛСДубТ ПрИСВОИТЬ Значение Tablel.
(Г.- Ежедневник
Когда \ Что
-DBNavigatorl
-DBGrid!
-Tablel
-DalaSourcel
Рис. 5.16. Форма приложения после добавления компонента DBNavigator
После этого программу можно откомпилировать и запустить. Следует обра-тить внимание, что для того чтобы после запуска программы в окне появи-лась информация или, если база данных пустая, можно было вводить новуюинформацию, свойство Active таблицы-источника данных должно иметьзначение true.
Работа с базой данных, представленной в виде таблицы, во многом похожана работу с электронной таблицей Microsoft Excel. Используя клавиши пе-ремещения курсора вверх и вниз, а также клавиши листания текста страни-цами (<Page Up> и <Page Down>), можно, перемещаясь от строки к строке,просматривать записи базы данных. Нажав клавишу <Ins>, можно добавитьзапись, а нажав клавишу <Del> — удалить. Для того чтобы внести измене-ния в поле записи, нужно, используя клавиши перемещения курсора влевои вправо, выбрать необходимое поле и нажать клавишу <F2>.
Глава 5. Базы данных 153
Выбор информации из базы данныхПри работе с базой данных пользователя, как правило, интересует не все еесодержимое, а некоторая конкретная информация. Найти нужные сведенияможно последовательным просмотром записей. Однако такой способ поисканеудобен и малоэффективен.
Большинство систем управления базами данных позволяют выполнять вы-борку нужной информации путем выполнения запросов. Пользователь фор-мулирует запрос, указывая критерий, которому должна удовлетворять инте-ресующая его информация, а система выводит записи, удовлетворяющиезапросу.
Для выборки из базы данных записей, удовлетворяющих некоторому крите-рию, предназначен компонент Query (рис. 5.17).
QueryРис. 5.17. Компонент Query
Компонент Query, как и компонент Table, представляет собой записи базыданных, но в отличие от последнего он представляет не всю базу данных(все записи), а только ее часть — записи, удовлетворяющие критерию за-проса.
В табл. 5.13 перечислены некоторые свойства компонента Query.
Таблица 5.13. Свойства компонента Query
Свойство Определяет
Name Имя компонента. Используется компонентом DataSource для связирезультата выполнения запроса (набора записей) с компонентом,обеспечивающим просмотр записей, например DBGrid
SQL Записанный на языке SQL запрос к базе данных (к таблице)
Active При присвоении свойству значения true активизируется процессвыполнения запроса
RecordCount Количество записей, удовлетворяющих критерию запроса
Для того чтобы во время разработки программы задать, какая информациядолжна быть выделена из базы данных, в свойство SQL надо записать за-прос — команду на языке SQL (Structured Query Language, язык структури-рованных запросов).
154 Часть II. Практикум программирования
В общем виде SQL-запрос на выборку данных из базы данных (таблицы)выглядит так:
SELECT СписокПолей
FROM ТаблицаWHERE
(Критерий)ORDER BY СписокПолей
где:
О SELECT — команда «выбрать из таблицы записи и вывести содержимоеполей, имена которых указаны в списке»;
П FROM — параметр команды, который определяет имя таблицы, из которойнужно сделать выборку;
О WHERE — параметр, который задает критерий выбора. В простейшем слу-чае критерий — это инструкция проверки содержимого поля;
D ORDER BY — параметр, который задает условие, в соответствии с которымбудут упорядочены записи, удовлетворяющие критерию запроса.
Например,запрос
SELECT Date_F, Task_F
FROM ‘:organizer:org.db’
WHERE ( Date_F = ‘09.02.2003’)
ORDER BY Date_F
обеспечивает выборку записей из базы данных organizer (из таблицы org.db),у которых в поле Date_F находится текст оэ.02.2003, т. е. формирует списокмероприятий, назначенных на 9 февраля 2003 года.
Другой пример. Запрос
SELECT Date_F, Task_F
FROM ‘:organizer:org.db’
WHERE
( Date_F >= ‘10.02.2003’) AND ( Date_F <= 46.02.2003′)
ORDER BY Date_F
формирует список дел, назначенных на неделю (с 10 по 16 февраля2003 года).
Запрос может быть сформирован и записан в свойство SQL компонентаQuery во время разработки формы или во время работы программы.
Для записи запроса в свойство SQL во время разработки формы используетсяредактор списка строк (рис. 5.18), окно которого открывается в результате
Глава 5, Базы данных 155
щелчка на кнопке с тремя точками в строке свойства SQL (в окне ObjectInspector).
String List Edilot
! 5 lines
SELECT Date_F, Task_FFROM ‘:organize!:org.db’WHERE[ Dale F >= ‘09.02.2003’) AND ( Date_F <= ‘16.02.2003’)
lORDERBYDate F
Code Editor… I fiK Cancel Help
Рис. 5.18. Ввод SQL-запроса во время разработки формы приложения
Сформировать запрос во время работы профаммы можно при помощи ме-тода Add, применив его к свойству SQL компонента Query.
Ниже приведен фрагмент кода, который формирует запрос (т. е. записываеттекст запроса в свойство SQL компонента Query) на выбор информации изтаблицы org базы данных organizer. Предполагается, что строковая пере-менная today (ТИП AnsiString) содержит дату В формате dd/mm/yyyy.
Forml->Queryl->SQL->Add(«SELECT Date_F, Task_F»);
Forml->Queryl->SQL->Add(«FROM ‘:organizer:org.db'»);
Forml->Queryl->SQL->Add(«WHERE (Date_F = ‘» + today + «‘)»);
Forml->Queryl->SQL->Add(«ORDER BY Date_F»);
Если запрос записан в свойство SQL компонента Query во время разработкиформы приложения, то во время работы профаммы критерий запроса мож-но изменить простой заменой соответствующей строки текста запроса.
Например, для запроса:
SELECT Date_F, Task_F
FROM ‘:organizer:org.db’
WHERE
( Date_F = ‘09.02.2003’}
ORDER BY Date_F
инструкция замены критерия выглядит так:
Queryl->SQL->Strings[3] = «(Date_F = ‘» + tomorrow + » ‘ ) » ;
156 Часть II, Практикум программирования
Следует обратить внимание на то, что свойство SQL является структурой ти-па TStrings, в которой строки нумеруются с нуля.
Для того чтобы пользователь мог выбирать информацию из базы данных,в форму разрабатываемого приложения надо добавить кнопки Сегодня, Зав-тра, Эта неделя и Все (рис. 5.19). Назначение этих кнопок очевидно. Такжев форму добавлены два компонента Label. Поле Labeii используется дляотображения текущей даты. В поле Labei2 отображается режим просмотрабазы данных.
Label2:м + — ••• V
Когда Что
Сегодня Завтра : ! Эта неделя \’. Все
Рис. 5.19. Окончательный вид формы
Функции обработки события click на кнопках Сегодня, Завтра и Эта неде-ля приведены в листинге 5.1. Каждая из этих функций изменяет соответст-вующим образом сформированный во время разработки формы SQL-запрос.Для получения текущей даты функции обращаются к стандартной функцииNOW, которая возвращает текущую дату и время. Преобразование даты встроку СИМВОЛОВ ВЫПОЛНЯет стандартная ФУНКЦИЯ FormatDateTime.
| Листинг 5.1. Обработка события Click на кнопках Сегодня, Завтра и Эта неделя \
// Щелчок на кнопке Сегодня
void fastcall TForml::ButtonlClick(TObject *Sender)
{
AnsiString today = FormatDateTime(«dd/iran/yyyy»,Now());
Forml->Label2->Caption = «Сегодня»;
// изменить критерий запроса
Queryl->SQL->Strings[3] = «(Date_F = ‘» + today + «‘)»;
Глава 5. Базы данных _ 157
// выполнить запрос
Forml->Queryl->Open ( ) ;
Forml->DataSourcel->DataSet = Forml->Queryl;
if ( ! Forml->Queryl->RecordCount)
{
ShowMessage («На сегодня никаких дел не запланировано!»);
// щелчок на кнопке Завтра
void _ fastcall TForml: :Button2Click (TObject *Sender)
{
AnsiString tomorrow = FormatDateTime («dd/mm/yyyy», Now() +1);
Forml->Label2->Caption = «Завтра»;
// изменить критерий запроса
Queryl->SQL->Strings[3] = » (Date_F = ‘» + tomorrow + «‘)»;
// выполнить запрос
Forml->Queryl->Open ( ) ;
Forml->DataSourcel->DataSet = Forml->Queryl;
if ( ! Forml->Queryl->RecordCount)
{
ShowMessage («На завтра никаких дел не запланировано!»);
// щелчок на кнопке Эта неделя
void _ fastcall TForml: :Button3Click (TObject Sender)
{
// от текущего дня до конца недели (до воскресенья)
TDateTime Present,
EndOfWeek;
Label2->Caption = «На этой неделе»;
Present= Now (); // Wow — возвращает текущую дату
// для доступа к StartOfWeek, EndOfWeek, YearOf и WeekOf
// надо подключить DateUtils.hpp (см. директивы ^include)
EndOfWeek = StartOfAWeek(YearOf(Present),WeekOf(Present)+1);
158 _ Часть II. Практикум программирования
Queryl->SQL->Strings[3] =
«(Date_F >= ‘ «+ FormatDateTime («dd/iratt/yyyy», Present) +» ‘} AND » +
» (Date_F < ‘ «+ FormatDateTime ( «dd/mm/yyyy», EndOfWeek) +» ‘ ) » ;
Queryl->0pen ( ) ;
if ( Queryl->RecordCount)
IDataSourcel->DataSet = Forml->Queryl;
}
else
ShowMessage («На эту неделю никаких дел не запланировано.»);
В результате щелчка на кнопке Все в диалоговом окне программы должнобыть выведено все содержимое базы данных. Базу данных представляеткомпонент таЫе!. Поэтому функция обработки события click на кнопкеВсе просто «переключает» источник данных на таблицу (листинг 5.2).
: Листинг 5.2. Обработка события на кнопке Все
// Щелчок на кнопке Всеvoid _ fastcall TForml : :Button4Click(TObject *Sender)
{// установить: источник данных — таблица
,
// таким образом, отобажается вся БДForml->DataSourcel->DataSet = Forml-XTablel;
Label2->Caption = «Все, что намечено сделать»;
Программа «Ежедневник» спроектирована таким образом, что при каждомее запуске в диалоговом окне выводится текущая дата и список дел, запла-нированных на этот и ближайшие дни. Вывод даты и названия дня недели вполе Label выполняет функция обработки события onActivate (ее текстприведен в листинге 5.3). Эта же функция формирует критерий запроса кбазе данных, обеспечивающий вывод списка задач, решение которых запла-нировано на сегодня (в день запуска программы) и на завтра. Если про-грамма запускается в пятницу, субботу или воскресенье, то завтрашнимднем считается понедельник. Такой подход позволяет сделать упреждающеенапоминание, ведь, возможно, что пользователь не включит компьютерв выходные дни.
Листинг 5.3. Функция обработки события OnActivate
AnsiString stDay[7] = («воскресенье»,»понедельник»,»вторник», «среда»,
«четверг»,»пятница»,»суббота»};
Глава 5. Базы данных 759
AnsiString stMonth[12] = {«января»,»февраля»,»марта»,
«апреля», «мая», «июня»‘, «июля»,
«августа»,»сентября»,»октября»,
«ноября»,»декабря»};
// активизация формы
void fastcall TForml::FormActivate(TObject *Sender)
{
TDateTime Today, // сегодня
NextDay; // следующий день (не обязательно завтра)
Word Year, Month, Day; // год, месяц, день
Today = Now ();
DecodeDate(Today, Year, Month, Day);
Labell->Caption = «Сегодня » + IntToStr(Day) + » » +
stMonth[Month-l] + » » +
IntToStr(Year) + » года, » +
stDay[DayOfWeek(Today) -1] ;
Label2->Caption = «Сегодня и ближайшие дни»;,
// вычислим следующий день
// если сегодня пятница, то, чтобы не забыть,
// что запланировано на понедельник, считаем, что следующий
// день — понедельник
switch ( DayOfWeek(Today)) {.
case 6 : NextDay = Today + 3; break; // сегодня пятница
case 7 : NextDay = Today + 2; break; // сегодня суббота
default : NextDay = Today + 1; break;
}
// запрос к базе данных; есть ли дела, запланированные
// на сегодня и на следующий день
Queryl->SQL->Strings[3] =
«(Date_F >= ‘»+ FormatDateTime(«dd/mm/yyyy»,Today)+»‘) AND » +
«(Date_F <= ‘»+ FormatDateTime(«dd/mm/yyyy»,NextDay)+»‘)»;
Queryl->0pen();
DataSourcel->DataSet = Forml->Queryl;
if ( ! Queryl->RecordCount)
(ShowMessage(«Ha сегодня и ближайшие дни никаких дел
не запланировано.»);
160 Часть II. Практикум программирования
Использование псевдонима для доступа к базе данных обеспечивает незави-симость программы от размещения данных в системе, позволяет размещатьпрограмму работы с данными и базу данных на разных дисках компьютера,в том числе и на сетевом. Вместе с тем для локальных баз данных типич-ным решением является размещение базы данных в отдельном подкаталогетого каталога, в котором находится программа работы с базой данных. Та-ким образом, программа работы с базой данных «знает», где находятся дан-ные. При таком подходе можно отказаться от создания псевдонима при по-мощи Database Desktop и возложить задачу создания псевдонима на про-грамму работы с базой данных. Очевидно, что такой подход облегчаетадминистрирование базы данных.
В качестве иллюстрации сказанного в листинге 5.4 приведен вариант реали-зации функции onActivate, которая создает псевдоним для базы данныхorganizer. Предполагается, что база данных находится в подкаталоге DATAтого каталога, в котором находится выполняемый файл программы. Непо-средственное создание псевдонима выполняет функция AddStandardAlias,которой в качестве параметра передается псевдоним и соответствующийему каталог. Так как во время разработки программы нельзя знать, в какомкаталоге будет размещена программа работы с базой данных и, следова-тельно, подкаталог базы данных, имя каталога определяется во вре-мя работы программы путем обращения к функциям paramstr(O) иExtractFiiePatch. Значение первой — полное имя выполняемого файла про-граммы, второй — путь к этому файлу. Таким образом, процедуреAddStandardAlias передается полное имя каталога базы данных.
Г • • • …. .;
I Листинг 5.4. Создание псевдонима во время работы программы
void fastcall TForml::FormActivate(TObject *Sender)
{
TDateTime Today, // сегодня
NextDay; // следующий день (не обязательно завтра)
Word Year, Month, Day; // год, месяц, день
Today = Now ();
DecodeDate(Today, Year, Month, Day);
Labell->Caption = «Сегодня » + IntToStr(Day) + » » +
stMonth[Month-l] + » » +
IntToStr(Year) + » гола, » +
stDay[DayOfWeek(Today) -1] ;
Глава 5. Базы данных 161
Label2->Caption = «Сегодня и ближайшие дни»;
// вычислим следующий день
// если сегодня пятница, то, чтобы не забыть,
// что запланировано на понедельник, считаем, что следующий
// день — понедельник
switch ( DayOfWeek(Today)) {
case 6 : NextDay = Today + 3; break; // сегодня пятница
case 7 : NextDay = Today + 2; break; // сегодня суббота
default : NextDay = Today + I; break;
1
tdefine DIN_ALIAS // псевдоним доступа к БД создается динамически
// если псевдоним создан при помощи Database Desktop
// или BDE Administrator, директиву #define DIN_ALIAS
// надо удалить («закомментировать»)
#ifdef DIN_ALIAS // псевдоним создается динамически
// создадим псевдоним для доступа к БД
Session->ConfigMode = cmSession;
Session->AddStandardAlias(«organizer»,
ExtractFilePath(ParamStr(0))+»DATA\\»,
«PARADOX»); // база данных «Ежедневник» —
// в формате Paradox
#endif
Forml->Tablel->Active = true; // открыть таблицу
// запрос к базе данных: есть ли дела, запланированные
// на сегодня и завтра
Queryl->SQL->Strings[3] =
«(Date_F >=•'»+ FormatDateTime(«dd/mm/yyyy»,Today)+»‘) AND » +
«(Date_F <= ‘»+ FormatDateTime(«dd/mm/yyyy»,NextDay)+»‘)»;
Queryl->0pen();
DataSourcel->DataSet = Forml->Queryl;
if ( ! Queryl->RecordCount)
{
ShowMessage(«На сегодня и ближайшие дни никаких дел
не запланировано.»);
бЗак. I252
162 Часть II. Практикум программирования
Перенос программы управлениябазой данных на другой компьютерЧасто возникает необходимость перенести базу данных на другой компью-тер. В отличие от процесса переноса обычной программы, когда, как прави-ло, достаточно скопировать только выполняемый файл (ехе-файл), при пе-реносе программы управления базой данных необходимо выполнить пере-нос BDE.
Здесь следует вспомнить, что BDE представляет собой совокупность про-грамм, библиотек и драйверов, обеспечивающих работу прикладной про-граммы с базой данных. Выполнить перенос BDE на другой компьютер»вручную» довольно трудно. Поэтому для переноса (распространения) про-граммы, работающей с базами данных, Borland рекомендует создать устано-вочную программу, которая выполнит копирование всех необходимых фай-лов, в том числе и компонентов BDE. В качестве средства создания устано-вочной программы Borland настоятельно советует использовать утилитуInstallShield Express, которая входит в состав всех наборов C++ Builder. По-ставляемая с C++ Builder версия этой утилиты специально адаптированак задаче переноса и настройки BDE.
ГЛАВА 6
Компонент программиста
C++ Builder позволяет программисту создать свой собственный компонент,поместить его на одну из вкладок палитры компонентов и использовать приразработке приложений точно так же, как и другие компоненты C++ Buil-der.
Наиболее просто создать компонент программиста можно на базе сущест-вующего (базового) компонента путем расширения или ограничения воз-можностей базового компонента. Например, компонент, обеспечивающийввод и редактирование числа, логично создать на основе компонента, обес-печивающего ввод строки символов.
Процесс создания компонента может быть представлен как последователь-ность следующих этапов:
1. Выбор базового класса.
2. Создание модуля компонента.
3. Тестирование компонента.
4. Добавление компонента в пакет компонентов.
Рассмотрим процесс создания компонента программиста на примере. Соз-дадим компонент NkEdit, который обеспечивает ввод и редактирование це-лого или дробного числа. Компонент также должен контролировать вводи-мое значение на принадлежность заданному диапазону. Тип числа и грани-цы диапазона должны задаваться во время разработки формы приложения,использующего компонент.
Выбор базового классаПриступая к разработке нового компонента, следует четко сформулироватьназначение компонента. Затем необходимо определить, какой из компонен-тов C++ Builder наиболее близок по своему назначению, виду и функцио-
164 Часть II. Практикум программирована
нальным возможностям к компоненту, который разрабатывается. Именн<этот компонент следует выбрать в качестве базового.
Создание модуля компонентаПеред началом работы по созданию нового компонента нужно создать от-дельный каталог для модуля и других файлов компонента. После этогоможно приступить к созданию компонента.
Чтобы начать работу над новым компонентом, надо активизировать процесссоздания нового приложения (команда File | New | Application), в менюComponent выбрать команду New Component и в поля диалогового окна NewComponent (рис. 6.1) ввести информацию о создаваемом компоненте.
mew Component
New Component I
Ancestor type: JTEdit [SldQrlsJ «3CJawName: (TNkEdii
falette Page: [Samples
JJnit lite name: (ОЛПроекты СВ\KoMnoHeHT\NkEdit.cpp
Search path: j$(BCB)\Lib;$(BCB)\Bin;$(BCB)Vlmports,$(BCBJ\
J
Install.. OK Cancel № l p j
Рис. 6.1. Начало работы над новым компонентом
В поле Ancestor type надо ввести базовый тип создаваемого компонента. Дляразрабатываемого компонента базовым компонентом является стандартныйкомпонент Edit (поле ввода-редактирования). Поэтому базовым типом раз-рабатываемого компонента является тип TEdit.
В поле Class Name необходимо ввести имя класса разрабатываемого компо-нента (например, TNkEdit). Вспомните, что в C++ Builder принято соглаше-ние, согласно которому имена типов должны начинаться буквой т.
В поле Palette Page нужно ввести имя вкладки палитры компонентов, накоторую будет помещен значок компонента. Название вкладки палитрыкомпонентов можно выбрать из раскрывающегося списка. Если в полеPalette Page ввести имя еще не существующей вкладки палитры компонен-тов, то непосредственно перед добавлением компонента вкладка с указан-ным именем будет создана.
В поле Unit file name находится автоматически сформированное имя файламодуля создаваемого компонента. C++ Builder присваивает модулю компо-
Глава 6. Компонент программиста 165
нента имя, которое совпадает с именем типа компонента, но без буквы т.Щелкнув на кнопке с тремя точками, можно выбрать каталог, в которомдолжен быть сохранен модуль компонента.
В результате щелчка на кнопке ОК будет сформирован модуль компонента,состоящий из двух файлов: файла заголовка (листинг 6.1) и файла реализа-ции (листинг 6.2).
1 Листинг 6.1. Файл NkEdit.h
ttifndef NkEditH
tfdefine NkEditH
#include <SysUtils.hpp>
#include <Classes.hpp>
ffinclude «Controls.hpp>
tinclude <StdCtrls.hpp>
class PACKAGE TNkEdit : public TEdit
{
private:
protected:
public:
fastcall TNkEdit(TComponent* Owner);
published:
};
tendif
i Листинг 6.2. Файл NkEdit.cpp
tinclude <vcl.h>
ttpragma hdrstop
Iinclude «NkEdit.h»
#pragma package(smart_init)
static inline void ValidCtrCheck(TNkEdit *)
I
new TNkEdit(NULL);
>
fastcall TNkEdit::TNkEdit(TComponent* Owner)
: TEdit(Owner)
166 _ Часть II. Практикум программированы
namespace NkEdit
{void _ fastcall PACKAGE Register ()
{
TComponentClass classes [1] = { _ classid(TNkEdit) } ;RegisterComponents («Samples», classes, 0} ;
В файле заголовка NkEdit.h находится объявление нового класса. В файлреализации NkEdit.cpp помещена функция Register, которая обеспечиваетрегистрацию, установку значка компонента на указанную вкладку палитрыкомпонентов.
В сформированный C++ Builder шаблон компонента нужно внести допол-нения: объявить поля данных, функции доступа к полям данных, свойства иметоды. Если на некоторые события компонент должен реагировать не так,как базовый, то в объявление класса нужно поместить объявления соответ-ствующих функций обработки событий.
В листингах 6.3 и 6.4 приведены файлы заголовка и реализации компонентаNkEdit после внесения всех необходимых изменений.
Г»»-‘»- ……….. :. ………….. • …… •-•••• …………………….. ‘. …………………….. • ………………………….. • ……………………………………….. • ……………… : ……………. • …………. ••• …… • …………. •
i Листинг 6,3. nkedit.h
#ifndef NkEditHfdefine NkEditH
linclude <SysUtils.hpp>#include «Classes. hpp>finclude <Controls . hpp>#include <StdCtrls.hpp>
class PACKAGE TNkEdit : public TEdit
{
private :
bool FEnableFloat; // разрешен ввод дробного числа
// диапазон
float FMin; // нижняя граница
float FMax; // верхняя граница
/* функция SetNumb используется для изменения содержимого
поля редактирования */
void _ fastcall SetNumb (float n) ;
/* Функция GetNumb используется для доступа к полю редактирования */
float fastcall GetNumb (void) ;
Глава 6. Компонент программиста 167
/* эти функции обеспечивают изменение границ диапазона
допустимых значений */
bool fastcall SetMin(float min);
bool fastcall SetMax(float max);
protected:
public:
fastcall TNkEdit(TComponent* Owner); // конструктор
/* Свойство Numb должно быть доступно только во время
работы программы. Поэтому оно объявлено в секции public.
Если надо, чтобы свойство было доступно во время разработки формы
и его значение можно было задать в окне Object Inspector, то
его объявление нужно поместить в секцию published
Vproperty float Numb = (read = GetNumb }; //, write = SetNumb);
// Функция обработки события KeyPress
DYNAMIC void fastcall KeyPress(char Skey);
published:
// объявленные здесь свойства доступны в Object Inspector
property bool EnableFloat = { read = FEnableFloat,
write =’FEnableFloat };
property float Min = {read = FMin,
write = SetMin };
property float Max = (read = FMax,
write = SetMax } ;
#endif
l Листинг 6.4. nkeditcpp
ttinclude <vcl.h>
#pragma hdrstop
linclude «NkEdit.h»
tpragma package(smart_init)
168 _ Часть II. Практикум программирования
static inline void ValidCtrCheck(TNkEdit *)
I
new TNkEdit (NULL) ;
// конструктор_ fastcall TNkEdit: : TNkEdit (TComponent* Owner)
: TEdit (Owner)
(
// конструктор имеет прямой доступ к полям компонента
Text = «О»;
FMin = 0;
FMax = 100;FEnableFloat = true;
namespace Nkedit
{
void _ fastcall PACKAGE Register ( )
{TComponentClass classes [1] = { _ classid (TNkEdit) } ;
4 RegisterComponents («Samples», classes, 0) ;
}
}
void _ fastcall TNkEdit: :SetNumb (float n)
{
Text = FloatToStr (n) ;
// возвращает значение, соответствующее строке,
// которая находится в поле редактирования
float _ fastcall TNkEdit : : GetNumb (void)
{•if ( Text. Length () )
return StrToFloat (Text) ;
else return 0;
// функция обработки события KeyPress в поле компонента NkEditvoid _ fastcall TNkEdit: : KeyPress (char &Key)
{
// Коды запрещенных клавиш заменим нулем, в результате чего
// эти символы в поле редактирования не появятсяswitch (Key) {
case ‘0’ :
Глава 6. Компонент программиста 169
case Ч’
case ‘2’
case ‘3’
case ‘4’
case ‘5’
case ‘б’
case ‘7’
case ‘8’
case ‘9’
case
break;
Key = DecimalSeparator;
if (Text.Pos(DecimalSeparator)
Key = 0;
break;
;! FEnableFloat);
case ‘-‘ : // знак «минус»
if (Text.Length()||(FMin >= 0))
// минус уже введен или fMin >= О
Key = 0;
break;
case VK_BACK: // клавиша <Backspace>
break;
default : // остальные символы запрещены
Key = 0;
if ((Key >=’0′) && (Key <= ‘9’)) {
/* Проверим, не приведет ли ввод очередной цифры
к выходу числа за границы диапазона. Если да,
то заменим введенное число на максимальное или минимальное*/
AnsiString st = Text + Key;
if (StrToFloat(st) < FMin) {
Key = 0;
Text = FloatToStr(FMin);
if (StrToFloat(st) > FMax) {
Key = 0;
Text = FloatToStr(FMax);
}
170 _ Часть II. Практикум программирования
// вызвать функцию обработки события KeyPress базового класса
TEdit: : KeyPress (Key) ;
// устанавливает значение поля FMin
bool _ fastcall TNkEdit: :SetMin (float min)
{
if (min > FMax) return false;.
FMin = min;
return true;
// устанавливает значение поля FMinbool _fastcall TNkEdit: : SetMax (float max){
if ( max < FMin) return false;
FMax = max;
return true;
В объявлении класса TNkEdit добавлены объявления полей FEnabiedFioat,FMin и FMax. Имена полей, согласно принятому в C++ Builder соглашению,начинаются с буквы F (от Field, поле). Поле FEnabiedFioat хранит признаквозможности ввода в поле редактирования дробного числа. Поля FMin иFMax хранят границы диапазона. Доступ к полям обеспечивают соответст-вующие свойства: EnabiedFioat, Min и мах. Так как объявления этих свойствнаходятся в секции published, то они будут доступны в окне ObjectInspector. Свойство Numb, представляющее собой число, которое находится вполе редактирования, объявлено в секции public, поэтому оно доступнотолько во время работы программы. Здесь следует обратить внимание на то,что у свойства Numb нет соответствующего поля. Значение этого свойствавычисляется во время работы программы путем преобразования в числозначения свойства Text базового компонента. Свойства Min и мах получаютдоступ к полям данных для чтения напрямую, для записи — посредствомфункций SetMin и SetMax. Свойство EnabiedFioat получает доступ к полюFEnabiedFioat для чтения и записи напрямую. Так как компонент NkEditдолжен обеспечить фильтрацию символов (в поле редактирования долж-ны отображаться только цифры и, в случае, если значение свойстваEnabiedFioat равно true, десятичный разделитель), то в объявление классадобавлено объявление функции KeyPress, которая предназначена для обра-ботки соответствующего события.
Реакцию компонента NkEdit на нажатие клавиши клавиатуры определяетфункция TNkEdit: : KeyPress. В качестве параметра эта функция получает код
Глава 6. Компонент программиста 171
нажатой клавиши. Перед вызовом функции TEdit: :KeyPress, котораяобеспечивает обработку события Keypress базовым компонентом, код нажа-той клавиши проверяется на допустимость. Если нажата недопустимая кла-виша, то код символа заменяется на ноль. Допустимыми для компонентаNkEdit, в зависимости от его настройки, являются цифровые клавиши, раз-делитель целой и дробной частей числа (в зависимости от настройки Win-dows, точка или запятая), «минус» и клавиша <Backspase>.
Здесь следует вспомнить, что в тексте программы дробная часть числовойконстанты отделяется от целой части точкой. Во время работы программыпри вводе исходных данных пользователь должен использовать тот символ,который задан в настройке Windows. В качестве разделителя обычно ис-пользуют запятую (стандартная для России настройка) или точку. Приве-денная процедура обработки события onKeypress учитывает, что настрой-ка Windows может меняться, и поэтому введенный пользователем символсравнивается не с константой, а со значением глобальной переменнойDecimaiseparator, которая содержит символ-разделитель, используемый вWindows в данный момент.
Тестирование компонентаПеред тем как добавить новый компонент в палитру компонентов, необхо-димо всесторонне его проверить. Для этого надо создать приложение, ис-пользующее компонент, и убедиться, что компонент работает так, как надо.
Во время создания формы приложения нельзя добавить в форму компо-нент, значка которого нет в палитре компонентов. Однако такой компонентможет быть добавлен в форму динамически, т. е. во время работы прило-жения.
Наиболее просто выполнить тестирование компонента можно следующимобразом. Сначала надо активизировать процесс создания нового приложе-ния, а затем создать форму (добавить и настроить необходимые компонен-ты) и сохранить приложение в том каталоге, в котором находятся файлытестируемого компонента.
Вид формы приложения тестирования компонента NkEdit приведен нарис. 6.2.
Форма содержит две метки. Первая метка обеспечивает вывод общей ин-формации о компоненте; вторая метка (на рисунке она выделена) использу-ется для вывода информации о настройке компонента. Самого компонентаNkEdit в форме нет. Он будет создан во время работы программы, в моментее запуска.
После того как форма тестового приложения будет создана, в модуль при-ложения надо внести дополнения, приведенные ниже.
172 Часть II. Практикум программирования
1. В текст файла реализации (срр-файл) включить следующую директивуfinclude «nkedit.cpp».
2. Объявить компонент NkEdit (оператор TNkEdit *NkEdit). Здесь следуетвспомнить, что компонент является объектом (точнее ссылкой на объ-ект), поэтому объявление компонента не обеспечивает создание компо-нента, а только создает указатель на компонент.
3. Для формы приложения создать процедуру обработки события OnCreate,которая путем вызова конструктора тестируемого компонента создасткомпонент и выполнит его настройку (присвоит значения свойствамкомпонента).
Labell •
LabeC —
У. Тест компонента NkEdit
— Компонент NkEdit предназначен для ввода чисел, поэтому в поле,’ компонента появляются только цифры и, в зависимости от• настройки компонента, десятичный разделитель и знак минус.
Рис. 6.2. Форма приложения «Тест компонента NkEdit»
В листинге 6.5 приведен файл реализации приложения тестирования ком-понента NkEdit.
I Листинг 6.5. Тест компонента
#include <vcl.h>
#pragma hdrstop
^include «tk_.h»
#include «nkedit . cpp»
#pragma package (smart_init)
#pragma resource «*.dfm»
TForml *Forml;
TNkEdit *NkEdit;
// форма
// компонент программиста
// конструктор формы
fastcall TForml::TForml(TComponent* Owner)
: TForm(Owner)
Глава 6. Компонент программиста 173
// создадим и инициализируем компонент NkEdit
NkEdit = new TNkEdit(Forml);
NkEdit->Parent = Forml;
NkEdit->Text = «0»;
NkEdit->Left = 10;
NkEdit->Top = 100;
// настроим компонент
// зададим границы диапазона
NkEdit->Min = -100;
NkEdit->Max = 100;
NkEdit->EnableFloat = true; // разрешен ввод дробных чисел
// обработка события FormCreate
void fastcall TForml::FormCreate(TObject *Sender)
AnsiString st = «Введите «;
// информация о компоненте
if (NkEdit->EnableFloat)
st = st + «дробное»;
else st = st ,+ «целое»;
st = st + » число от «;
st = st + FloatToStr(NkEdit->Min);
st = st + » до «;
st = st + FloatToStr(NkEdit->Max);
Label2->Caption = st;
‘•
Тест компонента NkEait
Компонент NkEdit предназначен для ввода чисел, поэтому в полекомпонента появляются только цифры и, в зависимости отнастройки компонента, десятичный разделитель и знак минус.
Введите дробное число от -100 до 100
Рис. 6.3. Тестирование компонента: попе ввода — компонент NkEdit
174 Часть II. Практикум программирована
Тестируемый компонент создает и настраивает конструктор формы. Следуетобратить внимание, что свойству Parent созданного компонента обязательнонадо присвоить значение. Если этого не сделать, то компонент на форме непоявится. Информацию о настройках созданного компонента выводитфункция FormCreate. На рис. 6.3 приведен вид окна программы «Тест ком-понента NkEdit» во время ее работы.
Установка компонентаДля того чтобы значок компонента появился в палитре компонентов, ком-понент должен быть добавлен в один из пакетов (Packages) компонентовC++ Builder. Пакет компонентов — это специальная библиотека (файл срасширением bpk). Например, для компонентов, созданных программистом,предназначен пакет dclusr.bpk.В процессе добавления компонента в пакет C++ Builder использует файлресурсов компонента, в котором должен находиться битовый образ значкакомпонента. Имя файла ресурсов компонента должно совпадать с именемфайла модуля компонента. Файл ресурсов имеет расширение dcr (DynamicComponent Resource). Битовый образ, находящийся внутри файла ресурсов,должен иметь имя, совпадающее с именем класса компонента.
Ресурсы компонентаФайл ресурсов компонента можно создать при помощи утилиты Image Editor,которую можно запустить из C++ Builder (команда Tools | Image Editor) илииз Windows (команда Пуск | Программы (C++ Builder | Image Editor).Для того чтобы создать файл ресурсов компонента, нужно из меню File вы-брать команду New и из появившегося списка выбрать тип создаваемогофайла — Component Resource File (рис. 6.4).В результате открывается окно файла ресурсов Untitledl.dcr, а в меню диа-логового окна Image Editor появляется новый пункт — Resource. Теперьнужно из меню Resourse выбрать команду New/Bitmap и в открывшемся ок-не Bitmap Properties (рис. 6.5) установить характеристики битового образазначка компонента: Size — 24×24 пиксела, Colors — 16.В результате этих действий в создаваемый файл ресурсов компонента будетдобавлен новый ресурс — битовый образ с именем Bitmap 1. Двойной щел-чок на имени ресурса (Bitmap!) раскрывает окно редактора битового образа,в котором можно нарисовать нужную картинку.Изображение в окне графического редактора можно увеличить. Для этогонеобходимо выбрать команду Zoom In меню View.Следует обратить внимание на то, что цвет правой нижней точки рисункаопределяет «прозрачный» цвет. Элементы значка компонента, закрашенныеэтим цветом, на палитре компонентов C++ Builder не видны.
Глава 6. Компонент программиста 175
Й0 Image Edit or
File Window Help :
Open.,, Ctrh-0
Resource File (,res)
Bitmap File (.brnp)
Icon File (,ico)
Cursor File (,qur)
(Create a new OCR file For use with custom VCL components
Рис. 6.4. Начало работы по созданию файла ресурсов компонента
Bitmap Properties
г Size
i Md(h [24
j Height Щ
• Colors —
С Monochrome (2 colors)
(? VGA (16 colors)
Г SuperVGA (256 colors)
Cancel
Рис. 6.5. Диалоговое окно Bitmap Properties
Перед тем как сохранить файл ресурсов компонента, битовому образу надоприсвоить имя. Имя должно совпадать с именем класса компонента. Чтобызадать имя битового образа, необходимо щелкнуть правой кнопкой мышина имени битового образа (Bitmapl), выбрать в появившемся контекстномменю команду Rename и ввести новое имя.
Созданный файл ресурсов компонента нужно сохранить в том каталоге,в котором находится файл модуля компонента. Для этого надо из меню Fileвыбрать команду Save.
На рис. 6.6 приведен вид окна Image Editor, в левой части которого содер-жится файл ресурсов компонента TNkEdit (nkedit.dcr), а в правой части -окно редактора битового образа, в котором находится изображение значкакомпонента. Обратите внимание, что имя файла ресурсов компонента(NkEdit.dcr) должно совпадать с именем модуля компонента (NkEdit.cpp), aимя битового образа (TNKEDIT) — с именем класса компонента (TNkEdit).
176 Часть II. Практикум программирования
и? Image EditorFife £dit Text View |itmap Window [Help
|lТ
• ••I ‘ M
•Г
ИШ1Б Contents
В Bitmap
•~ TNKEDIT
ГГИГШИ
til
.Id x|
.
IX: 020 Yi 000
Рис. 6.6. Значок компонента NkEdit
УстановкаПосле того как будет создан файл ресурсов компонента, можно приступитьк установке компонента в пакет компонентов. Компонент можно устано-вить в существующий пакет или создать новый пакет и затем установитьв него компонент.
Чтобы установить компонент в существующий пакет, надо из меню Compo-nent выбрать команду Install Component и заполнить поля вкладки Intoexisting package диалогового окна Install Component (рис. 6.1).
Install Component
Into existing package |
I УПЙ file name:
| Search path:
| gackage file name:
i Package Description:
|ДДДД х|
ito new package |
D : \\\ роекты CB \КомпонетЛЫКЕ dil. cpp Browse… 1
$(BC8)\Lib;$(BCB)\Bin;$(BCB)\lmports;$(BCB)\Ptojects\Bpl;$(BCB)\Ptojects j
C:\Pragram Rles\BorlandSCBuMer6\Lib\dclusr.t
Borland User Components
| OK
P^ Jll B|owse… I
Cancel Help
Рис. 6.7. Диалоговое окно Install Component
Глава 6. Компонент программиста 177
В поле Unit file name (Имя файла модуля) нужно ввести имя файла модуля.Для этого удобно воспользоваться кнопкой Browse.
Поле Search path (Путь поиска) должно содержать разделенные точкой сзапятой имена каталогов, в которых C++ Builder во время установки ком-понента будет искать необходимые файлы, в частности файл ресурсов ком-понента. Если имя файла модуля было введено в поле Unit file name выбо-ром файла из списка, полученного при помощи кнопки Browse, тоC++ Builder автоматически добавляет в поле Search path имена необходи-мых каталогов. Следует обратить внимание на то, что файл ресурсов компо-нента должен находиться в одном из каталогов, перечисленных в полеSearch path. Если его там нет, то компоненту будет назначен значок его ро-дительского класса.
Поле Package file name должно содержать имя пакета, в который будет уста-новлен компонент. По умолчанию компоненты, создаваемые программи-стом, добавляются в пакет dclusr.bpk.
Поле Package description содержит название пакета. Для пакета dclusr.bpkэто текст: Borland User Components.
После того как поля будут заполнены, надо щелчком на кнопке ОК активи-зировать процесс установки. Сначала на экране появляется окно Confirm(рис. 6.8), в котором C++ Builder просит подтвердить обновление пакета.
х]
Package dclusr.bpl will be rebuilt. Continue?
Ыо ttelp
Рис. 6.8. Запрос подтверждения обновления пакета в процессе установки компонента
После щелчка на кнопке Yes процесс установки продолжается. Если он за-вершается успешно, то на экране появляется информационное сообщение(рис. 6.9) о том, что пакет обновлен, а компонент зарегистрирован.
Information
г\ Package c’Aprogram fites\borland\cbullder6\Projects\Bpl\dclusr60.bpl has been installed,The following new component(s) have been registered: NkEdit.TNkEdit.
Рис. 6.9. Сообщение об успешной установке компонента
После установки компонента в пакет открывается диалоговое окно Package(Редактор пакета компонентов) (рис. 6.10), в котором перечислены компо-ненты, находящиеся в пакете.
178 Часть II. Практикум программирования
I Package — dtlusr.bpk
<&. . I 0Compile j Add
.J3*»__
[-: !’ ГДЯ
§ dclusr.cpp
dclusr.tesi-D NkEdilcpp-Ц NkEdildcr
Й-£Э RequiresК) rtl.bpi
:-‘J3l vcLbpi
UP J •<§•• ШRemove I !:’..• t.’ili Options
! Path j
cAprogtamfiles\borland\cbuilder6SLibc: \progtam f iles\borland\cbuilder6VJbОЛПроекты СВ\КомпонентОЛПроекты СВНКомпоненг
Рис. 6.10. Окно редактора пакета компонентов
На этом процесс установки компонента заканчивается. В результате навкладке палитры компонентов, имя которой было задано при создании модулякомпонента, появляется значок установленного компонента (рис. 6.11).
Рис. 6.11. Значок компонента NkEdit на вкладке Samples
Проверка компонентаПосле того как компонент будет добавлен в пакет и его значок появится впалитре компонентов, необходимо проверить поведение компонента вовремя разработки приложения, использующего этот компонент (работоспо-собность компонента была проверена раньше, когда компонент добавлялсяв форму приложения динамически, во время работы программы).
Можно считать, что компонент работает правильно, если во время разра-ботки приложения удалось поместить этот компонент в форму разрабаты-ваемого приложения и, используя окно Object Inspector, установить значе-ния свойств компонента, причем как новых, так и унаследованных от роди-тельского класса.
Работоспособность компонента NkEdit можно проверить, использовав его,например, в приложении «Сила тока», вид формы которого приведен нарис. 6.12.
Глава 6, Компонент программиста 179
Для ввода исходных данных программаиспользует компонент NkEdit ‘..’• ‘• ‘•
Введите напряжение и величину сопротивления,затем щелкните на КНОПКЕ Вычислить
Напряжение (вольт)’
Сопротивление (Ом);•;’ jo
Вычислить I’. Завершить
. NkEdit!
— NkEdit2
-LabeW
— Buttonl
Рис. 6.12. Форма приложения «Сила тока» (поля ввода-редактирования компоненты NkEdit)
Внешне форма разрабатываемого приложения почти ничем не отличается отформы приложения «Сила тока», рассмотренного в гл. 2. Однако если вы-брать поле ввода, то в окне Object Inspector будет указано, что текущимкомпонентом является компонент класса TNkEdit, а в списке свойств можнобудет увидеть свойства, которых нет у стандартного компонента Edit(рис. 6.13).
EnableFloat
Мах-
Min •
Properties j Events |
DiagMode
Enabled’ ‘
EnableFloat
iElFont
Height»»»
HelpContext
HelpKeywoid
HelpType
HideS election
Hint
ImeMode
ImeName
Left»
Max
MaxLength
Min
Name
OEMConvett
|A( shown
dmMenual
true
hue
ITFontj»
22 ‘
6 «
htContext
taue
impontCate
144
100
0
0 «»
NkEditt
false
Рис. 6.13. Значения свойств EnableFloat, Max и Min компонента NkEditможно задать в окне Object Inspector
В листинге 6.6 приведен модуль приложения «Сила тока». Здесь надо обра-тить внимание на следующее. Первое. В программе нет кода, обеспечиваю-
180 _ Часть II. Практикум программирования
щего фильтрацию символов, вводимых в поле редактирования. Тем не ме-нее во время работы программы пользователь может ввести в поле редакти-рования только положительное число. Второе. В программе не используетсяфункция strToFioat. Число, которое соответствует введенной в поле ре-дактирования строки символов, получается путем обращения к свойствуNumb.
Очевидно, что использование в программе компонента NkEdit вместо стан-дартного Edit освобождает программиста от рутины, сокращает размер кодаи делает его более понятным.
| Листинг 6.6. «Сила тока»
// нажатие клавиши в поле Напряжение
void _ fastcall TForml : :NkEditlKeyPress (TObject *Sender, char &Key)
{
if ( Key == VK_RETURN)
NkEdit2->SetFocus () ;
// нажатие клавиши в поле Сопротивление
void _ fastcall TForml : :NkEdit2KeyPress (TObj’ect *Sender, char SKey)
{
if ( Key == VK_RETURN)
Buttonl->SetFocus () ;
// нажатие кнопки Вычислить
void _ fastcall TForml: :ButtonlClick (TObject *Sender)
{
float u; // напряжение
float r; // сопротивление
float i; // ток
// получить исходные манные из полей ввода
u = NkEditl->Numb;
г = NkEdit2->Numb;
if ( г == 0) {
ShowMessage («Сопротивление не должно быть равно нулю»)
return;
// вычислить ток
i = u/r;
Глава 6. Компонент программиста 181
// вывести результат
Label4->Caption = «Ток : » +
FloatToStrF(i,ffGeneral,7,3) + «А»;
Настройка палитры компонентовC++ Builder позволяет менять порядок следования вкладок в палитре ком-понентов, названия вкладок, а также порядок следования значков компо-нентов на вкладках. Настройка палитры компонентов выполняется в диало-говом окне Palette Properties, которое открывается выбором из менюComponent команды Configure Palette (рис. 6.14).
Palette Properties
Palette |
Eases: Components:
SystemData AccessData ControlsdbExpressDataSnai
ADOnterBase
WebServicesInternetE xpressInternetWebSnapFastNetDecision CubeQ ReportDialogsWin 3.1SamplesActiveX
Name Package
dclbdeSO
sTuJI TStoredPmc dclbdeSO
fllTDatabase dclbdeEQ
y4^i Т Session dclbdeBO
™g|i TBatehMove dclbdeEO
Щ) TUpdateSQL dclbde60
Zl
Add… Delete Rename… Move Up Move Dgwn
Cancel Help
Рис. 6.14. Диалоговое окно Palette Properties
Сначала в списке Pages необходимо выделить нужную вкладку палитрыкомпонентов. Затем, если надо изменить порядок следования вкладокпалитры компонентов, следует воспользоваться кнопками Move Up иMove Down и путем перемещения выбранного имени по списку Pages до-биться нужного порядка следования вкладок.
Если надо изменить порядок следования значков компонентов на вкладке,то в списке Components следует выбрать нужный значок компонента икнопками Move Up и Move Down переместить значок на новое место.
182 Часть II, Практикум программирования
При необходимости изменить имя вкладки палитры следует в списке Pagesвыбрать имя нужной вкладки, нажать кнопку Rename и в поле Page nameоткрывшегося диалогового окна Rename page (рис. 6.15) ввести новое имя.
[Rename page Jll
| Раде name: (Примерь/
(Ж Cancel Help
Рис. 6.15. Диалоговое окно Rename page
ГЛАВА 7
Консольное приложение
Хотя эта книга посвящена программированию в Windows, нельзя обойтивниманием так называемые консольные приложения. Консольное приложе-ние — это приложение, которое для взаимодействия с пользователем не ис-пользует графический интерфейс. Устройством, обеспечивающим взаимо-действие с пользователем, является консоль — клавиатура и монитор, рабо-тающий в режиме отображения символьной информации (буквы, цифры испециальные знаки).
В операционной системе консольное приложение работает в окне команднойстроки.
Консольные приложения удобны как иллюстрации при рассмотрении об-щих вопросов программирования, когда надо сосредоточиться на сути про-блемы, а также как небольшие утилиты «для внутреннего потребления».
Ввод/выводПеред тем как приступить к созданию консольного приложения, рассмот-рим функции, обеспечивающие вывод на экран и ввод с клавиатуры.
Наиболее универсальными функциями, обеспечивающими вывод и вводИНфорМаЦИИ В КОНСОЛЬНЫХ ПрИЛОЖеНИЯХ, ЯВЛЯЮТСЯ ФУНКЦИИ printf И scanf.
Для того чтобы программа могла их использовать, в начало программы надоВКЛЮЧИТЬ директиву #include <stdio.h>.
Функция printfВ общем виде инструкция вызова функции printf выглядит так:
printf(УправляющаяСтрока, СписокПеременных)
184 Часть II. Практикум программирования
Параметр УправляющаяСтрока задает способ отображения (формат) значенийпеременных, имена которых задает параметр списокПеременных. Помимоспецификаторов формата, параметр УправляющаяСтрока может содержатьсимволы и управляющие последовательности.
Параметр списокПеременных не является обязательным и представляет собойпоследовательность разделенных запятыми имен переменных, значения ко-торых должны быть выведены.
Спецификатор формата задает вид вывода. Например, значение переменнойтипа float можно вывести как десятичное число с точкой (%f) или как чис-ло в формате с плавающей точкой (%е). В спецификаторе формата можнозадать размер поля вывода (количество позиций экрана), а для формата f -размер поля для вывода целой и дробной частей числа. Если во время рабо-ты программы окажется, что выводимое значение не умещается в поле, ука-занном в спецификации, то для его вывода будет использовано столько по-зиций, сколько необходимо.
В табл. 7.1 приведены наиболее часто используемые спецификаторы форма-та. Необязательный параметр п, вместо которого надо подставить десятич-ное число, задает размер поля вывода; параметр m — размер поля для выво-да цифр дробной части.
Таблица 7. 1. Спецификаторы формата
Спецификатор Тип переменной
%nd int
%n.mf float или double
%ne float или double
%nc char
%ns
Форма вывода
Десятичное со знаком
Дробное с десятичной точкой
Дробное в виде числа с плавающей
Символ
Строка
точкой
При выводе одной инструкцией значений нескольких переменных значениепервой переменной выводится в соответствии с первым по порядку специ-фикатором формата из управляющей строки, второй со вторым и т. д.
Следует обратить внимание на то, что компилятор не проверяет, соответст-вует ли количество переменных, значения которых должны быть выведены,количеству спецификаторов в управляющей строке, а также соответствиетипа переменной — спецификатору. Например, если переменная х объявле-на как float, то в инструкции printf («x=%i», x) компилятор не обнаружитошибку.
Глава 7. Консольное приложение 185
Если надо вывести символ, который не может быть помещен в строку вы-вода обычным образом путем набора на клавиатуре, — например, символновой строки или двойная кавычка, которая в языке C/C++ используетсядля ограничения в тексте программы строк, — то вместо этого символаприменяется специальная последовательность символов. Специальная(управляющая) последовательность начинается символом обратной наклон-ной черты. Во время работы программы символы специальной последова-тельности на экран не выводятся, а выполняется действие, обозначаемоеэтой последовательностью. В табл. 7.2 приведены наиболее часто исполь-зуемые управляющие последовательности.
Таблица 7.2. Управляющие последовательности
Последовательность Действие
\п Переводит курсор в начало следующей строки
\г Переводит курсор на следующую строку текущейколонки
\t Переводит курсор в следующую позицию табу-ляции
Выводит двойную кавычку
\\ Выводит обратную наклонную черту
\ОхШестнадцатеричноеЧисло Выводит символ, код которого указан
Для вывода на экран сообщений часто используют функцию puts, которая,в отличие от printf, после вывода автоматически переводит курсор в началоследующей строки. У функции puts один параметр — сообщение. В про-стейшем случае в качестве параметра функции puts используется строковаяконстанта. Например, функция
puts(«У лукоморья дуб зеленый,ХпЗлатая цепь.на дубе том.»)
выводит две строчки стихотворения, каждую на отдельной строке, и перево-дит курсор в начало следующей строки.
Чтобы вывести цветной текст, надо использовать функции cprintf и cputs.Они ничем не отличаются от рассмотренных ранее printf и puts, за исклю-чением того, что цвет символов, выводимых этими функциями, можно за-дать, ВЫЗВав функцию textcolor, а цвет фона — textbackground.
В общем виде инструкции вызова указанных выше функций выглядят так:
textcolor(Цвет);textbackground(Цвет);
Параметр цвет — параметр целого типа, в качестве которого обычно ис-пользуют одну из именованных констант (табл. 7.3).
186 Часть II. Практикум программирование
Цвет
Черный
Синий
Зеленый
Бирюзовый
Красный
Сиреневый
Коричневый
Светло-серый
Серый
Голубой
Светло-зеленый
Светло-бирюзовый
Алый
Светло-сиреневый
Желтый
Белый (яркий)
Таблица 7.3.
Константа
BLACK
BLUE
GREEN
CYAN
RED
MAGENTA
BROWN
LIGHTGRAY
DARKGRAY
LIGHTBLUE
LIGHTGREEN
LIGHTCYAN
LIGHTRED
LIGHTMAGENTA
YELLOW
WHITE
Константы, в качестве параметра Цвет
Значение константы
0
11
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Следует обратить внимание на то, что в качестве параметра функцииtextcoior можно использовать символьные константы со значением от Одо 15, а в качестве параметра функции textbackground — только от 0 до 7.
При выводе на экран весьма полезна функция cirscr, которая очищает эк-ран, закрашивая его цветом фона, установленным функцией textbackground.
Функции textcoior, textbackground, cirscr и приведенные выше константыобъявлены в файле conio.h, поэтому, чтобы они были доступны, в текстПрограммы НУЖНО ВКЛЮЧИТЬ директиву ttinclude <conio.h>.
Функция scantНаиболее универсальной функцией, которая позволяет ввести данные склавиатуры, является функция scanf. В общем виде инструкция вызовафункции scanf для ввода значения одной переменной выглядит так:
scanf(Формат, & Переменная);
Глава 7. Консольное приложение 187
где:
П Формат — это строка, которая содержит спецификатор формата, опреде-ляющий то, как должна интерпретироваться строка, введенная склавиатуры. Наиболее часто используемыми спецификаторами являются:%i — для ввода целых, %f — для ввода дробных, %s — для ввода строк;
П ^Переменная — это адрес переменной, значение которой вводится.
Например, инструкция
scanf(«%i», skol);
вводит целое число, а инструкция
scanf(«%i%f», &kol, Scena);
вводит целое и дробное.
При вызове функции scanf происходит следующее. Программа приостанав-ливает работу и ждет, пока пользователь наберет на клавиатуре строку сим-волов и нажмет клавишу <Enter>. До нажатия <Enter> можно редактироватьвводимую строку (например, нажав клавишу <Back Space> можно удалитьпоследний введенный символ). После нажатия клавиши <Enter> функцияscanf преобразует введенную строку в данные и записывает их в перемен-ную, адрес которой указан. Преобразование выполняется в соответствии соспецификатором формата. Например, в результате выполнения инструкцииscanf («%f», scena) и набора на клавиатуре строки 25.99 значение перемен-ной сепа будет равно 25.99.
Следует обратить внимание, что при использовании функции scanf наибо-лее частой ошибкой, причем не обнаруживаемой компилятором, являетсяотсутствие символа & перед именем переменной.
Если введенная пользователем строка не соответствует типу ожидаемыхданных — например, программа ждет ввода целого числа, а пользовательввел дробное, — то функция scanf обрабатывает только ту часть введеннойстроки, которая может быть преобразована в требуемые данные. Например,в программе для ввода данных о стоимости покупки используется инструк-ция scanf ( «%i%£» , skol, &cena), которая предполагает, что пользовательвведет в одной строке сначала количество предметов, а затем цену предмета.Если во время работы программы вместо строки 3 24.99 (три предмета по24.99) ввести строку 24.99 3, то значение переменной koi будет равно 24,а переменной сепа — 99.
i
Создание консольного приложенияКонсольное приложение создается следующим образом. Сначала нужно изменю File выбрать команду New | Other Application и на вкладке New по-явившегося диалогового окна New Items щелкнуть на значке Console Wizard
188 Часть II. Практикум программирования
(рис. 7.1). В результате этих действий на экране появится окно ConsoleWizard (рис. 7.2). В этом окне можно выбрать язык программирования иуказать, будет ли использоваться та или иная библиотека. После того какбудут заданы параметры создаваемого консольного приложения, надощелкнуть на кнопке ОК. В результате C++ Builder создаст проект консоль-ного приложения и на экране появится окно редактора кода, в котором на-ходится шаблон консольного приложения — функция main (рис. 7.3).
ConsolsWizard «
-*!
Data Modules j Business J Wefa Documents j WebSnap j WebServices
New j ActiveX | Multitier j Projectl j Forms j Dialogs (Projects
Application Batch File С File CLX ComponentApplication
f=biC++
Console Control Panel Control Panel CppFile Data ModuleWizard Application Module
DLL Wizard Form Frame Header File Library
Г Сам Г Iriheril Г Use
OK Cancel Help
Рис. 7.1. Чтобы приступить к созданию консольного приложения,надо щелкнуть на значке Console Wizard
Console Wizard
г Source Type ~
г Г» Specify project source
Г UseVCL
Г Use CLX
Г Mulli Threaded
\У Console Application
J<J
‘ЛOK Cancel Help
Рис. 7.2. В окне Console Wizard надо задать характеристики консольного приложение
Начинается консольное приложение директивой #pragma heirs top, котораязапрещает выполнение предварительной компиляции подключаемых фай-
Глава 7. Консольное приложение 189
лов. После этой директивы надо вставить директивы tinciude, обеспечи-вающие подключение необходимых библиотек (например, ^include<stdio.h>). Директива #pragma argsused отключает предупреждение компиля-тора о том, что аргументы, указанные в заголовке функции, не используются.
В Unitl.cpp
-yji) Ptoject2 • ClassesUnitl.cpp
^_.
иа hdtrstop
i#pcagma argsusediint roain(int argc, char* argv[] )
<return 0;
iLJ1: 1 Codified Insert «f\Code/»
Jj»
Рис. 7.З. Шаблон консольного приложения
Следует обратить внимание на то, что консольное приложение разрабатыва-ется в Windows, а выполняется как программа DOS. В DOS и Windows бук-вы русского алфавита имеют разные коды (в DOS используется кодировкаASCII, а в Windows — ANSI). Это приводит к тому, что консольное прило-жение вместо сообщений на русском языке выводит «абракадабру».
Проблему вывода сообщений на русском языке консольными приложения-ми можно решить, разработав функцию перекодировки ANSI-строки встроку ASCII. Если эту функцию назвать rus, то инструкция вывода сооб-щения может выглядеть, например, так:
printf( rus(«Скорость: %3.2f км/час»), v) ;
В качестве примера консольного приложения в листинге 7.1 приведена про-грамма «Угадай число», которая для вывода сообщений использует функциюRUS. Значение функции rus — строка символов в кодировке ASCII, соответ-ствующая строке, полученной в качестве параметра.
190 _ Часть II. Практикум программирования
I Листинг 7.1. Пример консольного приложения
#pragma hdrstop
#include <stdio.h>
# include <conio.h> // для доступа к getchf)
#include <stdlib.h> // для доступа к srand(), rand()
^include <time.h> // для доступа к time_t и time()
char* rus (char* st) ; // преобразует ANSI-строку в строку ASCII
#pragma argsused
iint main(int argc, char* argv[])
{
int comp, // число, «задуманное» компьютером
igrok, // вариант игрока
n=0; // число попыток
// ГСЧ — генератор случайных чисел
time_t t; // текущее время (для инициализации ГСЧ)
srand( (unsigned) time (&t) ) ; // инициализация ГСЧ
comp = rand () % 10 + 1;
puts ( rus ( » ХпКомпьютер \»задумал\» число от 1 до 10.»));
puts ( rus ( «Вы должны его угадать за три попытки .»));
do
{
printf («->»);
scanf(«%i», Sigrok) ;
while ( igrok != comp && n < 3) ;
if (igrok == comp)
printf ( rus ( «ВЫ ВЫИГРАЛИ ! » ) ) ;
else {
puts ( rus ( «Вы проиграли . » ) ) ;
printf ( rus ( «Компьютер \»задумал\» число %d») , comp) ;
}
printf ( гиз(«\пДля завершения нажмите любую клавишу. . . » ) ) ;
getchO;
return 0;
Глава 7. Консольное приложение _ 191
/* Функция rus преобразует ANSI -строку в строку ASCIIи может использоваться для вывода сообщенийна русском языке в консольных программах.
Пример использования:printff rus («Скорость: %3.2f км/час»), v) ;
print f ( rus («У лукоморья дуб зеленый \ п «) ) ;V
char* rus (char* st)
{unsigned char* p = st;
/* при объявлении символов как char русские буквыкодируются отрицательными числами */
while ( *р)
{if (*p >= 192) // здесь русская буква
if (*р <= 239) // А, Б, … Я, а, б, … п
*р -=64;
else // p … я
*р -= 16;
Р++;
}
return st;
Компиляция консольного приложения выполняется обычным образом, т. е.выбором из меню Project команды Compile.
После успешной компиляции программа может быть запущена выбором изменю Run команды Run. При запуске консольного приложения на экранепоявляется стандартное окно командной строки. На рис. 7.4 приведен видокна командной строки, в котором работает консольное приложение, соз-данное в C++ Builder.
Процесс сохранения проекта консольного приложения стандартный. В ре-зультате выбора из меню File команды Save Project на экране сначала появ-ляется окно Save Project, в котором нужно ввести имя проекта, а затем -окно Save Utit, в котором надо задать имя модуля.
Получить доступ к модулю консольного приложения (тексту программы)для того, чтобы внести изменения в программу, несколько сложнее. Снача-ла, выбрав в меню File команду Open Project, нужно открыть файл проекта.Затем надо открыть окно Project Manager (команда View | Project Manager),
192 Часть II. Практикум программирования
раскрыть список файлов, выбрать срр-файл и из контекстного меню вы-брать команду Open (или сделать двойной щелчок на имени срр-файла)(рис. 7.5).
: О:\Мроек ты СВ\Консольное приложениеХдзте.ене
Компьютер «задумал» число от 1 до 10.Зы должны его угадать за три попытки.
Зы проиграли.<омпыотер «задумал» число 1]ля завершения нажмите любу» клавишу.
Рис. 7.4. Окно командной строки, в котором работает консольное приложение
[Project Manager
lgame.exeNew Remove
Files Path
В-(Щ1 ProjeclGroupl31(fp game.exe
game, resgame.bpl
С: \Program Files\Bo(landSCBuildeiS\PcojectsОАПроекты СВ\Консольное приложениеОДПроекты СВ^Консольное приложениеОДПроекты СВ\Консольное приложениеОДПроекты СВ\Консольное приложение
Preprocess
Remove From ProjectSave
Save As…
Compile
Edit Local Options,..
V Toolbar
Status Bar
Stay on TopV Dockable
Рис. 7.5. Чтобы внести изменения в программу, надо в окне Project Managerвыбрать срр-файл и из контекстного меню выбрать команду Open
ГЛАВА 8
Справочная система
Каждая программа должна обеспечивать пользователя справочной инфор-мацией. Существует два способа отображения справочной информации:классический (рис. 8.1, левый) и современный, в «интернет-стиле» (рис. 8.1,правый). Классический способ отображения справочной информации при-меняется большинством приложений, в том числе и C++ Builder. Отобра-жение справочной информации в интернет-стиле используется в программ-ных продуктах Microsoft и, в последнее время, в продуктах других разработ-чиков программного обеспечения.
Классическая справочная система представляет собой набор файлов, ис-пользуя которые программа Winhelp, являющаяся составной частью Win-dows, выводит справочную информацию. Основой такой справочной систе-мы являются hip-файлы.
Основой современной справочной системы являются chm-файлы. Chm-файлпредставляет собой компилированный HTML-документ, полученный путемкомпиляции (объединения) файлов, составляющих HTML-документ, в томчисле и файлов иллюстраций.
Создать hip-файл можно при помощи утилиты Microsoft Help Workshop, ко-торая входит в комплект C++ Builder (файл утилиты hce.exe находится вкаталоге \CBuilder\Help\Tools). Chm-файл можно создать при помощи ути-литы Microsoft HTML Help Workshop, которая, к сожалению, в составC++ Builder не включена.
Рассмотрим процесс создания справочной системы, сначала классической, азатем — современной.
•
Создание справочной системыпри помощи Microsoft Help WorkshopПроцесс создания справочной системы состоит из двух этапов. На первомэтапе надо подготовить справочную информацию, на втором — преобразо-
7 Зак. 1252
194 Часть II. Практикум программирования
вать справочную информацию в справочную систему. Задача первого этапаможет быть решена при помощи редактора текста, второго — посредствомутилиты Microsoft Help Workshop.
Файл Дрзвк$ .Закладка Параметры
Сапер 2003Игра Сапер .2003 является аналогом игрыСапер, входящей в состав Microsoft Windows, v ‘.
ПравилаИгровое поле состоит из клеток, в каждой изкоторых может быть мина. Задача игрока-найти все мины и пометить их флажками.Используя кнопки мыши, игрок может открытьклетку или поставить в нее флажок, указавтем самым, что в клетке находится минаКлетка открывается щелчком левой кнопкимыши, флажок ставится щелчком правой.Если в клетке, которую открыл игрок, естьмина, то происходить взрыв (сапер ошибся, аон, как известно, ошибается только один раз), •.и игра заканчивается. Если в клетке мины ‘••„’•’нет. то в этой клетке появляется число,соответствующее количеству мин,находящихся в соседних клетках. Анализируяинформацию о количестве мин в клетках, vi
JDI.X
СкрытьО
Назад
£| Сапер 2003
щ ц^ЗПБЗit] Опрогра*лме
Правила
Игровое поле состоит из клеток, в каждой изкоторых может быть мина Задача игрока — найтивсе мины и пометить их флажками.
Используя кнопки мыши, игрок может открытьклетку или поставить е нее флажок, указав темсамым, что в кпетке находится мина. Клеткаоткрывается щелчком левой кнопки мыши,флажок ставится щелчком правой. Если в кпетке,которую открыл игрок, есть мина, то происходитьвзрыв (сапер ошибся, а он. как известно,ошибается только один раз), и игразаканчивается. Если а кпетке мины нет, то в этойкпетке появляется число, соответствующееколичеству мин. находящихся в соседних клетках.Анализируя информацию о количестве мин вклетках, соседних с уже открытыми, игрок может
Рис. 8.1. Два способа представления справочной информации:классический и современный
Подготовка справочной информацииИсходным материалом для Microsoft Help Workshop является справочнаяинформация, представленная в виде rtf-файла. Наиболее просто подготовитьrtf-файл справочной информации можно при помощи Microsoft Word.
Сначала нужно набрать текст разделов справки. Заголовки разделов нужнооформить одним из стилей Заголовок. Каждый раздел должен заканчиватьсясимволом «разрыв страницы».
После того как текст разделов будет набран, каждому разделу надо назна-чить идентификатор. Идентификатор назначается путем вставки перед заго-ловком раздела сноски #.
Для того чтобы назначить разделу идентификатор, нужно установить курсорперед первой буквой заголовка раздела, затем в меню Вставка выбратькоманду Сноска, а появившемся диалоговом окне Сноски выбрать в группеНумерация положение другая, в поле редактирования ввести символ «#»(рис. 8.2).
В результате щелчка на кнопке ОК в документ будет вставлена сноска #, а внижней части окна документа откроется окно ввода текста сноски. В этомокне рядом со значком сноски надо ввести идентификатор раздела(рис. 8.3). Рекомендуется, чтобы идентификатор раздела состоял из префик-са юн_ и порядкового номера раздела, например, IDH_I, юн_2 и т. д.
Глава 8. Справочная система 195
Вставить сноску —
(• обычную Внизу страницы
£»» концевую В конце документа
Нумерация —
С* автоматическая 1, Zt Э, ..:
<*» другая; |*
Си_мвол… 1
ОК Отмена j Параметры,,. |
Рис. 8.2. Чтобы задать идентификатор раздела,надо перед заголовком раздела вставить сноску #
Сноска, —помечаетзаголовокраздела
| sapei — Miciosoft Void
айл Древка Цид Вставка Формат CSPBMC £абяииа Цкно Справка
с* «в rf: ей 9 : ; -v. ie <? «:*>*’ ; • • «,ш ‘s ‘s New Ro -10 . ‘ Q Cw« Ж К Н «» \\f *
Текст сноски —идентификаторраздела
-*Сапер-20(ЩИгра Сапер 2003ЮН_3 является-аналогом игры Сапер, входящей в состав MicrosoftWindows.^IIПравила!Игровое- поле состоит из клеток, в каждой из которых может быть мина. Задача игрока -найти все мины и пометить их флажками.^Используя кнопки мыши, игрок-может-открыть клетку или поставить в-нее-флажок, указав темсамым, что-в-клетке находится-мина,-Клетка открывэется-щелчком левой кнопки мыши,-флажок ставится щелчком правой. Если в клетке, которую открыл игрок, есть мина,-то-происходить-взрыв (сапер ошибся,-а-он.-как известно,-ошибается только один-раз),-и игра-заканчивается -Если-в клетке мины-нет,-то-в-этой клетке паявляется-число. соответствующее-количеству мин, находящихся-в-соседних-клеткэх. Анализируя информацию о-количестве-мин в клетках,.соседних с уже открытыми, игрок может обнаружить, пометить флажками, все
1
Сноски-Все сноски
?ШН *
‘, Закрыть]
m1/2 :аНГЛИЙСКИЙ
Рис. 8.3. Вставка в документ сноски, помечающей заголовок раздела справки
Обычно в тексте справочной информации есть ссылки, которые обеспечи-вают переход к другому разделу, связанному с тем, который в данный мо-мент видит пользователь.
Во время подготовки текста справочной информации слово-ссылку следуетподчеркнуть двойной линией и сразу за этим словом, без пробела, помес-тить идентификатор раздела справки, к которому должен быть выполнен
196 Часть II. Практикум программирования
переход в результате выбора ссылки. Вставленный идентификатор необхо-димо оформить как скрытый текст. Чтобы задать двойное подчеркивание,нужно выделить слово-ссылку, выбрать команду Формат | Шрифт и в по-явившемся окне выбрать способ подчеркивания. Аналогичным образом надозадать «скрытый текст» для идентификатора. В качестве примера на рис. 8.4приведен вид окна редактора текста во время подготовки файла справочнойинформации для программы «Сапер 2003». Название игры помечено какссылка на другой раздел справки, который имеет идентификатор юн_з.
м saper — Microsoft Word
! Файл Правка Вив Вставка Фор]мат Сервис Хайаица Окно Справка
. Н , <3 В. V •’• ;.Times New Roman
«Я :0 + И Couier Ж Л 2
Ссылка на —другой раздел
*Сапер-2003Ц1
налогом и гры- Сапер, входящей в- состав Microsoft-Windows ,Ц1!»Правила^Игровое-поле состоит из клеток,-в каждой из которых-может быть мина.-Задача-игрока -•найти все-мины-и-пометить-их-флажками.Т]Используя кнопки мыши, игрок может-открыть клетку или поставить в нее флажок, указав темсамым,-что в клетке-находится-мина -Клетка-открывается-щелчком-левой-кнопки мыши,-флажок ставится щелчком правой. Если в клетке, которую открыл игрок, есть мина.-то-происходить -взрыв-(сапер ошибся, а он. как известно, ошибается-только один раз), и игра-заканчивается.-Если-в клетке-мины-нет,-то в этой-клетке-появляется-число,-соответствующее- JLколичеству-мин, находящихся-в соседних клетках.-Анзлизируя информацию о количестве-мин в клетках.-соседних с уже открытыми, игрок может обнаружить, пометить флажками, все Д
СноскиШсе сноски
«IDH 1Ц*ЮН~2Ц*шн_зц
4-1.Стр- 1 Разд 1 1/2 ;на з,4сп Ст 4 Кол 1
Рис. 8.4. Оформление ссылки на другой раздел
Помимо ссылки, обеспечивающей переход к другому разделу справки, в до-кумент можно вставить ссылку на комментарий — текст, который появляет-ся во всплывающем окне. Во время работы справочной системы ссылки накомментарии выделяются цветом и подчеркиваются пунктирной линией.При подготовке документа справочной системы комментарии, как и разде-лы справки, располагают на отдельной странице, однако текст комментарияне должен иметь заголовка. Сноска # должна быть поставлена перед тек-стом комментария. Ссылка на комментарий оформляется следующим обра-зом: сначала надо подчеркнуть одинарной линией слово, выбор которогодолжен вызвать появление комментария, затем сразу после этого словавставить идентификатор комментария, оформив его как скрытый текст.
Глава 8. Справочная система 197
Следует отметить, что справочная информация может быть распределена понескольким файлам.
Проект справочной системыПреобразование файла справочной информации в файл справочной систе-мы выполняет входящий в состав Microsoft Help Workshop компилятор. Ис-ходными данными для компилятора является справочная информация,представленная в виде rtf-файлов, и файл проекта справочной системы.
Для того чтобы преобразовать справочную информацию, подготовленную вредакторе текста, в справочную систему, сначала надо создать файл проектасправочной системы. Для этого нужно запустить Microsoft Help Workshop ив меню File выбрать команду New | Help Project (рис. 8.5). На экране по-явится диалоговое окно Project File Name. В этом окне (рис. 8.6) надо от-крыть папку, в которой находится файл справочной информации (rtf-файл),задать имя проекта и щелкнуть на кнопке Сохранить. В результате этих дей-ствий будет создан файл проекта (hpj-файл) и станет доступным окно про-екта справочной системы (рис. 8.7).
?, Microsoft HeteWoiks*
МмШ-УжШ
Ready :
Рис. 8.5. Начало работы над новым проектом
Первое, что надо сделать, — это добавить в проект rtf-файл, в котором на-ходится справочная информация. Для этого нужно сначала щелкнуть накнопке Files, затем в открывшемся окне Topic Files — на кнопке Add (рис. 8.8).
198 Часть II. Практикум программирована
На экране появится стандартное диалоговое окно Открытие файла, используя которое можно выбрать нужный rtf-файл. Если справочная информацираспределена по нескольким файлам, то операцию добавления файла нуж»повторить.
I Project File Name no!Папка: | £j/ sapei
ffjsapet
Имя Файла; |sapei|
Хип Файла: |
~Bfr» Ш’О-.Щ’.
Сохранить i_ __ : . ,
•»• | Отмена |
— . ; ,„ ; ‘ «l;»»:»‘»
Рис. 8.6. В поле Имя файла надо ввести название проекта
Help File: jsaper-hlp
[OPTIONS]LCID=Ox419 0x0 0x0 ; РусскийREPORT=Yes
ipfons.
FJes…
WJodows…
fiitmaps…
Map…
£onfig…
uata Files…
£ave and CompJe
Рис. 8.7. Окно проекта справочной системы
После того как все нужные файлы будут выбраны, надо в окне Topic Filesщелкнуть на кнопке ОК. В результате этих действий вновь станет доступ-ным окно проекта, в разделе [FILES] которого будут перечислены файлы,в которых находится справочная информация.
Следующее, что надо сделать, — это назначить числовые значения иденти-фикаторам разделов справочной информации. Для этого в окне проекта на-до сначала щелкнуть на кнопке Map, затем, в открывшемся окне Map, — на
Глава 8. Справочная система 199
кнопке Add (рис. 8.8). На экране появится окно Add Map Entry (рис. 8.9).В поле Topic ID этого окна надо ввести идентификатор раздела справки(идентификаторы были назначены разделам во время создания rtf-файла),в поле Mapped numeric value — число, идентифицирующее раздел. В полеComment можно ввести комментарий — название раздела справки. Послетого как будут, назначены числовые значения идентификаторам разделовсправки, окно Map можно закрыть.
Topic Files
Ippicffes
Add..
Include,..
folders…
f/ Accept revision maiks in topic fiies
Г™ Topic files use a double-byte character set
OK. Cancel
Рис. 8.8. Чтобы добавить в проект rtf-файл, щелкните на кнопке Add
Add Map Fnliy
Topic ID:
[1DHJ
Mapped numeric value:
:Comment
[Общая информация
Cancel
Рис. 8.9. Назначение идентификатору раздела числового значения
Последнее, что надо сделать, — это настроить вид окна справочной инфор-мации. Для этого надо в окне проекта щелкнуть на кнопке Windows, в полеCreate a window named открывшегося окна Create a window (рис. 8.10) ввестислово main и щелкнуть на кнопке ОК.
200 Часть II. Практикум программирована
•1 Deals <i window л ЯвНИаВ
Before you can modify windowproperties, you must cieate at leastone window.
Create a window named:
main
Based on this standard window:
Procedure _^j
OK Cancel j
General ] Position j Buttons) Color (Macros)
Wjndow type: j main j J
J,
Include..
Jjtle bar text: jCanep)
Comment; f
; Window attributes ~
; Г~ I- •• ‘f Г» Maximize window
OK Отмена
Рис. 8.10. Диалоговое окноCreate a window
Рис. 8.11. В поле Title bar text надо ввестизаголовок окна справочной системы
На экране появится окно Window Properties, в поле Title bar text вкладкиGeneral которого нужно ввести заголовок главного окна создаваемой спра-вочной системы (рис. 8.11).
Help He: [saper.hlp
(OPTIONS]LCID=Ox41 Э 0x0 0x0 ; РусскийREPORT*Yes
[FILES]saper.rtf
[MAP]ЮН 1=1IDH 2=2IDH_3=3
[WINDOWS]
; Общая информация; Правила; 0 программе
flptbns.^
Fjles…
Windows…
Bitmaps…
Map-
Alias…
£onfig..
fiala Files…
S.ave and Compile
Рис. 8.12. Работа над проектом простой справочной системы завершена;можно выполнить компиляцию
На этом процесс создания проекта простой справочной системы можносчитать завершенным (рис. 8.12). Теперь можно выполнить компиляцию.Для этого надо в меню File выбрать команду Compile, в появившемся диало-говом окне Compile a Help File установить флажок Automatically display Helpfile in WinHelp when done (Автоматически показывать созданную справочную
Глава 8. Справочная система 201
систему по завершении компиляции) и щелкнуть на кнопке Compile(рис. 8.13).
Compile a Help File
Project file:
|d:\npoeKTbicb\saper\SAPER.HPJ
F? fdiriimize window while compiling
Browse
2Ш
J
P» jjj&utonv -hen done]
Temporary settings (fot testing only)
Г» IWD off compression (reduces compile time]
17 Include .rtf fier>ame and topic Ю in Help file
Compile I Cancel
Рис. 8.13. Чтобы выполнить компиляцию, надо щелкнуть на кнопке Compile
По завершении компиляции на экране появится окно с информационнымсообщением о результатах компиляции и, если компиляция выполнена ус-пешно, окно созданной справочной системы. Файл справочной системы(HLP-файл) компилятор поместит в ту папку, в которой находится файлпроекта.
Вывод справочной информации
Обычно окно справочной системы становится доступным в результате на-жатия клавиши <F1> или выбора в меню Справка команды ?.
Для того чтобы во время работы программы пользователь, нажав клавишу<F1>, мог получить справочную информацию, надо чтобы свойствоHelpFile главного окна приложения содержало имя файла справочной сис-темы, а свойство HeipContext — числовой идентификатор нужного раздела(рис. 8.14).
Для каждого компонента формы можно задать свой раздел справки. Разделсправки, который появляется, если фокус находится на компоненте и поль-зователь нажимает клавишу <F1>, определяется значением свойстваHeipContext этого компонента. Если значение свойства Heipcontexr эле-мента управления равно нулю, то при нажатии клавиши <F1> появляетсятот раздел справки, который задан для формы приложения.
Для того чтобы справочная информация появилась на экране в результатевыбора в меню ? команды Справка, надо создать функцию обработки собы-тия Onclick для соответствующей команды меню. Процесс создания функ-ции обработки события для команды меню ничем не отличается от процес-са создания функции обработки события для элемента управления, напри-мер, для командной кнопки: в списке объектов надо выбрать объект типа
202 Часть II. Практикум программирования
Tmenuitem, для которого создается функция обработки события, а во вклад-ке Events — событие.
Properties j Events
ri3entWidth ‘ей:Sa’.»l’L» ;p
H Constraints
Cursor
nFace
ijTSizeConslraini
jtrue
i crDefault
DefaullMonitor i dnrActrveForm
DockSite
DragKind
DiagMode
Enabled
EIFont
FormStyl©
Height
HelpContext
| false
i dkDrag
IdmManual
i t f u e!(TFont)
‘fsNormal
1480
HelpFile isapei.hlplHelpKeyword ^
HelpType JhtContext
Hint
All shown
Рис. 8.14. Свойство HelpFile должно содержать имя файла справки,а свойство HelpContext — идентификатор раздела
Ниже приведена функция обработки события Onclick для команды Справкаменю ?.
// выбор в меню ? команды Справка
void _ fastcall TForml: :N3Click (TObject *Sender)
{
WinHelp(Forml->Handle, «saper.hlp»,HELP_CONTEXT, 1) ;
Вывод справочной информации выполняет функция winHeip, которой в ка-честве параметра передается идентификатор окна программы, котораязапрашивает вывод справочной информации, файл справки, константуHELP_CONTEXT и идентификатор раздела, содержимое которого должно бытьотражено.
HTML Help WorkshopПомимо стандартного, классического способа представления справочнойинформации, в современных программах все чаще используется представ-ление информации в интернет-стиле (рис. 8.15).
Глава 8. Справочная система 203
•ЗИ <>Скрыть Назад
ig Свпер 2003
iii шиш^]0 программе 1
]
•:’
m &Печать Параметры
*
Правила
Игровое поле состоит из клеток, в каждой изкоторых может быть мина. Задача игрока — найтивсе мины и пометить их флажками.
Используя кнопки мыши, игрок может открытьклетку или поставить в нее флажок, указав темсамым, что в клетке находится мина. Клеткаоткрывается щелчком левой кнопки мыши,флажок ставится щелчком правой. Если в клетке, -которую открыл игрок, есть мина, то происходитьвзрыв (сапер ошибся, а он, как известно,ошибается только один раз), и игразаканчивается. Если в клетке мины нет. то в этойклетке появляется число, соответствующееколичеству мин, находящихся в соседних клетках.Анализируя информацию о количестве мин вклетках, соседних с уже открытыми, игрок может ,
Рис. 8.15. Современный, в интернет-стиле способ отображения справочной информации
Основой современной справочной системы являются компилированныеHTML-документы — файлы с расширением chm. Chm-файл получается пу-тем компиляции (объединения) файлов, составляющих HTML-документ.
Отображение справочной информации обеспечивает операционная система.
Создать chm-файл можно при помощи утилиты Microsoft HTML Help Work-shop. Исходной информацией для компилятора справочной системы явля-ются файлы HTML, файлы иллюстраций и файл проекта.
Чтобы получить chm-файл, надо:
О подготовить справочную информацию в виде набора HTML-документов;
П создать файл проекта;
О создать файл контекста (содержания);
П выполнить компиляцию.
Последние три из перечисленных выше шагов выполняются в программеHTML Help Workshop.
Подготовка справочной информацииПодготовить справочную информацию в HTML-формате можно при помо-щи любого редактора текста. Наиболее быстро это можно сделать, еслиредактор позволяет сохранить набранный текст как HTML-документ. Можновоспользоваться и встроенным редактором Microsoft HTML Help Workshop,но для этого надо знать язык HTML (по крайней мере, его основы).
204 Часть II. Практикум программирования
В простейшем случае вся справочная информация может быть помещена водин HTML-файл. Однако если для навигации по справочной системепредполагается использовать вкладку Содержание (см. рис. 8.15), в которойбудут перечислены разделы справочной информации, то в этом случае ин-формацию каждого раздела нужно поместить в отдельный HTML-файл.
Использование Microsoft WordСначала нужно набрать текст разделов справки (каждый раздел в отдельномфайле). Заголовки разделов и подразделов надо оформить одним из стилейЗаголовок. Заголовки разделов, как правило, оформляют стилем Заголовок!,подразделов — стилем Заголовок 2.
Следующее, что надо сделать, — это вставить закладки в те точки докумен-та, в которые предполагаются переходы из других разделов справочной сис-темы. Чтобы вставить закладку, нужно установить курсор в точку текста, вкоторой должна быть закладка, из меню Вставка выбрать команду Закладкаи в поле Имя закладки диалогового окна Закладка ввести имя закладки(рис. 8.16).
1 ЗакладкаИмя закладки:
(сопрограмме
Сортировать по! <• имени
Г» Скрытые закладки
1 Добавить ] ‘••д.:»-.’.’- 1
3
f позиции
,,,,,, 1Отмена
Рис. 8.16. Добавление закладки
Имя закладки должно отражать суть предполагаемого перехода к закладке,содержимое помечаемого фрагмента текста. В имени закладки пробел ис-пользовать нельзя. Вместо пробела можно поставить символ подчеркивания.Заголовки, оформленные стилем Заголовок, помечать закладками не надо.Таким образом, если в создаваемой справочной системе предполагаютсяпереходы только к заголовкам разделов справочной информации, закладкиможно не вставлять.
После того как будут расставлены закладки, можно приступить к расстанов-ке ссылок. Различают ссылки, которые обеспечивают навигацию внутри
Глава 8. Справочная система 205
раздела, и те, которые обеспечивают переход к другому разделу справочнойсистемы.
Чтобы вставить ссылку, обеспечивающую навигацию внутри раздела, надовыделить фрагмент текста (слово или фразу), при выборе которого долженбыть выполнен переход, из меню Вставка выбрать команду Гиперссылка,в появившемся окне Добавление гиперссылки (рис. 8.17) сначала щелкнутьна кнопке Связать с местом в этом документе, затем — выбрать закладкуили заголовок, к которому должен быть выполнен переход.
Добавление гиперссыпки
Текст:
Выберите место в документе:.
Подсказка…
Начало документаВ Заголовки
; !-• Сапер 2003; ; Правила
О программе: Закладки
Отмена
Рис. 8.17. Выбор точки документа для перехода по ссылке
Если нужно вставить в документ ссылку на раздел справки, который нахо-дится в другом файле, то в диалоговом окне Добавление гиперссылки надощелкнуть на кнопке Файл и в появившемся стандартном окне выбрать имянужного HTML-файла.
После того как в документ будут помещены все необходимые гиперссылки,документ нужно сохранить в HTML-формате.
Использование HTML Help Workshop
Использование HTML-редактора, входящего в состав HTML Help Workshop,предполагает знание основ HTML — языка гипертекстовой разметки (далееприведены краткие сведения об HTML, которых достаточно для того, чтобысоздать вполне приличную справочную систему).
Чтобы создать HTML-файл, надо запустить HTML Help Workshop, из менюFile выбрать команду New | HTML File и в появившемся окне HTML Title
206 Часть II. Практикум программирования
(рис. 8.18) задать название раздела справки, текст которого будет находитьсяв создаваемом файле.
‘HTML и •
<!DOCTYPE HTML PUBLIC «-//IETF//DTD HTML//EN»><HTML><HEAD><meta name=»GENERATOR» content=»Microsoft8,regj HTML Help Workshop 4.1 «><TITLE>Untitled</TITLE>
<BODY>Enter the title for the HTML file:
</BODY></HTML>
(Правила)
Cancel
Рис. 8.18. Начало работы над новым HTML-файлом
После щелчка на кнопке ОК становится доступным окно HTML-редактора,в котором находится шаблон HTML-документа. В этим окне, сразу послестроки <BODY>, можно набирать текст.
Основы HTML
HTML-документ представляет собой текст, в который помимо обычноготекста включены специальные последовательности символов — теги. Тегначинается символом < и заканчивается символом >. Теги используютсяпрограммами отображения HTML-документов для форматирования текстав окне просмотра (сами теги не отображаются).
Большинство тегов парные. Например, пара тегов <Н2> </н2> сообщает про-грамме отображения HTML-документа, что текст, который находится междуэтими тегами, является заголовком второго уровня и должен быть отобра-жен соответствующим стилем.
В табл. 8.1 представлен минимальный набор тегов, используя которые мож-но подготовить HTML-файл с целью дальнейшего его преобразованияв chm-файл справочной системы.
Глава 8. Справочная система 207
Таблица 8.1. HTML-теги
Тег Пояснение
<TITLE> Название </TITLE>
<BODY BACKGROUND = «Файл»
ВСС01,(Ж=»Цвет»
ТЕХТ=»Цвег»>
<BASEFONT
SIZE=n>
<BR>
<А NAME=» За кладка «> </А>
<А
<IMG SRC=»Иллюстрация»>
Задает название HTML-документа. Програм-мы отображения HTML-документов, как пра-вило, выводят название документа в заголов-ке окна, в котором документ отображается.Если название не задано, то в заголовке окнабудет выведено название файла
Параметр BACKGROUND задает фоновый рису-нок, BGCOLOR — цвет фона, TEXT — цвет сим-волов HTML-документа
Задает основной шрифт, который использует-ся для отображения текста: FACE— названиешрифта, SIZE— размер в относительных еди-ницах. По умолчанию значение параметраSIZE равно 3. Размер шрифта заголовков (см.тег <н>) берется от размера, заданного пара-метром SIZE
Определяет текст, находящийся между тегами<Н1> и </Hl>, как заголовок уровня 1.Пара тегов <Н2> </H2> определяет заголовоквторого уровня, а пара <нз> </нз> — третьего
Конец строки. Текст, находящийся после это-го тега, будет выведен с начала новой строки
Текст, находящийся внутри этих тегов, явля-ется параграфом
Текст, находящийся внутри этой пары тегов,будет выделен полужирным
Текст, находящийся внутри этой пары тегов,будет выделен курсивом
Помечает фрагмент документа закладкой.Имя закладки задает параметр NAME. Это имяиспользуется для перехода к закладке
Выделяет фрагмент документа как гипер-ссылку, при выборе которой происходит пе-ремещение к закладке, имя которой указанов параметре HREF
Выводит иллюстрацию, имя файла которойуказано в параметре SRC
Комментарий. Текст, находящийся междудефисами, на экран не выводится
208 Часть II. Практикум программированы
Набирается HTML-текст обычным образом. Теги можно набирать как прописными, так и строчными буквами. Однако, для того чтобы лучше был;видна структура документа, рекомендуется записывать все теги строчным!(большими) буквами. Следующее, на что надо обратить внимание — это точто программы отображения HTML-документов игнорируют «лишние» про-белы и другие «невидимые» символы (табуляция, новая строка). Это значит,что для того чтобы фрагмент документа начинался с новой строки, в концепредыдущей строки надо поставить тег <вк>, а для того чтобы между стро-ками текста появилась пустая строка, в HTML-текст надо вставить два тега<BR> подряд.
Работая с HTML-редактором в программе HTML Help Workshop, уже впроцессе набора HTML-текста можно увидеть, как будет выглядеть наби-раемый текст. Для этого надо из меню View выбрать команду In Browser илищелкнуть на командной кнопке, на которой изображен стандартный значокInternet Explorer.
В качестве примера на рис. 8.19 приведен текст одного из разделов спра-вочной системы программы «Сапер 2003».
<HTML>
<Т1ТЬЕ>Правила</Т1ТЬЕ>
<BODY BGCOLOR=#FFFFFF BACKGROUND =»»>
<BASEFONT FACE=»Arial» SIZE=2>
<A ЫАМЕ=»Правила»><Н2>Правила</Н2х/А><Р>Игровое поле состоит из
клеток, в каждой из которых может быть мина. Задача игрока — найти все
мины и пометить их флажками.</Р> <Р>Используя кнопки мыши, игрок может
открыть клетку или поставить в нее флажок, указав тем самым, что в
клетке находится мина. Клетка открывается щелчком левой кнопки мыши,
флажок ставится щелчком правой. Если в клетке, которую открыл игрок,
есть мина, то происходить взрыв (сапер ошибся, а он, как известно,
ошибается только один раз), и игра заканчивается. Если в клетке мины
нет, то в этой клетке появляется число, соответствующее количеству мин,
находящихся в соседних клетках. Анализируя информацию о количестве мин
в клетках, соседних с уже открытыми, игрок может обнаружить, пометитьфлажками, все мины. Ограничений на количество клеток, помеченных
флажками, нет. Однако, для завершения игры (выигрыша) флажки должны
быть установлены только в тех клетках, в которых есть мины. Ошибочно
установленный флажок можно убрать, щелкнув правой кнопкой мыши
в клетке, в которой он находится.</Р>
<I>CM.</IXBR><А HREF=»saper_01.htm#Canep_2003″>Canep 2003</AXBR>
<А HREF=»saper_03.htm#0_nporpaMMe»>0 программе</А><ВК></BODY>
</HTML>
Рис. 8.19. HTML-текст раздела справочной системы
Глава 8. Справочная система 209
Создание файла справкиПосле того как справочная информация будет подготовлена, можно присту-пить к непосредственному созданию справочной системы.
Сначала надо запустить HTML Help Workshop, из меню File выбрать коман-ду New | Project и в окне New Project задать имя файла проекта создаваемойсправочной системы (рис. 8.20). После щелчка на кнопке Далее в этом иследующем окнах окно HTML Help Workshop должно выглядеть так, какпоказано на рис. 8.21.
New Project — Destination
Specify the name of your project file, and whereytiu would like it to be created.
ЮЛПроекты CB\Saper\saper.hhp
! Browse…
< Цазад Далее > Отмена
Рис. 8.20. Начало работы над новым проектом
Первое, что надо сделать,— это сформировать раздел [FILES], которыйдолжен содержать имена HTML-файлов, в которых находится справочнаяинформация. Чтобы добавить в раздел [FILES] имя файла, надо щелкнуть накнопке Add/Remove topic files (см. рис. 8.21), а затем в появившемся диало-говом окне Topic Files (рис. 8.22) — на кнопке Add, после чего в появив-шемся стандартном диалоговом окне Открыть выбрать HTML-файл разделасправки. Если справочная информация распределена по нескольким фай-лам, то операцию добавления нужно повторить несколько раз. После тогокак в диалоговом окне Topic Files будут перечислены все необходимые длясоздания справочной информации HTML-файлы, нужно щелкнуть накнопке ОК. В результате этих действий в файле проекта появится раздел[FILES], в котором будут перечислены HTML-файлы, используемые длясоздания справочной системы (рис. 8.23).
Следующее, что надо сделать, — это задать главный (стартовый) раздел изаголовок окна справочной системы. Заголовок и имя файла главного раз-дела вводятся соответственно в поля Title и Default file вкладки General диа-
210 Часть II. Практикум программирования
лотового окна Options (рис. 8.24), которое появляется в результате щелчкана кнопке Change project options (см. рис. 8.21).
Если для навигации по справочной системе предполагается использоватьвкладку Содержание, то надо создать файл контекста. Чтобы это сделать,нужно щелкнуть на вкладке Contents, подтвердить создание нового файла и
Change projectoptions
Add / Remove •topic files
«HTML Help Workshop
File View Test Tools Help
.JSJ.XJ
j Contents | Index j Help
1ы
[OPTIONS]Compatibility Л
Compiled file=sapei.chrn
Display compile piogress=No
Language=0x419 Русский
О^Проекты CB\Saper\saper.hhp
Рис. 8.21. Окно HTML Help Workshop в начале работы над новым проектом
Topic Files
Jopic files:
JJ.SJ
saper_01.htm ‘ Add… «»‘;!
Bemove
OK Cancel
Рис. 8.22. Диалоговое окно Topic Files
Глава 8. Справочная система 211
?HTML Help Workshop
File tfew lest To,ols Help
Project | Contents | Index | Help
*|
Г-?
[OPTIONS]Compatibly»!.1Compiled lile sapei.chmdisplay compile progress=No_anguage=0x41 9 Русский
sapef_01 .htmsaper_02.htmsaper_03.htm
0:\Проекты CB\Saper\saper,hhp
Рис. 8.23. В разделе [FILES] перечислены файлы, используемые для создания chm-файла
General | Files | CompikMJ Merge Files]
life Сапер 2003
uelaultfile: jsaper_01.htm
Defaultjaindow: j
Г Language of help f Je—гj • (Русский Qthet…
OK Отмена
Рис. 8.24. В диалоговом окне Options надо задать заголовок окна справочной системыи файл главного раздела
212 Часть II. Практикум программирования
Inserta heading
Inserta page
Edit J £Lselection
Рис. 8.25. Вкладка Contents
задать имя файла контекста, в качестве которого можно использовать имяпроекта. В результате станет доступной вкладка Contents (рис. 8.25), в кото-рую нужно ввести содержание — названия разделов справочной системы.
Содержание справочной системы принято изображать в виде иерархическо-го списка. Элементы верхнего уровня соответствуют разделам, а подчинен-ные им элементы — подразделам и темам.
Чтобы во вкладку Contents добавить элемент, соответствующий разделусправочной системы, нужно щелкнуть на кнопке Insert a heading, в полеEntry title появившегося диалогового окна Table of Contents Entry (рис. 8.26)ввести название раздела и щелкнуть на кнопке Add. На экране появится ок-но Path or URL (рис. 8.27). В поле HTML titles этого окна будут перечисле-ны названия разделов (заголовки HTML-файлов) справочной информации,которая находится во включенных в проект файлах (имена этих файлов ука-заны в разделе [FILES] вкладки Project). Если вместо названия раздела будетуказано имя файла, это значит, что в соответствующем файле нет тега<TITLE>. Выбрав раздел, надо щелкнуть на кнопке ОК. В результате пере-численных выше действий во вкладке Contents появится строка с названиемраздела справочной информации.
При необходимости изменить значок, соответствующий добавленному раз-делу, следует щелкнуть на кнопке Edit selection и, используя список Imageindex вкладки Advanced окна Table of Contents, выбрать нужный значок(обычно рядом с названием раздела или подраздела изображена книжка).
Глава 8. Справочная система 213
Table of Contents Entry
General j Advanced | Help
Entry title: Available information types:
jCanep 2003
Add… £diL. fjemove
Files/URLs and their information types:
Alternate URL:
Add/Edit…
OK Отмена
Рис. 8.26. Добавление элемента в список разделов
IpathorURL ЩЩ
Project file:
ОЛПроекты CB\Sapet\saper.hhp
HTML titles:
3 Add…
0 программеПравила
• Сапер 2003 ;
File or URL:
saper_01 .him
| OK
Browse… j
Cancel j
Рис. 8.27. Выбор файла, соответствующего элементу списка разделов
214 Часть II. Практикум программирования
Подраздел добавляется точно так же, как и раздел, с тем только отличием,что после того как подраздел будет добавлен, нужно щелкнуть на кнопкеMove selection right. В результате чего уровень заголовка понизится, т. е.раздел станет подразделом.
Элементы содержания, соответствующие темам справочной информации,добавляются аналогичным образом, но процесс начинается щелчком накнопке Insert a page.
Иногда возникает необходимость изменить порядок следования элементовсписка содержания или уровень иерархии элемента списка. Сделать этоможно при помощи командных кнопок, на которых изображены стрелки.Кнопки Move selection up и Move selection down перемещают выделенныйэлемент списка, соответственно, вверх и вниз. Кнопка Move selection rightперемещает выделенный элемент вправо, т. е. делает его подчиненным пре-дыдущему элементу списка. Кнопка Move selection left выводит элемент изподчиненности предыдущему элементу.
В качестве примера на рис. 8.28 приведена вкладка Contents справочнойсистемы программы «Сапер 2003».
? HTML Help Workshop
File View lest Took jjelp
0:\Проекты CB\5aper\saper.hhp
Рис. 8.28. Вкладка Contents содержит названия разделов справочной системы
Компиляция
После того как будут определены файлы, в которых находится справочнаяинформация (сформирован раздел [FILES]) и подготовлена информация для
Глава 8. Справочная система 215
формирования вкладки Содержание (создан файл контекста), можно вы-полнить компиляцию — преобразовать исходную справочную информациюв файл справочной системы (chm-файл).
Исходной информацией для HTML Help компилятора являются:
О файл проекта (hhp-файл);
П файл контекста (hhc);
П файлы справочной информации (htm-файлы);
П файлы иллюстраций (gif- и jpg-файлы).
Результатом компиляции является файл справочной системы (chm-файл).
Чтобы выполнить компиляцию, надо в меню File выбрать команду Compile,в появившемся диалоговом окне Create a compiled file (рис. 8.29) установитьпереключатель Automatically display compiled help file when done (после ком-пиляции показать созданный файл справки) и щелкнуть на кнопке Compile.В результате этого будет создан файл справки и на экране появится окносправочной системы, в котором будет выведена информация главного раз-дела.
Create a compiled file
Project file:
ШЛПроекты CBSSaperSsaper.hhpJ Browse…
Automatically display compiled help file when done
Compile j Cancel
Рис. 8.29. Диалоговое окно Create a compiled file
Вывод справочной информацииВывести справочную информацию, которая находится в chm-файле, можнонесколькими способами. Наиболее просто это сделать при помощи утилитыhh.exe, являющейся составной частью Windows. Вызвать утилиту отображе-ния справочной информации и передать ей в качестве параметра имя файласправочной системы можно при помощи функции winExec. У функцииwinExec два параметра. Первый — имя выполняемого файла программы,которую надо запустить, и командная строка. Второй параметр определяетспособ отображения окна запускаемой программы. Окно запускаемой про-граммы может быть развернуто на весть экран (SW_MAXIMIZE), запущенная
216 Часть II. Практикум программирования
программа может работать в свернутом окне (SW_MINIMIZE) или окно про-граммы может иметь размер и положение такие, какими они былив предыдущем сеансе работы (SW_RESTORE). Ниже в качестве примера при-ведена функция обработки события click на кнопке Справка. Функцияобеспечивает вывод справочной информации, которая находится в файлеsaper.chm.
// Щелчок на кнопке Справка
void _fastcall TForml::Button2Click(TObject *Sender)
(
WinExec(«hh saper.chm»,SW_RESTORE);
ГЛАВА 9
Созданиеустановочного диска
Современные программы распространяются на компакт-дисках. Процессустановки программы, который, как правило, предполагает не только соз-дание каталога и перенос в него выполняемых файлов и файлов данных спромежуточного носителя, но и настройку системы, для многих пользовате-лей является довольно трудной задачей. Поэтому установку прикладнойпрограммы на компьютер пользователя обычно возлагают на специальнуюпрограмму, которая находится на том же диске, что и файлы программы,которую надо установить. Таким образом, разработчик прикладной про-граммы помимо основной задачи должен создать программу установки -инсталляционную программу.
Инсталляционная программа может быть создана точно так же, как и любаядругая программа. Задачи, решаемые во время инсталляции, являются типо-выми. Поэтому существуют инструментальные средства, используя которыеможно быстро создать инсталляционную программу, точнее, установочныйдиск, не написав ни одной строчки кода.
Программа InstallShield ExpressОдним из популярных инструментов создания инсталляционных программявляется пакет InstallShield Express. Borland настоятельно рекомендует ис-пользовать именно эту программу, поэтому она есть на установочном дискеC++ Builder.
Процесс создания инсталляционного диска (CD-ROM) при помощиInstallShield Express рассмотрим на примере.
Пусть нужно создать инсталляционную дискету для программы «Сапер».Перед тем как непосредственно приступить к созданию установочной про-граммы в InstallShield Express, нужно выполнить подготовительную рабо-ту — составить список файлов, которые должны быть установлены на ком-
218 Часть II. Практикум программирования
пьютер пользователя; используя редактор текста, подготовить rtf-файлы ли-цензионного соглашения (EULA — End User Licensia Agreement) и краткойсправки (readme-файл). Список файлов программы «Сапер», которые долж-ны быть перенесены на компьютер пользователя, приведен в табл. 9.1.
Таблица 9.1. Файлы программы «Сапер», которые нужно установитьна компьютер пользователя
Файл
Saper.exe
Saper.chm
Readme.rtf
Eula.rtf
Назначение
Программа
Файл справочной информации
Краткая справка о программе
Лицензионное соглашение
Куда устанавливать
Program FilesVSaper
Program Files\Saper
Program Files\Saper
Program Files\Saper
Новый проектПосле того как будет составлен список файлов, нужно запустить InstallShieldExpress, из меню File выбрать команду New и в поле Project Name andLocation ввести имя файла проекта (рис. 9.1).
JNew Project x|
Project Name and Location:
[F:\Projects\Saper\Saper
Project Language:
j English (United States)
ш~3
OK | Cancel Help
Рис. 9.1. Начало работы над новым проектом
После щелчка на кнопке ОК открывается окно проекта создания инсталля-ционной программы (рис. 9.2). В левой части окна перечислены этапы про-цесса создания и команды, при помощи которых задаются параметры соз-даваемой инсталляционной программы.
Команды настройки объединены в группы, название и последовательностькоторых отражает суть процесса создания инсталляционной программы. За-головки групп пронумерованы. Настройка программы установки выполня-ется путем последовательного выбора команд. В результате выбора командыв правой части главного окна появляется список параметров. Команды, ко-торые были выполнены, помечаются галочками.
Глава 9. Создание установочного диска 219
Я Saper — InstallShield Express Borland Limited Edition
Fte Edit View Go Project Build Idols Help
St D с£У IE fib i ч> ± ,-;>!Organize Your Setup
В ф
«I
j InstallShield TodayHelpO’eanlze Your Setup
3 General Information(jp Features
f Setup TypesUpgrade Paths
Specify Application Data
ft Hes
gj Files and FeaturesЙ Objects/Merge Module:й Dependencies
Configure the Target System — »52 Shortcuts/Folders
§ RegistryODBC Resources
[Ц) INI File ChangesK] File Extensionsf$ Environment Variables
Customize the Setup Appearai»3 Dialogs JT.I
I ±T
Organize Your Setup
The first step in building anything is to lay a solid foundation. jfUjLThe base of your setup is formed by specifying application \ijjrinformation through the General Information view and creatingfeatures in the Features view.
!?lGeperal Information
The General information view is where you set global projectproperties such as the application name and support information.Most of the properties in this view are optional. Your setup will workproperly if you accept the defaults or do not provide values for theoptional properties. However, the following properties are required:Subject, Product Name, Publisher Product Codej Upgrade Code,and Destination Folder,
Features, are the building blocks of your setup. They represent a
Ready
Рис. 9.2. В левой части окна проекта перечислены этапы и команды процесса созданияинсталляционной программы
СтруктураКоманды группы Organize Your Setup (рис. 9.3) позволяют задать структурупрограммы установки.
Organize Your Setup
General Information
Features
Setup Types
Upgrade Paths
Рис. 9.З. Команды группы Organize Your Setup
В результате выбора команды General Information в правой части окна рас-крывается список, в который нужно ввести информацию об устанавливае-мой программе.
Значения большинства параметров, за исключением тех, которые иденти-фицируют устанавливаемую программу и ее разработчика, можно оставить
220 Часть II. Практикум программирования
без изменения. Параметры, значения которых нужно изменить, приведеныв табл. 9.2.
Таблица 9.2. Параметры команды General Information
Параметр Определяет Значение
Product Name Saper
1.01.0001
Название устанавливаемойпрограммы
Product Version Версия устанавливаемойпрограммы
INSTALLDIR Каталог компьютера пользова- [ProgramFilesFolder] Saperтеля, в который будет установ-лена программа
Следует обратить внимание на параметр INSTALLDIR. По умолчанию предпо-лагается, что программа будет установлена в каталог, предназначенный дляпрограмм. Поскольку во время создания инсталляционной программы нель-зя знать, как на компьютере пользователя называется каталог программ ина каком диске он находится, то вместо имени реального каталога исполь-зуется его псевдоним— [ProgramFilesFolder]. В процессе установки про-граммы на компьютер пользователя инсталляционная программа получит изреестра Windows имя каталога программ и заменит псевдоним на это имя.
Другие псевдонимы, которые используются в программе InstallShield Express,приведены в табл. 9.3
Таблица 9.3. Некоторые псевдонимы каталогов Windows
Псевдоним Каталог
[WindowsVolume]
[WindowsFolder]
[SystemFolder]
[ProgramFiles Folder]
[PersonalFolder]
Корневой каталог диска, на котором находится Windows
Каталог Windows, например C:\Winnt
Системный каталог Windows, например C:\Winnt\System32
Каталог программ, например C:\Program Files
Папка Мои документы на рабочем столе (расположениепапки зависит от версии ОС и способа входа в систему)
Очевидно, что возможности инсталлированной программы определяютсясоставом установленных компонентов. Например, если установлены файлысправочной системы, то пользователю в процессе работы с программойдоступна справочная информация. Команда Features (возможности) позво-ляет создать (определить) группы компонентов, которые определяют воз-
Глава 9. Создание установочного диска 221
можности программы и которые могут устанавливаться по отдельности.Разделение компонентов на группы позволяет организовать многовариант-ную, в том числе и определяемую пользователем, установку программы.
В простейшем случае группа Features состоит из одного элемента AlwaysInstall. Чтобы добавить элемент в группу Features, нужно щелкнуть правойкнопкой мыши на слове Features, из появившегося контекстного меню вы-брать команду New Feature Ins и ввести имя новой группы, например HelpFiles and samples. После этого в поле Description нужно ввести краткуюхарактеристику элемента, а в поле Comments — комментарий (рис. 9.4).
Features
©SSSHESЩ Up Help Files and Samples
Always Install, Progrjsm FeatureDescription
Remote Installation
AdvertisedCommentsREG File To Merge At Build
Enter the description for this Feature here.
Favor Local
Allow AdvertiseEnter comments regarding this feature here.
Рис. 9.4. Несколько элементов в группе Features обеспечивают возможностьмноговариантной установки
Команда Setup Types позволяет задать, будет ли пользователю во время ус-тановки программы предоставлена возможность выбрать (в диалоговом окнеSetup Type) вариант установки. Установка может быть обычной (Typical),минимальной (Minimal) или выборочной (Custom). Если устанавливаемаяпрограмма сложная, т. е. состоит из нескольких независимых компонентов,то эта возможность обычно предоставляется.
Для программы «Сапер» предполагается только один вариант установки -Typical. Поэтому флажки Minimal и Custom нужно сбросить (рис. 9.5).
«gi Setup TypesШШШЦММв ^ М ЯЮМ11Щ1Щ1П1ШШЛС.Ж*1ЯИЯЯ»,Ш«.ШШ.ЫИ1*в«ЛМв(1ЯВЭЙ!« i. ЖПЫНН Ш^Ш^ Н
i-<:-. 4
B<
/J InstallShield Today ->•X и=1„^ Help• Organize Your Setup
<S fjjj] General Information(jp Features
•/ ‘Щ Setup Types№)J Upgrade Paths
^ Specify Application Data•3> Files
Ш Files and Features— — — —
Setup Types
V StTypical…1 MinimalL J ;чЗ CuStstom
Рис. 9.5. Команда Setup Types позволяет задать возможные вариантыустановки программы
222 Часть II. Практикум программирования
Выбор устанавливаемых компонентовКоманды группы Specify Application Data (рис. 9.6) позволяют определитькомпоненты программы, которые должны быть установлены на компьютерпользователя. Если в проекте определены несколько групп компонентов(см. команду Features), то нужно определить компоненты для каждой группы.
Specify Application Data
rjS Files
S| Files and Features
1Й Objects/Merge Modules
ii | Dependencies
Рис. 9.6. Команды группы Specify Application Data
В результате выбора команды Files правая часть окна будет разделена наобласти (рис. 9.7). В области Source computer’s files можно выбрать файлы,которые необходимо перенести на компьютер пользователя. В областиDestination computer’s folders надо выбрать папку, в которую эти файлыдолжны быть помещены. Для того чтобы указать, какие файлы нужно уста-новить на компьютер пользователя, следует просто «перетащить» требуемыефайлы из области Source computer’s files в область Destination computer’sfiles. Если в группе Features несколько элементов, то надо определить фай-лы для каждого элемента.
if Files , ;
Feature: [Always Install 1
Source computer’s folders
; M Cj Inetpub• \ ffl CJ Program Files
— Jj Projects
: —f «1 Organiser
; M Cj| Saper
; : ш-Cj pw; 1 Simpsons
< Г : 2 l»» i
Ч
J
JDestination computer’s folders
££ Destination Computer3 GO [ProgramFilesFolder]
В id Saper [INSTALLDIR]L*j Database [DATABASEDIF
<l 1 Ч
Source computer’s files
Name ] Size j Type j Modified
ISJeula 20,9КБ Формат RTF 14.10.2003 Hi…
Bjreadme 9,S4KE Форматер НЛО. 2003 10;..,
[l saper 11,6КБ Скомпилирова,.. 30.0-1.200315;…
ULsaper 404КБ Приложение 09.07.200313:…
Щ Saper 177КБ InstallShieldEx… 15.10.200317;…
Destination computer’s files
Name j , Size j Link To | Mo. !
Osaper.exe 404КБ F:\Projects\Sap… 07.:
^1 1 >l
Рис. 9.7. Выбор файлов, которые нужно перенести на компьютер пользователя
Глава 9. Создание установочного диска 223
Команда Object/Merge Modules позволяет задать, какие объекты, напримердинамические библиотеки или пакеты компонентов, должны быть помеще-ны на компьютер пользователя и, следовательно, на установочную дискету.Объекты, которые нужно поместить на установочную дискету, выбираютсяв списке InstallShield Objects/Merge Modules (рис. 9.8).
*- Objects/Merge Modules
InstallShield Objects/Merge Modules
nfijADORTL __J
DgjBaseVO.’3®BDE_ENT
ПЙОАОЗ.бО
DjSiDatabeseRTL
С! и DatabaseVCL
Г 1 Й ПлМЧплп
Description of BDE_ENT
NameBDE_ENT
Destination(Use merge module’s default destination)
File NameF:\Prograon Files\Borland\Delphi7
\MergeModules\BDE_EMT.Msm
Aufhnr Л1
Conditional Installation
Help
Select which feature, or /^P^Yfeatures, you want to associate jlrthis module with. If theselected feature is installed,the module will also be installed, Mergemodules replace the concept of objectsfound in earlier versions of InstallShield.See MerQe Modules for more information.
.d
Рис. 9.8. Выбор объектов, которые должны быть установлены на компьютер пользователя
Конфигурирование системы пользователяКоманды группы Configure the Target System (рис. 9.9) позволяют задать,какие изменения нужно внести в систему пользователя, чтобы настроитьсистему на работу с устанавливаемой программой.
> Configure the Target System
Ц±\ Shortcuts/Folders
fjT Registry
Sip ODBC Resources
Щ) INI File Changes
|xj File Extensions
|$ Environment Variables
Рис. 9.9. Команды группы Configure the Target System
224 Часть II. Практикум программирования
Команда Shortcuts/Folders позволяет указать, куда нужно поместить ярлык,обеспечивающий запуск устанавливаемой программы. В результате выбораэтой команды в правой части окна открывается иерархический список,в котором перечислены меню и папки, куда можно поместить ярлык про-граммы. В этом списке нужно выбрать меню, в которое должен быть поме-щен ярлык, щелкнуть правой кнопкой мыши и в появившемся списке вы-брать команду New Shortcut (рис. 9.10).
i-1 Щ] Shortcuts
B|jTaskbar
: Е 1-Я Start Menu
;» (§j Startup 1
§ Send To
Desktop
SWit
New Shortcut t ins
New Advertised Shortcut «S
New Shortcut to Preexisting file
New Folder
Рис. 9.10. В списке Shortcuts нужно выбрать меню, в которое должен быть помещенярлык запуска программы
Look™ I’jfj Saper [INSTALLDIR] jrj !V]
j Name j Size j Link To
404 КБ F:\Projects\Sap.
L»J Database
< I 1
File Qame: j saper.exe
Files of | Executable Files (*,exe)
j<j
j| Modified
. 07.09.2C
±1
Open |
Cancel
Рис. 9.11. Выбор файла, для которого создается ярлык
[ШрЕддНИИИ Saper Game Shortcut» T;bJ -31 TasKdar
; H -:рч Start Menu
El ц§] Programs Menu
Щ Saper Game
^щ ьсагсир
|3 Desktop
Description
Arguments
Target [INSTALLDIR]saper.exe
Icon File F : \Projects\Saper\saper . exe
Icon Index 0
Run Normal Window
Working Directory
Hot Key
Comments
Рис. 9.12. Ярлык создан, теперь можно выполнить его настройку
Глава 9. Создание установочного диска 225
Затем, в диалоговом окне Browse for Shortcut Target, нужно выбрать файлпрограммы (рис. 9.11), щелкнуть на кнопке Open и ввести имя ярлыка. По-сле этого можно выполнить окончательную настройку ярлыка, например, вполе Arguments ввести параметры командной строки, а в поле WorkingDirectory — рабочий каталог (рис. 9.12).
Настройка диалоговДля взаимодействия с пользователем программа установки использует стан-дартные диалоговые окна. Разрабатывая программу инсталляции, програм-мист может задать, какие диалоги увидит пользователь в процессе инстал-ляции программы.
Чтобы задать диалоговые окна, которые будут появляться на экране мони-тора во время работы инсталляционной программы, надо в группе Customizethe Setup Appearance (рис. 9.13) выбрать команду Dialogs и в открывшемсясписке Dialogs (рис. 9.14) отметить диалоги, которые нужно включить впрограмму установки.
Customize the Setup Appearance
~Э Dialogs
Д Billboards
5K Text and Messages
Рис. 9.13. Команды группы Customize the Setup Appearance
В -Э DialogsjO Splash Bitmap
I- @ ~3 Install WelcomeЙ ~ | License Agreement
: @ 3 Readme: I …j ~?1 Customer Information
U 3 Destination FolderI D 3 Database FolderS» И ГЭ Setup Type
Г ; 3 Custom Setup! S3 ~3 Ready to Install: 3 3 Setup Progress: В «3 Setup Complete Success
Banner Bitmap <15ProductFolder>\Redist\LanguagfReadme File <ISProductFolder>\Redist\0409\Re;
Рис. 9.14. В списке Dialogs нужно отметить диалоги, которые должны появитьсяв процессе установки программы на компьютер пользователя
В таблице Properties (справа от списка диалогов) перечислены свойства вы-бранного диалога. Программист может изменить значение этих свойств и,тем самым, выполнить настройку диалога. Например, для диалога Readmeнужно задать имя файла (свойство Readme File), в котором находится крат-кая справка об устанавливаемой программе.
8 Зак. 1252
226 Часть II. Практикум программированы
Для большинства диалогов можно определить баннер (свойство ваппеBitmap) — иллюстрацию, которая отображается в верхней части окна диалога. Формат файла баннера — BMP, размер — 499×58 пикселов.
В табл. 9.4 перечислены диалоговые окна, которые могут появиться во время работы инсталляционной программы.
Таблица 9.4. Диалоговые окна процесса установки
Диалоговое окно Назначение
Вывод иллюстрации, которая может служить в качествеинформации об устанавливаемой программе. Размер ил-люстрации — 465×281 пиксел, формат — BMP
Вывод информационного сообщения на фоне иллюстрации(размер 499×312 пикселов)
Вывод находящегося в rft-файле лицензионного сообщения.Позволяет прервать процесс установки программы в случаенесогласия пользователя с предлагаемыми условиями
Вывод краткой информации об устанавливаемой программе
Запрашивает информацию о пользователе (имя, названиеорганизации) и, возможно, серийный номер устанавливае-мой копии
Предоставляет пользователю возможность изменить пре-допределенный каталог, в который устанавливается про-грамма
Предоставляет пользователю возможность изменить пред-определенный каталог, предназначенный для баз данных
Предоставляет пользователю возможность выбрать типустановки программы (Typical— обычная установка,Minimal — минимальная установка, Custom — выборочнаяустановка)
Предоставляет пользователю возможность выбрать уста-навливаемые компоненты при выборочной (Custom) уста-новке
Вывод информации, введенной пользователем на преды-дущих шагах, с целью ее проверки перед началом непо-средственной установки программы
Показывает процент выполненной работы во время уста-новки программы
Информирует пользователя о завершении процесса уста-новки. Позволяет задать программу, которая должна бытьзапущена после завершения установки (как правило, этосама установленная программа), а также возможность вы-вода содержимого Readme-файла
Splash Bitmap
Install Welcome
License Agreement
Readme
CustomerInformation
Destination Folder
Database Folder
Setup Type
Custom Setup
Ready to Install
Setup Progress
Setup CompleteSuccess
Глава 9. Создание установочного диска 227
Для того чтобы диалоговое окно появлялось во время работы инсталляци-онной программы, необходимо установить флажок, расположенный слеваот названия диалогового окна. Для окон License Agreement и Readme нужнозадать имена rtf-файлов, в которых находится соответствующая инфор-мация.
В простейшем случае профамма инсталляции может офаничиться выводомследующих диалогов:
П Readme;
О Destination Folder;
П Ready to Install;
П Setup Progress;
CJ Setup Complete Success.
Системные требованияЕсли устанавливаемая профамма предъявляет определенные требованияк ресурсам системы, то, используя команды фуппы Define Setup Requirementsand Actions (рис. 9.15), эти требования можно задать.
Define Setup Requirements and Actions
§ Requirements
Custom Actions
£J Setup Files
Рис. 9.15. Команды группы Define Setup Requirements and Actions
::>-:• version ; AIT:
Processor
RAM Any
Screen Resolution Any Resolution
Color Depth Any colors
Рис. 9.16. Параметры, характеризующие систему
В результате выбора команды Requirements на экране появляется таблица(рис. 9.16), в которую надо ввести значения параметров, характеризующихсистему: версию операционной системы (OS Version), тип процессора(Processor), объем оперативной памяти (RAM), разрешение экрана (ScreenResolution) и цветовую палитру (Color Depth). Значения характеристик за-
228 Часть II. Практикум программирования
даются путем выбора из раскрывающегося списка, значок которого появля-ется в результате щелчка в поле значения параметра.
Если программа не предъявляет особых требований к конфигурации систе-мы, то команды группы Define Setup Requirements and Actions можно про-пустить.
Создание образа установочной дискетыКоманды группы Prepare for Release (рис. 9.17) позволяют создать образ ус-тановочной дискеты (CD-ROM) и проверить, как работает программа уста-новки.
Prepare for Release
(||у Build Your Release
!§• Test Your Release
QJ, Distribute Your Release
Рис. 9.17. Команды группы Prepare for Release
Для того чтобы активизировать процесс создания образа установочной дис-кеты (CD-ROM), нужно выбрать команду Build Your Release, щелкнуть пра-вой кнопкой мыши на значке носителя, на который предполагается помес-тить программу установки, и из появившегося контекстного меню выбратькоманду Build (рис. 9.18).
|ШЭИИИ |fcDl.ROM ReleaseJJ7J :, ^ ‘ кУсЯНЙЛГ — 4
•В ф Custom К&ЩЧЕЭИ33-ф DVD-10
f«»;Vi DVD-1Bдан f, DVD-5 T*tt>un I Compress Media
ЕЯ -ф DVD-9В 0, Singlelmage
:
—
M5I Engine VersionMSI Engine Location
Include Setup.exeInclude MSI Engine(s)
Delay MSI Engine RebootSuppress Launcher Warning
«Generate Autorijn,inF File
•• 05C
No
2,0
Copy From Source MediaYesBoth 9x and NT EnginesYesYesNo
Рис. 9.18. Активизация создания образа установочного CD-ROM
В результате этих действий на диске компьютера в папке проекта будет соз-дан образ установочного диска. Если в качестве носителя выбран CD-ROM,то образ будет помещен в подкаталог \Express\Cd_rom\DiskImages\Diskl.
Можно, не завершая работу с InstallShield Express, проверить, как функцио-нирует программа установки. Для этого надо щелкнуть на одной изкомандных кнопок Run или Test (рис. 9.19). Команда Run устанавливает
Глава 9. Создание установочного диска 229
программу, для которой создана программа установки, на компьютер разра-ботчика. Команда Test только имитирует установку, что позволяет прове-рить работоспособность интерфейса.
Run Test
Рис. 9.19. Используя команды Run и Test можно проверить,как работает программа установки
После того как программа установки будет проверена, можно создать ре-альный установочный диск. Для этого надо просто скопировать (записать)содержимое каталога \Express\Cd_rom\DiskImages\DisklHa CD-ROM.
ГЛАВА 10
Примеры программ
Система проверки знанийТестирование широко применяется для оценки уровня знаний в учебныхзаведениях, при приеме на работу, для оценки квалификации персоналаучреждений, т. е. практически во всех сферах деятельности человека. Испы-туемому предлагается ряд вопросов (тест), на которые он должен ответить.
Обычно к каждому вопросу дается несколько вариантов ответа, из которыхнадо выбрать правильный. Каждому варианту ответа соответствует некото-рая оценка. Суммированием оценок за ответы получается общий балл, наоснове которого делается вывод об уровне подготовленности испытуемого.
Рассмотрим программу, которая позволяет автоматизировать процесс тести-рования.
Требования к программеВ результате анализа используемых на практике методик тестирования былисформулированы следующие требования к программе:
О программа должна обеспечить работу с тестом произвольной длины, т. е.не должно быть ограничения на количество вопросов в тесте;
О вопрос может сопровождаться иллюстрацией;
П для каждого вопроса может быть до четырех возможных вариантов ответасо своей оценкой в баллах;
П результат тестирования должен быть отнесен к одному из четырех уров-ней, например: «отлично», «хорошо», «удовлетворительно» или «плохо»;
П вопросы теста должны находиться в текстовом файле;
П в программе должна быть заблокирована возможность возврата к преды-дущему вопросу. Если вопрос предложен, то на него должен быть данответ.
Глава 10. Примеры программ 231
На рис. 10.1 приведен пример окна программы тестирования во время ееработы.
История Санкт-Петербурга
Архитектор Исаакиевского собора.
Г ДоменикоТрезини
(• iSnocT МонФерраЦ
Р К.арл Росси
Дальше j
Рис. 10.1. Диалоговое окно программы тестирования
Файл тестаТест представляет собой последовательность вопросов, на которые испы-туемый должен ответить путем выбора правильного ответа из несколькихпредложенных вариантов.
Файл теста состоит из трех разделов:
П раздел заголовка;
П раздел оценок;
П раздел вопросов.
Заголовок содержит название теста и общую информацию о тесте — напри-мер, о его назначении. Заголовок состоит из двух абзацев: первый абзац -название теста, второй — вводная информация.
Вот пример заголовка:
История Санкт-ПетербургаСейчас Вам будут предложены вопросы о знаменитых памятниках и архитектурныхсооружениях Санкт-Петербурга. Вы должны из предложенных нескольких вариантов ответавыбрать правильный.
За заголовком следует раздел оценок, в котором указывается количествобаллов, необходимое для достижения уровня, и сообщение, информирую-
232 Часть II. Практикум программированы
шее испытуемого о достижении уровня. В простейшем случае сообщение —это оценка. Для каждого уровня надо указать балл (количество правильныхответов) и в следующей строке — сообщение. Вот пример раздела оценок:
100Отлично85Хорошо60Удовлетворительно50Плохо
За разделом оценок следует раздел вопросов теста.
Каждый вопрос начинается текстом вопроса, за которым (в следующейстроке) следуют три целых числа. Первое число — это количество альтерна-тивных ответов, второе — номер правильного ответа, третье — признак ил-люстрации. Если к вопросу есть иллюстрация, то третье число должно бытьравно единице, и в следующей строке должно быть имя файла иллюстра-ции. Если иллюстрации к вопросу нет, то признак иллюстрации долженбыть равен нулю. Далее следуют альтернативные ответы, каждый из кото-рых должен представлять собой один абзац текста.
Вот пример вопроса:
Архитектор Зимнего дворца321herm.bmpБартоломеоКарл РоссиОгюст Монферран
В приведенном примере к вопросу даны три варианта ответа, правильнымявляется второй ответ (архитектор Зимнего дворца — Карл Росси). К вопро-су есть иллюстрация (третье число во второй строке — единица), котораянаходится в файле herm.bmp.
Ниже в качестве примера приведен текст файла вопросов для контроля зна-ния истории памятников и архитектурных сооружений Санкт-Петербурга.
История Санкт-ПетербургаСейчас Вам будут предложены вопросы о знаменитых памятниках и архитектурныхсооружениях Санкт-Петербурга. Вы должны из предложенных нескольких вариантов ответавыбрать правильный.7Вы прекрасно знаете историю Санкт-Петербурга!6Вы много знаете о Санкт-Петербурге, но на некоторые вопросы ответили неверно.
Глава 10. Примеры программ 233
5 : : ‘. . ‘» ‘ ;Вы недостаточно хорошо знаете историю Санкт-Петербурга?4Вы, вероятно, только начали знакомиться с историей Санкт-Петербурга?Архитектор Исаакиевского собора:321isaak.bmpДоменико ТрезиниОпорт МонферранКарл РоссиАлександровская колонна воздвигнута в 1836 году по проекту Огюста Монферранакак памятник, посвященный:210деяниям императора Александра Iподвигу русского народа в Отечественной войне 1812 годаАрхитектор Зимнего дворца321herm.bmpБартоломее РастреллиКарл РоссиОпост МонферранМихайловский (Инженерный) замок—жемчужина архитектуры Петербурга — построенпо проекту:310Андрея Никифоровича ВоронихинаИвана Егоровича СтароваВасилия Ивановича БаженоваОстров, на котором находится Ботанический сад, основанный императором Петром I,называется:331botbmpЗаячийМедицинскийАптекарскийНевский проспект получил свое название:320по имени реки, на которой стоит Санкт-Петербургпо имени близко расположенного монастыря, Александро-Невской лаврыв память о знаменитом полководце —-Александре НевскомСкульптура знаменитого памятника Петру I выполнена:210ФальконеКлодтом
Файл теста может быть подготовлен в текстовом редакторе Notepad илив Microsoft Word. В случае использования Microsoft Word при сохранениитекста следует указать, что надо сохранить только текст. Для этого в диало-говом окне Сохранить в списке Тип файла следует выбрать Только текст(*.txt).
234 Часть II, Практикум программирования
Форма приложенияНа рис. 10.2 приведен вид формы программы тестирования.
Поле Labell предназначено для вывода начальной информации, вопроса ирезультатов тестирования. Компонет imagel предназначен для вывода иллю-страции, сопровождающей вопрос. Кнопка Buttoni используется для под-тверждения выбора ответа и перехода к следующему вопросу.
Labell
Imagel
Buttoni •
г». Система тестирования
OK
Рис. 10.2. Форма программы тестирования
Нетрудно заметить, что в форме нет радиокнопок — компонентовRadioButton, обеспечивающих вывод альтернативных ответов и прием ответаиспытуемого. В рассматриваемой программе компоненты RadioButton будутсозданы динамически, во время работы программы.
В табл. 10.1 и 10.2 приведены значения свойств формы и компонентаLabell. Значения остальных свойств этих и других компонентов можно ос-тавить без изменений.
Таблица 10.1. Значения свойств формы
Свойство Значение Пояснение
Border-Icons. biSystemMenu true
Borderlcons.biMinimize false
Borderlcons.biMaximize false
Есть кнопка системного меню
Нет кнопки Свернуть окно
Нет кнопки Развернуть окно
Глава 10. Примеры программ 235
Таблица 10.1 (окончание)
Свойство Значение Пояснение
BorderStyle bsSingle Тонкая граница окна, нельзя изме-нить размер окна
Таблица 10.2. Значения свойств компонента Labell
Свойство Значение Пояснение
AutoSize false Запрет изменения размера поля в соответствии с егосодержимым
Wordwrap true Разрешить перенос слов в следующую строку поля
Следует обратить внимание, что несмотря на то, что свойстваBorderlcons.biMinimize И Borderlcons.biMaximize имеют значение false,кнопки Свернуть окно и Развернуть окно отображены в форме. Реальноевоздействие значений этих свойств на вид окна проявляется только во вре-мя работы программы. Значение свойства BorderStyle также проявляет себятолько во время работы программы.
Отображение иллюстрацииДля отображения иллюстраций используется компонент imagei.
Размер и положение компонента image и, следовательно, размер и положе-ние поля, используемого для отображения иллюстрации, наиболее простозадать во время разработки формы. В рассматриваемой программе применя-ется другой подход.
Очевидно, что размер области формы, которая может быть использованадля вывода иллюстрации, зависит от длины (количества слов) вопроса, атакже от длины и количества альтернативных ответов. Чем длиннее вопроси ответы, тем больше места в поле формы они занимают, и тем меньшеместа остается для иллюстрации.
Размер и положение областей (компонентов), предназначенных для выводавопроса, альтернативных ответов и иллюстрации, можно задать в процессесоздания формы. Однако можно поступить иначе — задать размер и поло-жение областей во время работы программы, после того как из файла будетпрочитан очередной вопрос, когда будет получена информация о количест-ве альтернативных ответов. После того как вопрос прочитан, можно вычис-лить, сколько места займет текст вопроса и вариантов ответа и сколько мес-та можно выделить для отображения иллюстрации (рис. 10.3).
236 Часть II. Практикум программирования
Label1->Top
ClientHeight
Button 1->Тор •
Labeh->Height
(RadioButton[0]->Height + 20) *n
Рис. 10.3. Вычисление размера области вывода иллюстрации
Если реальный размер иллюстрации превышает размер области, выделеннойдля ее отображения, то необходимо выполнить масштабирование иллюстра-ции. Для этого надо сначала присвоить максимально возможные значениясвойствам width и Height, а затем — присвоить значение true свойствуProportional. Следует обратить внимание, что для того чтобы масштабиро-вание было выполнено без искажения, значение свойства stretc должнобыть false.
Доступ к файлу тестаПередать имя файла теста программе тестирования можно через параметркомандной строки.
При запуске программы из операционной системы при помощи командыПуск | Выполнить параметры командной строки указывают после именивыполняемого файла программы (рис. 10.4).
Запуск программы
Введите имя программы, папки, документа илиресурса Интернета, и Windows откроет их.
Открыть: 10:\Проекты CB\tester.exe Peterburg.txt!
OK Отмена Обзор..,
Рис. 10.4. Передача параметра при запуске программы командой Пуск | Выполнить
Глава 10. Примеры программ 237
Если запуск программы выполняется при помощи значка, изображающегопрограмму на рабочем столе или в папке, то параметр командной строкизадают в окне Свойства этого значка. Например, для настройки программытестирования на работу с файлом теста Peterburg.txt надо раскрыть окносвойств значка (щелкнуть правой кнопкой мыши на значке и из появивше-гося контекстного меню выбрать команду Свойства) и в поле Объект (послеимени выполняемого ‘файла программы) ввести имя файла теста (Peter-burg.txt), заключив его в двойные кавычки (рис. 10.5).
Общие Ярлык j
Проверка знаний
Тип объекта: Приложение
Размещение: Проекты СВ
Объект: I «0:\Проекты CB\tester.exe» «Peterburg.txt»!
F ,;:,.,.., ьвош -,- : • • • — . . . ‘ . , п
Г» Запускать от имени другого пользователя .
Рабочая папка: «0:\ПроектыСВ»
Быстрый вызов: ((Нет
QKHO: |обычный размер окна
Комментарий:
Найти объект… 1 Изменить значок…
ОК Отмена Прицепить
Рис. 10.5. Настройка программы тестирования на работу с файлом Peterburg.txt
Программа может получить информацию о количестве параметров команд-ной строки, обратившись к функции ParamCount. Доступ к конкретному па-раметру обеспечивает функция Paramstr, которой в качестве параметра пе-редается номер параметра, значение которого надо получить. Парамет-ры командной строки нумеруются с единицы. Следует обратить внимание,что значением paramStr(O) является полное имя выполняемого файла про-граммы.
Ниже приведен фрагмент программы, который демонстрирует доступ к па-раметрам командной строки.
238 Часть II. Практикум программирования
int n = ParamCount ( ) ;
if ( n < 1)
{
Labell->Font->Style = TFontStyles ( ) « fsBold;
Labell->Caption =
«В командной строке надо указать имя файла теста»;
Buttonl->Tag = 2;
return;
/ / открыть файл теста
f = FileOpenfParamStr (1) , fmOpenRead) ;
При запуске программы, использующей параметры командной строки, изсреды разработки параметры нужно ввести в поле Parameters диалогового ок-на Run Parameters (рис. 10.6), которое открывается в результате выбора изменю Run команды Parameters.
llRiin Parameters F j
Local j Remote]
~ Host Application — ‘ —
г Parameters'»»1 —
•»•) Browse…— ‘ ^ „ I :
I [Peterburg.M j»j i
Load OK Cancel ttelp
Рис. 10.6. Параметры командной строки надо ввести в поле Parameters
Текст программыПосле того как будет создана форма программы, можно приступить к коди-рованию (набору текста). Сначала надо внести дополнения в объявлениеформы (листинг 10.1) — объявить массив компонентов RadioButton, функ-цию обработки события click на кнопке выбора ответа и функции, обеспе-чивающие отображение и удаление вопроса. Следует обратить внимание нато, что объявление массива компонентов RadioButton (указателей на компо-ненты) только устанавливает факт существования компонентов, сами жекомпоненты будут созданы в начале работы программы. Делает это конст-
Глава 10. Примеры программ _ 239
руктор формы. Он же задает функции обработки события click для компо-нентов массива. Другой важный момент, на который следует обратить вни-мание, это объявление функций swowvopros и Erasevopros как методов объ-екта Forml. Это сделано для того, чтобы обеспечить этим функциям прямойдоступ к компонентам формы.
Текст модуля главной формы приведен в листинге 10.2.
I Листинг 10.1. Программа тестирования (заголовочный файл)
#ifndef tester_H
#define tester_H
linclude <Classes.hpp>
#include «Controls. hpp>
#include <StdCtrls.hpp>
finclude <Forms.hpp>
#include <ExtCtrls .hpp>
#include <Dialogs.hpp>
#include <Graphics.hpp>
// вопрос
struct TVopros {
AnsiString Vopr; // вопрос
AnsiString Img; // иллюстрация (имя BMP-файла)
AnsiString Otv[4]; // варианты ответа
int nOtv; // кол-во вариантов ответа
int rOtv; // номер правильного ответа
// форма
class TForml : public TForm
{
published : // IDE-managed Components
TLabel *Labell; // информационное сообщение, вопрос
TImage *Imagel; // иллюстрация к вопросу
TButton *Buttonl; // кнопка OK / Дальше
void _ fastcall FonnActivate (TObject *Sender) ;
void _ fastcall ButtonlClick (TObject * Sender };
private :
TRadioButton *RadioButton[4] ; // варианты ответа — кнопки выбораvoid _ fastcall RadioButtonClick (TObject * Sender ); // щелчок на
// кнопке выбора ответа
void _ fastcall ShowVopros (TVopros v) ; // выводит вопрос
void fastcall EraseVopros (void) ; // удаляет вопрос
240 _ Часть II. Практикум программирования
public :_ fastcall TForml (TComponent* Owner) ;
extern PACKAGE TForml *Forml;
tendif
i Листинг 10.2. Программа тестирования; ……………………………….. , ………….. ,„„ …………….. ,_ ……………. ,__ …………………………….. , …………….
; ……………. . ……………. , ……. ,.,..,
/* Универсальная программа тестирования. Тест загружается
из файла, имя которого должно быть указано в командной
строке .
Программа демонстрирует создание и настройку компонентов
во время работы программы.
*/
#include <vcl . h>
Ipragma hdrstop
•#include «tester_.h»
tinclude <stdio.h> // для доступа к функции sscanf
ttpragma package (smart_init)
tpragma resource «*.dfm»
TForml *Forml; // форма
int f; // ‘ дискриптор фата теста
// имя файла теста берем из командной строки
int level [4]; // кол-во правильных ответов ,. необходимое
// для достижения уровня
AnsiString mes[4];// сообщение о достижении уровня
TVopros Vopros; // вопрос
int otv; // номер выбранного ответа
int right =0; // кол-во правильных ответов
// функции, обеспечивающие чтение вопроса из файла теста
int Get Int (int f ) ; // читает целое
int GetString (int f, AnsiString *st) ; // читает строку
// конструктор
fastcall TForml::TForml(TComponent* Owner)
: TForm(Owner)
Глава 10. Примеры программ 241
int i;
int left = 10;
// создадим радиокнопки для выбора
// правильного ответа, но сделаем их невидимыми
for (i = 0; i < 4; i++)
{
// создадим радиокнопку
RadioButton [i] = new TRadioButton ( Forml ) ;
// установим значения свойств
RadioButton[i]->Parent = Forml;
RadioButton[i]->Left = left;
RadioButton[i]->Width = Forml->ClientWidth — left — 20;
RadioButton[i]->Visible = false;
RadioButton [ i ] ->Checked = false;
// зададим функцию обработки события Click
RadioButton [i]->OnClick = RadioButtonClick;
void _ fastcall TForml: : FormActivate (TObject *Sender)
{
AnsiString st;
// имя файла теста должно быть указано в командной строке
int n = ParamCount ( ) ;
if ( n < 1)
{Labell->Font->Style = TFontStyles О « fsBold;
Labell->Caption =
«В командной строке запуска надо задать имя файла теста»;
Buttonl->Tag = 2;
return;
// открыть файл теста
f = FileOpen(ParamStr (1) , fmOpenRead) ;
if ( f == -1)
{
Labell->Font->Style = TFontStyles ()« fsBold;
Labell->Caption =
«Ошибка доступа к файлу теста » + ParamStr(l)
242 Часть II. Практикум программирования
Buttonl->Tag
return;
2;
// вывести информацию о тесте
GetString(f, &st); // прочитать название теста
Forml->Caption = st;
GetString(f, sst) ; // прочитать вводную информацию
Label l->Width = Forml->ClientWidth — Labell->Left -20;
Labell->Caption = st;
Labell->AutoSize = true;
// прочитать информацию об уровнях оценки
for (int i=0; i<4;
level [i] = Getlnt (f) ;
GetString(f, &mes[i]);
// читает из файла очередной вопрос
bool GetVopros (TVopros *v)
{
AnsiString st;
int p; // если р=1, то к вопросу есть иллюстрация
if ( GetStringtf, & (v->Vopr) ) != 0)
{
// прочитать кол-во вариантов ответа, номер правильного ответа// и признак наличия иллюстрации
v->nOtv = Getlnt (f);
v->rOtv = Getlnt (f);
p = Getlnt (f) ;
if (p) // к вопросу есть иллюстрация
GetString (f , & (v->Img) ) ;
else v->Img = «»;
// читаем варианты ответа
for (int i = 0; i < v->nOtv;
GetString (f, & (v->0tv[i] ) ) ;
}
return true;
Глава 10. Примеры программ _ 243
else return false;
// выводит вопрос
void _ fastcall TForml: : ShowVopros (TVopros v)
{
int top;
int i;
// вопрос
Labell->Width = ClientWidth — Labell-XLeft -20;
Labell->Caption = v.Vopr;
Labell->AutoSize = true;
if (v.Img != «») //к вопросу есть иллюстрация
{
/* определим высоту области, которую можно
использовать для вывода иллюстрации */
int RegHeight = Buttonl->Top
— (Labell-ХГор + Labell->Height +10) // область вывода вопроса
— (RadioButton[l]->Height + 10) * v.nOtv;
Imagel->Top = Labell->Top + Labell->Height + 10;
// загрузим картинку и определим ее размер
Imagel->Visible = false;
Imagel->AutoSize = true;
Imagel->Picture->LoadFromFile (v. Img) ;
if (Imagel->Height > RegHeight) // картинка не помещается
{Imagel->AutoSize = false;
Imagel->Height = RegHeight;
Imagel->Proportional = true;
}
Imagel->Visible = true;
// положение полей отсчитываем от иллюстрации
top = Imagel-ХГор + Imagel->Height + 10;
Ielse // положение полей отсчитываем от вопроса
top = Labell-ХГор + Labell->Height + 10;
// варианты ответа
for (i = 0; i < v.nOtv; i
RadioButton[i]->Top = top;
RadioButton[i]->Caption = v.Otvfi];
244 Часть II. Практикум программирования
RadioButton[i]->Visible = true;
RadioButton[i]->Checked = false;
top += 20;
// щелчок на радиокнопке выбора ответа
void _ fastcall TForml: :RadioButtonClick (TObject *Sender)
{
int i =0;
while { ! RadioButton[i] ->Checked)
otv = i+1;
// ответ выбран, сделаем доступной кнопку Дальше
Buttonl->Enabled = true;
// удаляет вопрос с экрана
void _ fastcall TForml : :EraseVopros (void)
{
Iraagel->Visible = false; // скрыть поле вывода иллюстрации
// скрыть поля выбора ответа
for (int i = 0; i <4; i++)
{
RadioButton[i]->Visible = false;
RadioButton[i]->Checked = false;
}
Buttonl->Enabled = false; // сделать недоступной кнопку Дальше
}
// щелчок на кнопке ОК/Дальше/ОК
void _ fastcall TForml : :ButtonlClick (TObject *Sender)
{
bool ok; // результат чтения из файла очередного вопроса
switch (Buttonl->Tag) {
case 0: // щелчок на кнопке ОК в начале работы программы
// прочитать и вывести первый вопрос
GetVopros (SVopros) ;
ShowVopros (Vopros) ;
Buttonl->Caption = «Дальше»;
Buttonl->Enabled = false;
Глава 10. Примеры программ _ 245
Buttonl->Tag = 1;
break;
case 1 : // щелчок на кнопке Дальше
if (otv = Vopros.rOtv) // выбран правильный ответ
right++;
EraseVqpros ( ) ;
ok = GetVopros ( sVopros ) ;
if ( ok)
ShowVopros (Vopros) ;
else
// вопросов больше нет
(
FileClose(f ) ;
// вывести результат
AnsiString st; // сообщение
int i; // номер достигнутого уровня
Forml->Caption = «Результат тестирования»;
st.printf («Правильных ответов: %i\n», right) ;
// определим оценку
1 = 0; // предположим, что испытуемый
// ответил на все опросы
while (( right < level [i]) &й (1 < 3))
st = st + mes [i] ;
Labell->Caption = st;
Buttonl->Caption = «OK»;
Buttonl->Enabled = true;
Buttonl->Tag = 2;
}
break;
case 2 : // щелчок на кнопке OK в конце работы программы
Forml->Close ( ) ; // завершить работу программы
// Функция GetString читает строку из файла
// значение функции — количество прочитанных символов
int GetString (int f, AnsiString *st)
{
unsigned char buf[300]; // строка (буфер)
unsigned char *p = buf ; // указатель на строку
246 _ Часть II, Практикум программирования
int n; // кол-во прочитанных байт (значение функции FileRead)
int len =0; // длина строки
n = FileRead(f, p, 1) ;
while ( n != 0)
{
if ( «p == ‘\r’)
{
n = FileRead(f, p, 1); // прочитать ‘\n’break;
P++;n = FileRead ( f , p, 1 )
*p = ‘\0’;
if ( len !=0)
st->printf («%s», buf)
return len;
// читает из файла целое число
int Getlnttint f)
{char buf [20]; // строка (буфер)char *p = buf; // указатель на строку
int n; // кол-во прочитанных байт (значение функции FileRead)int a; // число, прочитанное из файла
n = FileRead (f, p, 1) ;
while ( (*p >= ‘0’) && (*p <= ‘9’) && (n > 0) )
n = FileRead(f, p, 1);
}
if ( *p == ‘\r’)
n = FileRead(f, p, 1); // прочитать ‘\n’
*p = ‘\0’;
// изображение числа в буфере, преобразуем строку в целое
sscanf(buf,»%i», Sa);
return a;
Глава 10. Примеры программ 247
Как было сказано ранее, объявление массива компонентов не создает ком-поненты, а только устанавливает факт их существования. Создает и на-страивает КОМПОНеНТЫ RadioButton КОНСТруКТОр форМЫ (фуНКЦИЯ TForml: :TFormi). Непосредственное создание компонента (элемента массива) выпол-няет оператор .
RadioButton[i] = new TRadioButton(Forml)
Следующие за этим оператором инструкции обеспечивают настройку ком-понента. В том числе, они путем присваивания значения свойству onclickзадают функцию обработки события click. В рассматриваемой программедля обработки события click на всех компонентах RadioButton используетсяодна и та же функция, которая путем опроса значения свойства checkedфиксирует номер выбранного ответа и делает доступной кнопку Дальше(Buttonl).
После запуска программы и вывода на экран стартовой формы происходитсобытие onActivate. Функция обработки этого события проверяет, указан лив командной строке параметр — имя файла теста. Реализация программыпредполагает, что если имя файла теста задано без указания пути доступа кнему, то файл теста и файлы с иллюстрациями находятся в том же каталоге,что и программа тестирования. Если же путь доступа указан, то файлыс иллюстрациями должны находиться в том же каталоге, что и файл теста.Такой подход позволяет сгруппировать все файлы одного теста в одном ка-талоге.
Если файл теста задан, функция открывает его, читает название теста ивводную информацию и затем выводит их в диалоговое окно, причем на-звание выводится в заголовок, а вводная информация — в поле Label 1.
Непосредственное чтение строк из файла выполняет функция Getstring.Значением функции является длина строки. Следует обратить внимание наТО, ЧТО фуНКЦИЯ GetString Возвращает СТрОКу AnsiString.
После того как прочитана общая информация о тесте, программа считываетиз файла теста информацию об уровнях оценки и фиксирует ее в массивахlevel и mes. Критерий достижения уровня (количество правильных ответов)считывает функция Getint.
После вывода информационного сообщения программа ждет, пока пользо-ватель не нажмет кнопку Ok (Buttonl).
Командная кнопка Buttonl используется:
П для завершения работы программы, если в командной строке не указанфайл теста;
П для активизации процесса тестирования (после вывода информационно-го сообщения);
248 Часть II. Практикум программирования
П для перехода к следующему вопросу (после выбора варианта ответа);
О для завершения работы программы (после вывода результата тестиро-вания).
Таким образом, реакция программы на нажатие кнопки Buttoni зависит отсостояния программы. Состояние программы фиксирует свойство Tag кноп-ки Buttoni.
После вывода информации о тесте значение свойства Tag кнопки Buttoniравно нулю. Поэтому в результате щелчка на кнопке Buttoni выполняетсята часть программы, которая обеспечивает вывод первого вопроса и заменунаходящегося на кнопке текста ОК на текст Дальше, и заменяет значениесвойства Tag на единицу.
В процессе тестирования значение свойства Tag кнопки Buttoni равно еди-нице. Поэтому функция обработки события click сравнивает номер вы-бранного ответа (увеличенный на единицу номер компонента RadioButton)с номером правильного ответа, увеличивает на единицу счетчик правильныхответов (в том случае, если выбран правильный ответ) и активизирует про-цесс чтения следующего вопроса. Если попытка чтения очередного вопросазавершилась неудачно (это значит, что вопросы исчерпаны), функция выво-дит результаты тестирования, заменяет текст на командной кнопке на ОК иподготавливает операцию завершения работы программы (свойству Tag при-сваивает значение 2).
Чтение вопроса (вопрос, информация о количестве альтернативных ответов,номер правильного ответа и признак наличия иллюстрации, а также имяфайла иллюстрации и альтернативные ответы) из файла теста выполняетФУНКЦИЯ GetVoproS.
Вывод вопроса, иллюстрации и альтернативных ответов выполняет функцияshowvopros. Сначала функция выводит вопрос — присваивает значениесвойству caption компонента Labeii. Затем, если к вопросу есть иллюстра-ция, функция вычисляет размер области, которую можно выделить для ото-бражения иллюстрации, и загружает иллюстрацию. Если размер иллюстра-ции больше размера области, функция устанавливает максимально возмож-ный размер компонента imagei и присваивает значение false свойствуAutoSize и true ~ свойству Proportional, обеспечивая тем самым масшта-бирование иллюстрации. После этого функция выводит альтернативные от-веты. Положение компонентов, обеспечивающих вывод альтернативных от-ветов, отсчитывается от нижней границы компонента image 1, если к вопро-су есть иллюстрация, или компонента Labeii, если иллюстрации нет.
Сразу после вывода вопроса кнопка Дальше (Buttoni) недоступна. Сделаноэто для того, чтобы блокировать возможность перехода к следующему во-просу, если не дан ответ на текущий. Доступной кнопку Дальше делаетфункция обработки события click на одном из компонентов RadioButton.
Глава 10. Примеры программ 249
Кроме того, функция путем сканирования (проверки значения свойстваchecked компонентов массива RadioButton) определяет, на каком из компо-нентов массива испытуемый сделал щелчок и, следовательно, какой из ва-риантов ответа выбран. Окончательная фиксация номера выбранного ответаи сравнение его с номером правильного ответа происходит в результате на-жатия кнопки Дальше.
Игра «Сапер»Всем, кто работает с операционной системой Windows, хорошо знакомаигра «Сапер». В этом разделе рассматривается аналогичная программа.
Пример окна программы в конце игры (после того, как игрок открыл клет-ку, в которой находится мина) приведен на рис. 10.7.
Новая игра ?
1
1&1
1
1
1
1
1
2
«Ь
1
1
1
2
**,
1
1
1
Б-Р»I
£2
г~Г»1
1
в
+
2
«4к
|
1
«А*
А
1
Эту клеткусапер открыл
Ошибка! В клеткемины нет
Эти клетки саперне успел открыть
Рис. 10.7. Окно программы «Сапер»
Правила игры и представление данныхИгровое поле состоит из клеток, в каждой из которых может быть мина.Задача игрока — найти все мины и пометить их флажками.
250 Часть II, Практикум программирования
Используя кнопки мыши, игрок может открыть клетку или поставить в неефлажок, указав тем самым, что в клетке находится мина. Клетка открывает-ся щелчком левой кнопки мыши, флажок ставится щелчком правой. Еслив клетке, которую открыл игрок, есть мина, то происходит взрыв (саперошибся, а он, как известно, ошибается только один раз) и игра заканчива-ется. Если в клетке мины нет, то в этой клетке появляется число, соответст-вующее количеству мин, находящихся в соседних клетках. Анализируя ин-формацию о количестве мин в клетках, соседних с уже открытыми, игрокможет обнаружить и пометить флажками все мины. Ограничений на коли-чество клеток, помеченных флажками, нет. Однако для завершения игры(для выигрыша) флажки должны быть установлены только в тех клетках,в которых есть мины. Ошибочно установленный флажок можно убрать,щелкнув правой кнопкой мыши в клетке, в которой он находится.
В программе игровое поле представлено массивом N+2 на М+2, где NxM -размер игрового поля. Элементы массива с номерами строк от 1 до jV иномерами столбцов от 1 до М соответствуют клеткам игрового поля(рис. 10.8); первые и последние столбцы и строки соответствуют границеигрового поля.
012
NЛ/-Н
U 1 ^ … IVI IVI-r
*-
1″
«-*
-*
Рис. 10.8. Клетке игрового поля соответствует элемент массива
В начале игры каждый элемент массива, соответствующий клеткам игровогополя, может содержать число от 0 до 9. Ноль соответствует пустой клетке,рядом с которой нет мин. Клеткам, в которых нет мин, но рядом с которы-ми мины есть, соответствуют числа от 1 до 8. Элементы массива, соответст-вующие клеткам, в которых находятся мины, имеют значение 9, а элементымассива, соответствующие границе поля, содержат —3.
В качестве примера на рис. 10.9 изображен массив, соответствующий со-стоянию поля в начале игры.
В процессе игры состояние игрового поля меняется (игрок открывает клет-ки и ставит флажки, и, соответственно, меняются значения элементов мас-сива. Если игрок поставил в клетку флажок, то значение соответствующего
Глава 10. Примеры программ 251
элемента массива увеличивается на 100. Например, если флажок поставленправильно, т. е. в клетку, в которой есть мина, значение соответствующегоэлемента массива станет равным 109. Если флажок поставлен ошибочно(например, в пустую клетку), элемент массива будет содержать число 100.Если игрок открыл клетку, значение элемента массива увеличиваетсяна 200. Такой способ кодирования позволяет сохранить информацию обисходном состоянии клетки.
-3
-3
-3
-3
-3
_з
-3
-3
-3
-3
-3
-3
-3
9
1
111
0
0
0
0
0
-3
-3
1
1
2
9
2
0
1
2
2
1
-3
-3
0
0
2
9
2
0
2
9
9
1
-3
-3
0
0
1
11
0
2
9
3
1
-3
—3
0
0
0
0
0
0
1
1
1
0
-3
-3
0
0
0
0
0
0
0
0
0
0
-3
-3
0
0
0
0
0
0
0
0
0
0
-3
-3
0
0
1
2
2
2
1
1
0
0
-3
-3
0
0
1
9
9
3
9
1
0
0
-3
-3
0
0
1
2
3
9
2
1
0
0
-3
-3
-3
-3
-3
-3
-3
-3
-3
-3
-3
-3
-3
Рис. 10.9. Массив в начале игры
Форма приложенияГлавная (стартовая) форма ифы «Сапер» приведена на рис. 10.10.
MainMenul —
Новая игра ?
Рис. 10.10. Главная форма программы «Сапер»
252 _ Часть II. Практикум программирования
Следует обратить внимание на то, что размер формы не соответствует раз-меру игрового поля. Нужный размер формы будет установлен во время ра-боты программы. Делает это функция обработки события OnFormActivate,которая на основе информации о размере игрового поля (количестве клетокпо вертикали и горизонтали) и размере клеток устанавливает значениясвойств ciientHeight и clientwidth, определяющие размер клиентской об-ласти главного окна программы.
Главное окно программы содержит компонент MainMenui, который пред-ставляет собой главное меню программы. Значок компонента MainMenu на-ходится на вкладке Standard (рис. 10.11).
[! ^ pi IT % А [Ж й] ей I* ® ffl Я С] Ш С.’] J3
MainMenu
Рис. 10.1.1. Компонент MainMenu
Значок компонента MainMenu можно поместить в любое место формы, т. к.во время работы программы он не виден. Пункты меню появляются в верх-ней части формы в результате настройки компонента. Для настройки менюиспользуется редактор меню, который запускается двойным щелчком левойкнопкой мыши на значке компонента или путем выбора из контекстногоменю компонента команды Menu Designer. В начале работы над новым ме-ню, сразу после добавления компонента к форме, в окне редактора нахо-дится один-единственный прямоугольник — заготовка пункта меню. Чтобыпревратить эту заготовку в меню, нужно в поле Caption окна Object Inspectorввести название меню.
Если перед какой-либо буквой в названии меню ввести знак &, то во времяработы программы можно будет активизировать этот пункт меню путем на-жатия комбинации клавиши <Alt> и клавиши, соответствующей символу,перед которым стоит знак &. В названии меню эта буква будет подчеркнута.
Чтобы добавить в главное меню элемент, нужно в окне редактора меню вы-брать последний (пустой) элемент меню и ввести название нового пункта.
Чтобы добавить в меню команду, нужно выбрать тот пункт меню, в кото-рый надо добавить команду, переместить указатель активного элемента ме-ню в конец списка команд меню и ввести название команды.
На рис. 10.12 приведено окно редактора меню, в котором находится менюпрограммы «Сапер».
.После того как будет сформирована структура меню, нужно, используя окноObject Inspector, выполнить настройку элементов меню (выбрать настраи-ваемый пункт меню можно в окне формы приложения или из списка объ-ектов в верхней части окна Object Inspector). Каждый элемент меню (пунк-
Глава 10. Примеры программ 253
ты и команды) — это объект типа TMenuitem. Свойства объектов TMenuitem(табл. 10.3) определяют вид меню во время работы программы.
Рис. 10.12. Структура меню программы «Сапер»
Таблица 10.3. Свойства объекта TMenuitem
Свойство Определяет
Name Имя элемента меню. Используется для доступа к свойствам
Caption Название меню или команды
Bitmap Значок, который отображается слева от названия элемента меню
Enabled Признак доступности элемента меню. Если значение свойстваравно false, то элемент меню недоступен, при этом названиеменю отображается серым цветом
При выборе во время работы программы элемента меню происходит собы-тие Click. Чтобы создать процедуру обработки этого события, нужно в окнеформы выбрать пункт меню и щелкнуть левой кнопкой мыши — C++ Buil-der создаст шаблон процедуры обработки этого события. В качестве приме-ра ниже приведена функция обработки события click, которое возникаетв результате выбора из меню ? команды Справка. N3 — это имя элементаменю, соответствующего этой команде.
// выбор в меню «?» команды Справка
void fastcall TForml::N3Click(TObject *Sender)
WinHelp(Forml->Handle,»saper.hip»,HELP_CONTEXT,I);
Игровое полеНа разных этапах игры игровое поле выглядит по-разному. Вначале полепросто разделено на клетки. Во время игры, в результате щелчка правойкнопкой мыши, в клетке появляется флажок. Щелчок левой кнопкой тоже
254 _ Часть II. Практикум программирования
меняет вид клетки: клетка меняет цвет и в ней появляется цифра или мина(игра на этом заканчивается). Рассмотрим объекты, свойства и методы,обеспечивающие работу с графикой.
Начало игрыВ начале игры надо расставить мины и для каждой клетки поля подсчитать,сколько мин находится в соседних клетках. Функция NewGame (ее текст при-веден в листинге 10.3), решает эту задачу.
| Листинг 10.3. Функция NewGame
// новая игра — генерирует новое полеvoid _ f astcall NewGame ( )
< ‘// Очистим элементы массива, соответствующие отображаемым
// клеткам, а в неотображаемые, по границе игрового поля,
// запишем число -3. Уникальное значение клеток границы
// используется функцией Open для завершения рекурсивного
// процесса открытия соседних пустых клеток.
int row, col;
for (row=0; row <= MR+1; row++)
for (col=0; col <= MC+1; col++)
Pole [row] [col] = -3;
for (row=l; row <= MR; row++)
for (col=l; col <= MC; col++)
Pole [row] [col] = 0;
// расставим мины
time_t t; // используется генератором случайных чисел (ГСЧ)
srand( (unsigned) time (&t) } ; // инициализация ГСЧ
int n = 0; // количество мин
do
{
row = randO % MR +1;
col = rand() % MC +1;
if ( Pole [row] [col] != 9)
{
Pole [row] [col] = 9;
while ( n < 10) ;
Глава 10. Примеры программ 255
// вычисление количества мин в соседних клеткахint k;
for ( row =1; row <= MR; row++)
for ( col = 1; col <= MC; col++)
if ( Pole[row][col] != 9) {
k =0;
if ( Pole[row-1][col-1] == 9) k++;
if ( Pole[row-1][col] == 9) k++;
if ( Pole[row-1][col+1] == 9) k++;
if ( Pole[row][col-1] = 9)
if ( Pole[row][col+1] == 9)
if ( Pole[row+1][col-1] == 9)
if ( Pole[row+1][col] == 9)
if ( Pole[row+1][col+1] == 9)
}
status = 0;
nMin = 0;
nFlag = 0;
Pole[row][col] = k;
// начало игры
// нет обнаруженных мин
// нет флагов
После того как функция NewGame расставит мины, функция ShowPole (еетекст приведен в листинге 10.4) выводит изображение игрового поля.
I Листинг 10.4. Функция ShowPole
// показывает полеvoid fastcall TForml::ShowPole( int status)
{for ( int row = 1; row <= MR; row++)
for ( int col = 1; col <= MC; col++)
Kletka(row, col, status);
Функция ShowPole выводит изображение поля последовательно, клетка заклеткой. Вывод изображения отдельной клетки выполняет функция Kletka,ее текст приведен в листинге 10.5. Функция Kletka используется для выводаизображения поля в начале игры, во время игры и в ее конце. В начале иг-ры (значение параметра status равно нулю) функция выводит только кон-тур клетки, во время игры — количество мин в соседних клетках или фла-жок, а в конце она отображает исходное состояние клетки и действия поль-зователя. Информацию о фазе игры функция Kletka получает черезпараметр status.
256 Часть II. Практикум программирования
I Листинг 10.5. Функция Kletka
// рисует на экране клетку
void _ fastcall TForml :: Kletka (int row, int col, int status)
{
int x = LEFT + (col-1)* W;
int у = TOP + (row-1)* H;
if (status ==0) // начало игры
{
// клетка — серый квадрат
Canvas->Brush->Color = clLtGray;
Canvas->Rectangle (x-1 , y-1 , x+W, y+H) ;
return;
// во время (status = 1) и в конце (status = 2} игры
if ( Pole [row] [col] < 100)
{
// клетка не открытаCanvas->Brush->Color = clLtGray; // не открытые — серые
Canvas->Rectangle (x-1, y-1, x+W, y+H) ;
if (status == 2 && Pole [row] [col] == 9)
Mina ( x, y) ; // игра закончена, показать мину
return;
// клетка открыта
Canvas->Brush->Color = clWhite; // открытые белые
Canvas->Rectangle (x-1, y-1, x+W, y+H) ;
if ( Pole [row] [col] == 100) return; // клетка пустая
if ( Pole [row] [col] >= 101 && Pole [row] [col] <= 108)
{
Canvas->Font->Size = 14;
Canvas->Font->Color = clBlue;
Canvas->TextOutA(x+3,y+2, IntToStr( Pole [row] [col] -100))
return;
}
if ( Pole [row] [col] >= 200)
Flag(x, y) ;
if (Pole [row] [col] == 109) // на этой мине подорвались!
Глава 10. Примеры программ 257
Canvas->Brush->Color = clRed;
Canvas->Rectangle(x,y,x+W,y+H);
»if (( Pole[row][col] % 10 == 9) && (status == 2))
Mina( x, y);
Игра
Во время игры программа воспринимает нажатия кнопок мыши и, в соот-ветствии с правилами игры, открывает клетки или ставит в клетки флажки.
Основную работу выполняет функция обработки события OnMouseDown (еетекст приведен в листинге 10.6). Функция получает координаты точки фор-мы, в которой игрок щелкнул кнопкой мыши, а также информацию о том,какая кнопка была нажата. Сначала функция преобразует координаты точ-ки, в которой игрок нажал кнопку мыши, в координаты клетки игровогополя. Затем она вносит необходимые изменения в массив Pole и, если на-жата правая кнопка, вызывает функцию Flag, которая рисует в клетке фла-жок. Если нажата левая кнопка в клетке, в которой нет мины, то эта клеткаоткрывается, и на экране появляется ее содержимое. Если нажата леваякнопка в клетке, в которой есть мина, то вызывается функция showPoie,которая показывает все мины, в том числе и те, которые игрок не успелнайти.
: ;— — • • «» -:—»•»: » Т» :•• •• • • • •• «•» -|
i Листинг 10.6. Обработка события OnMouseDown на поверхности игрового поля i
// нажатие кнопки мыши на игровом поле
void fastcall TForml::FormMouseDown(TObject *Sender, TMouseButton
Button,
TShiftState Shift, int x, int y)
<
if ( status == 2) return;•
if ( status == 0) status = 1;
x -= LEFT;
у -= TOP;
if (x > 0 && у > 0)
{
// преобразуем координаты мыши
// в индексы клетки поля
int row = y/H + 1;
int col = x/W + 1;
9 Зак. 1252
258 Часть II. Практикум программирования
if (Button == iribLeft)
if ( Pole[row][col] == 9)
Pole[row][col] +=100;status = 2 ; // игра закончена
ShowPole(status);
else if ( Pole[row][col] < 9)i
Open(row,col);
ShowPole(status);
}
}
else if (Button = mbRight)
nFlag++;
if ( Pole[row][col] == 9)
nMin++;
Pole[row][col] += 200; // поставили флаг
if (nMin == NM && nFlag == MM)
status = 2; // игра закончена
ShowPole(status);
else Kletka(row, col, status);
}
Функция Flag (листинг 10.7) рисует флажок. Флажок (рис. 10.13) состоит и:четырех примитивов: линии (древко), замкнутого контура (флаг) и ломанойлинии (буква «М»). Функция Flag рисует флажок, используя метод базовоеточки, т. е. координаты всех точек, определяющих положение элементе!рисунка, отсчитываются от базовой точки.
Функция Mina (листинг 10.8) рисует мину. Мина (рис. 10.14) состоит ивосьми примитивов: два прямоугольника и сектор образуют корпус миныостальные элементы рисунка — линии («усы» и полоски на корпусе).
Обеим функциям в качестве параметров передаются координаты базовоточки рисунка и указатель на объект, на поверхности которого надо рисовать.
Глава 10. Примеры программ 259
(х+8,у+12) (х+30,у+12)
(х+4,у+4)
(х+4,У+Ю) _Г
(х+4,у+14)
(х+4,у+20)
(х+4,у+36)
Рис. 10.13. Флажок
(х+16,у+26)
(х+8,у+30)
(х+6,у+36)
\/
01
\V
•J
/L Ц—ы« ч
— -_i_L..
(х+24,у+26)
(х+30,у+32)
(х+6,у+36)
Рис. 10.14. Мина
I Листинг 10.7. Функция Flag рисует флажок
// рисует флагvoid fastcall TForml::Flag( int x, int y)
TPoint p[4]; // координаты флажка и нижней точки древка
// точки флажка
р[0].х=х+4; р[0].у=у+4;
260 Часть II. Практикум программирования
р[1].х=х+30; р[1].у=у+12;р[2].х=х+4; р[2].у=у+20;
// установим цвет кисти и карандаша
Canvas->Brush->Color = clRed;
Canvas->Pen->Color = clRed; // чтобы контур флажка был красный
Canvas->Polygon(р, 2); // флажок
// древко
Canvas->Pen->Color = clBlaek;
Canvas->MoveTo(p[0].x, p[0].y);
Canvas->LineTo(x+4, у+Зб) ;
•TPoint m[5]; // буква М
т[0].х=х+8; т[0].у=у+14;
т[1].х=х+8; т[1].у=у+8;
т[2].х=х+10; т[2].у=у+10;
т[3].х=х+12; т[3].у=у+8;
т[4].х=х+12; т[4].у=у+14;
Canvas->Pen->Color = clWhite;
Canvas->Polyline(m, 4);
Canvas->Pen->Color = clBlaek;
Листинг 10.8. Функция Mina рисует мину
// рисует минуvoid fastcall TForml::Mina(int x, int y)
f
Canvas->Brush->Color = clGreen;
Canvas->Pen->Color = clBlaek;
// корпус
Canvas->Rectangle(x+16,y+26,x+24,y+30);
Canvas->Rectangle(x+8,y+30,x+32,y+34);
Canvas->Pie(x+6,y+28,x+34,y+44,x+34,y+36,x+6,y+36);
// полоса на корпусе
Canvas->MoveTo(x+12,y+32); Canvas->LineTo(x+28,y+32);
// основание
Canvas->MoveTo(x+8,y+36); Canvas->LineTo(x+32,y+36);
// вертикальный «ус»
Canvas->MoveTo(x+20,y+22); Canvas->LineTo(x+20,y+26);
Глава 10. Примеры программ 261
// боковые «усы»
Canvas->MoveTo(x+8, у+30); Canvas->LineTo(х+6,у+28);Canvas->MoveTo(x+32,y+30); Canvas-XLineTo(х+34,у+28);
Справочная информацияВ результате выбора в меню ? команды Справка или нажатия клавиши <F1>должна появляться справочная информация — правила ифы (рис. 10.15).
Файл Правка Закладка Параметры ^правка
Садержание Печать
СаперИгра Сапер является аналогом игры Сапер,входящей в состав Microsoft Windows.
ПравилаИгровое поле состоит из клеток, в каждой изкоторых может быть мина. Задача игрока -найти все мины и пометить их флажками.Используя кнопки мыши, игрок может открытьклетку или поставить в нее флажок, указавтем самым, что в клетке находится мина.Клетка открывается щелчком левой кнопкимыши, флажок ставится щелчком правой.Если в клетке, которую открыл игрок, естьмина, то происходит взрыв (сапер ошибся, аон, как известно, ошибается только один раз),и игра заканчивается. Если в клетке минынет, то в этой клетке появляется число,соответствующее количеству мин,находящихся в соседних клетках. Анализируяинформацию о количестве мин в клетках,
Рис. 10.15. Окно справочной системы программы «Сапер»
Для того чтобы во время работы программы пользователь, нажав кла-вишу <F1>, мог получить справочную информацию, свойствам HeipFileи HeipContext главной формы надо присвоить значения, указанные втабл. 10.4.
Таблица ЮЛ. Значения свойств главной формы
Свойство
HeipFile
HeipContext
Значение
saper.hlp
1
Пояснение
Файл справки
Идентификатор раздела, содержимое которогоотображается в результате нажатия <F1>
262 Часть II. Практикум программирования
Для того чтобы справочная информация появилась на экране в результатевыбора в меню ? команды Справка, надо создать функцию обработки собы-тия Onclick для соответствующей команды меню. Процесс создания функ-ции обработки события для команды меню ничем не отличается от процес-са создания функции обработки события для элемента управления, напри-мер, для командной кнопки: в списке объектов надо выбрать объект типаTMenuitem, для которого создается функция обработки события, а во вкладкеEvents — событие.
Ниже приведена функция обработки события Onclick для команды Справкаменю ?.
// выбор в меню ? команды Справка
void _ fastcall TForml: :N3Click (TObject Sender)
WinHelp(Forml->Handle,»saper.hlp»,HELP_CONTEXT,l) ;
)I
Вывод справочной информации выполняет функция winHelp, которой в ка-честве параметра передается идентификатор окна программы, котораязапрашивает вывод справочной информации, файл справки, константуHELP_CONTEXT и идентификатор раздела, содержимое которого должно бытьотражено.
Информация о программеПри выборе из меню ? команды О программе на экране должно появитьсяодноименное окно (рис. 10.16).
О программе
Программа демонстрирует работа с графикой,массивами и использование рекурсии.
Текст программы можно найти в книге:
Культин Н.Б.Самоучитель C++ Builder.-СПб.: БХВ-Петербург. £003.
.bhv. шffismt
OK
Рис. 10.16. Выбрав ссылку, можно активизировать браузери перейти на страницу издательства «БХВ-Петербург»
Чтобы программа во время своей работы могла вывести на экран окно, отличное от главного (стартового), нужно добавить в проект форму. Делаетеэто выбором из меню File команды New form. В результате выполнени
Глава 10. Примеры программ 263
команды New form в проект добавляется новая форма и соответствующий еймодуль.
Если в проекте несколько форм, то для того чтобы получить доступ к нуж-ной форме и, соответственно, к модулю, надо выбрать имя нужной формы всписке диалогового окна View Form (рис. 10.17), которое становится доступ-ным в результате щелчка на командной кнопке View Form (рис. 10.18) илинажатия комбинации клавиш <Shift>+<F12>.
Рис. 10.17. Выбрать нужную форму можно в списке окна View Form
ш»Я-
j View Form (Shifl+F12)|
Рис. 10.18. Командная кнопка View Form
Вид формы AboutForm после добавления необходимых компонентов приве-ден на рис. 10.19, значения ее свойств — в табл. 10.5.
Таблица 10.5. Значения свойств формы О программе
Свойство Значение
Name
Caption
BorderStyle
Borderlcons.biSystemMenu
AboutForm
О программе
bsSingle
false
264 Часть II. Практикум программирования
Таблица 10.5 (окончание)
Свойство Значение
Borderlcons.biMininize
Borderlcons.biMaximize
false
false
• Программа демонстрирует работу с графикой,’. массивами и использование рекурсии.
. Текст программы можно найти в книге: — • •
Культин Н.Б.• Самоучитель C++ Builder.: -СПб.: БХВ-Петербург. 2003. :
OK
Рис. 10.19. Форма О программе
Вывод окна О программе выполняет функция обработки события click, ко-торое происходит в результате выбора из меню ? команды О программе(листинг 10.9). Непосредственно вывод окна выполняет метод showModai,который выводит окно как модальный диалог. Модальный диалог перехваты-вает все события, адресованные другим окнам приложения, в том числе иглавному. Таким образом, пока модальный диалог находится на экране,продолжить работу с приложением, которое вывело модальный диалог,нельзя.
Листинг 10.9. Вывод окна О программе
void _ fastcall TForml : :N4Click (TObject *Sender)
// «привяжем» окно О программе к главному окну приложения
AboutForm->Top = Forml->Top + Forml->Height/2 — AboutForm->Height/2;
AboutForm->Left = Forml->Left + Forml->Width/2 — AboutForm->Width/2;
AboutForm->ShowModal ( ) ;
Если не предпринимать никаких усилий, то окно О программе появится втой точке экрана, в которой находилась форма во время ее разработки.Вместе с тем, можно «привязать» это окно к главному окну программы так,чтобы оно появлялось в центре главного окна. Привязка осуществляется наосновании информации о текущем положении главного окна программы(свойства тор и Left) и о размере окна О программе.
Глава 10. Примеры программ 265
На поверхности формы О программе есть ссылка на сайт издательства»БХВ-Петербург». Предполагается, что в результате щелчка на ссылке в ок-не браузера будет открыта указанная страница. Для того чтобы это про-изошло, надо создать функцию обработки события onclick для компонентаLabels. Значения свойств компонента Labels приведены в табл. 10.6, а текстфункции обработки события — в листинге 10.10.
Таблица 10.6. Значения свойств компонента Labels
Свойство Значение Комментарий
Font. Color clBlue Цвет —синий
Font.Style.Underline true Подчеркивание
Cursor crHandPoint При позиционировании указателя мышина текст указатель принимает формуруки
Для запуска браузера использована функция sheilExecute, которая открыва-ет указанный файл при помощи программы, предназначенной для работыс файлами указанного типа. Так как имя файла в данном случае представ-ляет собой URL-адрес, то будет запущен браузер (тот, который установленна компьютере пользователя).
Наиболее просто передать URL-адрес в функцию SheilExecute можно какстроку-константу, например:
SheilExecute(AboutForm->Handle, «open», «http:\\\\www.bhv.ru»,NULL, NULL, SW_RESTORE);
Но лучше URL-адрес брать из поля метки. В функцию sheiiExute надо пе-редать указатель на обычную строку, т. е. завершающуюся нулевым симво-лом. Однако свойство caption — это Ansistring. Преобразование строкиAnsi В указатель на null terminated string ВЫПОЛНЯСТ МеТОД c_str() .
• ‘ • «‘»» ‘ ‘;{Листинг 10.10. Щелчок в поле URL
void fastcall TAboutForm::LabelSClick(TObject *Sender)
{
/* наиболее просто передать в функцию SheilExecuteстроку-константу (URL-адрес) так, как показано ниже:
SheilExecute (AboutForm->Handle,»open»,»http:\\\\www.bhv.ru»,NULL, NULL)
266 _ Часть II. Практикум программирована
Лучше URL-адрес брать из поля метки.
В функцию ShellExecute надо передать указатель на
null terminated— строку, но свойство Caption — это AnsiString.
Преобразование Ansi -строки в char* выполняет метод c_str()
*/\
// открыть файл, имя которого находится в поле LabelS
ShellExecute (AboutForm->Handle, «open»,Label5->Caption.c str () ,
NULL, NULL, SW_RESTORE) ;
Окно О программе закрывается в результате щелчка на кнопке ОК. Функ
ция обработки этого события приведена ниже.
void _ fastcall TAboutForm: :ButtonlClick(TObject *Sender)
{
ModalResult = mrOk; // убрать окно О программе
Текст программыПолный текст профаммы «Сапер» приведен ниже: в листингах 10.11 и 10.12 —
заголовочный файл и модуль главной формы; в листинге 10.13 — модульформы О программе.
; Листинг 10.11. Заголовочный файл главной формы (saper_.h)
#ifndef saper_H
#define saper_H
#include <Classes.hpp>
#include <Controls.hpp>
linclude <StdCtrls.hpp>
#include <Forms.hpp>
^include <ExtCtrls.hpp>
# include <Menus . hpp>
class TForml : public TForm
{
__publ i shed :
TMainMenu *MainMenul;
// команды главного меню
TMenuItem *N1; // Новая игра
TMenuItem *N2; // команда «?»
Глава 10. Примеры программ _ _ 267
// команды меню «?»
TMenuItem *N3; // Справка
TMenuItem *N4; // О программе
void _ fastcall FormMouseDown (TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y) ;
void _ fastcall FormPaint (TObject *Sender);
void _ fastcall FormCreate (TObject *Sender) ;
// выбор команды в меню
void _ fastcall NlClick (TObject *Sender) ; // Новая игра
void __fastcall N3Click (TObject *Sender) ; // Справка
void _ fastcall N4Click (TObject *Sender) ; // О программе
private :
void _ fastcall ShowPole (int status); // отображает поле
// отображает содержимое клетки
void _ fastcall Kletka (int row, int col, int status) ;
void _ fastcall Mina (int x, int y) ; // рисует мину
void __fastcall Flag( int x, int y) ; // рисует флаг
public :
_ fastcall TForml (TComponent* Owner);
extern PACKAGE TForml *Forral;
#endif
! ……….. ••-••••• …………… ‘ ……………… ••:•••- ………………………. — ………………. » …………. ‘ ……………… ••-••• ……… » ……. •••»••i Листинг 10.12. Модуль главной формы (saper_.cpp)
/*Игра «Сапер». Демонстрирует работу с графикой,
использование рекурсии, доступ к файлу справочной
информации.
*/# include <vcl.h>
ttinclude <stdlib.h> // для доступа к ГСЧ
#include <time.h>
^include <stdio.h>
#pragma hdrstop
#include «saper_.h»
#include «saper_2.cpp»
268 _ Часть II. Практикум программирования
ttpragma package (smart_init)
ttpragma resource «*.dfm»
TForml *Forml; // главное окно
_ fastcall TForml: : TForml (TComponent* Owner)
: TForm (Owner)
#define MR 10 .// кол-во клеток по вертикали
#define MC 10 // кол-во клеток по горизонтали
Idefine NM 10 // кол-во мин
int Pole[MR+2] [MC+2]; // минное поле
// 0. .8 — количество мин в соседних клетках
// 9 — в клетке мина
// 100.. 109 — клетка открыта
// 200.. 209 — в клетку поставлен флаг
int nMin; // кол-во найденных мин
int nFlag; // кол-во поставленных флагов
int status =0; //0 — начало игры; 1 — игра; 2 — результат
// смещение игрового поля относительно левого верхнего угла
// поверхности формы
ttdefine LEFT 0 // по X
fdefine ТОР 1 // по Y
Idefine W 40 // ширина клетки поля
Idefine H 40 // высота клетки поля
void _ fastcall NewGameO ; // новая игра — «разбрасывает» мины
void _ fastcall Open (int row, int col); /* открывает текущую и соседние
пустые клетки */
// нажатие кнопки мыши на игровом поле
void _ fastcall TForml :: FormMouseDown (TObject *Sender, TMouseButton
Button,
TShiftState Shift, int x, int y)
(
if ( status == 2) return;
if ( status == 0) status = 1,-
x -= LEFT;
у -= TOP;
Глава 10. Примеры программ 269
if (х > 0 & & у > 0)
{
// преобразуем координаты мыши
// в индексы клетки поля
int row = y/H + 1;
int col = x/W + 1;
if (Button == mbLeft)
{
if ( Pole[row][col] == 9)
{
Pole[row][col] +=100;
status = 2; // игра закончена
ShowPole(status);
}
else if ( Pole[row][col] < 9)
{
Open(row,col);
ShowPole(status);,
}
else if (Button == mbRight)
{
nFlag++;
if ( Pole[row][col] == 9)
nMin++;
Pole[row][col] += 200; // поставили флаг
if (nMin == NM && nFlag == NM)
{
status =2; // игра закончена
ShowPole(status);
)
else Kletkafrow, col, status);
// Функция обработки события OnCreate обычно используется .
// для инициализации глобальных переменных
void fastcall TForml::FormCreate(TObject *Sender)
{
// В неотображаемые эл-ты массива, которые соответствуют
// клеткам по границе игрового поля, запишем число -3.
Ч
270 _ Часть //. Практикум программирования
// Это значение используется функцией Open для завершения
// рекурсивного процесса открытия соседних пустых клеток.
for ( int row=0; row <= MR+1; row++)
for ( int col=0; col <= MC+1; col++)
Pole [row] [col] = -3;
NewGameO; // «разбросать» мины
Forml->ClientWidth = W*MC;
Forml->ClientHeight = H*MR+TOP+1;
// Вывод поля как результат обработки события Paint
// позволяет проводить любые манипуляции с формой
// во время работы программыvoid _ fastcall TForral: : FormPaint (TObject *Sender)
{ShowPole( status) ;
// Показывает полеvoid _ fastcall TForml : : ShowPole ( int status)
{for ( int row = 1; row <= MR; row++)
for ( int col = 1; col <= MC; col++)
Kletka(row, col, status);
// рисует на экране клеткуvoid _ fasteall TForml: :Kletka (int row, int col, int status)
{int x = LEFT + (col-1)* W;
int у = TOP + (row-1)* H;
if (status ==0) // начало игры
(// клетка — серый квадрат
Canvas->Brush->Color = clLtGray;
Canvas->Rectangle (x-1, y-l,x+W,y+H) ;return;
// во время (status = 1) и в конце (status = 2) игрif ( Pole [row] [col] < 100)
{// клетка не открыта
Canvas->Brush->Color = clLtGray; // не открытые — серые
Глава 10. Примеры программ _ 27 1
Canvas->Rectangle(x-l,y-l,x+W,y+H) ;if (status == 2 && Poletrow] [col] == 9)
Mina ( x, y) ; // игра закончена, показать минуreturn;
// клетка открыта
Canvas->Brush~>Color = clWhite; // открытые — белыеCanvas->Rectangle (x-l,y-l,x+W, y+H) ;
if ( Pole [row] [col] == 100) // клетка открыта, но она пустая
return;
if ( Poletrow] [col] >= 101 && Pole [row] [col] <= 108)
{Canvas->Font->Size = 14;
Canvas->Font->Color = clBlue;
Canvas->TextOutA(x+3,y+2, IntToStr (Poletrow] [col] -100) ) ;return;
if ( Poletrow] [col] >= 200)
Flag(x, y) ;
if (Poletrow] [col] == 109) // на этой мине подорвались!
(Canvas->Brush->Color = clRed;
Canvas->Rectangle (x,y,x+W,y+H) ;
if (( Poletrow] [col] % 10 == 9) && (status == 2))
Mina( x, y) ;
// рекурсивная функция открывает текущую и все соседние
// клетки, в которых нет мин
void fastcall Open(int row, int col)
{if (Pole[row][col] == 0)
{Pole[row][col] = 100;
// открываем клетки слева, справа, снизу и сверху
Open(row,col-1);
Open(row-1,col);
Open(row,col+1);
Open(row+1,col);
272 Часть II. Практикум программирования
// открываем примыкающие диагонально
Open(row-I,col-1);
Open(row-l,col+1);
Open(row+1,col-1);
Open(row+1,col+1);
else
// -3 — это граница игрового поля
if (Pole [row] [col] < 100 && Pole [row] [col] != -3)
Pole [row] [col] += 100;
// новая игра — генерирует новое поле
void _ f astcall NewGame ( )
{
// Очистим эл-ты массива, соответствующие отображаемым
// клеткам, а в неотображаемые (по границе игрового поля)
// запишем число -3. Уникальное значение клеток границы
// используется функцией Open для завершения рекурсивного
// процесса открытия соседних пустых клеток.
int row, col;
for (row=0; row <= MR+1; row++)
for (col=0; col <= MC+1; col++)
Pole [row] [col] = -3;
for (row=l; row <= MR; row++)
for (col=l; col <= MC; col++)
Pole [row] [col] = 0;
// расставим мины
time_t t; // используется ГСЧ
srand( (unsigned) time (&t) ) ; // инициализация ГСЧ
int n = 0; // кол-во мин
do
{
row = rand() % MR +1;
col = rand() % MC +1;
if ( Pole [row] [col] != 9)
{
Pole [row] [col] = 9;
while ( n < 10) ;
Глава 10. Примеры программ _ 273
// вычисление кол-ва мин в соседних клеткахint k;
for ( row = 1; row <= MR; row++)
for ( col = 1; col <= MC; col++)
if ( Pole [row] [col] != 9) {
k =0;
if ( Polefrow-1] [col-1] == 9) k++;
if ( Pole [row-1] [col] == 9) k++;
if ( Pole [ row-1 ] [col+1] == 9) k++;
if ( Pole [row] [col-1] == 9) k++;
if ( Pole [row] [col+1] == 9) k++;
if ( Pole [row+1] [col-1] == 9) k++;
if ( Pole [row+1] [col] = 9) k++;
if ( Pole [row+1] [col+1] == 9) k++;
Pole [row] [col] = k;
}
status =0; // начало игры
nMin =0; // нег обнаруженных мин
nFlag =0; // нет флагов
// рисует мину
void _ fastcall TForml: :Mina (int x, int y)
{
Canvas->Brush->Color = clGreen;
Canvas->Pen->Color = clBlack;
Canvas->Rectangle (x+16, y+26, x+24, y+30) ;
// корпус
Canvas->Rectangle (x+8 , y+30, x+32, y+34 ) ;
Canvas->Pie (x+6, y+28, x+34, y+44, x+34, y+36, x+6, y+36) ;
// полоса на корпусе
Canvas->MoveTo (x+12, y+32) ; Canvas->LineTo (x+28, y+32) ;
// основание
Canvas ->MoveTo (x+8, y+36) ; Canvas->LineTo (x+32, y+36) ;
// вертикальный «ус»
Canvas->MoveTo (x+20, y+22) ; Canvas->LineTo (x+20, y+26) ;
// боковые «усы»
Canvas->MoveTo(x+8, y+30); Canvas->LineTo (x+6, y+28) ;
Canvas ->MoveTo (x+32, y+30) ; Canvas->LineTo (x+34, y+28) ;
274 _ Часть II. Практикум программирования
// рисует флаг
void _ fastcall TForml : : Flag ( int x, int y)
{
TPoint p[4]; // координаты флажка и нижней точки древка
// точки флажка
р[0].х=х+4; р[0].у=у+4;
р[1].х=х+30; р[1].у=у+12;
р[2].х=х+4; р[2].у=у+20;
// установим цвет кисти и карандаша
Canvas->Brush->Color = clRed;
Canvas->Pen->Color = clRed; // чтобы контур флажка был красный
Canvas->Polygon(p, 2); // флажок
// древко
Canvas ->Pen->Color = clBlack;
Canvas->MoveTo(p[0] .x, p[0].y);
Canvas->LineTo(x+4,y+36) ;
TPoint m[5]; // буква М
m[0] .x=x+8; m[0] .y=y+14;
m[l].x=x+8; m[l] .y=y+8;
m[2] .x=x+10; m[2] .y=y+10;
m[3] .x=x+12; m[3].y=y+8;
m[4] .x=x+12; m[4].y=y+14;
Canvas->Pen->Color = clWhite;
Canvas->Polyline (m, 4) ;
Canvas->Pen->Color = clBlack;
// команда главного меню Новая игра
void _ fastcall TForml: :NlClick(TObject *Sender)
{
NewGame ( ) ;
ShowPole (status) ;
// выбор в меню «?» команды О программе
void _ fastcall TForml: :N4Click (TObject *Sender)
AboutForm-ХГор = Forml->Top + Forml->Height/2
— AboutForm->Height/2;
Глава 10. Примеры программ 275
AboutForm->Left = Forml->Left + Forml->Width/2
— AboutForm->Width/2;
AboutForm->ShowModal();
// выбор в меню «?» команды Справка
void fastcall TForml::N3Click(TObject *Sender)
WinHelp(Forml->Handle,»saper.hip»,HELP__CONTEXT,I);
I
{ Листинг 10.13. Модуль формы О программе (saper2_.cpp)
# include <vcl.h>
ttpragma hdrstop
finclude «saper_2.h»
#pragma package (smart_init)
tpragma resource «*.dfm»
TAboutForm *AboutForm;
_ fastcall TAboutForm: : TAboutForm (TComponent* Owner)
: TForm(Owner)
// Выбор URL-адресаvoid _fastcall TAboutForm: :Label5Click (TObject *Sender)
{/* В функцию ShellExute надо передать указатель на null terminated
строку (char*) . Свойство Caption — это AnsiString. Преобразование
Ansi -строки в указатель на nt -строку выполняет метод c_str()
*/
// открыть файл, имя которого находится в поле Labels
ShellExecute (AboutForm->Handle, «open»,Label5->Caption.c_str ( ) ,
NULL, NULL, SW_RESTORE) ;
// щелчок на кнопке OK
void __fastcall TAboutForm: :ButtonlClick (TObject *Sender)
(
ModalResult = mrOk;
276 Часть /I. Практикум программирования
Очистка дискаОткрыв каталог какого-либо проекта C++ Builder, можно увидеть, что по-мимо файлов, составляющих проект и используемых компилятором для ге-нерации выполняемого файла (bpr-, dfm-, h- и срр-файлы), в каталоге естьфайлы с расширением obj, tds и еще несколько файлов, расширение кото-рых начинается значком ~ (рис. 10.20).
(•Проверка знаний
j Файл Правка В_ид
| — Назад * •* — jf
j 4дрес jo Проверка знаний
^Поиск — Папки .^Журнал Ча X Si*
jj ^Переход
Проверка знаний
7 элементов выделено.
Общий размер файлов: 2,01 МБ
tester.tdstester_.~ddptester_.~dfmtester_,~htester, objtester_,objtester_.~cpp
Размер J Тип
jjsltester. bpr
8|itester_,dFmIjjytester.cpp
]JjUtester_,cppкедwpftester.exe
Peterburg.txtJij экономика, txt
lSAAK.BMP
Я tester.. ~ddpЯ tester ,~dfm
j»]tester_.ddp’ Пtester .h
ПВыделено объектов: 7
4КБ
1КБ
. 1 КБ
9КБ
34КБ
2КБ
2KB
59КБ
206КБ67КБ
9КБ
1 КБ
1КБ
2 КБ
1КБ
2КБ
13КБ
57КБ
1КБ
1 984 КБ
BCBProjectC++Builder Form
C++Builder Source …
C+-f-Builder Source …Приложение
Текстовый документТекстовый док/ментТочечный рисунок
Точечный рисунок
Точечный рисунокФайл»~СРР»Файл «~DDP»Файл «~DFM»
Файл «~Н»
Файл «DDP»Файл «Н»
Файл «OBJ»
Файл «OBJ»Файл»RES»Файл «TDS»
JJ
2,01 МБ I Мой компьютер
Рис. 10.20. Содержимое каталога проекта «Проверка знаний». Файлы, выделенные цветом,по окончании работы над проектом можно удалить
Файлы с расширением tds и obj создает компилятор в процессе генерациивыполняемого файла. Это временные файлы. По окончании работы надпроектом они не нужны, и их можно удалить, тем более что размер tds-файла может достигать нескольких мегабайт. Файлы, расширение которыхначинается значком ~, — это резервные копии соответствующих файловпроекта. По окончании работы над проектом их тоже можно удалить с диска.
Программа «Очистка диска» удаляет из текущего каталога и всех его подка-талогов файлы, которые по окончании работы над проектом не нужны
Глава 10. Примеры программ 277
(если удалить временные файлы проекта, работа над которым еще не за-вершена, то в процессе компиляции они будут созданы снова).
Окно программы «Очистка диска» в начале ее работы приведено нарис. 10.21. Для выбора каталога, который надо «почистить», используетсястандартное диалоговое окно Обзор папок, которое появляется в результатещелчка на кнопке Каталог.
@КПЯШВИИШШ1Программа удалит ненужные, созданные в процессе компиляциипроектов С-м-Builder, Файлы [obj, tds] и резервные копии («Ърг,»dim, «h, ~срр] из указанного каталога и его подкаталогов.
Кат ак пот Каталог…
Выберите каталог
fjjj Рабочий стол
£&»2у Мои документы
| Ж Диск 3,5 (А:); Й»О Локальный диск (С:); Ш~9 Локальный диск (D:): iil t3 Локальный диск (Е:)i Ш- S3 Локальный диск (F:): Ж Щ Компакт-диск (G:)
Ш 6ЁЕ Мое сетевое окружение
Отмена
Рис. 10.21. Окно программы «Очистка диска» в начале ее работы
Процесс активизации процесса очистки активизирует кнопка Выполнить,которая становится доступной только после того, как пользователь выбереткаталог. В процессе очистки диска программа выводит в поле Memo именаудаленных файлов.
Вид формы программы приведен на рис. 10.22. После того как компонентыбудут добавлены в форму, необходимо выполнить их настройку — задатьзначения свойств (табл. 10.7).
Текст программы «Очистка диска» приведен в листинге 10.14.
278 Часть II. Практикум программирования
Таблица 10.7. Настройка компонентов
Компонент Свойство Значение Комментарий
Forml
Forml
Button2
Memol
BorderStyle bsSingle Тонкая граница окна.Во время работы программынельзя изменить размер окна,захватив границу мышью
Borderlcins.biMaximize false Во время работы программыв заголовке окна нет кнопкиРазвернуть
Enabled
ScrollBars
false В начале работы программыкнопка Выполнить недоступ-на
ssVertical Есть вертикальная полосапрокрутки
П^Гочисткадйска
‘.-;
:
.
Программа удалит ненужные, созданные в процессе компиляции •проектов C++Builder, Файлы (obj, Ids) и резервные копии (~bpr, ;»dfm, ~h, ~cpp) из указанного каталога и его подкаталогов.
. : „ …, I (
<атаклог’ ‘ I • Каталог… Выполнить*!»
3
V
d
Friif!
~ Button2
Рис. 10.22. Форма программы «Очистка диска»
! Листинг 10.14. Очистка диска;
#include <vcl.h>
tpragma hdrstop
«include «clear .h»
Глава 10. Примеры программ _ 270
#include <FileCtrl.hpp> // для доступа к SelectDirectory
#pragma package (smart_init)
#pragma resource «*.dfm»
TForml *Forml;
_ fastcall TForml: : TForml (TComponent* Owner)
: TForm (Owner)•
AnsiString Directory; // каталог, в котором находятся проекты C++ Builder
AnsiString cDir; // текущий каталог
AnsiString FileExt; // расширение файла
int n = 0; // количество удаленных файлов
// щелчок на кнопке Каталог
void _ fastcall TForml: : Button! Click (TQbject *Sender)
{
AnsiString dir; // каталог, который выбрал пользователь
if ( SelectDirectory («Выберите каталог»,»», dir))
{
// диалог Выбор файла завершен щелчком на кнопке ОК
Editl-XText = dir;
Button2->Enabled = true; // теперь кнопка Выполнить доступна
// удаляет ненужные файлы из текущего каталога и его подкаталогов
void _ fastcall Clear (void)
TSearchRec SearchRec; // информация о файле или каталоге
cDir = GetCurrentDir ()+»\\»;
if ( FindFirst («*.*», faArchive, SearchRec) == 0)
do {
// проверим расширение файла
int p = SearchRec . Name . Pos («.»);
FileExt = SearchRec. Name. Substring (p+1, MAX_PATH) ;
if ( ( FileExt [1] == ‘-‘) I I ( FileExt == «obj»)
( FileExt = «tds») )
280 _ Часть II. Практикум программирования
Forml->Memol->Lines->Add (cDir+SearchRec .Name) ;
DeleteFile (SearchRec.Name) ;
while { FindNext (SearchRec) == 0);
// обработка подкаталогов текущего каталога
if ( FindFirst («*», faDirectory, SearchRec) == 0)
do
if ( (SearchRec. Attr & faDirectory) == SearchRec. Attr)
{
// каталоги «. . » и «. » тоже каталоги,
// но в них входить не надо ! ! I
if (( SearchRec.Name !=».») &&
(SearchRec.Name != «..»))
{
ChDir (SearchRec.Name) ; // войти в подкаталог
Clear (); // очистить каталог
ChDir («..»); // выйти из каталога
while ( FindNext (SearchRec) == 0) ;
// щелчок на кнопке Выполнить
void _ fastcall TForml: :Button2Click (TObject *Sender)
{
Memol->Clear () ; // очистить поле Memol
Directory = Editl->Text;// каталог, который выбрал пользователь
ChDir (Directory) ; // войти в каталог
Clear (); // очистить текущий каталог и его подкаталоги
Mernol->Lines->Add(«») ;
if (n)
Memol->Lines->Add( «Удалено файлов: » + IntToStr (n) ) ;
else
Memol->Lines->Add (
«В указанном каталоге нет файлов, которые надо удалить.»);
Основную работу (удаление файлов) выполняет рекурсивная функция clear(рекурсивной называют функцию, которая в процессе работы вызывает сама
Глава 10. Примеры программ 281
себя). Решение реализовать функцию clear как рекурсивную не случайно:функция обрабатывает каталоги компьютера, которые являются рекурсивны-ми объектами. Рекурсивным называют объект, частично состоящий из объ-ектов этого же типа.
Алгоритм функции clear приведен на рис. 10.23.
С Clear
Обработать файлытекущего каталога
Естьнеобработанные
одкаталоги?
Рис. 10.23. Алгоритм функции Clear
Сначала функция clear обрабатывает текущий каталог: просматривает всефайлы и удаляет те, которые надо удалить. Просмотр файлов обеспечиваютфункции FindFirst и FindNext. Функция FindFirst просматривает каталог,указанный при ее вызове, и записывает в структуру searchRec имя первогоиз найденных файлов, имя которого соответствует маске. В данной про-грамме маска *.*, т.е. функция выбирает первый по порядку файл. Еслифайл найден, то выполняется проверка его расширения. Если расширениефайла’оЬ), tds или начинается со значка ~, то имя файла добавляется в поле
282 Часть II. Практикум программирования
Memol, а сам файл удаляется с диска. Удаляет файл функция DeieteFiie. По-сле обработки первого файла для поиска следующего вызывается функцияFindNext. После того как все файлы текущего каталога будут обработаны,функция clear проверяет, есть ли в текущем каталоге подкаталоги. Провер-ку выполняет функция FindFirst, которой в качестве параметра передаетсяконстанта faDirectory, информирующая функцию о том, что надо искатьимена каталогов, а не файлов. Если в текущем каталоге нет подкаталогов,то функция clear завершает работу. Если в текущем каталоге есть подката-логи, то выполняется вход в подкаталог (делает это функция choir) и вызовфункции clear (для обработки подкаталога функция вызывает саму себя).Если в текущем каталоге нет необработанных каталогов, то она завершаетработу и возвращает управление функции clear, которая ее вызвала и кото-рая после этого продолжает обработку «своих» подкаталогов.
Вывод окна Обзор папок выполняет функция seiectoirectory, которую вы-зывает функция обработки события click на кнопке Каталог. Для доступа кэтой функции в текст программы надо включить директиву<FileCtrl.hpp>.
ПРИЛОЖЕНИЕ 1
C++ Builder -краткий справочник
Приложение представляет собой краткий справочник по компонентам ифункциям C++ Builder.
КомпонентыВ этом разделе приведено краткое описание базовых компонентов C++ Buil-der. Подробное описание этих и других компонентов можно найти в спра-вочной системе.
ФормаФорма (объект тип TForm) является основой программы. Свойства формы(табл. П1.1) определяют вид окна программы.
Таблица П1.1. Свойства формы (объекта TForm)
Свойство Описание
Name Имя формы. В программе имя формы используется для управле-ния формой и доступа к компонентам формы
Caption Текст заголовка
Тор Расстояние от верхней границы формы до верхней границы экра-на
Left Расстояние от левой границы формы до левой границы экрана
Width Ширина формы
Height Высота формы
Clientwidth Ширина рабочей (клиентской) области формы, т. е. без учета ши-рины левой и правой границ
284 Приложение 1
Таблица П1.1 (окончание)
Свойство Описание
ClientHeight Высота рабочей (клиентской) области формы, т. е. без учета вы-соты заголовка и ширины нижней границы формы
BorderStyle Вид границы. Граница может быть обычной (bsSizeable), тонкой(bssingle) или отсутствовать (bsNone). Если у окна обычная гра-ница, то во время работы программы пользователь может припомощи мыши изменить размер окна. Изменить размер окна стонкой границей нельзя. Если граница отсутствует, то на экран вовремя работы программы будет выведено окно без заголовка.Положение и размер такого окна во время работы программыизменить нельзя
Bordericons Кнопки управления окном. Значение свойства определяет, какиекнопки управления окном будут доступны пользователю во времяработы программы. Значение свойства задается путем присвое-ния значений уточняющим свойствам biSystemMenu, biMinimize,biMaximize и biHelp. Свойство biSystemMenu определяетдоступность кнопки Свернуть и кнопки системного меню,biMinimize— кнопки Свернуть, biMaximize— кнопки Развер-нуть, biHelp— кнопки вывода справочной информации
Icon Значок в заголовке диалогового окна, обозначающий кнопку вы-вода системного меню
Color Цвет фона. Цвет можно задать, указав название цвета или эле-мент цветовой схемы операционной системы. Во втором случаецвет компонента «привязан» к цветовой схеме операционной сис-темы и будет изменяться при каждой смене цветовой схемы
Font Шрифт. Шрифт, используемый «по умолчанию» компонентами,находящимися на поверхности формы. Изменение свойства Fontформы приводит к автоматическому изменению свойства Fontкомпонента, располагающегося на поверхности формы. То естькомпоненты наследуют свойство Font от формы (имеется воз-можность запретить наследование)
Canvas Поверхность, на которую можно вывести графику
LabelКомпонент Label (рис. П1.1) предназначен для вывода текста на поверх-ность формы. Свойства компонента (табл. П1.2) определяют вид и распо-ложение текста.
Standard
1 Label
Рис. П1.1. Компонент Label — поле вывода текста
C++ Builder — краткий справочник 285
Таблица П1.2. Свойства компонента Label (поле вывода текста)
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компо-ненту и его свойствам
Caption Отображаемый текст
Left Расстояние от левой границы поля вывода до левой границы формы
Тор Расстояние от верхней границы поля вывода до верхней границыформы
Height Высота поля вывода
Width Ширина поля вывода
AutoSize Признак того, что размер поля определяется его содержимым
wordwrap Признак того, что слова, которые не помещаются в текущей строке,автоматически переносятся на следующую строку (значение свойст-ва AutoSize ДОЛЖНО быть false)
Alignment Задает способ выравнивания текста внутри поля. Текст может бытьвыровнен по левому краю (tabeftJustify), по центру (taCenter)или по правому краю (taRightJustify)
Font Шрифт, используемый для отображения текста. Уточняющие свойст-ва определяют шрифт (Name), размер (size), стиль (style) и цветсимволов(Color)
ParentFont Признак наследования компонентом характеристик шрифта формы,на которой находится компонент. Если значение свойства равноtrue, то текст выводится шрифтом, установленным для формы
Color Цвет фона области вывода текста
Transparent Управляет отображением фона области вывода текста. Значениеtrue делает область вывода текста прозрачной (область вывода незакрашивается цветом, заданным свойством Color)
Visible Позволяет скрыть текст (false) или сделать его видимым (true)
EditКомпонент Edit (рис, П1.2) представляет собой поле ввода-редактированиястроки символов. Свойства компонента приведены в табл. П1.3.
Edit
Рис. П1.2. Компонент Edit — поле ввода-редактирования строки символов
286 Приложение 1
Таблица П1.3. Свойства компонента Edi t (поле редактирования)
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компо-ненту и его свойствам, в частности для доступа к тексту, введенно-му в поле редактирования
Text Текст, находящийся в поле ввода и редактирования
Left Расстояние от левой границы компонента до левой границы формы
Тор Расстояние от верхней границы компонента до верхней границыформы
Height Высота поля
Width Ширина поля
Font Шрифт, используемый для отображения вводимого текста
ParentFont Признак наследования компонентом характеристик шрифта фор-мы, на которой находится компонент. Если значение свойства рав-но true, то при изменении свойства Font формы автоматическименяется значение свойства Font компонента
Enabled Используется для ограничения возможности изменить текст в полередактирования. Если значение свойства равно false, то текств поле редактирования изменить нельзя
visible Позволяет скрыть компонент (false) или сделать его видимым(true)
ButtonКомпонент Button (рис. П1.3) представляет собой командную кнопку.Свойства компонента приведены в табл. П1.4.
Standard |_•_
я тButton
Рис. П1.3. Компонент Button — командная кнопка
Таблица П1.4. Свойства компонента Button (командная кнопка)
Свойство Описание
Name Имя компонента. Используется в программе для доступа к компо-ненту и его свойствам
C++ Builder — краткий справочник 287
Таблица П1.4 (окончание)
Свойство Описание
Caption Текст на кнопке
Left Расстояние от левой границы кнопки до левой границы формы
Тор Расстояние от верхней границы кнопки до верхней границы формы
Height Высота кнопки
Width Ширина кнопки
Enabled Признак доступности кнопки. Если значение свойства равно true, токнопка доступна. Если значение свойства равно false, то кнопканедоступна— например, в результате щелчка на кнопке, событиеClick не возникает
Visible Позволяет скрыть кнопку (false) или сделать ее видимой (true)
Hint Подсказка — текст, который появляется рядом с указателем мышипри позиционировании указателя на командной кнопке (для того что-бы текст появился, надо, чтобы значение свойства showHint былоtrue)
ShowHint Разрешает (true) или запрещает (false) отображение подсказкипри позиционировании указателя на кнопке
MemoКомпонент Memo (рис. П1.4) представляет собой элемент редактированиятекста, который может состоять из нескольких строк. Свойства компонентаприведены в табл. П1.5.
|х <*
Memo
Рис. П1.4. Компонент Memo
Таблица П1.5. Свойства компонента Memo
Свойство Описание
Name
Text
Имя компонента. Используется для доступа к свойствам компонента
Текст, находящийся в поле Memo. Рассматривается как единое целое
288 Приложение 1
Таблица П1.5 (окончание)
Свойство Описание
Lines Массив строк, соответствующий содержимому поля. Доступ к строкеосуществляется по номеру. Строки нумеруются с нуля
Left Расстояние от левой границы поля до левой границы формы
Тор Расстояние от верхней границы поля до верхней границы формы
Height Высота поля
width Ширина поля
Font Шрифт, используемый для отображения вводимого текста
ParentFont Признак наследования свойств шрифта родительской формы
RadioButton
Компонент RadioButton (рис. П1.5) представляет зависимую кнопку, со-стояние которой определяется состоянием других кнопок группы. Свойствакомпонента приведены в табл. П1.6.
Если в диалоговом окне надо организовать несколько групп радиокнопок,то каждую группу следует представить компонентом RadioGroup.
Standard I
gr4=
RadioButton
Рис. П1.5. Компонент RadioButton
Таблица П1.6. Свойства компонента RadioButton
Свойство Описание
Name Имя компонента. Используется для доступа к свойствам компонента
Caption Текст, который находится справа от кнопки
Checked Состояние, внешний вид кнопки. Если кнопка выбрана, то значениесвойства Checked равно true, если кнопка не выбрана, то false
Left Расстояние от левой границы флажка до левой границы формы
Тор Расстояние от верхней границы флажка до верхней границы формы
Height Высота поля вывода поясняющего текста
C++ Builder — краткий справочник 289
Таблица П1.6 (окончание)
Свойство Описание
Width Ширина поля вывода поясняющего текста
Font Шрифт, используемый для отображения поясняющего текста
ParentFont Признак наследования характеристик шрифта родительской формы
CheckBoxКомпонент CheckBox (рис. П1.6) представляет собой независимую кнопку(переключатель). Свойства компонента приведены в табл. П1.7.
•
IF ОШ 1х
CheckBox
Рис. П1.6. Компонент CheckBox
Таблица П1.7. Свойства компонента CheckBox
Свойство Описание
Name Имя компонента. Используется для доступа к свойствам компонента
Caption Текст, который находится справа от флажка
Checked Состояние, внешний вид флажка. Если флажок установлен(в квадратике есть «галочка»), то значение свойства Checked равноtrue; если флажок сброшен (нет «галочки»), то значение checkedравно false
State Состояние флажка. В отличие от свойства Checked, позволяет раз-личать установленное, сброшенное и промежуточное состояния.Состояние флажка определяет одна из констант: cbChecked (уста-новлен); cbGrayed (серый, неопределенное состояние); cbUnChecked(сброшен)
AllowGrayed Свойство определяет, может ли флажок быть в промежуточном со-стоянии: если значение AllowGrayed равно false, то флажок можетбыть только установленным или сброшенным; если значениеAllowGrayed равно true, то допустимо промежуточное состояние
Left Расстояние от левой границы флажка до левой границы формы
Тор Расстояние от верхней границы флажка до верхней границы формы
ЮЗак. 1252
290 Приложение 1
Таблица П1.7 (окончание)
Свойство Описание
Height Высота поля вывода поясняющего текста
width Ширина поля вывода поясняющего текста
Font Шрифт, используемый для отображения поясняющего текста
ParentFont Признак наследования характеристик шрифта родительской формы
LlstBoxКомпонент ListBox (рис. П1.7) представляет собой список, в котором мож-но выбрать нужный элемент. Свойства компонента приведены в табл. П1.8.
Standaid|_
QЖ A.J5T Й.ИГ I* <S
ListBox
Рис. П1.7. Компонент ListBox
Таблица П1.8. Свойства компонента ListBox
Свойство Описание
Name Имя компонента. В программе используется для доступа к компо-ненту и его свойствам
Items Элементы списка — массив строк
Count Количество элементов списка
Sorted Признак необходимости автоматической сортировки (true) спискапосле добавления очередного элемента
itemindex Номер выбранного элемента (элементы списка нумеруются с нуля).Если в списке ни один из элементов не выбран, то значение свойст-ва равно —1 (минус один)
Left Расстояние от левой границы списка до левой границы формы
Тор Расстояние от верхней границы списка до верхней границы формы
Height Высота поля списка
Width Ширина поля списка
Font Шрифт, используемый для отображения элементов списка
ParentFont Признак наследования свойств шрифта родительской формы
C++ Builder — краткий справочник 291
ComboBoxКомпонент ComboBox (рис. П1.8) дает возможность ввести данные в полередактирования путем набора на клавиатуре или выбором из списка. Свой-ства компонента приведены в табл. П1.9.
|ЗГ В L2D I*;
ComboBox
Рис. П1.8. Компонент ComboBox
Таблица П1.9, Свойства компонента comboBox
Свойство Описание
Name
Text
Items
Count
Itemlndex
Sorted
DropDownCount
Left
Top
Height
Width
Font
ParentFont
Имя компонента. Используется для доступа к свойствам компо-нента
Текст, находящийся в поле ввода/редактирования
Элементы списка — массив строк
Количество элементов списка
Номер элемента, выбранного в списке. Если ни один из элемен-тов списка не был выбран, то значение свойства равно -1 (ми-нус один)
Признак необходимости автоматической сортировки (true) спи-ска после добавления очередного элемента
Количество отображаемых элементов в раскрытом списке. Есликоличество элементов списка больше, чем DropDownCount, топоявляется вертикальная полоса прокрутки
Расстояние от левой границы компонента до левой границыформы
Расстояние от верхней границы компонента до верхней границыформы
Высота компонента (поля ввода/редактирования)
Ширина компонента
Шрифт, используемый для отображения элементов списка
Признак наследования свойств шрифта родительской формы
292 Приложение i
StringGridКомпонент stringGrid (рис. П1.9) представляет собой таблицу, ячейкикоторой содержат строки символов. Свойства компонента stringGrid приве-дены в табл. ШЛО.
А тStringGrid
Рис. П1.9. Компонент StringGrid
Таблица П1.10. Свойства компонента stringGrid
Свойство Описание
Name
ColCount
RowCount
DefaultColWidth
DefaultRowHeight
FixedCols
FixedRows
Cells
GridLineWidth
Left
Top
Height
Width
Имя компонента. Используется в программе длядоступа к компоненту и его свойствам
Количество колонок таблицы
Количество строк таблицы
Ширина колонок таблицы
Высота строк таблицы
Количество зафиксированных слева колонок таб-лицы. Зафиксированные колонки выделяются цве-том и при горизонтальной прокрутке таблицы оста-ются на месте
Количество зафиксированных сверху строк табли-цы. Зафиксированные строки выделяются цветом ипри вертикальной прокрутке таблицы остаются наместе
Соответствующий таблице двумерный массив.Ячейке таблицы, находящейся на пересечениистолбца с номером col и строки с номером row,соответствует элемент cells [col] [row]
Ширина линий, ограничивающих ячейки таблицы
Расстояние от левой границы поля таблицы до ле-вой границы формы
Расстояние от верхней границы поля таблицы доверхней границы формы
Высота поля таблицы
Ширина поля таблицы
Builder — краткий справочник 293
Таблица П1.10 (окончание)
Свойство Описание
Options.goEditing
Options.goTab
Options.goAlwaysShowEditor
Font
ParentFont
Признак допустимости редактирования содержимо-го ячеек таблицы (true — редактирование разре-шено, false — запрещено)
Разрешает (true) или запрещает (false) использо-вание клавиши <ТаЬ> для перемещения курсорав следующую ячейку таблицы
Признак нахождения компонента в режиме редак-тирования. Если значение свойства false, то длятого чтобы в ячейке появился курсор, надо или на-чать набирать текст или нажать клавишу <F2>, илисделать щелчок мышью в ячейке таблицы
Шрифт, используемый для отображения содержи-мого ячеек таблицы
Признак наследования характеристик шрифта фор-мы
ImageКомпонент image (рис. ШЛО) обеспечивает вывод на поверхность формыиллюстраций, представленных в формате BMP (чтобы компонент можнобыло использовать для отображения иллюстраций в формате JPG, надоподключить модуль JPEG — включить в текст программы директиву # include<jpeg.hpp>). Свойства компонента image приведены в табл. П1.11.
image
Рис. П1.10. Компонент Image
Таблица П1.11. Свойства компонента image
Свойство Описание
Picture
Width, Height
Иллюстрация, которая отображается в поле компонента
Размер компонента. Если размер компонента меньше размераиллюстрации, а значение свойств AutoSize, strech иProportional равно false, то отображается часть иллюстрации
294 Приложение 1
Таблица П1.11 (окончание)
Свойство Описание
Proportional Признак автоматического масштабирования картинки без иска-жения. Чтобы масштабирование было выполнено, значениесвойства AutoSize должно быть false
Strech Признак автоматического масштабирования (сжатия или растя-жения) иллюстрации в соответствии с реальным размером ком-понента. Если размер компонента не пропорционален размеруиллюстрации, то иллюстрация будет искажена
AutoSize Признак автоматического изменения размера компонента всоответствии с реальным размером иллюстрации
Center Признак определяет расположение картинки в поле компонентапо горизонтали, если ширина картинки меньше ширины полякомпонента. Если значение свойства равно false, то картинкаприжата к правой границе компонента, если true — то картинкарасполагается по центру
Visible Отображается ли компонент, и, соответственно, иллюстрация,на поверхности формы
Canvas Поверхность, на которую можно вывести графику (см.табл. П1.25)
TimerКомпонент Timer (рис. П1.11) обеспечивает генерацию последовательностисобытий OnTimer. Свойства компонента приведены в табл. П1.12.
Timer
Рис. П1.11. Компонент Timer
Таблица П1.12. Свойства компонента Timer
Свойство Описание
Name Имя компонента. Используется для доступа к компоненту
interval Период генерации события OnTimer. Задается в миллисекундах
Enabled Разрешение работы. Разрешает (значение true) или запрещает (зна-чение false) генерацию события OnTimer
C++ Builder — краткий справочник 295
AnimateКомпонент Animate (рис. П1.12) позволяет воспроизводить простую, не со-провождаемую звуком анимацию, кадры которой находятся в AVI-файле.Свойства компонента приведены в табл. П1.13.
Animate
Рис. П1.12. Компонент Animate
Таблица П1.13. Свойства компонента Animate
Свойство Описание
Name Имя компонента. Используется для доступа к свойствам компонен-та и управления его поведением
FileName Имя AVI-файла, в котором находится анимация, отображаемая припомощи компонента
StartFrame Номер кадра, с которого начинается отображение анимации
stopFrame Номер кадра, на котором заканчивается отображение анимации
Activate Признак активизации процесса отображения кадров анимации
Color Цвет фона компонента (цвет «экрана»), на котором воспроизводит-ся анимация
Transparent Режим использования «прозрачного» цвета при отображении ани-мации
Repetitions Количество повторов отображения анимации
MediaPlayerКомпонент MediaPlayer (рис. П1.13) позволяет воспроизвести видеоролик,звук и сопровождаемую звуком анимацию. Свойства компонента приведеныв табл. П1.14.
MediaPlayer
Рис. П1.13. Компонент MediaPlayer
296 Приложение 1
Таблица П1.14. Свойства компонента MediaPlayer
Свойство Описание
Name
DeviceType
FileName
AutoOpen
Display
VisibleButtons
Имя компонента. Используется для доступа к свойствам ком-понента и управлениея работой плеера
Тип устройства. Определяет конкретное устройство, котороепредставляет собой компонент MediaPlayer. Тип устройствазадается именованной константой: dtAutoSelect — тип уст-ройства определяется автоматически; dtVaweAudio— проиг-рыватель звука; dtAVlVideo — видеопроигрыватель;dtCDAudio — CD-проигрыватель
Имя файла, в котором находится воспроизводимый звуковойфрагмент или видеоролик
Признак автоматического открытия сразу после запуска про-граммы файла видеоролика или звукового фрагмента
Определяет компонент, на поверхности которого воспроизво-дится видеоролик (обычно в качестве экрана для отображениявидео используют компонент Panel)
Составное свойство. Определяет видимые кнопки компонента.Позволяет сделать невидимыми некоторые кнопки
SpeedButtonКомпонент SpeedButton (рис. П1.14) представляет собой кнопку, на поверх-ности которой находится картинка. Свойства компонента приведены втабл. П1.15.
SpeedButton
Рис. П1.14. Компонент SpeedButton
Таблица П1.15. Свойства компонента SpeedButton
Свойство Описание
Name
Glyph
Имя компонента. Используется для доступа к компоненту и егосвойствам
Битовый образ, в котором находятся картинки для каждого из со-стояний кнопки. В битовом образе может быть до четырех изобра-жений кнопки (рис. П1.15)
C++ Builder — краткий справочник 297
Таблица П1.15 (окончание)
Свойство Описание
NumGlyphs Количество картинок в битовом образе Glyph
Flat Свойство Flat определяет вид кнопки (наличие границы). Еслизначение свойства равно true, то граница кнопки появляется толь-ко при позиционировании указателя мыши на кнопке
Grouplndex Идентификатор группы кнопок. Кнопки, имеющие одинаковыйидентификатор группы, работают подобно радиокнопкам: нажатиеодной из кнопок группы вызывает срабатывание других кнопок этойгруппы. Чтобы кнопку можно было зафиксировать, значение свойст-ва Grouplndex не должно быть равно нулю
Down Идентификатор состояния кнопки. Изменить значение свойстваможно, если значение свойства Grouplndex не равно нулю
AllowAllUp Свойство определяет возможность отжать кнопку. Если кнопка на-жата и значение свойства равно true, то кнопку можно отжать
Left Расстояние от левой границы кнопки до левой границы формы
Тор Расстояние от верхней границы кнопки до верхней границы формы
Height Высота кнопки
Width Ширина кнопки
Enabled Признак доступности кнопки. Если значение свойства равно true,то кнопка доступна. Если значение свойства равно false, то кнопканедоступна
visible Позволяет скрыть кнопку (false) или сделать ее видимой (true)
Hint Подсказка — текст, который появляется рядом с указателем мышипри позиционировании указателя на командной кнопке (для тогочтобы текст появился, надо, чтобы значение свойства ShowHint бы-ло равно true)
ShowHint Разрешает (true) или запрещает (false) отображение подсказкипри позиционировании указателя на кнопке
Недоступная Зафиксированная
оОбычная Нажатая мышью
Рис. П1.15. Структура и пример битового образа Glyph:картинки, соответствующие состоянию кнопки
298 Приложение 1
UpDownКомпонент UpDown (рис. П1.16) представляет собой две кнопки, используякоторые можно изменить значение внутренней переменной-счетчика на оп-ределенную величину. Увеличение или уменьшение значения происходитпри каждом щелчке на одной из кнопок. Свойства компонента приведеныв табл. П1.16.
Edi.
UpDown
Рис. П1.16. Компонент UpDown
Таблица П1.16, Свойства компонента UpDown
Свойство Описание
Name Имя компонента. Используется для доступа к компоненту и егосвойствам
Position Счетчик. Значение свойства изменяется в результате щелчка накнопке Up (увеличивается) или Down (уменьшается). Диапазонизменения определяют свойства Min и Мах, величину измене-ния — свойство Increment
Min Нижняя граница диапазона изменения свойства Position
Мах Верхняя граница диапазона изменения свойства Position
Increment Величина, на которую изменяется значение свойства Positionв результате щелчка на одной из кнопок компонента
Associate Определяет компонент (Edit — поле ввода/редактирования), ис-пользуемый в качестве индикатора значения свойства Position.Если значение свойства задано, то при изменении содержимогополя редактирования автоматически меняется значение свойстваPosition
Orientation Задает ориентацию кнопок компонента. Кнопки могут быть ори-ентированы вертикально (udvertical) или горизонтально(udHorizontal)
TableКомпонент Table (рис. П1.17) представляет всю таблицу базы данных.Свойства компонента приведены в табл. П1.17.
C++ Builder — краткий справочник 299
а»*
Table
Рис. П1.17. Компонент Table — таблица базы данных
Таблица П1.17. Свойства компонента Table
Свойство Определяет
Name Имя компонента. Используется для доступа к свойствам компо-нента
DatabaseName Имя базы данных, частью которой является таблица (файл дан-ных), для доступа к которой применяется компонент. В качествезначения свойства следует использовать псевдоним базы дан-ных
TableName Имя файла данных (таблицы данных), для доступа к которомуиспользуется компонент
ТаЫеТуре Тип таблицы. Таблица может быть набором данных в форматеParadox (ttParadox), dBase (ttDBase), FoxPro (ttFoxPro) илипредставлять собой форматированный текстовый файл(ttASCIl)
Active Признак того, что таблица активна (файл данных открыт). В ре-зультате присваивания свойству значения true происходит от-крытие файла таблицы
QueryКомпонент Query (рис. П 1.18) представляет часть базы данных— записи,содержимое которых удовлетворяет критерию SQL-запроса к таблице. Свой-ства компонента приведены в табл. П1.18.
Таблица П1.18. Свойства компонента Query
Свойство Определяет
Name Имя компонента. Используется компонентом Datasource для связирезультата выполнения запроса (набора записей) с компонентом,обеспечивающим просмотр записей, например DBGrid
SQL Записанный на языке SQL-запрос к базе данных (к таблице)
Active При присвоении свойству значения true активизирует выполнениезапроса
300 Приложение 1
Таблица П1.18 (окончание)
Свойство Определяет
RecordCount Количество записей в базе данных, удовлетворяющих критериюзапроса
Query
Рис. П1.18. Компонент Query обеспечивает выбор информации из базы данных
DataSourceКомпонент DataSource (рис. П1.19) обеспечивает связь между данными,
представленными компонентом Table или Query, и компонентами отобра-
жения данных (DBEdit, овмето, DBGrid). Свойства компонента приведены в
табл. П1.19.
Data Access]
Щ XML J: o; jf L
DataSource
Рис. П1.19. Компонент DataSource обеспечиват связь между даннымии компонентом просмотра-редактирования
Таблица П1.19. Свойства компонента DataSource
Свойство Определяет
Name
DataSet
Имя компонента. Используется компонентом отображе-ния данных для доступа к компоненту и, следовательно,к данным, связь с которыми обеспечивает компонент
Компонент, представляющий собой входные данные(Table ИЛИ Query)
DBEdit, DBMemo, DBTextКомпоненты DBEdit и DBMemo (рис. П1.20) обеспечивают просмотр и редак-
тирование полей записи базы данных, компонент DBText — только про-смотр. Свойства компонентов приведены в табл. П1.20.
C++ Builder — краткий справочник 301
, f __ : Data Controls |
^ «И Ё2 ‘«А РЙ» ts •d «И ‘»Я »»P< :i=l VM ‘•Я В Тр :Ф
DBText DBMernoDBEdit
Рис. П1.20. Компоненты просмотра и редактирования полей БД
Таблица П1.20. Свойства компонентов DBText, DBEdit и DBMemo
Свойство Определяет
Name Имя компонента. Используется для доступа к свойствам компонента
DataSource Компонент-источник данных
DataField Поле базы данных, для отображения или редактирования которогоиспользуется компонент
DBGridКомпонент DBGrid (рис. П1.21) используется для просмотра и редактирова-ния базы данных в режиме таблицы. Свойства компонента приведены втабл. П1.21.
! Data Controls
И ‘ЕВ ‘А ПЕГ Щ| .J И S ‘ I* ill ^Й Ш Ы J’ …… I ………
DBGrid ,
Рис. П1.21. Компонент DBGrid обеспечивает работу с базой данных в режиме таблицы
Таблица П1.21. Свойства компонента DBGrid
Свойство Описание
Name
DataSource
Columns
Options
Options.dgTitles
Имя компонента
Источник отображаемых в таблице данных (компонентDataSource)
Свойство columns представляет собой массив объек-тов типа TColumn, каждый из которых определяет ко-лонку таблицы и отображаемую в ней информацию(см. табл. П1.22)
Свойство Options определяет настройку компонента
Разрешает вывод строки заголовка столбцов
302 Приложение 1
Таблица П1.21 (окончание)
Свойство Описание
Options.dglndicator
Options.dgColumnResize
Options.dgColLines
Options.dgRowLines
Разрешает вывод колонки индикатора. Во время ра-боты с базой данных текущая запись помечается вколонке индикатора треугольником, новая запись —звездочкой, редактируемая — специальным значком
Разрешает менять во время работы программы шири-ну колонок таблицы
Разрешает выводить линии, разделяющие колонкитаблицы
Разрешает выводить линии, разделяющие строки таб-лицы
Таблица П1.22. Свойства объекта TColumn
Свойство Определяет
FieldName
Width
Font
Color
Alignment
Title.Caption
Title.Alignment
Title.Color
Title.Font
Поле записи, содержимое которого выводится в колонке
Ширину колонки в пикселах
Шрифт, используемый для вывода текста в ячейках колонки
Цвет фона колонки
Способ выравнивания текста в ячейках колонки. Текст можетбыть выровнен по левому краю (taLeftJustify), по центру(taCenter) или по правому краю (taRightJustify)
Заголовок колонки. Значением по умолчанию является имяполя записи
Способ выравнивания заголовка колонки. Заголовок можетбыть выровнен по левому краю (taLeftJustify), по центру(taCenter) или по правому краю (taRightJustify)
Цвет фона заголовка колонки
Шрифт заголовка колонки
DBNavigatorКомпонент DBNavigator (рис. П1.22 и П1.23) обеспечивает перемещениеуказателя текущей записи, активизацию режима редактирования, добавлениеи удаление записей. Компонент представляет собой совокупность команд-ных кнопок (табл. П1.23). Свойства компонента приведены в табл. П1.24.
C++ Builder — краткий справочник 303
Data Controls j
DBNavigator
Рис. П1.22. Значок компонента DBNavigator
^п^ш^тшищшаРис. П1.23. Компонент DBNavigator
Таблица П1.23. Кнопки компонента DBNavigator
Кнопка
Гм] К первой
[~«1 К предыдущей
l*j К следующей
[W] К последней
Г+J Добавить
Г 1 Удалить
[~Г] Редактирование
[•] Сохранить
[х] Отменить
[Я Обновить
Свойство
Name
Обозначение
nbFirst
nbPrior
nbNext
nbLast
nblnsert
nb Delete
nbEdit
nbPost
Cancel
nbRe fresh
Таблица
Определяет
Действие
Указатель текущей записи перемещаетсяк первой записи файла данных
Указатель текущей записи перемещаетсяк предыдущей записи файла данных
Указатель текущей записи перемещаетсяк следующей записи файла данных
Указатель текущей записи перемещаетсяк последней записи файла данных
В файл данных добавляется новая запись
Удаляется текущая запись файла данных
Устанавливает режим редактирования те-кущей записи
Изменения, внесенные в текущую запись,записываются в файл данных
Отменяет внесенные в текущую записьизменения
Записывает внесенные изменения в файл
П1.24. Свойства компонента DBNavigator
Имя компонента. Используется для доступа к свойствам ком-понента
304 Приложение 1
Таблица П1.24 (окончание)
Свойство Определяет
DataSource
VisibleButtons
Имя компонента, являющегося источником данных. В качествеисточника данных может выступать база данных (компонентDatabase), таблица (компонент Table) или результат выпол-нения запроса (компонент Query)
Видимые командные кнопки
Графика
CanvasCanvas — это поверхность (формы или компонента image), на которой соот-ветствующие методы (табл. П1.25) могут вычерчивать графические прими-тивы. Вид графических элементов определяют свойства поверхности, на ко-торой эти элементы вычерчиваются (табл. П1.26).
Таблица П1.25. Методы объекта canvas
Метод Описание
TextOut(x,y,s) Выводит строку s от точки с координатами (х, у). Шрифтопределяет свойство Font поверхности (Canvas), на которуювыводится тест, цвет закраски области вывода текста —свойство Brush этой же поверхности
Draw(x,y,b) Выводит от точки с координатами (х, у) битовый образ Ь.Если значение свойства Transparent поверхности, на кото-рую выполняется вывод, равно true, то точки, цвет которыхсовпадает с цветом левой нижней точки битового образа, неотображаются
LineTo(x,y) Вычерчивает линию из текущей точки в точку с указаннымикоординатами. Вид линии определяет свойство Pen
MoveTo(x,y) Перемещает указатель текущей точки в точку с указаннымикоординатами
PolyLine(pl) Вычерчивает ломаную линию. Координаты точек перегибазадает параметр pi — массив структур типа TPoint. Еслипервый и последний элементы массива одинаковы, то будетвычерчен замкнутый контур. Вид линии определяет свойствоРеп
Polygon(pi) Вычерчивает и закрашивает многоугольник. Координатыуглов задает параметр р! — массив структур типа TPoint.Первый и последний элементы массива должны быть одина-ковы. Вид границы определяет свойство Реп, цвет и стильзакраски внутренней области — свойство Brush
C++ Builder — краткий справочник 305
Таблица П1.25 (окончание)
Метод Описание
Ellipse (xl, yl, [V18]х2,у2)
Вычерчивает эллипс, окружность или круг. Параметры xl,yii Х2 и у2 задают размер прямоугольника, в который впи-сывается эллипс. Вид линии определяет свойство Реп
<х2,У2) (Х2,у2)
Arc(xl,yl ,x2,y2,хЗ,уЗ,х4,у4)
Вычерчивает дугу. Параметры xl, yl, x2, у2 определяютэллипс, из которого вырезается дуга, параметры х2, у2, хЗ,и у4 — координаты концов дуги. Дуга вычерчивается противчасовой стрелки от точки (хЗ, уЗ) к точке (х4, у4). Вид линии(границы) определяет свойство Реп, цвет и способ закраскивнутренней области — свойство Brush
(хЗ.уЗ) (Х4,у4)
(Х4,у4) (ХЗ.уЗ)
(Х2.У2) (Х2,У2)
Rectangle(xl,yl,х2,у2)
RoundRec(xl,yl,х2,у2,хЗ,уЗ)
Вычерчивает прямоугольник. Параметры xl, yl, x2 и у2 за-дают координаты левого верхнего и правого нижнего углов.Вид линии определяет свойство Реп, цвет и способ закраскивнутренней области — свойство Brush
Вычерчивает прямоугольник со скругленными углами. Па-раметры xl, yl, х2 и у2 задают координаты левого верхнегои правого нижнего углов, хЗ и уЗ — радиус скругления. Видлинии определяет свойство Реп, цвет и способ закраскивнутренней области — свойство Brush
(Х1.У1)хЗ
N/уз
\(Х2,у2)
306 Приложение 1
Таблица П1.26. Свойства объекта Canvas
Свойство Описание
Transparent Признак использования «прозрачного» цвета при выводе битовогообраза методом Draw. Если значение свойства равно true, тоточки, цвет которых совпадают с цветом левой нижней точки би-тового образа, не отображаются
Реп Свойство Реп представляет собой объект (см. табл. (11.27), свой-ства которого определяют цвет, толщину и стиль линий, вычерчи-ваемых методами вывода графических примитивов
Brush Свойство Brush представляет собой объект (см. табл. П 1.28),свойства которого определяют цвет и стиль закраски областей,вычерчиваемых методами вывода графических примитивов
Font Свойство Font представляет собой объект, уточняющие свойствакоторого определяют шрифт (название, размер, цвет, способоформления), используемый для вывода на поверхность холстатекста
РепОбъект Реп является свойством объекта canvas. Свойства объекта Реп(табл. П1.27) определяют цвет, стиль и толщину линий, вычерчиваемых ме-тодами вывода графических примитивов.
Таблица П1.27. Свойства объекта Реп
Свойство Описание
Color Цвет линии (clBlack — черный; clMaroon — каштановый; clGreen —зеленый; cloiive— оливковый; clNavy— темно-синий; clPurple —розовый; clTeal — зелено-голубой; clGray— серый; clSilver— се-ребристый; clRed — красный; clLime — салатный; clBlue — синий;clFuchsia — ярко-розовый; clAqua — бирюзовый; ciwhite — белый)
Style Стиль (вид) линии. Линия может быть: psSolid— сплошная; psDash —пунктирная (длинные штрихи); psDot — пунктирная (короткие штрихи);psDashDot — пунктирная (чередование длинного и короткого штри-хов); psDashDotDot — пунктирная (чередование одного длинного идвух коротких штрихов); psClear— не отображается (используется,если не надо изображать границу, например, прямоугольника)
Width Толщина линии задается в пикселах. Толщина пунктирной линии неможет быть больше 1
C++ Builder — краткий справочник 307
Brush
Объект Brush является свойством объекта canvas. Свойства объекта Brush(табл. П1.28) определяют цвет, стиль закраски внутренних областей конту-ров, вычерчиваемых методами вывода графических примитивов.
Таблица П1.28. Свойства объекта Brush
Свойство Определяет
Color Цвет закрашивания замкнутой области
Style Стиль (тип) заполнения области (bsSolid— сплошная заливка;bsClear— область не закрашивается; bsHorizontal— горизонтальнаяштриховка; bsVertical — вертикальная штриховка; bsFDiagonal —диагональная штриховка с наклоном линий вперед; bsBDiagonal —диагональная штриховка с наклоном линий назад; bsCross — гори-зонтально-вертикальная штриховка, в клетку; bsDiagCross — диаго-нальная штриховка, в клетку)
ФункцииВ этом разделе приведено краткое описание наиболее часто используемыхфункций. Подробное их описание можно найти в справочной системе.
Функции ввода и вывода
Таблица П1.29. Функции ввода и вывода
Функция Описание
InputBox(Заголовок,Подсказка,Значение)
ShowMessage(s)
MessageDlg(s,t,b,h)
В результате выполнения функции на экране появляет-ся диалоговое окно, в поле которого пользователь мо-жет ввести строку символов. Значением функции явля-ется введенная строка. Параметр Значение задает зна-чение функции «по умолчанию», т. е. строку, котораябудет в поле редактирования в момент появления окна
Процедура ShowMessage выводит окно, в котором нахо-дится сообщение s и командная кнопка ОК
Выводит на экран диалоговое окно с сообщением sи возвращает код кнопки, щелчком на которой пользо-ватель закрыл окно. Параметр t определяеттип окна: mtWarning — Внимание; mtError — ошибка;mtlnformation — информация; mtConfirmation — за-прос; mtCustom— пользовательское (без значка).
305 Приложение 1
Таблица П1.29 (окончание)
Функция Описание
(прод.) Параметр ь (множество — заключенный в квадратныескобки список констант) задает командные кнопкидиалогового окна (mbYes, mbNo, mbOK, mbCancel,mbHelp, mbAbort, mbRetry, mblgnore И mbAll). Пара-метр h задает раздел справочной системы программы,который появится в результате нажатия кнопки Helpили клавиши <F1>. Если справочная система не ис-пользуется, значение параметра должно быть 0. Значе-ние функции равно коду кнопки, которую нажал поль-зователь (mrAbort, mrYes, mrOk, mrRetry, mrNo,mrCancel, mrlgnore ИЛИ mrAll)
Математические функции
Таблица П1.30. Математические функции
Функция Значение
abs (n) Абсолютное значение п
sqrt (n) Квадратный корень из п.
ехр (п) Экспонента п
random[vi9] (n) Случайное целое число в диапазоне от 0 до п-1 (передпервым обращением к функции необходимо вызватьфункцию randomize ( ) , которая выполнит инициализа-цию программного генератора случайных чисел)
sin (а) Синус выраженного в радианах угла а
cos (а) Косинус выраженного в радианах угла а
tan (а) Тангенс выраженного в радианах угла a
asin (n) Угол (в радианах), синус которого равен п
acos (n) Угол (в радианах), косинус которого равен п
atan (n) Угол (в радианах), тангенс которого равен п
Обратите внимание: для того чтобы в программе были доступны приведен-ные функции, в ее текст надо включить директиву #inciude <math.h>.
C++ Builder — краткий справочник 309
Величина угла тригонометрических функций должна быть выражена в ра-дианах. Для преобразования величины угла из градусов в радианы использу-ется формула (а -3.1415256) / 180, где а- величина угла в градусах;3.1415926— число «пи». Вместо константы 3.1415926 можно использоватьстандартную именованную константу M_PI. Константа M_PI определена вфайле math.h.
Функции преобразования
Таблица П1.31. Функции преобразования
Функция Значение функции
IntToStr(k)
FloatToStr(n)
FloatToStrF(n, f, k,m)
StrToInt(s)
StrToFloat(s)
Строка, являющаяся изображением целого k
Строка, являющаяся изображением вещественного n
Строка, являющаяся изображением вещественного п.При вызове функции указывают: f — формат; k — точ-ность; т— количество цифр после десятичной точки.Формат определяет способ изображения числа:ffGeneral— универсальный; ffExponent— научный;f f Fixed — с фиксированной точкой; f fNumber — с раз-делителями групп разрядов; ffCurrency— финансо-вый. Точность — нужное общее количество цифр: 7 илименьше для значения типа single, 15 или меньше длязначения типа Double и 18 или меньше для значениятипа Extended
Целое число, изображением которого является строка s
Дробное число, изображением которого является стро-ка s
Функции манипулированиядатами и временемБольшинству функций манипулирования датами в качестве параметра пере-дается переменная типа TDateTime, которая хранит информацию о дате ивремени.
ДЛЯ ТОГО ЧТОбЫ В Программе были ДОСТУПНЫ фуНКЦИИ DayOf, WeekOf, MonthOf
и др., в ее текст надо включить директиву linciude <Dateutiis.hpp[L29]>.
310 Приложение 1
Функция
Таблица П1.32. Функции манипулирования датами и временем
Значение
Now ()
DateToStr(dt)
TimeToStr(dt)
DayOf(dt)
MonthOf(dt)
WeekOf(dt)
YearOf(dt)
DayOfWeek(dt)
StartOfWeek(w)
HourOf(dt)
MinuteOf(dt)
SecondOf(dt)
DecodeDate(dt,y,m, d)
DecodeTime(dt,h,m, s,ms)
FormatDateTime(s,dt)
Системная дата и время — значение типа TDateTime
Строка символов, изображающая дату в форматеdd.mm.yyyy
Строка символов, изображающая время в форматеhh:mm:ss
День (номер дня в месяце), соответствующий дате,указанной в качестве параметра функции
Номер месяца, соответствующий дате, указаннойв качестве параметра функции
Номер недели, соответствующий дате, указаннойв качестве параметра функции
Год, соответствующий указанной дате
Номер дня недели, соответствующий указанной дате:1 — воскресенье, 2 — понедельник, 3 — вторник и т. д.
Дата первого дня указанной недели
Количество часов
Количество минут
Количество секунд
Возвращает год, месяц и день, представленные от-дельными числами
Возвращает время (часы, минуты, секунды и милисе-кунды), представленное отдельными числами
Строка символов, представляющая собой дату иливремя. Способ представления задает строка форматаs, например, строка dd/mm/yyyy задает, что значени-ем функции является дата, а строка hh:mm— время
События
Таблица П1.33. События
Событие Происходит
OnClick При щелчке кнопкой мыши
C++ Builder — краткий справочник 311
Таблица П1.33 (окончание)
Событие Происходит
OnDblClick При двойном щелчке кнопкой мыши
OnMouseDown При нажатии кнопки мыши
OnMouseUp При отпускании кнопки мыши
OnMouseMove При перемещении мыши
OnKeyPress При нажатии клавиши клавиатуры
OnKeyDown При нажатии клавиши клавиатуры. События OnKeyDown иOnKeyPress — это чередующиеся, повторяющиеся события, кото-рые происходят до тех пор, пока не будет отпущена удерживаемаяклавиша (в этот момент происходит событие OnKeyUp)
OnKeyUp При отпускании нажатой клавиши клавиатуры
OnCreate При создании объекта (формы, элемента управления). Процедураобработки этого события обычно используется для инициализациипеременных, выполнения подготовительных действий
OnPaint При появлении окна на экране в начале работы программы, послепоявления части окна, которая, например, была закрыта другимокном и в других случаях. Событие сообщает о необходимостиобновить (перерисовать) окно
OnEnter При получении элементом управления фокуса
OnExit При потере элементом управления фокуса
Исключения
Таблица П1.34. Типичные исключения
Тип исключения Возникает
EConvertError
EDivByZero
EZeroDivide
При выполнении преобразования, если преобразуемая вели-чина не может быть приведена к требуемому виду. Наиболеечасто возникает при преобразовании строки символов в число
Целочисленное деление на ноль. При выполнении операциицелочисленного деления, если делитель равен нулю
Деление на ноль. При выполнении операции деления наддробными операндами, если делитель равен нулю
312 Приложение 1
Таблица П1.34 (окончание)
Тип исключения Возникает
EFOpenError При обращении к файлу, например при попытке загрузитьфайл иллюстрации при помощи метода LoadFrcmFile. Наи-более частой причиной является отсутствие требуемого файлаили, в случае использования сменного диска, отсутствие дис-ка в накопителе
ElnOutError При обращении к файлу, например при попытке открыть длячтения (инструкция reset) несуществующий файл
EDBEngineError При выполнении операций с базой данных, например при по-пытке выполнить SQL-запрос к несуществующей таблице
ПРИЛОЖЕНИЕ 2
Содержимоекомпакт-диска
Прилагаемый к книге компакт-диск содержит проекты (см. табл. П2.1),приведенные в книге в качестве примеров. Каждый проект находится в от-дельном каталоге.
Помимо файлов проекта, в каждом каталоге находится выполняемый файл,что позволяет увидеть, как работает программа, без загрузки проекта вC++ Builder.
Большинство программ не требуют для своей работы никаких дополнитель-ных программных компонентов (библиотек) и могут быть запущены непо-средственно с CD-ROM.
Некоторые программы, например программы работы с базами данных, тре-буют, чтобы в системе был установлен процессор баз данных BorlandDatabase Engine (устанавливается автоматически в процессе установки накомпьютер C++ Builder) и зарегистрирован псевдоним соответствующейбазы данных. Создать псевдоним базы данных можно при помощи SQLExplorer или BDE Administrator, которые также автоматически устанавлива-ются на компьютер в процессе установки C++ Builder.
Для активной работы с примерами, для того чтобы иметь возможность вно-сить в них изменения, необходимо скопировать каталоги проектов на жест-кий диск компьютера.
Таблица П2.1. Содержимое компакт-диска
Каталог/Проект Краткое описание Глава
Сила тока/Amper Программа вычисляет силу тока в электриче- 2ской цепи. Демонстрирует обработку событияClick, ввод из поля редактирования, вывод вполе метки, использование функций strToFloatи FloatToStrF
314 Приложение 2
Таблица П2.1 (продолжение)
Каталог/Проект Краткое описание Глава
Сила тока/Amperl
Вывод текста/TextOutDemo
График функции/grf
Просмотр иллюстраций/ShowPic
Битовый образ/BitMap
Фоновый рисунок/Back
Кораблик/Ship
Полет над городом /Flight
Полет над городом /Flight»!
Баннер/Baner
Программа вычисляет силу тока в электриче-ской цепи. Демонстрирует: обработку событияKeyPress; исключения EZerroDevide (делениена ноль) при помощи инструкции try … catch
Демонстрирует вывод текста на поверхностьформы при помощи метода TextOutA, обра-ботку событий OnPaint и OnFormResize
Строит график функции. Демонстрирует: ис-пользование методов Line, MoveTo, TextOutA;обработку события OnFormResize
Программа позволяет просматривать иллюст-рации. Демонстрирует: использование компо-нента Image; использование функцийFindFirst и FindNext; доступ к стандартномуокну Обзор папок
Формирует картинку из битовых образов, за-груженных из файла. Демонстрирует: загрузкуи вывод битовых образов; влияние свойстваTransparent
Формирует фоновый рисунок путем много-кратного вывода битового образа на поверх-ность формы
Простая мультипликация (изображение фор-мируется из графических примитивов). Демон-стрирует использование методов, обеспечи-вающих вычерчивание графических примити-вов; использование компонента Timer
Мультипликация, элементы которой загружа-ются из bmp-файла. Демонстрирует вывод наповерхность формы иллюстраций, загруженныхиз файла
Мультипликация, элементы которой загружа-ются из ресурса программы. Демонстрируетзагрузку битовых образов из ресурса про-граммы
Выводит на поверхность формы простой «муль-тик» — (баннер), все кадры которого находятсяв одном bmp-файле. Демонстрирует использо-вание метода CopyRect
3
Содержимое компакт-диска 315
Таблица П2.1 (продолжение)
Каталог/Проект Краткое описание Глава
Просмотр анимации/ShowAVI
Звуки Windows/WinSound
CDPIayer/CDPIayer
VideoPlayer
Ежедневник/org
Компонент
Консольное приложение/Game
Справочная система
Сапер
Программа позволяет просмотреть, в том чис- 4ле и по кадрам, простую (не сопровождаемуюзвуком) анимацию (содержимое avi-файла).Демонстрирует использование компонентовAnimate И FileOpen
Программа позволяет прослушать звуковые 4фрагменты, находящиеся в wav-файлах. Де-монстрирует использование компонентаMediaPlayer, использование функций FindFirstи FindNext для формирования списка файлов
Полнофункциональный проигрыватель CD-дис- 4ков. Демонстрирует использование компонентаMediaPlayer
Простой видеоплеер. Демонстрирует исполь- 4зование компонента MediaPlayer для воспро-изведения небольших видеороликов (форматAVI) и использование компонента SpeedButton
База данных «Ежедневник». Комплексный при- 5мер. Демонстрирует использование компонен-тов Table, DataSource, Query, DBGrid ИDBNavigator
Компонент программиста, предназначенный 6для ввода целых или дробных (в зависимостиот настройки компонента) чисел в заданномдиапазоне. В каталоге находится модуль ком-понента (NkEdit.cpp), программа тестированиямодуля компонента (tk.bpr) и программа тести-рования компонента (Amper4.bpr).Замечание. Перед тем как открыть проектAmper4, необходимо установить компонентNkEdit в пакет dclusr
Игра «Угадай число». Пример консольного при- 7ложения
Справочная система для программы «Сапер». 8Каталог содержит файлы справочной инфор-мации и файлы проектов, необходимые длясоздания справочной системы в форматах HLPиСНМ
Игра «Сапер». Демонстрирует работу с графи-кой, использование компонента Menu, исполь-зование рекурсии, вывод справочной инфор-мации, запуск внешних программ
10
316 Приложение 2
Таблица П2.1 (окончание)
Каталог/Проект Краткое описание Глава
Проверка знаний
Очистка диска
Система тестирования. Демонстрирует исполь- 10зование компонентов, создаваемых во времяработы программы
Утилита «Очистка диска». Демонстрирует ис- 10пользование рекурсии
‘
Рекомендуемая литература
1. Вирт Н. Алгоритмы и структуры данных / Пер. с англ. — М.: Мир,1989. — 360 с., ил.
2. Гринзоу Лу. Философия программирования для Windows 95/NT / Пер.с англ. — СПб.: Символ-Плюс, 1997. — 640 с., ил.
3. Зелковиц М., Шоу А., Гэннон Дж. Принципы разработки программногообеспечения / Пер. с англ. — М.: Мир, 1982. — 386 с., ил.
4. Культин Н. Б. C/C++ в примерах и задачах. — СПб.: БХВ-Петербург,2001. — 288 с., ил.
5. Практическое руководство по профаммированию / Пер. с англ. Б. Мик,П. Хит, Н. Рашби и др.; под ред. Б. Мика, П. Хит, Н. Рашби. — М.:Радио и связь, 1986. — 168 с., ил.
6. Страуструп Б. Язык профаммирования C++. — М.: Радио и связь, 1991.
7. Фокс Дж. Профаммное обеспечение и его разработка / Пер. с англ. -М.: Мир, 1985. — 368 с., ил.
Предметный указатель
Alias 137Alias Manager 137
ВBDE 144Borland Database Engine 144Brush 306, 307
I
Image Editor 94, 174InstallShield Express 162
MMacromedia Flash 128Microsoft Help Workshop 193Microsoft HTML Help Workshop 193
Canvas 78, 284, 294CD Player 115ClientHcight 284ClientWidth 283
Database Desktop 137О настройка 142DecimalSeparator 171
Pen 306printf 183
sSQL-запрос 154
ТTransparent 306
ВАбсолютное значение 308
База данных:О добавление записи 150О локальная 135О просмотр 147О псевдоним 137О создание таблицы 138О тип поля 140, 141О удаление записи 150О удаленная 135
Внешняя программа:О запуск 265Вывод на поверхность формы:О картинка 304О текст 304
Графический примитив 65
дДуга 305
Предметный указатель 319
ИИллюстрация:О добавление к форме 235Исключение:О EConvertError 311О EDivByZero 44, 311О EFOpen Error 312О ElnOutError 44О ERangeError 44О EZeroDivide 44, 311
ККарандаш 306Квадратный корень 308Кисть 306Компонент:О Animate 102, 295О Button 24, 286О CheckBox 289О ComboBox 291О DataSource 144, 300О DBEdit300О DBGrid 147, 301О DBMemo 300О DBNavigator 150, 302О DBText 300О Edit 19, 285О Form 283О Image 293О Label 22, 284О ListBox290О Main Menu 252О MediaPlayer 109О Memo 287О Query 153, 299О RadioButton 288О SpeedButton 296О StringGrid 292О Table 144, 298О Timer 294О UpDown 298О программиста 163Косинус 308Круг 305
ЛЛиния 62, 304О замкнутая 304О ломаная 63, 304
О тип 64О толщина 64О цвет 64
мМетод:О CopyRect98О Ellipse 63, 69О FillRect 68О LineTo 62, 66О LoadFromFile 78О LoadFromResourceName 97О MoveTo 66О Pie 70О Polygon 68О Polyline 63О PolyLine 66О Rectangle 62, 67О ShowModal 264О TextOut71Многоугольник 304
ООкружность 63, 305
пПакет компонентов 174Преобразование AnsiToChar 265Прозрачность 306Проигрыватель CD 115Прямоугольник 62, 305Псевдоним БД 137О динамический 160О создание 160
Редактор образов 174Редактор файла ресурсов 94Рекурсия 280Ресурс 174
Свойство:О Brush 64Продолжение рубрики см. на с. 320
320 Предметный указатель
Свойство (прод.):0 Canvas 620 Cursor 2650 HelpContext 2010 HelpFile 20 1,2610 Pen 640 Pixels 74Синус 308Случайное число 308Событие 260 OnClick260 OnCreate 270 OnDblClick260 OnEnter 270 OnExit 270 OnKeyDown 260 OnKeyPress 260 OnKeyUp270 OnMouseDown 260 OnMouseMove 260 OnMouseUp 260 OnPaint 27, 630 OnTimerSS0 обработка 27, 48Спецификатор формата 1 84Ссылка на раздел справки 195
Т
Тип TRect 68
УЛ 7
0
0
00
0
00
0
0
000
0
00
0
0
00
0
0
0
0
00
0
0
00
0
00
0
0
DayOf310DayOfWeek 310DecodeDate 310DecodeTime 310Exp 308ExtractFilePatch 160FloatToStr 309FloatToStrF 309FormatDateTime 156, 310HourOf310InputBox 307IntToStr 309MessageDlg 46, 307, 308MinuteOf310MonthOf310Now 156, 310ParamStr 160Random 308Rect 68, 99scanf 186SecondOf310SelectDirectory 282ShellExecute 265ShowMessage 45, 307Sin 308Sqrt 308StaitOfWeek 310StrToFloat 309StrToInt 309TimeToStr 310WeekOf310WinExec 215WinHelp 202, 262YearOf 310
Установочная дискетаО создание 162
Ф
Файл:О пакет компонентов (DPK) 174О ресурсов компонента 174Функция:О Abs308О AddStandardAlias 160О Bounds 99О c_str 265О Cos 308
О cprintflSSО DateToStr 310
Цвет:О закраски 64, 306О линии 64, 306
эЭллипс 63, 305
ЯЯзык SQL 153