ON KEY LABEL F1 HELP ID _SCREEN.ActiveForm.HelpContextID
ENDPROC
zPROCEDURE optTree.Click
THISFORM.pgf1.ActivePage = 1
ENDPROC
PROCEDURE optList.Click
LOCAL lo
lo = THISFORM.pgf1.pagList.cboFilter
IF lo.ListCount = 0
#DEFINE ALL_LOC "All"
lo.AddListItem(ALL_LOC, 1, 1)
lo.AddListItem("-1", 1, 2)
lo.ListIndex = 1
SELECT reftext
FOR i = 1 TO RECCOUNT()
lo.AddListItem(reftext.text, i + 1, 1)
lo.AddListItem(ALLTRIM(STR(reftext.xref_id)), i + 1, 2)
SKIP
ENDFOR
ENDIF
SELECT solution.text, solution.key FROM SOLUTION WHERE type != "N" ORDER BY text INTO ARRAY THISFORM.aSamples
lo.Parent.lstSamples.Requery
lo.ListIndex = 1
THISFORM.pgf1.ActivePage = 2
ENDPROC
commandbutton
solutions.pgf1.pagTree
cmdCollapseAll
commandbutton
qhj ZtuQha;jdfn[iaetr
MS Sans Serif
oleImages
HideSelection
Indentation
MousePointer
BorderStyle
.OLEObject = C:\WINNT35\System32\COMCTL32.OCX
commandbutton
Top = 9
Left = 399
Height = 18
Width = 15
FontBold = .F.
FontName = "Courier New"
FontSize = 11
Caption = "-"
TabIndex = 3
ToolTipText = "Collapse All"
Name = "cmdCollapseAll"
PROCEDURE Click
o = THISFORM.pgf1.pagTree.oleTree
FOR i = 1 TO o.Nodes.Count
o.Nodes(i).Expanded = .F.
ENDFOR
ENDPROC
PROCEDURE InteractiveChange
IF THIS.Value = "-1"
SELECT solution.text , solution.key FROM SOLUTION ;
WHERE type != "N" ORDER BY text INTO ARRAY THISFORM.aSamples
SELECT solution.text, solution.key FROM solution ;
WHERE solution.key = ;
SOME(select xref.key from xref where xref.xref_id = VAL(THIS.Value)) ;
ORDER BY text INTO ARRAY THISFORM.aSamples
ENDIF
THIS.Parent.lstSamples.Requery
THIS.Parent.lstSamples.ListIndex = 1
ENDPROC
Top = 9
Left = 382
Height = 18
Width = 15
FontBold = .F.
FontName = "Courier New"
FontSize = 11
Caption = "+"
TabIndex = 2
ToolTipText = "Expand All"
Name = "cmdExpandAll"
FontBold = .F.
FontName = "MS Sans Serif"
FontSize = 8
BoundColumn = 2
ColumnCount = 2
ColumnWidths = "411,0"
Height = 23
Left = 5
Style = 2
TabIndex = 1
Top = 28
Width = 411
Name = "cboFilter"
FontBold = .F.
FontName = "MS Sans Serif"
FontSize = 8
BoundColumn = 2
ColumnCount = 2
ColumnWidths = "470,0"
RowSourceType = 5
RowSource = "THISFORM.aSamples"
Height = 139
Left = 5
TabIndex = 2
Top = 55
Width = 411
IntegralHeight = .T.
Name = "lstSamples"
PROCEDURE DblClick
IF THISFORM.cmdRun.Enabled
THISFORM.cmdRun.Click
ENDIF
ENDPROC
PROCEDURE UIEnable
LPARAMETERS lEnable
IF lEnable AND !EMPTY(solutions.descript)
THIS.Value = solutions.key
ENDIF
IF !lEnable
o = THISFORM.pgf1.pagTree.oleTree
FOR i = 1 to o.Nodes.Count
IF o.Nodes(i).Key = ALLTRIM(THIS.Value)
o.Nodes(i).Selected = .T.
EXIT
ENDIF
ENDFOR
ENDIF
ENDPROC
PROCEDURE ProgrammaticChange
THIS.InteractiveChange
ENDPROC
PROCEDURE InteractiveChange
SELECT SOLUTIONS
LOCATE FOR Key = THIS.Value
IF EMPTY(file)
THISFORM.cmdRun.Enabled = .F.
THISFORM.cmdSee.Enabled = .F.
THISFORM.cmdRun.Enabled = .T.
THISFORM.cmdSee.Enabled = .T.
ENDIF
THISFORM.Refresh
ENDPROC
THISFORM
CMDRUN
ENABLED
CLICK
LENABLE
SOLUTIONS
DESCRIPT
VALUE
THISFORM
PAGTREE
OLETREE
NODES
COUNT
SELECTED
INTERACTIVECHANGE
SOLUTIONS
VALUE
THISFORM
CMDRUN
ENABLED
CMDSEE
REFRESH
DblClick,
UIEnabley
ProgrammaticChange
InteractiveChange
HELP ID (VAL(solutions.key))
MODIFY FORM (ALLTRIM(solutions.path) + "\" + ALLTRIM(solutions.file)) METHOD &cMacro
testdata
THISFORM
VISIBLE
SOLUTIONS
METHOD
CMACRO
TESTDATA
Click,
ButtonCount = 2
BackStyle = 0
BorderStyle = 0
Value = 1
Height = 28
Left = 11
Top = 18
Width = 381
TabIndex = 0
Name = "opg1"
Option1.FontBold = .F.
Option1.FontName = "MS Sans Serif"
Option1.FontSize = 8
Option1.BackStyle = 0
Option1.Caption = "View samples by \<outline"
Option1.Value = 1
Option1.Height = 15
Option1.Left = 8
Option1.Top = 8
Option1.Width = 130
Option1.AutoSize = .T.
Option1.Name = "optTree"
Option2.FontBold = .F.
Option2.FontName = "MS Sans Serif"
Option2.FontSize = 8
Option2.BackStyle = 0
Option2.Caption = "View samples by \<filtered list"
Option2.Value = 0
Option2.Height = 15
Option2.Left = 174
Option2.Top = 8
Option2.Width = 145
Option2.AutoSize = .T.
Option2.Name = "optList"
PAGTREE
OLETREE
PARENT
ONODE
NODES
IMAGE
SORTEDO
THIS.C_SOLUTIONS1b
THISFORM
KEEPHELP
C_SOLUTIONS1
RESTOREHELP
C_SOLUTIONS1
SAVEHELP
THIS.pgf1.pagTree.oleImagesb
Visual FoxPro could not load ActiveX controls used by this form. Try reinstalling sample applications.
THIS.pgf1.pagTree.oleTreeb
Visual FoxPro could not load ActiveX controls used by this form. Try reinstalling sample applications.
PAGTREE
OLEIMAGES
OLETREE
FILLTREE
filltree,
DeactivateK
Activate
Destroy
Could not run view sample: CE
NERROR
CMETHOD
NLINE
SOLUTIONS
HELP ID (VAL(solutions.key))
HELP ID (VAL(solutions.key))
Arial
Results of Query CC
.QPR
HELP ID (VAL(solutions.key))
Arial
Results of View CC
testdata
THISFORM
VISIBLE
SOLUTIONS
KEEPHELP
BROW_WIND
TESTDATA
_VIEW
Error,
Click
DDDDDD@
|CONTEXT
|CTXOMAP
|FONT
|KWBTREE
|KWDATA
|KWMAP
|SYSTEM
|TOPIC
|TTLBTREE
|bm10
|bm11
|bm12
|bm13
|bm14
|bm15
wwpwp
wpwp w
pwp w
wwppw
pwpwpw
pwwppwwpw
pwppw
pwpwpw
wwpwpw
pwppw
pwwpw
pwppw
wwx4w
DDODODOD
ODOODOOD
ODODOD
ODOOD
OODOODOOD
ODDOD
OODOD
ODDOD
ODDOOD
DODDODD
ODOOD
DDODDODOD
pwppw
ppwpp.w
pwppw
ppwppwppw
pwppwppw
pwppw
ppwpp.w
ppwppwpwp
pwwpwppwpww
wwppw
pwppw
ppwpp.w
ppwppwpw
pwppwpww
pwppw
ppwpp.w
wpwppw
ppwpp
ppwpww
pwpww
Microsoft Word
System
Times New Roman
"Arial
Option Button Group
Page Frame
00 99
DA9919;
K:H!-
?pDDO
DDGpO
DDGpL
DD@wD@
wwxwwx
wDwwxww
wwxwwx
wDwwxww
Visual FoxPro Solutions
BrowseButtons()
secondary
Components
Solutions Sample:
Solutions Sample
See Also
List of Components
The Visual FoxPro Solutions sample is a collection of independent samples designed to illustrate particular features of Visual FoxPro. As you go through these samples, you can see how to accomplish specific tasks in Visual FoxPro.
To run the Solutions Sample application
Enter the following in the Command window:
DO (HOME() + 'samples\solution\solution')
The samples are organized into the following categories: ActiveX, Controls, Databases, Forms, Menus, Reports, Toolbars, and WinAPI. To see all of the components in this treeview, choose the
Expand All
button and scroll through the components.
When you select a component, you can:
Read a brief description of the sample in the description area at the bottom of the main Solutions form,
Run the sample by choosing
Run Sample
See the code by choosing
See Code
After you close the form or designer that is opened, you are returned to the main Solutions form.
See Also
How the Solutions Sample Works
How the Solutions Sample WorksH
How the Solutions Sample Works
Each component of the Solutions sample is listed in SOLUTION.DBF. This table stores the following:
The key and parent key ids required to add nodes to a treeview control.
The image id in the ImageList control for the picture to be displayed beside the item in the treeview control.
The file name and path of the components.
The method to open when you choose
See Code
The description to be displayed in the Visual FoxPro Solutions form.
There are two additional tables used to provide filtered list access to the components: XREF.DBF and REFTEXT.DBF.
The FillTree method of the SOLUTION.SCX reads the information from SOLUTION.DBF to fill the treeview control.
Each form in the Solutions suite contains an object based on the c_solutions class in SOLUTION.VCX. This class provides a single place for environment and localization settings. When the c_solutions object is destroyed, old settings are restored and, if the Solutions form exists, it is redisplayed.
The custom class is used in the Solutions sample because it provides greater flexibility: you can add it to existing forms, and, if you want, you can delete it from the forms in the Solutions suite and customize the forms for your own use. Instead of using a custom class to manage the environment settings, you can provide this functionality in one form class from which all forms in t'
he Solutions sample are derived.
Form records in SOLUTION.DBF have a value of
stored to the type field. In the code associated with cmdRun and cmdSee, the form is run or modified.
* extract from cmdRun.Click
CASE solutions.type = "F" && form
DO FORM (ALLTRIM(solutions.path) + "\" + ALLTRIM(solutions.file))
In the Data Environment of SOLUTION.SCX, the cursor for SOLUTION.DBF is given an alias of
Solutions.
Reports and Queries
Report records in SOLUTION.DBF have a value of
stored to the type field and queries have a type of
. You can run the reports and queries in the code associated with cmdRun, and you can modify them in the code associated with cmdSee.
* extract from cmdRun
CASE solutions.type = "R" && report
REPORT FORM (ALLTRIM(solutions.path) + "\" + ALLTRIM(solutions.file)) PREVIEW NOCONSOLE
THISFORM.Visible = .T.
Running a query opens the result set in a Browse window. By default, a Browse is displayed in the currently active window, which, in this sample would be the Solutions form. To display the Browse in a separate window, this code defines and activates another window, runs the query, then releases the separate window:
CASE solutions.type = "Q" && query
#DEFINE TITLE_LOC "Results of query "
DEFINE WINDOW brow_wind FROM 1,1 TO 30, 100 TITLE TITLE_LOC + UPPER(ALLTRIM(file))+ ".QPR " ;
FLOAT GROW MINIMIZE ZOOM CLOSE FONT "Arial",10
ACTIVATE WINDOW brow_wind NOSHOW
DO (ALLTRIM(solutions.path) + "\" + ALLTRIM(solutions.file) + ".QPR")
RELEASE WINDOW brow_wind
THISFORM.Visible = .T.
ENDCASE
Components in the Solutions Sample ApplicationX
Components in the Solutions Sample Application
Add and Remove Items in a Treeview Control
Add Items Interactively to a List Box
Add Menu Items at Run Time
Add New Items to a Combo Box
Allow Users to Choose List Values
Allow Users to Drag and Drop Controls
Automate a Microsoft Excel Spreadsheet
Automate a Microsoft Word Document in a Form
Automate Microsoft Word and Excel
Change Pages When a User Chooses a Button
Change the Number of Tabs at Run Time
Coordinate Menu Items and Toolbar Buttons
Create a 1-To-Many Data Entry Form
Create a Default Unique Id Value for a Field
Create a Query-By-Example Form
Create a Single Table Data Entry Form
Create an SDI Form
Create Small Indexes Using BINTOC( )
Create Dynamic Shortcut Menus
Customize the Open Dialog Box
Disable or Display a Check Beside a Menu Item
Display a Stop Watch
Display a System Clock
Display Calculated Values in a Column
Display Child Records from a Relationship
Display Controls in
a Grid
Display Different Pages Without Tabs
Display Line Animation on a Form
Display Multiple Columns in a List Box
Display Pictures in a List
Display Pictures in an Image Control
Display Shortcut Menus
Display System Information
Draw Lines and Shapes on a Form
Dynamically Format Grid Columns
Edit a Memo Field or Text File
Execute Commands at Specified Intervals
Fill a List with Values from Different Sources
Format Input and Validate Data in a Text Box
Get Application Information from the Windows Registry
Get Version Information
Graph Equations on a Form
Index on Expressions
Interactively Build a SELECT Statement
Manipulate Display Characteristics of a Graph
Move Items Between List Boxes
Multiselect Items in a List Box
Nest Transactions
Open Dialog Box Flag Values
Open Multiple Files Interactively
Pass Parameters between Forms
Print a Percent of Total in a Report
Print Customer Mailing Labels
Print Data Dictionary Information
Print in Catalog Format
Print Product Orders By Quarter
Play an AVI File in an ActiveX Control
Play Multimedia Files Using MCI Commands
Present a User with Multiple Choices
Print an Invoice
Programmatically Check Table Properties
Programmatically Manipulate Objects
Programmatically Manipulate Text
Provide a Hierarchical Display of Items
Provide What
s This Help on a Form
Read and Write Visual FoxPro Registry Values
Read ODBC Registry Values
Refresh a Graph in a Form
Resize and Reposition Controls at Run Time
Return a Value from a Form
Run Multiple Instances of a Form
See Check Box Design Options
See Command Button Design Options
Select Customers in a Specific Country
Select Records from a Full Outer Join
Select Records from a Left Outer Join
Select Records from a Nested Join
Select Records from a Right Outer Join
Select Records from an Inner Join
Select Records from Both Inner and Outer Joins
Select the Ten Worst Selling Products
Select the Top Ten Best Selling Products
Send Mail
Sort List Box Items
Sort or Order A Table At Run Time
Use API Functions that Require a STRUCT
Use API Functions that Require Pointers to Arrays
Use Conditional Formatting in a Report
Use Slider and Status Bar Controls
Use the RichText Control
View Type Library Information
Add and Remove Items in a Treeview ControlT
Add and Remove Items in a Treeview Control
File: SAMPLES\SOLUTION\OLE\BLDTREE.SCX
A treeview control displays a collection of Node objects, each of which consists of a label and an optional bitmap. After creating a treeview control, you can add, remove, arrange, and otherwise manipulate Node objects by setting properties and invoking methods.
This sample illustrates adding nodes to a treeview control, deleting nodes, selecting nodes programmatically, writing a treeview hierarchy to a table, and reading a treeview hierarchy from a table.
Adding Nodes
Each node in a treeview control needs to have a unique key that is a character string, generated by the NewKey method in this sample form.
The Add method of the treeview control is used to add new nodes. The code associated with the Click event of cmdNewNode adds a root level node using the Add method:
o = THISFORM.oleTree
o.Nodes.Add(,1,THISFORM.NewKey(),"Click to edit text",0)
The code associated with the Click event of cmdNewChild adds a node as a child of the currently selected node:
o = THISFORM.oleTree
IF !ISNULL(o.SelectedItem) THEN
o.Nodes.Add(o.SelectedItem.Key, 4, THISFORM.NewKey(), "Click to edit text",0)
ENDIF
Deleting Nodes
You can delete all of the nodes by calling the Clear method:
THISFORM.oleTree.Nodes.Clear
Or you can use the Remove method to delete selected nodes. All children of the deleted node are also deleted.
To save your treeview hierarchy in a table so you can reload it and edit it, loop through all the nodes in the treeview control and write the Key, the parent node
s Key, and the Text to the appropriate fields of a table.
FOR i = 1 TO loNodes.Count
IF ISNULL(loNodes.Item(i).Parent)
lcParent = "0_" && Root
lcParent = loNodes.Item(i).Parent.Key
ENDIF
INSERT INTO (lcDBFName) VALUES ;
(loNodes.Item(i).Key, ;
lcParent, ;
loNodes.Item(i).Text)
ENDFOR
To reconstruct the treeview hierarchy, scan through the records in the table, using the parent key, key, and text values that you previously stored.
* Fill the TreeView control with values in the table.
This sample demonstrates adding and removing list box items. When a user types text in the text box and presses ENTER, the text in the text box is added to the list and the cursor is returned to the text box so that the user can enter another value.
To allow a user to interactively add items to a list, use the AddItem method. In the sample, the following code in the text box KeyPress event adds the text in the text box to the list box and clears the text box when the user presses ENTER:
PARAMETERS nKeyCode, nShiftCtrlAlt
IF nKeyCode = 13 && Enter Key
THISFORM.lstAdd.AddItem (This.Value)
THIS.Value = ""
ENDIF
The following code in the DblClick event of the list box removes the item that was double-clicked, sending the value to the text box:
This sample illustrates adding user-entered text to a combo box drop-down and providing lookup capability.
Adding User Text to a Combo Box Drop-Down
A combo box allows a user to enter text or select an item from a drop-down list. You can also add the text a user types in the combo bE
ox as a new item in the drop-down list so the user won
t have to type the same text multiple times.
There are multiple ways to add user text to the drop-down list of a combo box, depending on the RowSourceType property setting of the combo box. In this sample, the RowSourceType of the combo boxes is 1 - Value. If the value the user enters isn
t already in the drop-down list for cboCombo, the following code adds a comma and the new value to the RowSource:
cCountryName = ALLTRIM(Custs.Country)
IF ATC(m.cCountryName,THIS.RowSource)=0 AND !EMPTY(m.cCountryName)
THIS.RowSource=THIS.RowSource+","+m.cCountryName
ENDIF
The combo-box in the
Programmatically Manipulate Text
example has a RowSourceType of 0 - None. The following code in the Valid event of cboSearchString in SAMPLES\SOLUTION\CONTROLS\TXT_EDT\TEXT.SCX adds a user-entered value to the drop-down list of the combo box:
IF !EMPTY(THIS.Text)
FOR i = 1 TO THIS.ListCount
IF THIS.List(i) = THIS.Text
RETURN
ENDIF
ENDFOR
THIS.AddItem(THIS.Text)
ENDIF
If the RowSource of the combo box is an array, you need to add the user text to the array and call the Requery method of the combo box.
If the RowSource is a table or a cursor, you need to add a record, REPLACE the blank field with the user-entered value and Requery the combo box.
Provide Lookup Capability
In addition to illustrating how to add items to a combo box, this sample demonstrates three ways of allowing a user to filter a table for particular values. A user can:
Enter values in a combo box.
Select an item from a drop-down list.
Enter partial values in a combo box for incremental search.
Enter Values in a Combo Box
The key code is associated with the LostFocus event of cboCombo. After making sure that the user has entered a value, the LostFocus code selects the records that match the user
s text and sets the RecordSource property of the grid to the result set.
cDisplayValue = ALLTRIM(THIS.DisplayValue)
IF THIS.Value = "(All)"
SELECT country AS location,* FROM CUSTOMER;
INTO CURSOR Custs
thisform.grdcust.recordsource = "Custs"
SELECT country AS location,* FROM CUSTOMER ;
WHERE UPPER(ALLTRIM(Customer.Country)) = UPPER(m.cDisplayValue);
INTO CURSOR Custs
THISFORM.grdCust.RecordSource = "Custs"
ENDIF
Select an Item from a Drop-down List
Basically the same lookup code is associated with the InteractiveChange event of cboDrop
if the Value of the combo box is
(All)
, Select all records into the cursor, otherwise, select the records that match the user
s choice.
Enter Partial Values for Incremental Search
Code in the InteractiveChange event of cboIntSearch performs the lookup every time the user types a character in the combo box.
WHERE UPPER(ALLTRIM(Customer.Country)) = UPPER(m.cDisplayValue);
INTO CURSOR Custs
THISFORM
ecord
ource = "Custs"
ENDCASE
THISFORM.ResetCombos(THIS)
THISFORM.LockScreen = .F.
Allow Users to Choose List ValuesK
Allow Users to Choose List Values
File: SAMPLES\SOLUTION\FORMS\DATALOOK.SCX
This sample illustrates providing users with a set of values, selected from another table, in a list box and in a drop-down list box. The value the user chooses is stored in the current table.
It is often more convenient for a user to choose from a list of predetermined values, and, of course, you minimize the risk that the user will mistype a value. Setting a few list box properties is all that is required to provide this capability. For example, the following properties were set for cboEmp_id on the
Using Combo Box
page:
Property
Setting
BoundColumn
ColumnCount
ControlSource
orders.emp_id
RowSource
SELECT DISTINCT ALLTRIM( employee.first_name) + " " + ALLTRIM( employee.last_name) , EMP_ID FROM employee INTO CURSOR cEmpCombo ORDER BY first_name
RowSourceType
3 - SQL Statement
Rather than having the user choose an employee id number from the drop-down list, the SELECT statement allows you to show the user the employees
first and last names.
Because the SELECT statement creates a cursor, code in the Destroy event closes the cursor:
IF USED("cEmpCombo") THEN
USE IN cEmpCombo
ENDIF
Allow Users to Drag and Drop ControlsO
Allow Users to Drag and Drop Controls
File: SAMPLES\SOLUTION\FORMS\DDROP.SCX
This sample explains how to implement drag and drop operations. One page on the form illustrates manual dragging of controls by calling the Drag method. Explicitly calling the Drag method allows you to process other code in the Click event of the control. The other page illustrates using the Automatic DragMode setting so that the Drag and Drop operation is started automatically when the user presses the mouse button over the controls.
Repositioning the Command Button
In the MouseMove event of cmdDrop, if the left mouse button is down, find out how far the mouse pointer is from the top and the left of the command button and begin the drag operation.
LPARAMETERS nButton, nShift, nXCoord, nYCoord
IF nButton = 1 && Left button
THISFORM.XOffset = nXCoord - THIS.Left
THISFORM.YOffset = nYCoord - THIS.Top
THIS.Drag
ENDIF
In the DragDrop event of the page that the command button is on, reposition the command button.
oSource.Left = nXCoord - THISFORM.XOffset
oSource.Top = nYCoord - THISFORM.Yoffset
Changing the Color of the Shape
The DragMode property of the colored squares on the Change Colors page of the form is set to 1 - Automatic. As soon as the user presses the mouse button on the squares, the drag operation begins. Any code added to the Click event of the squares would never be executed.
Code in the DragDrop event of the circle changes its BackColor property to match that of the drag source.
LPARAMETERS oSource, nXCoord, nYCoord
THIS.BackColor = oSource.BackColor
Automate Microsoft Word and ExcelK
Automate Microsoft Word and Excel
File: SAMPLES\SOLUTION\OLE\OLEAUT1.SCX
This is a simple sample showing Visual FoxPro as an OLE Automation Controller. It demonstrates how to select data from a Visual FoxPro database, place the data in a Microsoft Excel worksheet, graph the data using Chart, and then display the graph in Word. To use this sample, you need at least Excel 5.0, Word 6.0, and TESTDATA.DBC!customer.dbf, located in the \SAMPLES\DATA directory.
The following line of code creates a reference to a Microsoft Excel spreadsheet.
objXLsheet=createobject("Excel.Sheet")
The following line of code adds a chart to the spreadsheet.
The following line of code creates a reference to Microsoft Word
objWDdoc=createobject("word.basic")
oWordRef = GetObject('','word.basic')
Automate a Microsoft Excel SpreadsheetP
Automate a Microsoft Excel Spreadsheet
File: SAMPLES\SOLUTION\OLE\OLEXL.SCX
This form shows two samples of Visual FoxPro calling an Excel worksheet through automation.
Trend
button performs a query followed by a cross-tab to create a dataset to pass to Excel through automation using the Excel.Sheet object. Once in Excel, Visual FoxPro can call a Trend function to perform a simple regression analysis.
Chart
button automates the Excel.Chart object to create a chart. Excel supports passing data through automation, but MS Graph does not. However, you can distribute MS Graph with your applications.
Automate a Microsoft Word Document in a FormV
Automate a Microsoft Word Document in a Form
File: SAMPLES\SOLUTION\OLE\OLEWORD.SCX
This sample shows how you can automate an embedded Word object on a form, insert some rich text, and then format the text. Typical automation with Word is usually done via the
This example illustrates using a toolbar to set FontName, FontSize, FontBold, FontItalic, ForeColor, and BackColor properties of controls on a form.
The toolbar is the tbrEditing class in SAMPLES\CLASSES\SAMPLES.VCX. The nAppliesTo property of the class specifies whether to set the properties of the currently selected control, all text boxes and edit boxes on the form, or all controls on the form. The code in the InteractiveChange or Click event of the toolbar controls sets the properties. For example, the following code is associated with the Click event of cmdBold:
IF TYPE("_SCREEN.ActiveForm") = 'O'
oForm = _SCREEN.ActiveForm
RETURN
ENDIF
DO CASE
CASE THIS.Parent.nAppliesTo = 1
&& Current Control
oForm.ActiveControl.FontBold = THIS.Value
CASE THIS.Parent.nAppliesTo = 2
&& Text and edit boxes
oForm.SetAll('FontBold', THIS.Value, 'TEXTBOX')
oForm.SetAll('FontBold', THIS.Value, 'EDITBOX')
CASE THIS.Parent.nAppliesTo = 3
&& All Controls
oForm.SetAll('FontBold', THIS.Value)
ENDCASE
The only code in the form is associated with the GotFocus event of the controls. Each GotFocus event contains the following line of code:
THISFORMSET.tbrEditing.Refresh(THIS)
The Refresh method of tbrEditing sets the values of the editing controls of the toolbar to reflect the current settings of the object whose reference is passed in as a parameter.
Change Pages When a User Chooses a ButtonS
Change Pages When a User Chooses a Button
File: SAMPLES\SOLUTION\CONTROLS\PAGEFRAME\MSGBOX
This sample allows you to interactively construct a message box.
There are six command button combinations possible in a message box. Each of these combinations is displayed on a separate page in a page frame on the Messagebox Builder form.
The option buttons, labeled 0 through 5, allow you to specify which combination of command buttons you want to be displayed in your message box. The selected button in the page indicates the default Messagebox button selection. The ActivePage property of the page frame is set to the Value of the Option group.
Constructing the MESSAGEBOX Code
In the InteractiveChange event of the controls on the form, the WriteCode method of the form is called to dynamically construct the MESSAGEBOX code.
This sample illustrates using a page frame with tabs. The number of tabs
changes dynamically when a user chooses a new value in a spinner. When the user selects a tab, a list box displays values specific to the tab.
To change the number of tabs at run time
Set the PageCount property to the desired number of pages.
The list box in this sample is positioned on the form, not on any of the pages in the page frame. This placement allows you to have a single control visible in all of your pages.
Two user-defined form methods set the captions on the tabs and make sure the values in the list box match: UpdateList and SetCaption.
UpdateList Method
UpdateList is called when the number of tabs changes and when the user selects a new tab.
Alphabet is a user-defined form property that is used to determine the captions for each tab To get the same functionality in different languages, set the Alphabet property to a string containing all the letters in the target language alphabet.
Coordinate Menu Items and Toolbar ButtonsS
Coordinate Menu Items and Toolbar Buttons
File: SAMPLES\SOLUTION\MENUS\TOOLMENU.SCX
This sample illustrates coordinating menu items and toolbar buttons that provide the same functionality.
Sometimes you
ll want to make particular functionality accessible from both menu items and toolbar buttons. For sample, in Visual FoxPro you can save a file by choosing the
toolbar button or by choosing
from the
menu.
There are three components to this sample:
Component
Description
TOOLMENU.SCX
the form
tbrBackColor in SOLUTION.VCX
the toolbar
TOOLMENU.MNX
the menu
In the Init event of the form, a toolbar object is created whose object reference is a property on the form,
oToolbar
SET CLASSLIB TO ..\solution
This.oToolbar = CREATEOBJECT('tbrbackcolor')
* Position the toolbar and show it
THIS.oToolbar.Left = THIS.Left + 10
THIS.oToolbar.Top = THIS.Top - 50
THIS.oToolbar.Visible = .T.
* Push the current menu on the stack so it can be
* restored in the Destroy event of the form.
PUSH MENU _MSYSMENU
* Run the menu
DO toolmenu.mpr
Rather than coding duplicate functionality in the toolbar and the menu, updating it both places if changes are required, the code associated with the menu items calls the code associated with the toolbar buttons. For example, the following command is associated with the first menu item:
_VFP.ActiveForm.oToolbar.cmdRed.click
The SKIP FOR clause of the menu items causes them to be disabled when the associated toolbar button is disabled. For example, the following expression is associated with the SKIP FOR clause of the first menu item:
!_VFP.ActiveForm.oToolbar.cmdRed.Enabled
Create a 1-To-Many Data Entry FormL
Create a 1-To-Many Data Entry Form
File: SAMPLES\SOLUTION\FORMS\MANY.SCX
This sample illustrates the basic tasks associated with a one-to-many data entry form.
When you choose the
button beside the parent table text boxes, the following code is executed:
SELECT CUSTOMER
APPEND BLANK
THISFORM.Refresh
When you choose the
button beside the grid that displays the child records, more code is executed.
After selecting the orders table, the code calculates a new id value for the order, adds the blank record, then stores the parent id and order id to the appropriate fields.
CALCULATE MAX(order_id) ALL TO lMaxID
lMaxID = ALLTRIM(STR(VAL(lMaxID) + 1))
APPEND BLANK
REPLACE cust_id WITH Customer.Cust_id IN orders
REPLACE order_id with lMaxID in orders
This method of creating a new id value would not be reliable if multiple users were adding new orders at the same time. Instead, you can create a new id as illustrated in the
Create a Default Unique ID Value for a Field
sample.
Create a Default Unique Id Value for a FieldV
Create a Default Unique ID Value for a Field
File: SAMPLES\SOLUTION\DB\NEWID.SCX
This sample uses a stored procedure in a database to provide a default primary key value.
To create a default unique ID
Add a separate table to the database that stores the next ID for each table in the database.
The name of this table in the sample is IDS.DBF. It contains two fields:
Table C(10), NextID I
Create a function in the stored procedures of the database to return the next id value from the id table.
The name of this function in the sample is
NewID
. It is listed below.
Set the default value for the field to the function.
NewID Stored Procedure
FUNCTION NewID(tcAlias)
LOCAL lcAlias, lnID, lcOldReprocess, lnOldArea
lnOldArea = SELECT()
IF PARAMETERS() < 1
lcAlias = UPPER(ALIAS())
ELSE
lcAlias = UPPER(tcAlias)
ENDIF
lcOldReprocess = SET('REPROCESS')
* Lock until user presses Esc
SET REPROCESS TO AUTOMATIC
IF !USED("IDS")
USE newid!ids IN 0
ENDIF
SELECT ids
IF SEEK(lcAlias, "Ids", "table")
IF RLOCK()
lnID = ids.nextid
REPLACE ids.nextid WITH ids.nextid + 1
UNLOCK
ENDIF
ENDIF
SELECT (lnOldArea)
SET REPROCESS TO lcOldReprocess
RETURN lnID
ENDFUNC
Create a Query-By-Example FormH
Create a Query-By-Example Form
File: SAMPLES\SOLUTION\FORMS\QBF.SCX
This sample enables users to search and filter records in the same interface that they view the records.
When a user chooses
Enter QBF
, the code associated with the Click event of cmdQBFMode begins a transaction and appends a blank record to the table to store the user
s query text.
* extract from cmdQBFMode.Click
BEGIN TRANSACTION
APPEND BLANK
THISFORM.Refresh
When the user chooses
Query
, code associated with the Click event of cmdExecuteQBF rolls back the transaction, throwing away the new record.
You can use transactions only with tables contained in a database. If you want to include QBF capabilities for a table that is not in a database, you can loop through all the controls on the form, save the old ControlSource property setting and set the ControlSource property of the controls to an empty string. After getting the user query string, you can loop back through the controls and reset the ControlSource properties.
Code associated with the Click event of cmdExecuteQBF also loops through the controls on the form, checks for user-entered values, and calls the ParseCondition method to assemble the filter string.
A user can enter a single value to match or an expression. For example, a user can enter either of the values below in the Title text box to set a filter:
Sales Manager
Sales Manager
If the user doesn
t enter an expression, quotation marks are not required.
This sample illustrates the simplest scenario for a single-user, single-table data entry form.
The ControlSource property of each of the text boxes and combo boxes on the form is set to a field in the Customer table.
An APPEND BLANK command is issued in the Click event of cmdNew.
APPEND BLANK
THISFORM.Refresh
The DELETE command is issued in the Click event of cmdDelete.
* cmdDelete.Click
#DEFINE MSGBOX_YES
#DEFINE C_MSGBOX1
#DEFINE C_DELETE_LOC
"Are you sure you want to delete this record?"
IF MESSAGEBOX(C_DELETE_LOC,C_MSGBOX1) = MSGBOX_YES
DELETE
IF !EOF()
SKIP 1
ENDIF
IF EOF() AND !BOF()
SKIP -1
ENDIF
THISFORM.Refresh
ENDIF
Extending the Data Entry Form
To create a more robust data entry form, one that allows a user to cancel changes or allows multiple users to access the same data, you need to use transactions and table or row buffering. For more information on these features, see Chapter 17,
Programming for Shared Access,
in the Visual FoxPro
Developer
s Guide
Create an SDI Form<
Create an SDI Form
File: SAMPLES\SOLUTION\FORMS\SDIFORM.SCX
This sample illustrates Visual FoxPro support of SDI forms. In order to create an SDI form, all you have to do is set the form
s ShowWindow property to 2 - As Top-Level Form. SDI forms do not require the Visual FoxPro window to be visible.
Adding Forms
There are two ways to add forms to a Top-Level (SDI) form. The first and easiest is to create a new form and set its ShowWindow property to 1 (In Top-Level form). While this may seem the most appropriate, it is not always the best solution because the ShowWindow property can only be set at design time.
Another method is to use the ACTIVATE WINDOW command. The code below from the SDIForm sample shows just this. Since this command is not object-based, you must reference a form by its window name (Name property).
Menus can also be added to SDI forms. There is now a new Top-Level Form check box in the
Menu Designer
s View
menu
General Options
dialog box. A
Top-Level Form
menu will be generated if you check this option and can be called as shown here.
DO sdiform.mpr WITH
THISFORM,.T.
If system menu items rely on the main Visual FoxPro window being visible, they won
t give the expected results when the main Visual FoxPro window is hidden.
Adding Toolbars
In addition to menus and windows, you can also add toolbars to your SDI forms. Toolbars are objects like forms, so you can take advantage of the Visual FoxPro object model and scope that toolbar to the form. The SDI form sample uses a custom property to create and keep the toolbar in scope.
SET CLASSLIB TO sditbar ADDITIVE
thisform.oToolbar=create("sditb1")
thisform.oToolbar.show
Create Dynamic Shortcut MenusG
Create Dynamic Shortcut Menus
File: SAMPLES\SOLUTION\MENUS\DYNSHORT.SCX
This sample illustrates an alternative way to create shortcut menus.
The shortcut menus in the
Display Shortcut Menus
sample were created in the Menu Designer. The advantages of using the Menu Designer are ease of design, the ability to create cascading menus, and simple integration on a form. With the Menu Designer, however, you need a separate .MNX, .MNT, and .MPR file for each shortcut menu. If you make a change, you need to generate and compile the menu code again.
The dynamic shortcut menu engine is a custom class that you can add to any form: menulib in SAMPLES\CLASSES\UTILITY.VCX. The ShowMenu method of this class defines a menu and displays it at the MousePointer location as determined by the MROW(
) and MCOL(
) functions.
In the RightClick event of the objects you want to create a shortcut menu for:
Create an array with the shortcut menu items.
Pass the array to the ShowMenu method of the menulib class.
Process the user choice by checking the BAR(
) value.
For example, the following code is associated with the RightClick event of the form:
LOCAL laMenu[5]
laMenu=""
laMenu[1]="\<Center"
laMenu[2]="\<Font..."
laMenu[3]="\<Minimize"
laMenu[4]="\-"
laMenu[5]="E\<xit"
THISFORM
.oMenuShortcut.ShowMenu(@laMenu)
DO CASE
CASE BAR()=1
THISFORM
.AutoCenter=.T.
CASE BAR()=2
THISFORM
.SetFont
CASE BAR()=3
THISFORM
.WindowState=1
CASE BAR()=5
THISFORM
.Release
ENDCASE
Customize the Open Dialog BoxG
Customize the Open Dialog Box
File: SAMPLES\SOLUTION\OLE\COMMDLOG.SCX
This sample illustrates customizing the appearance and behavior of the
dialog box as exposed through the Common Dialog control.
You can set the Flags property of the Common Dialog control to specify the behavior of the
dialog box. For a list of the various Flags values, see
Open Dialog Box Flag Values
The following code in the Click event of cmdFiles checks the values of the various check boxes on the form and sets the Flags property of the Common Dialog control.
Set the Read-only checkbox flag
IF !thisform.chkRead.Value
m.nFlags = m.nFlags + 4
ENDIF
Set the Multiple files flag
IF thisform.chkMulti.Value
m.nFlags = m.nFlags +
ENDIF
Set the Help button flag
IF thisform.chkHelp.Value
m.nFlags = m.nFlags + 16
ENDIF
Set the enforce file existence flag
IF thisform.chkMulti.Value
m.nFlags = m.nFlags + 4096
ENDIF
Set the Flags property of the Common Dialog control
THISFORM
.oleCommDlog.Flags = m.nFlags
Set the Filter property of the Common Dialog control
You can use the Filter property of the Common Dialogs control to specify what files a user is allowed to choose.
THISFORM
.oleCommDlog.Filter = "All files
"(*.*)|*.*|Text (*.txt)|*.txt
"|Pictures(*.bmp;*.ico)|*.bmp;*.ico"
Open Dialog Box Flag ValuesE
Open Dialog Box Flag Values
You can customize the
dialog box by setting the Flag property to the sum of a selection of these values:
Value
Description
Causes the
Read Only
check box to be initially checked when the dialog box is created. This flag also indicates the state of the
Read Only
check box when the dialog box is closed.
Causes the
Save As
dialog box to generate a message box if the selected file already exists. The user must confirm whether to overwrite the file.
Hides the
Read Only
check box.
Forces the dialog box to set the current directory to what it was when the dialog box was opened.
Causes the dialog box to display the Help button.
Specifies that the common dialog box allows invalid characters in the returned filename.
Specifies that the
File Name
list box allows multiple selections. The user can select more than one file at run time by pressing the SHIFT key and using the UP ARROW and DOWN ARROW keys to select the desired files. When this is done, the FileName property returns a string containing the names of all selected files. The names in the string are delimited by spaces.
Indicates that the extension of the returned filename is different from the extension specified by the DefaultExt property. This flag isn't set if the DefaultExt property is Null, if the extensions match, or if the file has no extension. This flag value can be checked upon closing the dialog box.
Specifies that the user can enter only valid paths. If this flag is set and the user enters an invalid path, a warning message is displayed.
Specifies that the user can enter only names of existing files in the File Name text box. R
If this flag is set and the user enters an invalid filename, a warning is displayed. This flag automatically sets the
flag.
Specifies that the dialog box prompts the user to create a file that doesn't currently exist. This flag automatically sets the
and
flags.
16384
Specifies that sharing violation errors will be ignored.
32768
Specifies using the Windows 95 explorer-like
Open A File
dialog box template. (Windows 95 only.)
524288
Use the Explorer-like
Open A File
dialog box template. Common dialogs that use this flag do not work under Windows NT using the Windows 95 shell.
1048576
Do not dereference shell links (also known as shortcuts). By default, choosing a shell link causes it to be dereferenced by the shell.
1048576
Do not dereference shortcuts (shell links). By default, choosing a shortcut causes it to be dereferenced by the shell. (Windows 95 only.)
2097152
Allows the user to use long filenames. (Windows 95 only.)
Disable or Display a Check Beside a Menu ItemW
Disable or Display a Check Beside a Menu Item
File: SAMPLES\SOLUTION\MENUS\CHKMENU.SCX
This sample illustrates dynamically disabling menu items and displaying check marks beside specific menu items.
The menu in this sample was created in the
Menu Designer
and is run when the form is initialized.
DO chkmenu.mpr
To disable a menu item, include an expression that evaluates to false (.F.) in the SET SKIP OF command. For example, the following line of code in the InteractiveChange event of a check box issues SET SKIP OF with the inverse of the value of the check box, disabling the menu item when the check box is not selected.
SET SKIP OF BAR 1 OF checkitems !THIS.Value
To display a check mark beside a menu item, include an expression that evaluates to true (.T.) after the TO keyword of the SET MARK OF command. For example, the following line of code in the InteractiveChange event of a check box issues the SET MARK OF command with the Value property setting of the check box.
SET MARK OF BAR 1 OF checkitems TO THIS.Value
Display a Stop Watch>
Display a Stop Watch
File: SAMPLES\SOLUTION\CONTROLS\TIMER\SWATCH.SCX
This sample includes the Stopwatch class (described in Chapter 3,
Object-Oriented Programming,
in the
Developer's Guide
The Stopwatch Class
The Stopwatch class includes a timer and several display labels. The Timer increments numeric custom properties of the class and sets the Caption property of the labels accordingly.
The Start method of the class sets the Enabled property of the Timer to true (.T.). The Stop method sets the Enabled property of the Timer to false
(.F.). And the Reset method sets the numeric properties to 0.
The Swatch Form
The Swatch form contains an object derived from the Stopwatch class, along with some command buttons. The code written for the Click event of the first command button on the form calls the Start and Stop methods of the Stopwatch class. The second button calls the Reset method of the Stopwatch class.
Display a System Clock@
Display a System Clock
File: SAMPLES\SOLUTION\CONTROLS\TIMER\CLOCK.SCX
This sample contains the Clock custom control in SAMPLES.VCX on a form. The class includes a text box for displaying the date and time and a timer for updating the display.
The TimeFormat property of the clock class can be set to 0 for 24-hour time format or 1 for 12-hour format. The code in the Timer event of the timer updates the time:
This class contains a separate text box for date and time values. If you want to hide one or the other, you can easily set its Visible property to false (.F.). An easier way to display the time and date is to use a single text box and set the value of this text box in a timer control to DATETIME(
). This will allow you to take advantage of the Hours, Seconds, and DateFormat properties of a text box.
Display Calculated Values in a ColumnO
Display Calculated Values in a Column
File: SAMPLES\SOLUTION\CONTROLS\GRID\CALC.SCX
This sample illustrates how to display a calculated value in a column.
Set the ControlSource property of the column to an expression with a calculation. For example, the following expression for the ControlSource of the Profit column displays the difference between the price and cost.
Products.Unit_Price - Products.Unit_Cost
When you change one or more values in the expression, the value in the column is automatically updated.
Columns that display an expression containing a calculation are read-only.
Display Child Records from a RelationshipS
Display Child Records from a Relationship
File: SAMPLES\SOLUTION\CONTROLS\GRID\1_MANY.SCX
This sample demonstrates coordinating a one-to-many-to-many form with two grids displaying the many sides of the relationships. Very little code is needed in this sample. Setting a few properties is all that is involved.
Property settings
Text boxes for the "one" side of the relationship:
ControlSource = Customer.cust_id
ControlSource = Customer.company
Grid for the first "many" side of the relationship:
ChildOrder = cust_id
LinkMaster = customer
RecordSource = orders
RecordSourceType = 1 - Alias
RelationalExpr = customer.cust_id
ColumnCount = 4
Column1.ControlSource = "orders.order_no"
Column1.Header1.Caption = "Order"
Column2.ControlSource = "orders.order_date"
Column2.Header1.Caption = "Date"
Column3.ControlSource = "orders.to_name"
Column3.Header1.Caption = "Ship To"
Column4.ControlSource = "orders.order_amt"
Column4.Sparse = .F.
Column4.Header1.Caption = "Total"
Column4.Text1.InputMask = "$$999,999.99"
Grid for the 2nd 'many' side of the relationship
ChildOrder = order_id
LinkMaster = Orders
RecordSource = Orditems
RecordSourceType = 1 - Alias
RelationalExpr =Orders.order_id
ColumnCount = 4
Column1.ControlSource = "orditems.line_no"
Column1.Header1.Caption = "Item"
Column2.ControlSource = "products.prod_name"
Column2.Header1.Caption = "Product"
Column3.ControlSource = "orditems.quantity"
Column3.Header1.Caption = "Qty."
Column4.ControlSource = "orditems.unit_price"
Column4.Sparse = .F.
Column4.Header1.Caption = "Price"
Column4.Text1.InputMask = "$$9,999.99"
In addition to the text boxes and the grids, the form contains an object based on the VCR class in BUTTONS.VCX. The SkipTable property of this class is set to the table you want the record pointer to be moved in when the user chooses a table navigation button. Because the user can easily manually move through the records in the grids (Orders and Orditems), SkipTable is set to Customer.
Display Controls in a GridD
Display Controls in a Grid
File: SAMPLES\SOLUTION\CONTROLS\GRID\CONTROLS.SCX
This sample demonstrated controls displayed in grid columns.
You can add controls to a column in the
Form Designer
by selecting a column and adding a control or programmatically with the AddObject method.
There are a few properties that are important for displaying controls in a column:
CurrentControl Property
After you add a control to a grid column, you need to set the column
s CurrentControl property to the new control for the new control to be displayed.
Sparse Property
The check boxes on the form allow you to toggle the Sparse property of the grid columns that contain controls. When Sparse is set to .T., the control is only displayed when the focus is on a cell in the column. When Sparse is set to .F., the control is always displayed in each cell in the column.
Controls and Events
Notice that the control in the column processes the events when you are set the focus to a cell in the column. For example, if you select a cell in a column with a spinner, when you press the up and down arrows, you increment or decrement the value in the spinner. This is the default behavior for a spinner, not the default behavior for a text box in a grid cell.
For a more detailed description of adding controls to grid columns, see Chapter 10, "Using Controls," in the
This sample demonstrates manipulating pages without tabs in a form page. The frame in the middle of the form contains three pages that are brought to the front as the user chooses command buttons. Each page can have its own controls and appearance.
The method that brings a particular page to the front is ZOrder. For example, the following line of code in the click event of one of the command buttons brings pagCustomers to the front:
THISFORM.pgfPeople.pagCustomers.ZOrder
You can also use the ActivePage property of the page frame to determine which pages are displayed:
THISFORM.pgfPeople.ActivePage = 1
Display Line Animation on a FormJ
Display Line Animation on a Form
File: SAMPLES\SOLUTION\GRAPHICS\ANIM.SCX
This sample illustrates drawing lines on a form. More specifically, it demonstrates saving coordinates of sets of lines drawn on a form and redrawing them, along with additional lines at intermediate positions, giving the illusion of motion.
Adding lines to the table.
Each time a user draws a line on the form, its coordinates are stored in a table with the following structure:
Description
Frameno
Incremented each time the user chooses
New Frame
Objno
Incremented each time a line is added to a frame.
The starting X coordinate for a line.
The ending X coordinate for a line.
The starting Y coordinate for a line
The ending Y coordinate for a line.
Playing the frames.
The code that plays the frames, uses the table again in another work area, selects the second work area, and goes to the next frame:
USE (lcTable) AGAIN IN 0 ALIAS shadow
SELECT shadow
LOCATE FOR frameno # &lcTable..frameno
The variable
nBetween
determines how many intermediate lines are drawn on the form between a line in one frame and the corresponding line in the next frame.
FOR nb = 1 TO nBetween
Inside the FOR loop, the code scans for all of the lines associated with a frame and calculates coordinates for the intermediate lines, for example:
The code then prints each intermediate line, and after a WAIT of .05 seconds clears the form and continues thek
loop.
THISFORMSET.frmAnimation.line(nx1,ny1,nx2,ny2)
Display Multiple Columns in a List BoxP
Display Multiple Columns in a List Box
File: SAMPLES\SOLUTION\CONTROLS\LISTS\LMULCOL.SCX
This sample demonstrates displaying multiple columns in a list box. The form displayed contains a list box and a spinner. The number of columns in the list box is set to the Value property of the spinner: 1, 2, 3, or 4.
To set the width of the columns in a multi-column list box, use the ColumnWidths property. For example, if there are 3 columns in the list box, the following command will set the column widths to 10, 15, and 20, respectively:
Form.List.ColumnWidths = "10, 15, 20"
To set the fields to be displayed in the columns, set the RowSource property. For example, the following command sets the sources of three columns in a 3-column list box to the contact, city, and country fields of the customer table.
Form.List.RowSource = "contact,city,country"
The ColumnLines property determines whether lines are displayed between the columns in the list.
Display Pictures in a ListD
Display Pictures in a List
File: SAMPLES\SOLUTION\LISTS\PICLIST.SCX
This sample illustrates how you can spice up your list boxes by adding picture graphics beside the individual text items. In this sample, you can pick any database (.DBC) file, and the list box will show different images beside the names of tables, local views and remote views.
The following code from cmdDatabase.Click enumerates through a .DBC and selectively adds pictures to list items using the Picture property. The Picture property relies on an index setting to determine which list item to affect.
FOR i = (m.nTblCount+1) TO thisform.lstDatabase.ListCount
IF DBGETPROP(ALLTRIM(thisform.lstDatabase.List[m.i]),; "view","sourcetype") = 1
*Local view
thisform.lstDatabase.Picture[m.i] = m.cLViewBMP
* Remote view
thisform.lstDatabase.Picture[m.i] = m.cRViewBMP
ENDIF
ENDFOR
You need to ensure that the images used are sized correctly to fit within the space of a single list box item, which differs with the FontSize of the list.
Display Pictures in an Image ControlN
Display Pictures in an Image Control
File: SAMPLES\SOLUTION\FORMS\IMAGE.SCX
This sample illustrates displaying bitmaps or icons in an image control.
The list box on the form displays files. In the InteractiveChange event of the list box, the Picture property of the image control is set to the selected file, if the file is a .BMP or .ICO.
This sample illustrates displaying shortcut menus when a user
right-clicks
an object. When you have created a shortcut menu in the
Menu Designer
, the code in the form to activate the menu is very simple. The following code is associated with the RightClick event of the form:
DO frmshort.mpr WITH THIS
The following code is associated with the RightClick event of the edit boxes on the form:
DO edtshort.mpr WITH THIS
The FRMSHORT Menu
The FRMSHORT menu was designed to take an object parameter. The following code is included in the menu
s setup code:
PARAMETER oREF
#PREPOP
#PREPOP
generative directive causes the code in the menu
s cleanup to be generated before the ACTIVATE POPUP command. This allows you to disable or enable menu items at run time, as well as displaying check marks beside menu items.
The code associated with the menu items, sets properties of the object that was passed to the .MPR as a parameter. For example, the
Always on top
item sets the AlwaysOnTop property of the form.
The following code, included in the menu
s cleanup code, displays a check mark beside the
Always on top
item when the form
s AlwaysOnTop property is set to true (.T.).
SET MARK OF BAR 4 OF frmshort TO oRef.AlwaysOnTop
The EDTSHORT Menu
The EDTSHORT menu also accepts an object parameter in its setup code. Because there is no need to display a check mark beside the items in this menu, the #PREPOP generator directive is not used.
For an alternative way to display shortcut menus, see the
Create Dynamic Shortcut Menus
sample.
Display System InformationD
Display System Information
File: SAMPLES\SOLUTION\OLE\SYSINFO.SCX
This sample illustrates using the SysInfoControl to display system information and to notify when a system setting changes.
The bulk of the code in this sample is in the CheckStatus method. Code in this method checks the settings of various SysInfoControl properties to see their current settings, and populates a treeview control with this information. For example, the following section of code checks the BatteryLifePercent setting:
IF ThisForm.SysInfo.BatteryLifePercent = 255
* Add a node to display the information
ENDIF
When a system setting changes, an event of the SysInfoControl occurs. Code associated with each of these events sets the caption of a label and calls the CheckStatus method to refresh the treeview control. For example, the following code is associated with the SysColorsChanged event:
ThisForm.Status.Caption = SysColorsChanged_LOC
ThisForm.CheckStatus
Draw Lines and Shapes on a FormI
Draw Lines and Shapes on a Form
File: SAMPLES\SOLUTION\FORMS\GRAPHICS\ANIM.SCX
This sample illustrates how to use form graphics methods (PSet, Line, and Circle) and properties (DrawMode, DrawStyle, DrawWidth) to allow a user to draw figures and shapes on a form in different colors and different pen widths.
The sample includes a toolbar (defined in FDPROC.PRG) and a form (based on frmFD in FD.VCX). The user can select settings in the toolbar that affect the graphics properties of the form. When the form is set to accept user drawing, the MousePointer is set to 2 (cross-hairs).
The drawing functionality is coded in the methods associated with the MouseDown and MouseMove events of the form:
* MouseDown
PARAMETERS nButton, nShift, nXCoord, nYCoord
IF THIS.MousePointer = 2
THIS.PSet(nXCoord, nYCoord)
ENDIF
* MouseMove
PARAMETERS nButton, nShift, nXCoord, nYCoord
IF THIS.MousePointer = 2
THISFORM.LINE(nXCoord, nYCoord)
ENDIF
Dynamically Format Grid ColumnsI
Dynamically Format Grid Columns
File: SAMPLES\SOLUTION\CONTROLS\GRID\DYNGRID.SCX
This sample illustrates setting the DynamicForeColor and DynamicBackColor properties of grid columns.
The code of interest in this sample is associated with the InteractiveChange event of the drop-down list cboFormat.
First, the code clears the dynamic fore and back color settings:
oGrd.SetAll("dynamicbackcolor", "", "Column")
oGrd.SetAll("dynamicforecolor", "", "Column")
Then, code in a CASE statement sets the new DynamicForeColor or DynamicBackColor properties. For example, the following line of code displays discontinued items with a gray ForeColor.
This sample enables you to view and edit text from a memo field or a text file in an edit box.
Displaying text from a memo field is as easy as setting the ControlSource of the edit box to the memo field.
There are two ways you can edit a text file in an edit box: using low-level file functions and creating a cursor to hold the text. This sample creates a cursor instead of using low-level file functions.
Editing a Text File with Low-Level File Functions.
You can open a file using FOPEN(
), read the contents of the file using FREAD(
), and store the contents to a memory variable or to the Value property of the edit box. You can then write changes to the file using FWRITE(
) and close the file using FCLOSE(
Editing a Text File by Loading It into a Cursor Field
The advantage to creating a cursor for a text file, other than the fact that the code is a little simpler, is that Visual FoxPro manages writing large amounts of text in a cursor to temporary files if there isn
t enough memory.
IF SELECT("textfile") = 0
CREATE
CURSOR textfile (filename c(60),mem m)
APPEND BLANK
ENDIF
REPLACE textfile.FileName WITH GETFILE("TXT")
IF EMPTY(textfile.FileName)
RETURN
ENDIF
SELECT textfile
APPEND MEMO mem FROM (textfile.FileName) OVERWRITE
This sample form contains a text box and a spinner. Text you type in the text box is displayed in a WAIT WINDOW. You can set the spinner to the number of seconds you want to elapse between each WAIT WINDOW command.
In the InteractiveChange event of the spinner, the appropriate timer interval is set. The Interval property is 1/1000th of a second, so the interval is set to the spinner value * 1000:
The code associated with the Timer event can include any command or procedure: code to update data, check for mail, display system resources, and so on.
This sample demonstrates setting the RowSourceType of a list box at run time to a value, an alias, a SQL statement, a query (.QPR), an array, fields in a table, files in a directory, and the structure of a table.
The combo box on the form contains all the possible RowSourceTypes of a list (except for 9 - popup, which is included for backward compatibility). The code associated with the InteractiveChange event sets the new RowSourceType and RowSource properties for the list.
When you change both the RowSourceType and RowSource of a list box at run time, you need to:
Set the RowSourceType to 0
Set the RowSource to the new source
Set the RowSourceType to the new type
If you don't follow this order, the existing RowSource and RowSourceType settings could conflict after one new value is set and before the corresponding value is set.
This sample shows how to set text box properties to make it easy for a user to enter data in the required format.
Format
Property
Setting
Allow Only Digits
InputMask
999999999
Select On Entry
SelectOnEntry
All Uppercase
Format
Read Only
ReadOnly
US Telephone Number
InputMask
(999) 999-9999
Password text
PasswordChar
Date Formatting
DateFormat
a number between 0 and 14
Validating Input
The following code in the Valid event of a text box prevents a user from leaving the text box if the letter
is in the text.
IF "a"$ THIS.Value
#DEFINE MESSAGE_LOC
"The text box value cannot contain the letter 'a'"
MESSAGEBOX(MESSAGE_LOC,48+0+0)
RETURN 0
RETURN .T.
ENDIF
Get Application Information from the Windows Registry_
Get Application Information from the Windows Registry
File: SAMPLES\SOLUTION\WINAPI\REGFILE.SCX
This sample shows how to access the Windows registry using the native Visual FoxPro DECLARE-DLL command. The Windows API provides a number of functions you can use to access, read and write to the registry. The REGISTRY.PRG class library in \SAMPLES\CLASSES contains a complete set of these functions you can use in your applications.
In this specific sample, you can use registry functions to check for the existence of a particular application. For example, you might want to distribute an application which relies on using Excel to automate the creation of a Pivot Table. The registry contains the location, version and other information about a particular application.
Get Version InformationA
Get Version Information
File: SAMPLES\SOLUTION\WINAPI\GETVER.SCX
This sample allows you to display version information from a .DLL or .EXE.
A new function called GetFileVersion(
) has been added to FOXTOOL.FLL which allows you to obtain version information on a file. The following code illustrates how you can call the function. See TOOLS\FOXTOOLS.HLP for details on the specific array elements.
Visual FoxPro now allows you to add File Version information to EXE and DLL files at build time. This version information is stored in a file resource and can be accessed via the Windows Explorer. EXE files created in Visual FoxPro 3.0 will not have a file version resource.
Graph Equations on a FormC
Graph Equations on a Form
File: SAMPLES\SOLUTION\FORMS\GRAPHICS\GRAPH.SCX
This sample shows how to graph equations with form graphics. The user can scale the equation by choosing the Zoom command buttons. The user can also move the graph's origin by clicking and dragging.
The graphing engines for this sample are in two programs: CGRAPH.PRG and PGRAPH
.PRG. CGRAPH graphs equations based on Cartesian coordinates. PGRAPH graphs equations based on Polar coordinates. These programs use the PSet and Line methods of a form to draw the equation.
The following code, associated with the OneGraph method of the form set, runs the CGRAPH program when a user chooses the
Graph
button.
THISFORMSET.frmGraph.Draw
DO cgraph WITH ;
graph.equation, ;
graph.step, ;
graph.ecolor, ;
graph.connect, ;
THISFORMSET.nFormX, ;
THISFORMSET.nFormY, ;
.F., ;
THISFORMSET.frmgraph, ;
THISFORMSET.nFormScale
The following table lists the parameters for CGRAPH:
Parameter
Description
equation
The equation in terms of X. Will plot the answer as Y.
Step increment.
ecolor
Equation color.
connect
Whether the previous point is connected to the current point with a line.
nFormX
Point on form where x = 0
nFormY
Point on form where y = 0
lAddCoords
Whether to draw coordinate lines.
frmgraph
Name of the form to write to.
nFormScale
Scale to graph the equation at
Index on Expressions>
Index on Expressions
File: SAMPLES\SOLUTION\DB\INDEX2.SCX
This index sample shows several options you might consider when using a character field to represent a Unique ID (one often comprised of numeric data). An index tag based on a character field will sort based on the
ASCII
values of the data whereas a numeric expression, using the VAL(
) function, will sort on numeric sequences. The following table shows the sort difference of two indexes.
CExpression
VAL(cExpression
When you use the VAL(
) function, all non-numeric values will be converted to 0.
By incorporating the BINTOC(
) function, you can also reduce the size of your index tags considerably.
Create Small Indexes Using BINTOC( )N
Create Small Indexes Using BINTOC(
File: SAMPLES\SOLUTION\DB\INDEX1.SCX
This sample show various indexing schemes you can use with numeric and integer data types to get significant saN
vings in index size and disk space consumed. In addition, smaller sized indexes usually result in faster searches. The new BINTOC() function allows you to convert an integer (numeric) value to a binary character representation.
Syntax
BINTOC(
nExpression
nSize
Depending on the size of your expression, you can set the
nSize
parameter to accommodate the value of your expression in the least amount of characters.
The following line of code creates an index on a numeric field.
INDEX on line_no TAG line_no
The next time you are working with indexes on numeric integer data, consider using something like the following:
INDEX on BINTOC(line_no,1) TAG line_no
Interactively Build a SELECT StatementP
Interactively Build a SELECT Statement
File: SAMPLES\SOLUTION\FORMS\MAKESQL.SCX
This sample shows how to allow a user to build a custom query at run time. Combo boxes on the form allow a user to choose fields from the currently open table. The BldSQL method processes the names of the fields and the values users type into text boxes to create an executable SQL SELECT statement.
Additional methods, ValidateType and SetTextboxFormat, make sure that the appropriate values are entered into the text boxes and correctly incorporated into the SELECT statement.
After the WHERE clause has been constructed and stored to the variable lcWhere, the following command creates the SELECT statement:
Once the SELECT statement is constructed, it can be executed with macro substitution:
&lcSQL
Manipulate Display Characteristics of a GraphW
Manipulate Display Characteristics of a Graph
File: SAMPLES\SOLUTION\OLE\OLEGRAPH.SCX
This sample shows how to incorporate MS Graph into your applications. MS Graph ships with Visual FoxPro and can also be included in your distributed applications. MS Graph 5.0 is an OLE Automation Server that Visual FoxPro can automate using the standard CREATEOBJECT(
) function. With Visual FoxPro, Graph objects can be embedded in either bound or unbound OLE Controls. An OleBoundControl (bound to a General field) is the only way to programmatically insert data into a graph.
MS Graph
s automation support provides access only to a graph object, not its datasheet. Data can be inserted into a Graph only with the APPEND GENERAL command on a General field. The following code uses the HasLegend property and is an example of automation.
cGData = ""+TAB+"Cats"+TAB+"Dogs"+CRLF+;
"1994"+TAB+"11"+TAB+"22"+CRLF+;
"1995"+TAB+"33"+TAB+"44"+CRLF+;
"1996"+TAB+"55"+TAB+"55"+CRLF
APPEND GENERAL gen1 CLASS "msgraph.chart" DATA m.cGData
THIS.OleBoundControl1.ControlSource = "Gen1"
THIS.OleBoundControl1.HasLegend = .F.
The APPEND GENERAL command in this case creates a new chart object. If you do not include the
CLASS
msgraph.chart
clause, then the chart is merely updated. The CLASS clause
will create a new chart and override any existing formatting.
Move Items Between List BoxesG
Move Items Between List Boxes
File: SAMPLES\SOLUTION\CONTROLS\LISTS\LMOVER.SCX
This sample demonstrates moving items from one list box to another. A user can double-click one item to move it, or select one or more items and drag them, or use the appropriate command buttons to move the items between the lists.
The two list boxes and four associated command buttons are saved as a class: MoverLists in SAMPLES.VCX. The base class of MoverLists is CONTAINER. To be able to add and remove items from lists, the RowSourceType of the lists must be set to 0 - None. If you want to fill the list box with array elements or values from a table, you can use code like the following:
*array
FOR i = 1 to ALEN(myarray)
List.AddItem(myarray[i])
ENDFOR
*table
List.AddItem(table.field)
ENDSCAN
To Move Items by Double-Clicking
The following code is associated with the DblClick event of the left list box (lstSource). Similar code is associated with the DblClick event of the right list box (lstSelected).
"THIS" refers to lstSource. "THIS.Parent" refers to the moverlists class, the container of the lists.
To Move All Items from One List to Another
The following code is associated with the Click event of cmdAddAll:
DO WHILE THIS.PARENT.lstSource.ListCount > 0
THIS.PARENT.lstSelected.AddItem;
(THIS.PARENT.lstSource.List(1))
THIS.PARENT.lstSource.RemoveItem(1)
ENDDO
THIS.PARENT.Refresh
To Move Selected Items from One List to Another
If you remove an item from a list box, the ListCount property of the list box is decremented, as is the ListIndex of all the subsequent items in the list. To move multiply-selected items, you need to use a DO WHILE loop. The following code is associated with the Click event of cmdAdd:
nCnt = 1
DO WHILE nCnt <= THIS.PARENT.lstSource.ListCount
IF THIS.PARENT.lstSource.Selected(nCnt)
THIS.PARENT.lstSelected.AddItem;
(THIS.PARENT.lstSource.List(nCnt))
THIS.PARENT.lstSource.RemoveItem(nCnt)
nCnt = nCnt + 1
ENDIF
ENDDO
THIS.PARENT.Refresh
To Drag-and-Drop Items from One List to Another
Implementing drag-and-drop between the list boxes involves code associated with the MouseDown, MouseMove, DragOver, and DragDrop events. Three user-defined properties (DragThreshold, MouseX, and MouseY) extend the usability of the class.
The MouseDown code stores the X and Y coordinates of the mouse pointer to class properties.
*MouseDown
Parameters nButton, nShift, nXCoord, nYCoord
THIS.PARENT.MouseX = nXCoord
THIS.PARENT.MouseY = nYCoord
The MouseMove code makes sure the left mouse button in pressed before initiating the drag procedure. In addition, to guard against accidental dragging, this code checks to make sure that the user has moved the mouse a distance greater than a set
threshold (8 pixels by default).
*MouseMove
Parameters nButton, nShift, nXCoord, nYCoord
IF nButton = 1 && Left Mouse
IF ABS(nXCoord - THIS.PARENT.MouseX) > ;
THIS.Parent.DragThreshold OR ;
ABS(nYCoord - THIS.PARENT.MouseY) > ;
THIS.Parent.DragThreshold
THIS.Drag
ENDIF
ENDIF
The DragOver code changes the DragIcon of the source when the mouse pointer enters and leaves the list box
air space.
*DragOver
Parameters oSource, nXCoord, nYCoord, nState
DO CASE
CASE nState = 0 && Enter
oSource.DragIcon = THIS.Parent.CanDropIcon
CASE nState = 1 && Leave
oSource.DragIcon = THIS.Parent.NoDropIcon
ENDCASE
The DragDrop code makes sure that the source of the drag is not the same as the target of the drag and calls the method associated with the Click event of the cmdAdd command button (in the case of lstSelected) or cmdRemove (in the case of lstSource).
*DragDrop
Parameters oSource, nXCoord, nYCoord
IF oSource.Name != THIS.Name
THIS.PARENT.cmdAdd.Click
ENDIF
Multiselect Items in a List BoxI
Multiselect Items in a List Box
File: SAMPLES\SOLUTION\CONTROLS\LISTS\LMSEL.SCX
This sample shows how to manage multiple items selected in a list box. The form contains a list box with the MultiSelect property set to True (.T.). A combo box on the form contains all the items that are selected in the list box.
To process the multiple selected items in a list box
to copy them to an array or incorporate them elsewhere in your application
loop through the list items and process the ones for which the Selected property is set to true (.T.). The following code is included in the Click event of the list box to display the selected items in a combo box and the number of selected items in a text box:
nNoSelected = 0 && variable to track number of selected items
THISFORM.cboSelected.Clear && clear the combo box
* main processing loop
FOR i = 1 TO THIS.ListCount
IF THIS.Selected(i)
nNoSelected = nNoSelected + 1
THISFORM.cboSelected.Additem (THIS.List(i))
ENDIF
ENDFOR
THISFORM.txtNoSelected.Value = nNoSelected
In the code associated with the Init event of this form, and in many places throughout this sample application, the character string values initially added to the list are first defined with a
#DEFINE
directive. Each of the defined constants ends with "_LOC". Microsoft internal localization tools extract these definitions so that the strings can be translated into whatever language the application is being localized in.
Nest Transactions;
Nest Transactions
File: SAMPLES\SOLUTION\DB\TRANS.SCX
This sample illustrates beginning, ending, and rolling back transactions. You can decide to commit or discard changes to a single table when you use table buffering, but you can decide to commit or discard changes to any number of tables when you use transactions.
Before editing either table, click the
Begin
button. After editing, you can click
Begin
again to nest another transaction, or you can click
to commit your edits to the table or
Rollback
to discard your changes.
The key commands in this example are:
BEGIN TRANSACTION
END TRANSACTION
ROLLBACK
The function that returns the current number of nested transactions is:
This sample shows how to populate a list with files. When you populate a list with files, built-in functionality allows a user to select new drives and directories. In this sample, a user can select one or more files in the list and open them for editing.
The following code loops through the items in the list box and opens the selected files for editing:
FOR nFile = 5 to THISFORM.lstFiles.ListCount
IF THISFORM.lstFiles.Selected(nFile)
MODIFY FILE (THISFORM.lstFiles.List(2) + ;
THISFORM.lstFiles.List(nFile)) NOWAIT
ENDIF
ENDFOR
When the RowSourceType property is set to 7 - Files:
lstFiles.List(1) refers to the drive
lstFiles.List(2) refers to the path
lstFiles.List(3) is a separator line
lstFiles.List(4) is [..]. Click to go to the parent directory
Files can start at lstFiles.List(5)
Pass Parameters between FormsG
Pass Parameters between Forms
File: SAMPLES\SOLUTION\FORMS\PARAM.SCX
This solution illustrates passing parameters to a form and returning a value back.
PARAM Form
This form has the user enter a question and possible responses. Then, in the Click event of the cmdAsk button, the ParamAsk form is opened by passing the Question and Possible responses.
cParam1 = THISFORM.txtPassValue1.value
nParam2 = THISFORM.opgPassValue2.value
DO FORM LOCFILE("ParamAsk.scx") WITH cParam1, nParam2 TO nRetValue
PARAMASK Form
The PARAMETERS are passed to the Init of the form where they are processed.
PARAMETERS cQuestion, nButtons
THISFORM.txtQuestion.caption = cQuestion
In the Unload event of the form, the value stored in retvalue is returned back to the calling form:
RETURN THISFORM.retValue
Play an AVI File in an ActiveX ControlP
Play an AVI File in an ActiveX Control
File: SAMPLES\SOLUTION\OLE\MMSAMPLE.SCX
The sample shows how to use the Multimedia control to play an AVI file in a control that has an hWnd property.
The control with the hWnd is a custom ActiveX control called hWin, created with the OLE control wizard in Microsoft Visual C++ 4.0. In creating the hWin .OCX, all the default options in the OLE Control wizard were chosen, all the default properties were added to the control, and the code waD
s compiled.
In the Init of the form, the following line of code directs the Multimedia control to play the AVI in the hWin control (named Test).
ThisForm.VCR.hWndDisplay = ThisForm.Test.hWnd
Play Multimedia Files Using MCI CommandsR
Play Multimedia Files Using MCI Commands
File: SAMPLES\SOLUTION\FORMS\MCI_PLAY.SCX
This sample form uses MCI (Multimedia Command Interface) to play multimedia files and can play any visual or non-visual media that is installed on your system. However, the GETFILE(
) function prompts for the most common media files of .AVI, .WAV, .MOV, and .MID. To choose another file, select
All Files
and choose the desired file.
The documentation for the MCI commands is in Chapter 7 of the Windows SDK
Multimedia Programmer's Reference
Three Windows API functions are declared in the Init of the form:
mciSendString
mciGetErrorString
SetWindowPos
The DoMCI method of the form executes an MCI command that is passed in as a parameter.
Classes
You can open the form to see all the code necessary to run multimedia files, but the functionality has also been extracted into classes that you can easily incorporate into your own applications.
VideoFrame Class
The VideoFrame class in the Visual FoxPro SAMPLES\CLASSES\SAMPLES.VCX class library can be used to play a visual multimedia file, such as a Video for Windows file. The class allows you to position and size the video to be played, and then provides built-in methods to easily play the media file.
For an example of using this class, see VIDEO.SCX in the Visual FoxPro SAMPLES\SOLUTION\FORMS directory.
Property
Description
AutoOpen
Specifies whether the video file should automatically opened and displayed when the object is instantiated. The default value is true (.T.).
AutoPlay
Specifies whether the video file should automatically play when it is opened. The default value is true (.T.).
AutoRepeat
Specifies whether the video file will loop the video. Setting this to .T. will cause the video to play continuously. The default value is false (.F.).
ControlSource
Specifies a Field that contains the video file reference. If empty, the class expects a static file name to be in the VideoFile property
MCIalias
Specifies the alias to be used by MCI. If left empty, the alias defaults to the Name
property of the class. Normally this can be left empty, but if the user wants to play the same video file twice at the same time, a different alias would need to be specified for each.
VideoFile
Holds the name of a video file to play, for example
D:\VFP\SAMPLES\SOLUTION\FORMS\FOX.AVI
Method
Description
CloseVideo
Closes the video file and releases all resources associated with it.
DoMCI
Called by the other methods to execute MCI commands. It can also be called by a user to execute a specific MCI command.
OpenVideo
Opens the video file and shows the first frame.
PauseVideo
Pauses a playing video. The video can be restarted by using the PlayVideo
method
PlayVideo
Plays the video file. The video file must be opened in the OpenVideo method before it can be played.
SetPosition
Allows the user to specify the position of the media file. It can be executed at any time after the video file has been opened. Valid values are "Start", "End", or a specific millisecond into the video.
Sound Player Class
This class is also contained in the SAMPLES\CLASSES\SAMPLES.VCX class library. It can be used to play a non-visual multimedia file, such as a waveaudio file. The class allows you to specify the file to be played, and then provides built-in methods to easily play the media file.
Property
Description
AutoOpen
Specifies whether the sound file should be automatically opened and displayed when the object is instantiated. The default value is true (.T.).
AutoPlay
Specifies whether the sound file should be automatically played when it is opened. The default value is true (.T.).
AutoRepeat
Specifies whether the sound file plays continuously. The default value is false (.F.).
ControlSource
Specifies the column that contains the sound file reference. If empty, the class expects a static file name to be in the SoundFile property.
MCIAlias
Specifies the alias to be used by MCI. If left empty, the alias defaults to the Name
property of the class. Normally this can be left empty, but if the user wants to play the same sound file twice at the same time, a different alias would need to be specified for each.
SoundFile
Holds the name of a sound file to play, for example
C:\WINDOWS\CHIMES.WAV
Method
Description
OpenSound
Opens the sound file.
PlaySound
Plays the sound file. The file must be opened with the OpenSound method before it can be played.
PauseSound
Pauses the playing of a sound file. Play can be contiued by calling the PlaySound method.
SetPosition
Allows the user to specify the position of the media file. It can be executed at any time after the file has been opened. Valid values are "Start", "End", or a specific millisec
ond into the sound.
CloseSound
Closes the sound file and releases all resources associated with it.
Present a User with Multiple ChoicesN
Present a User with Multiple Choices
File: SAMPLES\SOLUTION\CONTROLS\BUTTONS\QUIZ.SCX
This sample illustrates using an option button group with no default selection and binding a character field to the option group.
To display an option group with no selected button, do one of the following
Set the Value property of each of the option buttons in the group to 0 of .F.
Set the Value property of the option button group to 0.
To store the caption of option buttons to a table field
Set the ControlSource of the option button group to the field.
Print a Percent of Total in a ReportN
Print a Percent of Total in a Report
File: SAMPLES\SOLUTION\REPORTS\PERCENT.FRX
The sample report, PERCENT.FRX, shows one way to calculate and display values at the beginning report before all the records from the record source have been printed. This sample report prints a percentage based on a total that is usually calculated and printed at the end of a report.
The sample report uses the tables, EMPLOYEE and ORDERS in its Data Environment. A public variable and expressions using the ORDER_AMT field are used to calculate the percentages.
To sort the data appropriately for the group defined in the report, the Order property on Cursor1 is set to the EMP_ID index.
The public variable, nTotalSales, defined in the Init event of Cursor2, stores the total for all orders. The variable is declared public to make it visible beyond the Cursor2 Init code.
A field control in the Group Footer band calculates and displays the percentage for each employee using the following expression:
This report shows an invoice report that uses a view to combine information from multiple tables, a function to collect data from the user, and a one-to-many report layout. When the report is run, the view runs first and prompts the user for a date range using a function called DATEPICK.PRG. After the user provides the dates, the view runs and selects the records to display in the report.
The Record Source
View, INVOICE, used in this report resides in the TESTDATA database provided with the Solution project. This view combines data from four tables, CUSTOMER, ORDERS, ORDITEMS, and PRODUCTS. To filter the tables for records within a date range, the view has two filters each with a parameter, dStart_Date and dEnd_Date.
The Data Environment
The view is included in the data environment. To store values collected for the view and to restore the path setting, the BeforeOpenTables method of the data environment declares three public variables dStart_date, dEnd_Date, cOldPath, The first two match the parameters specified in the view. The third, cOldPath saves the current path setting so the path can be restored in the Destroy method. The path is then changed so the report is able to find the function which prompts the user for a range of dates. The final command runs the function.
The Destroy method of the data environment has public variables for the start and end dates, path setting to return the default path to what it was before the report was run, and release statements for all three of the public variables.
The DATEPICK.PRG
This function defines and runs a form class called frmDATEPICK. The form class includes four comboboxes that display and collect values to use in the public variables, dStart_Date and dEnd_Date. The four variables collected are nFromMonth, nFromYear, nToMonth, and nToYear. These variables store the user input and are used to determine the value of dStart_Date and dEnd_Date. The function also checks to make sure the user entered values for each element of the date and verifies that the end date is after the start date.
The Report Layout
In the report layout, a Group Header band holds the controls for the customer information, the Detail band has the controls for the order items, and the Group Footer band holds the controls that display the calculated values for the invoice.
To format the address appropriately, an expression in the control concatenates several fields with appropriate punctuation. To calculate values in the Group Footer band, two report variables, nSubtotal and nDiscount, store values for the subtotal and the percentage discount.
Print Customer Mailing LabelsG
Print Customer Mailing Labels
File: SAMPLES\SOLUTION\REPORTS\CUST.LBX
This example illustrates printing mailing labels, one for each customer in the customer table.
The labels include 4 items:
Company
Contact +
+ Title
Address
City +
+ Region+
+ Country
The logo is displayed on each label by using the OLE container control.
Print Data Dictionary InformationK
Print Data Dictionary Information
File: SAMPLES\SOLUTION\REPORTS\DBCTOFRX.SCX
This sample illustrates a simple way to generate a report with the contents of a Visual FoxPro database (DBC). Simply pick a DBC file when prompted and a report will be generated for you to preview. You can click on the Print button to generate a hard copy of it.
The sample creates a temporary cursor and inserts new records as the DBC is scanned. Table and view records are added along with their associated field and index information.
Print Product Orders By QuarterI
Print Product Orders By Quarter
File: SAMPLES\SOLUTION\REPORTS\ORDGRAPH.SCX
This sample illustrates generating and printing graphs on-the-fly. Visual FoxPro allows you add graphs to forms as either OleControls or OleBoundControls. The latter representing a g!
raph which is bound to data via a General field.
If you intend to use the VFP report writer to print graphs, you need to use General fields to store the graphs. The easiest way to create a new graph in a General field is to use the APPEND GENERAL command, for example:
APPEND GENERAL graphfield CLASS
msgraph
The example above will create a graph in a General field, however, it won
t contain your data. The DATA clause actually passes data to the graph.
The following code loops through records already containing data and constructs a string to pass to the graph with APPEND GENERAL .... DATA.
Once you have a table or cursor containing a General field with your graphs, you can then print it to a Visual FoxPro report using the REPORT FORM command. You cannot include an ActiveX control in a report.
Print in Catalog FormatA
Print in Catalog Format
File: SAMPLES\SOLUTION\REPORTS\WRAPPING.FRX
The sample report, WRAPPING.FRX, prints an employee directory and shows how you can wrap text around graphics, alternate the print position of controls, and float controls below fields that stretch. The data environment for this report contains the EMPLOYEE table from the TESTDATA.DBC in the Solution project.
The Report Layout
The Title band holds the name and description of the report. The Detail band holds the field and label controls that print for each record. For each record the report displays four categories of information.
Employee name and title
Biography
Box of quick reference information such as phone and address
Photograph
After printing the name and title, this report wraps the text of the biography around the photograph, alternates information from left to right, and floats the box down the page relative to the biography.
Wrap Text Around Graphics
To wrap the memo field around the picture, the report uses two field controls to display the contents of the memo field. The first control is above the picture to display two lines of text. The second field is also sized to show two lines of text, but is narrower and positioned next to the picture.
The first field control prints all of the words in the memo field up to the position where a break should occur to continue the words in the second control. The expression is shown below.
LEFTC(employee.notes,nWrapCharPos)
The second field control prints the remaining words from the memo field. The expression for the second field control is shown below.
The expressions for the controls use report variables to determine the words the controls display from the memo field.
nFirstMemoLen determines the number of characters that can be displayed in the first field without truncating. For this report, the variables value is always 185. If you use this in your own report, you will need to change this constant to match the maximum number of characters you want above the picture.
nMemoLen determines the length of the memo field for the current record. This variable's expression is LENC
(employee.notes)
nSpace determines the character position of the first space after the characters displayed in the first control. This variable's expression is
nWrapCharPos determines the character position within the memo field where the break should occur. This variable's expression is
nSpace + nFirstMemoLen
Alternate the Position of Printed Objects
In this report, the positions of the employee biography, the quick reference group, and the photograph alternate from left to right with each record. To alternate the positions, the report has two sets of controls for the parts of the report that alternate. Because two controls are used to wrap the biography text, the first control does not alternate and, therefore, does not need to be included in the two sets.
One set of controls specifies printing with the photograph on the left side. A second set specifies the printing for the photograph on the right side. The controls in both sets use a report variable, nCounter, that calculates a count which determines when the set should print. One set prints when nCounter's value is 0; the other when the value is 1. The Print When expression for the first set of controls is
MOD(nCounter,2) = 0
. For the second set, the expression is
MOD(nCounter,2) = 1
Float Controls Below Controls that Stretch
This report prints the box of information prints below the biography. Since the length of the biography varies with each record, the control that displays the biography information next to the picture is set to stretch and uses only the space necessary to print the contents of the field. The box that prints below the biography floats down the page depending on the length of the biography. This box is a group of field, label, and rectangle controls. To prevent the biography from printing on top of the group, the field position for each of the controls in the group is set to float.
Print Report Details in a Ledger StyleP
Print Report Details in a Ledger Style
File: SAMPLES\SOLUTION\REPORTS\LEDGER.FRX
The report , LEDGER.FRX, prints an employee phone list that alternates printing a gray background behind records. The data environment for this report contains the EMPLOYEE table from the TESTDATA.DBC in the Solution project.
In the report layout, the Page Header band has label controls that print the report title, description, and column headings. The Detail band has the field and label controls that print the information for each employee.
To print with ledger style, the controls for the employee information are on top of a rectangle. The rectangle's color is gray and it's mode is opaque. The report prints the rectangle for every other record by evaluating an expression in the Print When opti
ons of the rectangle control. The expression is MOD(nCounter,2) = 1 which uses a report variable, nCounter that increments for each record printed. The report uses the value of this variable to determine when to print the rectangle.
Programmatically Check Table PropertiesQ
Programmatically Check Table Properties
File: SAMPLES\SOLUTION\DB\INFO.SCX
This sample illustrates getting information about a table at run time.
Field Information
The AFIELDS(
) function provides most of the information about table fields displayed in this sample. In addition to the information displayed in this sample, AFIELDS(
) provides information about field and table validation expressions and messages, trigger expressions and messages, as well as long table name and table comment in the database.
Index Information
The TAG(
) and KEY(
) functions provide index information:
lo = THISFORM.edtProperties
FOR i = 1 TO 254
IF !EMPTY(TAG(i)) && Checks for tags in the index
lo.Value = lo.Value + TAG(i) +
+ KEY(i)
EXIT
ENDIF
ENDFOR
Programmatically Manipulate ObjectsM
Programmatically Manipulate Objects
File: SAMPLES\SOLUTION\FORMS\OBJECTS.SCX
This sample shows how to set properties at run time for objects in a form set. The sample form set contains two forms. Code associated with the Click event of controls on both forms change the property settings of other controls.
When setting properties of controls at run time, remember to reference the control through its container hierarchy. For example, to set the Value property of a control on one form from code in a method of another form, reference the highest-level container (the form set), and all subsequent containers.
THISFORMSET.frmLeft.chkBold.Value = .F.
For a more detailed description of this sample, see Chapter 9, "Creating Forms," in the
Developer's Guide
Programmatically Manipulate TextJ
Programmatically Manipulate Text
File: SAMPLES\SOLUTION\CONTROLS\TXT_EDT\TEXT.TXT
This sample illustrates using the SelStart, SelLength, and SelText properties of an edit box to manipulate the text at run time. The sample also counts the characters, words, and paragraphs in a text file and allows a user to search for a string in a text file.
Formatting Text
The following code is included in the Click event of the button that formats selected text to uppercase:
lo = THIS.Parent.edtText
lnOldStart = lo.SelStart
lnOldLength = lo.SelLength
lo.SelText = UPPER(lo.SelText)
lo.SelStart = lnOldStart
lo.SelLength = lnOldLength
If you want to specify the font attributes of selected sections of text, use a RichText control.
Searching for Text
After getting the text to search for, the following code loops through all the text in the edit box, comparing it to tha
s LockScreen property to true (.T.) before searching and false (.F.) after searching. Otherwise, the form will repaint every time the SelStart property of the edit box is changed.
Provide a Hierarchical Display of ItemsQ
Provide a Hierarchical Display of Items
File: SAMPLES\SOLUTION\OLE\OUTLINE.SCX
This sample shows two different types of ActiveX controls which you can use for outlining. In this sample, a directory structure is displayed. A custom method on the form named FillTree is called recursively to iterate through the entire tree structure.
The Outline control can be used for simple outlining, however, it does not offer the Windows 95 shell look available with the Treeview control. In addition, the Treeview control also allows display of images with each node.
Outline Control
You can add items to the outline control with the AddItem method. Indentation is handled through the Indent method which takes an index number representing the item to affect.
The new Treeview control can give your applications a truly genuine Windows 95 look. Unlike the Outline control which uses methods and item indexes, the Treeview control uses a Nodes collection.
To display images in a treeview control, you must add an ImageList control to the form.
s This Help on a form, a button with a question mark is displayed in the upper right corner of the form.
When a user clicks this button or presses SHIFT+ F1, the form is set to WhatsThis mode. You can also programmatically enter this state by calling the WhatsThisMode method of the form. When the form is in WhatsThis mode, the mouse pointer changes. A user can click a control and get context-sensitive help
for that control in a popup window.
If the WhatsThisHelpID of a control or a form is set to -1 (the default), the text in the popup window indicates that no help topic is available for the control.
To provide What
s This Help
Create a Help file with a topic for each control on the form.
In the Map section of the Help project, map HelpContextID values to the topics.
Set the WhatsThisHelp property of the form to true (.T.).
Set the WhatsThisButton property of the form to true (.T.).
Set the WhatsThisHelpID of the controls to the appropriate helpcontextID values.
In the Load or Init of the form, use the SET HELP TO command to specify the help file for the form.
In addition to WHATTHIS.SCX, this sample includes the following files:
Description
WHATTHIS.HLP
The Help file for the form
WHATTHIS.HPJ
The Help project file
WHATTHIS.RTF
The source document for the Help file
Read and Write VFP Registry ValuesV
Read and Write Visual FoxPro Registry Values
File: SAMPLES\SOLUTION\WINAPI\REGFOX.SCX
This example shows how to access the Windows Registry using the native Visual FoxPro DECLARE-DLL command. The Windows API provides a number of functions you can use to access, read and write to the registry. The REGISTRY.PRG class library in \SAMPLES\CLASSES contains a class definition that exposes these functions as methods that you can call in your applications.
The contents of the Visual FoxPro Options dialog, Field Mapping settings and Label definitions (to name a few) are stored in the Registry. Since many of these settings are not available via SET functions, you can use Registry functions to access these values. The following code populates an array of all the settings in the Options dialog.
regfile = HOME()+"samples\classes\registry.prg"
SET PROCEDURE TO (m.regfile) ADDITIVE
oReg = CreateObject("FoxReg")
DIMENSION aFoxOptions[1,2]
m.nErrNum = oReg.EnumFoxOptions(@aFoxOptions)
The following code calls the SetFoxOption method of the FoxReg class (defined in REGISTRY.PRG) to set TALK OFF in the registry.
regfile = HOME()+"samples\classes\registry.prg"
SET PROCEDURE TO (m.regfile) ADDITIVE
oReg = CreateObject("FoxReg")
m.nErrNum = oReg.SetFoxOption("TALK","OFF")
Read ODBC Registry ValuesC
Read ODBC Registry Values
File: SAMPLES\SOLUTION\WINAPI\REGODBC.SCX
This example shows how to access the Windows Registry using the native Visual FoxPro DECLARE-DLL command. The Windows API provides a number of functions you can use to access, read and write to the registry. The REGISTRY.PRG class library in \SAMPLES\CLASSES contains a class definition that exposes these functions as methods that you can call in your applications.
The Registry contains a PN
listing of all installed ODBC drivers and data sources. If your application relies on using ODBC, then you might want to perform a Registry check to see if a particular driver or data source is installed. This example shows how to query for ODBC information.
LOCAL oReg,regfile,nErrNum,lDrivers
PUBLIC aODBCData
regfile = HOME()+"samples\classes\registry.prg"
SET PROCEDURE TO (m.regfile) ADDITIVE
oReg = CreateObject("ODBCReg")
DIMENSION aODBCData[1]
m.nErrNum = oReg.GetODBCDrvrs(@aODBCData)
Refresh a Graph in a FormC
Refresh a Graph in a Form
File: SAMPLES\SOLUTION\OLE\STOCK.SCX
This sample illustrates selecting data from a table and passing it to MS Graph to refresh the values in a chart. Most of the code to do this is associated with the InteractiveChange event of the cboMonth combo box:
Select the data into a cursor
SELECT date, close;
FROM Stock1 WHERE MONTH(date) = THIS.Value ;
ORDER BY date INTO CURSOR wtemp
Create a character string containing the selected data
SELECT wtemp
lcData = " " + TAB + "Closing Price" + CRLF
lcData = lcData + DTOC(date)
lcData = lcData + TAB
lcData = lcData + ALLTRIM(STR(close)) + CRLF
ENDSCAN
Send the character string to MS Graph
SELECT Graph
APPEND GENERAL msgraph DATA lcData
Resize and Reposition Controls at Run TimeT
Resize and Reposition Controls at Run Time
File: SAMPLES\SOLUTION\FORMS\CRESIZE.SCX
A user can resize this sample form as desired. The controls on the form are resized or repositioned relative to the new Height and Width properties of the form.
This form uses the resizable class in SAMPLES\CLASSES\SAMPLES.VCX to manage resizing and repositioning of the controls. The following line of code is added to the Resize event of the form, calling the AdjustControls method of the resizable class:
THIS.Resizable2.AdjustControls
In the Init of the resizable class, code loops through all the controls in the form, storing their positions and sizes relative to the form in an array. When the form is resized, the AdjustControls method resizes and repositions the controls to their relative sizes and positions.
You can add more controls to the form and the new controls will also be resized and repositioned.
The RepositionList and ResizeList properties contain a space-delimited list of all the classes that you want to reposition and resize. If you don
t want a certain class to be resized, remove it from the ResizeList.
You can prevent a user from making the form too small for the objects contained on it by setting the form's MinHeight and MinWidth properties.
Return a Value from a FormD
Return a Value from a Form
File: SAMPLES\SOLUTION\FORMS\LOGFORM.SCX
This sample illustrates returning a value from a login form. The launching form (LOGFORM.SCX) uses the DO Fm
ORM command to run the login form and store the return value to a variable (cUser).
DO FORM
Login
cUser
To return a value from a form, the WindowType property of the form must be set to 1 - Modal.
The login form (LOGIN.SCX) allows a user to enter a user name and a password. Code associated with the Click event of cmdOK checks to make sure that the correct password was entered:
LOCATE FOR UPPER(login.userid) = UPPER(ALLTRIM(THISFORM.txtUserName.Value))
IF FOUND() AND ALLTRIM(password) == ALLTRIM(THISFORM.txtPassword.Value)
THISFORM.cUser = ALLTRIM(login.userid)
THISFORM.Release
#DEFINE MISMATCH_LOC "The user name or password is incorrect. Please try again."
WAIT WINDOW MISMATCH_LOC TIMEOUT 1.5
THISFORM.txtUserName.Value = ""
THISFORM.txtPassword.Value = ""
THISFORM.txtUserName.SetFocus
ENDIF
Code associated with the Unload event of the login form returns the name of the user, if the user entered the correct password, or an empty string:
RETURN THIS.cUser
Run Multiple Instances of a FormJ
Run Multiple Instances of a Form
File: SAMPLES\SOLUTION\FORMS\LAUNCH.SCX
This sample demonstrates running multiple instances of a form.
aForms
is an array property of the form that launches the multiple instances. The following code is associated with the Click event of the command button that launches multiple forms:
Get the number of the last element in the array
nInstance = ALEN(THISFORM.aForms)
Determine the Top and Left Properties to cascade the new forms. These settings are passed as parameters when the form instances are launched.
Run the form and assign the object variable to the array element. The Linked keyword indicates that all instances will be released when the array is released. Without
LINKED
, the multiple instance forms would persist after the array is released.
DO FORM Multi NAME THISFORM.aForms[nInstance] WITH ;
nFormTop, nFormLeft, cFormCaption LINKED
Redimension the array so that more instances of the form can be launched.
This sample illustrates a variety of properties that can be set to customize command button display.
Property
Description
Cancel
The Click event code of the command button with Cancel set to true (.T.) is executed when a user presses ESC.
Default
The Click event code of the command button with Default set to true (.T.) is executed when a user presses ENTER
Picture
Bitmap displayed if Style is Graphical
Select Customers in a Specific CountryP
Select Customers in a Specific Country
File: SAMPLES\SOLUTION\DATA\TESTDATA.DBC
This sample illustrates using a parameterized view (
customers in specific country
in the testdata database) to display a subset of records that match a variable set at run time.
To create a parameterized view in the View Designer, enter a variable prefixed with a question mark (?) in the
Example
box of the
Filter
tab.
If the variable doesn
t exist at run time, the user is prompted to enter a value for the variable,
whichcountry
in this example. If the variable already exists, the view displays matching records without prompting for a new value.
Select Records from a Full Outer JoinO
Select Records from a Full Outer Join
File: SAMPLES\DATAT\FOUTERJ.QPR
The query, FOUTERJ, in the Solution project combines information from the country table and the customer table using a full outer join. Each result record has a field for each of the fields from the country table, and the
country
and
cust_id
field for the field from the customer table as specified in the SELECT clause of the SELECT-SQL statement.
SELECT
Country.*, Customer.country, Customer.cust_id;
testdata!customer
FULL JOIN
country ;
Customer.country = Country.country
Typically, a full outer join answers three questions about the records in your database. Some of the questions this query could answer are
Which customers are in which countries?
Which countries do not have any of our customers in them?
Which customer records are missing country information?
This information might help someone decide if they should expand their business to other countries, change their marketing strategy in some countries, or simply that some records in the database need the country information updated.
The full outer join returns all records from both tables and combines records that match the join condition. The result set includes three subsets of records.
Records matching the join condition that combine information from a record in each table.
Records from the country table that do not match the join condition.
Records from the customers table that do not match the join condition.
Because each record in the results has the same fields, the records that did not have a match in the other table have NULL values in the fields that would otherwise hold values the other table. For example, if a record for the country, Russia, did not have any related customer records in the customer table, that record appears in the results with NULL as the value of the field,
cust_id
and
country_b
NULL values appear in fields for non-matching records.
You can change the results of the query by specifying filters, a sort order, group, or other miscellaneous options for the query.
Select Records from a Left Outer JoinO
Select Records from a Left Outer Join
File: SAMPLES\DATA\LOUTERJ.QPR
The query, LOUTERJ, in the Solution project combines information from the orders table and the customer table using a left outer join. Each result record has a fields for the
order_id
from the orders table and for the
cust_id
company
country
fields from the customer table as specified in the SELECT clause of the SELECT-SQL statement.
Typically, a left outer join can answer two questions about the records in your database. Some of the questions this query could answer are:
Which orders belong to which customers?
Which orders do not have related customer information?
This information helps the database administrator determine which order records are missing information.
The left outer join returns all records from the table on the left of the join condition combined with the records from the table on the right of the condition that match the condition. The results set includes two subsets of records.
Records matching the join condition that combine information from a record in each table.
Records from the orders table that do not match the join condition.
Because each record in the results has the same fields, the records with an
order_id
that did not have a match in the customer table have NULL values in the fields that would otherwise hold values from the customer table. For example, if the record for order 11079, did not have any related customer records in the customer table, that record appears in the results with the value NULL in the fields,.N
cust_id
company
, and
country
The order for 11079 does not have a match any record in the Customer table
You can change the results of the query by specifying filters, a sort order, group, or other miscellaneous options for the query.
Select Records from a Nested JoinK
Select Records from a Nested Join
File: SAMPLES\DATA\NESTED.QPR
The query,
NESTED
, in the Solution project combines information from the customer, orders, and orditems tables using two inner join conditions. One join condition is between customer and orders; the other between orders and orditems. Each result record has fields for the
cust_id
and
company
from the customers table,
order_id
from the orders table, and
line_no
from the orditems table as specified in the SELECT clause of the SELECT-SQL statement.
The order in which the tables are joined determines the order the join conditions are evaluated. In this query, the join between orders and orditems is evaluated first and produces a subset of records that meets the join condition. This subset of records is matched to the records in the customer table and produces the final results set.
You can change the results of the query by specifying filters, a sort order, group, or other miscellaneous options for the query.
Select Records from a Right Outer JoinP
Select Records from a Right Outer Join
File: SAMPLES\DATA\ROUTERJ.QPR
The query, ROUTERJ, in the Solution project uses the testdata database, and combines information from the orders table and the employee table using a right outer join. Each result record has a field for the
order_id
from the orders table and for the
lastname
field from the employee table.
SELECT
Orders.order_id, Employee.last_name;
testdata!employee
RIGHT OUTER JOIN
testdata!orders ;
Employee.emp_id = Orders.emp_id
Typically, a right outer join can answer two questions about the records in your database. Some of the questions this query could answer are
Which orders were entered by which employees?
Which orders do not have an employee specified?
This information may help track specific orders and identify orders that do not have an employee specified as placing the order.
The right outer join retrieves all records from the table on the right of the join condition combined with the records from the table on the left that match the join condition. The results set includes two subsets of records.
Records matching the join condition that combine information from a record in each table.
Records from the orders table that do not match the join condition.
Because each record in the results has the same fields, the records with a
lastname
that did not have a match in Y
the orders table have NULL values in the field that would otherwise hold values from the orders table. For example, if a record for order number 11078 did not have any related employee records in the employee table, that record appears in the results with the value NULL in the field,
lastname
The record for order 11078 without a matching record in the EMPLOYEE table.
You can change the results of the query by specifying filters, sort order, group, or other miscellaneous options for the query.
Select Records from an Inner JoinK
Select Records from an Inner Join
File: SAMPLES\DATA\INNERJ.OPR
The query, INNERJ, in the Solution project uses the database, TESTDATA, and combines information from the tables, ORDERS and CUSTOMER using an inner join condition. Each result record has fields for the CUST_ID, COMPANY, and COUNTRY from the CUSTOMERS table, and ORDER_ID from the ORDERS table as specified in the SELECT clause of the SELECT-SQL statement.
This query retrieves and combines the records between the two tables that match the join condition. The condition specifies that the records must have the same value in the
cust_id
field.
The inner join returns only records that match the join condition.
An inner join typically answers one basic question. In this query, the question is what orders did each customers place? If a customer has a record in the database but has not placed an order, the record does not appear in the results because it is not part of the subset that matches the join condition.
You can change the results of the query by specifying filters, a sort order, group, or other miscellaneous options for the query.
Select Records from Both Inner and Outer JoinsX
Select Records from Both Inner and Outer Joins
File: SAMPLES\DATA\COMBOJ.QPR
The query, COMBOJ, uses the testdata database, and combines information from the tables, customer, orders, and orditems. Each result record has fields for the
company
from the customer table, the
order_date
from the orders table, and the
line_no
from the orditems table as specified in the SELECT clause of the SELECT-SQL statement.
The order the tables are joined determines the order the join conditions are evaluated. In this query, the join between orders and orditems is evaluated first and produces a subset of records that meets the join condition. Because of the inner join, the subset of records has only records from both table that match the condition. This subset of records is matched to the records in the customer table. Because of the outer join between customer and orders, any customers not having orders also appear in the results and have the value NULL.
stomers without orders are included in the results.
You can change the results of the query by specifying filters, a sort order, group, or other miscellaneous options for the query.
Select the Ten Worst Selling ProductsO
Select the Ten Worst Selling Products
File: SAMPLES\DATA\WORSTTEN.QPR
This query displays the worst ten selling products based on sales recorded in the Order Items table. The query uses the TOP
feature of the SELECT statement, and, because the default order is from smallest to largest, ordering by the sum of price and quantity returns the 10 lowest values.
SELECT TOP 10
Products.prod_name,;
(Orditems.unit_price*Orditems.quantity);
testdata!products
INNER JOIN
testdata!orditems ;
Products.product_id = Orditems.product_id;
GROUP BY
Products.prod_name;
ORDER BY
Select the Top Ten Best Selling ProductsR
Select the Top Ten Best Selling Products
File: SAMPLES\DATA\TOPTEN.QPR
This query displays the top ten selling products based on sales recorded in the Order Items table. The query uses the TOP
feature of the SELECT statement. Because the order is set to DESCENDING, ordering by the sum of price and quantity returns the 10 highest values.
SELECT TOP 10
Products.prod_name,;
( Orditems.unit_price* Orditems.quantity);
testdata!products
INNER JOIN
testdata!orditems ;
Products.product_id = Orditems.product_id;
GROUP BY
Products.prod_name;
ORDER BY
Send Mail3
Send Mail
File: SAMPLES\SOLUTION\OLE\SENDMAIL.SCX
This sample illustrates using the mailbtn class in SAMPLES\CLASSES\BUTTONS.VCX to create a simple messaging form that can send Visual FoxPro data to an e-mail address.
Mailbtn is a container class that contains a command button and two ActiveX controls: MAPI Session and MAPI Messages, both of which are defined in MSMAPI32.OCX. The MAPI Session control establishes a MAPI session, and the MAPI Messages control allows the user to perform a variety of messaging system functions.
The mailbtn class starts a new Mail session, collects data from the current record, and brings up the Send Mail dialog with the data inserted as the message text.
This class includes two custom methods AddTabs and StripPath for formatting the information gathered from the table and inserted in the mail message.
This class also takes advantage of another custom method called Signon as well as a custom property called logsession, which is set to .F. initially.
When the user clicks the cmdMail button, code in the Click event calls the signon method, setting logsession to true (.T.).:
this.logsession = .T.
this.OLEMSess.signon
If there is a failure on signon, the Error event of the class is called and logsession is set to .F.
The MAPI controls are invisible at run time. In addition, there are no events for the controls. To use them, you must specify the appropriate methods. For t
hese controls to work, MAPI services must be present. MAPI services are provided in Microsoft Mail and Exchange electronic mail systems for Microsoft Windows version 3.0 or later.
Sort List Box Items=
Sort List Box Items
File: SAMPLES\SOLUTION\CONTROLS\LISTS\LSORT.SCX
This sample demonstrates allowing a user to rearrange or sort the items in a list. The key properties to set are:
List.MoverBars = .T.
List.Sorted = .T.
Set the MoverBars property to true (.T.) to allow a user to reorder an item in the list by dragging the button to the left of the item to the new position.
Set the Sorted property to true (.T.) to display the list items in alphabetical order. You can still rearrange the items in the list after they have been sorted. Set the Sorted property to .T. again to sort the list in alphabetical order again.
The Sorted property applies only if the RowSourceType property of the list is set to 0 (None) or 1 (Value).
Sort or Order A Table At Run TimeK
Sort or Order A Table At Run Time
File: SAMPLES\SOLUTION\DB\ORDER.SCX
This sample illustrates changing the order that records in a table are listed. The customer table has index tags on the fields displayed in the grid. In the MouseUp event of each of the headers in the grid, the order of the table is set to the index tag associated with the field displayed in the column. For example, the following code is associated with the MouseUp event of the Company header:
LPARAMETERS nButton, nShift, nXCoord, nYCoord
IF nShift = 2 && CTRL
SET ORDER TO
Company
DESCENDING
SET ORDER TO
Company
ASCENDING
ENDIF
GO TOP
THISFORM.Refresh
Use API Functions that Require a StructQ
Use API Functions that Require a STRUCT
File: SAMPLES\SOLUTION\WINAPI.SYSTIME.SCX
This example illustrates calling the Windows API function GetSystemTime. GetSystemTime fills in a structure of WORD (16-bit unsigned integer) values with system time information.
C Function Declaration and Struct Definition
VOID GetSystemTime(
LPSYSTEMTIME
lpSystemTime
// address of system time structure
);
This is the struct definition
typedef struct _SYSTEMTIME {
WORD wYear;
WORD wMonth;
WORD wDayOfWeek;
WORD wDay;
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;
} SYSTEMTIME;
Calling the Function in Visual FoxPro
The Visual FoxPro code passes GetSystemTime a reference to a character variable, which is filled in with the WORD values.
* Visual FoxPro Code: cmdSystemTime.Click
DECLARE INTEGER GetSystemTime IN win32api STRING @
cBuff=SPACE(40)
GetSystemTime(@cBuff)
To retrieve the information from the character variable, cBuff, the following code converts 8 bit ASCII characters for year and month in the variable into 16 bit equivalents.
Use API Functions that Require Pointers to Arrays[
Use API Functions that Require Pointers to Arrays
File: SAMPLES\SOLUTION\WINAPI\SYSCOLOR.SCX
This example uses two Windows API functions to first get the system color settings (GetSysColor) and then to reset the system colors to new values (SetSysColors). Two of the three arguments required by SetSysColors are pointers to native C arrays.
GetSysColor
The GetSysColor function accepts an integer parameter, a number between 0 and 18, and returns a DWORD (32-bit unsigned integer) indicating the current color setting.
DWORD GetSysColor(
int
nIndex
// display element
);
nIndex is a value representing an area of the interface, as defined in the following list.
#define COLOR_SCROLLBAR 0
#define COLOR_BACKGROUND 1
#define COLOR_ACTIVECAPTION 2
#define COLOR_INACTIVECAPTION 3
#define COLOR_MENU 4
#define COLOR_WINDOW 5
#define COLOR_WINDOWFRAME 6
#define COLOR_MENUTEXT 7
#define COLOR_WINDOWTEXT 8
#define COLOR_CAPTIONTEXT 9
#define COLOR_ACTIVEBORDER 10
#define COLOR_INACTIVEBORDER 11
#define COLOR_APPWORKSPACE 12
#define COLOR_HIGHLIGHT 13
#define COLOR_HIGHLIGHTTEXT 14
#define COLOR_BTNFACE 15
#define COLOR_BTNSHADOW 16
#define COLOR_GRAYTEXT 17
#define COLOR_BTNTEXT 18
#define COLOR_INACTIVECAPTIONTEXT 19
#define COLOR_BTNHIGHLIGHT 20
#if(WINVER >= 0x0400) /* Windows 95 differences */
#define COLOR_3DDKSHADOW 21
#define COLOR_3DLIGHT 22
#define COLOR_INFOTEXT 23
#define COLOR_INFOBK 24
#define COLOR_DESKTOP COLOR_BACKGROUND
#define COLOR_3DFACE COLOR_BTNFACE
#define COLOR_3DSHADOW COLOR_BTNSHADOW
#define COLOR_3DHIGHLIGHT COLOR_BTNHIGHLIGHT
#define COLOR_3DHILIGHT COLOR_BTNHIGHLIGHT
#define COLOR_BTNHILIGHT COLOR_BTNHIGHLIGHT
#endif /* WINVER >= 0x0400 */
SetSysColors
The SetSysColors function requires three arguments: the number of elements in two arrays and the addresses of the two arrays.
BOOL WINAPI SetSysColors(
int
cElements
// number of elements to change
CONST INT *
lpaElements
// address of array of elements
CONST COLORREF *
lpaRgbValues
// address of array of RGB values
);
Calling SetSysColors in Visual FoxPro
The following code is extracted from cmdSetSysColors.Click:
DECLARE INTEGER
SetSysColors
IN win32api INTEGER, STRING, STRING
Construct the elements of the first array in a character variable.
cElements = ""
FOR i = 0 TO 18
cElements = cElements + THISFORM.DecToHex(i)
ENDFOR
Construct the elements of the second array in a character variable. The cursor that is scanned was filled with GetSysColor values in the Init of the form.
cColors = ""
cColors = cColors + THISFORM.DecToHex(INT(color))
ENDSCAN
SetSysColors
(18,cElements,cColors)
Use Conditional Formatting in a ReportP
Use Conditional Formatting in a Report
File: SAMPLES\SOLUTION\REPORTS\COLORS.FRX
This sample report demonstrates how you can use Print When conditions for controls to change field formatting based on the values in the record. The sample prints a "Product Inventory Report." If the product item is discontinued, it is printed in strikeout. If the In Stock amount is below the reorder level and the product is not discontinued, the item is printed in red. Otherwise, the product item is printed in standard black.
This report uses the table, PRODUCTS, from the database, TESTDATA, in the Data Environment. The Detail band has field controls for the product information such as ID, name, amount in stock, and amount on order. Another field control prints an reminder of the inventory level the reader of the reorder amount.
To handle the three cases, three sets of field controls for the product information are layered on top of each other in the Detail band. For the first set, the text color is red; for the second, the color is black; and for the third, the font effect is Strikeout.
Each control set has a different Print When expression.
For the plain black fields:
(products.in_stock > products.reorder_at) and products.discontinu = .F.
For the strikeout fields:
products.discontinu = .T.
For the red text color fields:
products.in_stock <= products.reorder_at and products.discontinu = .F.
Use Slider and Status Bar ControlsL
Use Slider and Status Bar Controls
File: SAMPLES\SOLUTION\OLE\SLIDER.SCX
This sample illustrates using the Slider control and the StatusBar control.
Slider Controls
Code in the Scroll event of each slider control sets the Value property of the other controls:
The StausBar Control Properties dialog box makes setting status bar properties easy.
To open the StatusBar Control Properties dialog, choose StatusBar Control Prop
erties from the shortcut menu of a StatusBar Control.
Use the RichText ControlB
Use the RichText Control
File: SAMPLES\SOLUTION\OLE\RTF.SCX
This sample illustrates using a RichText control to display and edit RTF text stored in the memo field of a table.
You can set the ControlSource of a RichText control directly to a character field, but not a memo field. Instead, create a form property to mediate between the RichText control and the memo field.
To store RTF text in a memo field
Set the ControlSource property of the RichText control to the form property.
THISFORM.oleRTF.ControlSource = THISFORM.cText
Store the memo field contents to the form property.
THISFORM.cText = rtf.source
Before moving the record pointer, store the TextRTF property of the RichText control to the memo field.
REPLACE rtf.Source WITH THISFORM.oleRTF.TextRTF
The text stored in the memo file is standard RTF format, for example:
{\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswiss MS Sans Serif;}{\f1\froman\fcharset2 Symbol;}{\f2\fswiss Arial;}{\f3\fswiss Arial;}} {\colortbl\red0\green0\blue0;\red255\green0\blue0;} \deflang1033\pard\qc\plain\f3\fs32\i The RichTextBox Control \par \pard\plain\f3\fs20
View Type Library InformationG
View Type Library Information
File: SAMPLES\SOLUTION\WINAPI\TYPELIB.SCX
The TYPELIB sample uses a Visual FoxPro class named Typelib which is stored in SAMPLES\CLASSES\TYPELIB.VCX. This container class has an ActiveX control called FoxTlib that contains a number of methods to read Type Library information from any DLL, EXE, or TLB file.
The Typelib wrapper class saves you time by handling much of the dirty work for you. There is a method called ExportTypeLib in this class which exports the contents of a specified Type Library to a text file:
If you take a look at the generated text file, you will notice that a Type Library can consist of multiple Type Infos. Each Type Info represents a specific class. When you generate a new EXE or DLL from a project using VFP, each class in the project which is marked as OLEPUBLIC will generate a separate Custom OLE Server. Note: you only have a single EXE/DLL file, however, this file can contain multiple servers (one for each OLEPUBLIC class). And VFP generates a single TLB file for the project. This Type Library file contains a separate Type Info for each OLEPUBLIC class.
Within each Type Info (OLEPUBLIC class), there are also Function descriptions. These represent all of the properties and methods of a class. For methods, the Type Library contains both parameter and return types. Some of the possible types are boolean , string, and variant. Because VFP does not strong type memory variables, many of the types used in your custom methods will be variant.
If you take a close look at the functions exported, you will notice double entries for many of the properties. Thi
s is because users can
the value of this property. And some languages such as Visual Basic allow you to have code executed when one of these properties is accessed or assigned. Hence, the Type Library will represent a single property with 2 entries. If only a single entry exists, then that property is read-only. Properties and methods which are marked as Hidden or Protected will not appear in the Type Library.
MS Sans Serif
Tms Rmn
Symbol
Courier
Times New Roman
Arial
MS Serif
Times
Helvetica
System
Courier New
New York
Geneva
LinePrinter
CG Times
Univers
Univers Condensed
Antique Olive
Garamond
CG Omega
Albertus Medium
Albertus Extra Bold
Clarendon Condensed
Coronet
Letter Gothic
Marigold
Wingdings
Marlett
Lucida Console
Arial Narrow
Arial Black
Book Antiqua
Bookman Old Style
Century Schoolbook
1-to-many form
ActiveX
ActiveX, automation
ActiveX, custom
ActiveX, Excel automation
ActiveX, RichText
ActiveX, slider and status bar controls
Add and Remove Items in a Treeview Control
Add Items Interactively to a List Box
Add Menu Items at Run Time
Add New Items to a Combo Box
Allow Users to Choose List Values
Allow Users to Drag and Drop Controls
Animation, form graphics
API Functions
Automate a Microsoft Excel Spreadsheet
Automate a Microsoft Word Document in a Form
Automate Microsoft Word and Excel
BEGIN TRANSACTION
BINTOC( )
Bitmaps, displaying
Calculations, in columns
Change Font Attributes
Change Pages When a User Chooses a Button
Change the Number of Tabs at Run Time
Check box, design options
Check mark, displaying beside a menu item
Clock
Column, displaying calculated values in
Combo Box, adding new items
Components in the Solutions sample application
Controls, adding to grid columns
Controls, resizing and repositioning
Coordinate Menu Items and Toolbar Buttons
Create a 1-To-Many Data Entry Form
Create a Default Unique Id Value for a Field
Create a Query-By-Example Form
Create a Single Table Data Entry Form
Create an SDI Form
Create Dynamic Shortcut Menus
Create Small Indexes Using BINTOC( )
Customize the Open Dialog Box
Dialog Box, customize
Disable or Display a Check Beside a Menu Item
Display a Stop Watch
Display a System Clock
Display Calculated Values in a Column
Display Child Records from a Relationship
Display Controls in a Grid
Display Different Pages Without Tabs
Display Line Animation on a Form
Display Multiple Columns in a List Box
Display Pictures in a List
Display Pictures in an Image Control
Display Shortcut Menus
Display System Information
Drag and drop, between list boxes
Drag and Drop, reposition a control
Draw Lines and Shapes on a Form
Dynamically Format Grid Columns
DynamicForeColor and DynamicBackColor
Edit a Memo Field or Text File
Edit box
Edit box, counting words
END TRANSACTION
Excel, automation
Execute Commands at Specified Intervals
Expressions, Indexing on
Files, opening
Fill a list with database elements
Fill a List with Values from Different Sources
Font, attributes, change
Form graphics, animation
Form graphics, graphing equations
Form graphics, lines and shapes
Form, 1-to-many
Form, data entry
Form, query by example
Format Input and Validate Data in a Text Box
Forms, running multiple instances
Forms, SDI
FoxDraw
Get Application Information from the Windows Registry
Get Version Information
GetSysColors
Graph
Graph Equations on a Form
Graph, refreshing
Grid, displaying calculated values in columns
Grid, displaying controls in columns
Grid, dynamic formatting
Grid, setting order
Help, What's This
How the Solutions Sample Works
Image control, displaying pictures
Index on Expressions
Indexes, small
Interactively Build a SELECT Statement
Labels
List box
List box, adding items
List box, displaying files
List box, multiple columns
List box, RowSourceType settings
List box, selecting multiple items
List box, Sorted property
List boxes, moving items between
Logon form
Lookup values
Mail, send
Manipulate Display Characteristics of a Graph
Memo field editing
Menu item, checking
Menu item, disabling
Menu items, adding at run time
Menu items, coordinating with toolbars
Menus, display shortcut
menus, dynamic shortcut
Microsoft Word and Excel, automate
MODIFY FILE command
Move Items Between List Boxes
Moverbars property, list box
MS Graph, manipulating
Multimedia
Multiple table data entry
Multiselect Items in a List Box
MultiSelect property, list box
Nest Transactions
Nodes, adding to a treeview control
OLE, Manipulating graph characteristics
Open Dialog Box Flag Values
Open Multiple Files Interactively
Option buttons, multiple choices
Outline control
Page frame, adjusting tabs at run time
Page frame, changing pages with option buttons
Page frames, without tabs
Parameters, passing
Pass Parameters between Forms
Play an AVI File in an ActiveX Control
Play Multimedia Files Using MCI Commands
Present a User with Multiple Choices
Print a Percent of Total in a Report
Print an Invoice
Print Customer Mailing Labels
Print Data Dictionary Information
Print in Catalog Format
Print Product Orders By Quarter
Print Report Details in a Ledger Style
Programmatically Check Table Properties
Programmatically Manipulate Objects
Programmatically Manipulate Text
Properties, setting at run time
Provide a Hierarchical Display of Items
Provide What's This Help on a Form
Queries, build a SELECT statement
Queries, Select records from a full outer join
Queries, Select records from a left outer join
Queries, Select records from a nested join
Queries, Select records from a right outer join
Queries, Select records from an inner join
Queries, Select records from both inner and outer joins
Queries, Select the ten worst selling products
Queries, Select the top ten best selling products
Queries, Top N
Query By Example
Read and Write VFP Registry Values
Read ODBC Registry Values
Refresh a Graph in a Form
Relationship, displaying in a form
Reports, catalog
xcel, automate
Reports, conditional formatting
Reports, invoice
Reports, ledger
Reports, percent of total
Resize and Reposition Controls at Run Time
Return a Value from a Form
RichText control
ROLLBACK
RowSourceType, filling a list box
Run Multiple Instances of a Form
SDI form, creating
Search for values
See Check Box Design Options
See Command Button Design Options
Select Customers in a Specific Country
Select Records from a Full Outer Join
Select Records from a Left Outer Join
Select Records from a Nested Join
Select Records from a Right Outer Join
Select Records from an Inner Join
Select Records from Both Inner and Outer Joins
Select the Ten Worst Selling Products
Select the Top Ten Best Selling Products
SelStart and SelLength properties
Send Mail
SET ORDER TO
Single table data entry
Slider
Solution.scx
Solutions Sample
Sort List Box Items
Sort or Order A Table At Run Time
Sparse property, setting
Status bar
Stop watch
Stored procedures, creating a default field value
System Information, display
Table properties, getting
Text box, formatting text
Text file editing
Timer, clock
Timer, displaying a stop watch
Timer, executing commands
Toolbars, coordinating with menus
Transactions, nesting
Treeview
Treeview control
Unique ID, creating
Use API Functions that Require a Struct
Use API Functions that Require Pointers to Arrays
Use Conditional Formatting in a Report
Use Slider and Status Bar Controls
Use the RichText Control
Validate data in a text box
Version, get information
View Type Library Information
Views, Select customers in a specific country
What's This Help
WinAPI, registry
WinAPI, Registry information
Word, automation
xcel, automate
Drag and drop, between list boxes
MODIFY FILE command
Reports, conditional formatting
Solutions Sample
How the Solutions Sample Works
Components in the Solutions Sample Application
Add and Remove Items in a Treeview Control
Add Items Interactively to a List Box
Add Menu Items at Run Time
Add New Items to a Combo Box
Allow Users to Choose List Values
Allow Users to Drag and Drop Controls
Automate Microsoft Word and Excel
Automate a Microsoft Excel Spreadsheet
Automate a Microsoft Word Document in a Form
Change Font Attributes
Change Pages When a User Chooses a Button
Change the Number of Tabs at Run Time
Coordinate Menu Items and Toolbar Buttons
Create a 1-To-Many Data Entry Form
Create a Default Unique Id Value for a Field
Create a Query-By-Example Form
Create a Single Table Data Entry Form
Create an SDI Form
Create Dynamic Shortcut Menus
Customize the Open Dialog Box
Open Dialog Box Flag Values
Disable or Display a Check Beside a Menu Item
Display a Stop Watch
Display a System Clock
Display Calculated Values in a Column
Display Child Records from a Relationship
Display Controls in a Grid
Display Different Pages Without Tabs
Display Line Animation on a Form
Display Multiple Columns in a List Box
Display Pictures in a List
Display Pictures in an Image Control
Display Shortcut Menus
Display System Information
Draw Lines and Shapes on a Form
Dynamically Format Grid Columns
Edit a Memo Field or Text File
Execute Commands at Specified Intervals
Fill a List with Values from Different Sources
Format Input and Validate Data in a Text Box
Get Application Information from the Windows Registry
Get Version Information
Graph Equations on a Form
Index on Expressions
Create Small Indexes Using BINTOC( )
Interactively Build a SELECT Statement
Manipulate Display Characteristics of a Graph
Move Items Between List Boxes
Multiselect Items in a List Box
Nest Transactions
Open Multiple Files Interactively
Pass Parameters between Forms
Play an AVI File in an ActiveX Control
Play Multimedia Files Using MCI Commands
Present a User with Multiple Choices
Print a Percent of Total in a Report
Print an Invoice
Print Customer Mailing Labels
Print Data Dictionary Information
Print Product Orders By Quarter
Print in Catalog Format
Print Report Details in a Ledger Style
Programmatically Check Table Properties
Programmatically Manipulate Objects
Programmatically Manipulate Text
Provide a Hierarchical Display of Items
Provide What's This Help on a Form
Read and Write VFP Registry Values
Read ODBC Registry Values
Refresh a Graph in a Form
Resize and Reposition Controls at Run Time
Return a Value from a Form
Run Multiple Instances of a Form
See Check Box Design Options
See Command Button Design Options
Select Customers in a Specific Country
Select Records from a Full Outer Join
Select Records from a Left Outer Join
Select Records from a Nested Join
Select Records from a Right Outer Join
Select Records from an Inner Join
Select Records from Both Inner and Outer Joins
Select the Ten Worst Selling Products
Select the Top Ten Best Selling Products
Send Mail
Sort List Box Items
Sort or Order A Table At Run Time
Use API Functions that Require a Struct
Use API Functions that Require Pointers to Arrays
Use Conditional Formatting in a Report
Use Slider and Status Bar Controls
Use the RichText Control
View Type Library Information
ext Box
Get Application Information from the Windows Registry