Rapid-Q Preface

Preface to Rapid-Q
Original Documentation by William Yu ©1999-2000
Contributors- Stanescu Serban, Andrew Shelkovenko , D. Glodt, Jacques Phillip, John Kelly, many others

PREFACE

Rapid-Q is a BASIC-like programming language for the 32-bit multiplatform. It provides graphical user interfaces (GUI) and CONSOLE programs. The compiler is actually an interpreter for Windows, Linux, and Unix. Rapid-Q compiles your BASIC source code into byte-code, which is normally attached to an interpreter, but can also be run from other programming languages using specialized DLLs. Also Rapid-Q supports partial object-oriented programming. If you're familiar with either QBasic, PowerBasic, or even VisualBasic, you'll be able to program in Rapid-Q in no time. The overall goal of the project was to provide an alternative BASIC programming language that's not only FREE, but good and easy to use. Rapid-Q is constantly being improved by public support and this help document is part of that development.
The Rapid-Q compiler was written and developed by William Yu. The final release of the software was in BETA testing stage. However, Mr. Yu sold the rights to the owner of RealBASIC(c). Now William Yu no longer supports Rapid-Q. Do not even think about contacting either William Yu or the staff of RealBASIC about Rapid-Q. They would prefer you buy their BASIC compiler. Just because Rapid-Q was released in Beta stage doesn't mean the compiler is not fully functional! Rapid-Q can make very useable programs of significant complexity. Also don't expect the compiler to become "open source."
In Mr. Yu's words, "Being a BASIC programmer at heart, I looked through the eyes of a user, and added the features and ease of use that I like to see in a good programming language... Perhaps in the future, some of these features will become standard in all BASIC languages. The advanced features that Rapid-Q offers need not be used at all, but is available when you get more comfortable with the language itself. For example, Rapid-Q offers object/component creation, function pointers, procedures with infinite parameters, variants, while still maintaining all the fundamental features that most BASIC programmers are familiar with, ie. GOTO, GOSUB, line numbers, etc. This makes converting legacy code much easier. The only feature which deviates from traditional BASIC languages is file handling. I believe that once you understand how file and memory streams work, this can be a huge benefit, rather than a hassle.

Source Codes
The best way to learn is by example. It really isn't enough just to look at it and say "Uh huh, yeah." Take some time to take it apart and rewrite the code yourself. Trial and error is always a good way of learning. It seems we learn more by our mistakes, this is also true for programming. Yes, you'll have many nights of frustration when your code just doesn't seem to run properly, but once that bug is found, you'll be dancing around like there's no tomorrow. Sources and documentation are found at:

http://www.airsys.org (complete RapidQ2 system in an archived folder)
http://g.slyip.com (The largest collection of sample code but slow bandwidth)
 http://www.holyguard.net/public/rapidq/index.asp?projectid=19
http://www.wildgardenseed.com/RQDP/
http://home.planet.nl/~water793/
The Future of Rapid-Q
There is still a large community of contributors to the Rapid-Q language. However, you are "on your own" with Rapid-Q. FreeBasic is a very good free alternative to RapidQ. RealBASIC is very good commercial alternative to Rapid-Q if you need support. You can get started with programming with Rapid-Q and move up. You too can contribute to the development of the language and keep this Free, simple and easy-to-use compiler alive.


Table of Contents

Rapid-Q Documentation by William Yu ©1999-2000 Contents

Contents

    Preface
    Chapter 1: Rapid-Q Overview
    • 1.1 How slow is Rapid-Q anyway?
    • 1.2 What about bloat-ware?
    • 1.3 Does Rapid-Q require any extra runtime DLLs?
    • 1.4 How much memory does Rapid-Q suck out of my programs?
    • 1.5 How easy is it to hack into my programs?
    • 1.6 Do I need a license to distribute my programs?
    Chapter 2: Rapid-Q Fundamentals
    • 2.1 Rapid-Q Environment
      • Required files and settings
    • 2.2 Using the Rapid-Q IDE
    • 2.3 Compiling and Running a Simple Application
    • 2.4 Command line switches
    • 2.5 General Structure of a Rapid-Q Program
    • 2.6 How close to the BASIC language is Rapid-Q?
    Chapter 3: Rapid-Q Language Guide
    • 3.1 Rapid-Q Directives
      • $APPTYPE
      • $DEFINE and $UNDEF
      • $ESCAPECHARS
      • $IFDEF and $IFNDEF
      • $INCLUDE
      • $MACRO
      • $OPTIMIZE
      • $OPTION
      • $RESOURCE
      • $TYPECHECK
    • 3.2 Variables and Assignments
      • Numeric types, string types
      • Numeric Range values
      • Proper assignment, and inconsistencies
    • 3.3 Rapid-Q Components/Objects
    • 3.4 Component Methods & Events
    • 3.5 Rapid-Q Subroutines & Functions
      • Special conditions
      • Passing by value or reference
    • 3.6 Rules of Scope
    Chapter 4: Writing your first Rapid-Q Application
    • 4.1 Deciding what to write
      • Simple database like program
      • Using QButton, QEdit, QForm, QLabel, and QListBox
    • 4.2 Designing the form
    • 4.3 Handling events
      • How to handle on click events
    • 4.4 Source Code Listing
    Chapter 5: Introduction to Forms
    • 5.1 What's in a form?
    • 5.2 Adding components to a form
    • 5.3 Tracking mouse position on form
      • Introduction to MouseX and MouseY
    • 5.4 Special Events for forms
      • OnResize, OnKeypress, OnKeydown
    • 5.5 Dialog boxes
      • Use of ModalResult
    • 5.6 Using the CREATE Method
    • 5.7 Embedding CREATEs
    • 5.8 Creating Menus
    Chapter 6: Writing Console Applications
    • 6.1 Overview of console functions
    • 6.2 Hello world example
      • Writing/Copying to/from offscreen pages
    • 6.3 Using PEEK and POKE
    • 6.4 Accepting user input
    • 6.5 Trapping extended keys
    • 6.6 Mixing CONSOLE with GUI
    • 6.7 Linux/Unix console
    Chapter 7: Introduction to streams
    • 7.1 File streams
      • Reading/Writing numbers and strings
    • 7.2 Memory streams
      • Copying between streams
    • 7.3 Saving/Loading UDTs and Arrays
    Chapter 8: Using Image Resources
    • 8.1 Supported Resources
    • 8.2 Introduction to Image lists
      • More on Rapid-Q's image cache
    • 8.3 Other kinds of Resources
    Chapter 9: SUBI, FUNCTIONI, and DLLs
    • 9.1 SUB/FUNCTIONs with variable parameters
    • 9.2 More on FUNCTIONI
    • 9.3 Introduction to DLLs
    • 9.4 How to call a DLL
    • 9.5 Using Quick View
    • 9.6 Writing your own DLLs
    • 9.7 Using unsupported types in DLL call
    • 9.8 API conversion table
    Chapter 10: Creating Custom Components
    • 10.1 Introduction to object creation
    • 10.2 Extending QCanvas
      • Adding new properties
      • Using Constructor
    • 10.3 Adding/Overriding Methods
    • 10.4 Defining Events
      • Inherting Events
    • 10.5 Adding components to components
    • 10.6 Extending empty components
    • 10.7 Public/Private properties and methods
    • 10.8 Templates and property sets
    • 10.9 Creating custom events
    • 10.10 QDiamondBox Source Code Listing
    Chapter 11: Using Function Pointers
    • 11.1 Introduction to the concept
    • 11.2 Defining function pointers
    • 11.3 Using function pointers properly
    • 11.4 What's not supported in Rapid-Q
    Chapter 12: Graphics under Windows
    • 12.1 Graphics under DOS versus Windows
    • 12.2 What components require painting
    • 12.3 Drawing graphics dynamically
      • Using QBITMAP as the off-screen page
    • 12.4 Ownerdraw List and Combo Boxes
      • Ownerdraw Variable vs. Fixed
    • 12.5 Using DirectX
    Chapter 13: Direct3D for Rapid-Q
    • 13.1 Requirement specifications
      • Required or suggested files
    • 13.2 Using Anim8or to create 3D models
    • 13.3 Loading/Using .X files
    • 13.4 Wrapping textures around an object
    • 13.5 Rotate/Moving objects
    Chapter 14: Programming in MySQL
    • 14.1 Quick introduction
      • Required files
    • 14.2 Connecting to MySQL
    • 14.3 How to perform queries and obtain result
    • 14.4 Interfacing QMYSQL with QSTRINGGRID
    • 14.5 Storing and retrieving blobs
    • 14.6 Using LOADBLOB and SAVEBLOB
    • 14.7 In conclusion
    Chapter 15: COM Programming
    • 15.1 Supported COM extensions
      • COM clients (automation controllers)
      • Active Documents
      • How to register COM objects
    • 15.2 About QOLEOBJECT
    • 15.3 About QOLECONTAINER
    Appendix A: Rapid-Q Component/Object Reference
    • APPLICATION (Windows/Linux)
      • Properties, Methods Application examples
    • CLIPBOARD
      • Properties, Methods ClipBoard examples
    • PRINTER
      • Properties, Methods Printer examples
    • QBITMAP
      • Properties, Methods QBitmap examples
    • QBUTTON (Windows/Linux)
      • Properties, Methods, Events, QButton examples
    • QCANVAS (Windows/Linux)
      • Properties, Methods, Events, QCanvas examples
    • QCHECKBOX (Windows/Linux)
      • Properties, Events, QCheckbox examples
    • QCOMBOBOX (Windows/Linux)
      • Properties, Methods, Events, QCombobox examples
    • QCOMPORT
      • Properties, Methods, Events, QComPort examples
    • QCOOLBTN (Windows/Linux)
      • Properties, Methods, Events, QCoolbtn examples
    • QDIRTREE
      • Properties, Methods, Events, QDirTree examples
    • QEDIT (Windows/Linux)
      • Properties, Events, QEdit examples
    • QFILELISTBOX
      • Properties, Methods, Events, QFileListBox examples
    • QFILESTREAM (Windows/Linux)
      • Properties, Methods, QFilestream examples
    • QFONT (Windows/Linux)
      • Properties, Methods, QFont examples
    • QFONTDIALOG
      • Properties, Methods, Events, QFontDialog examples
    • QFORM (Windows/Linux)
      • Properties, Methods, Events, QForm examples
    • QGAUGE
      • Properties, QGauge examples
    • QGLASSFRAME
      • Properties QGlassFrame examples
    • QGROUPBOX
      • Properties, Methods, Events, QGroupBox examples
    • QHEADER
      • Properties, Methods, Events, QHeader examples
    • QIMAGE
      • Properties, Methods, Events, QImage examples
    • QIMAGELIST
      • Properties, Methods, QImageList examples
    • QLABEL (Windows/Linux)
      • Properties, Events, QLabel examples
    • QLISTBOX (Windows/Linux)
      • Properties, Methods, Events, QListbox examples
    • QLISTVIEW
      • Properties, Methods, Events, QListView examples
    • QMAINMENU (Windows/Linux)
      • Properties, Methods, QMainMenu examples
    • QMEMORYSTREAM (Windows/Linux)
      • Properties, Methods, QMemorystream examples
    • QMENUITEM (Windows/Linux)
      • Properties, Methods, Events, QMenuItem examples
    • QMYSQL (Windows/Linux)
      • Properties, Methods, QMySQL examples
    • QOPENDIALOG (Windows/Linux)
      • Properties, Methods, QOpenDialog examples
    • QOLECONTAINER
      • Properties, Methods, QOleContainer examples
    • QOLEOBJECT
      • Properties, Methods, QOleObject examples
    • QOUTLINE
      • Properties, Methods, Events, QOutLine examples
    • QOVALBTN (Windows/Linux)
      • Properties, Methods, Events, QOvalbtn examples
    • QPANEL (Windows/Linux)
      • Properties, Events, QPanel examples
    • QPOPUPMENU
      • Properties, Methods, QPopupMenu examples
    • QRADIOBUTTON (Windows/Linux)
      • Properties, Events, QRadioButton examples
    • QRECT
    • QREGISTRY
      • Properties, Methods, QRegistry examples
    • QRICHEDIT (Windows/Linux)
      • Properties, Methods, Events, QRichedit examples
    • QSAVEDIALOG
      • Properties, Methods, QSaveDialog examples
    • QSCROLLBAR (Windows/Linux)
      • Properties, Events, QScrollBar examples
    • QSCROLLBOX
      • Properties, Methods, Events, QScrollBox examples
    • QSOCKET (Windows/Linux)
      • Properties, Methods, QSocket examples
    • QSPLITTER
      • Properties, Events, QSplitter examples
    • QSTATUSBAR
      • Properties, Methods, Events, QTrackBar examples
    • QSTRINGGRID
      • Properties, Methods, Events, QStringGrid examples
    • QSTRINGLIST (Windows/Linux)
      • Properties, Methods, QStringList examples
    • QTABCONTROL
      • Properties, Methods, Events, QTabControl examples
    • QTIMER (Windows/Linux)
      • Properties, Events, QTimer examples
    • QTRACKBAR
      • Properties, Methods, Events, QTrackBar examples
    • QTREEVIEW
      • Properties, Methods, Events, QTreeView examples
    Appendix B: Rapid-Q DirectX Component/Object Reference
    • QDXIMAGELIST
      • Properties, Methods, Events, QDXImageList examples
    • QDXSCREEN
      • Properties, Methods, Events, QDXScreen examples
    • QDXSOUND
      • Properties, Methods QDXSound examples
    • QDXTIMER
      • Properties, Methods, Events, QDXTimer examples
    Rapid-Q Direct3D Component/Object Reference
    This is a work in progress, some properties or methods may change in the future. All 3D operations are done in Retained mode.
    • QD3DFace
      • Properties, Methods, QD3DFace examples
    • QD3DFrame
      • Properties, Methods, QD3DFrame examples
    • QD3DLight
      • Methods, QD3DLight examples
    • QD3DMesh
      • Properties, Methods, QD3DMesh examples
    • QD3DMeshBuilder
      • Methods, QD3DMeshBuilder examples
    • QD3DTexture
      • Methods, QD3DTexture examples
    • QD3DVector
      • Properties, QD3DVector examples
    • QD3DVisual
      • Methods, QD3DVisual examples
    • QD3DWrap
      • Methods, QD3DWrap examples
    Appendix C: Rapid-Q Keywords & Statements
    • Valid Operators (In order of precedence)
      • Exponentiation (^)
      • Multiplication/Division and Shifts (*, /, \ (integer division), SHL, SHR)
      • Modulo arithmetic (MOD, INV)
      • Addition and subtraction (+, -)
      • Relation operations (=, >, <, <>, <=, >=)
      • Logical operations in order from high to low (NOT, AND, OR, XOR)
    • Rapid-Q internal definitions
      • WIN32, UNIX, TYPE
    • Rapid-Q supported Data Types
      • BYTE, WORD, INTEGER, VARIANT, etc...
    • Branching with GOTO and GOSUB
      • GOTO, GOSUB, RETURN
    • User defined types
      • TYPE versus STRUCT
    • Conditional statements
      • IF .. THEN .. ELSE, SELECT CASE
    • Loops
      • FOR .. NEXT, DO .. LOOP, WHILE .. WEND
    • Constructors/Methods
      • CONSTRUCTOR, CREATE, WITH
    • Procedures
      • SUB, FUNCTION, SUBI, FUNCTIONI
    • Internal Variables
      • Command$, CurDir$, MouseX, MouseY, etc...
    • Console keywords, Detailed list
      • CLS, COLOR, PRINT, INKEY$, etc...
    • Other reserved keywords, Detailed list
      • ABS, LEN, MID$, SWAP, etc...
    • Touble Shooting
      • How to Debug your programs


1: Rapid-Q FAQ

Rapid-Q Documentation by William Yu (c)1999-2000, Appended by John Kelly 		Introduction Chapter 1

1. Rapid-Q Overview /FAQ
(Frequently Asked Questions)

Rapid-Q is a BASIC -like programming language that is now abandoned by its creator William Yu. He sold the rights to RealBasic. (see Preface). However, it is still very functional and you can continue to use it. The compiler is multi-platform, although not completely compatible in terms of the graphical interface, but the underlying language is more or less compatible between platforms. Rapid-Q is available for Windows, Linux, and Unix (Solaris and HP-UX are supported). You can use Rapid-Q to create both GUI and CONSOLE applications, including CGI applications. Rapid-Q generates byte-code as opposed to the native opcode of your processor. This requires an interpreter to read and execute the byte-codes, however, this interpreter is embedded in all your applications, so no extra files are necessary when you distribute your executable. The biggest issue is speed, but depending on what you're using Rapid-Q for, this may not be a factor. Rapid-Q was originally created to provide a free implementation of a BASIC programming language for Windows.
1.0 Where do you get the latest RapidQ installer? Is it updated regularly?
You can download an installer for RapidQ (for Windows). It installs the compiler, the IDE, the fixed libraries, the fixed small libraries, the MySQL library, the helpfile (Rapidq.chm) and a riched32.dll (see "can't focus a disabled window" message below). It creates a program group and a desktop icon. It also associates *.bas files with the RQ IDE. An uninstaller is included:
http://www.mididesign.be/rapidq/rqinstall.exe or try these other sites:

Source code, documentation, and resources :
http://g.slyip.com (The largest collection of sample code but slow bandwidth)
 http://www.wildgardenseed.com/RQDP/
http://www.holyguard.net/public/rapidq/index.asp?projectid=19
http://home.planet.nl/~water793/

Discussion groups and collection of files to members
 http://groups.yahoo.com/group/rapid-q/files (members)
http://groups.yahoo.com/group/rapidq/files (members)
Don't expect updates, there is no guarantee of latest releases since RealBasic apparently will not longer support it. The RapidQ2 project is intended to improve the compiler by creating include files with added functionality.

1.0 If RapidQ is a Beta release does the program have a lot of bugs? Will they be fixed?
The bugs are not too bad and many can be avoided by alternative coding. The main reason for this new documentation is to inform programmers of possible bugs and alternative coding options. Obviously there is potential for a bug in your program that will not be fixed since support for the compiler is gone. Don't contact William Yu, or RealBasic about supporting the compiler! You can always look into other basics that have support like Real BASIC, FreeBasic, BCX, or Hot Basic (a rapidQ like language clone). Since there will be no upgrade to the compiler, the only way to improve the language is through coding and API calls. The RapidQ2.INC file was made as a way to start sharing standard code between programmers. It's not so bad, what compiler doesn't have a bug somewhere?

1.1 How slow is Rapid-Q anyway?
Although Rapid-Q is based on compiling your sources to byte-code, execution isn't as slow as many think. Byte-coded programs, which can be faster than some scripted programming languages. Obviously your programs will be slower than optimized C/C++ code and other compilers that build machine language code. however, it is not all that slow! You will notice slow speed for nested loops, heavy computations, or to perform very low level manipulation to data. For example, reading a single byte from a 1MB file will take longer in Rapid-Q than in most languages, but not so extremely slow. Same with looping I = I + 1 a few thousand times. But in terms of displaying graphics, controls and forms, it's just as fast as any other language. The problem with byte-code is going away with faster and faster computers. If you need real speed you can run a separate DLL written in another language (FreeBasic, BCX, HotBasic, C,but not ActiveX, COM or C++). There is also a way to add assembly language code to your program using RQASM..

1.2 What about bloat-ware?
At a minimum the Rapid-Q interpreter requires about 300KB (150KB for Linux, 600KB for Sparc). So this is the overhead that all your programs will have. Compared to some Windows programs, this isn't that bad, Most likely your bytecode is less than 50KB anyway (for a moderate/large application), plus any resources and graphics you may want to include of course.

1.3 Does Rapid-Q require extra runtime DLLs?
No. All your programs require no extra runtime DLLs or externalities. Just distribute your .EXE file and that's it. They should run on any Win95/98/NT system, assuming the end user hasn't done anything to his/her Windows System files. If you compare the bloat-ware of Rapid-Q and the runtime DLLs of other languages, Rapid-Q isn't that bad in terms of bloated size.

1.4 How much memory does Rapid-Q suck out of my programs?
It doesn't suck anything out of your programs (not literally), but it does suck memory out of Windows which in turn limit the amount of memory for your program(s). It really isn't as bad as one might think though. It eats up less than 200KB for virtual, global, and heap memory combined. This is because all variables and objects are created dynamically. The heap/stack memory is the one you should look out for. If your program is deeply nested or involves intense recursion, this can grow and shrink very rapidly. You don't need to worry about cleaning up your objects or variables when your program terminates. Rapid-Q will free all your objects and clean up the memory space for you.

1.5 How easy is it to hack into my programs?
Being a byte-code compiler, if the end user knows how everything is constructed, then it's just a formality. However, Rapid-Q generates a non-standard, or non-specific type byte-code output, which means, unless the user specifically knows what each operation does, it is very very difficult to hack your program. It's easy to hack into your string variables (like any other language), because these things aren't encrypted anyway. In most cases, your program should be safe from snoopers, they might not even know your program is byte-code generated! Unlike Java or other languages, Rapid-Q does not attach any symbol table or extra debugging information to your .EXE.

1.6 Do I need a license to distribute my programs?
No. You don't need a license to use Rapid-Q (it's free), and you definitely don't need any license to distribute or sell your programs. The only agreement you have to worry about is that if you choose to use Rapid-Q, you assume any and all consequences, direct or indirectly from the use of Rapid-Q. Rapid-Q can be used for any task, whether it's profit-seeking or otherwise. You don't pay me a cent, and you don't even have to acknowledge that your program was created with Rapid-Q (although this would be a nice gesture). You CANNOT, however, distribute Rapid-Q (the program itself) and charge for it. You're allowed to bundle Rapid-Q along with your program(s), so long as the user is well informed that it's not buying into Rapid-Q, but rather, buying into your program. How is that done? By not even advertising that your distribution includes a copy of Rapid-Q. Call it the hidden feature.

Q. Can you make a DLL with RapidQ? Can you link with .LIB files?
A. No, there is no support for making your own DLL, ActiveX, or COM programming interface. However, RapidQ can freely use DLLs written in another language if you can properly set up DECLARE SUB/FUNCTION statements. RapidQ cannot use DLL with COM interfaces. Also there is no ability for the compiler to do a run-time link with a library file (.LIB). Again FreeBasic, BCX, FSBL, HotBasic, and RealBasic are good alternatives here.

Q. What is the latest version of DirextX supported?
A. DirectX version 6.0 is the last version supported. DXsound is also version 6.0. The DirectX and Direct3D components are very functional but only represent a subset of all DirectX components, since they were not completed. Support for Direct 3D is through DirectX Retained Mode interface. It will continue to be provided by Microsoft but unfortunately is no longer being upgraded by Microsoft. There is no current support for DirectShow, DirectInput, and newer interfaces. It is possible to use wrapper DLLs (the DLL does the work for you).

Q. Can you use OpenGL for graphics and is it fast?
A. Yes, you can use OpenGL. There is a set of include files (http://g.slyip.com, or http://groups.yahoo.com/group/rapidq/files ) that allows you to interface to OpenGL (DLL libraries). There are not many examples at the time of this writting and limited texture file formats. The speed of OpenGL is mostly dependent on hardware acceleration, but you will notice that RapidQ will be slower than C++ code for 3D objects with 1000's of vertices. For small number of vertices, you may not notice any difference.

Q. My virus detection software (Norton) tells me RapidQ has a Trojan virus or some weird virus:
A. One is an old problem, that requires you to update your antivirus software. Also RapidQ compresses the executable with UPX. This makes for a smaller executable but the UPX file compressor might set off some virus dectection software. Unpack your program before running / distribution. Older Norton Antivirus definition files (Dec. 2004), detects the new rapidq3.lib (a Dr electron fixed library) as a "Hacktool." Norton tries to place the file(s) in quarantine. The library does not have a virus. Your options are :
1) Update Norton virus definition file or use the older rapidq3.lib.
2) Exclude the file or folder, and perform a scan. To exclude a file or folder, see:
http://service1.symantec.com/Support/nav.nsf/docid/199829164436
3) If Norton AntiVirus is set to its highest sensitivity, then put the virus settings back to their default (standard) level. This may be
important for AV alerts each time that a program writes to another file.
--Click Norton AntiVirus (NAV) 'options'
--Select Script blocking.
--Check the option "Ask me what to do (recommended)" under the title 'How to respond when a malicious script found'
See http://service1.symantec.com/support/nav.nsf/docid/2002041014332806

Q. I get a "Cannot focus a disabled or invisible window" error, how do I fix it?
A. The error doesn't cause any problems so just ignore it. The fix is to put the file "riched32.dll " (dated 3/2003) into the directory with RapidQ.EXE and RC.EXE. Obtain this file from rapidq source locations such as g.slyip.com (use the search box). The problem is a result of an newer richedit dll that comes with the newer versions of windows. The IDE must have a disabled or invisible window that it tries to focus when it first runs, but since earlier versions of the dll in question didn't catch it, it went unnoticed until the dll's were updated recently. Do not register this DLL! Just put it in the RapidQ directory.
Q. How to minimize an application to the task bar
A. Use QFormEx (found in rapidq2.inc) or these commands minimize an application to the task bar:
SetWindowLong(Form.Handle, GWL_HWNDPARENT, 0)
SetWindowLong(Application.Handle, GWL_HWNDPARENT, Form.Handle)
Form.WindowState = wsMinimized
Also the file http://groups.yahoo.com/group/rapidq/files/Scheduler.bas shows you how to manage a tray popup
menu.

Q. How do you to put a bitmap in the ClipBoard?
A. Draw to a QBitmapEx (found in rapidq2.inc) then use Bitmap.PasteToClipboard.
The width, height and PixelFormat of theQBitmapEx object affect how it looks.

Q. How do you find out if my application is already running, also called previous instance of your application.
A. Look on the web for the Previnst.Bas example:
1) One solution is use FindWindow like this previnst.bas example:
http://citymap.getmyip.com or http://g.slyip.com

Q. How can you create a custom event?
A. Yes, you can use an existing event like OnMouseMove, or make a custom event using Windows messages. See the source code for QFormEx to see custom events that hook the WndProc Callback function with Windows messages.

Here is an example by Pavel Minayev:
' A short example demonstrating custom events
' QCircle is a simple control that looks a circle, and it provides OnHitCircle event, which is called each time the
' user clicks inside of the circle. It also passes one argument which is the distance from the center of the circle to
' the point clicked.

$INCLUDE "rapidq.inc"
' This declaration is used as a template for event handlers
' for OnHitCircle event
DECLARE SUB HitCircleEvent(d AS SINGLE)
TYPE QCircle EXTENDS QCanvas
 ' Declare an event based on previously declared handler template
 OnHitCircle AS EVENT(HitCircleEvent)
 EVENT OnPaint
  WITH QCircle
   .Circle(0, 0, .Width, .Height, clWindowText, clBtnFace)
  END WITH
 END EVENT
 EVENT OnMouseDown(Button AS LONG, x AS LONG, y AS LONG, Shift AS LONG)
  WITH QCircle
   d = SQR((x - .Width / 2) ^ 2 + (y - .Height / 2) ^ 2)
   ' If cursor was inside of the circle, fire the event
   IF d <= .Width / 2 THEN CALLFUNC(.OnHitCircle, d)
  END WITH
 END EVENT
 CONSTRUCTOR
  Width = 100
  Height = 100
 END CONSTRUCTOR
END TYPE
' *************   Test code   *********
SUB Circle1_HitCircle(d AS SINGLE)
 SHOWMESSAGE "Distance from center: " + STR$(d)
END SUB
CREATE Form AS QForm
 Width = 300
 Height = 300
 CREATE Circle1 AS QCircle
  OnHitCircle = Circle1_HitCircle
 END CREATE
 Center
 ShowModal
END CREATE


2: Rapid-Q Fundamentals

Rapid-Q Documentation by William Yu (c)1999-2000 Chapter 2

2. Rapid-Q Fundamentals

Before jumping into any language, it helps to know how to use it first. This chapter will introduce you to the Rapid-Q environment, how to compile and run your programs, and what the general structure of your Rapid-Q program will look like.

2.1 Rapid-Q environment
Your Rapid-Q distribution should have included an IDE (integrated development environment) program (called RAPIDQ.EXE), along with the actual Rapid-Q compiler (RC.EXE). RAPIDQ32.LIB and RAPIDQCC.LIB are also required to compile any of your programs. If any of these files are missing, please report the problem to me or the webmaster of the site you downloaded Rapid-Q from. These are the main (4) programs that you will need to develop and compile your Rapid-Q source codes. The IDE is strictly optional, so if your distribution excludes this file, don't fret. If you feel more comfortable writing your programs in NotePad or whatever editor you choose, that's also fine. If that is the case, you probably want to skip the next section on Using the Rapid-Q IDE. All these files must reside in the same directory.

2.2 Using the Rapid-Q IDE
Unlike some IDEs that offer debugging options, the Rapid-Q IDE offers nothing more than an environment to write your programs, run them, and provide run-time command options. It has primitive error checks, I say primitive, because the IDE doesn't do the error checking at all, (RC.EXE) the compiler does all of it. It's just that the Rapid-Q IDE interfaces nicely with RC.EXE so you don't really notice that. It also provides syntax highlighting which makes using the Rapid-Q language much easier.
    What are its limitations:
  • Not all components are available in the form designer
  • When running your program, your source code is automatically saved
  • All files are compiled before they are executed
I can't speak for everybody, but the Rapid-Q IDE is a good tool to use when starting out to learn the Rapid-Q language, but as you become more accustomed to the language, most people would switch to their favourite text editor. That is not to say that you should abandon using the Rapid-Q IDE altogether, if you feel comfortable using it, by all means, stick with it.

2.3 Compiling and Running a Simple Application
Wait a minute, we haven't even covered the BASICs on writing a simple application yet. Don't worry, we'll get to that, it's better to know how to compile and run it first before doing anything else. Here is a very simple GUI application that you can type in and compile for yourself.
            DIM MainForm AS QFORM
            MainForm.ShowModal
If you're using the Rapid-Q IDE, just type in that code (or cut & paste if you like). Click on the Run Menu, and select Run. If all goes well, you should see an empty Window at the top left hand corner of the screen. Close it and return to your IDE. If you prefer the command line approach of compiling, then load up your favourite editor, copy the above code and save it to a file (Forms.BAS). Then to compile it, you type in:
          RC Forms.BAS
If all goes well, you should have a Forms.EXE file in the current directory. Just type Forms to run it. If all goes well, continue reading. If not, then something is amiss, in which case, see the Trouble Shooting section.

2.4 Command line switches for RC.EXE
I will only discuss the 3 more important ones:
      -I[Path] Change Include Path
      -L[Path] Change Library Path
      -G[File] Icon file
The compiler by default looks in the current directory for the .LIB files and any include files. You can override this by specifying the above command line switches. Since we're talking about C type parameters, there are a few niceties you have to know about, first, the paths should be specified like so:
      RC -Ic:/rapidq/includes
You can use \ instead of / but there's a reason why / is preferred, consider this:
      RC -I"c:\rapidq long dir\includes\"
If you never used C (or C++) you'll not likely see what I mean. If you prefer the above command line, you have to add an extra \ to the end (or drop it entirely), like so:
      RC -I"c:\rapidq long dir\includes\\"
or
      RC -I"c:\rapidq long dir\includes"
This is because C translates \" into " which is obvious to any C programmer. Also, long file names must be enclosed in quotations. Those are the catches, so now you know (or already knew).
Now, to change the default icon for your .EXE file, you can use the -G command switch:
      RC -Gzip.ico zipview.bas
When your ZIPVIEW.EXE file is generated, the file "zip.ico" will replace the default icon. Please note that your icon must be 32x32 and 16 colors (also 766 bytes).

2.5 General Structure of a Rapid-Q Program
There really is no pre-defined structure of a BASIC program, but there is a general form that most people conform to.
    Directives
    Declarations
    Global Variables
    Main Program
This is only a general form, your Rapid-Q applications can be structured in a variety of ways. Some of which will have similar results, and some will have devasting or more customized results. For example, $INCLUDE is a directive to import a file at that position. So if you use $INCLUDE somewhere in your main program, it would have a different result than if you included it at the beginning of your program.

2.6 How close to the BASIC Language is Rapid-Q?
Very close, all the familiar commands like DIM, PRINT, MID$, etc. are inherited. That does not mean you'll be able to port your DOS based QBasic programs to Rapid-Q without any modification. Since Rapid-Q is Windows based, providing primitive support for CONSOLE, it's a safe bet you won't directly convert your QBasic applications to Rapid-Q without a 50-90% rewrite of your source code (depending on what the code does). Comments in Rapid-Q begin with the ' symbol, just like QBasic, or you can use REM instead. You can also separate lines by using the colon : symbol. This has the same effect as starting a new line.
             PRINT "Hello" : PRINT "World"
         or
             PRINT "Hello"
             PRINT "World"
Most BASIC programmers will become very accustomed to the language once they use it. However, Rapid-Q does not inherit the properties of Visual Basic. For example, there's no SUB MAIN procedure, nor is there any public or private identifiers used in Rapid-Q. Your entire program is considered the MAIN program. Going from Rapid-Q to Visual Basic probably requires a bit more effort than the reverse.


3: Rapid-Q Language Guide

Rapid-Q Documentation by William Yu (c)1999-2000 Chapter 3

3. Rapid-Q Language Guide

In this chapter, I'll go through the language of BASIC, specifically Rapid-Q. Since Rapid-Q is derived from the BASIC language, most experienced BASIC programmers can skim this section if you so choose. There's a few new concepts that is not part of the BASIC language like infinite parameter passing and using the '-' operator on strings.

3.1 Rapid-Q Directives
Directives are used in Rapid-Q to tell the compiler how, and what kind of code is to be generated. Rapid-Q supports the following directives, which are usually included at the beginning of your programs.

 $APPTYPE

[ CGI | CONSOLE | GUI ] Default is GUI
$APPTYPE is used to tell the compiler what kind of application you want generated. Although the default is GUI, if no $APPTYPE directive is used, Rapid-Q will detect what kind of application your program is just by looking at the source code. To override this feature, include the $APPTYPE directive at the beginning of your source code.
Usage: $APPTYPE CONSOLE

$TYPECHECK

[ OFF | ON ] Default is OFF
$TYPECHECK is used to tell the compiler whether you want the source code parsed using strict type checking ON (all variables must be declared), or relaxed type checking OFF like traditional BASIC where you don't need to declare your variables. Note, you can turn ON or OFF type checking at anytime, so you can type check a portion of your code and turn it OFF afterwards.
Usage: $TYPECHECK ON

 $INCLUDE

[ FileName ]
Using $INCLUDE has the same effect as importing your file directly into your program at the point of call. You can use $INCLUDE anywhere in your program, except in a SUB or FUNCTION, but is most often included at the beginning of your source code. Enclosing the filename between quotes will search for that file in the current directory, and specified include paths. Enclosing the filename between < and > will search for that file in the current directory, specified include paths and the environment search paths.
Usage:
    $INCLUDE "RAPIDQ.INC"
    $INCLUDE <RAPIDQ.INC>

$RESOURCE

Handle AS FileName
Most Windows programming languages include support for Resource files. In Rapid-Q, this is somewhat different. In Rapid-Q, Resource files are just a collection of graphics files. There is no such thing as resource strings in Rapid-Q. Anyway, what's great about Resource files is that they are embedded into your applications. So if you're using 10 different bitmaps, you don't need to include them in your .ZIP distribution because it's already embedded into the .EXE. Enclosing the filename between quotes will search for that file in the current directory, and specified include paths. Enclosing the filename between < and > will search for that file in the current directory, specified include paths and the environment search paths.
Usage:
    $RESOURCE RES_BMP1 AS "CLOUDS.BMP"
    $RESOURCE RES_BMP1 AS <CLOUDS.BMP>

$DEFINE

NewDefinition [OldDefinition]
When you feel like redefining or creating new keywords/tokens, use this directive. However, be CAREFUL this directive can have bugs You cannot construct a series of tokens to be redefined. You cannot redefine operators or punctuations. $DEFINE cannot be used to define a function (like in C). The OldDefinition parameter is optional, so you can do this just fine: $DEFINE NEWDEF
Usage: $DEFINE INT16 SHORT

 $UNDEF

DefName [, DefName]
To undefine a previous call of define, use $UNDEF. You can specify multiple instances on the same line, separated with commas.
Usage: $UNDEF INT16, INT32

 $IFDEF

Definition
This directive is used to specify whether a piece of code should or should not be compiled. It is used in conjunction with $DEFINE. If the Definition has been defined, the code within the $IFDEF...($ELSE)...$ENDIF statement will be compiled, otherwise it is skipped entirely.
Usage:
    $IFDEF INT16
    ' if INT16 has been defined
    ' compile this portion
    $ELSE
    ' if INT16 has not been defined
    ' compile this portion
    $ENDIF

 $IFNDEF

Definition
$IFNDEF has the opposite effect as $IFDEF.
Usage:
    $IFNDEF INT16
    ' if INT16 has not been defined
    ' compile this portion
    $ELSE
    ' if INT16 has been defined
    ' compile this portion
    $ENDIF

 You can use this to avoid compiling the whole RapidQ.inc include file:
$IFNDEF __RQINC
  do rapidq commands that are also part of RapidQ.inc
$ENDIF

If you have RapidQ2.inc you can turn off all new coding and just use the old RapidQ.inc file by using this:
$DEFINE __RQINC2
$INCLUDE "RapidQ2.inc"      'now the program functions just like the old .inc file

 $OPTION

OptionName [Parameters]
BYREF, BYTECODE, DECIMAL, DIM, EXPLICIT, GTK, ICON, INKEY$, and WEAKTYPE are valid OptionNames.
Usage:
    $OPTION BYREF
    This changes the way variables are
    passed. By default, Rapid-Q passes variables
    by value. This option reverses that.
    Use with caution.

    $OPTION BYTECODE
    Compile as byte code only.

    $OPTION DECIMAL ","
    $OPTION DECIMAL 64
    This changes the default decimal
    character for use in VAL.
    The default decimal character is the period.

    $OPTION DIM BYTE
    $OPTION DIM WORD
    $OPTION DIM DWORD
    $OPTION DIM SHORT
    $OPTION DIM INTEGER
    $OPTION DIM LONG
    $OPTION DIM SINGLE
    $OPTION DIM DOUBLE
    $OPTION DIM STRING
    $OPTION DIM VARIANT
    This changes the default type
    for an undeclared variable.
    By default, all undeclared variables are
    assumed to be of type DOUBLE
    if no suffix is provided.

    $OPTION EXPLICIT
    Same as using TYPECHECK ON
    Maintained for compatibility with VB

    $OPTION GTK
    Uses GTK instead of XFORMS
    Make sure you have the proper files

    $OPTION ICON "path\file.ico"
    This changes the default icon
    of your executable file.

    $OPTION INKEY$ DEFAULT
    $OPTION INKEY$ TRAPALL
    This allows INKEY$ to accept/reject
    certain extended characters.
    TRAPALL will trap Shift/Ctrl/Alt/Menu
    as well as Caps/Num/Scroll lock.

    $OPTION VBDLL ON
    $OPTION VBDLL OFF
    This determines how DLLs are handled.
    If VBDLL is enabled (ON), your DLL
    declarations in Rapid-Q will mimic VB's
    such that your code can be used the
    same way in both languages.
    This option is OFF by default.

    $OPTION WEAKTYPE ON
    $OPTION WEAKTYPE OFF
    WeakType is disabled (OFF) by default
    WeakType allows for faster parsing
    and may help in porting some VB code.
    It should not generally be used,
    unless you know the code is okay.

 $OPTIMIZE

[ OFF | ON ] Default is OFF
$OPTIMIZE can be used to reduce the byte code size by eliminating unnecessary instructions. If you use this option, make sure it's one of the first things you call.
Usage: $OPTIMIZE ON

 $ESCAPECHARS

[ OFF | ON ] Default is OFF
If $ESCAPECHARS is turned ON, you can use escape sequences in your strings. Escape sequences can either be character or numeric escapes. Note that case is sensitive.
Usage: $ESCAPECHARS ON
Escape sequence
Details

  \a        Alarm bell
  \b        Backspace
  \f        Form feed
  \n        New line
  \r        Carriage return
  \t        Horizontal Tab
  \v        Vertical Tab
  \\        Backslash
  \"        Double quote
  \###      ### is any number 0..255
  \xHH      HH is a hexidecimal value 00..FF

Examples:
    PRINT "\""
    Output is "

    PRINT "\x41"
    Output is A

    PRINT "\t\65\66\67\t\68\69\70
    Output is ABC       DEF

    PRINT "Hey\r\n";
    Output is Hey with newline

$MACRO
(This command is VERY buggy and has limited functionality! Likely will cause strange compiler errors or crash.
MacroName[(Parameters, ...)] MacroDefinition
A Macro simply replaces a definition with another. It can be treated like a function if you supply parameters. Rapid-Q allows Macros to be embedded within another Macro (foward only to avoid recursion), token pasting using ##, and even macro overloading. You can also redefine operators and special characters except quotes. A definition can extend to multiple lines by using the colon as a line separator. A $MACRO directive is global if it preceeds any $INCLUDE directives. ie. the included files have access to those Macro definitions. A $MACRO directive only affects the module level (ie. the current file) if used in an $INCLUDE file. So if A depends on B and B has some $MACRO directives, then those $MACRO directives only affect B and A has no access to them unless redeclared in module A.
Notes:
If you use the $MACRO directive, you are forcing Rapid-Q to preprocess your code, which will prolong the compilation process. Rapid-Q normally performs a single-pass compilation process.
Usage:
    $MACRO ~ ,
    This redefines the comma character
    Try: ? STRING$(10 ~ "A")

    $MACRO strcat(a,b) a=a+b
    Implements a STRCAT function
    strcat(a$,"abc") translates to a$=a$+"abc"

 This won't work --> strcat(a1,b) a1=a1+b

    $MACRO VARID(x) V##x
    An example of token pasting
    DEFINT VARID(1) translates to DEFINT V1

    $MACRO TWO_PI (2*PI)
    $MACRO PI 3.14159
    Embedded Macros (forward only).
    Can't embed itself as a parameter.
    This avoids rescanning & recursion.

    $MACRO ADD(a,b,c,d) ADD(a,b)+ADD(c,d)
    $MACRO ADD(x,y) x+y
    $MACRO ADD(x,y,z) x+y+z
    An example of macro overloading

$Macro examples:
'Char presentation of number

Macro as pseudo SUB
DIM M AS
QMemoryStream

$Macro Digit2Char(D,a) _
M.Write(D):za=sizeOf(D):
_
M.Position=0:a=M.ReadBinStr(za) : M.Close

dim LPod as
double
lpod=33.234
Digit2Char(lpod,sss$)
print "Char LPod=",sss$:

dim tst as
integer
tst=33.234
Digit2Char(tst,zz$)
print "Char tst=",zz$:

 3.2 Variables and Assignments

Variables are stored in main memory, and stay there for the entire duration of your program. In Rapid-Q, type checking is very relaxed. Which means you can assign a string to an integer variable. The result is undefined, but will most likely return 0. Same goes with assigning a number to a string variable, the result is an empty string. Type checking is really done at the interpreter level in Rapid-Q, but since you don't want error messages popping up everywhere, I have disabled the check entirely. What this ultimately means is that you should be very very careful in assigning values to your variables, since you won't get any warnings from Rapid-Q. The only strict type checking done is for QObjects. You cannot assign a number or string to a variable expecting an Object for its value. Some examples of valid assignments:
         A% = "Hello"  "World"

         A$ = "Hi World!"

         A# = 34 + 34 - 324 * 3 / (34 / 5 + 5)

If you've never programmed in BASIC before, you're probably wondering what all those symbols after the A mean. Well, since most implementations of BASIC does not restrict you to define your variables before you use them, you can define them by using these symbols:
         ?, ??, ???, %, &, !, #, $
They represent BYTE (?), WORD (??), DWORD (???), SHORT (%), LONG (&) or INTEGER, SINGLE (!), DOUBLE (#), and STRING ($), respectively. Of course, if you didn't put any symbol in front of your undeclared variable, it's automatically assumed that the variable is a DOUBLE. That is the implementation used in Rapid-Q, for other languagues, the default maybe SINGLE, LONG, or what have you. Here's a table for your viewing pleasure:
    Type       ID  Size  Range
    --------- ---- ---- -------------
    Byte        ?   1   0..255
    Word       ??   2   0..65535
    Dword     ???   4   Only Linux version for now...
    Short       %   2   -32768..32767
    Integer     &   4   -2147483648..2147483647
    Long        &   4   -2147483648..2147483647
    Single      !   4   1.5 x 1045..3.4 x 1038
    Double      #   8   5.0 x 10324..1.7 x 10308
If you didn't like the way that was done, you could also use DIM to declare your variables, like so:
            DIM Number AS INTEGER
            DIM S AS STRING
            DIM B AS BYTE
Well, you get the idea. If you turned $TYPECHECK ON, then you will be forced to declare your variables like that. It's a nice habit to pick up, especially if you wanted to switch to languages like C or Pascal. You will be forced to declare all your variables before you use them. Here's something that's valid in Rapid-Q, but can confuse the daylights out of people:
            DIM Num$ AS INTEGER
    Yes, try to avoid obfuscated code like that.

(evilone_666k )
A little syntactic sugar thrown in. Previously, if you were to declare 3 variables of type INTEGER, you had to write:

DIM a AS INTEGER, b AS INTEGER, c AS INTEGER

The following is NOT correct:
 DIM a, b, c AS INTEGER

In this case, a and b will be VARIANTs, and only c is INTEGER. Previously, there was no workaround. However, you can group variables together using braces:
DIM (a, b, c) AS INTEGER

Here, all three variables are of type INTEGER - rather convenient. There is a disadvantage though: you cannot initialize variables declared in such a manner:
DIM (a = 1, b = 2) AS INTEGER ' error!

This is correctly written as:
DIM a AS INTEGER = 1, b AS INTEGER = 2

Also, you cannot have one of the variables be an array, while others aren't:
DIM (a, b(5), c) AS INTEGER ' incorrect!
DIM (a, b, c)(5) AS INTEGER ' correct: a, b and c are arrays

3.3 Rapid-Q Components/Objects

Rapid-Q offers reuseable components (or objects) which assists the programmer in developing Windows applications. Most RAD (Rapid Application Development) Programming languages offer this. For Visual C++, it's MFC, and for Java, it's JFC Swing. So what are visual components? They're basically just wrapper code that implement all the features of the Windows API control (or under Linux, whatever GUI API you're using) without all the headaches involved in using the API directly. For example, you can create windows using pure Windows API calls only, but this can run down for pages. In Rapid-Q, all this has been wrapped up into a component called QFORM. So instead of having to first register your class window, then display it and handle all the callbacks, all you do in Rapid-Q is:
             DIM Form AS QFORM
             Form.ShowModal
Comparing this to a C/C++ program, it's much cleaner, and easier to understand. There are a lot of supported components in Rapid-Q, like QBUTTON, QIMAGE, QFILESTREAM, etc. There are also some which aren't supported, that's the restriction involved in using Rapid-Q. Components are created exactly the same way you create variables, by using DIM. Each component has its own properties, methods and events. Properties are like the component's attributes. For example, Left, Top, Width, and Height are properties common to all visible controls, which define its placement within the form or Window. Caption is a property of type STRING. For a QFORM component, the Caption property defines the title of that form. Caption for a QBUTTON defines the text of that button. Caption for something like QFILESTREAM does not exist, since a QFILESTREAM isn't a visible component. It has its own properties. For a complete guide of the properties, methods and events for all components, please check the Appendix section. Here's a quick example of how you can assign properties to your components:
                 DIM Form AS QFORM
                 Form.Caption = "My Application"
                 Form.Left = 100
                 Form.Top = 100
Be careful to know which properties are Read-Only, and which ones are Write-Only. An example of a read-only property is the ITEMCOUNT property of a QLISTBOX. An example if a write-only property is the ICON property of a QFORM, used to specify the location of an icon to use as the default. Reading the Write-Only values, or Writing to Read-Only values have no defined meaning, and may result in a compile error or more seriously, your program crashing.

3.4 Component Methods & Events
Well, we've covered only the properties so far, but methods aren't much different. What exactly is a method you ask? It's really just a SUBROUTINE or FUNCTION. It's called a method, because the SUBROUTINE or FUNCTION only refers to that component. This is harder to explain than to understand. Here's an example of a method:
              DIM Form AS QFORM
              Form.Center
              Form.ShowModal
We used 2 methods here, Center, and ShowModal. The Center method is a SUBROUTINE that accepts no parameters. What it does is center the form on your desktop. ShowModal is actually a FUNCTION, but we ignore the return value in this case. It's a method used to Display your form, and wait for the user to close it. Note: Unlike some BASIC implementations, a FUNCTION can be called like a SUBROUTINE in Rapid-Q, you just ignore the return value. This is similar to C/C++. Other methods that you see may require some extra parameters, and some even accept an infinite number of parameters. You can also write these in Rapid-Q yourself, but I'll cover that topic later. So basically, methods are functions which perform a specific task on that component. In our above example, we're centering the form, and then displaying it.
All right, now what about events? Well, this can be a confusing subject if we were talking in terms of message passing and callbacks. Well, luckily, we can take a much higher level look at it. An Event occurs whenever something happens. This is very vague, something happening could be anything from time elasping, user clicking the mouse, user pressing a key, etc. Rapid-Q can't trap all these events, but the most important ones are. For example, if a user clicked on a button, you'd want to write some code to perform that task. We have to define a CALLBACK function to handle it. For each event which occurred, you want to direct that event to a subroutine you wrote to handle the event. Here's how:
       SUB ButtonClicked
          PRINT "Button was clicked"
       END SUB

       DIM Button AS QBUTTON
       DIM Form AS QFORM

       Button.Parent = Form                 ' Property
       Button.OnClick = ButtonClicked       ' Event
       Form.ShowModal                       ' Method
Seems easy enough right? It really is. Whenever an "OnClick" message/event occurs, the program jumps into your subroutine ButtonClicked and executes the code you have waiting in there. The above program is complete, so you can try it out yourself. For a list of all events that a particular component can receive, just look at the Appendix section.

3.5 Rapid-Q Subroutines & Functions
There are some GOTCHAS associated with Rapid-Q SUBs and FUNCTIONs. The first, and most important, is that all values passed are passed by VALUE (except for objects, variants, udts, and arrays). To pass a variable by reference, you need to prepend an @ symbol. The second catch is that only a maximum of 10 parameters can be accepted (except when calling an API function, then it's limited to 25). There's no difference in the way you create SUBs or FUNCTIONs in Rapid-Q (as compared to other BASIC languages like QBasic/PB):
    FUNCTION FindMax (X AS INTEGER, Y AS INTEGER) AS INTEGER
      IF X > Y THEN
        FindMax = X      '' Return value is X
      ELSE
        FindMax = Y      '' Return value is Y
      END IF
    END FUNCTION
The above code is valid, as is the following:
    FUNCTION FindMax (X%, Y%) AS INTEGER
      IF X% > Y% THEN
        FindMax = X%      '' Return value is X
      ELSE
        FindMax = Y%      '' Return value is Y
      END IF
    END FUNCTION
However, as you may notice, you can't have FindMax% without attaching an AS INTEGER to the end of the function.
 To pass a variable by reference, attach an @ symbol in front of your variable:
    SUB StrCat (Source AS STRING, Text AS STRING)
        Source = Source + Text
    END SUB

    A$ = "Hello"
    StrCat(@A$, " World!")
    PRINT A$                '-- Should print: Hello World!
Or if you prefer, you can also attach a BYREF keyword in your parameter list like so:
    SUB StrCat (BYREF Source AS STRING, Text AS STRING)
        Source = Source + Text
    END SUB

    A$ = "Hello"
    StrCat(A$, " World!")
    PRINT A$                '-- Should print: Hello World!
Yet another approach you can use instead (note that this is the "old" way, maintained for compatibility reasons):
    SUB Strcat (A$, B$)
       A$ = A$ + B$
    END SUB

    A$ = "Hello"
    Strcat(A$, " world!")
    A$ = STACK.STR(0)
    PRINT A$
The stack contains an array of integers and strings, to access the correct parameter, you have to specify the number (from left to right). The first element being 0. You can also pass QObjects, but you can't use it as a return value.
    SUB (Button AS QButton)
        Button.Left = 100
    END SUB
All components/QObjects are passed by reference.

3.6 Rules of Scope
Rapid-Q is not like BASIC in this case. Since Rapid-Q is a simple top-down one-pass compiler, the scope is very similar to that of Pascal.
Here's what I mean:

       SUB Test
          DIM I AS INTEGER
          I = 100
          PRINT I
       END SUB

       DIM I AS INTEGER
       I = 10

       SUB Test2
         PRINT I
       END SUB

       Test    '' Call Subroutine
       Test2
Here's how the scope works, for the SUB Test, the LOCAL variable I only extends down as far as the end of that SUB block. The variable I in the main program extends down all the way to the end of your program. That means SUB Test2 can use the global variable I because it's within its scope. You can also redeclare the variable I in SUB Test2, in which case the local I is used instead of the global I. Here's another situation to demonstrate the scope of variable names:
       DIM I AS INTEGER

       SUB Scope (I AS INTEGER)
         DIM I AS INTEGER
         PRINT I
       END SUB

       PRINT I
In fact, the line DIM I AS INTEGER is a wasted statement, since the variable I is shadowed by the parameter name I. Rapid-Q will warn you about this, but won't error out.


4: Writing your first Rapid-Q Application

Rapid-Q Documentation by William Yu (c)1999 Chapter 4

4. Writing your first Rapid-Q Application

Let's jump right into writing Windows applications in Rapid-Q! There will be a simple step-by-step guide, along with the complete source code listing at the end of this chapter.

4.1 Deciding on what to write
We're not going to write a simple "Hello World!" demo, nor are we going to write a web browser, we'll start with something meaningful, yet simple to write. Let's write a simple form based database type program. Some of the concepts we'll learn is form handling, event handling, and using the components, QEDIT, QBUTTON, QFORM, QLABEL, and QLISTBOX. Here's what our finished application should look like, you can modify the interface to your liking (if you're comfortable you know what you're doing).

It may look like a lot, but honestly, the source code is less than 100 lines! Most of the time spent is used designing the layout.

4.2 Designing the form
You can almost see the components that we'll need. One QFORM, 2 QBUTTONs, 4 QEDITs, 4 QLABELs, and finally 1 QLISTBOX. First of all, we need a Window (that's our QFORM). So let's type that in:
           DIM MainForm AS QFORM

           MainForm.Center
           MainForm.Caption = "My First Application"
           MainForm.Height = 340
           MainForm.Width = 350
           MainForm.ShowModal    '-- Display form
If you entered all this correctly, you should see an empty Window, with the same geometry as the above diagram. One thing to notice is that we're not using MainForm.Left or MainForm.Top because when the MainForm is centered, it is automatically calculated for us. All we really need is to supply the width and height of our Window.
All right, now that we have our Window, we'll have to add controls to it. You should place the following code BEFORE the line MainForm.ShowModal. For the sake of argument, let's begin by adding some labels to our Window.
       DIM NameLabel AS QLABEL, AddrLabel AS QLABEL
       DIM CityLabel AS QLABEL, PhLabel AS QLABEL

           NameLabel.Parent = MainForm
           NameLabel.Caption = "Name:"
           NameLabel.Top = 13
           NameLabel.Left = 25
           AddrLabel.Parent = MainForm
           AddrLabel.Caption = "Address:"
           AddrLabel.Top = 38
           AddrLabel.Left = 25
           CityLabel.Parent = MainForm
           CityLabel.Caption = "City:"
           CityLabel.Top = 63
           CityLabel.Left = 25
           PhLabel.Parent = MainForm
           PhLabel.Caption = "Phone #:"
           PhLabel.Top = 88
           PhLabel.Left = 25
We're creating 4 label components, and we're going to use MainForm as our container for these components, hence the Parent = MainForm association. If for example, we created a QPANEL on our form, it can also act as a container for any of our controls. But we won't get into that until later. For the moment, take some time to digest the above code and add it to our previous listing.
We now have our Window, our 4 labels, now let's add the 4 edit controls to our application.
       DIM NameEdit AS QEDIT, AddrEdit AS QEDIT
       DIM CityEdit AS QEDIT, PhEdit AS QEDIT

           NameEdit.Parent = MainForm
           NameEdit.Left = 70
           NameEdit.Top = 10
           NameEdit.Width = 230
           AddrEdit.Parent = MainForm
           AddrEdit.Left = NameEdit.Left
           AddrEdit.Width = NameEdit.Width
           AddrEdit.Top = 35
           CityEdit.Parent = MainForm
           CityEdit.Left = NameEdit.Left
           CityEdit.Width = NameEdit.Width
           CityEdit.Top = 60
           PhEdit.Parent = MainForm
           PhEdit.Left = NameEdit.Left
           PhEdit.Width = NameEdit.Width
           PhEdit.Top = 85
Looks familar doesn't it? It's the same idea as our QLABELs, the biggest thing is correct placement on the form. In the above example, we're aligning all the QEDIT controls just after the QLABELs. Again, take some time to digest the above code and add it to our existing code.
All that's left is to add our 2 buttons and one listbox control. Here's how we do that:
       DIM AddButton AS QBUTTON, ClearButton AS QBUTTON
       DIM ListBox AS QLISTBOX

           AddButton.Parent = MainForm
           AddButton.Left = 70
           AddButton.Top = 115
           AddButton.Width = 110
           AddButton.Caption = "&Add to Database"
           ClearButton.Parent = MainForm
           ClearButton.Left = 190
           ClearButton.Top = 115
           ClearButton.Width = 110
           ClearButton.Caption = "&Clear Database"

           ListBox.Parent = MainForm
           ListBox.Top = 150
           ListBox.Left = 70
           ListBox.Width = 230
           ListBox.Height = 150
Cut & Paste, and voila! Wow, we now have a form which looks exactly like the diagram above (section 4.1). Run it, fool around with it for a while, then return back, there's still two more things to implement.

 4.3 Handling Events
As you can see, the above code just flashes us with a nice user interface, but nothing to back it up with. If you tried clicking on the buttons, they do nothing. You'll have to write your event handler to handle a button click. Here's how:
           AddButton.OnClick = AddButtonClick
That it? Well, that's part of it, the OnClick event handler will transfer execution to the subroutine we named AddButtonClick. Now we'll have to go and write our subroutine. Just make sure you include the subroutine below, before adding the above code.
           SUB AddButtonClick
               IF ListBox.ItemCount > 0 THEN
                  '-- Add a nice separator
                  ListBox.AddItems "--------------------------"
               END IF
               ListBox.AddItems NameEdit.Text, AddrEdit.Text, _
                                CityEdit.Text, PhEdit.Text
           END SUB
Well, now we're getting somewhere. Whenever the user clicks on the add button, the code above gets executed. As you can see, all it does is add the text fields to our listbox. If you didn't already know, the underscore '_' character can be used in Rapid-Q to split up long lines. We're almost done, now we'll add an event handler for the other button.
           SUB ClearButtonClick
               ListBox.Clear
           END SUB

           ClearButton.OnClick = ClearButtonClick
Whew, if you counted all the lines, it is well below 100! Our application is now complete, you can play with it, add stuff to it, and generally learn from it.

4.4 Source code listing, in its entirety
DIM MainForm AS QFORM
DIM NameEdit AS QEDIT, AddrEdit AS QEDIT, _
    CityEdit AS QEDIT, PhEdit AS QEDIT
DIM NameLabel AS QLABEL, AddrLabel AS QLABEL, _
    CityLabel AS QLABEL, PhLabel AS QLABEL
DIM ListBox AS QLISTBOX
DIM AddButton AS QBUTTON, ClearButton AS QBUTTON

SUB AddButtonClick
  IF ListBox.ItemCount > 0 THEN
    '-- Add a nice separator
    ListBox.AddItems "--------------------------------"
  END IF
  ListBox.AddItems NameEdit.Text, AddrEdit.Text, _
                   CityEdit.Text, PhEdit.Text
END SUB

SUB ClearButtonClick
  ListBox.Clear
END SUB

NameLabel.Parent = MainForm
NameLabel.Caption = "Name:"
NameLabel.Top = 13
NameLabel.Left = 25
AddrLabel.Parent = MainForm
AddrLabel.Caption = "Address:"
AddrLabel.Top = 38
AddrLabel.Left = 25
CityLabel.Parent = MainForm
CityLabel.Caption = "City:"
CityLabel.Top = 63
CityLabel.Left = 25
PhLabel.Parent = MainForm
PhLabel.Caption = "Phone #:"
PhLabel.Top = 88
PhLabel.Left = 25

NameEdit.Parent = MainForm
NameEdit.Left = 70
NameEdit.Top = 10
NameEdit.Width = 230
AddrEdit.Parent = MainForm
AddrEdit.Left = NameEdit.Left
AddrEdit.Width = NameEdit.Width
AddrEdit.Top = 35
CityEdit.Parent = MainForm
CityEdit.Left = NameEdit.Left
CityEdit.Width = NameEdit.Width
CityEdit.Top = 60
PhEdit.Parent = MainForm
PhEdit.Left = NameEdit.Left
PhEdit.Width = NameEdit.Width
PhEdit.Top = 85

AddButton.Parent = MainForm
AddButton.Left = 70
AddButton.Top = 115
AddButton.Width = 110
AddButton.Caption = "&Add to Database"
AddButton.OnClick = AddButtonClick
ClearButton.Parent = MainForm
ClearButton.Left = 190
ClearButton.Top = 115
ClearButton.Width = 110
ClearButton.Caption = "&Clear Database"
ClearButton.OnClick = ClearButtonClick

ListBox.Parent = MainForm
ListBox.Top = 150
ListBox.Left = 70
ListBox.Width = 230
ListBox.Height = 150

MainForm.Center
MainForm.Caption = "My First Application"
MainForm.Height = 340
MainForm.Width = 350
MainForm.ShowModal


5: Introduction to forms

Rapid-Q Documentation by William Yu (c)1999-2000 Chapter 5

5. Introduction to forms

The basic concepts of forms are introduced in this chapter. The example program in the previous chapter will definitely help you understand the concepts a little better. I will use the terms form and windows interchangeably.

5.1 What's in a form?
A form (or window), is a generic container that can be displayed on your desktop. It is like a panel (see QPANEL). A form can have many appearences. In Rapid-Q, the only forms which are valid, are (you can also define custom shapes for your forms, using the method SHAPEFORM):
The default form is bsSizeable. What exactly is bsNone good for? Games :-) That's right, if the form is maximized, you can utilize the whole screen for your game. It can serve other purposes as well... MSIE uses it for a full screen web browser. Looks ugly though. If you're not sure how all these variables come from, take a look at RAPIDQ.INC bsNone = 0, bsSingle = 1, etc... these variables just make programming easier, so you don't need to remember the exact number, just the variable name to use.
          $INCLUDE "RAPIDQ.INC"

          DIM Form AS QFORM
          Form.BorderStyle = bsDialog
          Form.ShowModal
For bsSingle, the form looks exactly like bsSizeable, except that you cannot resize the form. In many cases, the only two useful forms are bsSizeable, and bsDialog.

5.2 Adding components to a form
If you followed closely the example in the previous chapter, you can add components onto the form simply by assigning the Parent property for that component.
        DIM Form AS QForm
        DIM Button AS QButton

        Button.Parent = Form       '' Add button to form
If you're wondering why that is, just consider a program with multiple forms. All visible components must have a Parent property. Components, such as QMENUITEM, or QTIMER do not have a parent property. Even though QMENUITEM is considered a "visible" component, its parent can only be a QMAINMENU or QPOPUPMENU. But instead of assigning a Parent property, you have to Add/Insert the items to the menu. If no Parent is given, the component remains hidden. In the case of QCANVAS or QIMAGE, you will get error messages if you try to draw on the components. This is because you can't draw on something not visible. In most cases, the Parent property should be the first property you assign before doing anything else. To hide components, you can use the Visible property.

5.3 Tracking the mouse position on a form
You can use MouseX and MouseY to track the position of the mouse on a form, but these 2 methods are being faded out. It is better just to handle the OnMouseMove event which pass the X and Y coordinates of the mouse position relative to the component.

5.4 Special events for forms
There are a few special events that only forms can handle. The most important is the OnResize event. This occurs whenever the user has clicked on the maximize button or manually resizes your form. Your program should almost always capture this event and update the size of your controls appropriately. Imagine if your MSIE browser window was 320x200, and when you resized the application to 640x480, the browser window was still 320x200. Looks ugly, because it is. If you don't want anyone resizing your form, just use a different BorderStyle as mentioned earlier.
Another special event is key presses. I suggest using OnKeyDown instead of OnKeyPress. The difference is that OnKeyDown can handle extended keys, and can detect Shift, Alt, and Ctrl states. If your application does not need to handle extended keys, then by all means, use OnKeyPress instead. Keyboard handling is useful for many applications that require it, like a typing tutor, games, etc... What might be confusing is the fact that OnKeyPress and OnKeyDown return extra parameters that you can use. This deviates from most of our understanding of Events. So far we've only covered simple events that don't require any special processing.
      SUB AddButtonClick
        '' Do stuff
      END SUB

      AddButton.OnClick = AddButtonClick
A simple click only passes a simple message to our button control, telling it that a click was received. Well, for key presses, this is more complicated. It's not enough to say that a key was pressed, we have to know what key was pressed, so we have to grab this extra message.
      SUB KeyPressed(Key AS WORD)
        '' Do stuff
        PRINT Key
      END SUB

      Form.OnKeyPress = KeyPressed
The key pressed is returned in the variable Key. You can name this anything you want, but your SUB must have at least that one parameter. Rapid-Q won't complain if you added more parameters, nor does it complain if you don't supply any parameters. It's up to you to make sure. For OnKeyDown, there's two parameters that are passed:
      SUB KeyDown(Key AS WORD, Shift AS INTEGER)
        '' Do stuff
        PRINT Key;" ";Shift
      END SUB

      Form.OnKeyDown = KeyDown
There are 3 shift states, ShiftDown, AltDown, and CtrlDown. Be careful of the ShiftDown state. Unlike OnKeyPress which handled all the Shiftdown states for you, OnKeyDown will not. This means if you pressed SHIFT+i you'll have to go UCASE$(Key). Extended keys are much different in Rapid-Q than what you'd expect in a QBasic program. For example, in QBasic, the arrow keys are easy to decode:
    DO
      A$=INKEY$
      IF A$=CHR$(0)+"H" THEN PRINT "Up arrow key pressed"
    LOOP
By using the OnKeyDown the virtual key code is returned, which is not a 2 byte code. The up arrow is Key = 38, left arrow Key = 37, right arrow Key = 39, and down arrow Key = 40

5.5 Dialog Boxes
A special type of form is a simple dialog box. Dialog boxes are usually extra interfaces to your main form. You don't usually implement a dialog box as your main form. For example, consider a main form where you have 3 choices:

Well, for each choice (except maybe for the last), you should create dialog boxes to handle the user's input. When the user clicks on the first button, a dialog box like this should appear:

The nice buttons are custom buttons. See RAPIDQ.INC for all the values.
     OKButton1.Kind = bkOK
     CancelButton1.Kind = bkCancel
Fine, but how do you know if the user pressed OK or CANCEL? There's actually two ways to do this, both involve using the ModalResult property. Remember how you called your dialog box:
   IF Dialog1.ShowModal = mrOK THEN
      '' User pressed OK
   ELSE
      '' User cancelled
   END IF
The ModalResult is a property of both the QButtons, and QForms. When we did this:
     OKButton1.Kind = bkOK
We also automatically did this:
     OKButton1.ModalResult = mrOK
What this means is that whenever you pressed the OK Button, the ModalResult returned is mrOK. This result automatically closes your Dialog1 form as well. Another less elegant approach is just to assign the ModalResult to your form. For example, let's assume this scenario:
      SUB ButtonClick
          Dialog1.ModalResult = mrOK
      END SUB

      OKButton1.ModalResult = mrNone   '' No result
      OKButton1.OnClick = ButtonClick
In the above scenario, clicking on the button will transfer control to the ButtonClick SUB. In this SUB, the ModalResult property of the Dialog1 form is set, which is doing exactly the samething as our previous example.

5.6 Using the CREATE Method
In most cases, using CREATE is preferred over DIM, this is because it saves you a lot of typing, and provides a cleaner look to your source code. For starters, let's just look at how much typing it could save you:
        DIM MainForm AS QForm
            MainForm.Left = 100
            MainForm.Top = 50
            MainForm.Height = 300
            MainForm.Width = 400
            MainForm.Caption = "Hello world!"
Well, here's what the above code looks like using CREATE:
        CREATE MainForm AS QForm
           Left = 100
           Top = 50
           Height = 300
           Width = 400
           Caption = "Hello world!"
        END CREATE
As you can see, you don't need to type MainForm each time, since the compiler will know exactly how you want the fields to be parsed.

5.7 Embedding CREATEs
Here's where using the CREATE method over DIM will save you time and confusion. This is what I mean about "encapsulation" of your controls:
        CREATE MainForm AS QForm
           Center
           CREATE Button1 AS QButton
              Left = 10: Top = 10: Height = 20: Width = 20
           END CREATE
           ShowModal
        END CREATE
You'll probably notice that we don't need the Parent property. This is because the compiler realizes that you want to include a Button to the MainForm (due to an embedded CREATE), so it automatically generates a Button1.Parent = MainForm for you. As you can also see, it looks much better, and you can visually see what components belong to want form/container. Rapid-Q can store up to 25 layers, in the above example, we only need one layer. I don't believe people need more than 4 or 5 layers (at most), but I set 25 as the maximum just to please the 1% who really want it. As you maybe able to figure out, components without a Parent property (non-visible components) are invalid in an Embedded CREATE.

5.8 Creating Menus
Creating menus using the CREATE method is no different:
        CREATE MainForm AS QForm
           Center
           CREATE MainMenu AS QMainMenu
              CREATE FileMenu AS QMenuItem
                Caption = "&File"
                CREATE OpenItem AS QMenuItem
                  Caption = "&Open"
                END CREATE
                CREATE SaveItem AS QMenuItem
                  Caption = "&Save"
                END CREATE
              END CREATE
           END CREATE
           ShowModal
        END CREATE
Instead of the Parent property, we're saving ourselves from using AddItems. This is probably easier to understand than using DIM to define all your menus.


6: Writing Console Applications

Rapid-Q Documentation by William Yu (c)1999 Chapter 6

6. Writing Console Applications

Console applications are as easy to create as Windowed applications. Whenever you feel like creating text-based applications, just compile as CONSOLE instead of GUI. As you may find, it's easier to learn the fundamentals of Rapid-Q (or the BASIC language in general) by creating simple console applications and testing your routines. It can also act as a debugging tool for your GUI applications.

6.1 Overview of console functions
A console application is a text-based application capable of writing to and accepting input from the console. A console application, in Rapid-Q, consists of one visible screen, and 7 off screen buffers. Here's an overview of some console functions:
   CLS    - Clear console screen
   PRINT  - Write output to screen (visible/offscreen)
   INPUT  - Accept input from user
   PCOPY  - Used to copy to and from the screen buffers
   LOCATE - Position cursor
   POS(0) - Get current cursor column
   CSRLIN - Get current cursor row

   COLOR  - Change color attribute of text
   POKE   - Put attribute/char on screen
   PEEK   - Get attribute/char from screen
   SLEEP  - Delay
   INKEY$ - Non-blocking keyboard check
These functions mimic the ones you would see under QBasic. PEEK and POKE operate the same way, SLEEP is more precise than QBasic's (ie. you can specify a fraction of a second, like in PowerBASIC). Notice that you don't require any DEF SEG statements, since this is Windows.

6.2 Hello world example
Rapid-Q is like most BASIC languages, you can create a hello world program in just one line:
     PRINT "Hello World!"
Compile and run, you've just created your first useless console application for Windows! Let's move on to something more interesting, copying to and from screen buffers.
   CLS
   PRINT "This is page 1"

   PCOPY 0, 1    '-- Copy visible page 0, to off screen page 1

   CLS
   PRINT "Press any key to see page 1"

   DO:LOOP UNTIL INKEY$<>""

   PCOPY 1, 0    '-- Copy off screen page 1, to visible page 0
As you can see, our visible page is always 0. Our off screen pages range from 1-7. PCOPY just copies the whole buffer and places it into another. You can even copy an off screen buffer to another off screen buffer like so:
    PCOPY 1,5
The contents in buffer 1, is now copied to buffer 5. There's nothing new introduced here that you wouldn't have found in QBasic. One new feature is that you can now write to any offscreen page:
   PRINT #1, "Hi World!"       '-- Write to page 1
The above example will write the string "Hi World!" to the offscreen page 1. Make sure you use the pound sign '#' else it will be treated as a number. To see it, use PCOPY 1, 0.
 LOCATE and COLOR have the same effect on the offscreen pages. You can also PEEK from and POKE to the offscreen pages, just supply an additional parameter, the first being the page number to write/read from.

6.3 Using PEEK and POKE
If you've never used PEEK and POKE before, it's not a big deal. In Rapid-Q, PEEK and POKE have the same functionality of QBasic (except for the additional feature to PEEK/POKE to any offscreen page). Addresses range from 0 to 3999. This is because the screen size is restricted to 80x25 in Rapid-Q. But if 80x25 = 2000, what's the extra 2000 for?
    POKE 0, ASC("A")
    POKE 1, 15
If you run this code, you'll see a white letter 'A' displayed at the upperleft corner of your console. One thing you should note is that a "byte" on the screen contains a character and its attribute. All even numbered address contain the character, all odd numbered addresses contain the attribute. If you don't exactly know what an attribute is, it's just a combination of the foreground color and background color all in one byte (8-bits). The lower 4 bits is reserved for the foreground color, and the upper 4 bits is reserved for the background color. If you know anything about bits and bytes, you can easily calculate the attribute:
    B? = &H07       '-- 0 = background, 7 = foreground
Yes, you can have high intensity background colors. Blinking is not supported yet.

6.4 Accepting user input
You can accept user input via the INPUT statement or by the INKEY$ function. Rapid-Q's INPUT statement is not like "normal" Basic INPUT that you may be familiar with. It is more like a LINE INPUT in that it will prompt for a complete line of information and only terminates if the user hits the enter key.
   INPUT "What is your age? ", Age
A quoted string can follow an INPUT statement, then a comma or semi-colon, followed by a variable. The input statement will store the result in the variable, string or numeric. The INPUT statement will block until the user has hit the enter key. For non-blocking keyboard inputs, try using INKEY$. It's a bit confusing to use at first, but it allows for customized keyboard handling. Let's use the same example above to demonstrate how this is done using INKEY$. However, in this version, we can customize input and filter out non-numeric characters.
   PRINT "What is your age? ";
   AGE$ = ""
   DO
     DO
       A$ = INKEY$
     LOOP UNTIL LEN(A$)
     IF A$ = CHR$(13) THEN EXIT DO
     IF A$ >= "0" AND A$ <= "9" THEN PRINT A$;:AGE$=AGE$+A$
   LOOP
   PRINT
   PRINT "You are "; AGE$; " years old."
Notice that if you press a non-numeric key, that character is not echoed. This is because we've restricted input to characters 0..9 only. Although the example is much longer than the previous one, we have customized our input using INKEY$ and that provides so much more power than INPUT. Another advantage of using INKEY$ is that you can also trap extended keys.

6.5 Trapping Extended Keys
Extended keys are 2 bytes in length, the first byte is an ESC character, which can be ignored, and the second byte is the virtual key code. In the Windows version, you can add the option to trap all keys, including shift, ctrl, key, caps lock, num lock, scroll lock, and that PopupMenu key (if you're using a Windows specific keyboard, no not the StartMenu Key, the other one, if it exists on your keyboard). You can turn on/off this option anytime you wish:
   $OPTION INKEY$ TRAPALL

   ' trap all keys including shift, alt, ctrl, caps/num/scroll lock
   ' and the PopupMenu key

   $OPTION INKEY$ DEFAULT

   ' traps all extended keys except the ones listed above
If you've used QBasic, you probably know the scan codes inside out, so all the virtual key codes that Rapid-Q dishes out is exactly the same scan codes you'd see in QBasic. The following code is an example of how to trap/parse extended keys, particularly the arrow keys:
   DO
     DO
       A$ = INKEY$
     LOOP UNTIL LEN(A$)

     IF LEN(A$) = 2 THEN
       SELECT CASE RIGHT$(A$, 1)
         CASE "P"
           PRINT "Down arrow key pressed."
         CASE "H"
           PRINT "Up arrow key pressed."
         CASE "M"
           PRINT "Right arrow key pressed."
         CASE "K"
           PRINT "Left arrow key pressed."
         CASE ELSE
           PRINT "Extended key "; A$
       END SELECT
     END IF

   LOOP UNTIL A$ = CHR$(27)
Even if you didn't know the scan codes, you can look at the output of the above example to figure them out.

6.6 Mixing CONSOLE with GUI
As you've noticed in the above example, we've mixed some CONSOLE operations with GUI ones. This is perfectly valid as long as you've compiled your application as CONSOLE. Under Linux/Unix there are some strange differences, please refer to the compatibilty guide for more information. For example, a GUI application for Linux/Unix can perform some CONSOLE operations such as PRINT, INPUT, and CLS without being compiled as CONSOLE.

6.7 Linux/Unix Console
Since most terminals are different, some console features will not work. If your terminal does not support color, none will be displayed. You don't need to worry about these issues, as Rapid-Q performs all proper error checking for you. The same can be said for extended keys, some terminals don't support certain keys. However, most terminals do support the arrow keys and Page up/down keys. You're almost guaranteed that those keys will work for most terminals.


7: Introduction to streams

Rapid-Q Documentation by William Yu (c)1999 Chapter 7

7. Introduction to streams

Rapid-Q supports file streams instead of the standard OPEN command used in BASIC. It has the same functionality, but is called differently. What's great about streams is that it's unlimited in size, and you can copy to and from different streams (ie. File to Memory).

7.1 File streams
File streams are used to create, read and write to files. All streams are opened as binary, with no locking capabilities (ie. all files you open are shared). Please familiarize yourself with these file modes:
     fmCreate    - Create file (read/write), truncate if file exists
     fmOpenRead  - Open file for reading only
     fmOpenWrite - Open file for writing only
     fmOpenReadWrite - Open file for reading & writing
To open a file you need to pass the filename, and provide one of the above file modes.
     DIM File AS QFileStream

     File.Open("Test.txt", fmOpenRead)
This will open Test.txt for reading only. To read data, you use the methods ReadNum and ReadStr. See RAPIDQ.INC for valid numbers.
     PRINT File.ReadNum(Num_SINGLE)   '-- Read 4 bytes as a SINGLE number
     PRINT File.ReadStr(1024)         '-- Read 1024 bytes
Another approach is to store the value into a variable, you can use the generic Read and Write routines.
     File.Read(A&)          '-- Read a long value and store in A&
     File.Write(B#)         '-- Write a double value B#

     '-- or similarily, with more work:
     A& = File.ReadNum(Num_LONG)
     File.WriteNum(B#, Num_DOUBLE)
After you're done with the file, make sure you close the handle. You can then reuse your file stream and open up another file. To test if you've reached the end of the file, you can either compare File.Position with File.Size or see if File.EOF is true (-1). So long as File.Position is less than File.Size, you haven't reached the end of the file. There are actually 2 ways to test if a file exists:
     IF FileExists("Test.txt") <> FALSE THEN
       File.Open("Test.txt", fmOpenRead)
     END IF
However, it's better just to cut this down to:
     IF File.Open("Test.txt", fmOpenRead) = FALSE THEN
        ShowMessage("Could not open file")
     END IF
File.Open will return a non-zero number if the file was successfully opened, 0 otherwise.

7.2 Memory streams
A memory stream is created whenever you DIM it. It's similar to file streams, all the methods are the same, such as ReadNum, WriteNum, etc... The only difference is that memory streams are stored in memory, which can grow/shrink with no upper bounds. It's even possible to store arrays of numbers in memory stream (see ARRAYS.BAS example). Memory streams serve many purposes, let your imagination take over. One useful purpose might be to store temporary data, such as copying a file to a memory stream and manipulating the data that way. So how can I copy from one stream to another? Quite easily, you can copy between different streams (ie. File to Memory) or of the same kind (ie. Memory to Memory).
    DIM File AS QFileStream
    File.Open("test.txt", fmOpenRead)

    DIM Memory AS QMemoryStream
    Memory.CopyFrom(File, File.Size)  '-- Copy everything
As you can see, we've just copied the entire contents of our file "test.txt" to our memory stream. Now you can manipulate your memory stream without affecting the file.

7.3 Saving/Loading UDTs and Arrays
Saving and loading UDTs is as simple as passing the UDT to QFileStream or QMemoryStream.
    TYPE TTest
        S AS STRING*8
        N AS INTEGER
    END TYPE

    DIM Test AS TTest
    DIM File AS QFileStream

    File.Open("test.txt", fmCreate)
    File.WriteUDT(Test)
    File.Close
In the above example, 12 bytes was saved to the file test.txt. 8 bytes for the fixed string S, and 4 bytes for N. To retrieve the UDT, use the method ReadUDT.
    File.Open("test.txt", fmOpenRead)
    File.ReadUDT(Test)
Saving/Loading arrays is equally easy.
    DIM A(1 TO 100) AS LONG
    DIM File AS QFileStream

    File.Open("test.txt", fmCreate)
    File.SaveArray(A(1), 100)
    File.Close
The first parameter of SaveArray is the starting array element to save, this could be any value from 1 to 100 in the above example. The next parameter specifies how many elements of the array to save. In this case we choose to save all 1..100 elements. Similarly, we can use LoadArray to retrieve our data:
    File.Open("test.txt", fmOpenRead)
    File.LoadArray(A(1), 100)
Streams are very popular in most high level languages for file/memory manipulation, but does take some time to get used to, especially if you're a die-hard BASIC user.


8: Using Image Resources

Rapid-Q Documentation by William Yu (c)1999 Chapter 8

8. Using Image Resources

Most Windows programming languages offer support for .RES (Resource) files. A Resource file is nothing more than a collection of images (plus resource strings and data). In this chapter, you'll learn about Image lists, how to embed resources in your executable, and how to properly use them in your applications.

8.1 Supported RESOURCES
Rapid-Q only "directly" supports image resources, ie. just Icons and Bitmaps. So what exactly is the difference between loading a picture at run-time, or loading resource handles? For one thing, whenever you declare a resource handle, that picture file is automatically embedded within your executable. Here's an example:
     $RESOURCE ICO_TEST AS "C:\ICONS\TEST.ICO"

     DIM Form AS QForm

     Form.ICOHandle = ICO_TEST
     'Form.Icon = "C:\ICONS\TEST.ICO"
The file C:\ICONS\TEST.ICO is embedded within your executable, which means you don't need to include TEST.ICO if you plan on distributing your .EXE program. Rapid-Q doesn't generate .RES files for you, and it can't handle other people's .RES files either. Most languages you'll see have a .RES file, but you can't use them in Rapid-Q, you'll have to extract the pictures within it, and use the $RESOURCE handle directive to include them in your application. It is also possible to do this:
     Form.ICOHandle = ICO_TEST

     DIM Image AS QImage

     Image.Icon = Form.Icon
Image.Icon normally accepts a string value, but if no string is specified, it'll read the previously cached icon. In this case, we're loading Form.Icon to our "cache" and Image.Icon will read from it. So what does this do?
     Image.Icon = Form.Icon + Form2.Icon
This will load Form2.Icon into the cache, so Image.Icon will copy Form2.Icon. However, please note that you can't assign Icon Handles, for example:
     Image.IcoHandle = Form.IcoHandle
The parser will try to look for a resource handle, but won't find one.

8.2 Introduction to Image lists
You may want to refer to the Appendix on the properties, and methods of QImageList. An Image list is an array of icons and/or bitmaps. They are ordered from 0 to N. The first image you add will be index 0, the next index 1, etc... an image list store images of FIXED width and height. Anytime you change the Width or Height property, you're ultimately clearing the entire array. Note, this does not mean you can't add a 100x100 BMP file when your image list width is 32. It just means your BMP will be resized, whether you wanted that or not.
    DIM ImageList AS QImageList
        ImageList.Width = 32
        ImageList.Height = 32
        ImageList.AddICOFile("app.ico")
        ImageList.AddBMPFile("app.bmp", 0)
You can add icons or bitmaps in any order. As before, you can also add images from the "cache" if no filename was specified. As before:
    ImageList.AddICOFile(Form.Icon)
    ImageList.AddICOFile(ImageList.GetICO(0))

8.3 Other kinds of Resources
You can include any kind of resource to your Rapid-Q program, but how can you use these other kinds? For example, if I include a .WAV file as a resource, how can I use it in my PLAYWAV routine? Well, since PLAYWAV can take resource handles, you can just pass it as a parameter:
    $RESOURCE Bomb_WAV AS "BOMB.WAV"

    PlayWav(Bomb_WAV, 1)      '-- 1 = background play

    SLEEP 5                   '-- Wait until wav is finished
As for other types, you can extract the resource to be manipulated.
    $RESOURCE Whatever_TYPE AS "text.txt"

    ExtractResource(Resource(0), "text.txt")
After you're done using it, you can simply delete the file. There are a wide range of uses for extracting resources, you can even use this technique in an installation program. For more information on EXTRACTRESOURCE, RESOURCE, and RESOURCECOUNT, please see Appendix C: Other reserved keywords


9: SUBI, FUNCTIONI, and DLLs

Rapid-Q Documentation by William Yu (c)1999-2000, appended by John Kelly Chapter 9

9. SUBI, FUNCTIONI, and DLLs

You'll learn all there needs to know about creating your own SUB/FUNCTIONs with variable number of parameters. If you know a little about C, you'll probably know about the most popular command printf. Well, it's actually possible to implement your own printf in Rapid-Q!

9.1 SUB/FUNCTIONs with variable parameters
Traditional SUBs or FUNCTIONs have a fixed number of parameters we can pass, but SUBI and FUNCTIONI can accept an infinite number (255) of variable parameters. You're probably wondering how we can retrieve these parameters, well, they are actually stored in an internal stack. So what you'll have to do is probe this stack for the correct parameter. Here are the keywords used to do that:
 ParamStr$() - Array of string parameters
 ParamVal() - Array of numeric parameters
 ParamValCount - Number of numeric parameters passed
 ParamStrCount - Number of string parameters passed
As a simple example, we'll just test to see that it works:
 SUBI TestSUBI (...)
 PRINT "String Parameters: "; ParamStrCount
 FOR I = 1 TO ParamStrCount
 PRINT I;" "; ParamStr$(I)
 NEXT I
 PRINT "Numeric Parameters: "; ParamValCount
 FOR I = 1 TO ParamValCount
 PRINT I;" "; ParamVal(I)
 NEXT I
 END SUBI

 TestSUBI "Hello", 1234, "Hmmm", "Yeah...", 9876, 1*2*3*4, UCASE$("Last one")
You'll probably notice that the ParamStr$() and ParamVal() arrays aren't zero-based (ie. their first value starts at 1). This may seem strange, since everything in Rapid-Q is zero-based. Anyway, besides that, something equally strange is the use of (...) in replace of parameter names. It doesn't really matter what you put in the brackets, as long as it's a valid token (one word). Try creating a FUNCTIONI, it's no different from creating a standard FUNCTION except you replace your formal parameter names with (...).

9.2 More on FUNCTIONI
To expand our knowledge, let's do more examples, here's one that will find the maximum number from the parameters you provide it.
 FUNCTIONI FindMax (...) AS DOUBLE

 DIM Largest AS DOUBLE
 DIM I AS BYTE

 Largest = -999999999999

 FOR I = 1 TO ParamValCount
 IF ParamVal(I) > Largest THEN
 Largest = ParamVal(I)
 END IF
 NEXT

 FindMax = Largest ' or Result = Largest
 END FUNCTIONI
The function goes through the entire list of numeric parameters and checks which one is the largest. Any string parameters are properly ignored. Now let's test it:
 PRINT "Largest number is: "; FindMax(523, 12.4, 602, 45, -1200)
 PRINT "Largest number is: "; FindMax(523, 12.4, FindMax(602, 45, -1200))
You can comfortably embed your FUNCTIONI if you like. There's really nothing to it. Just remember the keywords you need to access the internal stack, and away you go!

9.3 Introduction to DLLs
What is a DLL? It's a Dynamic Link Library which contain exported functions which can be used by any programming language that support DLLs. Your RapidQ program has SUBs and FUNCTIONs, why not use SUBs and FUNCTIONs that are already written? You get access to them by calling them inside the DLL. You could even write your DLL in FreeBasic, BCX, Delphi, or C++ and use those functions in Rapid-Q. Why use a DLL? Mainly so you can access the windows operating system for your program. Another reason to use a DLL is to use existing libraries run faster code. Because RapidQ is an interpreter program execution for large calculations using large number of loops can be done much faster with a DLL that uses true machine code. DLLs work by loading in the same process space as your program, so you have access to their exported functions. DLLs in Rapid-Q can only be dynamically linked at run-time (ie., when the program runs and not at compile time).

Not all DLLs are the same. Some DLLs are written especially for C++ and use 'COM interface' and some are written for Visual Basic to use 'ActiveX' technology (using an extension .OCX). Rapid-Q can only use DLLs following standard calling conventions such as in C or PASCAL languages. In other words, be sure you can get the documentation on a DLL and don't always assume RapidQ can use all DLLs. See the FreeBasic DLL tutorial for examples of making your own DLL for RapidQ.

9.4 How to call a DLL
There is an example called DLL.BAS included in your Rapid-Q distribution. Included is also a DLL called PASCAL.DLL. You may want to take a look at it. To call DLLs in Rapid-Q is almost identical to the way you call DLLs in PowerBASIC or VisualBASIC. It may look nasty, but I've decided to conform to that standard. One thing to note is that CASE MATTERS! Yes, that's right, if you miscapitalized your function, ka-boom! Oops, not to confuse you even more, but there's actually 2 functions. One which you will call in your program, and the other is the one contained in the DLL. These two functions/subs must have matching parameters, or ka-boom!

 DECLARE SUB Test LIB "TEST.DLL" ALIAS "MyFunc" (S AS STRING)
So you must be wondering, which is case sensitive, Test or MyFunc. Well, Test is the one you'll be calling in your own program, so you know that can't be it, MyFunc is the one contained in the DLL, so make sure you typed that in correct case! The above SUB will point to the memory address of your DLL (when loaded), and execute the code within. As you can see, there's only one parameter for our MyFunc routine. There are only 2 extra keywords introduced here, LIB and ALIAS. After LIB should be a string corresponding to the file name (and path if needed) of your DLL. If your DLL resides in your $PATH setting, you don't need to specify any path (ie. if your TEST.DLL resides in the folder as your application or in C:\WINDOWS\SYSTEM). The second keyword ALIAS is to specify the function/subroutine you can execute in that DLL. Make sure you check your case, this is very important. If you're not sure of the case, you can use a DLL viewer (such as Quick View, more on this later). What are the valid datatypes to pass?
SHORT/WORD, INTEGER/LONG/DWORD, DOUBLE, STRING, QRECT, QNOTIFYICONDATA, and any UDT you create.
Unlike some implementations which force you to pass your STRING as a pointer, Rapid-Q will do all this for you, so you need not worry. Whenever you see LPZSTR as a parameter, that just means Long Pointer Zero-Terminated String. You can safely pass any string variable. You may notice that some BASIC languages (like VB) will ignore ALIAS whenever the function matches the same function you're declaring. For example:
 DECLARE SUB MyFunc LIB "TEST.DLL"
However, this DOES NOT apply to Rapid-Q, you can't do this, so don't even try.
Calling a DLL function or calling your own function is exactly the same, there's nothing more you need to know:
 MyFunc("Hello")

9.5 Using Quick View
As mentioned before, if you're not sure of the exact case of your function, it's a good idea to take a look using Quick View.
Quick View might be included with Windows. . To invoke Quick View, load up Windows Explorer (or click on "My Computer"), then find a .DLL file, right click on it, and select Quick View from the menu. Look for an Export Table, that's where you'll find all the available functions. If Quick View does not appear then download a DLL viewer such as ADllExports.exe (you can search for it on the Web).

9.6 Writing your own DLLs
It's not possible to write DLLs in Rapid-Q. However there are a few BASIC compilers that let you write DLLs that use similar BASIC code as Rapid-Q. Some of the easiest to use are FreeBasic or BCX, which are free for downloading. Other alternatives are PowerBasic, HotBasic, or RealBasic. There are special procedures to follow such as knowing whether Rapid-Q passes a value or a pointer. Rapid-Q passes all variable tyes (i.e., BYTE, INTEGER, LONG, etc.) by its value. However, User Defined Types and STRINGs are passed by reference (as a ponter). This is important to remember for STRINGs, since Rapid-Q only passes the pointer (location in memory of the string, not the string itself). VisualBasic or PowerBasic may not always use string pointers. Please use pointers to strings in your parameters to avoid using OLE to allocate the string itself. Rapid-Q won't use OLE to allocate the string, since I don't anticipate many DLLs that don't use pointers to strings. To really understand how to work with DLLs you should review the FreeBasic DLL tutorial.

9.7 Using User Defined Types (UDTs) or unsupported types in a DLL call
Rapid-Q user defined type is passed as a pointer (i.e., always as ByRef). Rapid-Q stores the data in a packed format so that all information in the UDT is placed end-on-end depending on the size of the variable declared in the UDT. What is important is make sure you have your DECLARE SUB or DECLARE FUNCTION statements correct when you pass a pointer to the DLL. Commonly the variable name is prefixed with an "lp" meaning long pointer). :
'RECT is a structure of the form:
 TYPE RECT
   Left AS LONG
   Top AS LONG
   Right AS LONG
   Bottom AS LONG
 END TYPE

DECLARE FUNCTION GetWindowRect LIB "USER32" ALIAS "GetWindowRect" _
 (hWnd AS LONG, lpRect AS RECT) AS LONG
'note lpRect is really a LONG expecting a value to be an address in memory
Now you write your code like this:
DIM R AS RECT
 GetWindowRect(MainForm.Handle, R)
Sometimes in Windows programming you need to pass a NULL instead of the address of a UDT, for example to use a default. A NULL is just a long of value 0. To avoid getting a compile error, just change the type in the delaration:
DECLARE FUNCTION SpecialFunction LIB "Func.Dll" ALIAS "SpecialFunction"_
 (hWnd AS LONG, lpRect AS LONG) AS LONG 'tell the program to expect a long value

SpecialFunction(MainForm.Handle, 0&) 'now this works
SpecialFunction(MainForm.Handle, R) 'and this works too
We just changed the type of lpRect to LONG. This is because we want to pass a pointer (which is just a number). This will also work for passing the UDT normally as well

What if we want to pass complicated structures?
If you pass a UDT to a DLL, RapidQ will automatically pass the address to the start of one contiguous block of memory holding the UDT data. The DLL will then read from this memory location. After returning from the DLL, we can retrieve the returned data (in the case above GetWindowRect returns the RECT structure of the Window). This is rather simple, but what if there are nested TYPEs within a TYPE? Rapid-Q does not directly support nested TYPES but there is a work-around using QMEMORYSTREAM.
TYPE Struct1
  A AS INTEGER
END TYPE

 TYPE Struct2
   S AS Struct1
   I AS INTEGER
 END TYPE
If a DLL call requires a TYPE, which may have nested TYPEs, then you can do the same kind of conversion:
TYPE Struct1
 A AS INTEGER
 END TYPE

 TYPE Struct2
 S AS LONG
 I AS INTEGER
 END TYPE

 DIM S1 AS Struct1
 DIM S2 AS Struct2

 DIM M1 AS QMEMORYSTREAM
 DIM M2 AS QMEMORYSTREAM

 M1.WriteUDT(S1)
 S2.S = M1.Pointer
 M2.WriteUDT(S2)

 '' Call DLL function...
Now the last case we have to consider is strings within TYPEs. We can't just declare a string anymore, we have to declare a pointer to a string, for example:
TYPE TStruct
 ST AS STRING    'actually sends a Long Pointer Zero-Terminated String
 Other AS INTEGER
 END TYPE
This would not be valid since ST would be passed by value (in which case it can consume any number of bytes in memory). However, most DLL calls want strings passed by reference (ie. just give it the pointer to the string). A conversion is necessary, using VARPTR:
 TYPE TStruct
 ST AS LONG
 Other AS INTEGER
 END TYPE

 DIM Struct AS TStruct
 DIM S AS STRING

 S = SPACE$(100) '' Allocate some space for string
Struct.ST = VARPTR(S)
'' To get back the string use VARPTR$
S = VARPTR$(Struct.ST)
Please note that this string conversion is only necessary for TYPEs and not necessary for normal DLL calls. For normal DLL calls which have STRING as parameters, just pass the string and not the pointer, since Rapid-Q will translate this automatically for you. You can, of course, do the conversion yourself, just remember to change the STRING parameter to something like LONG, and pass VARPTR(S$) instead of the actual string S$.

9.8 API conversion table
Most API programming in Rapid-Q is for working with the large and powerful the windows operating system.API. Documentation for Windows API can be found at www.msdn.microsoft.com by entering the name of the FUNCTION or SUB in the search box. However, almost all documentation is in C. This can be challenging to understand for a BASIC programmer. The easiest way to explain how to read it is an example. Here is how the Windows API function WriteFile is declared in C:

BOOL WriteFile(

  HANDLE hFile,                   // handle to file to write to
  LPCVOID lpBuffer,               // pointer to data to write to file
  DWORD nNumberOfBytesToWrite,    // number of bytes to write
  LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
  LPOVERLAPPED lpOverlapped       // pointer to structure needed for overlapped I/O
);

and now the same version in RapidQ:

DECLARE FUNCTION WriteFile LIB "kernel32" ALIAS "WriteFile"_
   (hFile AS LONG, _                         'handle to file to write to
   lpBuffer AS STRING, _                     'pointer to data to write to file
   nNumberOfBytesToWrite AS DWORD, _         'number of bytes to write
   BYREF lpNumberOfBytesWritten AS DWORD, _  'pointer to number of bytes written
   lpOverlapped AS OVERLAPPED) AS LONG       'pointer to structure needed for overlapped I/O

Notice how variable types (BOOL, HANDLE, LPCVOID, etc.) are stated before the variable name (hFile, lpBuffer, etc.). Now Let's take the example of a more complictated example, creating an stream of data for an Audio-Visual-Interlaced file. The function is contained in a DLL called AVIFIL32.DLL in your Windows system Folder.

The AVIFileCreateStream function creates a new stream in an existing file and creates an interface to the new stream. The declaration in C is like this:

STDAPI AVIFileCreateStream(
  PAVIFILE pfile,
  PAVISTREAM * ppavi,
  AVISTREAMINFO * psi
);   // semicolon ends the entire command.

STDAPI means this is a FUNCTION that exists externally, and returns a LONG value (Often 'HRESULT' is used instead, but it all really means a LONG value is returned).
AVIFileCreateSteam is the name of the function.
pfile is a variable of type PAVFILE, which actually a variable holding the value holding a pointer. The 'p' reminds you it is a pointer.
ppavi is passed by reference (the * symbol means 'give me the address of the variable)
psi is a UDT of type AVISTREAMINFO and is passed to the API by reference (* means pointer).

Here is how you make the same Declare function in RapidQ:
Declare Function AVIFileCreateStream Lib "avifil32.dll" ALIAS "AVIFileCreateStreamA"_
 (ByVal   pfile AS LONG, _
 Byref    ppavi AS LONG, _
 ByRef   psi As AVISTREAMINFO) AS LONG

Notice there are big differences, especially since the actual name in the DLL is AVIFileCreateStreamA, but you will always call this function in Rapid-Q by AVIFileCreateStream.

Here is another example, showing how to pass a string to a Windows API:
STDAPI AVIFileOpen( PAVIFILE * ppfile, LPCTSTR szFile, UINT mode, CLSID pclsidHandler );

Here is how you make the same Declare function in RapidQ:

Declare Function AVIFileOpen Lib "avifil32.dll" ALIAS "AVIFileOpen"_
(ByRef ppfile AS LONG,_            'the * in the C code means ByRef
  ByVal szFile As String, _         'szFile = 'string with zero terminated character' of file name
  ByVal uMode AS LONG,_             'the API wants a UINT, or an unsigned integer, but LONG is ok
 _ByVal pclsidHandler AS LONG) AS LONG    'CLSID is a pointer, but we will pass a NULL, so use ByVAL
As you can see, translating C code can be tricky. Luckily, many API declarations have already been done for Visual Basic, and converting from Visual Basic to RapidQ is much easier than C to RapidQ. There is even a tool in FreeBasic called SWIG that converts C include files to FreeBasic code. To help understand how to convert between different variable types, here is a basic summary with some brief explanations. Special thanks to Mayuresh S. Kadu for this WIN32 API in VB guide.

C data type Pascal Visual Basic
ByRef is default 		Rapid-Q
ByVal is default for most
ATOM | SHORT | byval as INTEGER | SHORT
BOOL | BOOLEAN | byval as LONG | LONG
BYTE | BYTE | byval as BYTE | BYTE
CHAR | CHAR | byval as BYTE | BYTE
CHAR[20] | STRING[20] | as STRING | N/A in API Declarations
COLORREF | LONGINT | byval as LONG | LONG
DWORD | DWORD | byval as LONG | DWORD
Windows handles ie. HDC
HWD, HRESULT, HMENU,etc. 		Windows Handles byval as LONG LONG
INT, UINT | INTEGER, DWORD | byval as LONG | INTEGER, DWORD
LONG | LONGINT | byval as LONG | LONG
Pointers to a variable that are passed by value
LPVOID, LPDWORD,
LPINT, LPUNIT, etc. 		LONGINT byval as LONG BYVAL as LONG
Pointers to a long
LPVOID * , LPDWORD *,
LPINT *, etc 		^DWORD as LONG BYREF as LONG
LPARAM | LONGINT | byval as LONG | LONG
LPINT, LPUINT | ^INTEGER | as LONG | BYREF as LONG
LPRECT | ^TRECT | as ANY | QRECT
LPSTR, LPCSTR, LPCTSTR PCHAR byval as STRING as STRING or
BYVAL as STRING
LPVOID | LONGINT | as ANY | LONG
LPWORD | ^WORD | as INTEGER | BYREF as WORD
LRESULT | LONGINT | byval as LONG | LONG
NULL | NIL | byval as LONG | BYVAL as LONG (use 0& in call)
SHORT | SHORT | byval as INTEGER | SHORT
WORD | WORD | byval as INTEGER | WORD
WPARAM | LONGINT | byval as LONG | LONG

Many other types exist- the general rule is that if C declares the variable with an “L” or “LP” as the fist characters then it is a pointer of type LONG. A variable with 'DW' means double word (LONG or DWORD in RQ), and lpWxxx means word (WORD or SHORT in RQ).
RapidQ can accept but does not strictly support the unsigned data types such as DWORD, UINT8, UINT16, UINT32, etc. Usually this is not a problem if you are careful in handling the numbers in math statements. If you need 10 byte Reals, or 64 bit integers, then try FreeBasic, BCX, RealBasic, etc. instead. For those data types in red, they are pointers to the variable. In Rapid-Q, this requires using VARPTR in passing the address of the variable, and not the value of the variable. Here's some sample conversions:

 In VB:
 DECLARE SUB Test LIB "USER32" ALIAS "What" _
 (byval L AS LONG, byval S AS STRING)

 Test (1230, "Hello world!")

 In Rapid-Q:
 DECLARE SUB Test LIB "USER32" ALIAS "What" _
 (byval L AS LONG, byval S AS STRING)

 Test (1230, "Hello world!")
Nothing different there, note that Rapid-Q doesn't use BYVAL, so you can ignore putting them there. In the above example, the string is passed by reference, ie. the address of the string is passed, not the string itself. Here's an example which passes the whole string (not the address, so it involves OLE to allocate space for the string), this works fine in VB but not in Rapid-Q:
 In VB:
 DECLARE SUB Test LIB "USER32" ALIAS "What" _
 (byval L AS LONG, S AS STRING)

 Test (1230, "Hello world!")

 In Rapid-Q:
 Not possible, since it doesn't use OLE to allocate the string.
How about NULL strings? Here's another situation (please note that I don't use VB much so it may be possible to declare S as STRING and pass it a vbNullString, I'm not really sure so I'll play it safe):
 In VB:
 DECLARE SUB Test LIB "USER32" ALIAS "What" _
 (byval L AS LONG, byval S AS LONG)

 Test (1230, 0&)

 In Rapid-Q:
 DECLARE SUB Test LIB "USER32" ALIAS "What" _
 (byval L AS LONG, byval S AS LONG)

 Test (1230, 0&)
So what if we want to pass a string instead of a NULL string, then you'd need to use VARPTR:
 In VB or Rapid-Q:
 DIM S AS STRING
 S = "Hello world!"

 Test (1230, VARPTR(S))
A NULL string basically means an address of 0. VARPTR just returns the address of a variable. How about other pointers, like LPWORD? A WORD is just an unsigned 16-bit number, VB only supports signed 16-bit numbers called INTEGERs, but the general idea is to remove the byval keyword when passing variables by reference:
 In VB (doesn't support WORD, so use next best):
 DECLARE SUB Test LIB "USER32" ALIAS "Another" _
 (L AS INTEGER)

 DIM L AS INTEGER

 Test (L)

 In Rapid-Q:
 DECLARE SUB Test LIB "USER32" ALIAS "Another" _
 (BYREF L AS WORD)

 DIM L AS WORD

 Test (L)
In Rapid-Q, use BYREF when passing variables by reference, in VB you don't need to use BYREF, as the above example demonstrates.


10: Creating Custom Components

Rapid-Q Documentation by William Yu (c)1999 Chapter 10

10. Creating Custom Components

Creating your own custom components may be helpful when you want to have a custom look and feel to your forms (among other things). For example, instead of the the standard Windows checkboxes, you may want to create diamond like checkboxes (complete listing at end of chapter). By the end of this chapter, you'll be able to create your own fully reuseable components, even custom forms! We will start with a simple example of a diamond checkbox.

10.1 Introduction to object creation
You won't exactly be reinventing the wheel when you create your own custom objects. The way you create your own objects is to EXTEND a component (like QCanvas). What this means is that you'll inherit all its properties, methods, and events. After that, you may choose to override its properties, and/or methods, or create new properties and methods. The concept is really easy to understand, once you get the hang of things. Rapid-Q's component creation method doesn't resemble any language per se, but it doesn't look too foreign either. Since object creation is not something newbies should step right into, you should familiarize yourself with the concept of properties, methods, and events. You also need a good understanding of TYPEs, since events/methods within types is something new. Do not get confused with other OOP languages, Rapid-Q does not adopt overloading, protected or virtual members. Rapid-Q's OCC (Object Component Creation) paradigm doesn't model any language, but does take several ideas from other OOP languages like Delphi, C++ and Java.

10.2 Extending QCanvas
QCanvas is a very useful "blank sheet" component. It allows you to draw whatever you want on it, making this the most useful component to extend. First of all, how exactly do we extend it?
     TYPE QDiamondBox EXTENDS QCanvas
     END TYPE
Wow, that was easy. The above code is perfectly valid, although it doesn't do anything useful. What that did was create a new object called QDiamondBox which inherited all the properties, methods, and events of QCanvas. So we can now DIM it and assign values to it:
     DIM DBox AS QDiamondBox
         DBox.Top = 10
Okay, that's not very useful. Sometimes we would like to add properties to our existing component, and in our above example, we probably need a Caption property, and maybe a Checked property (since we're going to implement a checkbox type component). Adding properties is nothing new:
     TYPE QDiamondBox EXTENDS QCanvas
        Caption AS STRING
        Checked AS INTEGER
     END TYPE
As you can see, it looks like any UDT (user defined types) that most BASIC programmers are familiar with. So now we've added 2 additional properties to our new component, we'd access them like we would any property. Okay, but what if you want the values to be initialized to something when it gets created? Not a problem, you don't need a constructor procedure like in C++, you just embed this information like so:
     TYPE QDiamondBox EXTENDS QCanvas
        Caption AS STRING
        Checked AS INTEGER

        CONSTRUCTOR
          Caption = "DiamondBox"
          Checked = 0
        END CONSTRUCTOR
     END TYPE
After each DIM (that is, when you create the object), the default values are initialized. Rapid-Q does not require DESTRUCTORs though, as everything is automatically cleaned up for you when your program terminates. If you're not convinced this worked, test it out:
     DIM DBox AS QDiamondBox

     ShowMessage(DBox.Caption)
If it doesn't return 'DiamondBox' then something is wrong, check your spelling, and turn $TYPECHECK ON.

10.3 Adding/Overriding Methods
In Rapid-Q, all methods, properties, and events can be overridden. In fact, you can override a method and treat it like it were a property or custom event. Once you override this method/property, you won't be able to access the inherited one (since it's hidden). To access this property or method, you must explicitly call the SUPER class as demonstrated below. Becareful if using WITH Super ... END WITH, since all properties/methods will be referenced as the super class. The concept of overriding properties or methods is simple enough, instead of using the inherited properties, we can just redefine them instead.
     TYPE QDiamondBox EXTENDS QCanvas
        Left AS STRING
        Top AS BYTE

        SUB Pset
            PRINT Super.Left
        END SUB
     END TYPE
In the above example, we've overriding 2 properties of QCanvas, and 1 method. As you'll see, QDiamondBox has a property named Left which overrides the Left property of QCanvas. To use the Left property of the super class, we just use the provided invocation Super.Left instead of QDiamondBox.Left. Overriding methods and properties have many useful purposes. Consider a filter listbox. You can override the AddItems method, and create one yourself, but filtering out certain keywords you don't want included. It's also useful when you're porting your Windows code to Linux and vice versa. This way, you can have your own "standard" component for both versions. In any event, we won't cover this topic any further. Let's now move on to creating new methods for our components:
     TYPE QDiamondBox EXTENDS QCanvas
       Caption AS STRING
       Checked AS INTEGER

       FUNCTION TextSize AS INTEGER
         Result = LEN(QDiamondBox.Caption)
         'QDiamondBox.TextSize = LEN(QDiamondBox.Caption)
       END FUNCTION
     END TYPE
The above example is a good place to start. We've just defined a new method for our QDiamondBox component. As you've noticed, we have to embed our FUNCTIONs or SUBs in our TYPE declaration. This is called INLINE code, you should be familiar with this if you've used C++ or any other OOP language. Rapid-Q requires INLINE code, you cannot define your SUB and then have the SUB sitting outside our TYPE definition. Okay, the only thing that stands out is QDiamondBox.Caption, which does what exactly? Well, you're probably wondering why we couldn't just say
      Result = LEN(Caption)
Well, this doesn't help, since in our FUNCTION, we could have easily added
      DIM Caption AS INTEGER
Then Rapid-Q would be confused... Which one should I use, the local Caption variable, or the new property one? To ease the pain, when you want to use a property, or method you must also reference them as you would normally. Our object in this case is QDiamondBox (you can also use the reserved word this), and we want to reference the property Caption. Since the above method is pretty much useless in our component, we'll just drop it from our design. What we really need is a method to draw our component, so here we go:

  SUB DrawComponent
    IF QDiamondBox.Checked THEN
      QDiamondBox.Line(QDiamondBox.Height/2,0,0,QDiamondBox.Height/2,0)
      QDiamondBox.Line(0,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,QDiamondBox.Height,QDiamondBox.Height/2,0)
      QDiamondBox.Line(QDiamondBox.Height,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Paint(QDiamondBox.Height/2, QDiamondBox.Height/2, QDiamondBox.HiLightColor, 0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,QDiamondBox.Height,QDiamondBox.Height/2,&HFFFFFF)
      QDiamondBox.Line(QDiamondBox.Height,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,&HFFFFFF)
    ELSE
      QDiamondBox.Line(QDiamondBox.Height/2,0,0,QDiamondBox.Height/2,0)
      QDiamondBox.Line(0,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,QDiamondBox.Height,QDiamondBox.Height/2,0)
      QDiamondBox.Line(QDiamondBox.Height,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Paint(QDiamondBox.Height/2, QDiamondBox.Height/2, &HBBBBBB, 0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,0,QDiamondBox.Height/2,&HFFFFFF)
      QDiamondBox.Line(0,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,&HFFFFFF)
    END IF
    QDiamondBox.TextOut(QDiamondBox.Height + 5, QDiamondBox.Height/2-QDiamondBox.Height/4, QDiamondBox.Caption, 0, -1)
  END SUB
It may look nasty, but further investigation proves it's just long lines that appear cryptic. What the above code will do is draw a diamond and properly size your component so that it looks nice whenever you resize your component. This is very important, since you don't want your component to look like a miniature when your user specified Height = 100, Width = 100, etc... Just insert the above code inside our TYPE declaration. We also need to define another property HiLightColor. Whenever our check box is checked, we probably want our component to change color to notify the user that the box has been checked.

10.4 Defining Events
It's possible to define new events for our components, but this will be covered later For now we have all we need for our QDiamondBox component, OnPaint, and OnClick. So why exactly do we need to define events? Don't we just let the user do that? Yes, but since this is our custom component, we want things to happen. For example, the QCheckBox component automatically becomes checked and unchecked when we click on it, we didn't need to write our own event handler to do that. This is that samething we want to happen for our own custom component. For starters, we'll need our OnPaint event. This event is called each time the form/component is updated.
     TYPE QDiamondBox EXTENDS QCanvas
       'Properties here

       'Our DrawComponent Method here

       EVENT OnClick
         IF QDiamondBox.Checked THEN
           QDiamondBox.Checked = 0
         ELSE
           QDiamondBox.Checked = 1
         END IF
         QDiamondBox.DrawComponent
       END EVENT

       EVENT OnPaint
         QDiamondBox.DrawComponent
       END EVENT
     END TYPE
Fairly straightforward, we've already covered why you'd reference DrawComponent like so, but the EVENT identifier is new. All that says is we're creating an EVENT handler for our component. Write your code like you would normally. Whenever we create (DIM) our new component, the events are automatically registered for us. They are called whenever that event happens. Fair enough, but what if I need to write a new event handler? In our QDiamondBox example, we're definitely going to need to redefine OnClick, since we want to know whether the user has checked or unchecked the DiamondBox. This is probably where it gets naughty. Since we don't actually want to discard our previous declaration of OnClick, we'll have to inherit it.
     DIM DBox AS QDiamondBox

     SUB NewDBoxOnClick
         DBox.InheritOnClick
         ' do you stuff here
     END SUB

     DBox.OnClick = NewDBoxOnClick
As you can see, if we wanted to inherit the OnClick event, we reference it by using QObject.Inherit<EventName> Where EventName is the event we want inherited. It's actually possible to Inherit OnPaint in our above example, but that would serve no purpose. If the Inherited event is not found (ie. there was no previous declaration of it), you will get a compiler ERROR message.

10.5 Adding components to our component (composition)
In our example, there's really no need to include components to our new QDiamondBox component, but since this topic is useful for many purposes, it's covered in this section. You can only add Rapid-Q components, not ones you've created yourself. As before, there's nothing new to the way we add components or properties:
     TYPE QGenericForm AS QForm
       Panel AS QPanel
     END TYPE

     DIM GF AS QGenericForm
         GF.Panel.Left = 123
Notice how we reference an object within an object. First period is to reference our Panel object, and the second period is to reference the Panel's properties or methods. If you wanted your panel to have some default values, you use the CONSTRUCTOR method as before:
     TYPE QGenericForm AS QForm
       Panel AS QPanel

       CONSTRUCTOR
          Panel.Parent = QGenericForm
          Panel.Width = QGenericForm.ClientWidth
          Panel.Height = QGenericForm.ClientHeight
       END CONSTRUCTOR
     END TYPE
You'll probably notice that even though we've somewhat implied that the Panel will be a part of the form, we still need to assign its Parent property, or else the panel won't show up. Simple enough, but how about defining its EVENTs? Okay, no problem:
     TYPE QGenericForm AS QForm
       Panel AS QPanel

       EVENT Panel.OnClick
         ShowMessage("User clicked on panel")
       END EVENT

       EVENT OnClick
         ShowMessage("User clicked on form")
       END EVENT
     END TYPE
Notice the extra reference (period). If you ignored that, the OnClick EVENT will be attached to your QGenericForm instead. As before, to inherit EVENTs, you'll have to do something like:
     GF.Panel.OnClick = GF.Panel.InheritOnClick
Most of the time, you never really want to access the components within a component directly. For example, you can create your own custom form, with close buttons, resize buttons etc... none of which you want to rewrite event handlers for.

10.6 Extending an empty Component
There may be cases when you don't need to extend any component, and you just want to write your own custom interface object. A good example is implementing a QIniFile interface object. Perhaps provide properties and methods to easily access and write to your own custom .INI file or however you want to do it. To do this, there is an empty object provided in Rapid-Q:
    TYPE QIniFile EXTENDS QObject
       Size AS INTEGER
       FileName AS STRING

       SUB SaveINI
       END SUB
       SUB LoadINI
       END SUB
    END TYPE
This kind of object acts like QSocket. ie. It's not a visible component, it's mainly an interface type object. Objects provide a cleaner interface, and is more elegant (well, I don't really care myself). In conclusion, this is basically all you need to know about adding your own components to Rapid-Q, it's fairly easy to grasp.

10.7 Public/Private properties and methods
All properties and methods are PUBLIC by default. Here's how you can define the scope of your properties and methods:
     TYPE QText EXTENDS QObject
       PUBLIC:
         I AS INTEGER
         X AS INTEGER

       PRIVATE:
         Y AS INTEGER

       PUBLIC:
         SUB Test
            QText.X = QText.Y + 1
         END SUB
     END TYPE
Properties I and X are PUBLIC, meaning they can be used outside their scope (ie. outside TYPE). Same with method Test. However, property Y is PRIVATE, so you can not use the property Y outside its scope. Since SUB Test is still inside the scope of Y (ie. inside TYPE), you can use it there. You can define PROTECTED properties and methods, but they act exactly like PUBLIC properties and methods, since (as of this writing) you can't extend a type of your own. For those who don't have any OOP background, the reason you have PUBLIC and PRIVATE members is mainly for your end-user's sake. Obviously you'll know what members shouldn't be used outside its scope, but by defining PRIVATE members you tell your end-users not to touch these in your program since they are used "internally."

10.8 Templates and property sets
We have yet to cover how one creates their own custom events, so we'll get to that very soon, however, there are a few more interesting techniques, one called templates which you can use in your TYPE definition, and another called property sets. We will get to property sets later in this section, but let's start with templates. A template type definition may look a bit odd, but it was more or less modelled after C++.
    TYPE NewClass<DataType> EXTENDS QOBJECT
        N AS DataType
    END TYPE
Directly after declaring the new type, you can define the template <parameters>. In the above example, our only parameter is DataType, but you are allowed infinitely many parameters. Unlike C++ though, you don't specify the type of parameter, just the name. Now when you DIM this new type, you have to pass it that one extra template parameter:
    DIM MyClass1 AS NewClass<INTEGER>
    DIM MyClass2 AS NewClass<STRING>
Notice now how this works, the property N of MyClass1 is bound to an INTEGER data type, while MyClass2 has an N property which is bound to a STRING data type. Here are some other examples:
    TYPE Arrays<DataType, Size> EXTENDS QOBJECT
        Item(Size) AS DataType

        SUB Clear
            DIM N AS DataType
            DIM I AS LONG
            DIM V AS VARIANT

            WITH Arrays
                V = .Item(0)
                IF VARTYPE(V) = 2 THEN
                    '-- String data type
                    FOR I = 0 TO Size
                        .Item(I) = ""
                    NEXT
                ELSE
                    '-- Integer/Float
                    FOR I = 0 TO Size
                        .Item(I) = 0
                    NEXT
                END IF
            END WITH
        END SUB
    END TYPE

    DIM IntArray AS ARRAYS<INTEGER, 100>
    DIM StrArray AS ARRAYS<STRING, 50>

    IntArray.Clear
    IntArray.Item(1) = 99
    StrArray.Clear
    StrArray.Item(1) = "Hello world"

    PRINT IntArray.Item(1)
    PRINT StrArray.Item(1)
The use of templates can help reduce the amount of code by reusing the same TYPE for our INTEGER and STRING arrays. Now that we've covered templates, let's move on now to property sets. A property set is just a collection of properties, with one major difference, you can do special processing when a user sets the property. We will start with a somewhat useless example
    TYPE TForm EXTENDS QFORM
        Focus AS LONG PROPERTY SET Set_Focus

        PROPERTY SET Set_Focus (Handle AS LONG)
            WITH TForm
                .Focus = Handle
                IF .Focus THEN
                    SetFocus(Handle)
                END IF
            END WITH
        END PROPERTY
    END TYPE

    CREATE Form AS TForm
        CREATE Edit AS QEDIT
        END CREATE
        Focus = Edit.Handle
    END CREATE
Nevermind the function SetFocus, it's just an API call. In the above example, Focus is a property set, whenever you assign a value to this property, it automatically calls the routine Set_Focus as outlined in the SET parameter with the parameter being the value being assigned to it. Of course, you may be wondering why you'd even need this since it's equivalent to doing this:
    TYPE TForm EXTENDS QFORM
        SUB Focus (Handle AS LONG)
            IF Handle THEN
               SetFocus(Handle)
            END IF
        END SUB
    END TYPE

    CREATE Form AS TForm
        CREATE Edit AS QEDIT
        END CREATE
        Focus(Edit.Handle)
    END CREATE
As you may notice in this example, since Focus is a SUB, you can't retrieve the value (like in our previous example). In this case, you'd have to use another name such as GetFocus to check which handle has the focus. In the previous example, we can read and write the property and perform special processing when the property is assigned, which is what we wanted. Take for example, how the BorderStyle of QFORM is changed, when we assign a new value to BorderStyle, this initiates a sequence of events, but since BorderStyle is a property set, we don't need to define a SUB to set the style and a FUNCTION to retrieve the value.
    TYPE TForm EXTENDS QFORM
        GetStyle AS LONG
        SUB BorderStyle (Style AS LONG)
            TForm.GetStyle = Style
            SendMessage(TForm.Handle, etc...)
        END SUB
    END TYPE

    CREATE Form AS TFORM
        BorderStyle(bsNone)
        Caption = STR$(Form.GetStyle)
    END CREATE
That's a real waste as you can see, so you'd probably use property sets in that case. Obviously you won't need property sets if you don't require any special processing when assigning a value to a property. If you do decide to use property sets, there are some rules to follow: 1. Property and parameter should be of the same type; 2. Only simple types and QObjects are allowed to be property sets, so this excludes arrays and UDTs. The compiler will warn you if you violate these rules, but sometimes the error messages aren't so clear.

10.9 Custom events
Custom events are triggered by the programmer, ie. you. Let's try to come up with a situation where we would need to trigger an event. Take for example the QSOCKET component. It's completely void of any events, what if we want to know when the server is ready? Obviously we can keep polling to see when this occurs, but wouldn't it be nice if it was triggered for you, and then you can write an event handler to do what you want. I won't actually write the complete example, just the necessary parts to demonstrate how to create your own custom events:
    '-- Define, but don't implement, a template function
    DECLARE SUB ServerReady_EventTemplate (Socket AS LONG)

    TYPE TSocket EXTENDS QSOCKET
        OnServerReady AS EVENT(ServerReady_EventTemplate)
        Timer1 AS QTIMER
        Sock AS LONG

        EVENT Timer1.OnTimer
            WITH TSocket
                IF .IsServerReady(.Sock) AND .OnServerReady > 0 THEN
                    '-- OnServerReady  > 0 is to check whether pointer is null
                    '-- ie. is there really an event handler assigned
                    '-- If assigned, then trigger the event
                    CALLFUNC(.OnServerReady, .Sock)
                END IF
            END WITH
        END EVENT

        CONSTRUCTOR
            OnServerReady = 0
            Timer1.Enabled = 1
            Timer1.Interval = 500
        END CONSTRUCTOR
    END TYPE

    SUB ServerReady (Sock AS LONG)
        PRINT Sock;" is ready."
    END SUB

    CREATE Socket AS QSOCKET
        OnServerReady = ServerReady
    END CREATE
It might be a good idea to go through the next chapter on Function Pointers, since this is basically how custom events work. OnServerReady is really a function pointer, which points to a SUB (if assigned, if not, it is equivalent to 0). A declaration of the template SUB is required, this is to provide CALLFUNC with the necessary parameter types, if any. It may seem a bit confusing at first, since it takes some time getting used to the syntax and the idea of triggering an event. However, creating custom events has many benefits and uses, so learning how to create your own events could greatly simplify the use of your component or even extend the functionality of others (such as the above example).

10.10 QDiamondBox Source Code Listing
$APPTYPE GUI
$TYPECHECK ON

TYPE QDiamondBox EXTENDS QCanvas     '' You can extend any QObject
  '-- New Properties, you can also add components
  Caption AS STRING
  Checked AS INTEGER
  HiLightColor AS INTEGER

  '-- There are no protected methods, but you should let the user know anyway.
  '-- PROTECTED (meaning you shouldn't directly call it in your program).
  SUB DrawComponent
    IF QDiamondBox.Checked THEN
      QDiamondBox.Line(QDiamondBox.Height/2,0,0,QDiamondBox.Height/2,0)
      QDiamondBox.Line(0,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,QDiamondBox.Height,QDiamondBox.Height/2,0)
      QDiamondBox.Line(QDiamondBox.Height,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Paint(QDiamondBox.Height/2, QDiamondBox.Height/2, QDiamondBox.HiLightColor, 0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,QDiamondBox.Height,QDiamondBox.Height/2,&HFFFFFF)
      QDiamondBox.Line(QDiamondBox.Height,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,&HFFFFFF)
    ELSE
      QDiamondBox.Line(QDiamondBox.Height/2,0,0,QDiamondBox.Height/2,0)
      QDiamondBox.Line(0,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,QDiamondBox.Height,QDiamondBox.Height/2,0)
      QDiamondBox.Line(QDiamondBox.Height,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,0)
      QDiamondBox.Paint(QDiamondBox.Height/2, QDiamondBox.Height/2, &HBBBBBB, 0)
      QDiamondBox.Line(QDiamondBox.Height/2,0,0,QDiamondBox.Height/2,&HFFFFFF)
      QDiamondBox.Line(0,QDiamondBox.Height/2,QDiamondBox.Height/2,QDiamondBox.Height,&HFFFFFF)
    END IF
    QDiamondBox.TextOut(QDiamondBox.Height + 5, QDiamondBox.Height/2-QDiamondBox.Height/4, QDiamondBox.Caption, 0, -1)
  END SUB

  '-- Inherited Events (sorry, can't create any new events)
  '-- The user can still override these events, but it's not a good idea.
  EVENT OnClick
    IF QDiamondBox.Checked THEN
      QDiamondBox.Checked = 0
    ELSE
      QDiamondBox.Checked = 1
    END IF
    QDiamondBox.DrawComponent
  END EVENT

  EVENT OnPaint
    QDiamondBox.DrawComponent
  END EVENT

  '-- Default values
  CONSTRUCTOR
    Height = 30
    Width = 100
    HiLightColor = &H00FF00
    Caption = "DiamondBox"
    Checked = 0
  END CONSTRUCTOR
END TYPE

'----- Test our new component

DECLARE SUB DBox2Click

DIM Font AS QFont
    Font.Name = "Arial"
    Font.Size = 10

CREATE Form AS QForm
  Center
  Height = 120
  Caption = "Custom Check Boxes"
  CREATE DBox1 AS QDiamondBox
    Caption = "Diamond Box 1"
    Left = 100
    Height = 20
  END CREATE
  CREATE DBox2 AS QDiamondBox
    Caption = "Diamond Box 2"
    Top = 30
    Left = 100
    Height = 20
    Width = 140
    HiLightColor = &H0000FF
    Font = Font
    ShowHint = 1 ' True
    Hint = "Click me"
    OnClick = DBox2Click
  END CREATE
  CREATE DBox3 AS QDiamondBox
    Caption = "Diamond Box 3"
    Top = 60
    Left = 100
    Height = 20
  END CREATE
  ShowModal
END CREATE

SUB DBox2Click
  DBox2.InheritOnClick    '' Inherit event
  ShowMessage("Diamond Box 2 clicked")
END SUB


11: Using function pointers

Rapid-Q Documentation by William Yu (c)1999 Chapter 11

11. Using Function Pointers

Didn't think you'd see function pointers in a BASIC programming language did you? Well, in Rapid-Q function pointers are a bit different from what most people are used to. There are a few oddities I guess, but most of the important features are there, like redefining function pointers, and dynamic function pointers. Unfortunately (as of this writing), you can't pass function pointers as arguments.

11.1 Introduction to the concept
Great, so what are function pointers? I know a lot people are tired of terminology, only because the definition is probably a lot easier to understand/grasp. It helps to understand how things are stored in memory and addressed. For example, a function (ie. SUB or FUNCTION) occupies space in some address space somewhere. A pointer to that function is just the address of it. So if I know the address of the function, I can jump into that "process space" and execute the code within. This is the low level way of thinking, first push the parameters, and then jump to (ie. CALL) the function. So if pointers are only numbers, how do we find the address of the function? This is the question that will be considered next.

11.2 Defining function pointers
If you have prior experience with function pointers (ie. in C) there are a few differences you'll have to get accustomed to. In Rapid-Q, since function pointers are just numbers, you can use any valid numeric datatype to define your function pointers. Seems odd, yes, but pointers are only numbers. Try avoiding BYTE, since the address of your function may be greater than 255, using BYTE may not be large enough. I suggest sticking with INTEGER/LONG.
    DECLARE SUB Test (I AS INTEGER)

    DIM FPtr AS INTEGER

    BIND FPtr TO Test
Well, we use BIND in Rapid-Q to bind our variable FPtr to the function Test. This will do 2 things, obviously FPtr will point to the address space of Test, but it also binds the number of parameters to FPtr, this is important for the compiler so that it knows how many parameters to pass/accept. To call our function, we have to use the reserved word CALLFUNC:
    CALLFUNC(FPtr, 120)
This calls our SUB Test with 1 parameter. Obviously this isn't a very useful example, so consider when it is useful...
    DECLARE SUB Test1 (I AS INTEGER)
    DECLARE SUB Test2 (I AS INTEGER)

    DIM FPtr(1 TO 2) AS INTEGER

    BIND FPtr(1) TO Test1
    BIND FPtr(2) TO Test2
When you're binding arrays, please note that the first function that is bound will be the TEMPLATE for all your other elements. Confusing? Okay, let me put this into words people can understand. :) Our array is FPtr, our BIND bounds FPtr(1) to SUB Test1. FPtr is now BOUND. What this means is that if you BIND any other FPtr(i), the function MUST HAVE MATCHING NUMBER OF PARAMETERS. Maybe an example would help:
    DECLARE SUB Test1 (I AS INTEGER)
    DECLARE SUB Test2 (I AS INTEGER, J AS STRING)

    DIM FPtr(1 TO 2) AS INTEGER

    BIND FPtr(1) TO Test1
    BIND FPtr(2) TO Test2
The second BIND is incorrect, since Test2 does not have matching parameters with Test1. You will receive an error message if you do this. Notice that I say matching NUMBER of parameters, you really don't need matching TYPE parameters. Don't do this though, results may vary.

11.3 Using function pointers properly
It will be clear (once you've used function pointers for a while) that there are times when using function pointers is necessary, and times when they're not. I think every situation is different, but consider this situation:
     SELECT CASE I
       CASE 1
         Process1("1", 44)
       CASE 2
         Process2("2", 55)
       CASE 3
         Process3("3", 66)
       CASE 4
         :
         :
      etc...
You can generalize this situation, for example, a menu with several options, or perhaps a parser (yes Rapid-Q does use function pointers to parse your code). As you may notice, that's a lot of comparisons, especially if you're writing a parser where there's so many keywords (over 50 say). We can easily eliminate these comparisons by using function pointers, consequently speeding up your program. See FUNCPTR.BAS for a concrete example.
     BIND FPtr(1) AS Process1
     BIND FPtr(2) AS Process2
     BIND FPtr(3) AS Process3
     BIND FPtr(4) AS Process4
     BIND FPtr(5) AS Process5
     BIND FPtr(6) AS Process6
     BIND FPtr(7) AS Process7

     x = VAL(INPUT$(1))
     CALLFUNC(FPtr(x), 33)
None of the code you see above is executable as is, but I think you get the general idea. We don't need any case statements as you can see (this is assuming you've partitioned your function pointers properly).

11.4 What is not supported in Rapid-Q
Function pointers as arguments is not supported. As funny as that sounds, this is actually very useful. Unfortunately I didn't get a chance to implement this (yet). You can pass the function pointer value as an argument, but as you can see, you won't be able to call your function. The only way would be to define a global function pointer as your template, and then assign that to your argument. It's easier to see with an example:
     DECLARE FUNCTION MyFuncTemp (X AS LONG) AS LONG
     DECLARE FUNCTION Func1 (X AS LONG) AS LONG
     DECLARE FUNCTION Func2 (X AS LONG) AS LONG

     DIM Template AS INTEGER
     DIM I(100) AS INTEGER

     BIND Template TO MyFuncTemp
     BIND I(1) TO Func1
     BIND I(2) TO Func2

     SUB Test (FPtr AS INTEGER)
        Template = FPtr
        PRINT CALLFUNC(Template, 10)
     END SUB

     Test I(1)
That's about the only way you can work around this limitation.


 12: Graphics under Windows
Rapid-Q Documentation by William Yu (c)1999 Chapter 12

12. Graphics under Windows

Most of the information contained in this chapter will not apply to the Linux/Unix version, except for the first few sections. If you're a DOS programmer converting your skills to Windows, there are some differences in the way you display graphics, mostly introduced by the concept of events and the multi-tasking nature of Windows.

12.1 Graphics under DOS versus Windows
If you're familiar with DOS programming and not so familiar with Windows programming, you'll probably notice some major differences in the nature of Graphics programming under the two OSes. Under DOS it's much simpler since you don't have to worry about other "programs" interrupting your program. This means what you display/draw on the screen won't erase itself magically, you only worry about what to draw next. However, there is a slight difference under Windows. Although it's perfectly safe to draw on your form, it has several consequences. The most obvious is that another program may "interrupt" the execution/display of your program. Think about minimizing the form or have it hidden under another window. How will Windows know what to redraw once your program gains refocus? You would think that Windows is smart enough to redraw the part that was hidden, but unfortunately we're not that lucky. Your program must tell Windows what to redraw. Windows will tell you that your form requires redrawing by sending messages to your form. In particular, the OnPaint (WM_PAINT) message is sent to the window which requires repainting. It is then your responsibility to provide an OnPaint procedure to your component/form that requires it.

12.2 What components require painting?
All visible components actually, but fortunately most of the work is done by Windows. For example, there's no need to provide an OnPaint method for the QButton class since it's already implemented for you. You can of course write your own Button class as you may have learned in Chapter 10, in which case you'll be writing the OnPaint method for the user. The QForm and QCanvas components are the two most obvious candidates to do graphics on. You can think of QCanvas as your basic DOS graphics screen, what you want drawn should be written inside the OnPaint procedure:
    DECLARE SUB CanvasPaint (Sender AS QCanvas)

    CREATE Form AS QForm
        CREATE Canvas AS QCanvas
            OnPaint = CanvasPaint
        END CREATE
        ShowModal
    END CREATE

    SUB CanvasPaint (Sender AS QCanvas)
        Sender.FillRect(10,10,100,100,&HFF0000)      '-- Blue box
    END SUB
If you try hiding the form under another Window and then refocus the program, the blue box will still appear. Now try writing something that doesn't utilize the OnPaint procedure:
    CREATE Form AS QForm
        CREATE Canvas AS QCanvas
            FillRect(10,10,100,100,&HFF0000)      '-- Blue box
        END CREATE
        Form.ShowModal
    END CREATE
Notice anything? Exactly, there is no blue box. The paint message was sent when your form first appears on your desktop, and since you didn't write any OnPaint procedure, there's nothing to draw. So what really happens to that FillRect code? Nothing really, it's still executed, but the next paint message offset it. To understand this better, try this code which will display the blue box when your press the button, but try hiding the window again or minimizing it. Redisplay your window and see what happens:
    DECLARE SUB ButtonClick

    CREATE Form AS QForm
        CREATE Button AS QButton
          OnClick = ButtonClick
        END CREATE
        CREATE Canvas AS QCanvas
        END CREATE
        ShowModal
    END CREATE

    SUB ButtonClick
        Canvas.FillRect(10,10,100,100,&HFF0000)
    END SUB
When you click your button the blue box will be drawn, however, once you hide part of the window and redisplay your window, you'll probably notice that your blue box has dissappeared.

12.3 Drawing graphics dynamically
As you may have already noticed, if all your graphics are contained in your OnPaint procedure, how do you draw on it dynamically without it erasing itself magically? For this purpose, you'll have to draw on an off-screen graphics bitmap and then in your OnPaint procedure, you just use the Draw method to display the graphic. You can use the QBITMAP component as your off-screen graphics page. Here's some sample code for you to test:

DECLARE SUB CanvasPaint (Sender AS QCanvas)
DECLARE SUB ButtonClick (Sender AS QButton)

' Create bitmap for off-screen use
DIM BitMap AS QBITMAP
    BitMap.Height = 100
    BitMap.Width = 100
    BitMap.Paint(0,0,0,0)

CREATE Form AS QForm
    Center
    Caption = "Simple graphics demonstration"
    CREATE Canvas AS QCanvas
        OnPaint = CanvasPaint
    END CREATE
    CREATE SquareButton AS QButton
        Caption = "Draw Square"
        OnClick = ButtonClick
        Left = 150
    END CREATE
    CREATE CircleButton AS QButton
        Caption = "Draw Circle"
        OnClick = ButtonClick
        Left = 150
        Top = 50
    END CREATE
    CREATE LineButton AS QButton
        Caption = "Draw Line"
        OnClick = ButtonClick
        Left = 150
        Top = 100
    END CREATE
    ShowModal
END CREATE

SUB CanvasPaint (Sender AS QCanvas)
    Sender.Draw(0,0,Bitmap.BMP)
END SUB

SUB ButtonClick (Sender AS QButton)
    SELECT CASE Sender.Caption
        CASE "Draw Square"
            Bitmap.FillRect(10,10,50,50,&HFF0000)
        CASE "Draw Circle"
            Bitmap.Circle(10,60,50,110,&H0000FF,&H0000FF)
        CASE "Draw Line"
            Bitmap.Line(50,50,90,90,&H00FF00)
    END SELECT
    Canvas.Repaint       '-- Tell Canvas to repaint itself.
END SUB
Sample Output:
Output

Code Details:
Much of the code is self explanatory. The first bit of code creates and initializes the Bitmap component. Since QBitmap is a non-visible component, it does not receive paint messages, so anything you draw on the Bitmap will stay. Now that we have our Bitmap ready, our OnPaint procedure for QCanvas can use the Draw method to paint the Bitmap onto the Canvas. This is what you call double buffering, a similar technique is utilized in DirectX.

12.4 Ownerdraw List and Combo Boxes (including QStringGrid)
Ownerdrawn ListBoxes and ComboBoxes allow you to override the default paint method somewhat. It doesn't really let you redraw the entire interface of a list or combo box, since that's probably not what you want anyway. What it does allow you to do is override the paint method for the data. So instead of just displaying the text fields in your list or combo boxes, you can actually draw pictures in them and/or change the font/color for each individual item. There are 2 types of ownerdraw list/combo boxes.
  • 1. OwnerDrawFixed
  • 2. OwnerDrawVariable
A fixed ownerdrawn list/combo box means that all your items will have a fixed predetermined height. So let's consider the case where one of your pictures is 100 pixels high and another which is only 10 pixels high. If you specify an ItemHeight of say 10, the 100 pixel high picture will actually overlap some of your items since it doesn't have enough room for itself (this can be avoided if you use CopyRect instead of Draw). But in any event, it would have been much better to create variable sized item fields, so you'd use OwnerDrawVariable instead. The only problem with OwnerDrawVariable list/combo boxes is that it requires the programmer to specify the height of each item, it doesn't automatically calculate this field for you. In most cases this isn't that big of a problem, but nonetheless you'll have to store this extra information for each field. How you do this is entirely up to you. To see a working example of ownerdrawn list/combo boxes, look at LISTBOX.BAS included in EXAMPLES.ZIP. You can rewrite the code to work with ComboBoxes. You may notice that you don't implement any OnPaint event, but an OnDrawItem event.

Code Details:
  SUB ListBoxDrawItem(Index AS INTEGER, State AS BYTE, Rect AS QRECT)
    IF State = 0 THEN
      '-- Selected
      ListBox.FillRect(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom, &H00FF00)
    ELSE
      ListBox.FillRect(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom, &HFFFFFF)
    END IF
    ListBox.TextOut(100, Rect.Top+(Rect.Bottom-Rect.Top)/4, ListBox.Item(index), 0, -1)
    ListBox.Draw(Rect.Left, Rect.Top, Bitmap(Index).BMP)
  END SUB
Hopefully the code is self explanatory, but a few things you may notice is that you don't paint the entire listbox (ie. all items), but rather a paint message is sent everytime an item is changed. This item occupies a rectangular region in your listbox, so what the OnDrawItem sends to you is the region of this item (this is the Rect parameter). You should not overstep this bound that has been given to you (ie. don't try to draw outside this region, it's not yours to draw on!). I have not covered QStringGrid in this section, but the same idea persists. You'll have to implement the OnDrawCell event, which is similar to the way you handle OnDrawItem in list/combo boxes.

12.5 Using DirectX
Why is DirectX so popular? This question can be summed up quite frankly without going into much detail. It's faster than Windows GDI (and OpenGL in most cases), it supports most graphics cards, it's free to use, and it provides a lot of the most necessary graphics commands that programmers are looking for without implementing it themselves. Not to mention that it's widely supported and (to some people) easy to use. As you may note, this is not my general opinion about DirectX, but the general public opinion.
Does everyone have DirectX installed? In most cases, yes, it depends what version though. Not everyone will have the latest version, but that usually doesn't matter. DirectX for Rapid-Q only requires v5.0 and may even work for version v3.0 and up (untested). Rapid-Q does not yet support all the features of DirectX, like joystick or 3D programming.
To use DirectX under Rapid-Q, you'll have to know 2 things.
  • 1. All drawing is done on the off-screen page
  • 2. You need to FLIP to this page everytime you want it displayed
In essence, you can think of this off-screen page as already implemented for you (like in the above example where we had to use QBitmap as our off-screen page). You can think of the FLIP operation as a repaint operation just like in the above example. After you understand these 2 concepts, everything else is basically the same. You draw on the DirectX Screen like you would a QCanvas or QBitmap, then FLIP pages when you're ready to display your graphics. It is easier to look at some examples rather than for me to explain it. There is however, one more important topic, that is QDXTimer.
QDXTimer is a specialized timer specifically for DirectX, it provides slightly better precision than QTimer, and controls the frame rate so that your program doesn't run too fast. It may decrease your frame rate if your program is running too fast, but can't do much if your program is chugging along at 5 or 6 frames per second. Please use QDXTimer instead of the standard Windows timer QTimer when animating graphics in DirectX (not necessary but recommended).


13: Direct3D for Rapid-Q

Rapid-Q Documentation by William Yu (c)1999, Appended by John Kelly Chapter 13

13. Direct3D for Rapid-Q

Direct3D is a COM interface programming for Windows only that uses a windows API called Direct 3D Retained mode - or D3DRM. It came from the DelphiX project. It is unfinished in RapidQ but is still very functional. For some impressive examples of 3D graphics in RapidQ see the DEAengine demo. Direct 3D retained mode ( D3DRM) appeared with the earliest DirectX and stopped with DirectX7. It is slower than the DirectX8 + Immediate mode but much easier to program. D3DRM is high level programming in which 3D objects are put on "Frames", even a "camera" has its own Frame. In immediate mode, you have to calculate the geometry of the objects and continually render them like Open GL. Documentation on Direct 3D Retained mode is still available on Microsoft Development (MSDN) or older Windows API guides. Also try other locations
http://community.borland.com/soapbox/techvoyage/article/1,1795,10514,00.html#SpanBase5

13.1 Requirement specifications

The most basic requirement is that you have the DirectX 6.0 runtimes. If you're unsure what version you have, type DXDIAG at the command prompt, or find the file under C:\WINDOWS\SYSTEM. If you don't have DXDIAG then you'll definitely need to upgrade. You can download the runtime files at http://msdn.microsoft.com/directx/
Just the runtime files, you don't need the SDK, but if you want, no one is stopping you from downloading it. The SDK does contain an important file CONV3DS.EXE which is necessary to convert different 3D models for use with your programs. However, I have posted a link to this file so it's not necessary for you download the entire SDK just for that one file.

Other nice things to have:
  • 3D accelerated video card
  • A 3D modeler (like 3D Studio)
  • OpenGL (some 3D modelers use this)
Even if you don't have any of the above, this shouldn't matter. A 3D card is not necessary, but you'll find that running your programs can be 5 to 10 times slower, but still manageable if you have a good Pentium. I don't have a 3D card, and only get about 5-10 fps on my P200, but it doesn't bother me. If you don't have a 3D modeling program don't worry, there's some free 3D modelers on the internet. I find that Anim8or is pretty good, for something that's completely free there's nothing to complain about. It's only a 500KB download, which is very small compared to other 3D modeling programs I've seen. It does require OpenGL, but check your C:\WINDOWS\SYSTEM directory for OPENGL32.DLL. If you have it, you're in good shape, if not, just download it off the web at http://www.opengl.org/

Nice links to have:
OpenFX possibly the most advanced free 3D modeler available
www.delgine.com deled 3d tool for creating .x models and files.
Anim8or homepage good 3D modeler
DOGA Homepage another good free 3D modeler
CONV3DS.EXE converts .3DS files to .X files
3DCafe.com thousands of free 3D models available
Microsoft's DirectX homepage learn more, download their SDK documentation
http://www.3dengines.net/ for Potential 3-D engines or
http://cg.cs.tu-berlin.de/~ki/engines.html
http://www.aibots.myhost24.com/links/3d%20Engines.html
 http://www.basic4gl.net/ Basic4GL by Tom Mulgrew, basic development for open GL.
 http://www.blitzbasic.com/ Blitz Basic(impressive and simple!)
http://darkbasic.thegamecreators.com/
http://www.geocities.com/SiliconValley/Way/7233/index.html 'some 3d visual Basic code

13.2 Using Anim8or to create 3D models

If you already have a good understanding of how to create 3D models, you can skip this section. I will be using Anim8or to demonstrate simple 3D modeling which you can quickly use in your Rapid-Q programs. If you haven't already downloaded Anim8or's HTML documentation, I suggest you do that. I won't cover all there is to know about Anim8or, just the basics.

    Step by step introduction
  • Load Anim8or
  • Click on a polygon object
  • To draw this object, just click and drag your mouse on the main grid
  • Make sure to also center the object (not necessary but a good thing anyway). To do this, just select the object you want centered, then select from the menu: Edit|Locate|Center about origin
  • Make sure you haven't drawn an overly big polygon, perhaps the size of your pinky is good enough.
  • Now to export your object, select from the menu: Object|Export Just make sure to save as a .3DS file.
  • Let's just say you named your file poly.3ds then from the command prompt type in:
       CONV3DS -m poly.3ds
    I assumed you downloaded CONV3DS.EXE (copy this to your Windows directory if you want).
  • Once converted, you should have a poly.x file, this object file can now be used in your Rapid-Q program!
If you don't like doing your own 3D models you can always download pre-made 3D models from www.3dcafe.com and other websites like it. However, it's always nice to customize your objects, so learning to use a 3D modeling program wouldn't hurt. The optional parameter -m is used to create a single mesh for use with MeshBuilder. Without -m, your .X file is saved as a frame so you would have to use QD3DFrame to load your .X file.

13.3 Loading/Using .X Files
Simply loading an .X file is easy enough, to make sure you have this much working, copy and paste this code:
' Simply places an object on the scene

$TYPECHECK ON

CONST alClient = 5

'-- Light Types
CONST D3DRMLIGHT_AMBIENT = 0
CONST D3DRMLIGHT_POINT = 1
CONST D3DRMLIGHT_SPOT = 2
CONST D3DRMLIGHT_DIRECTIONAL = 3
CONST D3DRMLIGHT_PARALLELPOINT = 4

DECLARE SUB DXInitialize(Sender AS QDXScreen)
DECLARE SUB DXTimerExpired

DIM DXTimer AS QDXTimer
    DXTimer.Enabled = 1
    DXTimer.Interval = 0
    DXTimer.Activeonly = 0
    DXTimer.OnTimer = DXTimerExpired

CREATE Form AS QForm
    Caption = "Direct 3D Example"
    Center
    CREATE DXScreen AS QDXScreen
        Init(320,240)
        Align = alClient
        Use3D = 1
        UseHardware = 0        '' This is for non-3D accelerated video cards.
                               '' 3D will be emulated using software, which
                               '' is much slower.
        OnInitialize = DXInitialize
    END CREATE
    ShowModal
END CREATE

SUB DXInitialize(Sender AS QDXScreen)
   DIM Light AS QD3DLight
   DIM LightFrame AS QD3DFrame, MeshFrame AS QD3DFrame
   DIM MeshBuilder AS QD3DMeshBuilder

   DXScreen.CreateFrame(LightFrame)
   DXScreen.CreateFrame(MeshFrame)

   '-- Need light, else object would be completely hidden
   DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, Light)
   LightFrame.AddLight(Light)

   DXScreen.SetCameraPosition(-5, 10, 0)
   DXScreen.SetCameraOrientation(0.35, -0.65, 1.0, -0.15, 1.0, 0.5)

   MeshFrame.SetPosition(0, 0, 15)
   MeshFrame.SetOrientation(0, 0, 1, 0, 1, 0)
   MeshFrame.SetRotation(0, 0, 0, 0.05)     '-- Angle of rotation = 0.05

   DXScreen.CreateMeshBuilder(MeshBuilder)  '-- Create object

   MeshBuilder.Load("poly.x")               '-- Load your object
   MeshFrame.AddVisual(MeshBuilder)         '-- Add object to frame
END SUB

SUB DXTimerExpired
   DXScreen.ForceUpdate(0,0,50,50)   '-- Updates FPS Text
   DXScreen.Render
   DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
   DXScreen.Flip
END SUB
If everything worked, you should obtain some output that looks like this:
If you understood the example, it's quite easy to add more objects to the scene, just create another MeshFrame and load another object file. Play around with the code until you're satisfied.

13.4 Wrapping textures around an object
Now that we have the basics, time to wrap textures around our object. To do this, all we need is a .BMP file for our texture. There's a few important points to note, First, width and height of bitmap must be equal, and secondly, they must be powers of 2 (ie. 32x32, 256x256, etc.). This is obviously for optimization reasons, but don't ask me, I didn't create Direct3D. Anyway, to wrap this texture around our object, we just need to modify the above code a bit (changes are noted in Blue):
' Wrap textures around 3D object

$TYPECHECK ON

CONST alClient = 5

'-- Light Types
CONST D3DRMLIGHT_AMBIENT = 0
CONST D3DRMLIGHT_POINT = 1
CONST D3DRMLIGHT_SPOT = 2
CONST D3DRMLIGHT_DIRECTIONAL = 3
CONST D3DRMLIGHT_PARALLELPOINT = 4

'-- Wrap Types
CONST D3DRMWRAP_FLAT = 0
CONST D3DRMWRAP_CYLINDER = 1
CONST D3DRMWRAP_SPHERE = 2
CONST D3DRMWRAP_CHROME = 3
CONST D3DRMWRAP_SHEET = 4
CONST D3DRMWRAP_BOX = 5

CONST WrapType = D3DRMWRAP_SPHERE     '-- You can modify this

DECLARE SUB DXInitialize(Sender AS QDXScreen)
DECLARE SUB DXTimerExpired

DIM DXTimer AS QDXTimer
    DXTimer.Enabled = 1
    DXTimer.Interval = 0
    DXTimer.Activeonly = 0
    DXTimer.OnTimer = DXTimerExpired

CREATE Form AS QForm
    Caption = "Direct 3D Example"
    Center
    CREATE DXScreen AS QDXScreen
        Init(320,240)
        Align = alClient
        Use3D = 1
        UseHardware = 0        '' This is for non-3D accelerated video cards.
                               '' 3D will be emulated using software, which
                               '' is much slower.
        OnInitialize = DXInitialize
    END CREATE
    ShowModal
END CREATE

SUB DXInitialize(Sender AS QDXScreen)
   DIM Light AS QD3DLight
   DIM LightFrame AS QD3DFrame, MeshFrame AS QD3DFrame
   DIM MeshBuilder AS QD3DMeshBuilder
   DIM Texture AS QD3DTexture
   DIM Wrap AS QD3DWrap
   DIM Mesh AS QD3DMesh

   DXScreen.CreateFrame(LightFrame)
   DXScreen.CreateFrame(MeshFrame)

   DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, Light)
   LightFrame.AddLight(Light)

   DXScreen.SetCameraPosition(-5, 10, 0)
   DXScreen.SetCameraOrientation(0.35, -0.65, 1.0, -0.15, 1.0, 0.5)

   MeshFrame.SetPosition(0, 0, 15)
   MeshFrame.SetOrientation(0, 0, 1, 0, 1, 0)
   MeshFrame.SetRotation(0, 0, 0, 0.05)       ' Angle of rotation = 0.05

   DXScreen.CreateMeshBuilder(MeshBuilder)

   MeshBuilder.Load("poly.x")            '-- Egg object

   MeshBuilder.LoadTexture("back.bmp")   '-- New lines
   MeshBuilder.CreateMesh(Mesh)

   MeshFrame.AddVisual(Mesh)

   DXScreen.CreateWrap(WrapType, 0,0,0, 0,0,1, 0,1,0, 0,0, 1,1, Wrap)
   Wrap.Apply(Mesh)

END SUB

SUB DXTimerExpired
   DXScreen.ForceUpdate(0,0,50,50)
   DXScreen.Render
   DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
   DXScreen.Flip
END SUB
Again, if everything worked, you should obtain some output that looks like this (depending on what texture file you used of course):

As you can see, it doesn't take much to add textures to our objects. The only problem is you lose a few frame rates by doing this.

13.5 Rotating/Moving objects
Unfortunately as of this writing, there is no support for Animation sets, but that will be worked on later. You can do simple rotations and scene movements just by calling the method Move or manually setting the camera angles and positions. Using the example from above, add this extra code:
   DXScreen.ForceUpdate(0,0,50,50)
   DXScreen.Move(1)            '-- Add this line
   DXScreen.Render
This moves the camera position by the amount specified. The affect is a rotation about angle Theta. This Theta was specified on the line:
   MeshFrame.SetRotation(0, 0, 0, 0.05)       ' Angle of rotation = 0.05
DXScreen.Move animates the entire scene, to just animate a certain frame, you can use MeshFrame.Move(1).


14: Programming in MySQL

Rapid-Q Documentation by William Yu (c)1999 Chapter 14

14. Programming in MySQL

This chapter is a quick overview of what you can do with the QMYSQL component. It does not teach you about SQL or how to construct proper queries. It is assumed you have some prior knowledge of SQL, but not necessarily with MySQL.

14.1 Quick Introduction
MySQL is basically free for Unix and OS/2 platforms, but Rapid-Q only supports MySQL for Linux and Windows since my resources are limited to such machines. Under Windows, if you like MySQL, then you are required to pay a license fee after a 30 day trial period. Not to be confused with paying me of course, but if you want, I'll oblige. Why did I choose MySQL over other database servers? The reason is fairly simple, yet deserves some explanation anyway. MySQL is free, mostly, and it's multiplatform, which fits into Rapid-Q quite nicely. It's also easier for me to test, and quite simple to implement under Rapid-Q. It's fairly lightweight, fast, robust, and did I mention free? Perhaps in the future, other database servers will be supported, ie. through MyODBC or Window's ODBC.
    Required files:
  • MySQL server version 3.22.xx or better
  • Rapid-Q MySQL Libraries
  • MySQL Client if you don't want to run a server
After installing the MySQL server, test it to make sure it works (read their nice documentation and help files), you'll also need to copy LIBMYSQL.DLL (under Windows) and libmysqlclient.* (under Linux) to your library path directory. C:\WINDOWS\SYSTEM under Windows, and maybe /usr/lib under Linux (you can also just add a library path to the file instead of moving it). These library files are required by Rapid-Q, they should have come with your MySQL distribution, probably in C:\MYSQL\LIB and /usr/local/lib/mysql depending on your installation. If you already have MySQL installed, which is possible, make sure it's up to date, or if you have an SQL Administrator, check with the that person.

14.2 Connecting to MySQL
The introduction assumed that you wanted to install a MySQL server on your machine, but you can access a MySQL database from anywhere, as long as you have access of course. If you don't want to install a MySQL server (why wouldn't you?) then make sure you have the proper client libraries, ie. LIBMYSQL.DLL. To begin with, I'll assume you have the MySQL server installed. To connect to your local MySQL server is simple enough:
            DIM MySQL AS QMYSQL

            Host$ = ""
            User$ = ""
            Password$ = ""
            MySQL.Connect(Host$, User$, Password$)

            IF MySQL.Connected THEN PRINT "Successfully connected"
Change User$ and Password$ to suit your needs. Host$ can also take the value of "localhost" but is not necessary in this case. Now to connect to a remote MySQL server located, say, in allsql.com
            DIM MySQL AS QMYSQL

            Host$ = "allsql.com"
            User$ = "anonymous"
            Password$ = "guest"
            MySQL.Connect(Host$, User$, Password$)

            IF MySQL.Connected THEN PRINT "Successfully connected"
Most servers will use the standard MySQL port 3306, but if you know the exact port, then you can use the method RealConnect.
            DIM MySQL AS QMYSQL

            Host$ = "allsql.com"
            User$ = "anonymous"
            Password$ = "guest"
            Port% = 12345
            MySQL.RealConnect(Host$, User$, Password$, "", Port%, "", 0)

            IF MySQL.Connected THEN PRINT "Successfully connected"
See appendix section for the parameters of QMYSQL.RealConnect. It is suggested by the MySQL documentation that you use RealConnect instead of the using Connect.

14.3 How to perform queries and obtain the results
Write your queries like you would normally, for example, if you want to select everything from a certain table, say you have a table named user, then you can do this:
            DIM MySQL AS QMYSQL

            '' First connect to server

            '' Use database
            MySQL.SelectDB("mysql")

            '' Perform query
            MySQL.Query("select * from user")
The result of this query is stored internally, and sequentially. To obtain the result, you'll need to Fetch it. You can visualize a 2 dimensional table:
Since the result is stored sequentially, you have to fetch each row one at a time (not necessarily true, but assume we have no other choice). To do this is quite simple:
            WHILE MySQL.FetchRow       '' Get next row
                MySQL.FieldSeek(0)     '' Reset field position
                FOR I = 0 TO MySQL.FieldCount-1
                    PRINT MySQL.Row(I) '' Read current row element I
                NEXT
            WEND
MySQL.FetchRow fetches the next row. As long as there are still rows available to fetch, MySQL.FetchRow returns TRUE (non-zero number). MySQL.FieldCount is used to count how many fields per row there are in the current table. The rest is self explanatory.

14.4 Interfacing QMYSQL with QSTRINGGRID
As you may notice, it would be nice if the results could just be preloaded into a string grid instead of having to fetch everything and doing it manually. Unfortunately I haven't got any motivation to do this right now, but you can use this simple code until I get off my butt and implement it internally:
            SUB ExecuteQuery(MySQL AS QMYSQL, Grid AS QSTRINGGRID, Query AS STRING)
                IF MySQL.Query(Query) = 0 THEN
                   '' Failed to execute
                   EXIT SUB
                END IF

                DEFINT I = 0, J

                ''-- Write header
                Grid.ColCount = MySQL.FieldCount
                WHILE MySQL.FetchField
                   Grid.Cell(I,0) = MySQL.Field.Name
                   I++
                WEND

                Grid.RowCount = MySQL.RowCount+1
                J = 1
                WHILE MySQL.FetchRow       '' Get next row
                   MySQL.FieldSeek(0)      '' Reset field position
                   FOR I = 0 TO MySQL.FieldCount-1
                      Grid.Cell(I,J) = MySQL.Row(I)
                   NEXT
                   J++
               WEND
            END SUB

            ''-- Example
            ExecuteQuery(MySQL, MyGrid, "select * from user")
Obviously, you can interface QMYSQL with any component, or components, you want.

14.5 Storing and retrieving blobs
Blobs are just binary data that require special processing. Since blobs can contain NULL characters and other special characters that affect MySQL and Rapid-Q, you'll need to do some special processing with your binary data. Please note that blob sizes vary, depending on the field type. A BLOB, by default can hold up to 65535 bytes (a LONGBLOB should be able to handle 2^32-1 bytes). If you want to change the buffer size, you'll have to read up on it (max_allowed_packet). To store binary data, like images, you'll have to preprocess certain characters before you can send it over to your MySQL database.
            $INCLUDE "RAPIDQ.INC"

            DIM MySQL AS QMYSQL

            ''-- Connect to database code, etc...

            DIM File AS QFILESTREAM
            File.Open("test.bmp", fmOpenRead)

            ''-- Read file as binary, preserves NULL chars
            Buffer$ = File.ReadBinStr(File.Size)

            ''-- Here's the special processing
            ''-- Converts NULLs to \0 and others
            ProcessedBuffer$ = MySQL.EscapeString(Buffer$, File.Size)

            ''-- Insert blob in our table
            MySQL.Query("insert into MyImageTable values('Label 1', '" + _
                        ProcessedBuffer$ + "')")

            File.Close
            MySQL.Close
Since we're dealing with binary data, you have to be aware that we don't use LEN() or any other STRING processing functions with our binary data. Note that we can store text data in blob fields, in which case you can use any STRING processing functions you want. You may notice that MySQL.EscapeString converts the binary data to a usable format that can be passed to the MySQL database. Basically all it does is convert NULLs to '\0', ' to \', " to \", and CRLF to \r and \n respectively. Once parsed, the new string is returned which you can use in a query. So far so good, now we consider retrieving our blobs:
            $INCLUDE "RAPIDQ.INC"
            $INCLUDE "MYSQL.INC"

            DIM MySQL AS QMYSQL

            ''-- Connect to database code, etc...

            DIM File AS QFILESTREAM
            File.Open("out.bmp", fmCreate) ''-- Create new file

            ''-- Your query here
            MySQL.Query("select * from MyImageTable")

            WHILE MySQL.FetchRow
                MySQL.FieldSeek(0)
                MySQL.FetchLengths ''-- Required for binary data
                FOR I = 0 TO MySQL.NumField-1
                    MySQL.FetchField
                    IF MySQL.Field.Type = FIELD_TYPE_BLOB THEN
                        ''-- Read binary data from table
                        Buffer$ = MySQL.RowBlob(I, MySQL.Length(I))
                        File.WriteBinStr(Buffer$, MySQL.Length(I))
                    ELSE
                        Buffer$ = MySQL.Row(I)
                    END IF
                NEXT
            WEND

            File.Close
            MySQL.Close
Retrieving blobs from the database is a little more confusing than storing blobs. The first thing you have to note is that reading binary data and text strings are 2 different operations. Since text strings are NULL terminated, you don't have to worry about how many bytes to read, this is automatically calculated for you. However, since binary data can contain NULL characters, this makes reading blobs a little bit tricky. You have to fetch the lengths of each field, since we have blobs in our table, this is done by calling MySQL.FetchLengths for each row. Then to find out the length of each field, you use the internal array MySQL.Length(index%) which returns the length for field index%. Why do we have to do this? Because we need to know the size of our blob before we can read it in. To read binary data from our database, you use the specialized function MySQL.RowBlob(Row%, Bytes%) which returns a binary string. With this binary string, you can write the data to a file or memory, or manipulate the data directly. In the above example, we're just writing the data to a file.

14.6 Using LOADBLOB and SAVEBLOB
In the previous section, we uncovered the natural way of storing and retrieving blobs (binary data). However, there is an easier and faster way of doing the samething.
            ''-- Recall the natural way
            ProcessedBuffer$ = MySQL.EscapeString(Buffer$, File.Size)
            MySQL.Query("insert into MyImageTable values('Label 1', '" + _
                        ProcessedBuffer$ + "')")

            ''-- Using LOADBLOB instead
            ProcessedBuffer$ = MySQL.LoadBlob("test.bmp")
            MySQL.Query("insert into MyImageTable values('Label 1', '" + _
                        ProcessedBuffer$ + "')")
Using LOADBLOB eliminates the use of MySQL.EscapeString since it is just implemented internally for you. It simply takes a single argument (the name of the file to include), and returns the processed string. To retrieve a blob from the database and save it to a file, you can try this:
            WHILE MySQL.FetchRow
                MySQL.FieldSeek(0)
                '' MySQL.FetchLengths
                FOR I = 0 TO MySQL.NumField-1
                    MySQL.FetchField
                    IF MySQL.Field.Type = FIELD_TYPE_BLOB THEN
                        ''-- Save data to file
                        MySQL.SaveBlob(I, "temp.bmp")
                    ELSE
                        Buffer$ = MySQL.Row(I)
                    END IF
                NEXT
            WEND
In this instance we can ignore using MySQL.FetchLengths since it is, again, implemented internally for you. MySQL.SaveBlob takes two arguments. The first is the index (or field number if you will), and the second argument is the name of the file to save to. There are no return values associated with this function.

14.7 In conclusion
Using MySQL can save you a lot of time and effort, since you don't need to design your own database file structure, and searching is quite fast. Not to mention that MySQL is multiplatform, so you can use MySQL with Windows and Linux. If you already have prior knowledge with programming in MySQL, you'll probably notice some differences. For example,
            I = MySQL.SelectDB("mysql")
Under Rapid-Q, this function returns 0 if database cannot be opened, and a non-zero number otherwise. However, if you've used LIBMYSQL.DLL before, this function (called mysql_select_db) returns 0 on success and -1 on failure. So basically, just reverse your way of thinking when using Rapid-Q.


15: COM Programming

Rapid-Q Documentation by William Yu (c)1999, appended by John Kelly Chapter 15

15. COM Programming

Component Object Model (COM) and Distributed COM (or DCOM), is a specification that defines object creation and communication between objects. Rapid-Q only supports client-side COM programming (ie. you will not be able to create COM servers in Rapid-Q). Also, not all COM interfaces are supported. Most likely this component uses the IDispatch interface that is common to Visual Basic. Expect several bugs in the QOLEOBJECT and QOLECONTAINER components, and some EVENTS are not detected.

If you need some background on COM programming look at "COM tutorial" and the IUnknown interface in this CHM help file. Programming alternatives are BCX, RealBasic, FSBL, etc. Possibly FreeBasic will become COM compliant in the future. Another option is to download B2C which converts VB code into visual C++ code. Then you compile that with the free visual C++ toolkit. There are some limitations to the B2C. see http://support.microsoft.com/kb/216388
the free VC++ toolkit is at: http://msdn.microsoft.com/visualc/vctoolkit2003/default.aspx

15.1 Supported COM extensions
COM has many extended services which have grown over time. Unfortunately Rapid-Q is limited to only a few:
  • COM clients (or Automation controllers) is implemented in QOLEOBJECT
  • Active Documents is implemented in QOLECONTAINER
Automation controllers can be used to drive automation servers such as MS WORD over a local machine or remotely. So what are the benefits of automating a server? Well, since the server can be invoked by another machine, this can free up resources and CPU cycles needed on your client system. Since you could automate an application from across a network (or the internet), you don't need the application to reside on your machine to do some useful work on it. Imagine automating machinery from your home. Active documents is similar to automation, however, the "document" (more like ActiveX control) is embedded into your application. Once embedded, you can use automation to control the behaviour of the document. Rapid-Q does not support Type Libraries, so vtable binding is not possible. Speaking of binding, a COM server is usually registered on your computer the first time it is run or installed. For .DLLs or .OCXs, this may not always be the case, so to register a COM server manually, you can use Window's regsvr32 program.
    regsvr32 myprog.dll
You can type that in your MS-DOS command line prompt, or via Start|Run. There are also programming examples to register a COM object, see the Windows API help file for more information.

15.2 About QOLEOBJECT
As mentioned in the previous section, QOLEOBJECT implements an automation controller. This component works similarly to VB (no, VB does not have a QOLEOBJECT component), except for a few things which are either implemented in another way or is not yet supported. Let's look at some examples comparing the 2 methods:

    ' Both examples invoke MS WORD
    ' in VB
    DIM Obj AS OBJECT

    Set Obj = CreateObject("Word.Basic")
    ' or just DIM Obj AS Word.Basic
    Obj.AppShow

    ' in Rapid-Q
    DIM Obj AS QOLEOBJECT

    Obj.CreateObject("Word.Basic")
    Obj.AppShow
Note that type checking is off for OBJECT and QOLEOBJECT, so when you invoke Obj.AppShow this calls the method AppShow in MS WORD. You may notice that Rapid-Q also supports the Invoke method. This is to eliminate ambiguity but also to provide a work around. So what if MS WORD has a method called CreateObject? In Rapid-Q this causes a problem since CreateObject is a valid method of QOLEOBJECT, so that method will be called, not the one in MS WORD. The work around is to use the Invoke method.
    ' in Rapid-Q
    DIM Obj AS QOLEOBJECT

    Obj.CreateObject("Word.Basic")
    Obj.Invoke("CreateObject") ' Call CreateObject method in MS WORD
Obviously you shouldn't run the above example, MS WORD doesn't have a CreateObject method, but you get the idea. Setting and getting properties can be done similarly:
    ' in Rapid-Q
    DIM Obj AS QOLEOBJECT

    Obj.CreateObject("Gif89.Gif89.1")
    Obj.AutoStart = 1
    Obj.Invoke("AutoStart") = 1 ' this also works
So what's not supported in Rapid-Q? Several data types and arrays are not supported yet, as well as events. Also there isn't a "set" method available. ie:
    ' in VB
    DIM ADOCommand AS ADODB.Command
    DIM ADOConnection AS ADODB.Connection

    set ADOCommand.ActiveConnection = ADOConnection
The line in red is not yet available in Rapid-Q. See the Appendix section on QOLEOBJECT, you will find a method called InvokeCopy which does the samething, but unfortunately isn't fully functional as of this writing.

15.3 About QOLECONTAINER
QOLECONTAINER is basically a container for embedding ActiveX components or Active documents. This component is very similar to QOLEOBJECT, it is again type check free, so you can automate the control like you would automating servers. You may find yourself using the Invoke method more often than not, since QOLECONTAINER does have a lot of properties and methods already defined. Another way to avoid this problem is the assign the Container method of QOLEOBJECT. This creates a reference to the object, and so you can use QOLEOBJECT to automate the control. For those that aren't familiar, ActiveX controls are reusable visual controls which are heavily used in VB. Again, the limitations are obvious, Rapid-Q doesn't support ActiveX events, type libraries, and a few others mentioned before.
    '-- A short example
    DIM Form AS QFORM
    DIM Obj AS QOLECONTAINER

    Obj.Parent = Form
    Obj.CreateObject("gif89.gif89.1")
Since an ActiveX control is a visible component, you'll note that the QOLECONTAINER requires a parent property. You'll also have to be wary of the fact that the ActiveX component could update/refresh the component even before the form is shown, so you'll receive a Can't focus a disabled or invisible window when that happens. QOLECONTAINER has an AutoShow property which can be set to False meaning that the ActiveX control should not be displayed when created. You can use the method Show of QOLECONTAINER to display the control at anytime after creating the object. There is also another way to avoid the error message from popping up, see the Appendix section on QOLECONTAINER for a complete example.


DLL's Creating your own DLL for Rapid

Creating your own DLL for Rapid-Q using FreeBasic

FreeBASIC is a free, 32-bit BASIC compiler for Windows, DOS, and Linux. It is a powerful development tool and has support for many C libraries including Allegro, SDL, and OpenGL. It is nearly 100% compatible with QuickBASIC, and shares many keywords with RapidQ. FreeBASIC is not case sensitive and has full support for pointers (functions, virtual tables, etc), unsigned data types and nested structures.

In several ways FreeBasic is more powerful than RapidQ.
1) it is optimized compiled machine code, not interpreted, and allows inline Assembly code.
2) it can link with C-libraries including iDispatch COM and DirectX9
3) there are more variable types and nested UDTs, and more.

Where do you download FreeBasic? www.freeBasic.net, and check the forum at www.freeBasic.net/forum.
FreeBASIC was developed in C (GCC, MINGW) by V1ctor and supported by many programmers.

When would you use a DLL in RapidQ? The most common reason is because of the slow execution for intensive calculations. That will be covered below. So how do you make a RapidQ-FreeBasic program? Let's start with a simple example first. Let's start with a very simple example.

'Make a program called Test.bas that will be compiled as RapidQ code:
DECLARE SUB TestInteger lib "DLL_test" ALIAS "TestInteger@4" (byval myData AS Integer)
TestInteger(12345)

Now make a file called DLL_test.bas :

option explicit
'this declare statement sets the case sensitive name for the sub in the DLL
'without it the name would be all UPPERCASE, FreeBasic uses ByRef as default
DECLARE SUB TestInteger lib "DLL_test" alias "TestInteger" (byval myData AS Integer)

SUB TestInteger (byval myData AS Integer) EXPORT
    print "In FreeBasic your integer  = " , myData
END SUB

Now compile DLL_test.bas as a FreeBasic program, i.e., at the DOS prompt (or in an IDE)
*** the -dll command instructs it to generate a DLL file. ***
 fbc -dll DLL_test.bas

That's it! You can run Test.exe (the RapidQ program) at the DOS prompt and you should see "12345" printed. You will notice a few important details. The DECLARE statement in RapidQ has a funny @4 name added to the sub in the DLL name:

DECLARE SUB TestInteger lib "DLL_test" ALIAS "TestInteger@4" (byval myData AS Integer)
This is because the compiler code that generates the DLL automatically tags on this "mangled name" so that programs using the DLL know to use the STDCALL convention. The @4 means that 4 bytes will be put on the stack for so the calling program knows how many parameters need to be read. If instead you were going to pass two integers to the DLL then the compiler will add @8 to the end of the name, and for a three interger-parameter SUB it will add @12, and so on. Remember case is important for the Sub or Function in the DLL.

Other things to note here, FreeBasic uses the option explicit command to turn on type checking, just like $TYPECHECK ON in RapidQ. The other is EXPORT, which informs FreeBasic that this SUB will be the one available to external programs calling the DLL. All other SUB / FUNCTION, and variables will be global only to the FreeBasic program, not the RapidQ program. The other thing you will notice is that FreeBasic makes an DLL_test.dll.a. The .a files are for import libraries, you can delete them because you won't need them for RapidQ.

OK so now I know how to call a simple DLL with an integer.
What about other types? What about pointers?
'Let's try one with a DOUBLE and a pointer to an INTEGER:
 DECLARE SUB TestVars lib "DLL_test" ALIAS "TestVars@12" (byval myData AS Double, ByRef myInt AS INTEGER)
DIM a AS INTEGER
a = 12
TestVars(12345.12345, a)
ShowMessage STR$(a)        'let's see what returns

The FreeBasic code looks very familiar:
option explicit
DECLARE SUB TestVars lib "DLL_test" alias "TestVars" (byval myData AS Double, ByRef myInt AS INTEGER)

SUB TestVars(byval myData AS Double, ByRef myInt AS INTEGER) EXPORT
    print "In FreeBasic your Double  = " , myData
    print "In FreeBasic your integer value is  = " , myInt
    print "now it is 100"
    myInt = 100
END SUB

As you can see it works pretty much like in RapidQ. If you want the SUB or FUNCTION to change the variable, then pass it ByRef. Notice the
"TestVars@12" because the Double is 8 bytes, and the pointer (32-bit Windows) is 4 bytes. If you find it too difficult to figure out the name mangling? Download a DLL viewer like ADllExports.exe, and the program will show you the actual name.

The RapidQ BYTE, SHORT, SINGLE and DOUBLE has bugs when
passing these data types to a DLL.

BYTE, SHORT, WORD, SINGLE, and DOUBLE must be stored in a 32-bit long if passing ByVal to a DLL.
Basically always try to pass a 32-bit variable such as INTEGER, DWORD, or LONG. If your DLL needs less than 2 SINGLE or more than 2 DOUBLE variables, these will not be passed correctly! The safest way to pass these variables ByRef, if possible. If you must pass them ByVal then you should just state them as INTEGERS or LONG, in the DECLARE statement.

'here is the actual API call
SUB gluPerspective(fovy as Double, aspect as Double, zNear as Double, zFar as Double)
'here is how to implement it
DECLARE SUB gluPerspective_API LIB "glu32.dll" ALIAS "gluPerspective" _
   (fovy1 as long,fovy2 as long, aspect1 as long, aspect2 as long, _
   zNear1 as long, zNear2 as long, zFar1 as long, zFar2 as long)
   DEFDBL d: DEFINT i(7)
   d = fovy: MemCpy (VarPtr(i(0)), VarPtr(d), 8)
   d = aspect: MemCpy (VarPtr(i(2)), VarPtr(d), 8)
   d = zNear: MemCpy (VarPtr(i(4)), VarPtr(d), 8)
   d = zFar: MemCpy (VarPtr(i(6)), VarPtr(d), 8)
   gluPerspective_API(i(0), i(1), i(2), i(3), i(4), i(5), i(6), i(7))
END SUB

'here is another example of BYTE
Declare Sub keybd_event Lib "user32" Alias "keybd_event" _
(bVk As BYTE, bScan As Long, dwFlags As Long, dwExtraInfo As Long)

'all you have to do is change BYTE to LONG, and it will work fine
Declare Sub keybd_event Lib "user32" Alias "keybd_event" _
(bVk As Long, bScan As Long, dwFlags As Long, dwExtraInfo As Long)

Arrays and looping

Obviously a simple programs are not of real use. Actually you do not want to call a DLL for a single simple calculation because it takes time to just run the DLL code. What you need a DLL for is complicated calculations requiring multiple loops, access to high level libraries, and so forth. The most common use for RapidQ is speeding up calculations. Take an example where you would like to find the average of a large data set:

SUB CalcAverage(Datas() AS SINGLE, NumPts AS LONG, ByRef Average AS SINGLE)
  DIM Summ AS SINGLE, i AS INTEGER
  FOR i = 0 TO NumPts
     Summ = Summ + Datas(i)
  NEXT i
  Average = Summ / NumPts 'this will pass back the new average
END SUB
This calculation will take about 50 times longer in RapidQ relative to FreeBasic. So how do I pass my array to the DLL?
RapidQ handles arrays by reference, you just have to pass the reference to the first element in the array AND make sure FreeBasic knows it is getting an array of a specific type and how many elements are in it. There are actually two ways to do this:

 FreeBasic has special keyword PTR to indicate the SUB gets a pointer to an array of SINGLE:

SUB CalcAverage (Datas AS SINGLE PTR, BYVAL NumPts as LONG, ByRef Average AS SINGLE) EXPORT
  DIM Summ    AS SINGLE
  Dim fp As Single Ptr
  fp = @Datas					'asign the address local
  DIM f(NumPts) AS SINGLE  			'allocate a local array
  memcpy(@f(0), fp, NumPts*SIZEOF(SINGLE))   	'copy it
  FOR i = 0 TO NumPts				'now the code is just like RQ
     Summ = Summ + Datas(i)
  NEXT i
  Average = Summ / NumPts 			'this will pass back the new average
  memcpy(fp, @f(0), NumPts*SIZEOF(SINGLE))	'be sure to copy back!
END SUB

It is important to know RapidQ and FreeBasic use different descriptors of arrays (i.e., definition of the length of the array and the number of dimensions). But each program knows the address of the data. That is why the code is complicated with the assignment of the array address (fp =@Datas) and the memcpy command to create a new array that FreeBasic. There is another simpler way to write the code using indexing with brackets [ ] and using BYVAL Datas AS SINGLE PTR:

SUB CalcAverage (BYVAL Datas AS SINGLE PTR, BYVAL NumPts as LONG, ByRef Average AS SINGLE) EXPORT
  DIM Summ    AS SINGLE

  FOR i = 0 TO NumPts				'now the code is just like RQ
     Summ = Summ + Datas[i]			'note brackets not parens!
  NEXT i
  Average = Summ / NumPts 			'this will pass back the new average
END SUB

Passing strings and functions

Strings are complicated due to differences between compilers on how to describe all the parameters of a string. Like arrays, the complier needs to know how long the string is, and so forth. You can freely pass strings to FreeBasic, but it will just treat it as an array of bytes. An easy way to work with strings is to copy the passed string to a temporary FreeBasic string. RapidQ always passes strings by reference.

Compile this with fbc -dll mydll.bas

declare function teststr lib "mydll" alias "teststr" ( byval tstr as byte ptr) as long

function teststr (byval tstr AS BYTE PTR) as long EXPORT
  dim sss as string				'this is local to sub only, not RapidQ

  PRINT "the first char = "; CHR$(tstr[0])  	'note reference 0 based
  sss = *tstr 					'dereference value held in pointer
  sss=sss+"bzzzz"				'now treat it like any string
  print "in dll the new string =" ;sss
  teststr = INSTR(sss, "bz")  			'return back function result
end function

Test with this RapidQ code:

declare function teststr lib "mydll" alias "teststr@4" (tstr1 as string) as long
  DEFSTR aa$="abcdefgh"
  DEFLNG zz
  zz=teststr ( (aa$))
  print "teststr=" ; zz

There are several important things to notice. First FreeBasic uses byval tstr AS BYTE PTR to treat the string as an array that is passed by reference. Second, the temporary string, sss, is assigned the string with the asterisk (*) character which is used in the C language to dereference a pointer (that is get the value the memory that pointer is pointing to). The memory is assigned to sss until a CHR$(0) is reached, indicating a zero-terminated string. Third, you can also access individual characters with the index tstr[0] like that in arrays discussed above.

The last thing to point out is the FUNCTION works, by passing back to RapidQ a LONG value to the variable zz. At the time of this writing,
ONLY LONG, and INTEGERS can be passed back to RapidQ from a FreeBasic FUNCTION.

User defined types and more complicated calls

Since FreeBasic uses a syntax very similar to RapidQ, you can also pass UDTs (User define types) with ease. The following example shows just how complicated the structure can be and you will have total access to the RapidQ data inside the FreeBasic DLL:

Let's define the structure in RapidQ that show use of most variable types:

DECLARE SUB TestUDT lib "DLL_test" alias "TestUDT@4" (lpUDT AS LONG) '@4 is 4 bytes for UDT address
TYPE myUDT
  a AS BYTE
  b AS SHORT
  c As LONG
  d As STRING * 7	'must specify size
  e(0 to 20) As DOUBLE   'just the pointer is passed to the DLL!
END TYPE

DIM TheUDT as myUDT
  TheUDT.a = &HF0
  TheUDT.b = &HBBBB
  TheUDT.c = &HFF000001
  TheUDT.d = "hello!"  +CHR$(0)  'must end buffer with zero char
  TheUDT.e(3) = 5.2076

TestUDT(TheUDT)
ShowMessage str$(TheUDT.f(3))	'returns back new value

Again the FreeBasic code looks very familiar except for some variable types:

TYPE myUDT  FIELD=1	'sets this is a PACKED structure
  a AS BYTE		'that is default in RapidQ, not FB
  b As SHORT
  c As LONG
  d As ZSTRING * 7	'ZSTRING means zero-terminated string
  e As DOUBLE PTR	'RapidQ passes the array pointer!
END TYPE

DECLARE SUB TestUDT lib "DLL_test" alias "TestUDT" (BYREF lpUDT AS myUDT)

SUB TestUDT (BYREF lpUDT AS myUDT) EXPORT
  Print "Byte = "; HEX$(lpUDT.a)
  Print "Short = "; HEX$(lpUDT.b)
  Print "Long = "; HEX$(lpUDT.c)
  Print "print string is "; lpUDT.d		'FB knows it is a string
  Print "third char = "; CHR$(lpUDT.d[3])	'print out just one character
  lpUDT.e[3] = -20.567				'change its value...
END SUB

There are some important things to note. The ByREF statement for the UDT because RapidQ always passes UDTs by reference. Also, the FIELD=1 statement must be set in FreeBasic to handle the RapidQ UDT, which is commonly called a "packed structure." That just means all variables in the UDT are packed right next to each other without padding or aligning the data on specific boundaries. The other is the conversion of STRING to ZSTRING, and an array of DOUBLE to DOUBLE PTR. Again these are needed in FreeBasic to work with the way RapidQ actually passes the data to any DLL, not just FreeBasic. From this one example you should be able to see how to pass different variable types. Here is a table of other variable types. Note that Freebasic has more types than RapidQ, including unsigned versions of all RapidQ types. FreeBasic assumes that variables are passed ByRef unless specified ByVal.

RAPID-Q declaration | FreeBasic declaration | Range
var AS BYTE | ByVal var AS UBYTE | unsigned 0 to 255
var AS BYTE | ByVal var AS BYTE | signed -128 to 127
var AS SHORT | ByVal var AS SHORT | signed -32768 to 32767
var AS WORD | ByVal var AS USHORT | unsigned 0 to 65365
var AS LONG | ByVal var AS LONG | signed 4 bytes 32-bits
var AS INTEGER | ByVal var AS INTEGER | signed 4 bytes 32-bits
var AS DWORD (actually a LONG in Windows) | ByVal var AS UINTEGER | unsigned 4 bytes 32-bits
var AS STRING | var AS ZSTRING * size | fixed length or find last 0 char.
var AS SINGLE | ByVal var AS SINGLE | signed 4 bytes 32-bits ( 6 decimal digits)
var AS DOUBLE | ByVal var AS DOUBLE | signed 8 bytes 64-bits ( 15 decimal digits )
Arry(index) AS BYTE, var AS STRING | ByVal Arry AS BYTE PTR | Array of bytes, can be strings
Arry(index) AS INTEGER, etc. | ByVal Arry AS INTEGER PTR access by Arry[i] | Array of 32-bit integers
var AS UDTtype | ByRef var AS UDTtype | packed structure

Advanced Topics, passing data between the FreeBasic DLL and your RapidQ program

In this example you will pass the address of a RapidQ sub to the FreeBasic DLL. FreeBasic will then call your RapidQ sub by passing
an integer to it. You will find this important if a RapidQ component needs to be updated while the FreeBasic DLL is doing a long loop.

'**** FreeBasic DLL CODE filename: FB_CallBackFromDll.Bas
'compile this as fbc -dll FB_CallBackFromDll.Bas
' -----------------------------------------------------------------
' TEST SET INTEGER IN CALLING APP FROM A FreeBasic DLL
' by Jacques March 7th, 2006
' -----------------------------------------------------------------

' -----------------------------------------------------------------------------
' first set function declares
Declare function CallBackInDll lib "FB_CallBackFromDll" _
alias "FB_CallBackFromDll@4"_
(ByVal iCallBack AS FUNCTION(ByVal i AS INTEGER) AS INTEGER) as integer
' -----------------------------------------------------------------------------

function CallBackInDll (ByVal iCallBack AS FUNCTION(ByVal i AS INTEGER) AS INTEGER) as integer export
Dim iProgress As Integer
While iProgress < 200
iCallBack (iProgress)
Sleep (200)
iProgress = iProgress + 1
Wend
end function
' -----------------------------------------------------------------------------

'Now this will be your RapidQ program
'**** RAPIDQ CODE FileName: WhatEverYouwant.Bas
' -----------------------------------------------------------------------------
$ESCAPECHARS ON
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
'
Declare function CallBackInDll lib "FB_CallBackFromDll" _
alias "FB_CallBackFromDll@4"(ByVal iCallBack as Integer) as integer
'
Create frmGauge As QForm
Center
ClientWidth = 300
ClientHeight = 10
CREATE Gauge AS QGauge
Align = alClient
Max = 200
Color = &HFF00
position = 10
Kind = gkHorizontalBar ' gkPie
END CREATE
End Create
'-------------
Sub GaugeCallBack (iProgress As Integer)
Print "In RQ_CallBack: iProgress = ";iProgress ' or change your Gauge position
Gauge.Position = iProgress
DoEvents
End Sub
'
frmGauge.Show
'
CallBackInDll(CodePtr(GaugeCallBack))
'
' -------------------------------------------------------------
DefStr sExit
Input " CR to QUIT ", sExit
frmGauge.Close
Application.Terminate
' -------------------------------------------------------------
'

Other details:

FreeBasic will automatically use UPPERCASE for the Sub/Function in the DLL unless you use the ALIAS keyword in the FreeBasic program.

RapidQ uses the STDCALL convention and this is the default calling convention for FreeBasic and Windows API calls. STDCALL pushes the arguments from right to left onto the stack so that the last argument can be accessed by ebp+8. With stdcall convention the callee ( the called function ) has to completely clean up the stack, that is local variables/temps plus the arguments. as a last convention with stdcall function names are appeneded a @<num> where num is the number of bytes taken on the stack by the arguments of the function. CDECL convention hand pushes the argument list from right to left onto the stack so that the first element of the argumentlist is at ebp+8. no suffix is appended. this is most often used for variable argument lists and the like as the first element can tell how many arguments have been passed to the function.


APPLICATION Component

This object is global, and need not be created. This is extended in RAPIDQ2.INC

Application Properties
Field | Type | R/W | Default | Support
ExeName | STRING | R | WXG
The executable name of the application, path name is excluded (use COMMAND$(0) for full path information).
Handle | INTEGER | R | W
hInstance of the application.
HelpFile | STRING | RW | W
HelpFile specifies the name of the file the application uses to display help.
HintColor | INTEGER | RW | clInfoBk | W
HintColor determines the color of the hint boxes for the Help Hints.
HintHidePause | INTEGER | RW | 2500 | W
HintHidePause specifies the time interval to wait before hiding the Help Hint if the mouse has not moved from the control or menu item.
HintPause | INTEGER | RW | 500 | W
HintPause specifies the time interval that passes before the control's Help Hint appears when the user places the mouse pointer on a control or menu item.
HintShortPause | INTEGER | RW | 50 | W
HideShortPause specifies the pause to wait before bringing up a hint if a hint has already been shown.
Icon | STRING | RW | W
Specify an icon filename to appear as the default icon of your application.
IcoHandle | RESOURCE | W | W
Specify an icon resource to appear as the default icon of your application.
Example:
$RESOURCE game_ICO AS "game.ico"
Application.IcoHandle = game_ICO
ShowHint | INTEGER | RW | True | W
Title | STRING | RW | W

Application Methods
Method | Type | Description | Params | Support
HelpCommand | SUB (Command AS WORD, Data AS LONG) | Accesses the Help commands in the WinHelp API | 2 | W
HelpContext | SUB (Context AS LONG) | Bring up the Application's HelpFile at specifed Context ID | 1 | W
HelpJump | SUB (JumpID AS STRING) | Brings up the HelpFile and displays the screen in the Help file that has the JumpID | 1 | W
Minimize | SUB | Minimize Application | 0 | W
Terminate | SUB | Terminates Application | 0 | WXG

Application Methods with RAPIDQ2.INC (also see QProcess for threads)
GetPriority VOID

Get the current Application Process Priority Windows Priority of the application, typically will be NORMAL_PRIORITY_CLASS

0 W
SetPriority FUNCTION (Priority AS LONG)

Sets the Application Process priority, in case you want more or less CPU power to your program.
Possible values are:
IDLE_PRIORITY_CLASS Reduce RapidQ time allocation--, for occasional running
BELOW_NORMAL_PRIORITY_CLASS Win2000, NT, XP+ only, less power to your App
NORMAL_PRIORITY_CLASS Default
ABOVE_NORMAL_PRIORITY_CLASS Win2000, NT, XP+ only more CPU to your App
HIGH_PRIORITY_CLASS Other programs suffer, but yours gets most CPU
REALTIME_PRIORITY_CLASS CAUTION!!!
(REALTIME mouse,no keyboard, no disk, you own the CPU! You must do all hardware IO) 		1 W
Path STRING Returns the path of the application 0 W

Application Examples
Application.HintColor = &H00FF00

CREATE Form AS QFORM
CREATE Button AS QBUTTON
Hint = "Button Hint"
ShowHint = 1
END CREATE
ShowModal
END CREATE

Application Example #2
$INCLUDE "RAPIDQ2.INC"
ShowMessage "My application resides in folder " + Application.Path


CLIPBOARD

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: CLIPBOARD

CLIPBOARD Component

This object is global, and need not be created.

ClipBoard Properties
Field | Type | R/W | Default
Format | ARRAY of WORD | RW
Format is a list of all the format the Clipboard contains. There are too may formats to fit on this page, not to mention all the custom formats you may have registered. Check your WinAPI help file for a list.
FormatCount | INTEGER | R
FormatCount contains the number of formats in the Format array.
Text | STRING | RW
Text specifies the current contents of the Clipboard as a string.

ClipBoard Methods
Method | Type | Description | Params
Clear | SUB | Clear clipboard | 0
Deletes contents of the Clipboard.
Close | SUB | Free clipboard for other processes | 0
Closes the Clipboard if it is open. The Clipboard can be opened multiple times, so the Clipboard will remain opened until it has been closed the same number of times it has been opened.
GetAsHandle | FUNCTION (Format AS WORD) AS LONG | Returns handle of specified format | 1
GetAsHandle returns the data from the Clipboard in a raw Windows handle for the specified format.
GetAsText | FUNCTION (length%) AS STRING | Returns text of length% | 1
GetAsText returns the text contents of the Clipboard. See also Text property.
HasFormat | FUNCTION (Format AS WORD) AS SHORT | Returns true or false if the format exists or not | 1
HasFormat indicates if the Clipboard object contains a particular format. Returns 0 if format is absent, non-zero otherwise if format is present.
Open | SUB | Begin critcal section | 0
Opens the Clipboard and prevents other applications from changing its contents until the Clipboard is closed.
SetAsHandle | SUB (Format AS WORD, Handle AS LONG) | Set handle and format | 2
SetAsHandle places the data in the given format as a Windows handle.
SetAsText | SUB (Text$) | Set text of clipboard | 1
SetAsText sets the text contents of the Clipboard. See also Text property.

ClipBoard Examples
ClipBoard.Open
PRINT ClipBoard.Text
ClipBoard.Close


PRINTER

Rapid-Q Documentation by William Yu (c)1999 Appendix A: PRINTER

PRINTER Component

This object is global, and need not be created. Please note that some printers do not support Draw or CopyRect. The printer component is mainly used for graphics, although it may also be suitable for text, please refer to LPRINT for text-only printing.

Printer Properties
Field | Type | R/W | Default
Aborted | INTEGER | R
Aborted determintes if the user aborted the print job.
Capabilities.Copies | INTEGER | R
Capabilities.Copies indicates whether the print is capable of printing multiple copies.
Capabilities.Orientation | INTEGER | R
Capabilities.Orientation indicates whether the print is capable of different orientations.
Capabilities.Collate | INTEGER | R
Capabilities.Collate indicates whether the print is capable of collating.
Copies | INTEGER | RW
Number of copies to print.
CopyMode | INTEGER | RW | cmBlackNess
Font | QFONT | W
Fonts | ARRAY of STRING | R
FontsCount | INTEGER | R
Handle | INTEGER | R
Orientation | INTEGER | RW
Orientation determines if the print job prints vertically or horizontally on a page.
Valid orientation values are:
0 = poPortrait (Vertical print)
1 = poLandscape (Horizontal print)
PageHeight | INTEGER | R
PageNumber | INTEGER | R
PageWidth | INTEGER | R
PrinterIndex | INTEGER | RW
Printers | ARRAY of STRING | R
PrintersCount | INTEGER | R
Printing | INTEGER | R
Title | STRING | RW
Title is the text that appears in the Print Manager and on network header pages.

Printer Methods
Method | Type | Description | Params
Abort | SUB | Abort printing the document | 0
BeginDoc | SUB | Starts new document to print | 0
BeginDoc sends a print job to the printer.
EndDoc | SUB | Nothing is printed until this is called | 0
EndDoc will start the print job.
NewPage | SUB | Start printing on a new page | 0
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3
Draw | SUB (x%, y%, BMP) | Draw Bitmap on Canvas | 3
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4
Pset | SUB (x%, y%, c%) | Pixel plot | 3
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to printer | 5

Printer Examples
DECLARE SUB ButtonClick

SUB ComboBoxChange(Sender AS QComboBox)
  Printer.PrinterIndex = Sender.ItemIndex   '-- Change default printer
END SUB

DIM Font AS QFont
    Font.Color = &HFF0000
    Font.Name = "Arial"
    Font.Size = 20
DIM Bitmap AS QBitmap
Bitmap.BMP = "rapidq.bmp"

CREATE Form AS QForm
  CREATE ComboBox AS QComboBox
    Left = 5
    Top = 5
    Width = 150
    OnChange = ComboBoxChange
  END CREATE
  CREATE Button AS QButton
    Caption = "&Print"
    Top = 3
    Left = 180
    OnClick = ButtonClick
  END CREATE
  CREATE GroupBox AS QGroupBox
    Caption = "Print Preview..."
    Top = 35
    Width = Form.ClientWidth
  END CREATE
  Center
END CREATE

FOR I = 0 TO Printer.PrintersCount-1
  ComboBox.AddItems(Printer.Printers(I))    '-- Add printer list to combobox
NEXT
ComboBox.ItemIndex = Printer.PrinterIndex

Form.ShowModal

SUB ButtonClick
  Printer.Orientation = 1   ' Landscape
  Printer.BeginDoc
  Printer.TextOut(1000,1000,"Hi World!",0,-1)
  Printer.Font = Font
  Printer.TextOut(10,10,"Does this print?",0,-1)
  Printer.Line(10,10,500,500,0)
  Printer.EndDoc
END SUB


QBITMAP

Rapid-Q Documentation by William Yu (c)1999, appended by John Kelly Appendix A: QBITMAP

QBITMAP Component

QBitmap is a non-visible component, used to store/retrieve BMP images. Always set the PixelFormat, Width and Height properties first if possible before drawing to the QBITMAP. If you have RAPIDQ2.INC then it includes a custom component called QBITMAPex that supports Clipboard paste and copy, alphablending, loading of other graphic formats (JPG, GIF, TGA, etc.)

QBitmap Properties
Field | Type | R/W | Default | Support
BMP | STRING | RW | W
Use BMP to assign a new bitmap file, or to store BMP in the image cache.
Examples:
DIM Bitmap AS QBITMAP
Bitmap.BMP = "whatever.bmp"
BMPHandle | RESOURCE | W | W
CopyMode | INTEGER | RW | cmBlackness | W
Empty | INTEGER | R | W
Font | QFONT | W | W
Handle | INTEGER | RW | W
Height | INTEGER | RW | WG
Monochrome | INTEGER | RW | W
Pixel | 2D ARRAY of INTEGER | RW | WG
PixelFormat | INTEGER | RW | pfDevice | W
Top | INTEGER | RW | WG
Transparent | INTEGER | RW | False | W
TransparentColor | INTEGER | RW | W
TransparentMode | INTEGER | RW | 0 | W
0 = tmAuto (or ChromaTransparency)
1 = tmFixed (or ChromaTransparency Fixed)
-1 = tmAlpha (AlphaTransparency in 32 bits/pixel bitmaps QBitMapEx only)
Width | INTEGER | RW | WG

QBitmap Methods
Method | Type | Description | Params | Support
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6 | WG
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3 | W
Example (copies QIMAGE to bitmap at 10,10):
DIM Destination AS QRECT
DIM Source AS QRECT
DIM Image AS QIMAGE
DIM Bitmap AS QBITMAP
Image.BMP = "whatever.bmp"

WITH Destination
.Top = 10
.Left = 10
.Right = .Left+Image.Width
.Bottom = .Top+Image.Height
END WITH
WITH Source
.Top = 0
.Left = 0
.Right = Image.Width
.Bottom = Image.Height
END WITH
Bitmap.CopyRect(Destination, Image, Source)
Draw | SUB (x%, y%, BMP) | Draw Bitmap on Canvas | 3 | WG
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5 | WG
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5 | WG
LoadFromFile | SUB (FileName$) | Load BMP from a file | 1 | W
LoadFromStream | SUB (Stream) | Load BMP from a stream | 1 | W
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4 | WG
Pset | SUB (x%, y%, c%) | Pixel plot | 3 | WG
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5 | WG
Rotate | SUB (xOrigin%, yOrigin%, Angle%) | Rotates entire bitmap at specified origin | 3 | W
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7 | W
SaveToFile | SUB (FileName$) | Save BMP to a file | 1 | W
SaveToStream | SUB (Stream) | Save BMP to a stream | 1 | W
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2 | W
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1 | W
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1 | W
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6 | W
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to image | 5 | WG

QBitmap Examples

DIM BitMap AS QBitMap
BitMap.BMP = "close.bmp"

CREATE Form AS QForm
  CREATE Image1 AS QImage
    Left = 100
    Draw 5, 5, BitMap.BMP
  END CREATE
  Center
  ShowModal
END CREATE


QBUTTON

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QBUTTON

QBUTTON Component

QButton is a general purpose button control.

QButton Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
BMP | STRING | RW | W
Use BMP to assign a new bitmap file, or to use BMP in a draw statement.
Examples:
DIM button AS QBUTTON
button.BMP = "whatever.bmp"
Details:
You can hold multiple images on a single bitmap, but they must be of the same size and next to each other in a horizontal row.
The "first" bitmap appears when the button is up.
The "second" bitmap appears when the button disabled.
The "third" bitmap appears when the button is down (clicked).
You have to tell Rapid-Q how many images are in your bitmap by assigning the number to NumBMPs.
BMPHandle | RESOURCE | W | W
Assign a BMP resource handle to appear on the selected button.
Example:
$RESOURCE game_BMP AS "game.bmp"
DIM button AS QBUTTON
button.bmpHandle = game_BMP
Cancel | INTEGER | RW | False | W
If Cancel is True, the button's OnClick event handler executes when the user presses the Escape key.
Caption | STRING | RW | WXG
Caption specifies the text that appears on the button. To underline a character, include an ampersand (&) symbol before the character.
Color | INTEGER | RW | X
Cursor | INTEGER | RW | crDefault | W
Default | INTEGER | RW | False | W
If Default is True, the button's OnClick event handler executes when the user presses the Enter key.
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Handle | INTEGER | R | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
Kind | INTEGER | RW | bkCustom | W
Layout | INTEGER | RW | blBMPLeft | W
Layout determines where the bitmap image appears on the button.
0 = blBMPLeft -- image appears at the left side of the caption
1 = blBMPRight -- image appears at the right side of the caption
2 = blBMPTop -- image appears above the caption
3 = blBMPBottom -- image appears below the caption
Left | INTEGER | RW | 0 | WXG
ModalResult | INTEGER | RW | mrNone | W
NumBMPs | INTEGER | RW | W
NumBMPs determines the number of images within the bitmap button.
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
ShowHint | INTEGER | RW | False | WXG
Spacing | INTEGER | RW | 4 | W
Determines the separation, in pixels, between the image and the caption.
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WXG
Width | INTEGER | RW | WXG
Visible | INTEGER | RW | True | WXG

QButton Methods
Method | Type | Description | Params | Support
StartDrag | SUB | Allows Button to be dragged | 0 | W

QButton Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on the button | 0 | WXG
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2 | W
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1 | W
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WXG
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | WXG
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WXG

QButton Examples
  '-- A drag button

  DIM Form AS QForm
  DIM Button AS QButton

  SUB MouseDown
      Button.StartDrag
      SHOWMESSAGE STR$(Button.Left)+", "+STR$(Button.Top)
  END SUB

  Button.Parent = Form
  Button.OnMouseDown = MouseDown

  Form.ShowModal


QCANVAS

Rapid-Q Documentation by William Yu (c)1999-2000, & D.Glodt (c)2000-2004, John Kelly Appendix A: QCANVAS

QCANVAS Component

QCanvas is an empty image for painting on. Instead of loading your images, you must draw them on the QCanvas. If you have RAPIDQ2.INC then it supports QCanvasEx that has pen styles, clipboards, and other drawing methods.

QCanvas Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
ClientHeight | INTEGER | RW | W
ClientWidth | INTEGER | RW | W
Color | INTEGER | RW | WXG
CopyMode | INTEGER | RW | cmBlackness | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Handle | INTEGER (this is the same as the handle to a device context, or hDC | R | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | W
Left | INTEGER | RW | 0 | WXG
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
Pixel | 2D ARRAY of INTEGER | RW | WXG
PopupMenu | QPOPUPMENU | W | W
ShowHint | INTEGER | RW | False | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WXG
Width | INTEGER | RW | WXG
Visible | INTEGER | RW | True | WXG

QCanvas Methods

Method | Type | Description | Params | Support
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6 | WXG
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3 | W
Example (copies QIMAGE to canvas at 10,10):
DIM Destination AS QRECT
DIM Source AS QRECT
DIM Image AS QIMAGE
Image.BMP = "whatever.bmp"

SUB CanvasPaint (Sender AS QCANVAS)
WITH Destination
.Top = 10
.Left = 10
.Right = .Left+Image.Width
.Bottom = .Top+Image.Height
END WITH
WITH Source
.Top = 0
.Left = 0
.Right = Image.Width
.Bottom = Image.Height
END WITH
Sender.CopyRect(Destination, Image, Source)
END SUB

DIM Canvas AS QCANVAS
Canvas.OnPaint = CanvasPaint
Draw | SUB (x%, y%, BMP) | Draw Bitmap on Canvas | 3 | WG
Details:
BMP can be any BMP property from QBitmap, QImage, QImageList, etc. any component with a BMP property is fine.
Examples:
DIM Image1 AS QIMAGE
Image1.BMP = "whatever.bmp"
DIM Image2 AS QBITMAP
Image2.BMP = "whatever.bmp"

SUB CanvasPaint (Sender AS QCANVAS)
Sender.Draw(0, 0, Image1.BMP)
Sender.Draw(50, 50, Image2.BMP)
END SUB

DIM Canvas AS QCANVAS
Canvas.OnPaint = CanvasPaint
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5 | WXG
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5 | WXG
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4 | WXG
Pset | SUB (x%, y%, c%) | Pixel plot | 3 | WXG
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5 | WXG
Repaint | SUB | Force repainting | 0 | W
Rotate | SUB (xOrigin%, yOrigin%, Angle%) | Rotates entire canvas at specified origin | 3 | W
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7 | W
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw image and stretch to fit inside Rect | 2 | W
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1 | W
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1 | W
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6 | W
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to image | 5 | WXG

QCanvas Events

Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on canvas | 0 | WXG
OnDblClick | VOID | User double clicked on canvas | 0 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WXG
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | WXG
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WXG
OnPaint | VOID | Receives WM_PAINT message | 0 | WXG

QCanvas Examples
'  Pixel by pixel credit scroller for Rapid-Q by William Yu

DIM Canvas AS QCanvas
DIM Form AS QForm
DIM Timer1 AS QTimer
DIM Font AS QFont
DIM Y AS INTEGER
    Y = -20

SUB Resize
  Canvas.Height = Form.ClientHeight
  Canvas.Width = Form.ClientWidth
END SUB

SUB Paint
  Canvas.Textout (65,Y-30,"Beware the power of Rapid-Q!", &H00FF00, 0)
  Canvas.Textout (30,Y,"Credit Scroller written in Rapid-Q by William Yu", &HFFFFFF, 0)
END SUB

SUB TimerOver
  Timer1.Interval = 1  '' Can't go any lower!
  Y = Y + 1            '' Pixel by pixel!
  Paint
END SUB

Form.Width = 400
Form.Height = 200
Form.Center
Form.Color = 0

Font.Name = "Arial"
Font.Size = 12
Font.Color = &H00FF00
Canvas.Parent = Form
Canvas.Font = Font
Canvas.Color = 0
Canvas.OnPaint = Paint

Timer1.Interval = 1
Timer1.OnTimer = TimerOver

Form.Onresize = Resize
Form.ShowModal


QCHECKBOX

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QCHECKBOX

QCHECKBOX Component

QCheckbox is a wrapper for Window's check box control

QCheckbox Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Caption | STRING | RW | WXG
Checked | INTEGER | RW | False | WXG
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
Left | INTEGER | RW | 0 | WXG
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
ShowHint | INTEGER | RW | False | WXG
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WXG
Visible | INTEGER | RW | True | WXG
Width | INTEGER | RW | WXG

QCheckbox Methods
Method Type Description Params Support

QCheckbox Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked check box | 0 | WXG

QCheckbox Examples
  DIM Form AS QForm
  DIM Checkbox as QCheckBox

  SUB Check
    IF CheckBox.Checked THEN
       SHOWMESSAGE "Checked!"
    END IF
  END SUB

  CheckBox.Parent = Form
  CheckBox.OnClick = Check

  Form.ShowModal


QCOMBOBOX

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QCOMBOBOX

QCOMBOBOX Component

QCombobox implements a simple pull down listbox. The first item in any combobox is 0, the next is 1, and so on... If you want the first item to show up you must set it e.g., ComboBox.ItemIndex = 0

QCombobox Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
Color | INTEGER | RW | W
CopyMode | INTEGER | RW | cmBlackness | W
Cursor | INTEGER | RW | crDefault | W
DropDownCount | INTEGER | RW | 8 | W
DropDownCount is the maximum number of items displayed in the drop-down list.
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
Item | ARRAY of STRING | RW | WXG
ItemCount | INTEGER | R | WXG
ItemHeight | INTEGER | RW | W
ItemIndex | INTEGER | RW | -1 | WXG
ItemIndex indicates which item in the drop-down list is selected. If no item is selected, then ItemIndex is -1.
Left | INTEGER | RW | 0 | WXG
MaxLength | INTEGER | RW | W
MaxLength is the maximum number of characters the user can type into the edit portion of the combobox.
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
ShowHint | INTEGER | RW | False | WXG
Sorted | INTEGER | RW | False | WG
Style | INTEGER | RW | csDropDown | W
Style determines the display style of the combobox.
0 = csDropDown -- A drop-down list with an edit box for manually entered text.
1 = csSimple -- A drop-down list with an edit box and a fixed list (list box) underneath.
2 = csDropDownList -- A drop-down list with no edit box for manual entry.
3 = csOwnerDrawFixed -- Owner-draw drop-down list with an edit box. Each item in the list is the height specified by the ItemHeight property.
4 = csOwnerDrawVariable -- Owner-draw drop-down list with an edit box. Each item can have varying heights.
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Text | STRING | RW | W
Top | INTEGER | RW | 0 | WXG
Visible | INTEGER | RW | True | WXG
Width | INTEGER | RW | WXG

QCombobox Methods
Method | Type | Description | Params | Support
AddItems | SUBI | Add items to combobox | STRINGs, Infinite | WXG
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6 | W
Clear | SUB | Clears entire Combobox | 0 | WXG
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3 | W
DelItems | SUBI | Delete items by their index | Index #s, Infinite | WXG
Draw | SUB (x%, y%, BMP) | Draw Bitmap at (X,Y) | 3 | W
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5 | W
InsertItem | SUB (Index%, String$) | Insert item at Index% | 2 | WXG
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5 | W
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4 | W
Pset | SUB (x%, y%, c%) | Pixel plot | 3 | W
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5 | W
Repaint | SUB | Force repainting of combobox | 0 | W
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7 | W
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2 | W
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1 | W
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1 | W
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6 | W
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to image | 5 | W

QCombobox Events
Event | Type | Occurs when... | Params | Support
OnChange | VOID | User selects a different item | 0 | WXG
OnDrawItem | SUB (Index%, State%, R AS QRect) | Items are redrawn for ownerdraw comboboxes | 3 | W
OnMeasureItem | SUB (Index%, Height%) | Calculate Height for ownerdraw variable comboboxes | 3 | W

QCombobox Examples
  DIM Form AS QForm
  DIM ComboBox AS QComboBox

  SUB ItemChanged
    PRINT ComboBox.Item(ItemIndex)
  END SUB

  ComboBox.Parent = Form
  ComboBox.OnChange = ItemChanged
  ComboBox.AddItems "1. Apples", "2. Oranges", "3. Bananas"

  Form.ShowModal


QCOMPORT

Rapid-Q Documentation by William Yu (c)1999, appended by John Kelly Appendix A: QCOMPORT

QCOMPORT Component
(included in RAPIDQ2.INC)

QComPort provides an easy to use interface to communicate with the com ports. It was dropped from RapidQ, but now lives! The code extends the custom "Comport" by Pete Kleinschmidt. Most of the original QComport properties and Methods are incorporated. This component only for Windows 32. You cannot make arrays of this object and must be declared at the GLOBAL level. Does not need additional DLLs. The QCOMPORT Component has not been extensively tested. Works on Win98SE, and XP SP2). Use at your own risk.

Limitations:
Doesn't perform checks if hardware exists
Does not have the ability change flow control settings (Hardware, Xon/Xoff, etc).
When a port is opened it should default to whatever flow control settings last used on open or the default settings.
This requires programming some of the Device Control Block (DCB) settings, like that for Baud, Parity, etc.
The following docs may help you out.
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/hardware/commun_2pf7.asp
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwbgen/html/msdn_serial.asp

QComPort Properties
Field | Type | R/W | Default
BytesNotRead | DWORD | R
BytesNotWritten | DWORD | R
BaudRate | DWORD | RW | br110
Connected | BYTE | R
DataBits | BYTE | RW | 8
Handle | LONG | R
InQue (same as BytesNotRead, for compatibility) | DWORD | R
OutQue (same as BytesNotWritten, for compatibility) | DWORD | R
Parity | BYTE | RW | prNone
PendingIO (***) | INTEGER | R
Port (now a string) | STRING | RW | COM1
ReadBufSize | DWORD | RW | 1024
StopBits | BYTE | RW | sbOneStopBit
WriteBufSize | DWORD | RW | 1024

QComPort Methods
Method | Type | Description | Params
AbortAllIO | SUB (***) | Aborts all asynchronous read/write operations | 0
Close | SUB | Closes communication port | 0
Open | SUB | Opens communication port | 0
PurgeIn | SUB | Clears input buffer and stops all input functions | 0
PurgeOut | SUB | Clears output buffer and stops all output functions | 0
Read SUB Read(QFile/QMemoryStream, Count%, Wait%)
(***) 		Reads stream data from com port, Count% < 32000 3
ReadString | FUNCTION ReadString$(Count%, Wait%) | Returns a string representation bytes read from comport | 2
WaitForLastIO | SUB (***) | Blocks until last IO is completed | 0
Write SUB Write(QFile/QMemoryStream, Count%, Wait%)
(***) 		Writes stream to com port, Count% < 32000 3
WriteString | SUB WriteString(Str$, Wait%) | Writes string to communication port | 2

QComPort Events
Event | Type | Occurs when... | Params
OnBreak | VOID (***) | A line break is detected, input and output is suspended until break is cleared | 0
OnClose | VOID | Com Port is successfully closed | 0
OnComError | SUB(ErrorMessage AS String) | An error occurs | 0
OnOpen | VOID | Com port is successfully opened | 0
OnReadString | VOID | Data successfully read from Com Port | 0
OnWriteString | VOID | Data successfully written to Com Port | 0
OnRing | VOID (***) | A ring signal is detected, used only with modems. | 0
OnRxChar | SUB (InQue%) (***) | A character(s) arrives in the input buffer. | 1
OnTxEmpty | VOID (***) | Output buffer is flushed | 0
(*** = no longer supported)

QComPort Examples
$Apptype GUI
$TYPECHECK ON
$OPTIMIZE ON
$INCLUDE "RAPIDQ2.INC"

DECLARE SUB OpenClick
DECLARE SUB SendClick
DECLARE SUB ReadClick
DECLARE SUB ComError(strErrorMessage AS STRING)
DECLARE SUB PortOpen
DECLARE SUB PortClose
DECLARE SUB PortClosed
DECLARE SUB StringWritten
DECLARE SUB StringRead

DIM strPort   AS STRING
DIM dwBaud    AS DWORD
DIM bParity   AS BYTE
DIM bDataBits AS BYTE
DIM bStopBits AS BYTE

DIM MyPort AS COMPORT
MyPort.OnComError     = ComError
MyPort.OnOpen         = PortOpen
MyPort.OnClose        = PortClosed
MyPort.OnWriteString  = StringWritten
MyPort.OnReadString   = StringRead

DIM Font AS QFont
Font.Name="Courier New"

CREATE Form AS QFORM
    Caption = "Form1"
    Width   = 820
    Height  = 355
    Center
    CREATE lblPort AS QLABEL
        Caption = "COM Port"
        Left = 10: Width = 100: Top = 5
    END CREATE
    CREATE lblBaud AS QLABEL
        Caption = "Bits per second"
        Left = 10: Width = 100: Top = 30
    END CREATE
    CREATE lblParity AS QLABEL
        Caption = "Parity"
        Left = 10: Width = 100: Top = 55
    END CREATE
    CREATE lblDataBits AS QLABEL
        Caption = "Data bits"
        Left = 10: Width = 100: Top = 80
    END CREATE
    CREATE lblStopBits AS QLABEL
        Caption = "Stop Bits"
        Left = 10: Width = 100: Top = 105
    END CREATE
    CREATE lblSend AS QLABEL
        Caption = "String to Send"
        Left = 10: Width = 100: Top = 130
    END CREATE
    CREATE cbPort AS QCOMBOBOX
        AddItems "COM1","COM2","COM3","COM4"
        Left      = 120: Width = 70: Top = 5
        ItemIndex = 0
    END CREATE
    CREATE cbBaud AS QCOMBOBOX
        AddItems "9600", "14400", "19200","38400", "56000", "57600", "115200"
        Left = 120: Width = 70: Top = 30
        ItemIndex = 6
    END CREATE
    CREATE cbParity AS QCOMBOBOX
        AddItems  "None", "Odd", "Even", "Mark", "Space"
        Left = 120: Width = 70: Top = 55
        ItemIndex = 0
    END CREATE
    CREATE cbDataBits AS QCOMBOBOX
        AddItems  "4", "5", "6", "7", "8"
        Left = 120: Width = 70: Top = 80
        ItemIndex = 4
    END CREATE
    CREATE cbStopBits AS QCOMBOBOX
        AddItems "1", "1.5", "2"
        Left = 120: Width = 70: Top = 105
        ItemIndex = 0
    END CREATE
    CREATE Edit1 AS QEDIT
        Text  = ""
        Left = 120: Top = 130: Width = 200
    END CREATE
    CREATE RichEdit1 AS QRICHEDIT
        Left = 3: Top = 160: Width = 795: Height = 130
        PlainText   = 1
        ReadOnly    = 1
        ScrollBars  = 3
        WordWrap    = 0
        Font        = Font
    END CREATE
    CREATE StatusBar AS QStatusBar
        Left = 10: Top = 300: Width = 795: Height = 20
        SizeGrip  = FALSE
        AddPanels "Panel 1", "Panel 2"
        Panel(0).Caption = "Not Connected"
        Panel(0).Width = 645
        Panel(1).Caption = ""
    END CREATE
    CREATE OpenButton AS QBUTTON
        Caption = "&Open Port"
        Left = 330: Top = 5: Height = 20
        OnClick = OpenClick
    END CREATE
    CREATE SendButton AS QBUTTON
        Caption = "&Send"
        Left = 330: Top = 130: Height = 20
        Enabled = 0
        OnClick = SendClick
    END CREATE
    CREATE ReadButton AS QBUTTON
        Caption = "&Read"
        Left = 440: Top = 130: Height = 20
        Enabled = 0
        OnClick = ReadClick
    END CREATE
END CREATE

SUB OpenClick
    SELECT CASE cbPort.ItemIndex
     CASE 0
      strPort = "COM1"
     CASE 1
      strPort = "COM2"
     CASE 2
      strPort = "COM3"
     CASE 3
      strPort = "COM4"
    END SELECT

    SELECT CASE cbBaud.ItemIndex
      CASE 0
       dwBaud = 110
      CASE 1
       dwBaud = 300
      CASE 2
       dwBaud = 600
      CASE 3
       dwBaud = 1200
      CASE 4
       dwBaud = 2400
      CASE 5
       dwBaud = 4800
      CASE 6
       dwBaud = 9600
      CASE 7
       dwBaud = 14400
      CASE 8
       dwBaud = 19200
      CASE 9
       dwBaud = 38400
      CASE 10
       dwBaud = 56000
      CASE 11
       dwBaud = 57600
      CASE 12
       dwBaud = 115200
    END SELECT

    SELECT CASE cbParity.ItemIndex
      CASE 0
        bParity = NOPARITY
      CASE 1
        bParity = ODDPARITY
      CASE 2
        bParity = EVENPARITY
      CASE 3
        bParity = MARKPARITY
      CASE 4
        bParity = SPACEPARITY
    END SELECT

    SELECT CASE cbDataBits.ItemIndex
      CASE 0
        bDataBits = 4
      CASE 1
        bDataBits = 5
      CASE 2
        bDataBits = 6
      CASE 3
        bDataBits = 7
      CASE 4
        bDataBits = 8
    END SELECT

    SELECT CASE cbStopBits.ItemIndex
      CASE 0
        bStopBits = ONESTOPBIT
      CASE 1
        bStopBits = ONE5STOPBITS
      CASE 2
        bStopBits = TWOSTOPBITS
    END SELECT

   'Settings
   MyPort.Port     = strPort
   MyPort.BaudRate = dwBaud
   MyPort.Parity   = bParity
   MyPort.DataBits = bDataBits
   MyPort.StopBits = bStopBits

   'Open COM Port
   MyPort.Open
   MyPort.PurgeIn

   IF MyPort.Connected=TRUE THEN
     OpenButton.Enabled = 0
     SendButton.Enabled = 1
     ReadButton.Enabled = 1
   END IF
END SUB

SUB SendClick
  DIM BytesRead AS DWORD

  IF Edit1.Text="" THEN
    SHOWMESSAGE "Please enter String to Send"
  ELSE
    'Write to COM Port
    MyPort.WriteString(Edit1.Text + CHR$(13) +CHR$(10), 1000)
    Edit1.Text=""

    WHILE MyPort.BytesNotRead > 0
      RichEdit1.Text=RichEdit1.Text & MyPort.ReadString(MyPort.BytesNotRead, 500)	'& is addition operator..
      BytesRead=MyPort.BytesNotRead + BytesRead
      StatusBar.Panel(1).Caption = "Number of Bytes Read  " & STR$(BytesRead)
    WEND

    PortClose
  END IF
END SUB

SUB ReadClick
  DIM BytesRead AS DWORD

    MyPort.PurgeIn
    WHILE MyPort.BytesNotRead > 0
      RichEdit1.Text=RichEdit1.Text & MyPort.ReadString(MyPort.BytesNotRead, 5)	'& is addition operator..
      BytesRead=MyPort.BytesNotRead + BytesRead
      StatusBar.Panel(1).Caption = "Number of Bytes Read  " & STR$(BytesRead)
    WEND
END SUB

SUB ComError (strErrorMessage AS STRING)
  SHOWMESSAGE strErrorMessage
END SUB

SUB PortOpen
  StatusBar.Panel(0).Caption = "Connected to " & MyPort.Port
END SUB

SUB PortClose
    MyPort.Close
END SUB

SUB PortClosed
  StatusBar.Panel(0).Caption = "Not Connected"
  OpenButton.Enabled = 1
  SendButton.Enabled = 0
END SUB

SUB StringWritten
  SHOWMESSAGE "String was written"
END SUB

SUB StringRead
  SHOWMESSAGE "String was read"
END SUB
Form.ShowModal


QCOOLBTN

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QCOOLBTN

QCOOLBTN Component

QCoolbtn is an extension of QButton, but allows Flat buttons, and toggle buttons (via GroupIndex).

QCoolbtn Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
AllowAllUp | INTEGER | RW | False | W
AllowAllUp specifies whether all buttons in the group can be unselected at the same time.
BMP | STRING | W | WX
Use BMP to assign a new bitmap file, or to use BMP in a draw statement.
Examples:
DIM coolbutton AS QCOOLBTN
coolbutton.BMP = "whatever.bmp"
Details:
You can hold multiple images on a single bitmap, but they must be of the same size and next to each other in a horizontal row.
The "first" bitmap appears when the button is up.
The "second" bitmap appears when the button disabled.
The "third" bitmap appears when the button is clicked.
The "fourth" bitmap appears when the button stays down.
You have to tell Rapid-Q how many images are in your bitmap by assigning the number to NumBMPs.
BMPHandle | RESOURCE | W | W
Caption | STRING | RW | WXG
Cursor | INTEGER | RW | crDefault | W
Down | INTEGER | RW | False | WX
Down specifies whether the button is selected (down) or unselected (up).
Enabled | INTEGER | RW | True | WXG
Flat | INTEGER | RW | False | WX
Flat determines whether the button has a 3D border that provides a raised or lowered look.
Font | QFONT | W | W
GroupIndex | INTEGER | RW | 0 | W
GroupIndex allows buttons to work together as a group. If GroupIndex is 0, the button behaves independently of all other buttons.
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
Layout | INTEGER | RW | blBMPLeft | W
Layout determines where the bitmap image appears on the button.
0 = blBMPLeft -- image appears at the left side of the caption
1 = blBMPRight -- image appears at the right side of the caption
2 = blBMPTop -- image appears above the caption
3 = blBMPBottom -- image appears below the caption
Left | INTEGER | RW | 0 | WXG
NumBMPs | INTEGER | RW | W
NumBMPs determines the number of images within the bitmap button.
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
ShowHint | INTEGER | RW | False | WXG
Spacing | INTEGER | RW | 4 | W
Determines the separation, in pixels, between the image and the caption.
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WXG
Width | INTEGER | RW | WXG
Visible | INTEGER | RW | True | WXG

QCoolbtn Methods
Method | Type | Description | Params | Params
StartDrag | SUB | Allows Button to be dragged | 0 | W

QCoolbtn Events
Event | Type | Occurs when... | Params
OnClick | VOID | User clicked on the button | 0 | WXG
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WX
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | WX
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WX

QCoolbtn Examples
  '-- An example of toggle buttons (via GroupIndex)

  CONST False = 0: CONST True = 1

  DIM Form AS QForm
  DIM Cool1 AS QCoolbtn
  DIM Cool2 AS QCoolbtn

  Cool1.Parent = Form
  Cool1.GroupIndex = 1       '' Must be > 0
  Cool1.Down = True          '' Button initially down
  Cool2.Parent = Form
  Cool2.GroupIndex = 1       '' Same group as Cool1
  Cool2.Left = 40

  Form.ShowModal


QDIRTREE

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QDIRTREE

QDIRTREE Component

QDirTree is a custom component used to provide users with a Windows Explorer like directory list. It eats up a lot of resources, so use with caution. You don't usually need more than one of these.

QDirTree Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
BorderStyle | INTEGER | RW | bsSingle
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Directory | STRING | RW | False
Enabled | INTEGER | RW | True
FastLoad | INTEGER | RW | False
Font | QFONT | W
Height | INTEGER | RW
HideSelection | INTEGER | RW | False
Hint | STRING | RW
InitialDir | STRING | RW
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ReadOnly | INTEGER | RW | False
ReadOnStart | INTEGER | RW | False
ShowHint | INTEGER | RW | False
TabOrder | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
Visible | INTEGER | RW | True

QDirTree Methods
Method | Type | Description | Params
AddDirTypes | SUB | Add directory types | 0
AddDriveTypes | SUB | Add drive types | 0
DelDirTypes | SUB | Del directory types | 0
DelDirTypes | SUB | Del drive types | 0
FullCollapse | SUB | Collapse entire directory list | 0
FullExpand | SUB | Expand entire directory list (slow!) | 0
Reload | SUB | Re-read directories | 0

QDirTree Events
Event | Type | Occurs when... | Params
OnChange | VOID | Current directory changes | 0

QDirTree Examples
'' A Directory Tree like Windows Explorer.
'' QDIRTREE Component courtesy of Markus Stephany.
'' I took out removable drives because it doesn't work properly.
'' So you won't be able to view your floppy disk drives.  CD-ROM drives
'' are fine, as far as I know...

$TYPECHECK ON

DECLARE SUB ChangeDirectory

CREATE Form AS QForm
  Caption = "Directory Tree"
  Center
  CREATE DirTree AS QDirTree
    InitialDir = CURDIR$
    Width = Form.ClientWidth
    Height = Form.ClientHeight
    OnChange = ChangeDirectory
  END CREATE
  ShowModal
END CREATE

SUB ChangeDirectory
  ShowMessage DirTree.Directory
END SUB


QEDIT

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QEDIT

QEDIT Component

QEdit is a single-line edit control. More or less used to take input from user.

QEdit Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
AutoSize | INTEGER | RW | True | W
AutoSize determines whether the edit control should adjust its size automatically to accomodate the height of the text.
BorderStyle | INTEGER | RW | bsSingle | W
CharCase | INTEGER | RW | ecNormal | W
CharCase determines the case of the text within the edit control.
0 = ecNormal -- The text of the edit box displays in mixed case.
1 = ecUpperCase -- The text of the edit box displays in uppercase.
2 = ecLowerCase -- The text of the edit box displays in lowercase.
Color | INTEGER | RW | W
EditText | STRING | RW | W
EditText is the value of the text for the edit control after it is formatted using InputMask
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Handle | INTEGER | R | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
InputMask | STRING | RW | W
InputMask is the mask that represents what text is valid for the edit control
IsMasked | INTEGER | R | False | W
IsMasked indicates whether a mask exists for the edit control.
Left | INTEGER | RW | 0 | WXG
MaxLength | INTEGER | RW | 0 | WXG
Modified | INTEGER | RW | W
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PasswordChar | STRING | RW | W
PasswordChar indicates the character, if any, to display in place of the actual characters typed in the control. An empty string indicates that text should be displayed normally.
PopupMenu | QPOPUPMENU | W | W
ReadOnly | INTEGER | RW | False | WXG
SelLength | INTEGER | RW | W
SelStart | INTEGER | RW | W
SelText | STRING | RW | W
ShowHint | INTEGER | RW | False | WXG
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Text | STRING | RW | WXG
Top | INTEGER | RW | 0 | WXG
Visible | INTEGER | RW | True | WXG
Width | INTEGER | RW | WXG

QEdit Events
Event | Type | Occurs when... | Params | Support
OnChange | VOID | Text changed | 0 | WXG
OnKeyDown | SUB (Key AS WORD, Shift AS INTEGER) | Key held down | 2 | W
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1 | W
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2 | W
WndProc | SUB (Hwnd%, Msg%, wParam%, lParam%) | Messages sent to QEdit | 4 | W

QEdit Examples
  DIM Form AS QForm
  DIM Edit1 AS QEdit

  Edit1.Parent = Form

  Edit1.Text = "Hello"   '' Set as default text
  Form.ShowModal

'--------------------------------------------------------------

' Example on how to handle OnKeyDown event

SUB EditKeyDown (Key AS WORD, Shift AS INTEGER, Sender AS QEDIT)
    SELECT CASE Key
        CASE 27
            SHOWMESSAGE "Escape key pressed!"
        CASE 13
            SHOWMESSAGE "Enter key pressed!"
    END SELECT
END SUB

CREATE Form AS QFORM
    Center
    CREATE Edit AS QEDIT
        OnKeyDown = EditKeyDown
    END CREATE
    ShowModal
END CREATE
QEdit Input Masks
 !	If a ! character appears in the mask, optional characters are represented
        in the EditText as leading blanks. If a ! character is not present, optional
        characters are represented in the EditText as trailing blanks.
 >	If a > character appears in the mask, all characters that follow are in
        uppercase until the end of the mask or until a < character is encountered.
 <      If a < character appears in the mask, all characters that follow are in
        lowercase until the end of the mask or until a > character is encountered.

 <>     If these two characters appear together in a mask, no case checking is
        done and the data is formatted with the case the user uses to enter the data.
 \	The character that follows a \ character is a literal character. Use this
        character to use any of the mask special characters as a literal in the data.
 L	The L character requires an alphabetic character only in this position.
        For the US, this is A-Z, a-z.
 l	The l character permits only an alphabetic character in this position, but
        doesn't require it.

 A	The A character requires an alphanumeric character only in this position.
        For the US, this is A-Z, a-z, 0-9.
 a	The a character permits an alphanumeric character in this position, but
        doesn't require it.
 C	The C character requires an arbitrary character in this position.
 c	The c character permits an arbitrary character in this position, but
        doesn't require it.
 0	The 0 character requires a numeric character only in this position.
 9	The 9 character permits a numeric character in this position, but doesn't
        require it.

 #	The # character permits a numeric character or a plus or minus sign in
        this position, but doesn't require it.
 :	The : character is used to separate hours, minutes, and seconds in times.
        If the character that separates hours, minutes, and seconds is different
        in the regional settings of the Control Panel utility on your computer
        system, that character is used instead.
 /	The / character is used to separate months, days, and years in dates.
        If the character that separates months, days, and years is different
        in the regional settings of the Control Panel utility on your computer
        system, that character is used instead.

 ;	The ; character is used to separate the three fields of the mask.
 _	The _ character automatically inserts spaces into the text. When the
        user enters characters in the field, the cursor skips the _ character.


QFILELISTBOX

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QFILELISTBOX

QFILELISTBOX Component

Use QFileListBox when you want to maintain a listbox with all the files in a specific directory. It can also list directories as well.

QFileListBox Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Directory | STRING | RW
Directory is the directory that contains all the files listed in the file listbox.
Drive | STRING | RW
Enabled | INTEGER | RW | True
ExtendedSelect | INTEGER | RW | True
ExtendedSelect determines if the user can select a sequential range of items in the file listbox.
Filename | STRING | RW
FileName is the name of the selected file in the listbox, including the pathname.
Font | QFONT | W
Height | INTEGER | RW
Hint | STRING | RW
Item | ARRAY of STRING | RW
ItemCount | INTEGER | R
ItemHeight | INTEGER | RW
ItemIndex | INTEGER | RW
ItemIndex specifies the index of the selected item in the file listbox. If no item is selected, ItemIndex equals -1.
Left | INTEGER | RW | 0
Mask STRING RW *.*
MultiSelect | INTEGER | RW | False
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
SelCount | INTEGER | R
Selected | ARRAY of INTEGER | RW
ShowHint | INTEGER | RW | False
ShowIcons | INTEGER | RW | False
ShowIcons determines whether images should appear next to the file names.
TabOrder | INTEGER | RW
Tag | INTEGER | RW
TopIndex | INTEGER | RW
TopIndex specifies the index number of the item that appears at the top of the file listbox.
Top | INTEGER | RW | 0
Width | INTEGER | RW
Visible | INTEGER | RW | True

QFileListBox Methods
Method | Type | Description | Params
AddFileTypes | SUBI | Add certain file types to list box | INTEGER, Infinite
FileTypes determine which files are displayed in the file listbox according to their attributes.
0 = ftReadOnly -- Display files with read-only attribute.
1 = ftHidden -- Display files with hidden attribute.
2 = ftSystem -- Displays system files.
3 = ftVolumeID -- Displays volume name.
4 = ftDirectory -- Displays directories.
5 = ftArchive -- Display files with archive attribute.
6 = ftNormal -- Display files with no special attributes.
Example:
$INCLUDE "RAPIDQ.INC"
DIM FileListBox AS QFILELISTBOX
FileListBox.AddFileTypes(ftDirectory, ftHidden)
DelFileTypes | SUBI | Remove certain file types from list | INTEGER, Infinite
Update | SUB | Updates/refreshes file list | 0

QFileListBox Events
Event | Type | Occurs when... | Params
OnChange | VOID | Directory changes | 0
OnClick | VOID | File was clicked on | 0
OnDblClick | VOID | Selection was double clicked on | 0

QFileListBox Examples
'' Simple Application Launcher
'' How to use the File List Box as a Directory List Box in Rapid-Q by William Yu

$INCLUDE "RAPIDQ.INC"

DECLARE SUB ChangeDirectories
DECLARE SUB ExecuteApplication
DECLARE SUB ResizeForm

CREATE Form AS QForm
  Height = 300
  Width = 450
  CREATE DirList AS QFileListBox     '' Can double as a Directory list box
   ShowIcons = True
   Mask = "*.*"
   AddFileTypes(ftDirectory)          '' Add Directories
   DelFileTypes(ftNormal)             '' Remove files (see RAPIDQ.INC for values)
   OnDblClick = ChangeDirectories
   Height = Form.ClientHeight
   Width = 200
  END CREATE
  CREATE EXEList AS QFileListBox
   ShowIcons = True
   Mask = "*.EXE"
   OnDblClick = ExecuteApplication
   Left = 215
   Height = Form.ClientHeight
   Width = 225
  END CREATE
  Center
  Caption = DirList.Directory
  OnResize = ResizeForm
  ShowModal
END CREATE

SUB ChangeDirectories
  ChDir(DirList.Item(DirList.ItemIndex) - "[" - "]")
  DirList.Directory = CurDir$:  EXEList.Directory = CurDir$
  Form.Caption = CurDir$
END SUB

SUB ExecuteApplication
  RUN EXEList.FileName    ' Non-Blocking
'  SHELL EXEList.FileName  ' Blocks, until program terminates
                           ' Becareful running 16-bit applications
END SUB

SUB ResizeForm
  DirList.Height = Form.ClientHeight
  EXEList.Height = Form.ClientHeight
  EXEList.Width = Form.ClientWidth - 215
END SUB


QFILESTREAM

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QFILESTREAM

QFILESTREAM Component

QFilestream is Rapid-Q's way of handling files. It's more elegant than the GET, and PUT method of traditional BASIC.

QFilestream Properties
Field | Type | R/W | Default | Support
EOF | INTEGER | R | WXG
EOF specifies whether the file pointer has reached the end of file.
Handle | INTEGER | R | W
LineCount | INTEGER | R | WXG
LineCount determines how many lines there are in the file. Note that LineCount ignores the CR character, and will only detect LF, so it treats CRLF as one line, but LFLF as 2 lines.
Position | INTEGER | RW | WXG
Position specifies the current position of the file pointer, any read/write operations will begin from here.
Size | INTEGER | R | WXG
Size determines the size of the file in bytes.

QFilestream Methods
Method | Type | Description | Params | Support
Close | SUB | Close the stream | 0 | WXG
CopyFrom SUB (Stream, Bytes%) Copy from another stream
Either QFileStream or QMemoryStream
If Bytes%=0 then the whole stream is copied 		2 W
Use CopyFrom to copy a QFILESTREAM or a QMEMORYSTREAM to the current filestream.
Details:
If Bytes% = 0 then the Stream is reset to position 0 and the whole stream is then copied.
Example:
$INCLUDE "RAPIDQ.INC"
DIM File1 AS QFILESTREAM
DIM File2 AS QFILESTREAM

File1.Open("test.txt", fmCreate)
File2.Open("oldtest.txt", fmOpenRead)
File1.CopyFrom(File2, 123) '-- Copy 123 bytes from File2
ExtractRes | SUB (Resource AS LONG) | Extract resource to filestream | 1 | WXG
Extracts a resource from your program to the filestream.
Details:
The parameter Resource is not the resource handle, but the absolute position of the resource within your file. This requires that you use the keyword Resource(n) to specify the resource number.
Example (dumping all resources):
$INCLUDE "RAPIDQ.INC"
$RESOURCE res_1 as "res.1"
$RESOURCE res_2 as "res.2"

DIM File1 AS QFILESTREAM

File1.Open("test.txt", fmCreate)

FOR I = 0 TO ResourceCount-1
    File1.ExtractRes(Resource(I))
NEXT
LoadArray | SUB (Array(), NumElements&) | Load data into array | 2 | WXG
Open SUB (FileName$, Method%) Open a file, Method% see RAPIDQ.INC '-- File Mode
CONST fmCreate = 65535
CONST fmOpenRead = 0
CONST fmOpenWrite = 1
CONST fmOpenReadWrite = 2
2 WXG
Read | SUB (variable) | Generic Read, determines the storage space and saves data in variable | 1 | WXG
Datasize is automatically determined, and the value is stored into the variable.
Example:
$INCLUDE "RAPIDQ.INC"
DIM File1 AS QFILESTREAM
DIM B AS BYTE, I AS INTEGER

File1.Open("test.txt", fmOpenRead)
File1.Read(B) '-- Read a byte
File1.Read(I) '-- Read an integer
ReadLine | FUNCTION () AS STRING | Reads an entire line, supports UNIX files | 0 | WXG
ReadNum FUNCTION (Num_Type) AS DOUBLE Returns number '-- ie. PRINT File.ReadNum(Num_SINGLE)

Num_Type can be next
CONST Num_BYTE = 1
CONST Num_SHORT = 2
CONST Num_WORD = 3
CONST Num_LONG = 4
CONST Num_DWORD = 5
CONST Num_SINGLE = 6
CONST Num_DOUBLE = 8

1 WXG
ReadBinStr | FUNCTION (n) AS STRING | Read n bytes, returns the binary string | 1 | WXG
ReadStr | FUNCTION (n) AS STRING | Read n bytes, returns the text string | 1 | WXG
ReadUDT | SUB (MyType) | Read and store data in a MyType structure | 1 | WXG
SaveArray | SUB (Array(), NumElements&) | Save array | 2 | WXG
Seek SUB (Position%, From%) Seek to Position%, From% see RAPIDQ.INC
'-- Offsets
CONST soFromBeginning = 0 '-- Seek (offset) from Beginning
CONST soFromCurrent = 1 '-- Seek (offset) from Current position
CONST soFromEnd = 2 '-- Seek (offset) from End
2 WXG
Write | SUB (variable) | Generic Write, determines the storage space and saves data to file | 1 | WXG
WriteLine | SUB (S AS STRING) | Writes string with CR+LF | 1 | WXG
WriteNum | SUB (number, bytes%) | Writes a number to file | 2 | WXG
WriteBinStr | SUB (string, bytes%) | Writes a binary string to file | 2 | WXG
WriteStr | SUB (string, bytes%) | Writes a text string to file (fast) | 2 | WXG
WriteUDT | SUB (MyType) | Write data stored in a MyType structure | 1 | WXG

QFileStream Examples
  $INCLUDE "RAPIDQ.INC"

  DIM File AS QFileStream

  File.Open("test.bas", fmOpenRead)
  S$ = File.ReadStr(File.Size)         '' Read entire file
  PRINT S$                             '' print it
  File.Close

'------------------------------------------------------
  $INCLUDE "RAPIDQ.INC"

  TYPE MyType
      Name AS STRING*30
      Phone AS STRING*8
      Age AS INTEGER
  END TYPE

  DIM Person AS MyType
      Person.Name = "Joe"
      Person.Phone = "555-5555"

  DIM File AS QFileStream
      File.Open("test", fmCreate)
      File.WriteUDT(Person)


QFONT

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QFONT

QFONT Component

QFont is a component used to specify the font, color, and size for your text. It's not meant to be used as a stand-alone component, it has no effect until you assign a QFONT component to a component that uses it.

QFont Properties
Field | Type | R/W | Default | Support
Charset | INTEGER | RW | DEFAULT_CHARSET | W
Color | INTEGER | RW | W
FontCount | INTEGER | R | W
FontName | ARRAY of STRING | R | W
Handle | INTEGER | RW | W
Name | STRING | RW | WX
Pitch | INTEGER | RW | fpDefault | W
Size | INTEGER | RW | WX

QFont Methods
Method | Type | Description | Params | Support
AddStyles | SUBI | Add styles [bold, italic, etc] | INTEGER, Infinite | W
DelStyles | SUBI | Delete styles [bold, italic, etc] | INTEGER, Infinite | W

QFont Examples
  $INCLUDE "RAPIDQ.INC"

  DIM Font AS QFONT
  DIM Label AS QLABEL

  Font.Name = "Arial"
  Font.AddStyles(fsBold, fsItalic)
  Label.Font = Font      '' Assign font values


QFONTDIALOG

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QFONTDIALOG

QFONTDIALOG Component

QFontDialog displays Window's font selection dialog

QFontDialog Properties
Field | Type | R/W | Default
Color | INTEGER | RW
FontCount | INTEGER | R
FontName | ARRAY of STRING | R
MaxFontSize | INTEGER | RW
MinFontSize | INTEGER | RW
Name | STRING | RW
Size | INTEGER | RW

QFontDialog Methods
Method | Type | Description | Params
AddStyles | SUBI | Add styles [bold, italic, etc] | INTEGER, Infinite
DelStyles | SUBI | Delete styles [bold, italic, etc] | INTEGER, Infinite
AddOptions | SUBI | Add options [fdLimitSize, fdNoSizeSel, etc.] | INTEGER, Infinite
DelOptions | SUBI | Delete options [fdNoStyleSel, fdScalableOnly, etc.] | INTEGER, Infinite
Execute | FUNCTION | Returns TRUE or FALSE | 0
GetFont | SUB GetFont(F AS QFONT) | Get font attributes | 1
SetFont | SUB SetFont(F AS QFONT) | Set font attributes | 1

QFontDialog Events
Event | Type | Occurs when... | Params
OnApply | VOID | User clicks on apply button | 0

QFontDialog Examples
  '-- Simple demo
  DIM FontDialog AS QFontDialog
  DIM Font AS QFont
      Font.Name = "Arial"

  FontDialog.GetFont(Font)
  IF FontDialog.Execute THEN
    ShowMessage "You selected "+FontDialog.Name
    FontDialog.SetFont(Font)
  END IF


QFORM

Rapid-Q Documentation by William Yu (c)1999-2000, Appended by John Kelly Appendix A: QFORM

QFORM Component

QForm is a standard application Window. You can put any visible control component on a QForm, such as QEdit, QLabel, QButton, etc.
If you have RAPIDQ2.INC then it includes QFormEx that gives you extended functions like Drag & Drop, minimizing to the task bar, MouseWheel events, etc. QFormEx is for Windows 32 only. Cannot make arrays of QFormEx and must DIM at the GLOBAL level.

W = Windows, X = Rapid-Q/XForms, G = Rapid-Q/GTK

QForm Properties
Field | Type | Read/Write | Default Value | Support
AutoScroll | INTEGER | RW | True | W
Specify whether scroll bars should appear automatically on the form if it is not large enough to display all of its controls
BorderStyle | INTEGER | RW | bsSizeable | WXG
BorderStyle specifies the appearance and behaviour of the form border.
0 = bsNone -- Not resizeable; no visible border line or caption bar
1 = bsSingle -- Not resizeable; single-line border
2 = bsSizeable -- Standard resizeable border
3 = bsDialog -- Not resizeable; standard dialog box border
4 = bsToolWindow -- Like bsSingle but with a smaller caption
5 = bsSizeToolWin -- Like bsSizeable but with a smaller caption
Caption | STRING | RW | WXG
Caption is the text that appears as the title of your form.
ClientHeight | INTEGER | RW | WXG
The height of the form's client area, ie. the usable area inside the form's border.
ClientWidth | INTEGER | RW | WXG
The width of the form's client area, ie. the usable area inside the form's border.
Color | INTEGER | RW | clBtnFace | W
Color of the form.
Cursor | INTEGER | RW | crDefault | W
Cursor that appears when the mouse pointer is over the form.
Font | QFONT | W | W
Sets font property. Used for TextOut method.
FormStyle | INTEGER | RW | fsNormal | W
Get or set the form's style. Only fsNormal is supported.
Handle | INTEGER | R | W
Get the form's handle for WinAPI calls.
Height | INTEGER | RW | WXG
Get or set the form's vertical size (in pixels).
Hint | STRING | RW | W
The hint string that appears when the user moves the mouse pointer over the form. It is not displayed unless ShowHint is true.
IcoHandle | RESOURCE | W | W
Assign an icon resource handle to appear as the icon for your form.
Example:
$RESOURCE game_ICO AS "game.ico"
DIM Form AS QFORM
Form.IcoHandle = game_ICO
Icon | STRING | W | W
Assign an icon filename to appear as the icon for your form.
KeyPreview | INTEGER | RW | False | W
Specify whether keyboard events should occur on the form before they occur on the active control. Not all keys will be redirected.
Left | INTEGER | RW | 0 | WXG
Specifies the left edge of the form relative to the desktop screen.
ModalResult | INTEGER | W | W
Assigning a value to ModalResult will close the form when it is displayed modally.
0 = mrNone 1 = mrOk
2 = mrCancel 3 = mrAbort
4 = mrRetry 5 = mrIgnore
6 = mrYes 7 = mrNo
8 = mrAll
Parent | QFORM | W | W
Assigning a parent will remove the second form from the taskbar.
PopupMenu | QPOPUPMENU | W | W
Popupmenus are displayed when user right clicks on the form.
Example:
DIM PopupMenu AS QPOPUPMENU
DIM Form AS QFORM
Form.PopupMenu = PopupMenu
ShowHint | INTEGER | RW | False | W
If True then the hint popup message can be displayed.
Top | INTEGER | RW | 0 | WXG
Visible | INTEGER | RW | False | WXG
Specifies the visibility of the form.
Width | INTEGER | RW | 320 | WXG
WindowState | INTEGER | RW | wsNormal | W
Specifies how the form appears on the screen.
0 = wsNormal -- form appears neither maximized nor minimized
1 = wsMinimized -- form is minimized
2 = wsMaximized -- form is maximized

 QForm Methods
Method | Type | Description | Params | Support
AddBorderIcons | SUBI | Add Border Icons | INTEGER, Infinite | W
Valid border icons are:
0 = biSystemMenu -- The form icon
1 = biMinimize -- The minimize icon
2 = biMaximized -- The maximize icon
3 = biHelp -- The help icon
Example:
$INCLUDE "RAPIDQ.INC"
DIM Form AS QFORM
Form.AddBorderIcons(biHelp)
Center | SUB | Used to center a form | 0 | WXG
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle/Ellipse | 6 | W
Close | SUB | Close form | 0 | WXG
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3 | W
Example (copies QIMAGE to form at 10,10):
DIM Destination AS QRECT
DIM Source AS QRECT
DIM Image AS QIMAGE
Image.BMP = "whatever.bmp"

SUB FormPaint (Sender AS QFORM)
WITH Destination
.Top = 10
.Left = 10
.Right = .Left+Image.Width
.Bottom = .Top+Image.Height
END WITH
WITH Source
.Top = 0
.Left = 0
.Right = Image.Width
.Bottom = Image.Height
END WITH
Sender.CopyRect(Destination, Image, Source)
END SUB

DIM Form AS QFORM
Form.OnPaint = FormPaint
DelBorderIcons | SUBI | Remove Border Icons | INTEGER, Infinite | W
Valid border icons are:
0 = biSystemMenu -- The form icon
1 = biMinimize -- The minimize icon
2 = biMaximized -- The maximize icon
3 = biHelp -- The help icon
Example:
$INCLUDE "RAPIDQ.INC"
DIM Form AS QFORM
Form.DelBorderIcons(biMinimize)
Details:
Deleting icon may not necessarily remove it from the form's title bar, but the icon will be greyed out.
Draw | SUB (x%, y%, BMP) | Draw Bitmap on Canvas | 3 | W
Details:
BMP can be any BMP property from QBitmap, QImage, QImageList, etc. any component with a BMP property is fine.
Examples:
DIM Image1 AS QIMAGE
Image1.BMP = "whatever.bmp"
DIM Image2 AS QBITMAP
Image2.BMP = "whatever.bmp"

SUB FormPaint (Sender AS QFORM)
Sender.Draw(0, 0, Image1.BMP)
Sender.Draw(50, 50, Image2.BMP)
END SUB

DIM Form AS QFORM
Form.OnPaint = FormPaint
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5 | W
HideTitleBar | SUB | Hides Caption | 0 | W
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draw line on form | 5 | W
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4 | W
Pset | SUB (x%, y%, c%) | Pixel plot | 3 | W
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5 | W
Repaint | SUB | Repaints the entire form | 0 | W
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7 | W
ShapeForm | SUB (Filename$|Resource, TransparentColor&) | Shapes form as outline of image | 2 | W
Details:
The first parameter can either be a filename to the BMP file, or a BMP resource file. The second parameter indicates which color is transparent.. Also see Qskin
Example 1:
DIM Form AS QFORM
Form.ShapeForm("image.bmp", &HFFFFFF)
Example 2:
$RESOURCE image_BMP AS "image.bmp"
DIM Form AS QFORM
Form.ShapeForm(image_BMP, &HFFFFFF)
Show | SUB | Used to show form when hidden | 0 | WX
ShowModal | FUNCTION AS SHORT | Display form and wait for result | 0 | WXG
ShowTitleBar | SUB | Displays Caption | 0 | W
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2 | W
Details:
BMP can be any BMP property from QBitmap, QImage, QImageList, etc. any component with a BMP property is fine.
Examples (Double original size):
DIM Image1 AS QIMAGE
Image1.BMP = "whatever.bmp"

SUB FormPaint (Sender AS QFORM)
DIM R AS QRECT
R.Left = 0
R.Top = 0
R.Right = Image1.Width*2
R.Bottom = Image1.Height*2
Sender.StretchDraw(R Image1.BMP)
END SUB

DIM Form AS QFORM
Form.OnPaint = FormPaint
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1 | W
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1 | W
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6 | W
TextOut | SUB (x%, y%, s$, fc%, bc%) | Write text to form | 5 | W
Details:
fc% = foreground color
bc% = background color
For a transparent background, set bc% parameter to -1

QForm Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicks on open area of form | 0 | W
OnClose | SUB (Action AS INTEGER) | Form closes | 1 | W
OnHint | SUB (Hint AS STRING) | Hint is displayed | 1 | W
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2 | W
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1 | W
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | W
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | W
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | W
OnPaint | VOID | Form requires repainting | 0 | W
OnResize | VOID | Form is resized | 0 | W
OnShow | VOID | Form is displayed | 0 | W
WndProc | SUB (Hwnd%, Msg%, wParam%, lParam%) | Messages posted/sent to form | 4 | W
Only one WndProc per Form is allowed. So if you have multiple forms, only one may be able to receive messages at a time. (try using QFormEx in RapidQ2 instead or look into the multiple callbacks code by Jacques)

QForm Example

  DIM Form AS QForm
  DIM Button AS QBUTTON

  Button.Parent = Form     '' Add button to form container
  Form.Center
  Form.Caption = "Hello world!"

  IF Form.ShowModal THEN
    PRINT "Return result is TRUE"
  ELSE
    PRINT "Return result is FALSE"
  END IF


QGAUGE

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QGAUGE

QGAUGE Component

QGauge is a sophisticated progress monitor. Used visually to give users the progress of an operation.

QGauge Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
BackColor | INTEGER | RW | clWhite
BackColor specifies the background color of the component.
BorderStyle | INTEGER | RW | bsSingle
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
ForeColor | INTEGER | RW
ForeColor specifies the color of the progress meter.
Height | INTEGER | RW
Hint | STRING | RW
Kind | INTEGER | RW | gkHorizontalBar
Left | INTEGER | RW
Max | INTEGER | RW | 100
Min | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
Position | INTEGER | RW | 0
ShowHint | INTEGER | RW | False
ShowText | INTEGER | RW | True
ShowText determines whether the progress text (as a percent) should be displayed.
Top | INTEGER | RW
Visible | INTEGER | RW | True
Width | INTEGER | RW

QGauge Examples
$INCLUDE "RAPIDQ.INC"

CREATE Form AS QForm
  Center
  CREATE Gauge AS QGauge
    Position = 20
    Kind = gkPie
  END CREATE
  ShowModal
END CREATE


QGLASSFRAME

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QGLASSFRAME

QGLASSFRAME Component

QGlassFrame is a 3rd party Rapid-Q component, that makes your form look transparent and shaded, made possible by Aleksey Xacker. No support is offered for this component, there are some special cases in using this component.

QGlassFrame Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
ClientHeight | INTEGER | RW
ClientWidth | INTEGER | RW
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Handle | INTEGER | RW
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW
Moveable | INTEGER | RW | True
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ShowHint | INTEGER | RW | False
Top | INTEGER | RW
Transparency | INTEGER | RW | 60
TransparentColor | INTEGER | RW | 0
Width | INTEGER | RW

QGlassFrame Methods
Method Type Description Params

QGlassFrame Examples
$INCLUDE "RAPIDQ.INC"

CREATE Form AS QForm
  Caption = "Transparent Form"
  Center
  CREATE GlassFrame AS QGlassFrame
      Align = alClient
  END CREATE
  ShowModal
END CREATE

'------- Weird transparency color error
$INCLUDE "RAPIDQ.INC"

CREATE Form AS QForm
  Caption = "Transparent Form"
  Center
  CREATE GlassFrame AS QGlassFrame
      Align = alClient
      TransparentColor = &HFF0000
  END CREATE
  Show
END CREATE

'-- I don't know what's wrong, but doing this seems to
'-- work better than using ShowModal when changing colors

DO
    DoEvents
LOOP UNTIL Form.Visible = 0


QGROUPBOX

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QGROUPBOX

QGROUPBOX Component

QGroupBox implements Window's group box.

QGroupBox Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Caption | STRING | RW
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ShowHint | INTEGER | RW | False
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Visible | INTEGER | RW | True
Width | INTEGER | RW

QGroupBox Methods
Method | Type | Description | Params
Repaint | SUB | Repaint groupbox, and anything inside it | 0

QGroupBox Events
Event | Type | Occurs when... | Params
OnClick | VOID | User clicked on groupbox | 0
OnDblClick | VOID | User double clicked on groupbox | 0
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4

QGroupBox Examples
CREATE Form AS QForm
  CREATE GroupBox AS QGroupBox
    Caption = " Group Box "
    Left = 100
    CREATE Button AS QButton
      Caption = "Button"
    END CREATE
  END CREATE
  Center
  ShowModal
END CREATE


QHEADER

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QHEADER

QHEADER Component

QHeader is a set of column headers that the user can resize at runtime.

QHeader Internal Types
   TYPE SectionsType       '' ie. Header.Sections(0).Caption
     Alignment AS INTEGER  '' Default taLeftJustify
     AllowClick AS INTEGER '' True
     Caption AS STRING
     MaxWidth AS INTEGER   '' Default  10000
     MinWidth AS INTEGER   '' Default 0
     Style AS INTEGER      '' Default hsText
     Width AS INTEGER      '' Default 50
   END TYPE
QHeader Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
ClientHeight | INTEGER | RW
ClientWidth | INTEGER | RW
CopyMode | INTEGER | RW | cmBlackness
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
Handle | INTEGER | RW
Height | INTEGER | RW
Hint | STRING | RW
HotTrack | INTEGER | RW | False
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
Pixel | 2D ARRAY of INTEGER | RW
PopupMenu | QPOPUPMENU | W
Sections | ARRAY of SectionsType | RW
SectionsCount | INTEGER | R
ShowHint | INTEGER | RW | False
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
Visible | INTEGER | RW | True

QHeader Methods
Method | Type | Description | Params
AddSections | SUBI | Add new sections to header | STRING, Infinite
Clear | SUB | Clears all sections | 0
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3
Draw | SUB (x%, y%, BMP) | Draw Bitmap at (X,Y) | 3
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4
Pset | SUB (x%, y%, c%) | Pixel plot | 3
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5
Repaint | SUB | Force repainting of header | 0
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to image | 5

QHeader Events
Event | Type | Occurs when... | Params
OnDrawSection | SUB (Index%, Pressed%, Rect AS QRECT) | A header section needs to be redisplayed. Header section's Style property must be hsOwnerDraw | 3
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4
OnResize | VOID | Size of header control changes | 0
OnSectionClick | SUB (Index%) | Header section Index% is clicked | 1
OnSectionResize | SUB (Index%) | Header section is resized | 1
OnSectionTrack | SUB (Index%, Width%, State%) | Header section is dragged | 3

QHeader Examples
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

DECLARE SUB DrawSection (Index AS INTEGER, Pressed AS INTEGER, Rect AS QRECT, Sender AS QHEADER)
DECLARE SUB SectionTrack (Index AS INTEGER, Width AS INTEGER, State AS INTEGER, Sender AS QHEADER)

CREATE Form AS QFORM
    Caption = "QHeader example"
    Center
    CREATE Header AS QHEADER
        AddSections "1", "2", "3"
        Sections(1).AllowClick = FALSE
        Sections(0).Style = hsOwnerDraw
        Sections(0).Width = 100
        Sections(1).Style = hsOwnerDraw
        Sections(2).Style = hsOwnerDraw
        OnDrawSection = DrawSection
        OnSectionTrack = SectionTrack
    END CREATE
    CREATE ListBox1 AS QLISTBOX
        Align = alLeft
        Width = 100
        AddItems "1. Rapid-Q", "2. Taxes"
    END CREATE
    CREATE StatusBar AS QSTATUSBAR
        SimplePanel = TRUE
        SimpleText = "Not moving"
    END CREATE
    ShowModal
END CREATE

SUB DrawSection (Index AS INTEGER, Pressed AS INTEGER, Rect AS QRECT, Sender AS QHEADER)
    Sender.TextOut(Rect.Left+5,Rect.Top+1, STR$(Index+1), &HFF0000, -1)
    SELECT CASE Index
        CASE 0
            Sender.FillRect(Rect.Left+20,Rect.Top+2,Rect.Right-20,Rect.Bottom-2, &H00FF00)
        CASE 1
            Sender.Circle(Rect.Left+20,Rect.Top+2,Rect.Right-20,Rect.Bottom-2, &HFF, &HFF)
        CASE 2
    END SELECT
END SUB

SUB SectionTrack (Index AS INTEGER, Width AS INTEGER, State AS INTEGER, Sender AS QHEADER)
    StatusBar.SimpleText = "Moving "+STR$(Width)
    SELECT CASE Index
        CASE 0
            ListBox1.Width = Width
    END SELECT
END SUB


QIMAGE

Rapid-Q Documentation by William Yu (c)1999-2000, appended by D.Glodt (c)2000-2004, John Kelly Appendix A: QIMAGE

QIMAGE Component

QImage is used to display a graphical image (BMP/ICON). It can also be used to draw primitive graphics. If you have RAPIDQ2.INC then it supports QIMAGEex that gives you clipboard functions, copy to clipboard is possible if image was loaded with LoadFromFile method. You can load other graphic formats (JPG, GIF, TGA, etc.) if the DLL Nviewlib is present (check the internal variable NViewLibPresent is true).

QImage Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
Autosize | INTEGER | RW | False
AutoSize determines whether the image control resizes to accommodate the image it displays.
BMP | STRING | RW
Use BMP to assign a new bitmap file, or to store BMP in the image cache.
Examples:
DIM Image AS QIMAGE
Image.BMP = "whatever.bmp"
BMPHandle | RESOURCE | W
Center | INTEGER | RW | False
Center positions the image so that it is centered in the image control.
CopyMode | INTEGER | RW | cmBlackness
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
Handle | INTEGER | RW
Height | INTEGER | RW
Hint | STRING | RW
ICOHandle | RESOURCE (you cannot drawon top of icon images with draw. line., etc.) | W
Icon | STRING | W
IncrementalDisplay | INTEGER | RW | False
IncrementalDisplay specifies whether partial renderings of the image are drawn periodically during slow operations or on large compressed images.
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
Pixel | 2D ARRAY of INTEGER | RW
PopupMenu | QPOPUPMENU | W
ShowHint | INTEGER | RW | False
Stretch | INTEGER | RW | False
Stretch resizes the image so that it exactly fits the bounds of the image control.
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Transparent | INTEGER | RW | False
Width | INTEGER | RW
Visible | INTEGER | RW | True

QImage Methods
Method | Type | Description | Params
Center | SUB | Centers image | 0
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3
Draw | SUB (x%, y%, BMP) | Draw Bitmap at (X,Y) | 3
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4
Pset | SUB (x%, y%, c%) | Pixel plot | 3
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5
Repaint | SUB | Force repainting of image | 0
Rotate | SUB (xOrigin%, yOrigin%, Angle%) | Rotates entire image at specified origin | 3
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to image | 5

QImage Events
Event | Type | Occurs when... | Params
OnClick | VOID | User clicked on image | 0
OnDblClick | VOID | User double clicked on image | 0
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4

QImage Examples
  '-- How to use a resource file

  CONST False = 0
  CONST True = 1

  $RESOURCE RES_BMP1 AS "C:\WINDOWS\CLOUDS.BMP"

  DIM Form AS QForm
  DIM Image AS QImage

  Image.Parent = Form
  Image.Autosize = True
  Image.BMPHandle = RES_BMP1
  Form.ShowModal


QIMAGELIST

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QIMAGELIST

QIMAGELIST Component

QImageList is an array of images, all of the same/fixed size.

QImageList Properties
Field | Type | R/W | Default
BkColor | INTEGER | RW | clNone
BkColor determines which background color to use when drawing an image. Setting BkColor to clNone specifies no background color, ie. the image is drawn transparently. Setting BkColor to clDefault specifies using the imagelists background color when drawing.
BlendColor | INTEGER | RW | clNone
BlendColor determines which foreground color to use when drawing an image. Setting BlendColor to clNone specifies no blend color, while setting BlendColor to clDefault specifies the system highlight color for the foreground.
Count | INTEGER | R
Count returns the number of images in the imagelist.
DrawingStyle | INTEGER | RW | dsNormal
DrawingStyle specifies the style to be used when the imagelist is drawing an image.
0 = dsFocused -- Draws the image blending 25% with the system highlight color. This only affects imagelists which contain masks.
1 = dsSelected -- Draws the image blending 50% with the system highlight color. This only affects imagelists which contain masks.
2 = dsNormal -- Draws the image using the color specified in the BkColor property. If the BkColor is clNone then the image is drawn transparently using the mask.
3 = dsTransparent -- Draws using the mask regardless of the BkColor setting.
GetBMP | ARRAY of IMAGES/BMP | R
GetBMP returns the image specified by their index.
Examples:
DIM ImageList AS QIMAGELIST
DIM Button AS QBUTTON

ImageList.AddBMPFile("whatever.bmp", 0)
Button.BMP = Imagelist.GetBMP(0)
GetICO | ARRAY of IMAGES/ICO | R
Handle | INTEGER | RW
Height | INTEGER | RW
ImageType | INTEGER | RW | itImage
ImageType determines whether the imagelist will use the image or the associated image mask when drawing.
Masked | INTEGER | RW | True
Masked specifies whether the imagelist contains transparent or non-transparent images.
Width | INTEGER | RW

QImageList Methods
Method | Type | Description | Params
AddBMPFile | SUB (FileName$, MaskColor%) | Add BMP file to Imagelist | 2
AddICOFile | SUB (FileName$) | Add Icon file to Imagelist | 1
AddBMPHandle | SUB (BMP_Resource, MaskColor%) | Add BMP to Imagelist | 2
AddICOHandle | SUB (ICO_Resource) | Add Icon to Imagelist | 1
Clear | SUB | Removes all images | 0
Delete | SUB (Index%) | Delete image at Index% | 1
Draw | SUB (QIMAGE/QBITMAP/QCANVAS/QDXSCREEN, X%, Y%, Index%) | Draw on canvas at (X,Y) with image index% in ImageList | 4
InsertBMPFile | SUB (Index%, Filename$, Mask%) | Insert BMP file at Index% | 3
InsertICOFile | SUB (Index%, Filename$) | Insert Icon file at Index% | 2
InsertBMPHandle | SUB (Index%, BMP_Resource, Mask%) | Insert BMP at Index% | 3
InsertICOHandle | SUB (Index%, ICO_Resource) | Insert Icon at Index% | 2

QImageList Examples
' Imagelist demo

$resource bmp_handle as "nolight.bmp"
$resource ico_handle as "close.ico"

DIM ImageList AS QImageList
DIM Form AS QForm
DIM Button AS QButton

ImageList.Width = 9
ImageList.Height = 17
ImageList.AddBMPHandle bmp_handle,0
'ImageList.AddBMPFile "nolight.bmp", 0
ImageList.AddICOHandle ico_handle
'ImageList.AddICOFile "close.ico"

Button.Parent = Form
Button.BMP = Imagelist.GetBMP(0)

Form.Icon = ImageList.GetICO(1)

Form.Showmodal


QLABEL

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QLABEL

QLABEL Component

QLabel is a non-windowed control used to display 2D, 3D, and/or rotated text on a form/container. Note that rotated labels only work with true type fonts.

QLabel Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
Alignment | INTEGER | RW | taLeftJustify | W
Alignment determines the horizontal placement of the text within the label.
0 = taLeftJustify -- The text appears lined up along the left edge of the label.
1 = taRightJustify -- The text appears lined up along the right edge of the label.
2 = taCenter -- The text is horizontally centered in the label.
Angle | INTEGER | RW | 0 | W
Angle determines how the label is rotated. Specify a degree from 0 to 360.
Autosize | INTEGER | RW | False | W
AutoSize determines whether the size of the label automatically resizes to accommodate the text.
Must occur before the Caption property is set.
Caption | STRING | RW | WXG
Color | INTEGER | RW | WX
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Handle | INTEGER | R | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
LabelStyle | INTEGER | RW | tsNone | W
LabelStyle determines whether the label is displayed as 3D or 2D.
0 = lsNone -- The text appears as normal 2d text.
1 = lsRaised -- The text appears as 3d.
2 = lsRecessed -- The text appears engraved.
Layout | INTEGER (*** PROPERTY DOESN'T WORK ****) | RW | tlTop | W
Layout determines the vertical placement of the text within the label.
0 = tlTop -- The text appears at the top of the label.
1 = tlCenter -- The text is vertically centered in the label.
2 = tlBottom -- The text appears along the bottom of the label.
Left | INTEGER | RW | 0 | WXG
LowerColor | INTEGER | RW | clBtnShadow | W
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
ShowHint | INTEGER | RW | False | WXG
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WXG
Transparent | INTEGER | RW | False | W
UpperColor | INTEGER | RW | clBtnHighlight | W
Visible | INTEGER | RW | True | WXG
Width | INTEGER | RW | WXG
Wordwrap | INTEGER | RW | False | W

QLabel Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicks on label | 0 | W
OnDblClick | VOID | User double clicked on label | 0 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 3 | W
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 2 | W
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 3 | W
WndProc | SUB (Hwnd%, Msg%, wParam%, lParam%) | Messages sent to QLabel | 4 | W

QLabel Examples
  DIM Form AS QForm
  DIM Label1 AS QLabel

  Label1.Parent = Form

  Label1.Text = "Hello"
  Form.ShowModal

'--------------------------------------------------------

  ' Note that rotated labels only work with true type
  ' fonts, such as Arial and Courier New.

  DIM Form AS QForm
  DIM Label1 AS QLabel
  DIM Font AS QFont

  Font.Name = "Arial"

  Label1.Parent = Form
  Label1.Font = Font
  Label1.Text = "Hello"
  Label1.Angle = 45
  Form.ShowModal


QLISTBOX

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QLISTBOX

QLISTBOX Component

QListbox implements a generic (veritcal scrolling) Windows listbox. The first item in any listbox is 0, the next is 1, and so on...

QListbox Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
BorderStyle | INTEGER | RW | bsSingle | W
Color | INTEGER | RW | WX
Columns | INTEGER | RW | 0 | W
Columns specifies the number of columns, in a multi-column listbox, that are visible without having to scroll.
CopyMode | INTEGER | RW | cmBlackness | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WXG
ExtendedSelect | INTEGER | RW | True | WX
ExtendedSelect determines if the user can select a sequential range of items in the listbox.
Font | QFONT | W | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
Item | ARRAY of STRING | RW | WXG
Item contains the strings that appear in the listbox.
ItemCount | INTEGER | R | WXG
ItemHeight | INTEGER | RW | W
ItemIndex | INTEGER | RW | WXG
Left | INTEGER | RW | 0 | WXG
MultiSelect | INTEGER | RW | False | WX
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
SelCount | INTEGER | R | W
Selected | ARRAY of INTEGER | RW | WX
ShowHint | INTEGER | RW | False | WXG
Sorted | INTEGER | RW | False | WG
Sorted specifies whether the items in a listbox are arranged alphabetically.
Style | INTEGER | RW | lbStandard | W
Style determines whether the listbox is standard or owner-draw.
0 = lbStandard -- All items are strings, with each item the same height.
1 = lbOwnerDrawFixed -- Each item in the listbox is the height specified by the ItemHeight property.
2 = lbOwnerDrawVariable -- Items in the listbox can be of varying heights.
TabOrder | INTEGER | RW | W
TabWidth | INTEGER | RW | 0 | W
Tag | INTEGER | RW | WXG
Text | STRING | RW | W
Text defines the items in the listbox as CRLF terminated strings.
Top | INTEGER | RW | 0 | WXG
TopIndex | INTEGER | RW | W
Visible | INTEGER | RW | True | WXG
Width | INTEGER | RW | WXG

QListbox Methods
Method | Type | Description | Params | Support
AddItems | SUBI | Add items to listbox | STRINGs, Infinite | WXG
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6 | W
Clear | SUB | Clears entire listbox | 0 | WXG
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3 | W
DelItems | SUBI | Delete items by their index | Index #s, Infinite | WXG
Draw | SUB (x%, y%, BMP) | Draw Bitmap at (X,Y) | 3 | W
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5 | W
InsertItem | SUB (Index%, String$) | Insert item at Index% | 2 | WXG
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5 | W
LoadFromFile | SUB (FileName AS STRING) | Load file to list | 1 | W
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4 | W
Pset | SUB (x%, y%, c%) | Pixel plot | 3 | W
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5 | W
Repaint | SUB | Force repainting of listbox | 0 | W
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7 | W
SaveToFile | SUB (FileName AS STRING) | Save list to file | 1 | W
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2 | W
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1 | W
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1 | W
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6 | W
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to image | 5 | W

QListbox Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicks on item | 0 | WXG
OnDblClick | VOID | User double clicks on an item | 0 | WXG
OnDrawItem | SUB (Index%, State%, R AS QRect) | Items are redrawn for ownerdraw listboxes | 3 | W
OnEnter | VOID | User presses enter to select item | 0 | W
OnMeasureItem | SUB (Index%, Height%) | Calculate Height for ownerdraw variable listboxes | 3 | W
WndProc | SUB (Hwnd%, Msg%, wParam%, lParam%) | Messages sent to Listbox | 4 | W

QListbox Examples
  DIM Form AS QForm
  DIM ListBox AS QListBox

  ListBox.Parent = Form
  ListBox.AddItems "1. Apples", "2. Oranges", "3. Bananas"
  ListBox.DelItems 1,2       '' Deletes Oranges and Bananas

  ListBox.Item(0) = "1. Strawberries"   '-- Change the first item

  Form.ShowModal


QLISTVIEW

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QLISTVIEW

QLISTVIEW Component

QListView provides 3 different ways of displaying items on a form. Items can be displayed in columns with column headers and sub-items, or individually with large/small icons. There is a bug with ColumnsCount and OnColumnClick. Altneratively, you can try QLISTVIEWex.

QListView Internal Types
   TYPE ItemType            '' ie. ListView.Item(0).Caption
     Caption AS STRING
     Checked AS INTEGER     '' If CheckBoxes is enabled and item is checked
     Handle AS INTEGER      '' Read-only
     ImageIndex AS INTEGER
     Index AS INTEGER       '' Read-only
     Selected AS INTEGER
     StateIndex AS INTEGER
   END TYPE

   TYPE ColumnType          '' ie. ListView.Column(0).Width
     Caption AS STRING
     Width AS INTEGER
   END TYPE
QListView Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
BorderStyle | INTEGER | RW | bsSingle
CheckBoxes | INTEGER | RW | False
CheckBoxes specifies whether checkboxes appear next to the items in the listview.
Color | INTEGER | RW
Column | ARRAY of ColumnType | RW
ColumnClick | INTEGER | RW | True
ColumnClick determines whether the column header behaves like a button.
ColumnsCount | INTEGER (Has a BUG -- returns the wrong number on Read) | R
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
GridLines | INTEGER | RW | False
GridLines determines whether lines are drawn separating items in the list.
Handle | INTEGER | R
Height | INTEGER | RW
HideSelection | INTEGER | RW | False
HideSelection determines whether the listview gives a visual indication of which item is selected when focus shifts to another control.
Hint | STRING | RW
HotTrack | INTEGER | RW | False
HotTrack specifies whether list items are highlighted when the mouse passes over them.
Item | ARRAY of ItemType | RW
ItemCount | INTEGER | RW
ItemIndex | INTEGER | RW
LargeImages | QIMAGELIST | W
Left | INTEGER | RW | 0
MultiSelect | INTEGER | RW | False
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ReadOnly | INTEGER | RW | False
RowSelect | INTEGER | RW | False
RowSelect determines whether an entire row in the listview can be selected.
SelCount | INTEGER | RW
Selected | ARRAY of INTEGER | RW
ShowColumnHeaders | INTEGER | RW | True
ShowHint | INTEGER | RW | False
SmallImages | QIMAGELIST | W
SortType | INTEGER | RW | stNone
SortType determines if and how the items in the list are automatically sorted.
0 = stNone -- No sorting is done.
2 = stText -- Items are sorted according to their caption property.
StateImages | QIMAGELIST | W
SubItem | 2D ARRAY of STRING | RW
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
ViewStyle | INTEGER | RW | vsIcon
Visible | INTEGER | RW | True

QListView Methods
Method | Type | Description | Params
AddColumns | SUBI | Add column headers to listview | STRING, Infinite
AddItems | SUBI | Add items to listview | STRING, Infinite
AddSubItem | SUB (Index%, String$) | Add sub item to Index% | 2
Clear | SUB | Clear all items in listview | 0
ClearColumns | SUB | Clear all columns in listview | 0
DelItems | SUBI | Delete items from listview | INTEGER, Infinite
DelSubItem | SUB (Index%, SubIndex%) | Delete subitem from listview | 2
InsertItem | SUB (Index%, String$) | Insert item at Index% | 2
InsertSubItem | SUB (Index%, SubIndex%, String$) | Insert subitem | 3
SwapItem | SUB (Index1%, Index2%) | Swap items | 2

QListView Events
Event | Type | Occurs when... | Params
OnClick | VOID | Item was clicked on | 0
OnChange | SUB (Index%, Change AS BYTE) | Item changed (text, image, or state) | 2
OnColumnClick | SUB (Column%) BUG, always returns 0 in Column% | Column header was clicked | 1
OnDblClick | VOID | Selection was double clicked on | 0
OnKeyPress | SUB (Key AS BYTE) | Key was pressed | 1

QListView Examples
' Simple .ZIP viewer (doesn't extract or anything useful like that).
' You're free to modify and distribute the code without restrictions.
' Written in Rapid-Q by William Yu
' Demonstrates QOpenDialog, QFileStream, QListView, QMainMenu, QMenuItem
'              and QImageList.

$APPTYPE GUI
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

$RESOURCE ICO_ZIP AS "ZIP.ICO"
$RESOURCE ICO_APP AS "APP.ICO"

DECLARE SUB ZipView (ZIPFile AS STRING)
DECLARE SUB FormResize
DECLARE SUB OpenClick
DECLARE SUB ExitClick
DECLARE SUB IconClick
DECLARE SUB SmallIconClick
DECLARE SUB ReportClick
DECLARE SUB ItemDblClick

CONST SIG = &H04034B50         ' ZIP Signature/ID

TYPE ZFHeader
  Signature AS LONG
  Version AS WORD
  GPBFlag AS WORD              ' ?
  Compress AS WORD             ' Compression types
  DateTime AS LONG             ' Packed format
  CRC32 AS LONG
  CSize AS LONG                ' Compressed size
  USize AS LONG                ' Uncompressed size
  FileNameLen AS LONG
END TYPE

TYPE PackedDateType            ' I think this is it:
  Year AS SHORT                ' 7 bits
  Month AS BYTE                ' 4 bits
  Day AS BYTE                  ' 5 bits
  Hour AS BYTE                 ' 5 bits
  Minute AS BYTE               ' 6 bits
  Secs AS BYTE                 ' 5 bits
END TYPE                       ' Total = 32 bits

DIM CompType(0 TO 9) AS STRING
    CompType(0) = "Stored"
    CompType(1) = "Shrunk"
    CompType(2) = "Reduced1"
    CompType(3) = "Reduced2"
    CompType(4) = "Reduced3"
    CompType(5) = "Reduced4"
    CompType(6) = "Imploded"
    CompType(7) = "Defalted"
    CompType(8) = "DeflatN"      '' Could be DeflatX as well...
    CompType(9) = "DeflatX"

DIM OpenItem AS QMenuItem
    OpenItem.Caption = "&Open"
    OpenItem.OnClick = OpenClick
DIM BreakItem AS QMenuItem
    BreakItem.Caption = "-"
DIM ExitItem AS QMenuItem
    ExitItem.Caption = "E&xit"
    ExitItem.OnClick = ExitClick
DIM IconItem AS QMenuItem
    IconItem.Caption = "vs&Icon"
    IconItem.RadioItem = True
    IconItem.OnClick = IconClick
DIM SmallIconItem AS QMenuItem
    SmallIconItem.Caption = "vs&SmallIcon"
    SmallIconItem.RadioItem = True
    SmallIconItem.OnClick = SmallIconClick
DIM ReportItem AS QMenuItem
    ReportItem.Caption = "vs&Report"
    ReportItem.RadioItem = True
    ReportItem.Checked = True
    ReportItem.OnClick = ReportClick

DIM FileMenu AS QMenuItem
    FileMenu.Caption = "&File"
    FileMenu.AddItems OpenItem, BreakItem, ExitItem
DIM ViewMenu AS QMenuItem
    ViewMenu.Caption = "&View"
    ViewMenu.AddItems IconItem, SmallIconItem, ReportItem

DIM ImageList1 AS QImageList
    ImageList1.Height = 32
    ImageList1.Width = 32
    ImageList1.AddICOHandle ICO_APP
    ImageList1.AddICOHandle ICO_ZIP
DIM ImageList2 AS QImageList            ' Scale 16x16
    ImageList2.Height = 16
    ImageList2.Width = 16
    ImageList2.AddICOHandle ICO_APP
    ImageList2.AddICOHandle ICO_ZIP

CREATE Form AS QForm
  ICOHandle = ICO_ZIP
  Center
  OnResize = FormResize
  Height = 330
  Width = 525
  Caption = "Simple .ZIP Viewer for Rapid-Q"
  CREATE MainMenu AS QMainMenu
    AddItems FileMenu, ViewMenu
  END CREATE
  CREATE ListView AS QListView
    Width = Form.ClientWidth
    Height = Form.ClientHeight
    SmallImages = ImageList2
    LargeImages = ImageList1
    ViewStyle = vsReport
    AddColumns "FileName","Length","Method","Size","Rate","Date","Time","CRC-32"
    Column(0).Width = 200
    Column(4).Width = 40
    Column(5).Width = 70
    Column(7).Width = 70
    OnDblClick = ItemDblClick
  END CREATE
  ShowModal
END CREATE

'------------------------------------------------------------------

SUB ZipView (ZIPFile AS STRING)
  DIM Hdr      AS ZFHeader
  DIM ZF       AS QFileStream
  DIM PD       AS PackedDateType
  DIM FileName AS STRING
  DIM Index    AS INTEGER

  IF ZF.Open(ZIPFile, fmOpenRead) = False THEN
    ShowMessage("Problem with reading "+ZIPFile)
    EXIT SUB
  END IF

  ListView.Clear
  Hdr.Signature = ZF.ReadNum(4)

  Index = 0
  WHILE Hdr.Signature = SIG
    Hdr.Version  = ZF.ReadNum(2)
    Hdr.GPBFlag  = ZF.ReadNum(2)
    Hdr.Compress = ZF.ReadNum(2)
    Hdr.DateTime = ZF.ReadNum(4)
    Hdr.CRC32 = ZF.ReadNum(4)
    Hdr.CSize = ZF.ReadNum(4)
    Hdr.USize = ZF.ReadNum(4)
    Hdr.FileNameLen = ZF.ReadNum(4)

    FileName = ZF.ReadStr(Hdr.FileNameLen)

    PD.Year = ((Hdr.DateTime SHR 25) AND &H7F) + 1980
    PD.Month = (Hdr.DateTime SHR 21) AND &H0F
    PD.Day = (Hdr.DateTime SHR 16) AND &H1F
    PD.Hour = (Hdr.DateTime SHR 11) AND &H1F
    PD.Minute = (Hdr.DateTime SHR 5) AND &H3F
    PD.Secs = Hdr.DateTime AND &H1F
    ListView.AddItems FileName
    IF INSTR(UCASE$(FileName), ".ZIP") THEN
      ListView.Item(Index).ImageIndex = 1
    END IF
    ListView.AddSubItem Index, STR$(Hdr.USize)
    ListView.AddSubItem Index, CompType(Hdr.Compress)
    ListView.AddSubItem Index, STR$(Hdr.CSize)
    IF Hdr.USize = 0 THEN
      ListView.AddSubItem Index, "----"
    ELSE
      ListView.AddSubItem Index, STR$(INT((Hdr.USize - Hdr.CSize) / Hdr.USize * 100))+"%"
    END IF
    ListView.AddSubItem Index, STR$(PD.Month)+"-"+STR$(PD.Day)+"-"+STR$(PD.Year)
    ListView.AddSubItem Index, STR$(PD.Hour)+":"+STR$(PD.Minute)
    ListView.AddSubItem Index, LCASE$(HEX$(Hdr.CRC32))
    ZF.Seek(Hdr.CSize, soFromCurrent)
    Hdr.Signature = ZF.ReadNum(4)
    Index = Index + 1
  WEND

  IF Index = 0 THEN
     '-- Likely not a .ZIP file
     ShowMessage(ZIPFile+" is not a valid ZIP file!")
  END IF
END SUB

SUB OpenClick
  DIM OpenDialog AS QOpenDialog

  OpenDialog.InitialDir = CurDir$
  OpenDialog.Filter = "ZIP Files (*.zip)|*.zip|All Files (*.*)|*.*"

  IF OpenDialog.Execute THEN
    ZipView(OpenDialog.FileName)
  END IF
END SUB

SUB ExitClick
  Form.Close
END SUB

SUB FormResize
  ListView.Height = Form.ClientHeight
  ListView.Width = Form.ClientWidth
END SUB

SUB IconClick
  IconItem.Checked = True
  ListView.ViewStyle = vsIcon
END SUB

SUB SmallIconClick
  SmallIconItem.Checked = True
  ListView.ViewStyle = vsSmallIcon
END SUB

SUB ReportClick
  ReportItem.Checked = True
  ListView.ViewStyle = vsReport
END SUB

SUB ItemDblClick
  IF ListView.ItemIndex >= 0 THEN
    ShowMessage("Can't extract "+ListView.Item(ListView.ItemIndex).Caption);
  END IF
END SUB


QMAINMENU

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QMAINMENU

QMAINMENU Component

QMainmenu implements a container for your menu items. Use it to add a drop-down main menu to a form.

QMainMenu Properties
Field | Type | R/W | Default | Support
Handle | INTEGER | R | W
Parent | QFORM | W | WXG

QMainMenu Methods
Method | Type | Description | Params | Support
AddItems | SUBI | Add items to mainmenu | QMENUITEMs, Infinite | WXG
DelIndex | SUB (index AS LONG) | Delete items, by index, from menu | 1 | W
DelItems | SUBI | Delete items from menu | QMENUITEMs, Infinite | W
Insert | SUB (I%, Item AS QMENUITEM) | Insert an item | 2 | W

QMainMenu Examples
  DIM Form AS QForm
  DIM MainMenu AS QMainMenu
  DIM Item1 AS QMenuItem

  Item1.Caption = "&File"
  MainMenu.AddItems Item1
  MainMenu.Parent = Form

  Form.ShowModal


QMEMORYSTREAM

Rapid-Q Documentation by William Yu (c)1999, appended by John Kelly Appendix A: QMEMORYSTREAM

QMEMORYSTREAM Component

QMemorystream is used to store temporary data to memory for manipulation. It can be used for dynamic arrays, or simply reducing memory after data is used.

QMemorystream Properties
Field | Type | R/W | Default | Support
LineCount | INTEGER | R | W
LineCount determines how many lines there are in the memorystream. Note that LineCount ignores the CR character, and will only detect LF, so it treats CRLF as one line, but LFLF as 2 lines.
Pointer | INTEGER | R | WXG
Pointer specifies the memory address of the memorystream.
Position | INTEGER | RW | WXG
Position specifies the current position of the memory pointer, any read/write operations will begin from here.
Size | INTEGER | RW | WXG
Size determines the number of bytes allocated to the memorystream.

QMemorystream Methods
Method | Type | Description | Params | Support
Close SUB Close the stream
Comment: If you close the memorystream, you reset the whole stream. No need to open it again (there isn't even an open method for qmemorystream), just write to the memorystream again. Alain 22 Aug 2002 		0 WXG
CopyFrom SUB (Stream, Bytes%) Copy from another stream
Either QFileStream or QMemoryStream 		2 WXG
Use CopyFrom to copy a QFILESTREAM or a QMEMORYSTREAM to the current memorystream.
Details:
If Bytes% = 0 then the Stream is reset to position 0 and the whole stream is then copied.
Example:
$INCLUDE "RAPIDQ.INC"
DIM File1 AS QFILESTREAM
DIM Mem AS QMEMORYSTREAM

File1.Open("test.txt", fmOpenRead)
Mem.CopyFrom(File1, 123) '-- Copy 123 bytes from File1
ExtractRes | SUB (Resource AS LONG) | Extract resource to memorystream | 1 | WXG
Extracts a resource from your program to the memorystream.
Details:
The parameter Resource is not the resource handle, but the absolute position of the resource within your file. This requires that you use the keyword Resource(n) to specify the resource number.
Example (dumping all resources):
$INCLUDE "RAPIDQ.INC"
$RESOURCE res_1 as "res.1"
$RESOURCE res_2 as "res.2"

DIM Mem AS QMEMORYSTREAM

FOR I = 0 TO ResourceCount-1
    Mem.ExtractRes(Resource(I))
NEXT
LoadArray | SUB (Array(), NumElements&) | Load data into array | 2 | WXG
MemCopyFrom | SUB (Address&, Bytes&) | Copies contents of Address& to memorystream | 2 | WXG
MemCopyTo | SUB (Address&, Bytes&) | Copies contents to Address& | 2 | WXG
Read | SUB (variable) | Generic Read, determines the storage space and saves data in variable | 1 | WXG
ReadLine | FUNCTION () AS STRING | Reads an entire line | 0 | W
ReadNum | FUNCTION (n) AS DOUBLE | Read n bytes, returns number | 1 | WXG
ReadStr | FUNCTION (n) AS STRING | Read n bytes, returns the string | 1 | WXG
ReadBinStr | FUNCTION (n) AS STRING | Read n bytes, returns the binary string | 1 | W
ReadUDT | SUB (MyType) | Read and store data in a MyType structure | 1 | WXG
SaveArray | SUB (Array(), NumElements&) | Save array | 2 | WXG
Seek | SUB (Position%, From%) | Seek to Position%, From% see RAPIDQ.INC | 2 | WXG
Write | SUB (variable) | Generic Write, determines the storage space and saves data to memory | 1 | WXG
WriteLine | SUB (S AS STRING) | Writes string with CR+LF | 1 | W
WriteNum | SUB (number, bytes%) | Writes a number to memory | 2 | WXG
WriteBinStr | SUB (string, bytes%) | Writes a binary string to file (slow) | 2 | W
WriteStr | SUB (string, bytes%) | Writes string to memory | 2 | WXG
WriteUDT | SUB (MyType) | Write data stored in a MyType structure | 1 | WXG

QMemoryStream Examples
DIM Mem AS QMemoryStream

  S$ = "Hello world!"
  Mem.WriteStr(S$, LEN(S$))
  Mem.Position = 0
  S$ = Mem.ReadStr(LEN(S$))
  PRINT S$                            '' print it
  Mem.Close

'------------------------------------------------------

  DIM Mem AS QMemoryStream
  DIM I AS INTEGER

  I = 12
  Mem.Write(I)
  S$ = "Hello world!"
  Mem.Write(S$)
  Mem.Position = 0
  Mem.Read(I)
  S$ = SPACE$(I)
  Mem.Read(S$)
  PRINT S$                            '' print it
  Mem.Close

'------------------------------------------------------

  TYPE MyType
      Name AS STRING*30
      Phone AS STRING*8
      Age AS INTEGER
  END TYPE

  DIM Person AS MyType
      Person.Name = "Joe"
      Person.Phone = "555-5555"

  DIM Mem AS QMemoryStream
      Mem.WriteUDT(Person)

To correctly deallocate memory from QMEMORYSTREAM you should
set Position and Size to 0 and then set one value. To see how
this works, run Task Manager to follow memory in process.
Then run this code:

DIM Mem AS QMemoryStream

Showmessage "Pre memory"
Mem.Size = 3200005
S$ = Space$(3200000)
Mem.WriteStr(S$, LEN(S$))
Showmessage "Memory allocated"

'now deallocate
Mem.Position = 0
Mem.Size = 0
Showmessage "Memory should be all deallocated"

'loading a value finally resets memory
S$ = "hi"
Mem.WriteStr(S$, LEN(S$))
Showmessage "Finally deallocated by assigning value"
Mem.Close
Application.Terminate


QMENUITEM

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QMENUITEM

QMENUITEM Component

QMenuItem is used to describe the properties of an item in a menu. It is not meant to be a stand-alone component. You usually add a QMenuItem to a QMainMenu or QPopupMenu. To put in a separator use this method:
.Caption = "-"
. Enabled = False

QMenuItem Properties
Field | Type | R/W | Default | Support
Caption | STRING | RW | WXG
Caption specifies the text of the menu item.
Checked | INTEGER | RW | W
Checked specifies whether a check mark should appear beside the caption.
Command | INTEGER | R | W
Command is the Windows command ID associated with the menu item.
Count | INTEGER | R | W
Count is the number of subitems of the menu item.
Enabled | INTEGER | RW | True | W
Handle | INTEGER | R | W
Hint | STRING | RW | W
MenuIndex | INTEGER | RW | W
MenuIndex is index of the menu item within its parent menu.
RadioItem | INTEGER | RW | False | W
RadioItem specifies whether the menu item is mutually exclusive with other menu items in its group.
ShortCut | STRING | RW | W
ShortCut specifies the key combination users can type to quickly access the menu item.
Tag | INTEGER | RW | WXG
Visible | INTEGER | RW | True | W
Visible determines whether the menu item should be displayed.

QMenuItem Methods
Method | Type | Description | Params | Support
AddItems | SUBI | Add Subitems to MenuItem | QMENUITEMs, Infinite | WXG
DelIndex | SUB (index AS LONG) | Delete items, by index, from menu | 1 | W
DelItems | SUBI | Delete items from menu | QMENUITEMs, Infinite | W
Insert | SUB (I%, Item AS QMENUITEM) | Insert an item | 2 | W

QMenuItem Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User selects item | 0 | WXG

QMenuItem Examples
  DIM Form AS QForm
  DIM MainMenu AS QMainMenu
  DIM Item1 AS QMenuItem

  MainMenu.Parent = Form
  Item1.Caption = "&File"
  MainMenu.AddItems Item1

  Form.ShowModal


QMYSQL

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QMYSQL

QMYSQL Component

QMySQL is used to access your local or remote MySQL server. More information on MySQL can be obtained at http://www.mysql.com/

QMySQL Properties
Field | Type | R/W | Default | Support
Connected | INTEGER | R | WXG
Connected specifies whether you are currently connected to a MySQL server. Use the Connect method to establish a connection.
DB | ARRAY of STRING | R | WXG
DB returns a database list that are currently available on the MySQL server.
DBCount | INTEGER | R | WXG
DBCount returns the number of databases that are currently available on the MySQL server.
ColCount | INTEGER | R | WXG
ColCount returns the number of columns in the table. ColCount is used after an SQL query to determine the number of columns in the resulting table.
FieldCount | INTEGER | R | WXG
FieldCount returns the number of columns in the table. FieldCount is used after an SQL query to determine the number of columns in the resulting table.
Field.Decimals | INTEGER | R | WXG
Field.Decimals returns the number of decimals in the field.
Field.Flags | INTEGER | R | WXG
Field.Flags returns the flag settings. Refer to MYSQL.INC for supported values.
Field.Length | INTEGER | R | WXG
Field.Length returns the width of the column.
Field.MaxLength | INTEGER | R | WXG
Field.MaxLength returns the maximum width of the selected set. A result set can have multiple fields (or columns), Field.MaxLength returns the largest of these.
Field.Name | STRING | R | WXG
Field.Name returns the name of the column.
Field.Table | STRING | R | WXG
Field.Type | INTEGER | R | WXG
Field.Type returns the type of field. Refer to MYSQL.INC for supported values.
Length | ARRAY of INTEGER | R | WXG
Length returns the length of each field. Make sure a call to FetchLengths is made.
Row | ARRAY of STRING | R | WXG
Row returns the value stored in the particular Row for the current result set. The value is also dependent on the Field (or column). For example, Row(3) returns the value stored in Row 3 and whatever Column, ie. 2. Which is different from Row(3) of Column 3 for example.
RowCount | INTEGER | R | WXG
Table | ARRAY of STRING | R | WXG
Table returns a list of tables for the current database.
TableCount | INTEGER | R | WXG

QMySQL Methods
Method | Type | Description | Params | Support
Close | SUB | Disconnect from MySQL | 0 | WXG
Connect | FUNCTION (Host$, User$, Passwd$) AS INTEGER | Connect to MySQL | 3 | WXG
CreateDB | FUNCTION (DB$) AS INTEGER | Creates a new database | 1 | WXG
DropDB | FUNCTION (DB$) AS INTEGER | Drop database | 1 | WXG
EscapeString | FUNCTION (S$, Length%) AS STRING | Parses binary string S$ and returns a string that can be used in Blob fields | 2 | WXG
FetchField | FUNCTION AS INTEGER | Fetch next field | 0 | WXG
FetchLengths | FUNCTION AS INTEGER | Fetch lengths for current row | 0 | WXG
FetchRow | FUNCTION AS INTEGER | Fetch next row | 0 | WXG
FieldSeek | FUNCTION (Position%) | Jump to Field Position% | 1 | WXG
Query | FUNCTION (Query$) AS INTEGER | Query database | 1 | WXG
RealConnect | SUB (Host$, User$, Passwd$, DB$, Port%, UnixSock$, Flags%) | Connect to MySQL | 7 | WXG
Refresh | FUNCTION (RefreshFlags%) AS INTEGER | Refresh database | 1 | WXG
RowBlob | FUNCTION (Row%, Bytes&) AS STRING | Returns the binary blob as a string | 2 | WXG
RowSeek | FUNCTION (Row%) | Jump to a certain row | 1 | WXG
SelectDB | FUNCTION (DB$) AS INTEGER | Select database to use | 1 | WXG

QMySQL Events
Event Type Occurs when... Params

QMySQL Examples
' This simply checks that you have a working MySQL server and lets you
' view some database fields.

$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

DECLARE SUB Button1Click (Sender AS QBUTTON)
DECLARE SUB DBListBoxClick (Sender AS QLISTBOX)
DECLARE SUB TableListBoxClick (Sender AS QLISTBOX)
DECLARE SUB SQLFormResize (Sender AS QFORM)

DIM Font AS QFONT
    Font.Name = "Courier"
DIM MySQL AS QMYSQL

    CREATE SQLForm AS QFORM
        Caption = "Connected"
        Width = 330
        Height = 300
        Center
        CREATE DBLabel AS QLABEL
            Caption = "Select a database:"
        END CREATE
        CREATE DBListBox AS QLISTBOX
            Top = 20
            Width = 150
            Height = 100
            OnClick = DBListBoxClick
        END CREATE
        CREATE TableListBox AS QLISTBOX
            Top = 20
            Left = 165
            Width = 150
            Height = 100
            OnClick = TableListBoxClick
        END CREATE
        CREATE FieldEdit AS QRICHEDIT
            Top = 130
            Width = SQLForm.ClientWidth
            Height = SQLForm.ClientHeight-130
            ReadOnly = TRUE
            WordWrap = FALSE
            PlainText = TRUE
            Font = Font
            ScrollBars = ssBoth
        END CREATE
        CREATE Grid AS QSTRINGGRID
            Top = 130
            Width = SQLForm.ClientWidth
            Height = SQLForm.ClientHeight-130
            AddOptions(goEditing)
        END CREATE
        OnResize = SQLFormResize
    END CREATE

CREATE Form AS QFORM
    Caption = "SQL Demo"
    Width = 230
    Height = 174
    Center
    CREATE Label1 AS QLABEL
        Caption = "Host:"
        Left = 44
        Top = 23
    END CREATE
    CREATE Label2 AS QLABEL
        Caption = "User name:"
        Left = 16
        Top = 50
        Width = 57
    END CREATE
    CREATE Label3 AS QLABEL
        Caption = "Password:"
        Left = 21
        Top = 79
        Width = 54
    END CREATE
    CREATE Edit1 AS QEDIT
        Text = ""
        Left = 83
        Top = 18
    END CREATE
    CREATE Edit2 AS QEDIT
        Text = ""
        Left = 83
        Top = 46
    END CREATE
    CREATE Edit3 AS QEDIT
        Text = ""
        Left = 83
        Top = 74
    END CREATE
    CREATE Button1 AS QBUTTON
        Caption = "&Ok"
        Left = 32
        Top = 112
        Kind = 1
        Default = 1
        NumBMPs = 2
        OnClick = Button1Click
    END CREATE
    CREATE Button2 AS QBUTTON
        Caption = "E&xit"
        Left = 118
        Top = 112
        Kind = 6
        NumBMPs = 2
    END CREATE
    ShowModal
END CREATE

SUB Button1Click
    DIM I AS INTEGER

    IF MySQL.Connect(Edit1.Text, Edit2.Text, Edit3.Text) = 0 THEN
       ShowMessage("Failed to connect to MySQL Server")
       EXIT SUB
    END IF

    FOR I = 0 TO MySQL.DBCount-1
        DBListBox.AddItems(MySQL.DB(I))
    NEXT

    SQLForm.ShowModal

    SUB DBListBoxClick (Sender AS QLISTBOX)

        IF Sender.ItemIndex < 0 THEN EXIT SUB
        IF MySQL.SelectDB(Sender.Item(Sender.ItemIndex)) = 0 THEN
            ShowMessage("Could not open "+Sender.Item(Sender.ItemIndex))
            EXIT SUB
        END IF

        TableListBox.Clear
        FOR I = 0 TO MySQL.TableCount-1
            TableListBox.AddItems(MySQL.Table(I))
        NEXT
    END SUB

    SUB TableListBoxClick (Sender AS QLISTBOX)
        DIM Str AS STRING, J AS INTEGER

        IF Sender.ItemIndex < 0 THEN EXIT SUB
        IF MySQL.Query("show columns from "+Sender.Item(Sender.ItemIndex)) = 0 THEN
            ShowMessage("Could not query "+Sender.Item(Sender.ItemIndex))
            EXIT SUB
        END IF

        FieldEdit.Clear
        Grid.ColCount = MySQL.FieldCount
        I = 0
        WHILE MySQL.FetchField
            Grid.Cell(I,0) = MySQL.Field.Name
            I++
        WEND

        Grid.RowCount = MySQL.RowCount+1
        IF MySQL.RowCount THEN
            J = 1
            WHILE MySQL.FetchRow
                MySQL.FieldSeek(0)
                FOR I=0 to MySQL.NumFields-1
                    Grid.Cell(I,J) = MySQL.Row(I)
                NEXT
                J++
            WEND
        END IF
    END SUB
END SUB

SUB SQLFormResize (Sender AS QFORM)
    Grid.Height = Sender.ClientHeight - Grid.Top
    Grid.Width = Sender.ClientWidth-1
    TableListBox.Width = Sender.ClientWidth-1 - TableListBox.Left
END SUB

IF MySQL.Connected THEN MySQL.Close
END


QNOTIFYICONDATA

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QNOTIFYICONDATA

QNOTIFYICONDATA Component

QNotifyIconData is not a visible component, it's a data type with the form
   TYPE QNotifyIconData
     cbSize AS INTEGER       ' Read only
     hWnd AS INTEGER
     uID AS INTEGER
     uFlags as INTEGER
     uCallBackMessage as INTEGER
     hIcon as INTEGER
     szTip as STRING
   END TYPE
Its use is primarily restricted to the Shell_NotifyIcon API call, but you may find other uses for it as well.


QOPENDIALOG

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QOPENDIALOG

QOPENDIALOG Component

QOpenDialog displays a standard Window's file selection dialog box. Does not show shortcuts on WinXP. Note your current working will change to the directory last used by QOpenDialog.

QOpenDialog Properties
Field | Type | R/W | Default | Support
Caption | STRING | RW | W
FileName | STRING | RW | WX
Filter | STRING | RW | W
FilterIndex | INTEGER | RW | 1 | W
InitialDir | STRING | RW | W

QOpenDialog Methods
Method | Type | Description | Params | Support
Execute | FUNCTION | Returns TRUE or FALSE | 0 | WX

QOpenDialog Examples
  '-- Simple demo
  DIM OpenDialog AS QOpenDialog

  IF OpenDialog.Execute THEN
    ShowMessage "You selected "+OpenDialog.FileName
  END IF

'-- Using filters
  DIM OpenDialog AS QOpenDialog

  OpenDialog.Filter = "Picture files|*.BMP;*.ICO|All Files|*.*"
  OpenDialog.FilterIndex = 2    '' Use "All Files" as our default

  IF OpenDialog.Execute THEN
    ShowMessage "You selected "+OpenDialog.FileName
  END IF

Prev Component

Contents

Next Component


QOLEOBJECT

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QOLEOBJECT

QOLEOBJECT Component

QOleObject implements an automation client. Type checking is disabled for this component, see examples on how this can help you. This component is currently in an experimental stage. Longs, Doubles, and Strings are currently supported, other data types may be added later.

QOleObject Properties
Field Type R/W Default

QOleObject Methods
Method | Type | Description | Params
Container | QOLECONTAINER | W
CreateObject | FUNCTION (ClassName AS STRING) AS INTEGER | Create COM object, with actual name or CLSID | 1
CreateRemote | FUNCTION (Host AS STRING, ClassName AS STRING) AS INTEGER | Create remote COM object, with actual name or CLSID | 2
Free | SUB | Release object | 0
GetIDofName | FUNCTION (Name AS STRING) AS INTEGER | Returns the ID of an identifier, good for checking if it exists. Returns -1 if name is not found. | 1
GetObject | FUNCTION (ClassName AS STRING) AS INTEGER | Get active COM object, with actual name or CLSID | 1
Invoke | FUNCTIONI (ID AS STRING, Params, ...) AS VARIANT | Invoke method/property | Infinite
InvokeCopy | SUB (ID AS STRING, Object AS QOLEOBJECT) | Copy object (might not work... yet) | 2

QOleObject Events
Event Type Occurs when... Params

QOleObject Examples
' This example requires MS WORD
' If you're using a localized version with a foreign language,
' you'll have to adjust the parameter names to match.
' Comments in italics indicate the old style syntax before
' type checking was disabled.  You can choose either approach.

$ESCAPECHARS ON

DIM Object AS QOLEOBJECT

'Object.CreateObject("{000209FE-0000-0000-C000-000000000046}")
Object.CreateObject("Word.Basic")
'Object.Invoke("AppShow")
Object.AppShow
'Object.Invoke("AppMaximize", "", 1)
Object.AppMaximize("", 1)
'Object.Invoke("FileNew")
Object.FileNew

PRINT Object.Bold  '-- is bold enabled?

Object.Insert("Hello world!\n")
Object.Bold

PRINT Object.Bold  '-- Bold should be enabled

Object.Insert("Rapid-Q is awesome!\n")
Object.Bold(0)     '-- Turn Bold off

SLEEP 5

Object.Free


QOLECONTAINER

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QOLECONTAINER

QOLECONTAINER Component

QOleContainer is an ActiveX container whose properties and methods can be accessed similar to QOleObject. My best guess is that Rapid-Q uses the COM IDispatch interface for this component. The component is mostly unfinished but has some basic functionality. There is no documented way to trap an EVENT such as OnClick, etc. You can get a COM object viewer from the MS VC++ software development kit or from :
http://www.microsoft.com/com/resources/oleview.asp
http://download.microsoft.com/download/ole/ole2v/3.5/W351/EN-US/Ole2v.exe

QOleContainer Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
AllowInPlace | INTEGER | RW | True
AutoShow | INTEGER | RW | True
BorderStyle | INTEGER | RW | bsSingle
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW | 0
Modified | INTEGER | RW | False
Parent | QFORM/QPANEL/QTABCONTROL | W
ShowHint | INTEGER | RW | False
SizeMode | INTEGER | RW | smClip
State | INTEGER | RW | osEmpty
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
Visible | INTEGER | RW | True

QOleContainer Methods
Method | Type | Description | Params
CreateObject | FUNCTION (ClassName AS STRING) AS INTEGER | Create new embedded object | 1
Free | SUB | Release object | 0
Invoke | FUNCTIONI (ID AS STRING, Params, ...) AS VARIANT | Invoke method/property | Infinite

QOleContainer Events
Event | Type | Occurs when... | Params
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4
OnObjectMove | SUB (Rect AS QRECT) | OLE Object has moved or resized | 1
OnResize | VOID | After OLE container is resized | 0

QOleContainer Examples
' This example requires GIF89.DLL which can be found on
' Rapid-Q's knowledge base page.
' Make sure to register the .DLL if you haven't already
' c:\blah> regsvr32 gif89.dll
' Note, example works best if you load an animated GIF file.

CREATE Form AS QFORM
Caption = "Animated GIFs"
Center
Visible = 1
CREATE GifAnimation AS QOLECONTAINER
Align = alClient
CreateObject("Gif89.Gif89.1")
'-- FileName is a property in GIF89.DLL
FileName = "anim.gif"
END CREATE
Visible = 0
END CREATE
Form.ShowModal
GifAnimation.Free

Example #2 (shockwave player)
You need to have an edit in the Flash Movie with a variable
named 'texto' (dynamic).
CREATE Form AS QFORM
    Caption = "Swf"
    Center
    Visible = 1
    CREATE swf AS QOLECONTAINER
        CreateObject("ShockwaveFlash.ShockwaveFlash.5")
        movie= "c:\windows\escritorio\p1.swf"
        setvariable ("t","texto")
        height =200
        width = 200
    END CREATE
    Visible = 0
END CREATE

Form.ShowModal
'need to call this before program ends:
swf.Free

Example #3 (Create your own web page)
' ----------------------------------
$ESCAPECHARS ON
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
Declare Sub OnClose_frmRapidView
'
Sub DummyProc
End Sub
CREATE frmRapidView AS QFORM
     Autoscroll = false
     WindowState = wsMaximized
     Caption =  "Demo RQ & HTML"
     Visible = True
     WndProc = DummyProc
     CREATE msHTML AS QOLECONTAINER
         Align = alClient
         createObject("Shell.Explorer.1")
     END CREATE
     Visible = False
     Onclose = OnClose_frmRapidView
End Create

DIM c as string
c = "about:<head><basefont face=\"courrier\"></head><body scroll=\"no\">"
c = c + "<center><br><h1>Text Out, Anything you want<BR> One more line<br>WILL BE TOO SLOW</center></h1>"
c = c + "<H2><HR><U>GOOD LUCK</U></H2></basefont></head>"
msHTML.navigate(c)

Sub OnClose_frmRapidView
     application.Terminate
     End
End Sub
'
' ********************************************
frmRapidView.ShowModal
' ********************************************

Example #4 (Simple web browser)
' frmTestOle        J.Philippe, Frbruary 12th, 2003
$TYPECHECK ON
$INCLUDE "RapidQ.inc"
Const CRLF = Chr$(10) & Chr$(13)
'web site with properties and methods
DefStr sURL = "http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dninvbs/html/theinternetexplorerobjectmodel.asp"
Declare Function DeleteUrlCacheEntry Lib "wininet.dll" Alias_
 "DeleteUrlCacheEntryA" (ByRef lpszUrlName As String) As Long
'
Declare Sub OnClose_frmTestOle
Declare Sub OnClic_AnyMenu (Sender As QMenuItem)
'
Create frmTestOle As QForm
    WindowState = 2 ' wsMaximized
    Caption = "frmTestOle V 1.0.0       Loading URL in INTERNET EXPLORER"
    OnClose = OnClose_frmTestOle
    Visible = True
    Create oleIE As QOleContainer
        Align = 5 ' =alClient
        createObject("Shell.Explorer.1")  'also try  "Shell.Explorer.2"
    End Create
    Visible = False
End Create
frmTestOle.Show
DeleteUrlCacheEntry (sURL)  ' Delete the entry from the cache, forces a new download
oleIE.Navigate (sUrl)
Do               ' bugs without this
    DoEvents
Loop Until oleIE.Busy = False
'
frmTestOle.Caption = "frmTestOle V 1.0.0               Loaded"
'
' OLE IE PROPERTIES TEST
DefInt iReturn = MessageDlg (("        Application = " & Str$(oleIe.Application)            & "     ???" _
   & CRLF & "          Busy Flag = " & Str$(oleIE.Busy)                   & "     Work  0, -1)" _
   & CRLF & "           Document = " & Str$(oleIE.Document)               & "     ???" _
   & CRLF & "             Height = " & Str$(oleIE.Height)                 & "     in OLeContainer" _
   & CRLF & "              Width = " & Str$(oleIE.Width)                  & "     in OleContainer" _
   & CRLF & "       LocationName = " & oleIE.LocationName                 & "     Works" _
   & CRLF & "        LocationUrl = " & oleIE.LocationUrl                  & "     Works" _
   & CRLF & "             Parent = " & Str$(oleIE.Parent)                 & "     " _
   & CRLF & "  TopLevelContainer = " & Str$(oleIE.TopLevelContainer)      & "     " _
   & CRLF & "               Type = " & oleIE.Type                         & "     "), 2, 4, 0) 'mtInformation,MBOK
'
' The Following Properties Bug :
'             & "\n FullScreen = " & Str$(oleIE.FullScreen)  ' bugs
'             & "\n   FullName = " & oleIE.FullName          ' bugs
'             & "\n       Name = " & oleIE.Name              ' bugs
'             & "\n       Path = " & oleIE.Path              ' bugs
'             & "\n  StatusBar = " & Str$(oleIE.StatusBar)   ' bugs
'             & "\n    StatusText = " & oleIE.StatusText     ' bugs
'             & "\n       ToolBar = " & Str$(oleIE.ToolBar)  ' bugs
'             & "\n       Visible = " & Str$(oleIE.Visible)  ' bugs yet in OleContainer ???
'  I Dont even try Methods :)
'
frmTestOle.Caption = "frmTestOle V 1.0.0"
'
' *************************************
frmTestOle.Visible = False
frmTestOle.ShowModal
' *************************************
'
Sub OnClose_frmTestOle
    oleIE.Quit
    oleIE.Free
    Application.Terminate
    End
End Sub
'


QOUTLINE

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QOUTLINE

QOUTLINE Component

QOutLine implements the old style Win3.1 tree view.

QOutLine Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
BMPClosed | STRING | W
BMPLeaf | STRING | W
BMPMinus | STRING | W
BMPOpen | STRING | W
BMPPlus | STRING | W
BMPHandleClosed | RESOURCE | W
BMPHandleLeaf | RESOURCE | W
BMPHandleMinus | RESOURCE | W
BMPHandleOpen | RESOURCE | W
BMPHandlePlus | RESOURCE | W
BorderStyle | INTEGER | RW | bsSingle
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
Item | ARRAY of STRING | RW
ItemHeight | INTEGER | RW | 13
ItemIndex | INTEGER | RW
ItemSeparator STRING RW \
Left | INTEGER | RW | 0
LineCount | INTEGER | RW
OutLineStyle | INTEGER | RW | osTreePictureText
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
Row | INTEGER | RW
ScrollBars | INTEGER | RW | ssBoth
ShowHint | INTEGER | RW | False
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Visible | INTEGER | RW | True
Width | INTEGER | RW

QOutLine Methods
Method | Type | Description | Params
AddChild | SUB (Index%, String$) | Add child at Index% | 2
AddLines | SUBI | Add lines to Outline | STRING, Infinite
AddOptions | SUBI | Add Outline options | INTEGER, Infinite
Clear | SUB | Clear all items | 0
DelLines | SUBI | Delete lines from Outline | INTEGER, Infinite
DelOptions | SUBI | Delete Outline options | INTEGER, Infinite
Insert | SUB (Index%, String$) | Insert node at Index% | 2

QOutLine Events
Event | Type | Occurs when... | Params
OnClick | VOID | User clicked on item | 0
OnDblClick | VOID | User double clicked on item | 0

QOutLine Examples
CREATE Form AS QForm
  CREATE OutLine AS QOutLine
    AddLines "Parent 1", _
             " Child of Parent 1", _
             "  Child of Child of Parent 1", _
             "Parent 2", _
             "Parent 3", _
  END CREATE
  Center
  ShowModal
END CREATE


QOVALBTN

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QOVALBTN

QOVALBTN Component

QOvalbtn is similar to QCoolBtn, except the button looks round/oval.

QOvalbtn Properties >
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
BMP | STRING | W | W
BMPHandle | RESOURCE | W | W
Caption | STRING | RW | WX
Color | INTEGER | RW | WX
ColorHighLight | INTEGER | RW | W
ColorShadow | INTEGER | RW | W
Cursor | INTEGER | RW | crDefault | W
Down | INTEGER | RW | False | W
Enabled | INTEGER | RW | TrueWX
Flat | INTEGER | RW | False | WX
Font | QFONT | W | W
GroupIndex | INTEGER | RW | 0 | W
Height | INTEGER | RW | WX
Hint | STRING | RW | WX
Layout | INTEGER | RW | blBMPLeft | W
Left | INTEGER | RW | 0 | WX
NumBMPs | INTEGER | RW | W
Parent | QFORM/QPANEL/QTABCONTROL | W | WX
ShowHint | INTEGER | RW | False | WX
Spacing | INTEGER | RW | W
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WX
Transparent | INTEGER | RW | False | W
TransParentColor | INTEGER | RW | W
Width | INTEGER | RW | WX
Visible | INTEGER | RW | True | WX

QOvalbtn Methods
Method | Type | Description | Params | Support
StartDrag | SUB | Allows Button to be dragged | 0 | W

QOvalbtn Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on the button | 0 | WX
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WX
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | WX
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WX

QOvalbtn Examples
CREATE Form AS QForm
  CREATE OvalBtn AS QOvalBtn
    Caption = "Oval Button"
    Color = &H00FF00
  END CREATE
  ShowModal
END CREATE


QPANEL

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QPANEL

QPANEL Component

QPanel implements a generic container for your components.

QPanel Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Alignment | INTEGER | RW | taCenter | W
BevelInner | INTEGER | RW | bvNone | W
BevelOuter | INTEGER | RW | bvRaised | W
BevelWidth | INTEGER | RW | 1 | W
BorderStyle | INTEGER | RW | bsNone | W
'-- Bevel Style
CONST bvNone = 0
CONST bvLowered = 1
CONST bvRaised = 2

'-- Bevel Border
CONST bpNone = 0 '-- No visible border
CONST bpSingle = 1 '-- Single-line border
Caption | STRING | RW | W
ClientHeight | INTEGER | RW | WX
ClientWidth | INTEGER | RW | WX
Color | INTEGER | RW | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WX
Font | QFONT | W | W
Height | INTEGER | RW | WX
Hint | STRING | RW | W
Left | INTEGER | RW | 0 | WX
Parent | QFORM/QPANEL/QTABCONTROL | W | WX
ShowHint | INTEGER | RW | False | W
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WX
Width | INTEGER | RW | WX
Visible | INTEGER | RW | True | WX

QPanel Methods
Method | Type | Description | Params | Support
Repaint | SUB | Refreshes panel and all contents | 0 | W

QPanel Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on open area of panel | 0 | WX
OnDblClick | VOID | User double clicked panel | 0 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | W
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves over panel | 3 | W
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | W

QPanel Examples
  DIM Form AS QForm
  DIM Button AS QButton
  DIM Panel AS QPanel

  Panel.Parent = Form
  Panel.Width = 100
  Button.Parent = Panel

  Form.ShowModal


QPOPUPMENU

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QPOPUPMENU

QPOPUPMENU Component

QPopupMenu provides a popup menu selection control

QPopupMenu Properties
Field | Type | R/W | Default
Alignment | INTEGER | RW | paLeft
Alignment determines where the pop-up menu appears when the user clicks the right mouse button.
0 = paLeft - Pop-up menu appears with its top left corner under the mouse pointer
1 = paRight = Pop-up menu appears with its top right corner under the mouse pointer
2 = paCenter - Pop-up menu appears with the top center of the menu under the mouse pointer
AutoPopup | INTEGER | RW | True
AutoPopup determines whether the pop-up menu appears automatically when the user clicks the right mouse button.
Handle | INTEGER | R
Handle is the Windows menu handle for the menu.
Tag | INTEGER | RW
Tag stores an integer value, but is not used internally.
WindowHandle | INTEGER | RW
WindowHandle is the handle of the window that uses the menu.

QPopupMenu Methods
Method | Type | Description | Params
AddItems | SUBI | Add Item to Menu | QMENUITEMs, Infinite
DelIndex | SUB (index AS LONG) | Delete items, by index, from menu | 1
DelItems | SUBI | Delete items from menu | QMENUITEMs, Infinite
Insert | SUB (I%, Item AS QMENUITEM) | Insert an item | 2
Popup | SUB (X%, Y%) | Popup menu at (X,Y) | 2

QPopupMenu Events
Event | Type | Occurs when... | Params
OnPopup | VOID | Just before the pop-up menu appears | 0

QPopupMenu Examples
  DIM PopupMenu AS QPopupMenu
  DIM Item1 AS QMenuItem
  DIM Item2 AS QMenuItem

  Item1.Caption = "Item 1"
  Item2.Caption = "Item 2"
  PopupMenu.AddItems(Item1, Item2)

  PopupMenu.Popup(100,100)


QRADIOBUTTON

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QRADIOBUTTON

QRADIOBUTTON Component

QRadioButton is a simple radio item. If you want to group radiobuttons, use a container like QPanel.

QRadioButton Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Caption | STRING | RW | WXG
Checked | INTEGER | RW | False | WXG
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | W
Height | INTEGER | RW | WXG
Hint | STRING | RW | WXG
Left | INTEGER | RW | 0 | WXG
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
ShowHint | INTEGER | RW | False | WXG
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WXG
Visible | INTEGER | RW | True | WXG
Width | INTEGER | RW | WXG

QRadioButton Methods
Method Type Description Params

QRadioButton Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on radio button | 0 | WXG

QRadioButton Examples
  DIM Form AS QForm
  DIM Radio1 as QRadioButton
  DIM Radio2 as QRadioButton
  DIM Radio3 as QRadioButton

  Radio1.Parent = Form
  Radio1.Top = 10
  Radio1.Caption = "Item 1"
  Radio2.Parent = Form
  Radio2.Top = 35
  Radio2.Caption = "Item 2"
  Radio3.Parent = Form
  Radio3.Top = 60
  Radio3.Caption = "Item 3"

  Form.ShowModal


QRECT

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QRECT

QRECT Component

QRect is not a visible component, it's a data type with the form
   TYPE QRect
     Top    AS INTEGER
     Left   AS INTEGER
     Right  AS INTEGER
     Bottom AS INTEGER
   END TYPE


QREGISTRY

Rapid-Q Documentation by William Yu (c)1999, corrected by Jacques Philippe Appendix A: QREGISTRY

QREGISTRY Component

QRegistry encapsulates functions that operate on the Window's system registry. The Registry is composed of Keys and SubKeys. Each Key and SubKey can contain one or more variables named Values. These values have a ValueName and a ValueData.

Example :
Key HKEY_CLASSES_ROOT .Bas\Shell\Open\Command
contains a Default value who's ValueName is "" and whose value is "C:\Rapidq\RapidQ.Exe %1"
ValueName maybe "AnyName". The default ValueName is "" .
The Registry can be edited with Regedit.Exe or regedt32.Exe.

QRegistry Properties
Field | Type | R/W | Default
CurrentKey | INTEGER | R
CurrentPath | STRING | R
GetDataSize(ValueName$) | INTEGER | R
GetDataType(ValueName$) | INTEGER | R
HasSubKeys | INTEGER | R
KeyItemCount | INTEGER | R
ValueItemCount | INTEGER | R
RootKey | INTEGER | RW | HKEY_CURRENT_USER

QRegistry Methods
Method | Type | Description | Params
CloseKey | SUB | Closes opened key | 0
CreateKey | FUNCTION (Key$) AS INTEGER | Creates a new key in CurrentPath. | 1
DeleteKey | FUNCTION (Key$) AS INTEGER | Deletes key. | 1
DeleteValue | FUNCTION (ValName$) AS INTEGER | Deletes a value data. | 1
KeyExists | FUNCTION (Key$) AS INTEGER | Returns 0 or 1 if key exists. | 1
KeyItem | FUNCTION (Index%) AS STRING | Retrieve the names of the subkeys | 1
MoveKey | FUNCTION (OldKey$, NewKey$, Delete%) | Moves existing key, subkeys, and data values. | 3
OpenKey | FUNCTION (Key$, CanCreate%) | CanCreate specifies whether to create the specified key if it does not exist. | 2
ReadBinary | (*)FUNCTION (ValueName$, Index%) AS BYTE | Return binary value of specified key(Bug : Index must Start at -1) | 2
ReadFloat | FUNCTION (ValueName$) AS DOUBLE | Return double value of specified key | 1
ReadInteger | FUNCTION (ValueName$) AS INTEGER | Return integer value of specified key | 1
ReadString | FUNCTION (ValueName$) AS STRING | Return string value of specified key | 1
RegistryConnect | FUNCTION (CompName$) AS INTEGER | Establishes connection to another computer's registry. | 1
RenameValue | (*)SUB (OldValueName$, NewValueName$) | Renames existing data value. | 2
ValueExists | FUNCTION (ValueName$) AS INTEGER | Returns 0 or 1 if data value Value$ exists. | 1
ValueItem | FUNCTION (Index%) AS STRING | Retrieve the names of the data values | 1
WriteBinary | (*)SUB (ValueName$, BYTE(), Size%) | Write Array of BYTEs in the specified key | 3
WriteFloat | (*)SUB (ValeName$, ValueData#) | Write double value in the specified key | 2
WriteInteger | (*)SUB (ValueName$, ValueData&) | Write integer value in the specified key | 2
WriteString | (*)SUB (ValueName$, ValueData$) | Write string in the specified key | 2
Notes :
- READ and WRITE requires the mother KEY to be OPENED first with OpenKey(Key)
- WRITE subs Create ValueName if it does not exist
- MOVEKEY sets undefined ValueDatas of String type to "", which can be a problem.
- MOVEKEY with Delete% set to one is like renaming a key.

Common Windows registry constants are
Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_USERS = &H80000003
Const HKEY_PERFORMANCE_DATA = &H80000004
Const HKEY_CURRENT_CONFIG = &H80000005
Const HKEY_DYN_DATA = &H80000006
QRegistry Events
Event Type Occurs when... Params

QRegistry Examples
'  Detect if your computer is connected to the internet
Const HKEY_LOCAL_MACHINE = &H80000002
DIM Registry AS QRegistry

Registry.RootKey = HKEY_LOCAL_MACHINE
Registry.OpenKey("System\CurrentControlSet\Services\RemoteAccess", 0)

'(index was 0 originally, but due to ReadBinary bug it must be -1)
IF Registry.ReadBinary("Remote Connection", -1) = 1 THEN
  ShowMessage("You're connected!")
ELSE
  ShowMessage("You're not connected!")
END IF
Registry.CloseKey

' ---- EXAMPLE 2 by Jacques Phillipe -----------------
Const HKEY_CURRENT_USER  = &H80000001
'
DIM Registry AS QRegistry

With Registry
   .RootKey = HKEY_CURRENT_USER
'  Write Key and Values
'  --------------------
   .OpenKey("TestToDelete", 1)   ' Create Key if dont exist
        .WriteInteger("MyInteger", 1234567890)
        .WriteString ("Mystring", "1234567890")
        DefByte MyBinary(10) = {1,2,3,4,5,6,7,8,9,0}
        .WriteBinary ("MyBinary", MyBinary(), 10)
   .CloseKey
'  Read Values
'  -----------
   .OpenKey("TestToDelete", 1)
        Print "MyInteger=";.ReadInteger("MyInteger")
        Print " Mystring=";.ReadString ("Mystring")
        DefInt N
        For N = -1 To 8  ' This is a QREGISTRY 'bug' Binary index starts at -1
            Print "MyBinary(";N")=";.ReadBinary ("MyBinary", N)
        Next N
   .CloseKey
'  Delete the Key and all its Values
' ----------------------------------
   .DeleteKey ("TestToDelete")
End With
' Exit Console
' ------------
DefStr sExit
Input "    FINISHED               CR to QUIT ", sExit
Application.Terminate
' -------------------------------------


QRICHEDIT

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QRICHEDIT

QRICHEDIT Component

QRichedit implements a fully featured multi-line text edit control.

QRichedit Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
Alignment | INTEGER | RW | taLeftJustify | W
Alignment determines how the text is aligned within the edit control.
BorderStyle | INTEGER | RW | bsSingle | W
Color | INTEGER | RW | W
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W | WX
Handle | INTEGER | R | W
Height | INTEGER | RW | WXG
HideScrollBars | INTEGER | RW | True | WG
HideSelection | INTEGER . | RW | True | W
Set to False, or 0, to automatically scroll to show new content.
Hint | STRING | RW | WG
Left | INTEGER | RW | 0 | WXG
Line | ARRAY of STRING | RW | WXG
LineCount | INTEGER | RW | WXG
Modified | INTEGER | R | WG
Parent | QFORM/QPANEL/QTABCONTROL | W | WXG
PopupMenu | QPOPUPMENU | W | W
Plaintext | INTEGER | RW | False | W
Readonly | INTEGER | RW | False | WXG
ScrollBars | INTEGER | RW | ssNone | WXG
SelAttributes | QFONT | W | W
SelLength | INTEGER | RW | WXG
SelLength is the number of characters that are selected.
SelStart | INTEGER | RW | WXG
SelStart is the position of the first selected character in the text. If there is no selected text, SelStart indicates the position of the cursor.
SelText | STRING | RW | WXG
SelText is the selected portion of the edit control's text.
ShowHint | INTEGER | RW | False | WG
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Text | STRING | RW | WXG
Top | INTEGER | RW | 0 | WXG
WantTabs | INTEGER | RW | False | W
WantTabs determines whether the user can insert tab characters into the text.
Width | INTEGER | RW | WXG
WhereX | INTEGER | R | WXG
WhereY | INTEGER | R | WXG
Wordwrap | INTEGER | RW | True | W
Visible | INTEGER | RW | True | WXG

QRichedit Methods
Method | Type | Description | Params | Support
AddStrings | SUBI | Add strings | STRING, Infinite | WXG
Clear | SUB | Clear entire text | 0 | WXG
CopyToClipboard | SUB | Copy selected text to clipboard | 0 | W
CutToClipboard | SUB | Cut selected text to clipboard | 0 | W
LoadFromFile | SUB (FileName$) | Load text from a file | 1 | WXG
LoadFromStream | SUB (Stream AS QFILESTREAM/QMEMORYSTREAM) | Load text from a stream | 1 | WX
PasteFromClipboard | SUB | Paste text from clipboard | 0 | W
SaveToFile | SUB (FileName$) | Save text to a file | 1 | WXG
SaveToStream | SUB (Stream AS QFILESTREAM/QMEMORYSTREAM) | Save text to a stream | 1 | W
SelectAll | SUB | Selects all text from Richedit | 0 | WXG

QRichedit Events
Event | Type | Occurs when... | Params | Support
OnChange | VOID | Text changes | 0 | WG
OnKeyDown | SUB (Key AS WORD, Shift AS INTEGER) | Key held down | 2 | WG
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1 | WG
OnKeyUp | SUB (Key AS WORD, Shift AS INTEGER) | Key released | 2 | WG
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WX
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 2 | WX
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WX

QRichedit Examples
  $INCLUDE "RAPIDQ.INC"

  DIM Form AS QForm
  DIM RichEdit AS QRichEdit

  RichEdit.Parent = Form
  RichEdit.Scrollbars = ssBoth
  RichEdit.AddString "Hello world!"

  Form.ShowModal


QSAVEDIALOG

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QSAVEDIALOG

QSAVEDIALOG Component

QSaveDialog displays a Save As dialog box for saving files.

QSaveDialog Properties
Field | Type | R/W | Default
Caption | STRING | RW
FileName | STRING | RW
Filter | STRING | RW
FilterIndex | INTEGER | RW | 1
InitialDir | STRING | RW

QSaveDialog Methods
Method | Type | Description | Params
Execute | FUNCTION | Returns TRUE or FALSE | 0

QSaveDialog Examples
  '-- Simple demo
  DIM SaveDialog AS QOpenDialog

  IF SaveDialog.Execute THEN
    ShowMessage "You want to save as "+SaveDialog.FileName
  END IF


QSCROLLBAR

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QSCROLLBAR

QSCROLLBAR Component

QScrollBar is a Windows scroll bar, used to scroll contents of a window, form, or control. It can also act as a simple trackbar.

QScrollBar Properties
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Align determines how the control aligns within its parent control.
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WX
Handle | INTEGER | R | W
Height | INTEGER | RW | WX
Hint | STRING | RW | WX
Kind | INTEGER | RW | sbHorizontal | WX
Kind specifies whether the scrollbar is horizontal or vertical.
0 = sbHorizontal -- Scrollbar is horizontal.
1 = sbVertical -- Scrollbar is vertical.
LargeChange | INTEGER | RW | 1 | WX
LargeChange determines how much Position changes when the user clicks on the scrollbar on either side of the thumb or pressed PageUp or PageDown.
Left | INTEGER | RW | 0 | WX
Max | INTEGER | RW | 100 | WX
Min | INTEGER | RW | 0 | WX
PageSize | INTEGER | RW | 1 | W
PageSize specifies the distance along the trackbar.
Parent | QFORM/QPANEL/QTABCONTROL | W | WX
PopupMenu | QPOPUPMENU | W | W
Position | INTEGER | RW | 0 | WX
ShowHint | INTEGER | RW | False | WX
SmallChange | INTEGER | RW | 1 | WX
SmallChange determines how much Position changes when the user clicks the arrow buttons on the scrollbar or presses the arrow keys.
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WX
Width | INTEGER | RW | WX
Visible | INTEGER | RW | True | WX

QScrollBar Events
Event | Type | Occurs when... | Params | Support
OnChange | VOID | Scroll position changes | 0 | WX
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2 | W
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1 | W
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2 | W
OnScroll | SUB (ScrollCode AS BYTE, ScrollPos AS LONG) | Scrolling | 2 | W

QScrollBar Examples
' Color Palette for Rapid-Q by William Yu

DECLARE SUB ColorChange
DECLARE SUB Paint

CONST False = 0
CONST True = NOT False

'' Here's something that will convert your standard RGB to Rapid-Q's BGR.
'' And quite useless because an RGB function is already implemented!
FUNCTION ConvertRGB(R AS INTEGER, G AS INTEGER, B AS INTEGER) AS INTEGER
  ConvertRGB = (B SHL 16) OR (G SHL 8) OR R
END FUNCTION

CREATE Form AS QForm
  CREATE LabelRed AS QLabel
    Left = 10
    Top = 22
    Caption = "Red:"
  END CREATE
  CREATE LabelGreen AS QLabel
    Left = 5
    Top = 52
    Caption = "Green:"
  END CREATE
  CREATE LabelBlue AS QLabel
    Left = 10
    Top = 82
    Caption = "Blue:"
  END CREATE
  CREATE LabelNum1 AS QLabel
    Left = 270
    Top = 22
    Caption = "0"
  END CREATE
  CREATE LabelNum2 AS QLabel
    Left = 270
    Top = 52
    Caption = "0"
  END CREATE
  CREATE LabelNum3 AS QLabel
    Left = 270
    Top = 82
    Caption = "0"
  END CREATE
  CREATE ScrollRed AS QScrollBar
    Left = 50
    Top = 20
    Width = 200
    Height = 20
    Min = 0: Max = 255
    ShowHint =  True
    Hint = "Red Attribute"
    OnChange = ColorChange
  END CREATE
  CREATE ScrollGreen AS QScrollBar
    Left = 50
    Top = 50
    Width = 200
    Height = 20
    Min = 0: Max = 255
    ShowHint =  True
    Hint = "Green Attribute"
    OnChange = ColorChange
  END CREATE
  CREATE ScrollBlue AS QScrollBar
    Left = 50
    Top = 80
    Width = 200
    Height = 20
    Min = 0: Max = 255
    ShowHint =  True
    Hint = "Blue Attribute"
    OnChange = ColorChange
  END CREATE
  CREATE PaintBox AS QCanvas
    Left = 50
    Top = 110
    Height = 90
    Width = 200
    OnPaint = Paint
  END CREATE
  Caption = "Color Palette"
  Center
  ShowModal
END CREATE

SUB ColorChange
  LabelNum1.Caption = STR$(ScrollRed.Position)
  LabelNum2.Caption = STR$(ScrollGreen.Position)
  LabelNum3.Caption = STR$(ScrollBlue.Position)
  Paint
END SUB

SUB Paint
  PaintBox.Paint(0,0,ConvertRGB(ScrollRed.Position, ScrollGreen.Position, ScrollBlue.Position),&HFFFFFF)
END SUB


QSCROLLBOX

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QSCROLLBOX

QSCROLLBOX Component

QScrollBox is a scrolling window control.

QScrollBox Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
AutoScroll | INTEGER | RW | True
AutoScroll specifies whether scrollbars appear automatically on the scrolling windowed control if it is not large enough to display all of its controls.
BorderStyle | INTEGER | RW | bsSingle
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
HorzIncrement | INTEGER | RW | 8
HorzIncrement determines how far the display moves when the user clicks one of the small end arrows on the scrollbar.
HorzMargin | INTEGER | RW | 0
HorzMargin specifies the minimum number of pixels that must separater each control from the edge of the scrollbox.
HorzPosition | INTEGER | RW | 0
HorzPosition specifies the position of the thumb tab on the scrollbar.
HorzRange | INTEGER | RW | 0
HorzRange determines how far the scrollbox can move.
HorzTracking | INTEGER | RW | False
HorzTracking determines whether the scrollbox moves before the thumb tab is released.
HorzVisible | INTEGER | RW | True
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ShowHint | INTEGER | RW | False
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
VertIncrement | INTEGER | RW | 8
VertMargin | INTEGER | RW | 0
VertPosition | INTEGER | RW | 0
VertRange | INTEGER | RW | 0
VertTracking | INTEGER | RW | False
VertVisible | INTEGER | RW | True
Visible | INTEGER | RW | True

QScrollBox Methods
Method | Type | Description | Params
Repaint | SUB | Repaint control | 0

QScrollBox Events
Event | Type | Occurs when... | Params
OnClick | VOID | User clicked on scrollbox | 0
OnDblClick | VOID | User double clicked on scrollbox | 0
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4
OnResize | VOID | Scrollbox is resized | 0

QScrollBox Examples
CREATE Form AS QForm
  Center
  CREATE ScrollBox AS QScrollBox
    Left = 50
    CREATE Button AS QButton   '-- Create button inside scrollbox
    END CREATE
  END CREATE
  ShowModal
END CREATE


QSOCKET

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QSOCKET

QSOCKET Component

QSocket provides an easy to use interface to communicate between server/client with sockets.

QSocket Properties
Field | Type | R/W | Default | Support
Family | INTEGER | RW | AF_INET | W
Family specifies the address family.
LParam | INTEGER | RW | FD_CONNECT | W
LParam specifies the message to capture when you set WMessage and handle the message processing by assigning a new WndProc to your form.
MySocket | INTEGER | R | WXG
MySocket stores the result of operations such as Open. So instead of using the return value of Open, you can use the property MySocket.
Parent | QFORM | W | W
Protocol | INTEGER | RW | IPPROTO_IP | W
Tag | INTEGER | RW | WXG
Transferred | INTEGER | R | WXG
Type | INTEGER | RW | SOCK_STREAM | W
WMessage | INTEGER | RW | 0 | W
WMessage specifies a user defined message to be passed to your form for non-blocking calls, ie. Connecting.

QSocket Methods
Method | Type | Description | Params | Support
Accept | FUNCTION ClientSock%(Socket%) | Accepts Client Connection | 1 | WXG
Close | SUB (Socket%) | Closes Socket% file descriptor | 1 | WXG
Connect | FUNCTION Sock%(ServerName$, PortNum%) | Connect to server on PortNum% | 2 | WXG
ConnectionReady | FUNCTION Bool%(Sock%) | True/False if connection pending | 1 | WXG
GetHostIP | FUNCTION AS STRING | Returns host IP Address | 0 | WXG
GetHostName | FUNCTION AS STRING | Returns host name | 0 | WXG
GetPeerName | FUNCTION GetPeerName$(Socket%) | Returns peer name | 1 | WXG
IsClientReady | FUNCTION Bool%(Sock%, ClientSock%) | True/False if client is sending data | 2 | WXG
IsServerReady | FUNCTION Bool%(Sock%) | True/False if server is sending data | 1 | WXG
Open | FUNCTION Sock%(PortNum%) | Open TCP server on PortNum% | 1 | WXG
Peek | FUNCTION Peek$(Socket%, NumBytes%) | Peek information coming from socket, but do not clear. Win32 | 2 | W
Read | FUNCTION Message$(Socket%, NumBytes%) | Read NumBytes% | 2 | WXG
ReadByte | FUNCTION (Socket%) AS BYTE | Read a single byte | 2 | WXG
ReadLine | FUNCTION Message$(Socket%) | Read complete line | 1 | WXG
Write | SUB (Socket%, Message$, NumBytes%) | Sends NumBytes% from Message$ | 3 | WXG
WriteByte | SUB (Socket%, B AS BYTE) | Sends a single byte | 2 | WXG
WriteLine | FUNCTION Bytes%(Socket%, Message$) | Send Message$ | 2 | WXG

QSocket Examples
See the chatserver.bas and chatclient.bas (or chatserv.bas and chatcli.bas for Windows)
included in the Rapid-Q distribution.
Also take a look at http.bas included in the Rapid-Q for Windows distribution.


QSPLITTER

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QSPLITTER

QSPLITTER Component

QSplitter sits between a control aligned to one of the edges of the form and the controls that fill up the rest of the client area. It is used to resize the controls at runtime.

QSplitter Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alLeft
Align determines how the control aligns within its parent control.
Beveled | INTEGER | RW | True
Beveled determines whether the splitter looks beveled along the edge that moves.
ClientHeight | INTEGER | RW
ClientWidth | INTEGER | RW
Color | INTEGER | RW
Cursor | INTEGER | RW | crHSplit
Enabled | INTEGER | RW | True
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW
MinSize | INTEGER | RW | 30
MinSize is the minimum size, in pixels, of the client area the splitter must leave on the form.
Parent | QFORM/QPANEL/QTABCONTROL | W
ShowHint | INTEGER | RW | False
Tag | INTEGER | RW
Top | INTEGER | RW
Visible | INTEGER | RW | True
Width | INTEGER | RW

QSplitter Methods
Method Type Description Params

QSplitter Events
Event | Type | Occurs when... | Params
OnMoved | VOID | Splitter Moved | 0

QSplitter Examples
$INCLUDE "RAPIDQ.INC"

CREATE Form AS QFORM
    Height = 400
    Caption = "QSplitter example"
    Center
    Visible = 1                  '-- Required
    Visible = 0                  '-- trick
    CREATE Panel AS QPANEL
        Align = alTop            '-- Fill top portion of form
        Height = 100
        Caption = "PANEL"
    END CREATE
    CREATE Splitter AS QSPLITTER '-- Note position
        Align = alTop            '-- Fill middle
        Cursor = crVSplit
        Height = 10
    END CREATE
    CREATE RichEdit AS QRICHEDIT
        Align = alClient         '-- Fill rest of form
        AddStrings "RICHEDIT"
    END CREATE
    ShowModal
END CREATE


QSTATUSBAR

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QSTATUSBAR

QSTATUSBAR Component

QStatusBar implements a Windows status bar.

QStatusBar Internal Types
   TYPE PanelType           '' ie. StatusBar.Panel(0).Caption
     Alignment AS INTEGER   '' Specifies the text alignment, default is taLeftJustify
     Caption AS STRING
     Width AS INTEGER
   END TYPE
QStatusBar Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alBottom
Align determines how the control aligns within its parent control.
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW | 0
Panel | ARRAY of PanelType | RW
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ShowHint | INTEGER | RW | False
SimplePanel | INTEGER | RW | False
SimplePanel determines whether the statusbar displays a single panel or multiple panels.
SimpleText | STRING | RW
SimpleText contains the string that is displayed in the statusbar when SimplePanel is true.
SizeGrip | INTEGER | RW | True
SizeGrip determines whether the statusbar is resizable at runtime.
TabOrder | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
Visible | INTEGER | RW | True

QStatusBar Methods
Method | Type | Description | Params
AddPanels | SUBI | Add panels to status bar | STRING, Infinite
Clear | SUB | Clear panels | 0

QStatusBar Events
Event | Type | Occurs when... | Params
OnResize | VOID | Status bar is being resized | 0

QStatusBar Examples
CREATE Form AS QForm
  Center
  CREATE StatusBar AS QStatusBar
    AddPanels "Panel 1", "Panel 2", "Panel 3"
    Panel(1).Width = 100  ' change width of Panel 2
  END CREATE
  ShowModal
END CREATE


QSTRINGGRID

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QSTRINGGRID

QSTRINGGRID Component

QStringGrid allows you to present textual data in a tabular format, like cells in a spreadsheet program.

QStringGrid Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
BorderStyle | INTEGER | RW | bsSingle
Cell | 2D ARRAY of STRING | RW
Cell(X, Y) is an array of strings, one string for each cell in the grid.
X = Column, Y = Row
Col | INTEGER | RW
Col is the index of the column that contains the selected cell.
ColCount | INTEGER | RW | 5
Color | INTEGER | RW
ColumnList | ARRAY of STRING | RW
ColumnList maintains a list of strings deliminated by LF for use in Columned lists.
ColumnStyle | ARRAY of INTEGER | RW | gcsNone
ColumnStyle determines the style of each column.
0 = gcsList -- Column with a drop-down list for each item
1 = gcsEllipsis -- Column with an ellipsis button for each item
2 = gcsNone -- Normal column
ColWidths | ARRAY of INTEGER | RW
ColWidths is an indexed array giving the width in pixels of all the columns in the grid.
Cursor | INTEGER | RW | crDefault
DefaultColWidth | INTEGER | RW | 64
DefaultRowHeight | INTEGER | RW | 24
EditorMode | INTEGER | RW
Enabled | INTEGER | RW | True
FixedColor | INTEGER | RW
FixedCols | INTEGER | RW | 1
FixedColss is the number of columns on the left of the grid that cannot be scrolled.
FixedRows | INTEGER | RW | 1
FixedRows is the number of rows on the top of the grid that cannot be scrolled.
Font | QFONT | W
GridHeight | INTEGER | RW
GridLineWidth | INTEGER | RW | 1
GridWidth | INTEGER | RW
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW | 0
LeftCol | INTEGER | RW
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
Row | INTEGER | RW
Row is the index of the row that contains the selected cell.
RowCount | INTEGER | RW | 5
RowHeights | ARRAY of INTEGER | RW
RowHeights is an indexed array giving the height in pixels of all the rows in the grid.
ScrollBars | INTEGER | RW | ssBoth
Separator | STRING | RW
Separator determines how the stringgrid should parse (ie. read/write) grid data. For example, you can save the grid data to a file, with each item deliminated by the Separator.
ShowHint | INTEGER | RW | False
TabOrder | INTEGER | RW
TabStops | ARRAY of INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
TopRow | INTEGER | RW
Visible | INTEGER | RW | True
VisibleColCount | INTEGER | R
VisibleRowCount | INTEGER | R
Width | INTEGER | RW

QStringGrid Methods
Method | Type | Description | Params
AddOptions | SUBI | Add options to string grid | INTEGER, Infinite
goFixedVertLine = 0 horizontal lines appear between the rows within nonscrolling regions.
goFixedHorzLine = 1 vertical lines appear between the columns within nonscrolling regions.
 goVertLine = 2 vertical lines appear between the columns
goHorzLine = 3 horizontal lines appear between the rows.
 goRangeSelect = 4 the user can select a range of cells at one time. When goEditing is True, the user can no longer select a range of cells.
goDrawFocusSelected = 5 the cell with the focus is colored 'the same as other cells in a selected block are colored. When False, the cell with the focus remains the color of all unselected cells, the color specified with the grid Color property.

goRowSizing = 6 rows can be resized individually except for fixed or nonscrolling rows.
goColSizing = 7 columns can be resized individually except for fixed or nonscrolling columns.
 goRowMoving = 8 the user can move a row to a new location in the grid using the mouse.
goColMoving = 9 the user can move a column to a new location in the grid using the mouse.
 goEditing = 10 the user can edit the text in the grid. When goEditing is True, the user cannot select a range of cells at one time.
goTabs = 11 the user can use the Tab and Shift-Tab keys to move from column to column in the grid.
goRowSelect = 12 the user can only whole rows at a time instead of individual cells.

 goAlwaysShowEditor = 13 the grid is in automatic edit mode 'if goEditing is also True. When the grid is in automatic edit mode, the user does not have to press Enter or F2 before editing the contents of a cell. When goAlwaysShowEditor is False and goEditing is True, the user must press Enter or F2 before editing the contents of a cell. If goEditing is False, setting goAlwaysShowEditor to True has no effect.

goThumbTracking = 14 the contents of the grid scrolls while the user is moving the thumb tab of the grid scroll bar. When False, the contents of the grid doesn't scroll until the user releases the thumb tab in its new position.

'-- ColumnStyles
gcsList = 0
gcsEllipsis = 1
gcsNone = 2
DeleteCol | SUB (Column%) | Deletes/Remove a column | 1
DeleteRow | SUB (Row%) | Deletes/Remove a row | 1
DelOptions | SUBI | Delete options from string grid | INTEGER, Infinite
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3
Draw | SUB (x%, y%, BMP) | Draw Bitmap at (X,Y) | 3
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draws & Fills a rectangle | 5
InsertCol | SUB (Column%) | Inserts a blank column | 1
InsertRow | SUB (Row%) | Inserts a blank row | 1
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5
LoadFromFile SUB (File$, RowOffset%, ColOffset%, MaxRows%) Loads table from file w/Separator
 4
You can find out how many rows by loading the StringGrid Data into
in a QStringList First and using QStringList.ItemCount to get StringGrid.Rowcount:

Dim slTmp As QStringList
slTmp.LoadFromFile ("YourFile")
MyStringGrid.LoadFromFile ("YourFile", 0, 0, slTmp.ItemCount)
slTmp.Clear ' to free memory, if not in a procedure
LoadFromStream | SUB (S AS QFileStream/QMemoryStream, RowOffset%, ColOffset%, MaxRows%) | Loads table from stream w/Separator | 4
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4
Pset | SUB (x%, y%, c%) | Pixel plot | 3
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5
Repaint | SUB | Force repainting of stringgrid | 0
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7
SaveToFile SUB (File$, RowOffset%, ColOffset%, MaxRows%) Saves table to file w/Separator
 4
This only works if the path and the FILE exists. First create a file (and path if needed) either with a utility like NOTEPAD, or use Qfilestream. Then use FILEEXISTS to make sure the file exists.
SaveToStream | SUB (S AS QFileStream/QMemoryStream, RowOffset%, ColOffset%, MaxRows%) | Saves table to stream w/Separator | 4
SwapCols | SUB (Col1%, Col2%) | Swap two columns | 2
SwapRows | SUB (Row1%, Row2%) | Swap two rows | 2
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text to cell | 5

QStringGrid Events
Event | Type | Occurs when... | Params
OnDrawCell | SUB (Col%, Row%, State%, R AS QRect) | Cells need to be redrawn | 4
How to draw a cell in a custom color:
MyStringGrid.OnDrawCell = DrawCell

SUB Drawcell(Col%, Row%, State%, Rect AS QRect)
  IF (Row% > 0 AND Col% > 0) THEN   ' row 0 is fixed row
      MyStringGrid.FillRect(Rect.Left, Rect.Top, Rect.Left + MyStringGrid.ColWidths(Col%), _
            Rect.Top + MyStringGrid.RowHeights(Row%), SelectClr)
     MyStringGrid.TextOut(Rect.Left+2, Rect.Top+2, MyStringGrid.Cell(Col%, Row%), ClrTxt,-1)
  END IF
END SUB
OnEllipsisClick | SUB (Col%, Row%) | Pull down list is clicked | 2
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2
OnListDropDown | SUB (Col%, Row%, BYREF S AS STRING) | Pull down list is clicked. S is a string with items separated by a new line character. | 3
OnSelectCell | SUB (Col%, Row%, CanSelect%) | User has selected a cell | 3
OnSetEditText | SUB (Col%, Row%, Value$) | User has changed contents of cell | 3

QStringGrid Examples
CREATE Form AS QForm
  CREATE Grid AS QStringGrid
    Cell(1,1) = "hello"
  END CREATE
  Center
  ShowModal
END CREATE

'------------------------------------------------------------------
' Pulldown list example

$INCLUDE "RAPIDQ.INC"
$ESCAPECHARS ON

CONST AgeList = "10\n11\n12\n13\n14\n15\n16\n17\n18\n19"

SUB EllipsisClick (Col AS LONG, Row AS LONG, Sender AS QSTRINGGRID)
    Sender.Cell(Col, Row) = "Comments"+STR$(Row)
END SUB

CREATE Form AS QFORM
    CREATE Grid AS QSTRINGGRID
        Align = alClient
        AddOptions(goEditing)
        FixedRows = 1
        FixedCols = 0
        ColCount = 3
        RowCount = 5
        DefaultRowHeight = 20
        ColumnStyle(0) = gcsList
        ColumnStyle(1) = gcsEllipsis
        ColumnList(0) = AgeList
        Cell(0,0) = " Age"
        Cell(1,0) = " Comments"
        OnEllipsisClick = EllipsisClick
    END CREATE
    Caption = "Dropdown list example"
    Center
    ShowModal
END CREATE

NOTES:

    To fast clear StringGrid:
    FOR A = 0 TO GridResults.RowCount-1
      FOR B = 0 TO GridResults.ColCount-1
      GridResults.cell(Col,a)=""
     NEXT
    NEXT
    GridResults.rowCount=1


QSTRINGLIST

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QSTRINGLIST

QSTRINGLIST Component

QStringList is a non-visible component to store and manipulate a list of strings.

QStringList Properties
Field | Type | R/W | Default | Support
Duplicates | INTEGER | RW | dupIgnore | W
Item | ARRAY of STRING | RW | WXG
ItemCount | INTEGER | R | WXG
Sorted | INTEGER | RW | False | W
Text | STRING | RW | WXG

QStringList Methods
Method | Type | Description | Params | Support
AddItems | SUBI | Add strings to stringlist | STRINGs, Infinite | WXG
AddList | SUB (List AS QStringList) | Append another stringlist | 1 | WXG
Build | FUNCTION Build(Start%, End%, Delim$) AS STRING | Returns a deliminated string | 3 | WXG
Clear | SUB | Clears entire stringlist | 0 | WXG
DelItems | SUBI | Delete strings by their index | Index #s, Infinite | WXG
Exchange | SUB (Index1%, Index2%) | Swap strings at Index1% with Index2% | 2 | WXG
IndexOf | FUNCTION IndexOf%(String$) | Return Index number of string | 1 | WXG
InsertItem | SUB (Index%, String$) | Insert string at Index% | 2 | WXG
LoadFromFile | SUB (File$) | Load text file in stringlist | 1 | WXG
LoadFromStream | SUB (File AS QStream) | Load file/memorystream in stringlist | 1 | W
Parse | FUNCTION Parse(Source$, Delim$) AS LONG | Separates strings by the Delim$ and stores each item in the list | 2 | WXG
SaveToFile | SUB (File$) | Saves stringlist to file | 1 | WXG
SaveToStream | SUB (File AS QStream) | Load file/memorystream in stringlist | 1 | W
Sort | SUB | Sort the stringlist | 0 | WXG

QStringList Events
Event Type Occurs when... Params

QStringList Examples
  DIM StringList1 AS QStringList
  DIM StringList2 AS QStringList

  StringList1.AddItems "Oranges","Apples"
  StringList2.AddItems "Byte","Word","Integer"
  StringList1.AddList(StringList2)
  StringList1.Sort

  ?StringList1.Text
  ?StringList1.Item(3)
  ?StringList1.IndexOf("Word")
  ?StringList1.IndexOf("hi")

  '-------------------------------------------------------

  DIM StringList AS QSTRINGLIST

  StringList.Parse("James:Brown:555-3454:House",":")

  PRINT StringList.Build(0,StringList.ItemCount-1,",")


QTABCONTROL

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QTABCONTROL

QTABCONTROL Component

QTabControl is a tab set that has the appearance of notebook dividers, except it is not made up of several pages.

QTabControl Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
ButtonStyle | INTEGER | RW | False
ClientHeight | INTEGER | RW
ClientWidth | INTEGER | RW
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
FlatButtons | INTEGER | RW | False
FlatSeperators | INTEGER | RW | False
FocusButtons | INTEGER | RW | False
Font | QFONT | W
Height | INTEGER | RW
Hint | STRING | RW
HotTrack | INTEGER | RW | False
Left | INTEGER | RW | 0
MultiLine | INTEGER | RW | False
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ScrollOpposite | INTEGER | RW | False
ShowHint | INTEGER | RW | False
Tab | ARRAY of STRING | RW
TabHeight | INTEGER | RW
TabInactiveColor | INTEGER | RW
TabInactiveFont | QFONT | W
TabIndex | INTEGER | RW
TabOrder | INTEGER | RW
TabPosition | INTEGER | RW
TabWidth | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW
VerticalTabs | INTEGER | RW | False
Visible | INTEGER | RW | True

QTabControl Methods
Method | Type | Description | Params
AddTabs | SUBI | Add tabs to control | STRING, Infinite
DelTabs SUBI
*** bug, does not work*** 		Delete tabs from control INTEGER, Infinite
InsertTab | SUB (Index%, String$) | Inserts Tab at Index% | 2

QTabControl Events
Event | Type | Occurs when... | Params
OnChange | VOID | Tabs change | 0

QTabControl Examples
'' Tab Control Example for Rapid-Q by William Yu
'' When you hide a container (like QFORM, QTABCONTROL, and QPANEL), all the
'' components within it are also hidden.

$INCLUDE "RAPIDQ.INC"

DECLARE SUB TabChange

CREATE MainForm AS QForm
  Center
  Height = 300
  Width = 350
  Caption = "Tab Control demo"
  CREATE Tab AS QTabControl
    AddTabs "Tab 1","Tab 2","Tab 3","Tab 4"
    Width = MainForm.ClientWidth
    Height = MainForm.ClientHeight
    OnChange = TabChange
    HotTrack = True
    CREATE Panel0 AS QPanel
      Top = 40
      Left = 5
      Width = Tab.ClientWidth - 10
      Height = Tab.ClientHeight - 50
      Caption = "Panel 1"
      BevelInner = bvLowered
      CREATE Button1 AS QButton
        Caption = "Hello world!"
      END CREATE
    END CREATE
    CREATE Panel1 AS QPanel
      Top = 40
      Left = 5
      Width = Tab.ClientWidth - 10
      Height = Tab.ClientHeight - 50
      Caption = "Panel 2"
      BevelInner = bvLowered
      Visible = False
    END CREATE
    CREATE Panel2 AS QPanel
      Top = 40
      Left = 5
      Width = Tab.ClientWidth - 10
      Height = Tab.ClientHeight - 50
      Caption = "Panel 3"
      BevelInner = bvLowered
      Visible = False
    END CREATE
    CREATE Panel3 AS QPanel
      Top = 40
      Left = 5
      Width = Tab.ClientWidth - 10
      Height = Tab.ClientHeight - 50
      Caption = "Panel 4"
      BevelInner = bvLowered
      Visible = False
    END CREATE
  END CREATE
END CREATE

SUB TabChange
  SELECT CASE Tab.TabIndex
    CASE 0
      Panel0.Visible = True
      Panel1.Visible = False
      Panel2.Visible = False
      Panel3.Visible = False
    CASE 1
      Panel1.Visible = True
      Panel0.Visible = False
      Panel2.Visible = False
      Panel3.Visible = False
    CASE 2
      Panel2.Visible = True
      Panel1.Visible = False
      Panel0.Visible = False
      Panel3.Visible = False
    CASE 3
      Panel3.Visible = True
      Panel1.Visible = False
      Panel2.Visible = False
      Panel0.Visible = False
  END SELECT
END SUB

MainForm.ShowModal


QTIMER

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QTIMER

QTIMER Component

QTimer implements the Windows API timer functions. The real resolution of this timer is about 30 - 50 milliseconds, not 1! If you need better resolution try QDXTIMER. QDXTIMER does not require a DXSCREEN, you should be able to substitute QDXTIMER for QTIMER without problems.

QTimer Properties
Field | Type | R/W | Default | Support
Enabled | INTEGER | RW | True | WXG
Interval | INTEGER | RW | WXG
Interval determines the amount of time, in milliseconds, that passes before the timer component initiates another OnTimer event.
Tag | INTEGER | RW | WXG

QTimer Events
Event | Type | Occurs when... | Params | Support
OnTimer | SUB(Sender AS QTIMER) | Timer interval elaspes | 1 | WXG

QTimer Examples
' Timer & OnKeyPress example for Rapid-Q by William Yu
'       If no form is visible, Timer will not function.
'       Not for PURE CONSOLE apps, but you're allowed to MIX.

DIM Timer AS QTimer, Timer2 AS QTimer
DIM Form AS QFORM
DIM Label1 AS QLABEL, Label2 AS QLABEL
DIM Label3 AS QLABEL

SUB TimerOver
  Timer.Interval = 100
  I = I + 1
  Label1.Caption = STR$(I)
END SUB

SUB Timer2Over
  Timer2.Interval = 1000
  J = J + 1
  Label2.Caption = STR$(J)
END SUB

SUB KeyPressed (Key AS BYTE)      '' Event returns one parameter
  IF UCASE$(CHR$(Key)) = "Q" THEN
    FORM.CLOSE
  END IF
END SUB

I = 0        ' Undeclared variables are automatically global!
J = 0

FORM.CAPTION = "Timer Example"
FORM.WIDTH = 150
FORM.HEIGHT = 120
FORM.CENTER

Label1.Parent = Form
Label1.Caption = STR$(I)
Label1.Left = FORM.WIDTH/2

Label2.Parent = Form
Label2.Caption = STR$(J)
Label2.Left = FORM.WIDTH/2
Label2.Top = 40

Label3.Parent = Form
Label3.Caption = "Press 'Q' to quit'
Label3.Top = 75

Timer.Interval = 100
Timer.Enabled = 1          ' True
Timer.OnTimer = TimerOver

Timer2.Interval = 1000
Timer2.Enabled = 1          ' True
Timer2.OnTimer = Timer2Over

FORM.OnKeyPress = KeyPressed
FORM.SHOWMODAL


QTRACKBAR

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix A: QTRACKBAR

QTRACKBAR Component

QTrackBar is a track bar control used to represent a position along a continuum using a slider and, optionally, tick marks.

QTrackBar Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
Align determines how the control aligns within its parent control.
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Frequency | INTEGER | RW
Frequency specifies the increment between tick marks on the trackbar.
Handle | INTEGER | R
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW | 0
LineSize | INTEGER | RW | 1
LineSize is the amount the value of Position changes when the user presses the arrow keys.
Max | INTEGER | RW | 10
Max specifies the maximum Position of the trackbar.
Min | INTEGER | RW | 0
Min specifies the minimum Position of the trackbar.
Orientation | INTEGER | RW | tbHorizontal
Orientation specifies whether the trackbar is horizontal or vertical.
0 = tbHorizontal -- Min position is on the left, Max is on the right.
1 = tbVertical -- Min position is on the top, Max is on the bottom.
PageSize | INTEGER | RW | 2
PageSize specifies the amount Position is changed when the PageUp or PageDown key is pressed, or when the bar is clicked.
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
Position | INTEGER | RW
Position contains the current position of the slider.
SelEnd | INTEGER | RW
SelEnd specifies the position of the end point of the selection range.
SelStart | INTEGER | RW
SelStart specifies the position of the starting point of the selection range.
ShowHint | INTEGER | RW | False
TabOrder | INTEGER | RW
TickMarks | INTEGER | RW | tmBottomRight
TickMarks specifies the location of the tick marks.
0 = tmBottomRight -- Tick marks are on the bottom or right of the trackbar depending on the value of Orientation.
1 = tmTopLeft -- Tick marks are on the top or left of the trackbar depending on the value of Orientation.
2 = tmBoth -- Tick marks are on both sides of the trackbar.
TickStyle | INTEGER | RW | tsAuto
TickStyle specifies how tick marks are place on the trackbar.
0 = tsNone -- No tick marks are displayed.
1 = tsAuto -- Trackbar displays tick marks automatically for each increment in its range.
2 = tsManual -- Trackbar displays tick marks at either end. Use SetTick to set a tick in other positions
Top | INTEGER | RW | 0
Width | INTEGER | RW
Visible | INTEGER | RW | True

QTrackBar Methods
Method | Type | Description | Params
SetTick | SUB (Pos%) | Set a tick mark at Pos% | 1

QTrackBar Events
Event | Type | Occurs when... | Params
OnChange | VOID | Track bar changes | 0

QTrackBar Examples
CREATE Form AS QForm
  Center
  CREATE TrackBar AS QTrackBar
    ' Initialize track bar
  END CREATE
  ShowModal
END CREATE


QTREEVIEW

Rapid-Q Documentation by William Yu (c)1999 Appendix A: QTREEVIEW

QTREEVIEW Component

QTreeView displays a hierarchical list of items. Items are ordered by their index.

QTreeView Internal Types
   TYPE TreeNodeType           '' ie. TreeView.Item(0).Text
     Text AS STRING
     ImageIndex AS INTEGER
     StateIndex AS INTEGER
     SelectedIndex AS INTEGER
     Count AS INTEGER          '' Read only
     Level AS INTEGER          '' Read only
     IsVisible AS INTEGER      '' Read only
     Handle AS INTEGER         '' Read only
     HasChildren AS INTEGER
     Selected AS INTEGER
   END TYPE
QTreeView Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
BorderStyle | INTEGER | RW | bsSingle
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
Handle | INTEGER | RW
Height | INTEGER | RW
HideSelection | INTEGER | RW | False
Hint | STRING | RW
Images | QIMAGELIST | W
Indent | INTEGER | RW | 19
Item | ARRAY of TreeNodeType | RW
ItemCount | INTEGER | RW
ItemIndex | INTEGER | RW
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W
ReadOnly | INTEGER | RW | False
ShowButtons | INTEGER | RW | True
ShowHint | INTEGER | RW | False
ShowLines | INTEGER | RW | True
ShowRoot | INTEGER | RW | True
SortType | INTEGER | RW | stText
StateImages | QIMAGELIST | W
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
TopIndex | INTEGER | RW
Width | INTEGER | RW
Visible | INTEGER | RW | True

QTreeView Methods
Method | Type | Description | Params
AddItems | SUBI | Add items to treeview | STRING, Infinite
AddChildItems | SUB (Index%, S1$, S2$, ...) | Add child item at Index% | Minimum 2
Clear | SUB | Clear all items in treeview | 0
Collapse | SUB (Index%, Recurse%) | Collapses node | 2
DelItems | SUBI | Delete items from treeview | INTEGER, Infinite
Expand | SUB (Index%, Recurse%) | Expand node, revealing its childs | 2
FullCollapse | SUB | Collapses all nodes | 0
FullExpand | SUB | Expands all nodes | 0
GetItemAt | FUNCTION (X%, Y%) AS LONG | Get the index node at X,Y | 2
InsertItem | SUB (Index%, String$) | Insert item at Index% | 2
LoadFromFile | SUB (Filename AS STRING) | Load items from file | 1
SaveToFile | SUB (Filename AS STRING) | Save items to file | 1
Sort | SUB | Sort all items from A-Z | 0

QTreeView Events
Event | Type | Occurs when... | Params
OnClick | VOID | TreeView was clicked on | 0
OnChange | SUB (Index%) | Selection (not modification) has changed from one item to another | 1
OnChanging | SUB (Index%, AllowChange%) | Selection is about to be changed | 2
OnCollapse | SUB (Index%) | Just after a node has been collapsed | 1
OnCollapsing | SUB (Index%, AllowCollapse%) | A node is about to be collapsed | 2
OnDblClick | VOID | TreeView was double clicked on | 0
OnDeletion | SUB (Index%) | A node in the tree is deleted | 1
OnEdited | SUB (Index%, BYREF S$) | After the user edits a text of a node | 2
OnEditing | SUB (Index%, AllowEdit%) | The user starts to edit the text | 2
OnExpand | SUB (Index%) | After a node is expanded | 1
OnExpanding | SUB (Index%, AllowExpansion%) | A node is about to be expanded | 2
OnGetImageIndex | SUB (Index%) | The treeview looks up the ImageIndex of a node | 1
OnGetSelectedIndex | SUB (Index%) | The treeview looks up the SelectedIndex of a node | 1
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1
OnKeyUp | SUB (Key AS Word, Shift AS INTEGER) | User releases a key | 2
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4

QTreeView Examples
'' Tree view example, hot tracking through items

SUB TreeViewChange (Node AS INTEGER, AllowChange AS INTEGER, Sender AS QTREEVIEW)
    IF Node = 8 THEN AllowChange = 0
END SUB

SUB TreeViewMouseMove (X AS INTEGER, Y AS INTEGER, Shift AS INTEGER, Sender AS QTREEVIEW)
    I = Sender.GetItemAt(X,Y)
    IF I >= 0 THEN Sender.ItemIndex = I
END SUB

CREATE Form AS QFORM
    Center
    CREATE TreeView AS QTREEVIEW
        Align = 5
        AddItems "1","2","3"
        AddChildItems 0, "Sub 1", "Sub 2", "Sub 3"
        AddChildItems 4, "Sub 1", "Sub 2", "Sub 3"
        FullExpand
        OnChanging = TreeViewChange
        OnMouseMove = TreeViewMouseMove
    END CREATE
END CREATE

'-- No real purpose, just change all items
FOR I = 0 TO TreeView.ItemCount-1
    TreeView.Item(I).Text = STR$(I)
NEXT

Form.ShowModal


QDXIMAGELIST

Rapid-Q Documentation by William Yu (c)1999 Appendix B: QDXIMAGELIST

QDXIMAGELIST Component

QDXImageList maintains a list of images for use in your programs. Unlike QImageList, you must create the imagelist using an Image Library.

QDXImageList Properties
Field | Type | R/W | Default
Parent | QDXSCREEN | W

QDXImageList Methods
Method | Type | Description | Params
Draw | SUB (Item%, X%, Y%, Mask%) | Draw image on Screen | 4
LoadFromFile | SUB (FileName$) | Load imagelist | 1
LoadFromResource | SUB (Resource_Handle) | Load imagelist from resource handle | 1
LoadFromStream | SUB (Stream AS QFILESTREAM/QMEMORYSTREAM) | Load imagelist from stream | 1

QDXImageList Events
Event Type Occurs when... Params

QDXImageList Examples
' Target practise w/DirectX for Rapid-Q by William Yu
' Move using arrow keys, to shoot, press SPACEBAR

$APPTYPE GUI
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
$RESOURCE ships_DXG AS "ships.dxg"

DECLARE SUB DXTimerExpired
DECLARE SUB InitStars
DECLARE SUB KeyDown (Key AS BYTE, Shift AS BYTE)

CONST ScreenX = 400
CONST ScreenY = 300
CONST MaxStars = 150        '' Depending on your system, adjust as needed.

TYPE StarType
  X(MaxStars) AS INTEGER
  Y(MaxStars) AS INTEGER
  Z(MaxStars) AS INTEGER
END TYPE

DIM DXTimer AS QDXTimer
    DXTimer.Enabled = True
    DXTimer.Interval = 10
    DXTimer.OnTimer = DXTimerExpired
DIM Stars AS StarType
DIM MyShipX AS INTEGER
    MyShipX = 50
DIM EnemyShipX AS INTEGER
    EnemyShipX = ScreenX + 45
DIM EnemyShipY AS INTEGER
    EnemyShipY = 20
DIM Shoot AS INTEGER, ShootX AS INTEGER, ShootY AS INTEGER
    Shoot = False
DIM Hit AS INTEGER, HitCount AS INTEGER
    Hit = False

InitStars

CREATE Form AS QForm
  Center
  Caption = "DirectX Target Practise"
  ClientWidth = ScreenX
  ClientHeight = ScreenY
  'BorderStyle = bsNone           '' Setup fullscreen
  CREATE DXScreen AS QDXScreen
    Init(ScreenX, ScreenY)
    Align = alClient
    'FullScreen = True            '' Fullscreen mode
    Cursor = crNone              '' Hide Mouse
    CREATE DXImageList AS QDXImageList
      LoadFromResource(SHIPS_DXG)
    END CREATE
  END CREATE
  OnKeyDown = KeyDown
  ShowModal
END CREATE

SUB KeyDown (Key AS BYTE, Shift AS BYTE)
  SELECT CASE Key
    CASE 27
      Form.Close
    CASE 39
      MyShipX = MyShipX + 4
    CASE 37
      MyShipX = MyShipX - 4
    CASE IS = 32 AND Shoot = False
      Shoot = True
      ShootX = MyShipX + 20
      ShootY = ScreenY - 58
  END SELECT
END SUB

SUB InitStars
  DIM I AS INTEGER

  RANDOMIZE TIMER

  FOR I = 1 TO MaxStars
    Stars.X(I) = RND(ScreenX)
    Stars.Y(I) = RND(ScreenY)
    Stars.Z(I) = RND(3)
  NEXT I
END SUB

SUB DXTimerExpired
  DIM I AS INTEGER

  DXScreen.Fill(0)
  FOR I = 1 TO MaxStars
    SELECT CASE Stars.Z(I)
      CASE 0
        DXScreen.Pixel(Stars.X(I),Stars.Y(I)) = clWhite
        Stars.Y(I) = Stars.Y(I) + 3
      CASE 1
        DXScreen.Pixel(Stars.X(I),Stars.Y(I)) = &HAAAAAA
        Stars.Y(I) = Stars.Y(I) + 2
      CASE ELSE
        DXScreen.Pixel(Stars.X(I),Stars.Y(I)) = &H555555
        Stars.Y(I) = Stars.Y(I) + 1
    END SELECT
    IF Stars.Y(I) > ScreenY THEN
      Stars.Y(I) = -1
      Stars.X(I) = RND(ScreenX)
    END IF
  NEXT I
  DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), clWhite, -1)
  IF Hit THEN
    DXScreen.Circle(ShootX-HitCount/2,ShootY-20,ShootX+4+HitCount/2,ShootY-20+4+HitCount,&H2090FF,&H2090FF)
    IF HitCount = 0 THEN
      Hit = False
    ELSE
      HitCount = HitCount - 2
    END IF
  ELSE
    IF Shoot THEN
      SELECT CASE ShootX
        CASE EnemyShipX TO EnemyShipX+45
          IF ShootY > EnemyShipY AND ShootY < EnemyShipY+45 THEN
            EnemyShipX = ScreenX + 45
            EnemyShipY = EnemyShipY + 45
            Shoot = False
            Hit = True
            HitCount = 40
          END IF
      END SELECT
      DXScreen.Circle(ShootX,ShootY,ShootX+4,ShootY+4,&H2090FF,&H2090FF)
      IF ShootY < -4 THEN
         Shoot = False
      ELSE
         ShootY = ShootY - 4
      END IF
    END IF
    EnemyShipX = EnemyShipX - 2
    DXImageList.Draw(1, EnemyShipX, EnemyShipY, 0)
    IF EnemyShipX < -45 THEN
      EnemyShipX = ScreenX + 45
      EnemyShipY = EnemyShipY + 45
    END IF
  END IF
  DXImageList.Draw(0, MyShipX, ScreenY - 55, 0)
  DXScreen.Flip
END SUB


QDXSCREEN

Rapid-Q Documentation by William Yu (c)1999, appended by John Kelly Appendix B: QDXSCREEN

QDXSCREEN Component

QDXScreen allows you to create a Direct Draw/Direct3D screen for all DirectX components. All drawing is done on the off-screen buffer, so nothing is displayed until you flip to it. To use full screen mode, set FullScreen = True, and make sure your form border style is bsNone. If you don't it will temporarily change the screen resolution.
QDXScreen allows faster graphics than a QCANVAS ( GDI) because the OS writes directly to video memory. You can have menus, buttons, etc. in a DXscreen fullscreen **But** you must specify qdxscreen.fullScreen = True before you do Form.ShowModal. Once you are in fullscreen mode, you can't toggle back to non-fullscreen mode until the program ends.
<Windows only (DirectX version 6.0 or higher) >

 QDXScreen Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
AllowStretch | INTEGER | RW | True
AutoSize | INTEGER | RW | True
BitCount | INTEGER | RW | 8
Color | INTEGER | RW
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Font | QFONT | W
See QFont
FONT.BOLD		FONT.COLOR 		FONT.FONTNAME
FONT.NAME		FONT.HANDLE		FONT.SIZE
FONT.CHARSET		FONT.ADDSTYLES		FONT.PITCH
FONT.DELSTYLES		FONT.ITALIC		FONT.FONTCOUNT
FONT.UNDERLINE		FONT.STRIKEOUT
FullScreen | INTEGER | RW | False
Height | INTEGER | RW
Hint | STRING | RW
Left | INTEGER | RW
Parent QFORM/QPANEL/QTABCONTROL
The screen can be rapidly moved to another form by changing its Parent 		W
Pixel 2D ARRAY of INTEGER
This reads/writes color information to the screen. There is not the way to get the memory pointer of the screen buffer 		RW
ShowHint | INTEGER | RW | False
Top | INTEGER | RW
Use3D | INTEGER | RW | False
UseHardware | INTEGER (hardware acceleration, always try to use this) | RW | True
Visible | INTEGER | RW | True
Width | INTEGER | RW

QDXScreen Methods
Method | Type | Description | Params
Circle | SUB (x1%, y1%, x2%, y2%, c%, fill%) | Draw & Fill Circle | 6
CopyRect | SUB (D, Image, S) | D and S are QRECTs, Image can be a QImage, QCanvas, or QBitmap | 3
Draw | SUB (x%, y%, BMP) | Draw Bitmap at (X,Y) | 3
FastPset | SUB (X1%, Y1%, C%) not fully implemented? | Direct write pixel at x, y | 3
Fill SUB (Color%) Fill screen with color with BGR code
(&HFF = Blue, &H00FF = Green, &H0000FF = Red), etc. 		1
FillRect | SUB (x1%, y1%, x2%, y2%, c%) | Draw & Fill a rectangle | 5
Flip | SUB | Copies off-screen buffer to visible page, always flip to see it | 0
Init | SUB (Width%, Height%) | Create Screen | 2
Line | SUB (x1%, y1%, x2%, y2%, c%) | Draws a line | 5
Paint | SUB (x%, y%, c%, borderc%) | Fill Region | 4
Pset | SUB (x%, y%, c%) | Pixel Plot | 3
Rectangle | SUB (x1%, y1%, x2%, y2%, c%) | Draws a rectangle | 5
Release | SUB | Force update | 0
Rotate | SUB (xOrigin%, yOrigin%, Angle%) | Rotates entire screen at specified origin | 3
RoundRect | SUB (x1%, y1%, x2%, y2%, x3%, y3%, c%) | Draws & Fills a rounded rectangle | 7
StretchDraw | SUB (Rect AS QRECT, BMP) | Draw BMP and stretch to fit inside Rect | 2
TextHeight | FUNCTION (Text$) AS WORD | Returns the height, in pixels, of Text$ string | 1
TextWidth | FUNCTION (Text$) AS WORD | Returns the width, in pixels, of Text$ string | 1
TextRect | SUB (Rect AS QRECT, x%, y%, S$, fc%, bc%) | Write text, and clip within region Rect | 6
TextOut | SUB (x%, y%, S$, fc%, bc%) | Writes text | 5

QDXScreen 3D Methods
Method | Type | Description | Params
AddLight | SUB (Light AS QD3DLight) | Add light to scene | 1
CameraLookAt | SUB (F AS QD3DFrame, Constraint AS INTEGER) | Fix frame and constrain rotation | 2
CreateFace | SUB (Face AS QD3DFace) | Creates a face | 1
CreateFrame | SUB (Frame AS QD3DFrame) | Creates frame | 1
CreateLightRGB | SUB (LightType%, R#, G#, B#, Light AS QD3DLight) | Create light object | 5
CreateMeshBuilder | SUB (MB AS QD3DMeshBuilder) | Creates meshbuilder | 1
CreateShadow | SUB (MB AS QD3DMeshBuilder, Light AS QD3DLight, px#, py#, pz#, nx#, ny#, nz#, V AS QD3DVisual) | Creates a visual shadow object | 9
CreateWrap | SUB (WrapType%, A#, B#, C#, D#, E#, F#, G#, H#, I#, J#, K#, L#, M#, W AS QD3DWrap) | Creates a wrap object | 15
ForceUpdate | SUB (X1%, Y1%, X2%, Y2%) | Force update on specific region | 4
LoadTexture | SUB (File AS STRING, Tex AS QD3DTexture) | Create a texture object | 2
Move SUB (D AS DOUBLE) Moves/animates scene
(Quaterion operation) 		1
SetBackgroundImage | SUB (Tex AS QD3DTexture) | Set background image for scene | 1
SetCameraPosition | SUB (X#, Y#, Z#) | Set camera position for entire scene | 3
SetCameraOrientation SUB (DX#, DY#, DZ#, UX#, UY#, UZ#)
The camera.is a hidden QD3DFrame.
DX,DY, DZ range from -1 to 1 set left-right vs up- down.
UX, UY, range from -1 to 1 and set the roll (set UZ = 1; it has no effect) 		Set camera orientation for scene 6
SetRenderMode | SUB (M AS INTEGER) | Set render mode for scene | 1
SetVelocity SUB (X#, Y#, Z#, R%) Undocumented should affect
QDXSCREEN.MOVE(), QD3DFRAME.MOVE() 		set rotation velocity of a Quaterion operation 6
SetTextureQuality | SUB (Quality AS INTEGER) | Set texture quality for scene | 1

QDXScreen 3D ViewPort Methods (undocumented)
The viewport defines how a 3D scene is rendered on a 2D Screen. It implements a IDirectD3DRMViewPort object that sets the “viewing frustum” which is a 3D volume in a scene positioned relative to the viewport's camera. Objects within the viewing frustum are visible. For perspective viewing, the viewing frustum is the volume of an imaginary pyramid that is between the front clipping plane and the back clipping plane. The camera is at the tip of the pyramid, and its z-axis runs from the tip of the pyramid to the center of the pyramid's base. The front clipping plane is a distance D from the camera, and the back clipping plane is a distance F from the front clipping plane. You can set and retrieve these values by using the .VIEW.SETFRONT, .VIEW.SETBACK, .VIEW.GETFRONT, and .VIEW.GETBACK methods.. Why change the viewport? Change the perspective view or speed up the rendering process and eliminate objects you don’t want in the scene.
VIEW.CLEAR SUB ()
e.g., QDXScreen.View.Clear 		‘clears the DXSCREEN 0
VIEW.GETFRONT | FUNCTION () AS SINGLE | ‘gets the front clipping plane | 0
VIEW.SETFRONT SUB (RVFRONT AS SINGLE)
i.e.,
DIM a as SINGLE
a = QDXSCREEN.VIEW.GETFRONT
QDXSCREEN.VIEW.SETFRONT(a + 10) ‘ render less 		‘ set front clipping plane 1
VIEW.GETBACK | FUNCTION () AS SINGLE | ‘gets the back clipping plane | 0
VIEW.SETBACK | SUB (RVBACK AS SINGLE) 'default back is 5000 | ‘gets the front clipping plane | 1
VIEW.SETPLANE SUB ((LEFT#, RIGHT#, BOTTOM#, TOP#) ‘sets the front clipping plane of the viewing frustum with the coordinates of the four sides, relative to the camera's z-axis.
Changes the 3D perspective 		4

QDXScreen Events

Event | Type | Occurs when... | Params
OnClick | VOID | Mouse button clicked | 0
OnDblClick | VOID | Mouse button double clicked | 0
OnInitialize | VOID | DirectX succeeds in initializing | 0
OnInitializeSurface | VOID | Another event for you to do initializing | 0
OnKeyDown | SUB (Key AS Word, Shift AS INTEGER) | Key held down | 2
OnKeyPress | SUB (Key AS BYTE) | User presses a key | 1
OnMouseDown | SUB (Button%, X%, Y%) | Mouse button held down | 3
OnMouseMove | SUB (X%, Y%) | Mouse moves | 2
OnMouseUp | SUB (Button%, X%, Y%) | Mouse button is released | 3

QDXScreen Examples
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

declare SUB DrawOnScreen

DIM TheBMP AS QBITMAP
CREATE Form AS QForm
    ClientHeight = 480
    ClientWidth = 640
CREATE QScreen AS QDXScreen
    BitCount = 24
    width = Form.ClientWidth
    height = Form.ClientHeight
    Init(640, 480)  'define its memory, can be larger than visible screen
    OnClick  = DrawOnScreen
'   OnInitialize  = DrawOnScreen'will clear..
END CREATE
END CREATE
Form.ShowModal

SUB DrawOnScreen(Sender AS QDXScreen)
    TheBMP.LoadFromFile("test.bmp")
    QScreen.Draw(0,0, TheBMP.BMP)  'draw a picutre on it
    QScreen.Line(0,0,200,200,&HFF) 'draw a red line on picture
    QScreen.Flip  'need this for each new drawing
END SUB


QDXSOUND

Rapid-Q Documentation by William Yu (c)1999-2000 Appendix B: QDXSOUND

QDXSOUND Component

QDXSound implements DirectSound.

QDXSound Properties
Field | Type | R/W | Default
AutoUpdate | INTEGER | RW | True
AutoUpdate determines whether to let the internal thread update the sound buffer every 50ms, or let the programmer control the updates.
BufferLength | INTEGER | RW | 1000
BufferLength specifies how many bytes to read into the buffer for playing. For heavy computations or deeply nested loops, it's a good idea to extend the BufferLength so that the music can play uninterrupted.
FileName | STRING | RW
FileName specifies the .WAV file.
Frequency | INTEGER | RW
Frequency specifies the reproduction frequency. Do not set the frequency before loading a file, since a default frequency for the .WAV file will be given to you when you load a new sound file.
Looped | INTEGER | RW | False
Looped specifies whether to replay the sound file after it has finished playing.
Pan | INTEGER | RW | 0
Pan specifies the relative volume of the right and left channels within the range from -100 to 100. A value of -100 mutes the right channel, and a value of 100 mutes the left channel.
Parent | QFORM | W
Playing | INTEGER | R
Playing determines whether the sound file is currently playing.
Position | INTEGER | RW
Use Position to set/get the current playing position of the sound file.
Size | INTEGER | R
Size returns the file size of the .WAV file in bytes.
StickyFocus | INTEGER | RW | False
StickyFocus determines whether to keep playing even if the application loses focus.
Tag | INTEGER | RW
Tag is not used internally, it is reserved storage space for the programmer.
Volume | INTEGER | RW
Volume specifies the output volume for the current sound as a percentage. Setting volume to 0 mutes the sound, while setting volume to 100 plays the sound with "normal volume" (ie. your current sound settings for your computer).

QDXSound Methods
Method | Type | Description | Params
Play | SUB | Start playing sound | 0
Stop | SUB | Stop playing sound | 0
Update | SUB | Update sound buffer | 0

QDXSound Events
Event Type Occurs when... Params

QDXSound Examples
'-- DirectSound example for Rapid-Q by William Yu

$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"

DECLARE SUB exitItemClick (sender AS QMENUITEM)
DECLARE SUB openItemClick (sender AS QMENUITEM)
DECLARE SUB formShow (sender AS QFORM)
DECLARE SUB playButtonClick (sender AS QBUTTON)
DECLARE SUB stopButtonClick (sender AS QBUTTON)
DECLARE SUB positionTrackBarChange (sender AS QTRACKBAR)
DECLARE SUB freqTrackBarChange (sender AS QTRACKBAR)
DECLARE SUB volumeTrackBarChange (sender AS QTRACKBAR)
DECLARE SUB panTrackBarChange (sender AS QTRACKBAR)

CREATE form AS QFORM
    width = 360
    height = 300
    center
    CREATE dxSound AS QDXSOUND
    END CREATE
    CREATE mainMenu AS QMAINMENU
        CREATE fileMenu AS QMENUITEM
            caption = "&File"
            CREATE openItem AS QMENUITEM
                caption = "&Open..."
                onClick = openItemClick
            END CREATE
            CREATE breakItem1 AS QMENUITEM
                caption = "-"
            END CREATE
            CREATE exitItem AS QMENUITEM
                caption = "E&xit"
                onClick = exitItemClick
            END CREATE
        END CREATE
    END CREATE
    CREATE panTrackBar AS QTRACKBAR
        left = 10
        top = 10
        width = 200
        height = 30
        tickStyle = tsManual
        min = -100
        max = 100
        onChange = panTrackBarChange
        enabled = FALSE
    END CREATE
    CREATE panLabel AS QLABEL
        left = 215
        top = 20
        caption = "Pan 0dB"
    END CREATE
    CREATE volumeTrackBar AS QTRACKBAR
        left = 10
        top = 60
        width = 200
        height = 30
        tickStyle = tsManual
        min = 0
        max = 100
        position = 100
        onChange = volumeTrackBarChange
        enabled = FALSE
    END CREATE
    CREATE volumeLabel AS QLABEL
        left = 215
        top = 70
        caption = "Volume 100%"
    END CREATE
    CREATE freqTrackBar AS QTRACKBAR
        left = 10
        top = 110
        width = 200
        height = 30
        tickStyle = tsManual
        max = 44100
        position = 22050
        min = 0
        onChange = freqTrackBarChange
        enabled = FALSE
    END CREATE
    CREATE freqLabel AS QLABEL
        left = 215
        top = 120
        caption = "Frequency 22050Hz"
    END CREATE
    CREATE positionTrackBar AS QTRACKBAR
        left = 10
        top = 160
        width = 200
        height = 30
        tickStyle = tsManual
        onChange = positionTrackBarChange
        enabled = FALSE
    END CREATE
    CREATE positionLabel AS QLABEL
        left = 215
        top = 170
        caption = "Position 0 / 0"
    END CREATE
    CREATE playButton AS QBUTTON
        left = 30
        top = 210
        caption = "&Play"
        enabled = FALSE
        onClick = playButtonClick
    END CREATE
    CREATE stopButton AS QBUTTON
        left = 110
        top = 210
        caption = "&Stop"
        enabled = FALSE
        onClick = stopButtonClick
    END CREATE
    onShow = formShow
    showModal
END CREATE

SUB formShow (sender AS QFORM)
    panTrackBar.setTick(0)
    volumeTrackBar.setTick(50)
    freqTrackBar.setTick(22050)
    dxSound.looped = FALSE
END SUB

SUB exitItemClick (sender AS QMENUITEM)
    form.close
END SUB

SUB openItemClick (sender AS QMENUITEM)
    DIM openDialog AS QOPENDIALOG

    openDialog.filter = "*.wav|*.wav"
    IF openDialog.execute THEN
        dxSound.fileName = openDialog.fileName
        panTrackBar.enabled = TRUE
        volumeTrackBar.enabled = TRUE
        freqTrackBar.enabled = TRUE
        positionTrackBar.enabled = TRUE
        playButton.enabled = TRUE
        stopButton.enabled = TRUE
        positionTrackBar.position = 0
        positionTrackBar.max = dxSound.size
        freqTrackBar.position = dxSound.frequency
        freqTrackBarChange(freqTrackBar)
        positionTrackBarChange(positionTrackBar)
    END IF
END SUB

SUB playButtonClick (sender AS QBUTTON)
    dxSound.play
    WHILE dxSound.playing
        doEvents
        positionTrackBar.position = dxSound.position
        positionLabel.caption = "Position "+STR$(positionTrackBar.position)+" / "+STR$(dxSound.size)
    WEND
END SUB

SUB stopButtonClick (sender AS QBUTTON)
    dxSound.stop
    dxSound.position = 0
    positionTrackBar.position = 0
END SUB

SUB positionTrackBarChange (sender AS QTRACKBAR)
    dxSound.position = sender.position
    positionLabel.caption = "Position "+STR$(sender.position)+" / "+STR$(dxSound.size)
END SUB

SUB freqTrackBarChange (sender AS QTRACKBAR)
    dxSound.frequency = sender.position
    freqLabel.caption = "Frequency "+STR$(sender.position)+"Hz"
END SUB

SUB volumeTrackBarChange (sender AS QTRACKBAR)
    dxSound.volume = sender.position
    volumeLabel.caption = "Volume "+STR$(sender.position)+"%"
END SUB

SUB panTrackBarChange (sender AS QTRACKBAR)
    dxSound.pan = sender.position
    panLabel.caption = "Pan "+STR$(sender.position)+"dB"
END SUB


QDXTIMER

Rapid-Q Documentation by William Yu (c)1999 Appendix B: QDXTIMER

QDXTIMER Component

QDXTimer is a high precision timer for DirectX. It has automatic frame adjustments. This component gives better timer resolution than QTIMER, but don't expect better than 10 - 20 milliseconds resolution.

QDXTimer Properties
Field | Type | R/W | Default
ActiveOnly | INTEGER | RW | True
Enabled | INTEGER | RW | False
FrameRate | INTEGER | R
Interval | INTEGER | RW

QDXTimer Methods
Method Type Description Params

QDXTimer Events
Event | Type | Occurs when... | Params
OnTimer | VOID | Timer expired | 0

QDXTimer Examples
See DIRECTX.BAS example


QD3DFACE

Rapid-Q Documentation by William Yu (c)1999, John Kelly Appendix B: QD3DFACE

QD3DFACE Component

QD3DFace implements IDirect3DRMFace. A face is at least 3 vertices (1 vertex is an x,y,z point in space) that form a surface or plane. You give it the vertex data and QD3DFACE will generate the face for you. You can have a face with many vertices for a simple 3D shape, but vertices turned "inward" will not always be rendered. The order of the vertices are important as D3D only renders the "front" face. See D3D_Details for more information. Once a face is made, you add it to a QD3DMeshBuilder object.

QD3DFace Properties
Field | Type | R/W | Default
VertexCount | INTEGER Only returns the current QD3Dface | R

QD3DFace Methods
Method | Type | Description | Params
AddVertex | SUB (X#, Y#, Z#) | Add a vertex | 3
GetVertex | SUB (Index AS LONG, Position AS QD3DVector, Normal AS QD3DVector) | Retrieve the position and normal of a vertex | 3
SetColorRGB | SUB (R#, G#, B#) | Set face color | 3

QD3DFace Events
Event Type Occurs when... Params

QD3DFace Examples
$TYPECHECK ON

'*******************************************************************************************
'  simple program demonstrating manual meshes built in DIRECT 3D in RapidQ
'lights are moved by mouse by the QD3DFrame it is attached to
' Notice that each face of the polygon has one normal on the outside surface
' and is transparent on opposite side!! This is called "backface culling"
' JohnK
'******************************************************************************************
'
$INCLUDE "RapidQ_D3D.INC"		'constants

DECLARE SUB DXInitialize(Sender AS QDXScreen)	'initalize Direct3D Retained mode interface
DECLARE SUB DXInitializeSurface(Sender AS QDXScreen)'initialize Direct Draw surface
DECLARE SUB DXTimerExpired
DECLARE SUB MakePyramidMesh (TheMeshBuilder AS QD3DMeshBuilder)
DECLARE SUB ToggleRotation

DIM DXTimer AS QDXTimer			'regularly update display
    DXTimer.Enabled = 1
    DXTimer.Interval = 0
    DXTimer.Activeonly = 0
    DXTimer.OnTimer = DXTimerExpired

DIM MeshFrame AS QD3DFrame		'possible for root frame all 3d objects should be attached to a frame
DIM LightFrame AS QD3DFrame		'lights must be placed on a frame. Camera is attached to a frame by RapidQ for you
DIM MeshBuilder AS QD3DMeshBuilder	'mesh builder to create a mesh out of the face
DIM i as single				'increment a translation
DIM RotAngl as single : RotAngl = 0.03
DIM RotateIt as single: RotateIt = 0 ' toggle on/off rotation

RANDOMIZE
CREATE Form AS QForm
     Caption = "Direct 3D Example - click or move mouse"
    Width = 640
    Height = 480
    Center
    CREATE DXScreen AS QDXScreen	'really a direct draw surface?
        Init(640,480)
        Align = 5			'alClient - need this to center Direct Draw screen onto Form
        BitCount = 24			'24 bits/pixel use 32 for alpha bending on fast 3d cards
        Use3D = 1			'load Direct3D Retained mode
        UseHardware = 1			'get real!! 3D accelerated video cards are cheap
        OnInitialize = DXInitialize	'load your meshs/faces to the frames, set lights, camera
    OnInitializeSurface = DXInitializeSurface	'screen is ready to be drawn
    OnMouseDown = ToggleRotation			'mouse click stops/starts rotation
     END CREATE
 ShowModal						'get the program running
END CREATE

SUB DXInitialize(Sender AS QDXScreen)
    DIM Ambient AS QD3DLight	'need at least one light this can be local sub-- we won't modify it
    DIM Light AS QD3DLight		'will define as point light
''	*********  First we create the Frames  ******************
    DXScreen.CreateFrame(MeshFrame)		'create the frames objects will be attached to
    DXScreen.CreateFrame(LightFrame)	'probably allocates memory, handles, etc
    DXScreen.CreateMeshBuilder(MeshBuilder)	' all DXscreen.CreateXX are actually functions and return err codes!!

''		*********  next create the lights  ******************
    DXScreen.CreateLightRGB(D3DRMLIGHT_AMBIENT, 0.2, 0.2, 0.3, Ambient)	'ambient is dim grey
    DXScreen.AddLight(Ambient)		'ambient light moves with root frame
    DXScreen.CreateLightRGB(D3DRMLIGHT_POINT, .8, .8, 0.1, Light)	LightFrame.AddLight(Light)		'attach light to frame to move the light
    LightFrame.SetPosition(0, 2, -1)			'position the point light, units are x,y,z

    MakePyramidMesh(MeshBuilder)			'create your own mesh
    MeshBuilder.SetRGB(1, 1, 1)			'reflects all light on it
    MeshBuilder.SetQuality(D3DRMRENDER_GOURAUD)	'highest rendering Quality is D3DRMRENDER_PHONG, but not much diff
    MeshFrame.AddVisual(MeshBuilder)		'add it to a frame to move, translate, etc.
    MeshFrame.SetRotation(0, 0, 0,RotAngl)		' Angle of rotation on center for the planes we just made
    DXScreen.SetCameraPosition(1.5, 2, 0)		'you can move the camera around instead of rotating 3d object
    DXScreen.CameraLookAt(MeshFrame, D3DRMCONSTRAIN_Z)	'constrain the angle that the camera looks at
END SUB

SUB DXInitializeSurface(Sender AS QDXScreen)
   DXScreen.SetRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY)
END SUB

SUB DXTimerExpired
    LightFrame.SetPosition(Screen.MouseX/200, Screen.MouseY/200,  Screen.MouseY/200)
    DXScreen.ForceUpdate(0,0,50,40)     ' Update FPS text only
    DXScreen.Move(1)                    ' This does the rotation by 2 times
    DXScreen.Render
    DXScreen.TextOut(10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
    DXScreen.Flip
END SUB

SUB ToggleRotation
    IF RotateIt THEN
        MeshFrame.SetRotation(0, 0, 0, 0)
        RotateIt= 0
    ELSE
        MeshFrame.SetRotation(0, 0, 0, RotAngl)	' rotate on center, Angle of rotation is variable
        LightFrame.SetPosition(-1, 2, 0)	'units are x,y,z
        RotateIt = 1
    END IF
END SUB

SUB MakePyramidMesh (TheMeshBuilder AS QD3DMeshBuilder)
''		*********  next create a pyramid of 3-sided polygons  ******************

    DIM MaxX AS DOUBLE, MaxY AS DOUBLE		'terrain dimension
    DIM Face AS QD3DFace			'won't modify in main program so just declare it in sub
    MaxX = .5: MaxY = .5
        DXScreen.CreateFace(Face)
        Face.AddVertex(-MaxX, -MaxY, 0)
        Face.AddVertex(MaxX, -MaxY, 0)
        Face.AddVertex(0, 0, .5)
        TheMeshBuilder.AddFace(Face)	'make 3-sided polygons on the face into a mesh for rendering

        DXScreen.CreateFace(Face)
        Face.AddVertex(MaxX, -MaxY, 0)
        Face.AddVertex(MaxX, MaxY, 0)
        Face.AddVertex(0, 0, .5)
        TheMeshBuilder.AddFace(Face)	'work in a counter-clockwise fashion

        DXScreen.CreateFace(Face)
        Face.AddVertex(MaxX, MaxY, 0)
        Face.AddVertex(-MaxX, MaxY, 0)
        Face.AddVertex(0, 0, .5)
        TheMeshBuilder.AddFace(Face)

        DXScreen.CreateFace(Face)
        Face.AddVertex(-MaxX, MaxY, 0)
        Face.AddVertex(-MaxX, -MaxY, 0)
        Face.AddVertex(0, 0, .5)
        TheMeshBuilder.AddFace(Face)	'these are not OPTIMIZED faces since they share vertices
END SUB


QD3DFRAME

Rapid-Q Documentation by William Yu (c)1999, John Kelly Appendix B: QD3DFRAME

QD3DFRAME Component

QD3DFrame implements IDirect3DRMFrame. All 3D objects must be added with a QD3DFrame.AddVisual to be seen. There is a hidden PARENT frame (not the same as the Parent property) that all QD3DFrames attach to and move with. The "Camera" is also attached to the hidden PARENT frame for you by RapidQ. The QD3DFrame basically holds the 3D transformation matrix for rotation, scaling, and translation (a 4 x 4 homogeneous matrix). There is no GetTransformationMatrix function, so always keep track of your coordinates for the QD3DFrame.

QD3DFrame Properties
Field | Type | R/W | Default
FogColor | INTEGER | RW
FogEnabled (Probably WILL CRASH YOUR PROGRAM!) | INTEGER | RW
FogMode | INTEGER | RW
Parent QFORM/QPANEL (undocumented) Set parent property R/W

QD3DFrame Methods
Method | Type | Description | Params
AddFrame | SUB (Frame AS QD3DFrame) | Add a frame to this frame | 1
AddLight | SUB (Light AS QD3DLight) | Add light object to frame | 1
AddScale | SUB (CombineType%, X#, Y#, Z#) | Add scale | 4
AddVisual | SUB (Visual AS QD3DMeshBuilder/QD3DMesh/QD3DVisual) | Add visual object to frame | 1
CreateFrame | SUB (Frame AS QD3DFrame) | Create frame relative to this | 1
DeleteFrame | SUB (Frame AS QD3DFrame) | Removes a frame from hierarchy | 1
DeleteLight | SUB (Light AS QD3DLight) | Removes light object from frame | 1
DeleteVisual | SUB (Visual AS QD3DMeshBuilder/QD3DMesh/QD3DVisual) | Removes visual object from frame | 1
Load | SUB (FileName AS STRING) | Load a frame from .X file | 1
LookAt | SUB (F AS QD3DFrame, Constraint AS INTEGER) | Fix frame and constrain rotation | 2
Move | SUB (D AS DOUBLE) | Moves frame (rotate) | 1
SetBackgroundImage | SUB (Texture AS QD3DTexture) | Add texture to frame | 1
SetBackgroundRGB | SUB (R#, G#, B#) | Set background color | 3
SetFogParams | SUB (Start#, End#, Density#) (Don't expect this to work!) | Set fog parameters | 3
SetOrientation | SUB (DX#, DY#, DZ#, UX#, UY#, UZ#) | Set orientation of frame | 6
SetPosition | SUB (X#, Y#, Z#) | Set viewing position of frame | 3
SetRotation | SUB (X#, Y#, Z#, Theta#) | Set rotation relative to X,Y,Z | 4
SetTexture | SUB (Tex AS QD3DTexture) (Don't expect this to work!) | Add texture backdrop to frame | 1

QD3DFrame Events
Event Type Occurs when... Params

QD3DFrame Examples
(see the DEAengine examples at g.slyip.com)


QD3DLIGHT

Rapid-Q Documentation by William Yu (c)1999, John Kelly Appendix B: QD3DLIGHT

QD3DLIGHT Component

QD3DLight implements IDirect3DRMLight.

QD3DLight Properties
Field Type R/W Default
Parent QFORM/QPANEL (undocumented) Set parent property
Possible? QD3DLIGHT.PARENT = QD3DFrame 		R/W

QD3DLight Methods
Method | Type | Description | Params
SetLightRGB | SUB (LightType%, R#, G#, B#) | Set lighting type and color | 4
SetPenUmbra | SUB (Angle#) | Set light of outer cone | 1
SetRange | SUB (Range#) | Set range of light | 1
SetUmbra | SUB (Angle#) | Set light of inner cone | 1

QD3DLight Events
Event Type Occurs when... Params

QD3DLight Examples

'declare at GLOBAL level
'Master (parent) frame all 3d objects moving together attached to this frame
DIM WorldFrame      AS QD3DFrame
DIM AmbientLight    AS QD3DLight
DIM DayLight        AS QD3DLight
DIM DayLightFrame   AS QD3DFrame 'lights on a frame to turn on/off
DIM NightLight      AS QD3DLight 'like a flash light (spot/point light) in the dark
DIM NightLightFrame AS QD3DFrame 'This one for dark

'Then put this sample code in the QDXScreen.OnInit section:
  'ambient is dark for baseline darkness!!
DXScreen.CreateLightRGB(D3DRMLIGHT_AMBIENT, 0.3, 0.3, 0.3, AmbientLight)
DXScreen.AddLight(AmbientLight) 'this light moves with root frame
'true ambient day light
DXScreen.CreateLightRGB(D3DRMLIGHT_AMBIENT, 1.0, 0.91, 0.8, DayLight) DayLightFrame.AddLight(DayLight) 'to a frame so we can remove from scene
DayLightFrame.SetPosition(0, 30, 0) 'x,y,z position, some arbitary value until load a terrain
DayLightFrame.SetOrientation(0, -1, 0, 0, 1, 0) 'points straight down
' Could add on another sun light
' -- D3DRMLIGHT_DIRECTIONAL, or D3DRMLIGHT_POINT 'point is most computational,
' i.e., DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.3, 0.45, 0.5, SunLight)
 'directional is less computational
 'a cone of light works w/ the next commands
DXScreen.CreateLightRGB(D3DRMLIGHT_SPOT, 1.0, 1.0, 0.6, NightLight)
NightLightFrame.AddLight(NightLight) 'to a frame so we can remove from scene
NightLightFrame.SetPosition(0, 2, -20) 'x,y,z position,
NightLightFrame.SetOrientation(0, 0, 1, 0, 1, 0) 'points forward
View_Day_Time 'turn on day time

SUB View_Night_Time
DayLightFrame.DeleteLight(DayLight) 'attach light to frame to move the light!
'can't do this NightLight.SetLightRGB(D3DRMLIGHT_SPOT,0.505, 0.505, 0.02)
'simulate tungsten light
NightLight.SetUmbra(0.45) 'inner cone range in angle
NightLight.SetPenUmbra(0.97)
NightLight.SetRange(Max.Y/10)
NightLightFrame.AddLight(NightLight) 'attach light to frame to move the light!
ViewNightTimeMnu.Checked = True
ViewDayTimeMnu.Checked = False
END SUB

SUB View_Day_Time
NightLightFrame.DeleteLight(NightLight) 'attach light to frame to move the light!
DayLightFrame.AddLight(DayLight) 'attach light to frame to move the light!
' this code only sets ambient once and only once, can't change
' DXScreen.CreateLightRGB(D3DRMLIGHT_AMBIENT, 1.0, 1.0, 0.1, AmbientLight)
'ambient is dark for baseline darkness!!
' DXScreen.AddLight(AmbientLight) 'this light moves with root frame
ViewNightTimeMnu.Checked = False
ViewDayTimeMnu.Checked = True
END SUB


QD3DMESH

Rapid-Q Documentation by William Yu (c)1999 Appendix B: QD3DMESH

QD3DMESH Component

QD3DMesh implements IDirect3DRMMesh.

NOTE this component was unfinished. It has no real purpose or use. There is no way to add vertices, faces, colors, etc. to the component. MinY and MaxY return 0 after creation of a loaded Object. Use QD3DMeshBuilder instead.

QD3DMesh Properties

Field | Type | R/W | Default
MaxY | SINGLE | R
MinY | SINGLE | R

QD3DMesh Methods
Method Type Description Params

QD3DMesh Events
Event Type Occurs when... Params

QD3DMesh Examples
None-- do not use


QD3DMESHBUILDER

Rapid-Q Documentation by William Yu (c)1999, John Kelly Appendix B: QD3DMESHBUILDER

QD3DCamera Component

QD3DMeshBuilder implements IDirect3DRMMeshBuilder. This is the most important part of defining 3D objects in RapidQ. Either make a set of faces with QD3DFACE and then add them to the QD3DMESHBUILDER or you can load .X files or .3ds files if you have CONV3DS.EXE. See demos in DEAengine for sample code. If you want alphablending you must set (at least:)

DxScreen.setRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY)
Add the QD3DMESHBUILDER to a QD3DFrame in order to scale, rotate, or move it around the scene.

QD3DMeshBuilder Properties
Field | Type | R/W | Default
FaceCount | INTEGER Only of the last QD3Dface added | R
Parent QFORM/QPANEL (undocumented) Set parent property R/W

QD3DMeshBuilder Methods
Method | Type | Description | Params
AddFace | SUB (Face AS QD3DFace) | Add a face to mesh object | 1
AddVertex | SUB (X#, Y#, Z#) | Add a vertex | 3
CreateFace | SUB (Face AS QD3DFace) | Creates a new face with no vertices | 1
CreateMesh | SUB (Mesh AS QD3DMesh) | Create mesh from meshbuilder | 1
DeleteFace | SUB (Face AS QD3DFace) | Delete face from meshbuilder | 1
GetFace | SUB (Index AS LONG, Face AS QD3DFace) | Get a single mesh face | 2
Load | SUB (S AS STRING) | Load an object file (.x file) | 1
LoadTexture SUB (S AS STRING)
MeshBuilder. LoadTexture(“ground.bmp”) 		Texture file with a BMP file (use w/ D3DWrap) 1
Move | SUB (D AS DOUBLE) | Moves frame (rotate) | 1
Scale | SUB (X#,Y#,Z#) | Scale object | 3
SetQuality | SUB (Quality AS INTEGER) | Set rendering quality | 1
SetRGB | SUB (R#, G#, B#) | Set object's color | 3
SetRGBA | SUB (R#, G#, B#, A#) | Add color w/alphablending | 4
SetTexture | SUB (Tex AS QD3DTexture) | Add texture backdrop to object | 1
Translate | SUB (TX#, TY#, TZ#) | Translate is a move operation but in 3D | 3

QD3DMeshBuilder Events
Event Type Occurs when... Params

QD3DMeshBuilder Examples


QD3DTEXTURE

Rapid-Q Documentation by William Yu (c)1999 Appendix B: QD3DTEXTURE

QD3DTEXTURE Component

QD3DTexture implements IDirect3DRMTexture.

QD3DTexture Properties
Field Type R/W Default

QD3DTexture Methods
Method Type Description Params

QD3DTexture Events
Event Type Occurs when... Params

QD3DTexture Examples


QD3DVECTOR

Rapid-Q Documentation by William Yu (c)1999, John Kelly Appendix B: QD3DVECTOR

QD3DVECTOR Component

QD3DVector implements D3DVector. This is a user defined type with x,y,z elements for defining vertices, 3-D points or whatever you need for xyz coordinates. This is actually a UNION. What is a UNION? Basically two elements in the user defined type occupy the same location in memory. So you can read/write only one of the members. For example:
DIM V3D AS QD3DVector
V3D.DVX = 1.5 'note V3D.X will be the same as V3D.DVX !

QD3DVector Properties
Field | Type | R/W | Default
DVX | SINGLE | RW
DVY | SINGLE | RW
DVZ | SINGLE | RW
X | SINGLE (UNION with DVX) | RW
Y | SINGLE (UNION with DVY) | RW
Z | SINGLE (UNION with DVZ) | RW

QD3DVector Methods
Method Type Description Params

QD3DVector Events
Event Type Occurs when... Params

QD3DVector Examples


QD3DVISUAL

Rapid-Q Documentation by William Yu (c)1999 Appendix B: QD3DVISUAL

QD3DVISUAL Component

QD3DVisual implements IDirect3DRMVisual.

QD3DVisual Properties
Field Type R/W Default

QD3DVisual Methods
Method Type Description Params

QD3DVisual Events
Event Type Occurs when... Params

QD3DVisual Examples


QD3DWRAP

Rapid-Q Documentation by William Yu (c)1999 Appendix B: QD3DWRAP

QD3DWRAP Component

QD3DWrap implements IDirect3DRMWrap.

QD3DWrap Properties
Field Type R/W Default

QD3DWrap Methods
Method | Type | Description | Params
Apply | SUB (M AS QD3DMesh/QD3DMeshBuilder) | Apply wrap to mesh | 1
ApplyRelative SUB (F AS QD3DFrame, M AS QD3DMesh/QD3DMeshBuilder) Apply wrap relative to frame
Use this method when the wrap
type is D3DRMWRAP_CHROME,
which makes "environmental
mapping" 		2

QD3DWrap Events
Event Type Occurs when... Params

QD3DWrap Examples
'Correct running verions of the WRAP.BAS program. Shows you
'Chrome wrapping of a 3D object. The other files should be in your
'\examples\direct3d\wrap folder. This is also known as
' "environmental wrapping," which was used to give the metal-chrome
'appearance of the robot in "Terminator2."

$TYPECHECK ON

CONST alClient = 5

'-- Light Types
CONST D3DRMLIGHT_AMBIENT = 0
CONST D3DRMLIGHT_POINT = 1
CONST D3DRMLIGHT_SPOT = 2
CONST D3DRMLIGHT_DIRECTIONAL = 3
CONST D3DRMLIGHT_PARALLELPOINT = 4

'-- Renderer modes
CONST D3DRMRENDERMODE_BLENDEDTRANSPARENCY = 1
CONST D3DRMRENDERMODE_SORTEDTRANSPARENCY = 2
CONST D3DRMRENDERMODE_LIGHTINMODELSPACE = 8
CONST D3DRMRENDERMODE_VIEWDEPENDENTSPECULAR = 16
CONST D3DRMRENDERMODE_DISABLESORTEDALPHAZWRITE = 32

'-- Wrap Types
CONST D3DRMWRAP_FLAT = 0
CONST D3DRMWRAP_CYLINDER = 1
CONST D3DRMWRAP_SPHERE = 2
CONST D3DRMWRAP_CHROME = 3
CONST D3DRMWRAP_SHEET = 4
CONST D3DRMWRAP_BOX = 5

CONST WrapType = D3DRMWRAP_CHROME '-- You can modify this

DECLARE SUB DXInitialize(Sender AS QDXScreen)
DECLARE SUB DXInitializeSurface(Sender AS QDXScreen)
DECLARE SUB DXTimerExpired

DIM DXTimer AS QDXTimer
DXTimer.Enabled = 1
DXTimer.Interval = 0
DXTimer.OnTimer = DXTimerExpired

DIM MeshFrame AS QD3DFrame
DIM Mesh AS QD3DMesh
DIM Wrap AS QD3DWrap
DIM MeshBuilder AS QD3DMeshBuilder

CREATE Form AS QForm
Caption = "Direct 3D Example"
Center
Width = 330
Height = 350
CREATE DXScreen AS QDXScreen
Init(320,240)
Align = alClient
Use3D = 1
UseHardware = 1 ''for accelerated cards 0 for old ones
OnInitialize = DXInitialize
OnInitializeSurface = DXInitializeSurface
END CREATE
ShowModal
END CREATE

SUB CreateWrap
DXScreen.CreateWrap(WrapType, 0,0,0, 0,0,1, 0,1,0, 0,0, 1,1, Wrap)
Wrap.Apply(MeshBuilder)
END SUB

SUB DXInitialize(Sender AS QDXScreen)
DIM Light AS QD3DLight, Ambient AS QD3DLight
DIM LightFrame AS QD3DFrame
DIM Texture AS QD3DTexture

IF FileExists("back2.bmp") THEN
DXScreen.LoadTexture("back.bmp", Texture)
DXScreen.SetBackgroundImage(Texture)
ELSE
ShowMessage "missing bitmap"
END IF

DXScreen.CreateFrame(LightFrame)
DXScreen.CreateFrame(MeshFrame)

DXScreen.CreateLightRGB(_
D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, Light)
LightFrame.AddLight(Light)

DXScreen.CreateLightRGB(_
D3DRMLIGHT_AMBIENT, 0.1, 0.1, 0.1, Ambient)
DXScreen.AddLight(Ambient)

LightFrame.SetPosition(2, 0, 22)
DXScreen.SetCameraPosition(-5, 5, 0)
'numbers for CameraOrientation range from-1 to 1
DXScreen.SetCameraOrientation(0.35, -0.45, 1.0, -0.15, 1.0, 0.5)

MeshFrame.SetPosition(0, 0, 15)
MeshFrame.SetOrientation(0, 0, 1, 0, 1, 0)
'the SetRotation is a quaterion!
MeshFrame.SetRotation(0, 1, 0, 0.05) 'Angle = 0.05

DXScreen.CreateMeshBuilder(MeshBuilder)
' MeshBuilder.Load("cube.x") '-- should be in example folder
MeshBuilder.Load("egg.x") '-- egg object
MeshBuilder.Scale(2,2,2)
MeshBuilder.SetRGBA(1, 1, 1, 0.8) '-- Alpha blending!

MeshBuilder.LoadTexture("back2.bmp")
MeshFrame.AddVisual(MeshBuilder)
CreateWrap

END SUB

SUB DXInitializeSurface(Sender AS QDXScreen)
DXScreen.SetRenderMode(_
D3DRMRENDERMODE_BLENDEDTRANSPARENCY OR D3DRMRENDERMODE_SORTEDTRANSPARENCY)
END SUB

SUB DXTimerExpired
'DXScreen.Fill(0) ' Call this or
DXScreen.ForceUpdate(0,0,40,40) ' Update FPS text only
'DXScreen.Move(2) ' this is rotation by 2 times
MeshFrame.Move(1)
IF WrapType = D3DRMWRAP_CHROME THEN
Wrap.ApplyRelative(MeshFrame,MeshBuilder) 'for each frame!
END IF
DXScreen.Render
DXScreen.TextOut(_
10,10,"FPS: "+STR$(DXTimer.FrameRate), &HFFFFFF, -1)
DXScreen.Flip
END SUB
Prev Component Contents Next Component


Operators

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Operators

Introduction to Operators

Operators perform mathematical or logical operations on values. They are usually encompassed by an expression. For example, 2 * 8 is a valid expression, and * is an operator operating on values 2 and 8. Rapid-Q can evaluate both INFIX and POSTFIX (RPN) expressions, but if you want to evaluate POSTFIX expressions, you'll need to note the special cases.

Arithmetic operators
Rapid-Q maintains a table of precedence for each operator. The highest precedence operator will always execute before any lower precedence operator. For operators that share the same precedence, the left to right associativity law holds. Expressions enclosed in braces (...) automatically have higher precedence than expressions outside the braces.
Operation Operator Precedence Description
String index [] 1 Returns a character from a string
ie. s$[2]
returns the second character in string s$
Exponentiation ^ 1 Calculates power of a number
ie. 2^6
is 2 to the power of 6
Negation - 1 Negates a number
ie. -99
is negative 99
Multiplication * 2 Multiplies 2 numbers
ie. 2*6
is 2 multiplied by 6
Floating-point Division / 2 Divides 2 floating point numbers
ie. 6.5/2.6
is 6.5 divided by 2.6
Integer Division \ 2 Divides 2 integer numbers
Before integer division is performed, operands are rounded to integers. The result is truncated to an integer value.
ie. 6\2
is 6 divided by 2
Left Bit Shift SHL 2 Shifts bits left by amount specified
ie. 10 SHL 2
is number 10 whose bits are shifted 2 bits to the left
Right Bit Shift SHR 2 Shifts bits right by amount specified
ie. 10 SHR 2
is number 10 whose bits are shifted 2 bits to the right
Modulus/Remainder MOD 3 Returns the remainder of the division
ie. 15 MOD 10
is 15/10 whose remainder is 5
Inverse Modulus INV 3 Returns the inverse of a number in modulus
ie. 3 INV 26
The inverse of 3 is 9 in 1 (MOD 26)
Addition + 4 Add 2 operands (strings included)
ie. 3+6
is 3 plus 6 = 9
ie. "hi"+"world"
is "world" appended to "hi" = "hiworld"
Addition & 4 Same as using '+' but maintained for compatibility with other BASIC languages, such as VB.
Subtraction - 4 Subtracts 2 operands (strings included)
ie. 6-3
is 6 minus 3 = 3
ie. "jello"-"l"
is "jello" minus all occurrences of "l" = "jeo"

Relational operators
Relational operators are used to compare 2 values. The result of this comparison is either "true" (nonzero) or "false" (zero). You may assume that "true" equals -1.
Relation Operator Precedence Description
Equality = 5 Tests for equality between 2 operands (strings included)
ie. 2=2
if 2 equals 2 then "true" else "false"
Inequality <> 5 Tests for inequality between 2 operands (strings included)
ie. "hello"<>"world"
if "hello" is not equal to "world" then "true" else "false"
Less than < 5 Tests if operand is less than another (strings included)
ie. 2<10
if 2 is less than 10 then "true" else "false"
Greater than > 5 Tests if operand is greater than another (strings included)
ie. "z">"a"
if "z" is greater than "a" then "true" else "false"
Less than or equal <= 5 Tests if operand is less than or equal to another (strings included)
ie. 2<=10
if 2 is less than or equal to 10 then "true" else "false"
Greater than or equal >= 5 Tests if operand is greater than or equal to another (strings included)
ie. 20>=10
if 20 is greater than or equal to 10 then "true" else "false"

Logical operators
Logical operators perform tests on multiple relations, bit manipulation, or Boolean operations and return a true (nonzero) or false (zero) value to be used in making a decision.
Operation Operator Precedence Description
Logical complement NOT 6 Returns the complement (inverted bits)
ie. NOT -1
-1 has all bits set, NOT -1 inverts all bits
Conjunction AND 7 Compare corresponding bits in 2 operands and sets the corresponding bit in the result to 1 if both bits are 1.
ie. 5 AND 3
5 AND 3 = 1 since their first bits are set
Disjunction (inclusive "or") OR 8 Compares corresponding bits in 2 operands and sets bit to 1 if either one has a corresponding bit set.
ie. 5 OR 3
5 OR 3 = 7 since bits overlap
Exclusive "or" XOR 9 Compares corresponding bits in 2 operands and sets bit to 1 if only one of the operands has a corresponding bit set.
ie. 5 XOR 3
5 XOR 3 = 6 since one bit overlaps

INFIX/POSTFIX notation
Expressions, in most languages, are expressed in INFIX notation. Rapid-Q prefers INFIX notation, but can also handle POSTFIX notation with a few special cases.
      Example INFIX expression:
          A = 4 * 7 + (4 - 1)^6
INFIX notation is easier to use and understand than POSTFIX notation. In fact, Rapid-Q's POSTFIX notation is a simple side effect, and was not intentional. Please avoid using POSTFIX if possible.
      Example POSTFIX expression:
          A = (4) (7) (*) (4) (1) (-) (6) (^) (+)
The 2 expressions should evaluate to 757. As you'll note, when dealing with POSTFIX notation, make sure all operands and operators are enclosed in braces. When dealing with negation, you'll have to do this instead:
      Example POSTFIX expression w/negation:
          A = (5) (0-5) (-)
Notice that (0-5) and (-5) return different results.


Rapid-Q definitions

Rapid-Q Documentation by William Yu (c)1999, Appended by John Kelly Rapid-Q definitions

Internal Definitions

Rapid-Q has these variables already defined:
    $DEFINE WIN32 WIN32
    $DEFINE UNIX  UNIX
    $DEFINE TYPE  STRUCT
WIN32 is defined if you're using the Windows version of Rapid-Q
UNIX is defined if you're using the Linux/Unix version of Rapid-Q
TYPE is defined to replace the old style TYPE

Definitions for RapidQ.inc:
   __RQINC          'signals rapidQ.inc loaded
       (e.g. RapidQ.inc has the line $DEFINE __RQINC )
    __QBCOLOR        'signals RapidQ uses QBcolor(x) constants (in RapidQ.inc)

also see $DEFINE

Unhooking definitions
The term "unhooking" just means undefining a definition, ie:
    $UNDEF TYPE

This is the only definition that can affect your program when unhooked.
See the section on "User Defined Types" for more information.

Using definitions
Chapter 3 lists some examples on using $IFDEF and $IFNDEF:
    $IFDEF WIN32
         PRINT "I'm using the Windows version!"
    $ELSE
         PRINT "I'm using the Linux/Unix version!"
    $ENDIF


Rapid-Q Supported Data Types

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Data Types

Introduction to Data Types

A data type is just a definition. It is used to bind a variable to its definition and cannot be changed once bound (except for VARIANT type variables). For example, if a variable is bound to a STRING data type, it cannot change itself to an INTEGER definition. A variable can be assigned any one of these supported data types, BYTE, WORD, DWORD, SHORT, LONG/INTEGER, SINGLE, DOUBLE, STRING, VARIANT, and fixed-length strings. There are also such things as User Defined Data Types, which will be discussed in another section. Some BASIC implementations hold INTEGER as a 16-bit value, while Rapid-Q chooses to go 32-bit. So if you're worried about converting your old code, make sure to replace all occurrences of INTEGER with SHORT.

How to use data types
Since Rapid-Q is a BASIC language, there are 2 ways to define your variables. You can choose to do it explicitly using DIM
    DIM myNum AS LONG
    DIM myStr AS STRING
Similarly, you can attach a suffix symbol which describes the variable type:
    myNum& = 234
    myStr$ = "abc"
Chapter 3 has a list of these suffixes, but are listed here again for your convenience:
    Type       ID  Size  Range
    --------- ---- ---- -------------
    Byte        ?   1   0..255
    Word       ??   2   0..65535
    Dword     ???   4   Only Linux version for now...
    Short       %   2   -32768..32767
    Integer     &   4   -2147483648..2147483647
    Long        &   4   -2147483648..2147483647
    Single      !   4   1.5 x 1045..3.4 x 1038
    Double      #   8   5.0 x 10324..1.7 x 10308
    String      $

For C/Visual Basic conversion to RapidQ variable types see Vartypes.htm
A variant data type has no suffix, so you'll have to use DIM instead, or change the default DIM operation.
    $OPTION DIM VARIANT

    myVar = "hello!"
myVar is defined as a VARIANT since we've changed the default data type for DIM. Whenever Rapid-Q comes across an undefined symbol (with no suffix), it will choose the data type according to traditional BASIC. Traditionally, this has been choosen to be either SINGLE or DOUBLE. With Rapid-Q, you can choose any of the existing data types as the default one.

Variant data type
A Variant is a special kind of data type, since a Variant can mutate. Don't be afraid, it won't mutate to a virus or anything like that. It simply changes types on the fly, as needed. Even a simple operation like addition changes when you add 2 variants together. Take this for example:
   DIM V1 AS VARIANT, V2 AS VARIANT

   V1 = 101
   V2 = "99.5"

   PRINT V1+V2  '-- Output is 200.5
As you'll notice V2 is originally assigned a string, but V2 has changed its type to a floating point number when the addition takes place. Note that V2 is still a string, it just mutated itself for that one operation. Similarly,
   DIM V1 AS VARIANT, V2 AS VARIANT

   V1 = "101"
   V2 = 99.5

   PRINT V1+V2  '-- Output is 10199.5
In this case, V2 was originally a floating point number, but changed its type during the addition operation to a string. Notice how the order of operation defines the mutation. In the previous example, V1 was a number, so V1+V2 results in a numeric expression, while the above example produces a string.


Branching with GOTO and GOSUB

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Branching

Introduction to Branching

Branching seems to be very popular in BASIC, mainly because in the old days, BASIC was very unstructured and didn't carry with it the concepts we now see today. Sure, some say it's still unstructured, but so is a lot of other languages depending on your coding style. Branching is just the mechanism of skipping (or jumping) instructions, either forward or backward. It's much like writing SUBs and FUNCTIONs, just a bit more unstructured as you'll see.

What are labels?
Before talking about GOTOs and GOSUBs, you'll need to understand what labels are. You can think of them as bookmarks, they don't actually do anything, but you can use labels as a guide. The following are valid labels:
    Label1:
    100
    10.5
A label always appears as the first statement and can be any number or a named label. A named label must end with a colon : symbol. After any label, you can write your code as before.
    Label1:
       PRINT "some code..."
    100 PRINT "more code"
    10.5
       PRINT "yet more code"
The formatting above is just an example, it doesn't mean that a named label can't have code on the same line.

Branching with GOTO
Perhaps the most shunned upon keyword in BASIC is the GOTO statement. Obviously if you programmed in BASIC before, GOTO was used almost everywhere. This is because GOTO was so easy to understand, and when we first jump into programming, we don't usually pick up what subroutines and functions are. Rapid-Q still supports GOTO, but we definitely don't encourage its use, at all. In fact, if you find yourself using it now, you'll probably wonder why in a few years/months as you become more experienced. Here's an example of using GOTO:
    IF I = 100 THEN GOTO 10 ELSE GOTO 20

    10 PRINT "I = 100"
       END

    20 PRINT "I is not 100"
       END
If it's so terrible, are there any penalties in its use? No. In fact, it's probably the purest command you'll find. All it does is skip instructions, so in the above example, if I = 200, then the lines
    10 PRINT "I = 100"
       END
are skipped. GOTO requires no stack or memory consumption, unlike GOSUB and SUBs or FUNCTIONs. If you want to think about assembly, that's basically all you do, branch here and there, but since BASIC is a high level language, we usually don't like to think that way, so we avoid using GOTO if possible.

Branching with GOSUB .. RETURN
Using GOSUB is actually more useful than using GOTO, but still not recommended. It is in essence, calling a SUB without parameters. What it provides is a quick "hack" without creating SUBs. It is often used in loops, as you may see here:
    DO
      DO
        A$ = INKEY$
      LOOP UNTIL LEN(A$)

      IF A$ = "A" THEN
          GOSUB 100
      ELSEIF A$ = "B" THEN
          GOSUB 110
      ELSEIF A$ = "C" THEN
          GOSUB 110
      END IF
    LOOP

    END

    100 PRINT "A pressed"
        RETURN
    110 PRINT "B pressed"
        RETURN
    120 PRINT "C pressed"
        RETURN

The RETURN statement is used to jump back to the previous call of GOSUB. You can think of GOSUB as a GOTO statement with a marker, and the RETURN statement as another GOTO statement that returns to that marker.


User Defined Types

Rapid-Q Documentation by William Yu (c)1999 Appendix C: User Defined Types

Introduction to UDTs

User defined types (or UDTs) are structures that you can use in most BASIC languages, Rapid-Q is no exception. You can think of a UDT as a list of variables in a specific order.

Using TYPE
Here's an example of a user defined type:
    TYPE TWorld
        CityName(100) AS STRING
        Population(100) AS LONG
    END TYPE

    DIM World AS TWorld
As you can see, you can have arrays within UDTs. You can also create arrays of UDTs:
    TYPE TWorld
        CityName(100) AS STRING
        Population(100) AS LONG
    END TYPE

    DIM Country(100) AS TWorld
    Sample code would use it something like this:
    Country(1).CityName(15) = "Seattle"
    Country(1).Population(15) = 2343589
There is currently an issue with the memory address of your array (within UDT). Please note that this is hardly ever noticed unless you're going to pass one of these structures to a DLL that require arrays within UDTs. This address problem won't affect your program, but it's hard to explain (without getting too deep). NOTE: it only occurs when you create arrays of UDTs that have arrays within UDTs. In the first example (higher up), there is no address problem since you're not creating an array of UDTs. You can safely pass that to a DLL.

What is not supported
Unlike other languages such as Visual Basic, Pascal, C/C++, you cannot "nest" a UDT inside another UDT.

TYPE POINT
    X as INTEGER
    Y as INTEGER
END TYPE

TYPE Rectangle
    Top     AS POINT
   Bottom   AS POINT        'this won't work
END TYPE

'You would have to write the code this way...
TYPE Rectangle
    TopX     AS INTEGER
    TopY     AS INTEGER
    BottomX  AS INTEGER
    BottomY  AS INTEGER
END TYPE

Using this method, a problem is that you have to be careful not to repeat variable names from the nested UDT. Unfortunately this makes for some messy code when working with header files, Windows API calls, and and source code from other languages.

When you make a UDT and pass it to a DLL, you must have the UDT allocated in memory contiguously. You can use QMEMORYSTREAM and its pointer to make sure it is correctly formatted. You can try pass arrays of UDTs by writting multiple UDTs to a single memory stream. Please see: chapter9.html #97

UDTs and memory pointers
When you pass a UDT to a SUB, FUNCTION, or DLL, you will pass the pointer to the structure. If you read chapter 9 you will know how to pack the UDT into one contiguous block of memory into a QMEMORYSTREAM and get its pointer by QMEMORYSTREAM.Pointer property. Unlike C/C++you can't get the pointer to each element of the UDT, you will have to calculate an offset if you need to get a pointer. This is shown in the next examples

TYPE dataType
   x          AS INTEGER
   y          AS INTEGER
   z(1 to 3)  AS SINGLE    'only 4 bytes allocated (just an array pointer?)
END TYPE

DIM MyUDT AS dataType
DIM Mem AS QMemoryStream
Mem.WriteUDT(MyUDT)

Example#2

TYPE MyType
   Name AS STRING*30
   Phone AS STRING*8
   Age AS INTEGER
   z(1 to 3)  AS SINGLE
END TYPE

DIM Person AS MyType
Person.Name = "Joe"
Person.Phone = "555-5555"

DIM Mem AS QMemoryStream
Mem.WriteUDT(Person)
ShowMessage str$(Mem.Pointer)
ShowMessage str$(sizeof(Person))
Person.z(1) = 2.23451
ShowMessage str$(Person.z(1))
showmessage str$(varptr(Person.Age))  'this doesn't work, but is needed for COM interface!!
showmessage str$(@Person.Age)          'gets the value of the variable
ShowMessage str$(Mem.Pointer + 38 + SizeOf(INTEGER)) 'manually need to calculate offset!!!

Variable length strings and Object pointers are not supported

Only fixed and simple data types (like INTEGER, SINGLE, LONG, STRING *12) can be inside a UDT. For example, the next code sement will not compile..

TYPE MyUDT
    a  AS QRECT
    b  AS QD3DVector
    c  AS STRING
END TYPE
BUT if you define the type with EXTENDS it works...

TYPE newT  EXTENDS  QOBJECT
    a  AS QRECT
    b  AS QD3DVector
    c  AS STRING
END TYPE
Now your code runs ok, but you will probably run into bugs if you use the UDT methods:
Qmemorystream.ReadUDT(newT)
Qmemorystream.WriteUDT(newT)

--And you CAN'T make arrays of them --

DIM NewObj(1 to 100) as newT       'this compiles
NewObj(1).left = 10                'compiler error
So how do you make an array of custom components? You can try QCANVAS instead. It is the only Qcomponent that appears to allow arrays when EXTENDED.

$typecheck on
TYPE NewT EXTENDS QCANVAS
    a as integer
    b as string
    c as Qd3dVector
    d as Qbitmap
    e as single
    'd(1 to 5) as QBitmap        'can't have arrays of objects in an object
    e(1 to 5) as single             'errors occur with nested arrays however,
END TYPE

dim NewObj(1 to 6) as NewT
NewObj(2).a = 2
NewObj(2).b = "aaaaaaaaaaaaaaaaaahhh"
NewObj(1).c.x = 1
NewObj(1).c.dvx = 1
'NewObj(6).d(2).Width = 60 'bug
'NewObj(6).d(1).Height = 60 'bug
'NewObj(1).e(1) = 1.0009 'bug
NewObj(6).d.Width = 60
NewObj(6).d.Height = 60
NewObj(1).e = 1.0009
Still you can't use arrays inside custom components, you will have
to use the template like in this example (see the docs)

TYPE Arrays<DataType, Size> EXTENDS QOBJECT
ArrayItem(Size) AS DataType
and to call it in code

TYPE MyObject<SINGLE, Size> EXTENDS QOBJECT
ArrayItem(Size) AS DataType
... methods/subs/functions here
END TYPE

DIM myVar AS MyObject<SINGLE, 1000>

MyVar.ArrayItem(999) = 1.234
---------------------------------------
Copying UDTs
To copy 2 UDTs, just assign the two:

    TYPE TStuff
        A AS LONG
        B AS INTEGER
    END TYPE

    DIM S1 AS TStuff
    DIM S2 AS TStuff

    S1 = S2
Contents in S2 are copied to S1. When dealing with arrays within UDTs, the arrays are not copied, only referenced. To copy arrays of UDTs, you'll have to manually copy each one:
    DIM S1(100) AS TStuff
    DIM S2(100) AS TStuff

    FOR I = 1 TO 100
        S1(I) = S2(I)
    NEXT

Unhooking TYPE
There are actually 2 ways to create your types, with TYPE and STRUCT. STRUCT is actually mirrored in TYPE, to unhook the two, you have to undefine TYPE.
    $UNDEF TYPE

    TYPE TWorld
        CityName(100) AS STRING
        Population(100) AS LONG
    END TYPE

    DIM World AS TWorld
Using TYPE and STRUCT are not the same. If you unhook the two, TYPE now reverts back to the old style (pre-May 17 version), where arrays of UDTs is not allowed. Why the heck would I want a stripped down version? Well, perhaps performance. The old style TYPE lacks in many things, but makes up in performance, if that's really necessary.


Conditions

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Conditions

Introduction to Condition Statements

Conditional statements offer the ability to execute code for which the condition is satisfied. This is probably one of the first things you learn in programming, besides the usual.

IF .. THEN .. ELSE
There are 2 ways to use IF .. THEN .. ELSE. You can place your statement on one single line like so:
    IF I > 100 THEN PRINT "I is greater than 100"
Or split it up like so:
    IF I > 100 THEN
      PRINT "I is greater than 100"
    END IF
As you can see, I > 100 is a condition, as long as this is satisfied, the code gets executed, if not then that piece of code is skipped. A condition is satisfied whenever the expression evaluates to any non-zero number. Which also means that this is valid:
   I = 100
   IF I THEN
     PRINT "Condition satisfied"
   ELSE
     PRINT "Condition is not satisfied"
   END IF
Use ELSEIF whenever you have multiple conditions that you want satisfied:
   IF I > 10 AND I < 20 THEN
      '' do stuff
   ELSEIF I > 55 THEN
      '' do stuff
   ELSE
      '' do stuff
   END IF
Sometimes it helps to use SELECT CASE instead of all these ELSEIFs, which we'll cover next.

SELECT CASE .. END SELECT
Select cases are usually implemented when you have a lot of conditions that you want to test for. It's really not useful if you only have 2 or 3 conditions, but no one's stopping you from using it. There are no special cases in using SELECT CASEs in Rapid-Q, so everything you learned in QBasic, can be implemented here as well.
    SELECT CASE Expression
      CASE 1
        '' Do stuff
      CASE 5
        '' Do stuff
      CASE ELSE
        '' No conditions satisfied, do stuff
    END SELECT
It probably involves less typing, but there are many other useful purposes, for example, range testing becomes so much easier:

    SELECT CASE Expression
      CASE 1 TO 4, 10 TO 20
        '' Do stuff
      CASE 100 TO 150
        '' Do stuff
      CASE IS > 200
        '' Do stuff
    END SELECT
As you can see, you can have multiple test conditions by separating each with a comma. I think you can figure out how the IS keyword is used.


Loops

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Loops

Introduction to Looping

Loops provide a mechanism for executing a series of instructions a certain number of times. Many of your programs will involve looping. Compilers convert loops to GOTO statements, so you could implement your own LOOP using GOTOs without any consequences. However, for optimization purposes, the FOR loop in Rapid-Q doesn't use this mechanism to save on unnecessary instructions. You may notice that your FOR loop is slightly faster than your WHILE or DO loop in Rapid-Q.

FOR .. NEXT Loop
As previously stated, in Rapid-Q this looping structure is optimized, but you may only notice a slight difference. There are some special cases when using a FOR loop in Rapid-Q.
    FOR I(1) = 1 TO 100
    NEXT
This is not valid in Rapid-Q. Why not? Because I(1) is an array, you'll get a compiler error. Only simple types are supported, which means anything BUT arrays. The default increment value is 1, if you want a different increment value, please use STEP:
    FOR I = 1 TO 100 STEP 2
      PRINT I
    NEXT
This will skip all the even numbers, so the output will be: 1 3 5 7 9 ...etc. If for whatever reason you wanted to exit the loop, you can use EXIT FOR.

WHILE .. WEND
If you want to test a condition before entering the loop, you could use a WHILE .. WEND loop. There are no special cases when using this loop, it's exactly like QBasic:
    WHILE I < 100
      I++          '-- Increment I
    WEND
It's much like a DO .. LOOP, except the expression is tested before entering the loop. To exit the WHILE .. WEND loop for whatever reason, you use EXIT WHILE.

DO .. LOOP
A simple DO .. LOOP without any test expression will loop infinitely:
    DO
      PRINT " Hello World! "
    LOOP
To exit the DO .. LOOP, you use EXIT DO. Infinite loops aren't used much in Windows programming (event based anyway). You'll usually want a test expression as in our WHILE .. WEND loop, except we place it differently:
    DO
      I++
    LOOP UNTIL I >= 100
Unlike QBasic or other implementations of BASIC, Rapid-Q does not offer DO WHILE or LOOP WHILE. They're basically useless (ie. they can be implemented in another way), except to provide users with more options. For example, this is valid in QBasic:
   DO
   LOOP WHILE I < 100
Which is equivalent to:
   DO
   LOOP UNTIL I >= 100


Methods

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Methods

Introduction to Methods

There's many definitions of a "method," for lack of a better word, that's what I'm using to describe the methods CONSTRUCTOR, CREATE and WITH. Alone they serve no purpose, but you'll learn what each does, and how to use them here.

CREATE .. END CREATE
Using CREATE is exactly like using DIM
    CREATE Form AS QForm
    END CREATE

    '' or

    DIM Form AS QForm
However, the CREATE method offers more. It can save you typing, and also make your code look cleaner by embedding CREATEs (refer to Chapter 5). Any code you type inbetween the CREATE .. END CREATE method is automatically bound to that object. Since there's no point in regurgitating what was already mentioned, please refer to Chapter 5 for some examples.

WITH .. END WITH
The WITH construct is to provide the developer an easier way to reference properties, methods, and events of certain objects. Basically what it does is save you a lot of typing:
    Form.Caption = "Hello"
    Form.ShowModal

    '' Using WITH

    WITH Form
       .Caption = "Hello"
       .ShowModal
    END WITH
You can also embed WITH .. END WITH statements:
    Something.Another.Caption = "Hello"

    '' Using WITH

    WITH Something
       WITH Another
         .Caption = "Hello"
       END WITH
    END WITH
As you can see, the embedded WITH statement inherits the previous declaration. The period at the front tells the compiler to bind that variable to the WITH declaration. Anything which doesn't start with a period won't be bound, don't worry, decimal numbers won't be bound.

CONSTRUCTOR .. END CONSTRUCTOR
This method is only used inside a TYPE declaration when you're defining your own objects. It will give default values to your properties whenever your component is created (DIMmed).
    TYPE NewObject EXTENDS QObject
      Left AS INTEGER

      CONSTRUCTOR
        Left = 50
      END CONSTRUCTOR
    END TYPE
There's nothing to it, it's much like the CREATE method, except our object in this case is NewObject.


Procedures

Rapid-Q Documentation by William Yu (c)1999 Appendix C: Procedures

Introduction to Procedures

A procedure in BASIC is either a SUB or FUNCTION (or SUBI and FUNCTIONI). It's functionally the same as GOSUB and RETURN but introduces the concept of parameters and return values. Unlike QBasic, a FUNCTION can also be called as a SUB. Meaning you can ignore its return value.

DECLARE SUB
Use DECLARE SUB whenever you want to provide a "forward" declaration without actually writing the SUB yet.
    DECLARE SUB Test

    CALL Test

    SUB Test
      '' Do Stuff
    END SUB
Using CALL to call your subroutine is strictly optional. As you can see, we're providing a forward declaration of the SUB Test. To avoid using DECLARE SUB, you could have written the SUB Test before CALLing it.
    SUB Test
    END SUB

    Test
This way you don't need to use DECLARE SUB. Please note that your parameter names in the DECLARE SUB and your actual SUB declaration MUST MATCH exactly! If you're not sure what I mean, take this for example:
    DECLARE SUB Test (A AS INTEGER, B AS INTEGER)

    SUB Test (X AS INTEGER, Y AS INTEGER)
       PRINT X;" ";Y
    END SUB
Don't change the variable names! This is because when you defined your DECLARE SUB, the parameter names have been fixed as A and B, which also means you can comfortably do this:
    DECLARE SUB Test (A AS INTEGER, B AS INTEGER)

    SUB Test
       PRINT A;" ";B
    END SUB
This is perfectly valid, since you've already declared your subroutine to have an A and B parameter. You don't actually need to define parameters if you already have a forward declaration in place. Obviously this can become confusing so it's not recommended.

Passing variables by reference
There are 2 ways to pass variables by reference. Unlike other BASIC languages, Rapid-Q assumes that all parameters are passed by value unless explicitly specified. To do this explicitly, you can attach a BYREF keyword in front of your parameter list. Here's an example
    SUB StrCat (BYREF Source AS STRING, Text AS STRING)
        Source = Source + Text
    END SUB

    A$ = "Hello"
    StrCat A$, " world!"
    PRINT A$              '-- returns "Hello world!"
Another way is to prepend an '@' symbol in front of the variable:
    SUB StrCat (Source AS STRING, Text AS STRING)
        Source = Source + Text
    END SUB

    A$ = "Hello"
    StrCat @A$, " world!"
    PRINT A$              '-- returns "Hello world!"

FUNCTIONs versus SUBs
The only difference between a FUNCTION and a SUB is that a FUNCTION returns a value.
   FUNCTION Test AS INTEGER
     Test = 123
     Result = 123
   END FUNCTION

   Rval% = Test
Our FUNCTION Test returns an INTEGER, which we can clearly see returns 123. To return a value, you can use the FUNCTION's name or use the keyword Result. Just because you've attached a return value to the FUNCTION, it does not automatically terminate until it reaches your END FUNCTION. So you can really assign as many return values as you like without consequences. The last return value assigned will ultimately be the one bound to your FUNCTION. To exit a FUNCTION or SUB, just use EXIT FUNCTION, or EXIT SUB respectively. One special case in using SUBs or FUNCTIONs in Rapid-Q is that you can only pass at most 10 parameters. QObjects, Arrays, UDTs and Variants are passed by reference, everything else is passed by value. In order for Rapid-Q to recognize that you want to pass a variable by reference, you must attach an @ symbol in front of the variable, or use BYREF in your parameter list. See Chapter 3 section 5 for more information.

SUBI and FUNCTIONI
There's a whole chapter reserved for these two procedure methods. It's not really that complicated, but is very handy to use. They provide the programmer with infinite parameters without type checking. Only simple types like numbers and strings can be passed, no Arrays, UDTs or QObjects. See Chapter 9 for all the details.


Internal Variables

Internal Variables are Read-Only (except SCREEN.CURSOR and SCREEN.CURSORS). When I refer to Unix, I mean Linux & Unix.

Variable | Support | Type | Description
CommandCount | Windows Unix | INTEGER | Number of command line parameters received.
Command$() | Windows Unix | ARRAY | Array of commands received (commands are separated by spaces), first element starting at 1. The zero'th element is your application path/name.
CurDir$ | Windows Unix | STRING | Returns the current working directory of your application
IsConsole | Windows Unix | INTEGER | Returns a non-zero number if application is a console, 0 otherwise.
MouseX | Windows | INTEGER | Returns X Coordinate of Mouse Pointer relative to your active Form.
MouseY | Windows | INTEGER | Returns Y Coordinate of Mouse Pointer relative to your active Form.
NViewLibPresent
(RapidQ2.inc) 		Windows INTEGER IF True then the image library NviewLib.DLL is registered or in the directory. JPG, TGA, and other bitmap formats will be accessed. IF false, BMP format only.
ParamStrCount | Windows Unix | INTEGER | Returns number of String parameters received. This variable is used only inside a SUBI or FUNCTIONI declaration.
ParamStr$() | Windows Unix | ARRAY | Used only inside a SUBI or FUNCTIONI declaration. Returns string parameter value, first element starting at 0.
ParamVal() | Windows Unix | ARRAY | Used only inside a SUBI or FUNCTIONI declaration. Returns numeric parameter value, first element starting at 0.
ParamValCount | Windows Unix | INTEGER | Returns number of Numeric parameters received. This variable is used only inside a SUBI or FUNCTIONI declaration.
For other Screen internal variables and functions see the SCREEN component documentation with RAPIDQ2.INC
Screen.ConsoleX | Windows Unix | INTEGER | Returns maximum column for console screen, useful under Unix.
Screen.ConsoleY | Windows Unix | INTEGER | Returns maximum row for console screen, useful under Unix.
Screen.Cursor | Windows | INTEGER | Change global mouse pointer
Screen.Cursors | Windows | ARRAY of INTEGER | R/W array of cursor handles.
Screen.Height | Windows | INTEGER | Returns Windows screen Height (not to be confused with Form Height)
Screen.MouseX | Windows | INTEGER | Returns X Coordinate of Mouse Pointer relative to your screen.
Screen.MouseY | Windows | INTEGER | Returns Y Coordinate of Mouse Pointer relative to your screen.
Screen.Width | Windows | INTEGER | Returns Windows screen Width
Stack.Int() | Windows Unix | ARRAY | Returns most current stack integer parameter. First element starting at 0.
Stack.Str$() | Windows Unix | ARRAY | Returns most current stack string parameter. First element starting at 0.


Detailed Console Keywords

Most of these have the same functionality as QBasic, so you could just as easily look them up there. Again, when I refer to Unix, I mean Linux & Unix. The following keywords are all encapsulated in the CONSOLE object, so Console.PRINT is the same as PRINT.

CLS CONSOLE Statement Windows/Unix

Clears console screen of all text, and fills the console with the currect background color. CLS also returns the cursor to the home position in the top left corner of the screen.

Syntax: CLS
CLS

Details:
Under Windows, CLS is a CONSOLE statement, under Linux/Unix, CLS is implemented as a system call to clear, so you can safely call CLS without compiling as CONSOLE under Linux/Unix.

COLOR CONSOLE Statement Windows/Unix

Sets the current display colors for the console screen.
  • Foreground is the text color (range = 0-31)
  • Background is the screen color (range = 0-7)
0 = black  4 = red       8 = grey        12 = light red
1 = blue   5 = magenta   9 = light blue  13 = light magenta
2 = green  6 = brown    10 = light green 14 = yellow
3 = cyan   7 = white    11 = light cyan  15 = bright white

Syntax: COLOR [foreground][,background]
COLOR 15
COLOR 10, 3
COLOR ,1
COLOR

CONSOLE.INPUTHANDLE CONSOLE Statement Windows

Returns the console input handle for use in API calls.

Syntax: CONSOLE.INPUTHANDLE
hnd = CONSOLE.INPUTHANDLE

CONSOLE.OUTPUTHANDLE CONSOLE Statement Windows

Returns the console output handle for use in API calls.

Syntax: CONSOLE.OUTPUTHANDLE
hnd = CONSOLE.OUTPUTHANDLE

CSRLIN CONSOLE Function Windows/Unix

Returns the current line (row) position of the cursor.

Syntax: CSRLIN
Row% = CSRLIN

GET$ CONSOLE Function Windows/Unix

This function is mainly used in CGI programs, but can be used as a general purpose read function. It will read the STDIN.

Syntax: GET$(numeric-expression)
A$ = GET$(10)

Details:
GET$ under Linux/Unix is not a console function. To use GET$, compile your application as CONSOLE or CGI under Windows.

INKEY$ CONSOLE Function Windows/Unix

Returns a one- or two-byte string containing a character read from standard input (console). An empty string is returned if no character is waiting there.

Syntax: INKEY$
A$ = INKEY$

Details:
Extended keys start with CHR$(27) and are 2 bytes in length. Extended keys are arrow keys, page up/down, home, end, insert, delete, and F1-F12 keys. You can also trap the shift, ctrl, alt, caps/num/scroll lock keys under Windows.

INPUT CONSOLE Statement Windows/Unix

Reads a whole line of input from the. This statement causes the program to pause and wait for data until a carriage return is pressed.

Syntax: INPUT ["Prompt string"{;|,}] variable
INPUT A$
INPUT "Enter name: "; A$

Details:
INPUT for Rapid-Q is not exactly compatible with QBasic's INPUT. It is more like LINE INPUT. The return variable can be a string or numeric variable. Under Windows, INPUT is implemented as a CONSOLE function. Under Linux/Unix INPUT is not considered a CONSOLE function so there's no need to compile as CONSOLE.

LOCATE CONSOLE Statement Windows/Unix

Moves cursor to specified position.

Syntax: LOCATE [row][,column][,cursor]
LOCATE 10, 1
LOCATE ,10
LOCATE 5
LOCATE 1,,80

Details:
Under Windows you can assume that Row 25 is the last row and Column 80 as the last column. Under Linux/Unix this is dependent on your terminal, but you can use the internal variables Screen.ConsoleX and Screen.ConsoleY to determine the max column and row respectively. The first row and first column always starts at (1,1). The cursor argument is optional, and can take a range of values from 0 to 100 indicating the percentage of the character cell that is filled by the cursor. ie. specifying a value of 0 completely hides the cursor. The default cursor value is 1.

PCOPY CONSOLE Statement Windows

Copies one screen page to another.

Syntax: PCOPY sourcepage, destinationpage
PCOPY 0, 1
PCOPY 1, 5

Details:
The visible (on-screen) page is always 0. There are 7 off-screen pages (1 to 7). You can copy from any page onto any other page.

PEEK CONSOLE Function Windows

Returns the current character/attribute pair stored at a specified location on the console screen.

Syntax: PEEK([#pagenum,] address)
A% = PEEK(2000) '-- Peek location 2000 on current page
A% = PEEK(1, 2000) '-- Peek location 2000 on page 1

Details:
To understand how to compute the address, use this handy function:
   Char$ = CHR$(PEEK((Row%-1)*160+(Col%-1)*2))
   Attr = PEEK((Row%-1)*160+(Col%-1)*2+1)
As you may notice, all the even memory addresses contain the character, and all the odd numbered addresses contain the attribute. The attribute contains information about the foreground and background color.
   ForeGround% = Attr AND &HF
   BackGround% = Attr SHR 4
Why all the trouble? This is implemented for compatibility with QBasic. The only difference is that you don't use DEF SEG under Rapid-Q, and PEEK only works at the console level.

POKE CONSOLE Statement Windows

Writes a byte to the console page.

Syntax: POKE [#pagenum,] address, byte
POKE 2000, ASC("A") '-- Pokes an "A" character at location 2000
POKE 2001, 95 '-- Pokes attribute 95 to location 2000
POKE 1, 2001, 95 '-- Same as above but pokes to page 1

Details:
To understand how to compute the address, use this handy function:
   ChAddress = (Row%-1)*160+(Col%-1)*2
   AttrAddress = (Row%-1)*160+(Col%-1)*2+1
As you may notice, all the even memory addresses contain the character, and all the odd numbered addresses contain the attribute. The attribute contains information about the foreground and background color. To calculate the attribute, try this:
   Attr = (BackGround% SHL 4) OR ForeGround%
Why all the trouble? This is implemented for compatibility with QBasic. The only difference is that you don't use DEF SEG under Rapid-Q, and POKE only works at the console level.

POS CONSOLE Function Windows/Unix

Returns the current horizontal (column) position of the cursor.

Syntax: POS(0)
Column% = POS(0)

Details:
Please note that I did not make this function up (ie. its weird syntax), it's implemented for compatibility with QBasic.

PRINT CONSOLE Statement Windows/Unix

PRINT outputs data to the screen (or standard output).

Syntax: PRINT [#pagenum,][expressions][{;|,}]
PRINT "Number: "; 45
PRINT A$
PRINT #1, "This prints to screen page 1"

Details:
Expressions can be any string, number, or function. You can optionally use ; or , to print out more expressions. Under QBasic, PRINT can format your data if you use the comma, however, under Rapid-Q the comma and semi-colon have the same effect. Again, under Windows, PRINT is implemented as a CONSOLE function. Under Linux/Unix you do not need to compile as CONSOLE.

SCREEN CONSOLE Function Windows

Returns the ASCII character or attribute at (row, col) on the current console screen.

Syntax: SCREEN(row, col [, colorflag])
A% = SCREEN(1, 1) '-- Get character located on the first row and column
A% = SCREEN(5, 3, 1) '-- Get attribute of character located at (5,3)

Details:
The SCREEN function is very similar to the PEEK function, except that it's much easier to use. If you supply the function with a colorflag parameter, the function returns the attribute (ie. color), otherwise it returns the ASCII character. The SCREEN function only works on the current console screen and not on any hidden pages.

SETCONSOLETITLE CONSOLE Statement Windows

SetConsoleTitle is implemented as a WinAPI call to SetConsoleTitle but is called as a statement rather than a function (ie. no return value). If you would like a return value, you'll have to call the API function directly.

Syntax: SETCONSOLETITLE string-expression
SETCONSOLETITLE "Hello World!"

SLEEP CONSOLE Statement Windows/Unix

Suspends execution of the application for a specified amount of time.

Syntax: SLEEP seconds
SLEEP .5 '-- Delay for half a second

Details:
SLEEP requires a parameter, unlike QBasic. SLEEP waits until the number of seconds specified has elasped. You cannot break out of it by pressing a key (unlike QBasic). Under Windows, SLEEP is implemented as a console function. Under Linux/Unix, you do not need to compile as CONSOLE.


Console Keywords

Please note that it's possible to use some Console statements in Linux/Unix even if you compiled your program as GUI. However, this is not possible under Windows. The console statements allowed in Linux/Unix without having to compile as CONSOLE are: CLS, PRINT, and INPUT. SLEEP can also be used without consequences.

Keyword / Support/ Usage /Description

CLS / Windows/Unix

CLS
Clears console screen
COLOR / Windows Unix

COLOR [Fore%][, Back%]
Sets current color attribute, you can ignore either one of the parameters

CONSOLE.INPUTHANDLE / Windows

hnd = CONSOLE.INPUTHANDLE
Returns the console input handle

CONSOLE.OUTPUTHANDLE / Windows

hnd = CONSOLE.OUTPUTHANDLE
Returns the console output handle

CSRLIN / Windows Unix

CurRow% = CSRLIN
Returns current row of cursor

INKEY$ / Windows Unix

A$ = INKEY$
Returns ASCII/Extended key character typed

INPUT / Windows Unix

INPUT A$
Reads a full line of input from user

LOCATE / Windows Unix

LOCATE [Y%][, X%][, cursor]
Moves cursor to Y%, X% (upper left starts at 1,1). You can ignore either one of the parameters

PCOPY / Windows

PCOPY source, dest
Copy page from source to dest. The visible page is 0. There are 7 off screen pages.

PEEK / Windows
A% = PEEK([#PageNum,] address)
Returns the char/attribute value at address

POKE / Windows

POKE [#PageNum,] address, byte
Poke attribute or char at address

POS(0) / Windows Unix

CurPos% = POS(0)
Returns current position of cursor

PRINT / Windows Unix

PRINT [#PageNum[;|,]][stuff][;|,][...]
Write to standard output (console). To write to the offscreen buffers, use #PageNum. Where PageNum is 1-7. Only works under Windows.

SCREEN / Windows

A% = SCREEN(row, col [, colorflag])
Returns the chararacter or attribute value at (row,col)

SETCONSOLETITLE / Windows

SetConsoleTitle(Title$)
Set console title

SLEEP / Windows Unix

SLEEP n
Delay for n seconds, which can be a fraction


Reserved Keywords

Most of these have the same functionality as QBasic, so you could just as easily look them up there. Again, when I refer to Unix, I mean Linux & Unix.

Keyword Support Usage/Description
ABS Windows Unix ABS(NumericExpression)
Return absolute value of number
ACOS Windows Unix ACOS(NumericExpression)
Returns arccosine of NumericExpression
ASC Windows Unix ASC(Char$)
Returns the ASCII key value of Char$
ASIN Windows Unix ASIN(NumericExpression)
Returns arcsine of NumericExpression
ATN Windows Unix ATN(NumericExpression)
Returns arctangent of NumericExpression
BIN$ Windows Unix BIN$(Integer-Number)
Returns the binary representation of the Number (must be a positive integer).
BIND Windows Unix BIND Num TO MyFunc
BIND a function pointer
CALLBACK/CODEPTR Windows CODEPTR(MySUB)
Returns the absolute address of the SUB/FUNCTION
CALLFUNC Windows Unix CALLFUNC(Num, Param1, Param2, ...)
Call function pointer
CEIL Windows Unix CEIL(NumericExpression)
Rounds a numeric expression up towards positive infinity.
CHDIR Windows Unix CHDIR Path$
Change directory
CHR$ Windows Unix CHR$(Byte)
Returns character corresponding to the ascii key value
CINT Windows Unix CINT(NumericExpression)
Implemented for compatibility reasons. Use ROUND instead.
CLNG Windows Unix CLNG(NumericExpression)
Implemented for compatibility reasons. Use ROUND instead.
CONST Windows Unix CONST Variable = Expression
Assigns Variable a constant value
CONVBASE$ Windows Unix CONVBASE$(Str$, FromBase, ToBase)
Returns the representation Str$ FromBase to ToBase representation.
COS Windows Unix COS(NumericExpression)
Returns cosine of an angle given in radians
DATA Windows Unix DATA constant|EXECUTE(...) [, constant|EXECUTE(...), ...]
Stores data for easy retrieval, use READ to read the data.
DATE$ Windows Unix DATE$
Returns the current Date in MM-DD-YYYY format.
DEC Windows Unix DEC(Variable [, DecVal])
Decrements variable by 1 unless otherwise specified
DEF... Windows Unix DEF(...) Variable
See details for more information on this statement
DELETE$ Windows Unix DELETE$(S$, Index, Count)
Deletes Count number of characters from S$ starting at Index
DIM Windows Unix DIM Variable AS DataType
Creates variable of type DataType
DIR$ Windows DIR$[(FileSpec$, Attributes%)]
Returns the next file of FileSpec$
DIREXISTS Windows DIREXISTS(Path$)
Returns 0 if directory does not exist, non-zero otherwise
DOEVENTS Windows DOEVENTS
Polls events, useful when you're in a deep/big loop
END Windows Unix END
Terminates program
EXP Windows Unix EXP(NumericExpression)
Calculates the exponential function (e raised to the power of NumericExpression)
ENVIRON Windows Unix ENVIRON StringExpression
Set environment string
ENVIRON$ Windows Unix ENVIRON$(environment-string)
Get environment value
EXTRACTRESOURCE Windows Unix EXTRACTRESOURCE ResourceNumber%, FileName$
Extracts a resource to file
FIELD$ Windows Unix FIELD$(StringExpresion, Deliminator, FieldNumber)
Returns a field/token separated by deliminators.
FILEEXISTS Windows Unix FILEEXISTS(FileName$)
Returns 0 if file not found, non-zero otherwise
FIX Windows Unix FIX(NumericExpression)
Truncates fractional number, rounding down towards 0.
FLOOR Windows Unix FLOOR(NumericExpression)
Rounds a numeric expression down towards negative infinity.
FORMAT$ Windows Unix FORMAT$(S$, arg1, arg2, ...)
Returns a formatted string assembled from a format string and a series of arguments (up to 50)
FRAC Windows Unix FRAC(NumericExpression)
Returns the fractional part of the numeric expression.
HEX$ Windows Unix HEX$(NumericExpression)
Returns the HEXidecimal string representation of the NumericExpression
INC Windows Unix INC(Variable [, IncVal])
Increments variable by 1 unless otherwise specified
INITARRAY Windows Unix INITARRAY(Array, values, ...)
Initializes array with corresponding values
INP Windows Unix INP(Address)
Returns the byte value read from an I/O port 0..65535
INPW Windows Unix INPW(Address)
Returns the word value read from an I/O port 0..65535
INSERT$ Windows Unix INSERT$(Source$, S$, Index)
Insert Source$ string to string S$ at Index
INSTR Windows Unix INSTR([Start,] SearchString, FindString)
Function returns the position in the SearchString that FindString was found, 0 otherwise
INT Windows Unix INT(NumericExpression)
Convert NumericExpression to a 32-bit INTEGER, truncating decimals.
KILL Windows Unix KILL Filename$
Deletes file
KILLMESSAGE Windows KILLMESSAGE hWnd, Message
Removes message from queue
LBOUND Windows Unix LBOUND(ArrayName[, Dimension])
Returns the lowerbound of an array (Dimension starts at 1)
LCASE$ Windows Unix LCASE$(StringExpression)
StringExpression is lowercased
LEFT$ Windows Unix LEFT$(StringExpression, N)
Returns the leftmost N characters of a string
LEN Windows Unix LEN(StringExpression)
Returns the length of string
LFLUSH Windows LFLUSH
Calling this will start printing your document. Make sure all your LPRINTs are executed before calling LFLUSH.
LIBRARYINST Windows LIBRARYINST(DLLName)
Returns the handle to a loaded DLL module
LOG Windows Unix LOG(NumericExpression)
Returns the natural logarithm of NumericExpression
LPRINT Windows LPRINT [Expression][;|,][...]
LPRINT acts exactly like PRINT, except all output is directed to the default printer. Make sure to call LFLUSH. Also see the Printer component for graphical printing.
LTRIM$ Windows Unix LTRIM$(StringExpression)
Returns string with left padded spaces removed
MEMCMP Windows Unix MEMCMP(ptr1, ptr2, count)
Compares 2 memory addresses, returns 0 if not equal, non-zero otherwise.
MEMCPY Windows Unix MEMCPY(destination, source, count)
Copies count bytes of source memory address to destination memory address.
MEMSET Windows Unix MEMSET(source, char, n)
Initializes a source memory block with n bytes of char.
MESSAGEBOX Windows MESSAGEBOX(Msg$, Title$, MsgButtons%)
Displays a simple message box with prompts
MESSAGEDLG Windows MESSAGEDLG(Msg$, MsgType, MsgButtons, HelpContext)
Displays a message dialog box, see RAPIDQ.INC for proper types & buttons
MID$ Windows Unix MID$(StringExpression, I, N)
Returns string with characters from I to N of StringExpression
MKDIR Windows Unix MKDIR Dir$
Creates new directory
OUT Windows Unix OUT(Address, bytevalue)
Sends a byte value to a machine I/O port 0..65535
OUTW Windows Unix OUTW(Address, wordvalue)
Sends a word value to a machine I/O port 0..65535
PLAYWAV Windows PLAYWAV FileName$|Resource_Handle, SndOption
Plays a WAV file, see RAPIDQ.INC for sndOptions
POSTMESSAGE Windows POSTMESSAGE(Handle, uMsg, wParam, lParam)
Post message to handle, and does not block. Refer to your favourite WinAPI guide for the proper message numbers
QUICKSORT Windows QUICKSORT(Array-begin, Array-end, ASCEND | DESCEND)
Sort any array, BYTE, WORD, SHORT, STRING, etc...
RANDOMIZE Windows Unix RANDOMIZE [Num]
Use randomize to reseed the random number generator
READ Windows Unix READ variable [, variable, ...]
Reads next DATA statement, stores it in variable.
REDIM Windows Unix REDIM Array(1000) AS INTEGER
Use REDIM to redimension an array preserving existing data. REDIM is equivalent to DIM if the array has not yet been allocated.
RENAME Windows Unix RENAME File1$, File2$
Renames File1$ to File2$
REPLACE$ Windows Unix REPLACE$(S$, R$, Index)
Replaces a string from S$ with R$ starting at Index
REPLACESUBSTR$ Windows Unix REPLACESUBSTR$(Source$, ReplaceStr$, Withstr$)
Replaces the string ReplaceStr$ in Source$ with WithStr$
RESTORE Windows Unix RESTORE [linelabel]
Jumps to specific position in DATA statement.
RESOURCE Windows Unix RESOURCE(number%)
Get numeric value of Resource, mainly for use with ExtractResource, 0 based array.
RESOURCECOUNT Windows Unix RESOURCECOUNT
Get resource count.
REVERSE$ Windows Unix REVERSE$(S$)
Reverses a string
RGB Windows Unix RGB(Red%, Green%, Blue%)
Returns the BGR numeric representation of the color.
RIGHT$ Windows Unix RIGHT$(StringExpression, N)
Returns the righttmost N characters of a string
RINSTR Windows Unix RINSTR([Start,] SearchString, FindString)
Reverse INSTR Function, searching starts from the end of SearchString
RMDIR Windows Unix RMDIR Dir$
Removes directory
RND Windows Unix RND(UpperBound)
Returns a random number, if no upperbound is given, it returns a decimal number. Use RANDOMIZE to reseed.
ROUND Windows Unix ROUND(NumericExpression)
Rounds number to nearest integer.
RTRIM$ Windows Unix RTRIM$(StringExpression)
Returns string with rightmost padded spaces removed
RUN Windows Unix RUN command$
Executes command, but does not block
SENDMESSAGE Windows SENDMESSAGE(Handle, uMsg, wParam, lParam)
Post message to handle, and blocks. Refer to your favourite WinAPI guide for the proper message numbers
SGN Windows Unix SGN(NumericExpression)
Returns the sign of a numeric expression
SHELL Windows Unix SHELL command$
Executes command, and blocks until finished
SHOWMESSAGE Windows Unix SHOWMESSAGE msg$
Popups message in a simple box
SIN Windows Unix SIN(NumericExpression)
Returns sine of an angle given in radians
SOUND Windows SOUND freq, duration
Outputs sound through PC Speaker
SPACE$ Windows Unix SPACE$(Num)
Returns string with Num spaces
SQR Windows Unix SQR(NumericExpression)
Returns the square root of NumericExpression, make sure it's non-negative
STATIC Windows Unix STATIC Variable AS DataType
Creates variable of type DataType and preserves variable between procedure calls
STR$ Windows Unix STR$(NumericExpression)
Returns the string representation of the numeric expression
STRF$ Windows STRF$(NumericExpression, Format%, Precision%, Digits%)
Converts a floating point or number value to a string
STRING$ Windows Unix STRING$(m, n) or STRING$(m, StringExpression)
Returns a string m characters wide that only contains CHR$(n) character
SWAP Windows Unix SWAP A, B
Exchanges values, so A = B and B = A
TALLY Windows Unix TALLY(SearchString, MatchString)
Returns the number of occurrences of matchstring
TAN Windows Unix TAN(NumericExpression)
Returns tangent of an angle given in radians
TIME$ Windows Unix TIME$
Returns the current time in HH:MM:SS format.
TIMER Windows Unix T! = TIMER
Returns the current TIMER value
UBOUND Windows Unix UBOUND(ArrayName[, Dimension])
Returns the upperbound of array (Dimension starts at 1)
UCASE$ Windows Unix UCASE$(StringExpression)
Returns a string whose characters have been uppercased
UNLOADLIBRARY Windows UNLOADLIBRARY(DLLName)
Removes DLL from memory
VAL Windows Unix VAL(StringExpression)
Returns the closest numeric representation of the string expression
VARPTR Windows Unix VARPTR(variablename)
Returns the address of a variable.
VARPTR$ Windows Unix VARPTR$(address)
Returns the null-terminated string representation of a given address.
VARTYPE Windows Unix VARTYPE(variant)
Returns the type of a variant 0 - Integer, 1 - Float, 2 - String.


Other Detailed Keywords

Most of these have the same functionality as QBasic, so you could just as easily look them up there. Again, when I refer to Unix, I mean Linux & Unix.

ABS | MATH Function | Windows/Unix
A math function that returns the absolute value of a numeric expression.

Syntax: ABS(numeric-expression)
A% = ABS(-123)

Details:
The absolute value of function returns the unsigned magnitude of its argument. So, ABS(-1) and ABS(1) are both 1.

ACOS | MATH Function | Windows/Unix
A math function that returns the arccosine of a numeric expression.

Syntax: ACOS(numeric-expression)
D# = ACOS(0.55)

Details:
Numeric-expression is in the range -1 to 1.

ASC | STRING Function | Windows/Unix
A string processing function that returns a numeric value that is the ASCII code for the first character in a string expression.

Syntax: ASC(string-expression)
A% = ASC("A")

ASIN | MATH Function | Windows/Unix
A math function that returns the arcsine of a numeric expression.

Syntax: ASIN(numeric-expression)
D# = ASIN(0.55)

Details:
Numeric-expression is in the range -1 to 1.

ATN/ATAN | MATH Function | Windows/Unix
A math function that returns the arctangent of a numeric expression.

Syntax: ATN(numeric-expression)
D# = ATN(0.9)

Details:
Numeric-expression is the angle expressed in radians.

BIN$ | CONVERSION Function | Windows/Unix
A binary conversion function which will convert any positive INTEGER number to its binary representation.

Syntax: BIN$(numeric-expression)
S$ = BIN$(123)

Details:
Negative numbers are not supported, and so results are not defined.

BIND | POINTER Function | Windows/Unix
BIND will bind a variable as a function pointer.

Syntax: BIND variable TO function
DECLARE SUB MyFunc(X AS INTEGER)
BIND A% TO MyFunc

Details:
To invoke this function pointer, use CALLFUNC. Cannot be set to a a virtual Sub/Function address like a virtual table in C/C++.

CALLBACK/CODEPTR | ADDRESS Function | Windows
CODEPTR (or CALLBACK) will return the absolute address of a SUB or FUNCTION.

Syntax: CODEPTR(MySUB)
SUB MySUB
END SUB
A& = CODEPTR(MySUB)

Details:
Use this function for CALLBACK routines. Not all cases are implemented, results may vary depending on the CALLBACK and the type of parameters it receives. Cannot be set to a a virtual Sub/Function address like a virtual table in C/C++.

CALLFUNC | POINTER Function | Windows/Unix
CALLFUNC will execute the function pointer that was bound by using BIND.

Syntax: CALLFUNC(fptr, param1, param2, ...)
CALLFUNC(FPtr, 10, 20)
PRINT CALLFUNC(FPtr2, 10, 20)

Details:
Depending on how you BIND your function pointer, you can either call CALLFUNC as a statement or a function. Make sure to supply the necessary number of parameters, else you will receive a compile error. Passing function pointers as parameters is not yet implemented, but you can read up on Chapter 11 to see how to emulate this.

CEIL | MATH Function | Windows/Unix
A math function that rounds a numeric expression up toward positive infinity.

Syntax: CEIL(numeric-expression)
A% = CEIL(66.2) '-- Returns 67

CHDIR | SYSTEM Statement | Windows/Unix
CHDIR will change the current working directory for your application.

Syntax: CHDIR string-expression
CHDIR "c:\windows"

CHR$ | STRING Function | Windows/Unix
A string processing function that returns a one-character string whose ASCII code is the argument.

Syntax: CHR$(numeric-expression)
A$ = CHR$(66)

Details:
Numeric-expression should be in the range 0-255.

CINT | CONVERSION Function | Windows/Unix
A conversion function that converts a numeric expression to an integer by rounding the fractional part of the expression.

Syntax: CINT(numeric-expression)
A% = CINT(66.7)

Details:
Implemented for compatibility with QBasic, you can use the more logical function, ROUND, instead.

CLNG | CONVERSION Function | Windows/Unix
A conversion function that converts a numeric expression to an integer by rounding the fractional part of the expression.

Syntax: CLNG(numeric-expression)
A% = CLNG(66.7) '-- equals 67

Details:
Implemented for compatibility with QBasic, you can use the more logical function, ROUND, instead.

CONST | Statement | Windows/Unix
A non-executable statement that declares symbolic constants to use in place of numeric or string values.

Syntax: CONST constantname [ as Datatype ]= expression
CONST False = 0
CONST True AS LONG = NOT False
CONST A$ = "Hi world!"
CONST Char = CHR$(66)
CONST Combine = A$ + Char

Details:
Expression can be any value, numeric or string. Rapid-Q will decipher what the constant value will be bound to (ie. a string or a numeric variable) if the constantname is not followed by a type-declaration character (%. &, !, #, $, etc...).

CONVBASE$ | CONVERSION Function | Windows/Unix
A conversion function which takes the string expression represented in a specified base to be converted to another specified base determined by the arguments passed.

Syntax: CONVBASE$(string-expression, frombase, tobase)
S$ = CONVBASE$("FFD", 16, 2) '-- Convert from base 16 to 2
S$ = CONVBASE$("287", 10, 16) '-- Convert from base 10 to 16

Details:
Negative numbers are not supported. All Strings should be in UPPERCASE otherwise errors will result.
Also an exception Fault occurs for "FFFFFFFF" i.e.,
PRINT "Long: "+CONVBASE$("FFFFFFFF", 16, 10)

COS | MATH Function | Windows/Unix
A math function that returns the cosine of an angle given in radians.

Syntax: COS(numeric-expression)
PI = 3.14153
C# = COS(PI)

Details:
Numeric-expression is the angle expressed in radians.

DATA | Statement | Windows/Unix
A non-executable statement that stores the numeric and string constants used by a program's READ statements.

Syntax: DATA {constant|EXECUTE(...)}[,...]
DATA my dog ate my homework, "oh, boy!", 34.4
DATA EXECUTE(LEFT$("Hello", 2, 3))

Details:
Constant is any valid numeric or string constant. If a string constant contains commas, colons, or leading or trailing spaces you want to preserve in your program, you must enclose the string in double quotes. You can also execute code by using the EXECUTE keyword. The return value of this executed code will be the value returned to your READ statement.

DATE$ | SYSTEM Function | Windows/Unix
A function that returns a string containing the current date formatted as MM-DD-YYYY. Where MM = month (1-12), DD = day (1-31) and YY = year (1980-2099)

Syntax: DATE$
PRINT DATE$

Details:
Unlike QBasic where you can set the current date using the DATE$ statement, you cannot do this under Rapid-Q.

DEC | Statement | Windows/Unix
Decrements numeric variable by one, or by the amount specified.

Syntax: DEC(variable [, amount])
DEC(I)
DEC(I, 10)

Details:
You can also use the minus minus C-like statement :
DIM i as INTEGER
i = 5
i--
PRINT i

DEF... | Statement | Windows/Unix
DEFBYTE, DEFDBL, DEFDWORD, DEFINT, DEFLNG, DEFSHORT, DEFSNG, DEFSTR, DEFWORD are declaration statement that names one or more variables and allocates storage space for them.

Syntax: DEFINT variable[(subscripts)] [, ...]
DEFSTR A, B, C="Hello", D, E
DEFINT I=99, J(100,10), K

Details:
You cannot specify a range of variables, for example: DEFINT A-Z works fine under QBasic, but not Rapid-Q. You can initialize each variable as demonstrated above. DEF... statements are equivalent to calling DIM, but can save you a lot of typing. To initialize an array, wrap the values around curly braces {...}. For Example,
DEFINT A(1 TO 10) = {1,2,3,4,5,6,7,8,9,10}
Initializes elements 1 through 10 with the values 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10 respectively.

DELETE$ | STRING Function | Windows/Unix
A function that deletes part of a string.

Syntax: DELETE$(string-expression, start, length)
A$ = DELETE$("Hello world", 2, 3) '-- Result: Ho world

DIM | Statement | Windows/Unix
Declaration statement that names one or more variables and allocates storage space for them. There is no checking for limits on arrays. You can "read" an array value outside that used in DIM, giving unpredictable results. Always keep track of your array start and end instead of LBOUND and UBOUND for the best results.

Syntax: DIM variable[(subscripts)] AS type
DIM A AS INTEGER, B(2,5,3,9,2) AS INTEGER
DIM S AS STRING
DIM Form AS QFORM

Details:
Use the optional (subscripts) to declare the size of arrays, up to 5 dimensions. Here are some rules to remember:
OK:
DIM a AS INTEGER, b AS INTEGER, c AS INTEGER
NOT RECOGNIZED CORRECTLY:
DIM a, b, c AS INTEGER
(In this case, a and b will be VARIANTs, and only c is INTEGER)

OK:
DIM (a, b, c) AS INTEGER
NOT RECOGNIZED CORRECTLY:
DIM (a = 1, b = 2) AS INTEGER ' error!
(try this instead if you want to write your code compactly)
DIM a AS INTEGER = 1, b AS INTEGER = 2

Also, you cannot have one of the variables be an array, while others aren't:
 DIM (a, b(5), c) AS INTEGER ' incorrect!
DIM (a, b, c)(5) AS INTEGER ' correct: a, b and c are arrays

DIR$ | SYSTEM Function | Windows
A system function used to obtain the first/next file corresponding to a specified filespec.

Syntax: DIR$[(file-spec, attribute)]
FileName$ = DIR$("*.*", 0) '-- Get first file
FileName$ = DIR$ '-- Get next file

Details:
File-spec specifies a filename or path (which can include wildcards characters). Calling DIR$ with no parameters return additional filename matches. If no matches exist (or all matches have been exhausted), DIR$ returns an empty string. DIR$ returns all regular files as well as any special files specified in the attribute parameter.
Here are some valid file attributes, you can combine
them by using OR (ie. faReadOnly OR faDirectory)

&H1 = faReadOnly       &H8 = faVolumeID
&H2 = faHidden        &H10 = faDirectory
&H4 = faSysFile       &H20 = faArchive
                      &H3F = faAnyFile
To obtain additional information on the currently matched file, use the FileRec properties.
FileRec.FileName    - Returns Windows long file name
FileRec.ShortName   - Returns the short file name
FileRec.Date        - Returns the file date as a string
FileRec.Time        - Returns the file time as a string
FileRec.Size        - Returns the file size
FileRec.FileTime    - Returns the file time as an integer
You can use FileRec.FileTime to compare file times. So a newer file will have a FileTime greater than an older file.

DIREXISTS | SYSTEM Function | Windows
A function that returns 0 if directory does not exist, non-zero otherwise.

Syntax: DIREXISTS(string-expression)
A = DIREXISTS("c:\windows")

DOEVENTS | RAPID-Q Specific | Windows
Returns control to the operating system to process the events in its queue, and returns back control to the program once done.

Syntax: DOEVENTS
DO
DOEVENTS
LOOP

Details:
DoEvents should normally be used for long-running processes (ie. long loops or anything else that eats up the CPU), so that the user can abort the process if necessary. DoEvents can also be used to handle multiple forms.

END | Statement | Windows/Unix
Terminates your program.

Syntax: END
END

Details:
Call END to terminate your application, but if there are any Windows still opened, you should close them first. In some cases you may have to use Application.Terminate instead if you get an error with END

ENVIRON | SYSTEM Statement | Windows/Unix
A statement used to set or modify an environment variable.

Syntax: ENVIRON string-expression
ENVIRON "PATH=c:\windows"
ENVIRON "TEST what"

Details:
String-expression must have the form
parametername=text
or
parametername text
Everything to the left of the equal sign or space is assumed to be a parameter, and everything to the right, text. If the parametername has not previously existed in the environment string table, it is appended to the end of the table. If a pametername already exists, it gets deleted and the new parametername is appended to the end of the table.

ENVIRON$ | SYSTEM Function | Windows/Unix
A function that returns an environment string.

Syntax: ENVIRON$(environment-string)
A$ = ENVIRON$("PATH")

Details:
It is not possible, at this time, to retrieve an environment string by its index.

EXP | MATH Function | Windows/Unix
A math function that returns the exponential function (e raised to the power of n).

Syntax: EXP(numeric-expression)
A# = EXP(1)

EXTRACTRESOURCE | RESOURCE Statement | Windows/Unix
A statement that extracts a resource, from the current program, to a file.

Syntax: EXTRACTRESOURCE resource-value, filename
EXTRACTRESOURCE Resource(0), "test.bmp"

Details:
The resource-value is the absolute position of the resource within the current program. To find the absolute position of the resource, see also RESOURCE(), and RESOURCECOUNT.

FIELD$ | STRING Function | Windows/Unix
A function that returns a field (or token) separated by deliminators.

Syntax: FIELD$(Source-string, deliminator-string, field-number)
A$ = FIELD$("John&Doe&555-1234", "&", 2) '-- Returns Doe
A$ = FIELD$("John&&Doe&&555-1234", "&&", 3) '-- Returns 555-1234

FILEEXISTS | SYSTEM Function | Windows/Unix
A function that returns 0 if file does not exist, non-zero otherwise. The current working directory is searched for the file if no path is specified.

Syntax: FILEEXISTS(string-expression)
A = FILEEXISTS("rapidq.exe")

FIX | MATH Function | Windows/Unix
A function that removes the fractional part of a number.

Syntax: FIX(numeric-expression)
A% = FIX(342.97)

FLOOR | MATH Function | Windows/Unix
A math function that rounds a numeric expression down toward negative infinity.

Syntax: FLOOR(numeric-expression)
A% = FLOOR(66.7) '-- Returns 66

FORMAT$ | STRING Function | Windows/Unix
A function that returns a formatted string assembled from a Pascal style format string and a series of arguments. The Pascal style format string closely resembles C style format strings, but definitely not VB compatible.

Syntax: FORMAT$(Format-string, arg1, arg2, ...)
A$ = FORMAT$("Location: %s %4d %-10.4g", "Any", 1234, 55.39) '-- Returns Location: Any 1234 55.39
Details:
Format strings passed to the string formatting routines contain two types of objects--plain characters and format specifiers. Plain characters are copied verbatim to the resulting string. Format specifiers fetch arguments from the argument list and apply formatting to them. Format specifiers have the following form:
"%" [index ":"] ["-"] [width] ["." prec] type
A format specifier begins with a % character. After the % come the following, in this order:
An optional argument index specifier, [index ":"]
An optional left justification indicator, ["-"]
An optional width specifier, [width]
An optional precision specifier, ["." prec]
The conversion type character, type
The following table summarizes the possible values for type:
d | Decimal. The argument should be an integer value. The value is converted to a string of decimal digits. If the format string contains a precision specifier, it indicates that the resulting string must contain at least the specified number of digits; if the value has less digits, the resulting string is left-padded with zeros.
e | Scientific. The argument should be a floating-point value. The value is converted to a string of the form "-d.ddd...E+ddd". The resulting string starts with a minus sign if the number is negative. One digit always precedes the decimal point. The total number of digits in the resulting string (including the one before the decimal point) is given by the precision specifier in the format string--a default precision of 15 is assumed if no precision specifier is present. The "E" exponent character in the resulting string is always followed by a plus or minus sign and at least three digits.
f | Fixed. The argument should be a floating-point value. The value is converted to a string of the form "-ddd.ddd...". The resulting string starts with a minus sign if the number is negative. The number of digits after the decimal point is given by the precision specifier in the format string--a default of 2 decimal digits is assumed if no precision specifier is present.
g | General. The argument should be a floating-point value. The value is converted to the shortest possible decimal string using fixed or scientific format. The number of significant digits in the resulting string is given by the precision specifier in the format string--a default precision of 15 is assumed if no precision specifier is present. Trailing zeros are removed from the resulting string, and a decimal point appears only if necessary. The resulting string uses fixed point format if the number of digits to the left of the decimal point in the value is less than or equal to the specified precision, and if the value is greater than or equal to 0.00001. Otherwise the resulting string uses scientific format.
n | Number. The argument should be a floating-point value. The value is converted to a string of the form "-d,ddd,ddd.ddd...". The "n" format corresponds to the "f" format, except that the resulting string contains thousand separators.
m | Money. The argument should be a floating-point value. The value is converted to a string that represents a currency amount.
s | String. The argument must be a string. The string or character is inserted in place of the format specifier. The precision specifier, if present in the format string, specifies the maximum length of the resulting string. If the argument is a string that is longer than this maximum, the string is truncated.
x | Hexadecimal. The argument should be an integer value. The value is converted to a string of hexadecimal digits. If the format string contains a precision specifier, it indicates that the resulting string must contain at least the specified number of digits; if the value has fewer digits, the resulting string is left-padded with zeros.

Conversion characters may be specified in uppercase as well as in lowercase--both produce the same results.
An index specifier sets the current argument list index to the specified value. The index of the first argument in the argument list is 0. Using index specifiers, it is possible to format the same argument multiple times. For example Format$("%d %d %0:d %d", 10, 20) produces the string "10 20 10 20".

FRAC | MATH Function | Windows/Unix
A function that returns the fractional part of a number.

Syntax: FRAC(numeric-expression)
A# = FRAC(342.97)

GETCAPTURE | RAPID-Q Specific | Windows
Windows API that retrieves the handle of the window (if any) that has captured the mouse. Only one window at a time can capture the mouse; this window receives mouse input whether or not the cursor is within its borders. This is a keyword in RAPIDQ2.INC

Syntax: Handle = GETCAPTURE
DIM theHandle AS LONG
theHandle = GETCAPTURE
IF theHandle = Canvas.Handle THEN SHOWMESSAGE "Button is inside picture"

Details:
A value of 0 means the current program has not captured the mouse. Use the RELEASECAPTURE function to releases the mouse capture from a window in the current program and restore normal mouse input processing. A window that has captured the mouse receives all mouse input, regardless of the position of the cursor, except when a mouse button is clicked while the cursor hot spot is in the window of another thread.

GETFOCUS | RAPID-Q Specific | Windows
A WinAPI call that gets the handle to the control that recieves the keyboard output. This is a keyword in RAPIDQ2.INC

Syntax: GETFOCUS(hWnd)
GETFOCUS (Button.Handle)

Details:
You can set which control gets the focus with SETFOCUS.

HEX$ | CONVERSION Function | Windows/Unix
A function that returns the hexidecimal (base 16) representation of the (base 10) numeric expression.

Syntax: HEX$(numeric-expression)
A$ = HEX$(123)

Details:
Negative numbers are supported. In the Windows version, the string is pre-padded with 0's to fit the string length of 8.

HEXTOINC | CONVERSION Function | Windows/Unix
A function that returns a LONG integer from a string of a hexidecimal (base 16) number. Use this to convert HEX$ to a LONG integer (base 10). This function is only included in the RAPIDQ2.INC file.

Syntax: HexToInc(HexNum$)
DIM A AS LONG
A = HexToInc(HEX$(123))

Details:
A signed negative number will be returned.

IIF | Function | Windows/Unix
The immediate IF function returns one of two parts depending on the evaluation of an expression. Notice that both parts are evaluated, whether the expression returned true or false, so watch for undesirable side effects.

Syntax: IIF(expression, true-expr, false-expr)
A$ = IIF(6 > 5, "TRUE", "FALSE") '-- returns TRUE

INC | Statement | Windows/Unix
Increments numeric variable by one, or by the amount specified.

Syntax: INC(variable [, amount])
INC(I)
INC(I, 10)

Details:
You can also use the plus plus C-like statement :
DIM i as INTEGER
i = 5
i++
PRINT i

INITARRAY | ARRAY Statement | Windows/Unix
Initializes an array with the corresponding values. (POSSIBLE BUG, use MEMSET instead)

Syntax: INITARRAY(Array, value [, ...])
DIM A(1 TO 100) AS INTEGER
INITARRAY(A, 55, 234, 45, 99)

Details:
Equivalently:
DEFINT A(1 TO 100) = {55, 234, 45, 99}

Initializing arrays as opposed to looping through each one saves a bit of time.

INP | I/O Function | Windows/Unix
A device I/O function that returns the byte value read from an I/O port.

Syntax: INP(port)
A% = INP(&H3C9)

Details:
Port is any word value between 0 and 65535. Return value is in the range 0 to 255. This keyword is stable for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, try utilities like PorkTalk or io.dll instead.

INPW | I/O Function | Windows/Unix
A device I/O function that returns the word value read from an I/O port.

Syntax: INPW(port)
A = INPW(&H3C9)

Details:
Port is any word value between 0 and 65535. Return value is also in the range 0 to 65535. This keyword is stable for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, try utilities like PorkTalk or io.dll instead.

INSERT$ | STRING Function | Windows/Unix
A function that returns a string with an inserted substring beginning at a specified index.

Syntax: INSERT$(insert-string, source-string, index-number)
A$ = INSERT$("hi", "Hello", 3) '-- returns Hehillo

INSTR | STRING Function | Windows/Unix
A function that compares 2 strings and returns the position of the find-string with respect to the search-string. If found, INSTR returns the index position of the find-string, 0 otherwise.

Syntax: INSTR([start,] search-string, find-string)
A% = INSTR("Hello", "ll") '-- returns 3
A% = INSTR(4, "hehe they", "he") '-- returns 7

INT | MATH Function | Windows/Unix
A function that returns the largest integer less than or equal to a numeric-expression. Fractional part is truncated.

Syntax: INT(numeric-expression)
A& = INT(342.97)

KILL | SYSTEM Statement | Windows/Unix
A statement that removes a disk file.

Syntax: KILL filespec
KILL "mydocuments.txt"
KILL "*.c"

KILLMESSAGE | RAPID-Q Specific | Windows
A statement that removes a message from the queue.

Syntax: KILLMESSAGE hWnd, Message
KILLMESSAGE form.handle, WM_CHAR

Details:
Ideally, KillMessage should be used inside an event, such as OnKeyDown, to remove any messages you don't want processed further.

LBOUND | ARRAY Function | Windows/Unix
A function that returns the lower bound of the array.

Syntax: LBOUND(arrayname [,dimension])
DIM A(-50 TO 100) AS INTEGER
L% = LBOUND(A) '-- Returns -50

Details:
If the array has multiple dimensions, you can use the optional dimension argument to check the lower bound of each one. You might find this keyword unreliable in a SUB/FUNCTION. Just in case you should always keep track of the lower and upper bounds of an array since RapidQ does not check to see if you reference an array out of bounds!

LCASE$ | STRING Function | Windows/Unix
A string function that returns a string expression with all letters lower-case.

Syntax: LCASE$(string-expression)
A$ = LCASE$("HELLO") '-- returns hello

LEFT$ | STRING Function | Windows/Unix
A string function that returns a string consisting of the leftmost n characters of a string.

Syntax: LEFT$(string-expression, n)
A$ = LEFT$("Hello",2) '-- returns he

LEN | STRING Function | Windows/Unix
A function that returns the number of characters in a string.

Syntax: LEN(string-expression)
A% = LEN("HELLO") '-- returns 5

Details:
LEN will not return the number of bytes required by a variable. This option is available under QBasic.

LFLUSH | PRINTER Statement | Windows
A statement used to begin a print job.

Syntax: LFLUSH
LPRINT "print this line"
LFLUSH '-- call this to start printing

Details:
You should call LFLUSH after you're satisfied that you want to start printing. If you don't call LFLUSH, then whenever your application terminates is when your document will start its print job.

LIBRARYINST | DLL Function | Windows
Returns the handle to the DLL module. If the DLL hasn't been loaded yet or is not found, this function returns 0.

Syntax: LIBRARYINST(DLLName)
DECLARE FUNCTION UpdateWindow LIB "USER32" ALIAS _
"UpdateWindow" (hWnd AS LONG) AS LONG
UpdateWindow(0) '-- Using function will load DLL
hInst& = LIBRARYINST("USER32")

Details:
Declaring a function as a DLL function does not automatically load the DLL. The DLL is loaded once the function is used. Please note that library names should match, so in your declaration for LIB "USER32" ... to find this library, you must match that same name. ie. LIBRARYINST("USER32.DLL") returns 0, it must be "USER32" in this particular case. See also UNLOADLIBRARY.
RapidQ does not support compile-time linking with another .lib file.

LOG | MATH Function | Windows/Unix
A math function that returns the natural logarithm of a numeric expression.

Syntax: LOG(numeric-expression)
A# = LOG(10)

LPRINT | PRINTER Statement | Windows
A statement just like PRINT except all output is directed to the default printer. Make sure to call LFLUSH to start the print job.

Syntax: LPRINT [expressions][{;|,}][...]
LPRINT "print this line"
LFLUSH

Details:
You should call LFLUSH after you're satisfied that you want to start printing. If you don't call LFLUSH, then whenever your application terminates is when your document will start its print job.

LTRIM$ | STRING Function | Windows/Unix
A string function that returns a string with leading spaces removed.

Syntax: LTRIM$(string-expression)
A$ = LTRIM$(" Hello") '-- returns Hello

MEMCMP | MEMORY Function | Windows/Unix
A memory function that compares 2 memory addresses and returns 0 if the memory contents do not match, or non-zero otherwise.

Syntax: MEMCMP(ptr1, ptr2, count)
DEFINT I=10, J=10
A% = MEMCMP(VARPTR(I), VARPTR(J), SIZEOF(INTEGER))

MEMCPY | MEMORY Function | Windows/Unix
A memory function that copies n bytes of memory from source to destination.

Syntax: MEMCPY(destination, source, n)
DEFINT I=90, J=10
'-- After MEMCPY, I should equal 10
MEMCPY(VARPTR(I), VARPTR(J), SIZEOF(INTEGER))

Details
This is similar to the Windows API function call RtlMoveMemory or CopyMemory. The keyword WITH will not work on this, you must fully write out the component name:

WITH Form
.left =0
MEMCMP(VARPTR(myString), VARPTR(.caption), SIZEOF(.caption)
END WITH
In this example Form.Caption will not be recognized

MEMSET | MEMORY Function | Windows/Unix
A memory function that initializes a memory blocks.

Syntax: MEMSET(ptr, char, size)
DIM IntArray(1 TO 10) AS INTEGER
MEMSET(VARPTR(I(1)), 0, 10*SIZEOF(INTEGER))

Details:
Use this instead of INITARRAY

MESSAGEBOX | RAPID-Q Specific | Windows
Displays a simple message box with prompts. This implements Window's MessageBox API function.

Syntax: MESSAGEBOX(message, title, flags%)
IF MessageBox("Close this form?", "Close", 1) = 1 THEN
'-- Close form
END IF

Details:
Some Windows API valid flag for MessageBox() Flags
Public Const MB_OK = &H0&
Public Const MB_OKCANCEL = &H1&
Public Const MB_ABORTRETRYIGNORE = &H2&
Public Const MB_YESNOCANCEL = &H3&
Public Const MB_YESNO = &H4&
Public Const MB_RETRYCANCEL = &H5&

Public Const MB_ICONHAND = &H10&
Public Const MB_ICONQUESTION = &H20&
Public Const MB_ICONEXCLAMATION = &H30&
Public Const MB_ICONASTERISK = &H40&

Public Const MB_ICONINFORMATION = MB_ICONASTERISK
Public Const MB_ICONSTOP = MB_ICONHAND

Public Const MB_DEFBUTTON1 = &H0&
Public Const MB_DEFBUTTON2 = &H100&
Public Const MB_DEFBUTTON3 = &H200&

Public Const MB_APPLMODAL = &H0&
Public Const MB_SYSTEMMODAL = &H1000&
Public Const MB_TASKMODAL = &H2000&

Public Const MB_NOFOCUS = &H8000&
Public Const MB_SETFOREGROUND = &H10000
Public Const MB_DEFAULT_DESKTOP_ONLY = &H20000

Public Const MB_TYPEMASK = &HF&
Public Const MB_ICONMASK = &HF0&
Public Const MB_DEFMASK = &HF00&
Public Const MB_MODEMASK = &H3000&
Public Const MB_MISCMASK = &HC000&

Declare Function MessageBox Lib "user32" Alias "MessageBoxA" _
(ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

· hWnd
Identifies the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.
· lpText
Points to a null-terminated string containing the message to be displayed.
· lpCaption
Points to a null-terminated string used for the dialog box title. If this parameter is NULL, the default title Error is used.
· uType
Specifies a set of bit flags that determine the contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags.

Specify one of the following flags to indicate the buttons contained in the message box:
MB_ABORTRETRYIGNORE The message box contains three push buttons: Abort, Retry, and Ignore.
MB_OK The message box contains one push button: OK. This is the default.
MB_OKCANCEL The message box contains two push buttons: OK and Cancel.
MB_RETRYCANCEL The message box contains two push buttons: Retry and Cancel.
MB_YESNO The message box contains two push buttons: Yes and No.
MB_YESNOCANCEL The message box contains three push buttons: Yes, No, and Cancel.

Specify one of the following flags to display an icon in the message box:
MB_ICONEXCLAMATION, MB_ICONWARNING
An exclamation-point icon appears in the message box.

MB_ICONINFORMATION, MB_ICONASTERISK
An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONQUESTION A question-mark icon appears in the message box.
MB_ICONSTOP,
MB_ICONERROR,
MB_ICONHAND
A stop-sign icon appears in the message box.

Specify one of the following flags to indicate the default button:
MB_DEFBUTTON1 The first button is the default button.
MB_DEFBUTTON1 is the default unless MB_DEFBUTTON2, MB_DEFBUTTON3, or MB_DEFBUTTON4 is specified.
MB_DEFBUTTON2 The second button is the default button.
MB_DEFBUTTON3 The third button is the default button.
MB_DEFBUTTON4 The fourth button is the default button.

Specify one of the following flags to indicate the modality of the dialog box:
MB_APPLMODAL
The user must respond to the message box before continuing work in the window identified by the hWnd parameter. However, the user can move to the windows of other applications and work in those windows.
Depending on the hierarchy of windows in the application, the user may be able to move to other windows within the application. All child windows of the parent of the message box are automatically disabled, but popup windows are not.
MB_APPLMODAL is the default if neither MB_SYSTEMMODAL nor MB_TASKMODAL is specified.
MB_SYSTEMMODAL
Same as MB_APPLMODAL except that the message box has the WS_EX_TOPMOST style. Use system-modal message boxes to notify the user of serious, potentially damaging errors that require immediate attention (for example, running out of memory). This flag has no effect on the user's ability to interact with windows other than those associated with hWnd.
MB_TASKMODAL
Same as MB_APPLMODAL except that all the top-level windows belonging to the current task are disabled if the hWnd parameter is NULL. Use this flag when the calling application or library does not have a window handle available but still needs to prevent input to other windows in the current application without suspending other applications.

In addition, you can specify the following flags:
MB_DEFAULT_DESKTOP_ONLY
The desktop currently receiving input must be a default desktop; otherwise, the function fails. A default desktop is one an application runs on after the user has logged on.
MB_HELP
Adds a Help button to the message box. Choosing the Help button or pressing F1 generates a Help event.
MB_RIGHT
The text is right-justified.
MB_RTLREADING
Displays message and caption text using right-to-left reading order on Hebrew and Arabic systems.
MB_SETFOREGROUND
The message box becomes the foreground window. IWindows calls the SetForegroundWindow function for the message box.
MB_TOPMOST
The message box is created with the WS_EX_TOPMOST window style.
MB_SERVICE_NOTIFICATION
Windows NT only: The caller is a service notifying the user of an event. The function displays a message box on the current active desktop, even if there is no user logged on to the computer. If this flag is set, the hWnd parameter must be NULL. This is so the message box can appear on a desktop other than the desktop corresponding to the hWnd. For Windows NT version 4.0, the value of MB_SERVICE_NOTIFICATION has changed. See WINUSER.H for the old and new values. Windows NT 4.0 provides backward compatibility for pre-existing services by mapping the old value to the new value in the implementation of MessageBox and MessageBoxEx. This mapping is only done for executables that have a version number, as set by the linker, less than 4.0.
To build a service that uses MB_SERVICE_NOTIFICATION, and can run on both Windows NT 3.x and Windows NT 4.0, you have two choices. 1. At link-time, specify a version number less than 4.0; or 2. At link-time, specify version 4.0. At run-time, use the GetVersionEx function to check the system version. Then when running on Windows NT 3.x, use MB_SERVICE_NOTIFICATION_NT3X; and on Windows NT 4.0, use MB_SERVICE_NOTIFICATION.
MB_SERVICE_NOTIFICATION_NT3X Windows NT only: This value corresponds to the value defined for MB_SERVICE_NOTIFICATION for Windows NT version 3.51.

MESSAGEDLG | RAPID-Q Specific | Windows
Displays a message box with an icon and a user defined caption. This implements Window's MessageBoxEx API function.

Syntax: MESSAGEDLG(string-expression, msgType, msgButtons, helpContext)
IF MessageDlg("Close this form?", mtWarning, mbYes OR mbNo, 0) = mrNo THEN
'-- Don't close form
END IF

Details:
msgType is used to display the type of icon that will be displayed in your message box.
0 = mtWarning      3 = mtConfirmation
1 = mtError        4 = mtCustom
2 = mtInformation
msgButtons is used to display custom dialog buttons. To display more than one message button, just OR them.
1 = mbYes       32 = mbAbort
2 = mbNo        64 = mbRetry
4 = mbOK       128 = mbIgnore
8 = mbCancel   256 = mbAll
16 = mbHelp
helpContext is ignored for now.

MID$ | STRING Function | Windows/Unix
A string function that returns a substring with n chracters starting from i of string-expression.

Syntax: MID$(string-expression, i, n)
A$ = MID$("Hello",3,2) '-- returns ll

Details:
You cannot use MID$ in this way:
MID$(A$, 1, 1) = "G"
Under QBasic, this valid statement replaces the first character from A$ with "G". To acheive the same effect under Rapid-Q, please use the REPLACE$ string function.

MKDIR | SYSTEM Statement | Windows/Unix
A statement that creates a new directory.

Syntax: MKDIR pathspec
MKDIR "abc"

mkdir "C:\BAS\RAPIDQ\help2\1234" - without last slash
or
mkdir "C:\BAS\RAPIDQ\help2\1234\" - with last slash, All variants are working

Details:
MKDIR will not rewrite a directory if one already exists, if no path is specified, the directory is created in the current working directory.

OUT | I/O Statement | Windows/Unix
A device I/O statement that sends a byte value to a machine I/O port.

Syntax: OUT port, value
OUT &H3C9, 128

Details:
  • Port is any word value between 0 and 65535.
  • Value is any byte value between 0 and 255.

    This keyword is stable only for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, try utilities like PorkTalk or io.dll instead.

OUTW | I/O Statement | Windows/Unix
A device I/O statement that sends a word value to a machine I/O port.

Syntax: OUTW port, value
OUTW &H378, 128

Details:
  • Port is any word value between 0 and 65535.
  • Value is any byte value between 0 and 65535.

    This keyword is stable only for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, try utilities like PorkTalk or io.dll instead.

PLAYWAV | RAPID-Q Specific | Windows
Plays a .WAV file or a .WAV resource.

Syntax: PLAYWAV wavfilename|wavresource, sndOptions
$RESOURCE Welcome_WAV AS "welcome.wav"
PLAYWAV "welcome.wav", SND_ASYNC OR SND_LOOP
PLAYWAV Welcome_WAV, SND_ASYNC OR SND_LOOP

Details:
sndOptions determine how the wav file is played back.
0 = SND_SYNC     '-- waits for wav to finish
1 = SND_ASYNC    '-- background play
3 = SND_LOOP     '-- Loop wav once finished playing
You can combine SYNC or ASYNC with LOOP by OR'ing them. If your WAV file is not finished playing when you close your application, you will receive an access violation. You can stop the .WAV by passing an empty string as a filename.

POSTMESSAGE | RAPID-Q Specific | Windows
A WinAPI call to PostMessage, does not block.

Syntax: POSTMESSAGE hWnd, uMsg, wParam, lParam
POSTMESSAGE Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0

Details:
PostMessage is a WinAPI call so instead of filling this entire page with information you can look up this function in your WinAPI manual/help file.

QUICKSORT | SORTING Statement | Windows/Unix
QUICKSORT, aptly named, can be used to sort your arrays of any type, except Objects/UDTs of course. It, obviously, uses the QuickSort algorithm to perform the sort.

Syntax: QUICKSORT(Array-begin, Array-end, ASCEND|DESCEND)
DIM A(1000) AS INTEGER
'-- put stuff in A
QUICKSORT(A(10), A(500), ASCEND) '-- sorts elements 10..500

Details:
The pivot element in the above example is A(10), so if you want randomness, you'll have to replace A(10) with some random element from A(10)..A(500) in the above example. You can also sort multi-dimensional arrays and "span sort" arrays.

Span sorting:
           DIM A(1 TO 100) AS LONG
           DIM B(1 TO 100) AS LONG
           DIM C(1 TO 100) AS LONG

           '--- puts some values into array A, B, C
           RANDOMIZE TIMER
           FOR I = 1 TO 100
               A(I) = RND(50000)
               B(I) = RND(50000)
               C(I) = RND(50000)
           NEXT

           QUICKSORT A(1), C(100), ASCEND
           PRINT A(1)," ",B(1)," ",C(1)
As long as you DIM the arrays "side by side" they will share a contiguous space of memory, this means you can sort from the start of memory address A(1) to the end of memory address C(100). This technique is not recommended, but if you can find a use for it, go ahead.

RANDOMIZE | MATH Statement | Windows/Unix
Initializes (reseeds) the random-number generator.

Syntax: RANDOMIZE [numeric-expression]
RANDOMIZE TIMER

Details:
If argument is omitted, randomize will default as RANDOMIZE TIMER.

READ | Statement | Windows/Unix
A statement that reads values from a DATA statement and assigns the values to variables.

Syntax: READ variablelist
READ A%, S$, P(1,2)

Details:
Variablelist is made up of one or more variables, separated by commas, which are to receive the data. The variables may be string or numeric.

REDIM | Statement | Windows/Unix
Declaration statement that changes the space allocated to an array that has already been declared by DIM, preserving as much of the data as possible.

Syntax: REDIM variable[(subscripts)] AS type
DIM B(20) AS INTEGER
REDIM B(100) AS INTEGER

Details:
If the array has not yet been declared by DIM, REDIM will be equivalent to calling DIM (except when dealing with components, in which case you'll receive a compiler error). You cannot change the data type for the array, ie. you cannot redefine array B to be something other than an INTEGER (as in the above example). Combining arrays is a by-product of REDIM.
DIM A(1 to 100) AS INTEGER
DIM B(1 to 100) AS INTEGER
REDIM A(1 to 200) AS INTEGER   '-- Combines A and B together
What the above code does is preserve the data in A as well as combining the array B. so index from 101 to 200 is the data for B and 1 to 100 is the data for A. Clarification: Array B has not been modified, it still maintains its own address space and will not overwrite A's data and vice versa. Note that this by-product does not apply to redimming Fixed Strings, Variants and Components.
Redim table
  DIM Button(1 TO 2, 1 TO 2) AS QBUTTON
REDIM Button(1 TO 2, 1 TO 4) AS QBUTTON
Note that when dealing with multiple dimensions the elements are shifted to fill each column. So element (2,2) is actually moved to position (1,4).
Some problems to be aware of:
DIM A(1) AS STRING*4
REDIM A(20) AS STRING*4 'this redim causes an error!

RELEASECAPTURE | RAPID-Q Specific | Windows
Windows API that releases the mouse capture from a window in the current program after a SETCAPTURE function call. Restores normal mouse input processing. A window that has captured the mouse receives all mouse input, regardless of the position of the cursor, except when a mouse button is clicked while the cursor hot spot is in the window of another thread. This is a keyword in RAPIDQ2.INC

Syntax: Return = RELEASECAPTURE
DIM Rtn AS LONG
Rtn = ReleaseCapture 'Rtn is optional

Details:
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.

REM | Comment | Windows/Unix
A BASIC declaration that allows explanatory remarks to be inserted in a program. It's suggested that you use ' to start your comments instead.

Syntax: REM remark
REM This is a comment, nothing is executed
' This is another comment, use this one in RapidQ rather than REM:

a=5 rem fkfkl, - not working
a=5 ' fkfkl, - works

RENAME | SYSTEM Statement | Windows/Unix
A statement that renames a file. If file already exists the operation is not executed.

Syntax: RENAME file1, file2
RENAME "abc.txt", "xyz.txt"

REPLACE$ | STRING Function | Windows/Unix
A function that replaces a portion of a string with another.

Syntax: REPLACE$(source-string, replace-string, index)
A$ = REPLACE$("Hello", "J", 1) '-- returns Jello

REPLACESUBSTR$ | STRING Function | Windows/Unix
A function that replaces a substring with another string. All occurrences will be replaced. The length of the replacement string does not need to match the length of the replaced string.

Syntax: REPLACESUBSTR$(source-string, replace-string, replacement-string)
A$ = REPLACESUBSTR$("abcdefgabcdefg", "abc", "99") '-- returns 99defg99defg

RESOURCE | RESOURCE Function | Windows/Unix
A function that returns the absolute position of the resource from the current program.

Syntax: RESOURCE(numeric-expression)
EXTRACTRESOURCE Resource(0), "test.bmp"

Details:
RESOURCE() is an array consisting of 0 to RESOURCECOUNT-1 elements. Element 0 corresponds to the first $RESOURCE handle you specify and so on. If numeric-expression is not in the range 0 to RESOURCECOUNT-1, this function returns 0.

RESOURCECOUNT | RESOURCE Function | Windows/Unix
A function that returns the number of resources in the current program.

Syntax: RESOURCECOUNT
A% = RESOURCECOUNT

RESTORE | Statement | Windows/Unix
A statement that allows DATA statements to be reread from a specified line.

Syntax: RESTORE [{linelabel | linenumber}]
RESTORE

Details:
If the argument is omitted, the next READ statement which executes will read the first item in the first DATA statement in the program. Linelabel or Linenumber identifies the DATA statement you want the next READ statement to use. The first item from that line will be read.

REVERSE$ | STRING Function | Windows/Unix
A function that reverses (or mirrors) a string.

Syntax: REVERSE$(string-expression)
A$ = REVERSE$("Hello") '-- returns olleH

RGB | CONVERSION Function | Windows/Unix
A conversion function that takes the red, green and blue parameters and combines them to form a BGR numeric representation.

Syntax: RGB(redvalue, greenvalue, bluevalue)
C = RGB(255, 0, 255)

Details:
Values range from 0-255. Values outside this range produce undefined results.

RIGHT$ | STRING Function | Windows/Unix
A function that returns the rightmost n characters of a string.

Syntax: RIGHT$(string-expression, n)
A$ = RIGHT$("Hello", 3) '-- returns llo

Details
Limited to strings under 32K size.! If your strings are larger than 32K you must break up the string for RIGHT$

RINSTR | STRING Function | Windows/Unix
Reverse INSTR is a function that compares 2 strings and returns the position of the find-string with respect to the search-string. Instead of starting the search from left to right, like INSTR, RINSTR searches right to left (ie. the reverse of INSTR). If found, RINSTR returns the index position of the find-string, 0 otherwise.

Syntax: RINSTR([start,] search-string, find-string)
A% = RINSTR("Hello World", "l") '-- returns 10
A% = RINSTR(4, "hehe they", "he") '-- returns 3

RMDIR | SYSTEM Statement | Windows/Unix
A statement that removes a directory.

Syntax: RMDIR directory
RMDIR "abc"
RMDIR "LastCopy\123" for sub..subdirectory in the current directory.
RMDIR "C:\W98\" for full path

RND | MATH Function | Windows/Unix
A function that returns a random number whose sequence is generated by calling RANDOMIZE.

Syntax: RND[(upper-bound)]
A% = RND(10)

Details:
If no upper-bound is given, RND returns a decimal number in the range 0 to 1.

ROUND | MATH Function | Windows/Unix
A math function that converts a number to an integer by rounding the fractional part of the expression.

Syntax: ROUND(numeric-expression)
A% = ROUND(3.49) '-- Returns 3
A% = ROUND(3.50) '-- Returns 4

Details:
If the argument is negative, then Round always rounds toward zero. I.E. Round(-3.99) returns -3 instead of -4.
A way around this:

DEFBYTE NEG = 0
IF Answer < 0 THEN
NEG = 1
Answer = ABS(Answer)
END IF
Answer = ROUND(Answer)
IF NEG THEN Answer = -Answer
NEG = 0 ' reset Flag

RTRIM$ | STRING Function | Windows/Unix
A string function that returns a string with trailing spaces removed.

Syntax: RTRIM$(string-expression)
A$ = RTRIM$("Hello ") '-- returns Hello

RUN | SYSTEM Statement | Windows/Unix
A statement that executes a specified program without blocking.

Syntax: RUN filespec
RUN "rapidq.exe"

SENDMESSAGE | RAPID-Q Specific | Windows
A WinAPI call to SendMessage, blocks until message is processed.

Syntax: SENDMESSAGE hWnd, uMsg, wParam, lParam
SENDMESSAGE Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0

Details:
SendMessage is a WinAPI call so instead of filling this entire page with information you can look up this function in your WinAPI manual/help file. Note this is not a function as stated in the Windows API guide. Use the statement in RAPIDQ2.INC :
returnVal = SendMessageAPI hWnd, uMsg, wParam, lParam

SETFOCUS | RAPID-Q Specific | Windows
A famous WinAPI call that sets the keyboard output to the specified control/component. The window must be associated with the calling programs messages. This is a keyword in RAPIDQ2.INC

Syntax: SETFOCUS(hWnd)
SETFOCUS (Button.Handle)

Details:
You can find out which control is currently getting the focus with GETFOCUS.

SETCAPTURE | RAPID-Q Specific | Windows
Windows API that sets the mouse capture to the specified window belonging to the current program. Once a window has captured the mouse, all mouse input is directed to that window, regardless of whether the cursor is within the borders of that window. Only one window at a time can capture the mouse. This is a keyword in RAPIDQ2.INC

Syntax: Handle = SETCAPTURE(hWnd)
DIM aHandle AS LONG
aHandle = SETCAPTURE(Canvas.Handle)

Details:
If the function succeeds, the return value is the handle of the window that had previously captured the mouse. If there is no such window, the return value is NULL. See RELEASECAPTURE and GETCAPTURE

SGN | MATH Function | Windows/Unix
A math function that indicates the sign of a numeric expression.

Syntax: SGN(numeric-expression)
A% = SGN(-123) '-- Returns -1

Details:
If numeric-expression is positive, SGN returns +1.
If numeric-expression is zero, SGN returns 0.
If numeric-expression is negative, SGN returns -1.

SHELL | SYSTEM Statement/Function | Windows
SHELL can be called as a statement or as a function. It has the same functionality as RUN except that it blocks your application until the executed one has ended.

Syntax: SHELL command
SHELL "rapidq.exe"
Syntax: SHELL(command, showCMD)
PID = SHELL("rapidq.exe", SW_SHOWNORMAL)

Details:
If calling SHELL as a function, the return value is the process ID of the executed program, and will not block your program. showCMD can be any of the following:
0 = SW_HIDE              6 = SW_MINIMIZE
1 = SW_SHOWNORMAL        7 = SW_SHOWMINNOACTIVE
2 = SW_SHOWMINIMIZED     8 = SW_SHOWNA
3 = SW_SHOWMAXIMIZED     9 = SW_RESTORE
4 = SW_SHOWNOACTIVATE   10 = SW_SHOWDEFAULT
5 = SW_SHOW

Examples:
Shell "command.com /C copy /b one.txt+two.txt oneandtwo.txt"
x=Shell("Command.com /C echo y| del "+chr$(34) + ".\Original\*.*" +chr$(34) , 0)

SHOWMESSAGE | RAPID-Q Specific | Windows/Unix
A statement used to display a generic popup message box.

Syntax: SHOWMESSAGE string-expression
SHOWMESSAGE "Hello world!"

Details
' to get mulitple lines in a ShowMessage box:
CONST CR = CHR$(13)
CONST LF = CHR$(10)
CONST CRLF = CR + LF
SHOWMESSAGE "This will be on" + CRLF + "two lines!"

OR

$ESCAPECHARS ON
SHOWMESSAGE "This will be on\r\ntwo lines!"

SIN | MATH Function | Windows/Unix
A math function that returns the sine of an angle given in radians.

Syntax: SIN(numeric-expression)
PI = 3.14153
C# = SIN(PI)

Details:
Numeric-expression is the angle expressed in radians.

SIZEOF | MEMORY Function | Windows/Unix
A function that returns the size, in bytes, of a data type.

Syntax: SIZEOF(datatype|variable)
PRINT SIZEOF(MyUDT)
PRINT SIZEOF(MyVar)
PRINT SIZEOF(INTEGER)

Details:
To calculate the size of a UDT, you must first DIM it.
ie. DIM MyUDT AS TMyUDT
Not all cases are supported, may return 4 bytes for an array (the size of the array pointer since arrays are passed by reference).

SOUND | I/O Statement | Windows
A device I/O statement that generates sound through the PC Speaker.

Syntax: SOUND frequency, duration
SOUND 4000, 18

Details:
May not be supported in Windows versions later than Win98.
  • Frequency is a numeric expression whose value is between 37 and 32,767. Frequency is measured in cycles/second, or hertz.
  • Duration is a numeric expression whose value is between 0 and 65,535. There are 18.2 clock ticks per second, so 18 is considered 1 second, etc...

SPACE$ | STRING Function | Windows/Unix
A string function that returns a string of spaces of length n.

Syntax: SPACE$(n)
A$ = SPACE$(5)

SQR | MATH Function | Windows/Unix
A math function that returns the square root of a number.

Syntax: SQR(numeric-expression)
A# = SQR(9) '-- returns 3

STATIC | Statement | Windows/Unix
Similar to DIM, this statement names one or more variables and allocates storage space for them. However, declaring STATIC variables means that variable values are preserved between procedure calls. Note that only simple types are affected.

Syntax: STATIC variable[(subscripts)] AS type
STATIC A AS INTEGER, B AS BYTE, S AS STRING

Details:
STATIC has no affect (ie. same as using DIM) when declared in the main module. Use STATIC only inside a SUB/I or FUNCTION/I.

Examples:
    '-- Non static count
    SUB Count (N AS INTEGER)
       DIM B AS LONG

       B = N
       IF N = 10 THEN EXIT SUB
       Count(N+1)
       PRINT B
    END SUB

    Count(1)

    '-- Static count, B retains the same value
    SUB StaticCount (N AS INTEGER)
       STATIC B AS LONG

       B = N
       IF N = 10 THEN EXIT SUB
       StaticCount(N+1)
       PRINT B
    END SUB

    StaticCount(1)

STR$ | CONVERSION Function | Windows/Unix
A conversion function that returns a string representation of the value of a numeric expression.

Syntax: STR$(numeric-expression)
A$ = STR$(99)

STRF$ | CONVERSION Function | Windows
A conversion function that returns a formatted string representation of the value of a numeric expression.

Syntax: STRF$(numeric-expression, Format%, Precision%, Digits%)
A$ = STRF$(99.9934, ffGeneral, 4, 4)
A$ = STRF$(12345678, ffNumber, 8, 0)

Details:
Precision% specifies how many decimal places to calculate.
The following are valid Formats:
0 = ffGeneral      2 = ffFixed
1 = ffExponent     3 = ffNumber
ffGeneral converts to the shortest possible decimal string, where trailing zeros are removed. Digits% range from values of 0 to 4.
ffExponent converts to scientific notation of the form -d.ddd...E+dddd. Digits% range from values of 0 to 4.
ffFixed converts to fixed point format of the form -ddd.ddd... Digits% range from values of 0 to 18.
ffNumber converts to a number format of the form -d,ddd,ddd.ddd... Where the resulting string contains thousand separators.

STRING$ | STRING Function | Windows/Unix
A string function that returns a string whose characters all have a given ASCII code or whose characters are all the first character of a string expression.

Syntax: STRING$(count, byte)
A$ = STRING$(9, 65) '-- Returns AAAAAAAAA
Syntax: STRING$(count, string-expression)
A$ = STRING$(9, "ABC") '-- Returns AAAAAAAAA

Details:
The first parameter indicates the number of times to repeat the character. The second parameter can either be a string expression, whose first character is used as the repeat character, or a byte number in the range from 0 to 255 representing the ASCII character code.

SUPER | Custom Component Keyword | Windows/Unix
In Rapid-Q custom components, all methods, properties, and events can be overridden. To access the original property or method, you must explicitly call the SUPER class as demonstrated below. Becareful if using WITH Super ... END WITH, since all properties/methods will be referenced as the super class. The concept of overriding properties or methods is simple enough, instead of using the inherited properties, we can just redefine them instead. ALSO SUPER only takes values not variables... (odd bug)
     TYPE QDiamondBox EXTENDS QCanvas
        Left AS STRING
        Top AS BYTE

        SUB Pset
            PRINT Super.Left
        END SUB
     END TYPE

SWAP | Statement | Windows/Unix
An assignment statement that exchanges the values of 2 variables.

Syntax: SWAP variable1, variable2
SWAP A$, B$

Details:
Variable1 and variable2 should be of the same type, but Rapid-Q won't complain. Also, do not swap variants using the SWAP function if their types do not match.

TALLY | STRING Function | Windows/Unix
Tally counts the number of occurrences of MatchString within a SearchString.

Syntax: TALLY(search-string, match-string)
Count& = TALLY("abcdefghijklmnabc", "abc") '-- returns 2

TAN | MATH Function | Windows/Unix
A math function that returns the tangent of an angle given in radians.

Syntax: TAN(numeric-expression)
T# = TAN(90)

Details:
Numeric-expression is the angle expressed in radians.

THIS | QOBJECT Function inside EXTENDS | Windows/Unix
The keyword THIS is used as a handy reference to the component/object name inside a TYPE EXTENDS QOBJECT/QXXX statements

Example: THIS.Height = (numeric-expression)
TYPE MyObj EXTENDS QFORM
   Height as INTEGER
   CONSTRUCTOR
      THIS.Height = 30
    END CONSTRUCTOR
END TYPE

Details:
See extending custom components

TIME$ | SYSTEM Function | Windows/Unix
A function that returns a string containing the current time formatted as HH:MM:SS. Where HH = hour (0-23), MM = minute (0-59) and SS = seconds (0-59)

Syntax: TIME$
PRINT TIME$

Details:
Unlike QBasic where you can set the current date using the TIME$ statement, you cannot do this under Rapid-Q.

TIMER | SYSTEM Function | Windows/Unix
A function that returns the number of seconds elasped since midnight.

Syntax: TIMER
T! = TIMER

Details:
Timer value for Linux/Unix is the number of seconds elasped since your program started.

UBOUND | ARRAY Function | Windows/Unix
A function that returns the upper bound of the array.

Syntax: UBOUND(arrayname [,dimension])
DIM A(-50 TO 100) AS INTEGER
L% = UBOUND(A) '-- Returns 100

Details:
If the array has multiple dimensions, you can use the optional dimension argument to check the upper bound of each one. NOTE:
There is no checking for limits on arrays. You can "read" an array value outside that used in DIM, giving unpredictable results. Always keep track of your array start and end instead of LBOUND and UBOUND for the best results.

UCASE$ | STRING Function | Windows/Unix
A string function that returns a string expression with all letters upper-case.

Syntax: UCASE$(string-expression)
A$ = UCASE$("Hello") '-- returns HELLO

UNLOADLIBRARY | DLL Statement | Windows
Removes DLL from memory (only those declared in Rapid-Q). If DLL hasn't been loaded or is not found, this statement does nothing.

Syntax: UNLOADLIBRARY(DLLName)
DECLARE FUNCTION UpdateWindow LIB "USER32" ALIAS _
"UpdateWindow" (hWnd AS LONG) AS LONG
UNLOADLIBRARY("USER32") '-- Removes USER32.DLL from memory

Details:
It is not required that you unload a DLL, this is done for you when your Rapid-Q program ends. Unloading a DLL library from memory does not mean the function call that requires the DLL will fail. The DLL is again reloaded into memory before the function call, so you can UnLoad it again if you want. Please note that library names should match, so in your declaration for LIB "USER32" ... to unload this library, you must match that same name. UNLOADLIBRARY("USER32.DLL") does nothing, it must be "USER32" in this particular case. See also LIBRARYINST.

VAL | CONVERSION Function | Windows/Unix
A conversion function that returns a numeric representation of the string expression.

Syntax: VAL(string-expression)
A = VAL("995")

VARPTR | ADDRESS Function | Windows/Unix
A function that returns the address, ie. pointer to, of the given variable name. Variable must be a declared variable, ie. not a component variable such as QForm.Caption

Syntax: VARPTR(variablename)
Addr& = VARPTR(MyString$)
Addr& = VARPTR(MyArray(0)) 'be sure to reference the first element of your array

Details:
You can only get pointers to basic datatypes like INTEGER, SINGLE, DOUBLE. Pointers to Qobjects and components (like OBJPTR in visual basic) are not supported. Unlike C/C++, you cannot get a pointer of a member inside a UDT--
VARPTR(MyRec.NumRecords)

VARPTR$ | ADDRESS Function | Windows/Unix
A function that returns the string representation of a given address.

Syntax: VARPTR$(address)
S$ = VARPTR$(279027343)

VARTYPE | VARIANT Function | Windows/Unix
A function that returns the data type of the current value stored in the variant.

Syntax: VARTYPE(variant)
DIM myvariant(100) AS VARIANT
myvariant(1) = "G"
VType = VARTYPE(myvariant(1))

Details:
Valid return values are:
0 - Number (includes Byte, Word, Dword, Short, Long/Integer)
1 - Float (includes Single, Double)
2 - String

Example
dim TstNum as variant
DEFDBL Number1
Number1=77.0
TstNum=Number1
VType = VARTYPE(TstNum)
print "VType0=" ,VType  ' Return 0

Number1=77.01
TstNum=Number1
VType = VARTYPE(TstNum)
print "VType1=" ,VType  ' Return 1
All undefined variants are initialized as Numbers.

WITH .. END WITH Compiler DIRECTIVE /block Function Windows/Unix
This Keyword is a shortcut for user defined types, structures, components, or Qobjects. This will save you some typing. However, not all cases of WITH are supported. For instance, WITH will not work inside a MEMCPY and inside a custom component using WITH Super ... END WITH, since all properties/methods will be referenced as the super class.

DIM Form AS QFORM
'everything between WITH ...END WITH will substitute "Form" before the period.
WITH Form
.Left = 30
.Top = 50
END WITH


Trouble Shooting

Rapid-Q Documentation by William Yu (c)1999, Appended by John Kelly Appendix C: Trouble Shooting

How to debug your programs

In most cases, it's either a typo, or you're trying to use a function which is not supported under Rapid-Q. This occurs most often when you don't have $TYPECHECK ON. I can't stress this enough, unless you've used Rapid-Q for awhile, I strongly encourage everybody to turn this directive on. Rapid-Q has a very poor checking mechanism, and relies heavily on the programmer to write proper code. For Example:
    PRINT SPC(10)
SPC is not supported in Rapid-Q (in QBasic, SPC just skips spaces). If typechecking is off, the above statement is perfectly valid. SPC is a variable, initialized to 0, and (10) has no effect (ie. the number 10 is pushed on the stack, but no operation is done), so the above output will be 0.

Why didn't my SUB or FUNCTION run? Why didn't my code work?
When inside a SUB or FUNCTION, if RapidQ comes to a statement that fails, the program will EXIT the SUB or FUNCTION without warning you. To make sure your SUB/FUNCTION really was completed, put a statement like SHOWMESSAGE "End of Sub reached"at the end to make sure it really ran the subroutine. Otherwise there is a problem with your code that causes the program to leave your sub. This can also happen outside of a SUB/FUNCTION, but you probably will get a program that doesn't run.

Passing by reference
Only QObjects, Arrays, and Variants are passed by reference, all other variables are passed by value. To pass a variable by reference, you can either explicitly specify this by adding BYREF to your parameter list, or prepend an @ symbol to any variables you want passed by reference when calling the function. Do not use the @ symbol for Arrays, Variants, or QObjects since they are passed by reference by default. Read more about this in Chapter 3 or Appendix C: Procedures. Typechecking is done only for Arrays, Variants, and QObjects, since you can't pass an array of integers to a SUB that expects an array of doubles. You should get an error message if you try this, however, for all other variables which are passed by value, NO checking is done. Which means you could easily pass an integer to a SUB expecting a string. So becareful that you know the type of parameters for your SUB/FUNCTION, since Rapid-Q won't complain. Also make sure if you have DECLARE SUBs, that your SUB will have matching parameters, including matching parameter names.

Using Undocumented features
Rapid-Q has some undocumented features, most of which are in a beta-like stage. You can embed SUBs or FUNCTIONs but they can only be one level deep, and there are some consequences with using them. If you don't know what an embedded SUB looks like, take this for example:

    SUB MySub
      DIM I AS INTEGER

      SUB MyChildSub (X AS INTEGER)
        DIM N AS DOUBLE

        PRINT "In Child Sub"
      END SUB

      CALL MyChildSub(100)
    END SUB
There are some special issues involved, such as all variables are local to the SUBs that follow. Meaning, the variable I is local to SUB MyChildSub. Also, since Rapid-Q doesn't actually clean things up, you can actually call MyChildSub in your main program as well. This is a problem I'm working to correct when I find the time. One other feature which might interest people is postfix ++ and --
    DIM I AS INTEGER

    I++           '-- same as I = I + 1
    I--           '-- same as I = I - 1
    I -= 10       '-- same as DEC(I, 10)
    I += 15       '-- same as INC(I, 15)
Arrays are a special case, anything but Arrays can be incremented/decremented. Rapid-Q doesn't do any optimizing, so the above code and the given translation runs exactly the same. The boundaries of an array are not checked.

Other errors
If you don't have a clue as to what is causing your programs to crash, your only hope is to put several PRINT statements in your program and incrementally check each block of code so that it works properly. If you're using Unix or Linux, try using gdb, sometimes it will give you some useful information, but most of the time it's not really that helpful in this kind of setting. You can also use the custom component QDebug.
Contents


Windows API in RapidQ2

Windows API Windows API Function Calls in RapidQ2.INC Windows

These functions are included in the RapidQ2.inc file for extension of the language using Windows API function calls. For documentation on
these functions visit www.msdn.microsoft.com

AlphaBlend (hdc1 As Long, X1 As integer, Y1 As integer, Width1 As integer, Height1 As integer, hdc2 As Long, X2 As integer, Y2 As integer, Width2 As integer, Height2 As integer, BLEND As BLENDFUNCTION) As Long

AnyPopup () As Long

BFMoveMemory (byref Destination AS LONG, byref Source AS BLENDFUNCTION, Length AS LONG)

BitBlt ( ByVal hdcDest As Long, ByVal nXDest As Long, ByVal nYDest As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hdcSrc As Long, ByVal nXSrc As Long, ByVal nYSrc As Long, ByVal dwRop As Long) AS LONG

BringWindowToTop (ByVal hwnd As Long) As Long

CallWindowProc (lpPrevWndFunc As Long, hwnd As Long, Msg As Long, wParam As Long, lParam As Long) As Long

ChangeDisplaySettings (DevMo AS DevMode, ByVal dwFlags AS LONG) AS LONG

ChooseColorDlg (CC AS CHOOSECOLOR) AS LONG

ClearCommError (hFile AS LONG,_ '[IN] Handle to open Comm device

ClientToScreen (hwnd AS LONG, lpPoint AS LONG)

CloseHandle (hObject AS LONG) AS LONG 'If function succeeds, returns non-zero. If function fails, returns 0.

CommDlgExtendedError () As Long

CreateCompatibleBitmap (hdc As Long,nWidth As Long,nHeight As Long) As Long

CreateCompatibleDC (hdc As Long) As Long

CreateDC ( ByVal lpDriverName As String, ByVal lpDeviceName As String, ByVal lpOutput As String, lpInitData As DEVMODE) AS LONG

CreateFile (lpFileName AS STRING, dwDesiredAccess AS DWORD, dwShareMode AS DWORD, lpSecurityAttributes AS SECURITYATTRIBUTES, dwCreationDisposition AS DWORD, dwFlagsAndAttributes AS DWORD,_ '[IN] Specifies the file attributes and flags

CreatePen (nPenStyle As Long, nWidth As Long, crColor As Long) As Long

CreateSolidBrush (crColor As Long) As Long

CreateWindowEx (dwExStyle AS LONG, lpClassName AS STRING, lpWindowName AS STRING, dwStyle AS LONG, x AS LONG,y AS LONG, nWidth AS LONG, nHeight AS LONG, hWndParent AS LONG, hMenu AS LONG, hInstance AS LONG, lpParam AS LONG) AS LONG

DefMDIChildProc (hWnd AS LONG,uMsg AS LONG,wParam AS LONG,lParam AS LONG) AS LONG

DefWindowProc (hwnd AS LONG, msg as long, wparam as long, lparam as long) AS LONG

DeleteDC (hdc As Long) As Long

DeleteObject (hObject As Long) As Long

DragAcceptFiles (hWnd AS LONG, Accept AS LONG)

DragFinish (hDrop AS LONG)

DragQueryFile (hDrop AS LONG,iFile AS LONG,lpszFile AS LONG,cch AS LONG) AS LONG

DragQueryPoint (hDrop AS LONG, lppt AS POINTAPI) AS LONG

DrawCaption (hwnd AS LONG, hdc AS LONG, qrc AS QRECT, uFlags AS LONG) AS LONG

DrawEdge (hdc AS LONG, qrc AS QRECT, edge AS LONG, grfFlags AS LONG) AS LONG

DrawFrameControl (hdc AS LONG, qrc AS QRECT, utype AS LONG, ustate AS LONG) AS LONG

DrawIconEx (hdc As Long,xLeft As Long,yTop As Long,hIcon As Long,cxWidth As Long,cyWidth As Long,istepIfAniCur As Long,hbrFlickerFreeDraw As Long,diFlags As Long) As Long

Ellipse (hdc As Long,X1 As Long,Y1 As Long,X2 As Long,Y2 As Long) As Long

EnableWindow (ByVal hwnd AS LONG, ByVal fEnable AS LONG) AS LONG

EnumChildWindows (hWndParent AS LONG,lpEnumFunc AS LONG,lParam AS LONG) AS LONG

EnumDisplaySettings (byref DeviceName AS STRING, byval iModeNum AS DWORD, byref DevMo AS DevMode) AS LONG

ExitWindowsEx (ByVal uFlags AS LONG, ByVal dwReserved AS LONG) AS LONG

ExtFloodFill (hdc As Long,x As Long,y As Long,crColor As Long,wFillType As Long) As Long

FormatMessage (dwFlags AS DWORD, lpSource AS LONG, dwMessageId AS DWORD, dwLanguageId AS DWORD, BYREF lpBuffer AS STRING, nSize AS DWORD, lpArguments AS LONG) AS LONG ''If function succeeds, returns non-zero. If function fails, returns 0.

GetCapture () AS LONG

GetClassName (hwnd AS LONG,ByRef lpClassName AS STRING,nMaxCount AS LONG) AS LONG

GetClientRect (ByVal hwnd As Long, lpRect As RECT) As Long

GetCommState (hFile AS LONG, lpDCB AS DCB) AS LONG 'If function succeeds, returns non-zero. If function fails, returns 0.

GetCurrentObject (hdc As Long,uObjectType As Long) As Long

GetCurrentProcess () As Long

GetDC (ByVal hwnd AS LONG) AS LONG

GetDesktopWindow () AS LONG

GetDeviceCaps (ByVal hdc AS LONG, ByVal nIndex AS LONG) AS LONG

GetDriveType (nDrive As String) As Long

GetFocus () AS LONG

GetKeyState (ByVal nVirtKey As Long) As Integer

GetLastError () AS DWORD 'Returns last error code value

GetObject (hObject As Long,nCount As Long, lpObject AS TBITMAP) As Long

GetOpenFileName (pOpenfilename AS OPENFILENAME) AS LONG

GetParent (hwnd As Long) As Long

GetPixel (hdc as Long,x as Long,y as Long) as Long

GetPriorityClass (ByVal hProcess As Long) As Long

GetProp (ByVal hwnd As Long, ByVal lpString As String) As Long

GetSaveFileName (pOpenfilename AS OPENFILENAME) AS LONG

GetStockObject (nIndex As Long) As Long

GetSysColor (nIndex As Long) As Long

GetSystemMetrics (ByVal nIndex As Long) As Long

GetSystemPowerStatus (lpSystemPowerStatus As SYSTEM_POWER_STATUS) As Long

GetVersionEx (lpVersionInformation As OSVERSIONINFO) As Long

GetWindowLong (hwnd AS LONG, type AS LONG) AS LONG

GetWindowRect (ByVal hwnd As Long, lpRect As QRECT) As Long

GetWindowText (ByVal hwnd As Long, ByVal lpString As Long, ByVal cch As Long) As Long

GetWindowTextLength (ByVal hwnd As Long) As Long

IsIconic (ByVal hwnd As Long) As Long

IsWindowVisible (ByVal hwnd As Long) As Long

IsZoomed (ByVal hwnd As Long) As Long

LineTo (hdc As Long,x As Long,y As Long) As Long

LoadImage (hInst AS LONG,lpsz AS STRING, dwImageType AS LONG,dwDesiredWidth AS LONG, dwDesiredHeight AS LONG,dwFlags AS LONG) AS LONG

MDI_CreateWindow (dwExStyle AS LONG,lpClassName AS STRING,lpWindowName AS STRING,dwStyle AS LONG,x AS LONG,y AS LONG,nWidth AS LONG,nHeight AS LONG,hWndParent AS LONG,hMenu AS LONG,hInstance AS LONG,lpParam AS LONG) AS LONG

MDI_DefChildProc (hWnd AS LONG,uMsg AS LONG,wParam AS LONG,lParam AS LONG) AS LONG

MDI_EnumChild (hWndParent AS LONG,lpEnumFunc AS LONG,lParam AS LONG) AS LONG

MDI_GetClassName (hwnd AS LONG,ByRef lpClassName AS STRING,nMaxCount AS LONG) AS LONG

MDI_GetClientRect (hwnd AS LONG,lpRect AS QRECT) AS LONG

MDI_GetParent (hwnd As Long) As Long

MDI_GetProp (hwnd AS LONG,lpString AS STRING) AS LONG

MDI_GetRect (hwnd AS LONG, lpRect AS QRECT) AS LONG

MDI_GetText (hwnd AS LONG,ByRef lpString AS STRING,cch AS LONG) AS LONG

MDI_GetTextLenght (hwnd As Long) As Long

MDI_MoveWindow (hwnd AS LONG,x AS LONG,y AS LONG,nWidth AS LONG,nHeight AS LONG,bRepaint AS LONG) AS LONG

MDI_RegisterClass (pcWndClassEx AS MDI_CLASS) AS LONG

MDI_SendMessage (hwnd As Long, wMsg As Long, wParam As Long, lParam As Long) As Long

MDI_SetClassLong (hwnd As Long,nIndex As Long,dwNewLong As Long) As Long

MDI_SetFocus (hwnd AS LONG) AS LONG

MDI_SetLong (hwnd AS LONG,nIndex AS LONG,dwNewLong AS LONG) AS LONG

MDI_SetParent (hWndChild As Long,hWndNewParent As Long) As Long

MDI_SetProp (hwnd AS LONG,lpString AS STRING,hData AS LONG) AS LONG

MDI_SetText (hWnd AS LONG,lpString AS STRING) AS LONG

MDI_ShowWindow (hwnd As Long,nCmdShow As Long) As Long

MDI_isIconic (hwnd As Long) As Long

MDI_isZoomed (hwnd As Long) As Long

ModifyMenu (hMenu AS LONG,uPosition AS LONG,uFlags AS LONG,uIDNewItem AS LONG,lpNewItem AS LONG) AS LONG

mouse_event (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)

MoveToEx (hdc As Long,x As Long,y As Long, lpPoint As long) As Long

MoveWindow (hwnd AS LONG,x AS LONG,y AS LONG,nWidth AS LONG,nHeight AS LONG,bRepaint AS LONG) AS LONG

PatBlt (hdc As Long,x As Long,y As Long,nWidth As Long,nHeight As Long,dwRop As Long) As Long

PurgeComm (hFile AS LONG, dwFlags AS DWORD) AS LONG 'If function succeeds, returns non-zero. If function fails, returns 0.

ReadFile (hFile AS LONG, BYREF lpBuffer AS STRING, nNumberOfBytesToRead AS DWORD, BYREF lpNumberOfBytesRead AS DWORD, lpOverlapped AS OVERLAPPED) AS LONG 'If function succeeds, returns non-zero. If function fails, returns 0.

ReadFileEx (BYVAL hFile AS LONG, BYREF lpBuffer AS STRING, BYVAL nNumberOfBytesToRead AS DWORD, lpOverlapped AS OVERLAPPED,_ '[IN] Pointer to structure containing info if Comm device/file was opened in Overlapped mode.

Rectangle (hdc As Long,X1 As Long,Y1 As Long,X2 As Long,Y2 As Long) As Long

RegisterClassEx (pcWndClassEx AS WNDCLASSEX) AS LONG

ReleaseCapture () AS LONG

ReleaseDC (ByVal hwnd AS LONG, ByVal hdc AS LONG) AS LONG

RemoveProp (ByVal hwnd As Long, ByVal lpString As String) As Long

RoundRect (hdc As Long,X1 As Long,Y1 As Long,X2 As Long,Y2 As Long,X3 As Long,Y3 As Long) As Long

RtlMoveMemory (byref Destination AS LONG, byref Source AS LONG, Length AS LONG)

SLEEP (dwMilliseconds AS DWORD)

SelectObject (hdc As Long,hObject As Long) As Long

SendMessageAPI (hwnd As Long, wMsg As Long, wParam As Long, lParam As Long) As Long

SetActiveWindow (hWnd as integer) as integer

SetBkMode (hdc As Long,nBkMode As Long) As Long

SetCapture (hwnd AS LONG) AS LONG

SetClassLong (hwnd As Long,nIndex As Long,dwNewLong As Long) As Long

SetCommState (hFile AS LONG, lpDCB AS DCB) AS LONG 'If function succeeds, returns non-zero. If function fails, returns 0.

SetCommTimeouts (hFile AS LONG,_ '[IN] Handle to open Comm device

SetCursorPos (ByVal x As Long, ByVal y As Long) As Long

SetFocus (hwnd AS LONG) AS LONG

SetForegroundWindow (ByVal hwnd As Long) As Long

SetParent (hWndChild As Long,hWndNewParent As Long) As Long

SetPriorityClass (ByVal hProcess As Long, ByVal dwPriorityClass As Long) As Long

SetProp (ByVal hwnd As Long, ByVal lpString As String, ByVal hData As Long) As Long

SetROP2 (hdc As Long,nDrawMode As long) As Long

SetSuspendState (ByVal Hibernate As Long, ByVal ForceCritical As Long, ByVal DisableWakeEvent As Long) As Long

SetSystemPowerState (ByVal fSuspend As Long, ByVal fForce As Long) As Long

SetWindowLong (hWnd AS LONG,nIndex AS LONG, dwNewLong AS LONG) AS LONG

SetWindowPos (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal X As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long)

SetWindowText (ByVal hwnd As Long, ByVal lpString As String) As Long

SetupComm (hFile AS LONG,_ '[IN] Handle to open Comm device

ShellExecute (ByVal hwnd AS LONG, ByVal lpOperation AS STRING, ByVal lpFile AS STRING, ByVal lpParameters AS STRING, ByVal lpDirectory AS STRING, ByVal nShowCmd AS LONG) AS LONG

Shell_NotifyIcon (ByVal dwMessage As Long, lpData As QNOTIFYICONDATA) As Long

ShowWindow (hwnd As Long,nCmdShow As Long) As Long

StretchBlt (hdc As Long,x As Long,y As Long,nWidth As Long,nHeight As Long,hSrcDC As Long,xSrc As Long,ySrc As Long,nSrcWidth As Long,nSrcHeight As Long,dwRop As Long) As Long

SystemParametersInfo (uAction as Long,uParam as Long,lpvParam as Long,fuWinIni as Long) as Long

WriteFile (hFile AS LONG, lpBuffer AS STRING, nNumberOfBytesToWrite AS DWORD, BYREF lpNumberOfBytesWritten AS DWORD, lpOverlapped AS OVERLAPPED) AS LONG 'If function succeeds, returns non-zero. If function fails, returns 0.


Email

' eMail.Inc
' ==========
' Usage:
' ReturnCode& = eMail ( Recipients$, Subject$, Message$, Attachments$ )
'
' Recipients$ > Multiple recipients separated by ';', Name and address by ':'
' To sent a CC precede the name by '>'
' To sent a BCC precede the name by '<'
' Attachments$ > Multiple attachments separated by ';'
'
' Examples:
' eMRetCode& = (":me@myserver.com", "eMail.inc", "Does it work ?", "c:\autoexec.bat")
' eMRetCode& = ("You:you@ys.net;>Me:me@myserver.com", "CcTest", "", "")


Evaluate

'Math-Expression Evaluator
'Updated: Sept. 10, 2001
'This source code is simply extracted (with minor modifications) from the source code of QEDTukak 1.52
'originally written by Achilles B.Mina.
'
'You can use this file as a module in your program for the evaluation of
'user-entered mathematical expressions (like i.e. sin(.1)^2-3e2*ln(tan(.1*PI))).
'Simply call the function "EvaluateExpression(MathString$, DRGMode)" from your main program:
'MathString$ is the string to be evaluated (passed BYREF)
'DRGMode=0 for deg, DRGMode=1 for rad, DRGMode=2 for grad
'The global variable "EvaluateErrorFlag" can be used for error checking
'Have a look at eval_tst.qb as a simple example)


FtiQuery

' Warranties: None. This code is provided AS-IS.
' Developed on the Windows 98 SE platform.
' Version: 1.6.1!
'
' Dependencies:
' ftiExtractFileName
' ftiExtractProgNane
' ftiExtractProgPath
'
' Description:
' A cool include file that uses the registry to retrieve information on
'any file extension/type!

'Several constants have been defined that are used to retrieve this
'information, they are:

'
' Note(s):
' I'm going to try to put some of the code that reads the registry into
' a function, to reduce the file size.
'
' ftiClassName:
' queries the class name of the specified filetype
'
' ftiDefCommand:
' queries the value of the "shell/open/command" sub key
' of the parent program (module), the default command
'
' ftiContentType:
' queries the content type of the specified file type
'
' ftiQueryDefault:
' queries the integrity of the registered file extension
' (helps to see if there are any errors in the registry ;) )
'
' ftiProgramCommand:
' queries the parent (module) of the specified file type
'
' ftiDefaultIcon:
' queries the icon for the specified file type
'
' New updates:
'*****************************
' ftiProgramName:
' gets the actual file name of the parent of the specified file type
'
' ftiProgramExt:
' Gets the extension of the parent program. Later on I want to enable
' queries for the file extension.
'
' ftiProgramPath:
' Gets the actual program path.
'
' ** end of description *******************************************
' Special precautions:
' Whatever you do, DON'T turn the $escapechars preprocessor
' directive ON! Doing so may result in incorrect registry
' settings, and/or may cause Windows to CRASH (not being able to boot
' up Windows sounds about right).
'
' When you enter the first string argument of the GetFileTypeInfo function,
' make sure that you do not have 2 or more forward/backward slashes beside each other.
' Instead, enter the first argument like this: "C:/blah/files";
' not like this: "C:///blah//files".
'
' Of course, you wouldn't actually have paths like that,
' that is, unless Windows was playing dominoes with your ASCII character set at the time :P
'
' Known bugs:
' None actually, unless you consider the forward/backward slash problem a bug ;)
' You should be fine if you just obey the special rule.
'
' Usage:
'
' function:
' GetFileTypeInfo(FileType, ftiQueryValue)
'
' FileType: string
' ftiQueryValue: integer
'
' FileType can be a file extension, file name, path and file name,
' or even a dot with a file extension; basically anything as long as
' you obey the special rule defined in the Special precautions
' section. I'm trying to fix this =)
'
' ftiQueryValue is any of the several constants defined in the
' Description section.
'
' If an error occurs in reading the registry, GetFileTypeInfo will return -1.
' If you get a return value of one, that value is TRUE.
' If you get a return value of zero, that value is FALSE.


Новая страница 1

' Simple Syntax Hilighting example for Rapid-Q by William Yu
'
' QREdit - Extension of QRichEdit with automatic syntax hilighting
' Not very complete, but you can handle all the special cases.
'
' NEW PROPERTIES:
' HiLighColor - Color to use for hilighting keywords
'
' NEW METHODS:
' AddSyntaxes - Add any keywords you want hilighted
' HiLight - Call first time whenever you load a file, or add new lines
'
' There are actually 2 separate ways of doing this, the hard way, and the
' easy way. The hard way is to learn RTF and create your own RTF document
' programmically. It's definitely more work than the easy way, which I'll
' demonstrate in this example.
' I've decided to incorporate this into a component for easy reuse.


QLZFileStream component for Rapid-Q

QLZFileStream component, version 1.0.0
Copyright © 2001 Pavel "EvilOne" Minayev

General info

Class name: QLZFileStream

Base class: QObject

Description:

QLZFileStream component allows you to work with files compressed with Microsoft COMPRESS.EXE utility (included in this package) - the one that was used to compress MS-DOS 6.22 and Windows 3.1 distributives, replacing last character of file with underscore. Main advantage of this library is that it makes it possible to work with compressed files as if they were uncompressed and read-only; in other words, you can read arbitrary blocks of data from file, move file pointer to anywhere you want... The component was written to mimic QFileStream interface as close as possible, but due to limitations of Rapid-Q the match is not absolute. Anyhow, properties and methods provided by the component are enough to do whatever you could do with QFileStream. Besides, I think that you'll prefer some changed things over those seen in QFileStream (like new Read syntax).

Properties:
  • EOF
  • Handle
  • Position
  • Size

Methods:
  • Close
  • Open
  • Read
  • Read%
  • Read&
  • Read?
  • Read??
  • Read!
  • Read#
  • Read$
  • ReadBinStr
  • ReadLine
  • ReadNum
  • ReadStr
  • Seek

Properties

EOF

Definition: EOF AS LONG

Access: read-only

Description:

Contains 0 if file pointer is at the very end of file, non-zero value otherwise.

Handle

Definition: Handle AS LONG

Access: read-only

Description:

Contains file handle returned by LZOpenFile function; can be used with LZ* family of Win32 API functions.

Position

Definition: Position AS LONG

Access: read/write

Description:

Contains opened file pointer position, counting from beginning of file. Assigning a new value to property will change the position.

Size

Definition: Position AS LONG

Access: read-only

Description:

Contains opened file size.

Methods

Close

Definition: SUB Close

Description:

Closes previously opened file.

Open

Definition: FUNCTION Open(FileName AS STRING) AS LONG

Description:

Opens the file FileName. File is always opened for reading only. If operation is successful, non-zero value is returned. If an error occures (for example, if file wasn't found), the result is 0.

Read

Definition: FUNCTION Read(Buffer AS LONG, Count AS LONG) AS LONG

Description:

Reads Count bytes from file into memory location pointed by Buffer. You may use VARPTR to get the address of variable to read into it. This function is the only way to read UDTs, because ReadUDT is not supported. The return value is the number of bytes actually read, or 0 at end of file.

Read%

Definition: FUNCTION Read% AS SHORT

Description:

Reads a SHORT (2-byte signed integer) value from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

Read&

Definition: FUNCTION Read& AS LONG

Description:

Reads a LONG (4-byte signed integer) value from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

Read?

Definition: FUNCTION Read? AS BYTE

Description:

Reads a BYTE (single-byte unsigned integer) value from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

Read??

Definition: FUNCTION Read?? AS WORD

Description:

Reads a WORD (2-byte unsigned integer) value from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

Read!

Definition: FUNCTION Read! AS SINGLE

Description:

Reads a SINGLE (4-byte floating-point) value from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

Read#

Definition: FUNCTION Read# AS DOUBLE

Description:

Reads a DOUBLE (8-byte floating-point) value from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

Read$

Definition: FUNCTION Read$(Length AS LONG) AS STRING

Description:

Reads a string of length Length from file and returns it. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

ReadBinStr

Definition: FUNCTION ReadBinStr(Length AS LONG) AS STRING

Description:

The same as Read$ method. Provided for compatibility with QFileStream.

ReadLine

Definition: FUNCTION ReadLine AS STRING

Description:
Reads a line from file and returnes. The lines are supposed to be terminated either by CR/LF pair or by single LF - thus, files where lines are separated by single CR cannot be read with this function. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function.

ReadNum

Definition: FUNCTION ReadNum(Num AS LONG) AS DOUBLE

Description:
Reads a number from file and returns it; actual number of bytes read depends on the value of Num, which can be Num_SHORT, Num_LONG, Num_BYTE, Num_WORD, Num_SINGLE or Num_DOUBLE. The names are self- explanatory. There is no way to check if operation was successful; if you want to be sure, check EOF property every time before using this function. This function is provided for compatibility with QFileStream only, it's recommended that you use the Read* family of functions instead.

ReadStr

Definition: FUNCTION ReadStr(Length AS LONG) AS STRING

Description:

The same as Read$ method. Provided for compatibility with QFileStream.

Seek

Definition: SUB Seek(Offset AS LONG, From AS LONG)

Description:

Moves file pointer to position Offset, counting from beginning of file if From equals soFromBeginning, from end of file if From equals soFromEnd, or from current position if From equals soFromCurrent. In last two cases, negative offsets are allowed.


QAnim

Documentation component by D.Glodt (c)2003 Appendix A: QAnim

QAnim Component

QAnim is component of animation inherited from QImage component.
Dimensions Width and Height must be fixed and identical to dimensions of the images.

QAnim Properties
Field | Type | R/W | Default
Width | SHORT | R/W |
Height | SHORT | R/W |
Left | SHORT | R/W |
Top | SHORT | R/W |
Visible | INTEGER | R/W | False
ImageList | QIMAGELIST | R/W |
 | images for animation |  |
Index | SHORT | R/W | 0
 | Index image and show image |  |
BackColor | LONG | R/W |
 | Backcolor used for images if use image mask |  |
Masked | BOOLEAN | R/W | False
 | Use image mask |  |
Move | BOOLEAN | R/W | False
 | Start/Stop animation |  |

QAnim Methods
Method | Type | Description | Params

QAnim Events
Event | Type | Occurs when... | Params

QAnim Example
$TypeCheck on
$include "rapidq.inc"
$include "Object/QAnim.inc"
$resource img1 as "earthspn_frame_000.bmp"
$resource img2 as "earthspn_frame_001.bmp"
$resource img3 as "earthspn_frame_002.bmp"
$resource img4 as "earthspn_frame_003.bmp"
$resource img5 as "earthspn_frame_004.bmp"
$resource img6 as "earthspn_frame_005.bmp"
$resource img7 as "earthspn_frame_006.bmp"
$resource img8 as "earthspn_frame_007.bmp"
$resource img9 as "earthspn_frame_008.bmp"
$resource img10 as "earthspn_frame_009.bmp"

declare sub anim
declare sub opaque
declare sub transparent
declare sub close

CREATE Form AS QFORM
Caption = "Form1"
Width = 220
Height = 170
Center
OnClose=close
CREATE bt1 as QBUTTON
caption="Opaque"
left=120
top=10
OnClick=Opaque
END CREATE
CREATE bt2 as QBUTTON
caption="Transparent"
left=120
top=40
OnClick=Transparent
END CREATE
CREATE bt3 as QBUTTON
caption="Start/Stop"
left=120
top=70
OnClick=Anim
END CREATE
CREATE Image1 AS QAnim
Left=10
Top=10
width=96
height=96
BackColor=&hff0000
Masked=true
Imagelist.AddBMPhandle img1, &h0
Imagelist.AddBMPhandle img2, &h0
Imagelist.AddBMPhandle img3, &h0
Imagelist.AddBMPhandle img4, &h0
Imagelist.AddBMPhandle img5, &h0
Imagelist.AddBMPhandle img6, &h0
Imagelist.AddBMPhandle img7, &h0
Imagelist.AddBMPhandle img8, &h0
Imagelist.AddBMPhandle img9, &h0
Imagelist.AddBMPhandle img10, &h0
speed=100
index=0
END CREATE
END CREATE
Form.ShowModal

sub anim
if Image1.move then
Image1.Move=false
else
Image1.Move=true
end if
end sub

sub opaque
Image1.BackColor=&haa0000
end sub

sub transparent
Image1.BackColor=form.color
end sub

sub close
Image1.Move=false
application.terminate
end sub


QPANEL

based on Rapid-Q Documentation by William Yu (c)1999 Custom components: QBEVEL

QBevel Component

Qbevel implements a generic container for your components.

This component duplicates the Delphi TBevel.
' Not an entirely revolutionary thing, but as with most of my components, something to save
' time and coding. Play around with the combo boxes to see the effects. Rather simple
' actually, only two new properties: Shape and Style. I think you'll find them pretty self- explanatory...
' psyclops420 <psyclops420@yahoo.com>

QBevel Properties (QBEVEL EXTENDS QPANEL)

Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Alignment | INTEGER | RW | taCenter | W
'Style
CONST bsLowered = 0
CONST bsRaised = 1
'Shape'
CONST bsSpacer = 0
CONST bsBox = 1
CONST bsTopLine = 2
CONST bsBottomLine = 3
CONST bsLeftLine = 4
CONST bsRightLine = 5
CONST bsFrame = 6
BevelInner | INTEGER | RW | bvNone | W
BevelOuter | INTEGER | RW | bvRaised | W
BevelWidth | INTEGER | RW | 1 | W
BorderStyle | INTEGER | RW | bsNone | W
'-- Bevel Style
CONST bvNone = 0
CONST bvLowered = 1
CONST bvRaised = 2

'-- Bevel Border
CONST bpNone = 0 '-- No visible border
CONST bpSingle = 1 '-- Single-line border
Caption | STRING | RW | W
ClientHeight | INTEGER | RW | WX
ClientWidth | INTEGER | RW | WX
Color | INTEGER | RW | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WX
Font | QFONT | W | W
Height | INTEGER | RW | WX
Hint | STRING | RW | W
Left | INTEGER | RW | 0 | WX
Parent | QFORM/Qbevel/QTABCONTROL | W | WX
ShowHint | INTEGER | RW | False | W
TabOrder | INTEGER | RW | W
Tag | INTEGER | RW | WXG
Top | INTEGER | RW | 0 | WX
Width | INTEGER | RW | WX
Visible | INTEGER | RW | True | WX

Qbevel Methods
Method | Type | Description | Params | Support
Repaint | SUB | Refreshes panel and all contents | 0 | W

Qbevel Events
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on open area of panel | 0 | WX
OnDblClick | VOID | User double clicked panel | 0 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | W
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves over panel | 3 | W
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | W

Qbevel Examples

'=================================================
'        Sample program
'=================================================

DECLARE SUB ChangeStyle
DECLARE SUB ChangeShape

CREATE Form AS QFORM
    CREATE Menu AS QMAINMENU
        CREATE Item AS QMENUITEM
            Caption = "Menu"
        END CREATE
    END CREATE
    CREATE ToolBar AS QBEVEL
        Align = 1
        Height = 50
        Shape = bsTopLine
        Caption = "ToolBar"
    END CREATE
    CREATE Bevel AS QBEVEL
        Top = 80
        Left = 30
        Width = 130
        Height = 30
        color=&h0000ff
        font.color=&hffffff
        caption="Bevel"
        BevelWidth=9
    END CREATE
    CREATE Style AS QCOMBOBOX
        Top = 150
        Left = 10
        AddItems "bsLowered", "bsRaised"
        ItemIndex = 0
        OnChange = ChangeStyle
    END CREATE
    CREATE Shape AS QCOMBOBOX
        Top = 150
        Left = 160
        AddItems "bsSpacer", "bsBox", "bsTopLine", "bsBottomLine", "bsLeftLine", "bsRightLine", "bsFrame"
        ItemIndex = 0
        OnChange = ChangeShape
    END CREATE
END CREATE

Form.ShowModal

SUB ChangeStyle
    Bevel.Style = Style.ItemIndex
END SUB

SUB ChangeShape
    Bevel.Shape = Shape.ItemIndex
END SUB


QCDAUDIO

Documentation component by D.Glodt (c)2000-2001 Appendix A: QCDAUDIO

QCDAUDIO Component

QCDAUDIO is a media component used for read cd audio.

QCDAUDIO Properties
Field | Type | R\W | Default
Timer | QTIMER | RW |
 | Control the fréquency of the évent OnChange.
Time | STRING | R |
 | Time of cd.
TrackTime | STRING | R |
 | Time of songs.
TrackNumber | INTEGER | R |
 | Number of song from cd.
TimePosition | STRING | R |
 | Position tmsf(track,minutes,seconds,frame) of cd.
State | INTEGER | R | CD_CLOSE
 | State of cd,can be CD_PLAY,CD_PAUSE,CD_STOP.
AudioOpen | Boolean | R | FALSE
 | cd open.
Present | Boolean | R | FALSE
 | State cd present.
CurrentTrack | INTEGER | RW |
 | current song.
Error | STRING | R |
 | Text error if OPEN méthod return FALSE |  |

QCDAUDIO Methods
Method | Type | Description | Params
Open | FUNCTION | Open cd audio, return TRUE if no error | 0
Close | SUB | Close cd audio | 0
Play | SUB | Play cd audio | 0
Stop | SUB | Stop cd audio | 0
Pause | SUB | Set cd audio to mode pause | 0
Eject | SUB | Eject cd audio | 0

QCDAUDIO Events
Event | Type | Occurs when... | Params
OnChange | (track as integer,time as string) | position cd during play mode | 2

QCDAUDIO Examples

'**************************************************************************
'* application:player cd                                                  *
'* auteur:D.Glodt                                                         *
'* date:7-4-2001                                                          *
'**************************************************************************
$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\Qcdaudio.inc"

$RESOURCE PLAYBMP as "play.bmp"
$RESOURCE STOPBMP as "Stop.bmp"
$RESOURCE PAUSEBMP as "Pause.bmp"
$RESOURCE BACKBMP as "back.bmp"
$RESOURCE FORWARDBMP as "forward.bmp"
$RESOURCE EJECTBMP as "eject.bmp"
$RESOURCE CDICO as "cdaudio.ico"

Declare Sub Play
Declare Sub Stop
Declare Sub Pause
Declare Sub Back
Declare Sub Forward
Declare Sub Eject
Declare Sub Open
Declare Sub Close
Declare Sub Quitter
Declare Sub PostimerOnTimer(track as integer,time as string)

Dim cd as Qcdaudio
cd.OnChange=PostimerOnTimer
cd.timer.interval=200

CREATE Form AS QFORM
    Caption="CD Audio"
    Width=288
    Height=110
    Center
    BorderStyle=bsSingle
    icoHandle=CDICO
    OnClose=Quitter
    OnShow=Open
    CREATE Panel1 AS QPANEL
        Left=0
        Top=0
        Width=281
        Height=80
        BevelOuter=bvNone
        CREATE BtPlay AS QCOOLBTN
            BMPHandle=PLAYBMP
            Left=8
            Top=6
            Width=28
            Height=28
            Flat=true
            Hint="Play"
            ShowHint=true
            GroupIndex=1

            OnClick=Play
        END CREATE
        CREATE BtStop AS QCOOLBTN
            BMPHandle=STOPBMP
            Left=46
            Top=6
            Width=28
            Height=28
            Down=true
            Flat=true
            Hint="Stop"
            ShowHint=true
            GroupIndex=1
            OnClick=Stop
        END CREATE
        CREATE BtPause AS QCOOLBTN
            BMPHandle=PAUSEBMP
            Left=84
            Top=6
            Width=28
            Height=28
            Flat=true
            GroupIndex=1
            Hint="Pause"
            ShowHint=true
            OnClick=Pause
        END CREATE
        CREATE BtBack AS QCOOLBTN
            BMPHandle=BACKBMP
            Left=114
            Top=6
            Width=28
            Height=28
            Flat=true
            GroupIndex=0
            Hint="Back"
            ShowHint=true
            OnClick=Back
        END CREATE
        CREATE BtForward AS QCOOLBTN
            BMPHandle=FORWARDBMP
            Left=144
            Top=6
            Width=28
            Height=28
            Flat=true
            GroupIndex=0
            Hint="Forward"
            ShowHint=true
            OnClick=Forward
        END CREATE
        CREATE BtEject AS QCOOLBTN
            BMPHandle=EJECTBMP
            Left=174
            Top=6
            Width=28
            Height=28
            Flat=true
            GroupIndex=0
            Hint="Eject"
            ShowHint=true
            OnClick=Eject
        END CREATE
        CREATE Infos AS QSTATUSBAR
          AddPanels "Track:",""
          Panel(0).width=100
        END CREATE
    END CREATE
END CREATE

Form.ShowModal

Sub Open
  if cd.open then
    infos.panel(0).caption="Track:"+str$(cd.tracknumber)
    infos.panel(1).caption=cd.time
  end if
End Sub

Sub Close
  cd.close
End Sub

Sub Play
  if cd.audioOpen=false then
    if cd.open then
      infos.panel(0).caption="Track:"+str$(cd.tracknumber)
      infos.panel(1).caption=cd.time
    else
      btStop.down=true
    end if
  end if
  cd.play
End Sub

Sub Stop
  cd.stop
End Sub

Sub Pause
  cd.pause
End Sub

Sub Back
  cd.currentTrack=cd.currentTrack-1
  infos.panel(0).caption="Track:"+str$(cd.currentTrack)
  infos.panel(1).caption=cd.tracktime
  if cd.state=CD_PLAY then cd.play
End Sub

Sub Forward
  cd.currentTrack=cd.currentTrack+1
  infos.panel(0).caption="Track:"+str$(cd.currentTrack)
  infos.panel(1).caption=cd.tracktime
  if cd.state=CD_PLAY then cd.play
End Sub

Sub Eject
  cd.eject
  btStop.down=true
End Sub

Sub PostimerOnTimer(track as integer,time as string)
  infos.panel(0).caption="Track:"+str$(track)
  infos.panel(1).caption=time
  if cd.state=CD_STOP then
    btStop.down=true
  end if
End Sub

Sub Quitter
  cd.close
  form.close
End Sub


QCGI

QCGI.INC
(c) 2001-2002 Chris Warrington
rapidq.basic.c45207@spamgourmet.com

** CGI is a program that you write. When the program receives a request by checking environment variables (i.e., by checking QUERY_STRING) the program generates html code and forms to be produced on the clients web browswer. **

Version: 1.6
Date: 2005-FEB-22

========
License ]
========
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

A copy of GNU General Public License can be found in the file gpl.txt,
included in the archive.

The GNU General Public License allows you to USE this library in any of your programs,
but you MUST release the source code. If you modify this library, those changes must also
be released. Be sure to see gpl.txt for the legal mumbo-jumbo.

====
Use ]
====
This file, unlike CGI_NEW.INC, is an object implementation of a CGI interface.
There are two sample scripts included with QCGI, "info.rqb" and "cgi_test.rqb".

QCGI Properties
---------------
The following read/write properties control how QCGI processes input. They should
be set before Parse or Get is called for the first time.

AutoConvert AS INTEGER (Default = 1)
If this is set to 1, QCGI will convert %xx tokens into their respective
characters.
MaxInput AS INTEGER (Default = 32767)
Determines how many characters QCGI will process

The following read-only properties allow you to access CGI environmental
variables.

Accept AS STRING
AuthType AS STRING
ContentLength AS INTEGER
ContentType AS STRING
Cookie AS STRING
GatewayInterface AS STRING
PathInfo AS STRING
PathTranslated AS STRING
Referer AS STRING
RemoteAddr AS STRING
RemoteHost AS STRING
RemoteIdent AS STRING
RemoteUser AS STRING
RequestMethod AS STRING
ScriptName AS STRING
ServerSoftware AS STRING
ServerName AS STRING
ServerPort AS INTEGER
ServerProtocol AS STRING
UserAgent AS STRING

QCGI Methods
------------
Parse()
Parses the input into name/value pairs
Get(name AS STRING, BYREF value AS STRING) AS INTEGER
Stores the value of the name/value pair "name" in "value". If Parse() has
not been called, it will call Parse(). If "name" is found, the return is 1; if not,
the return is 0. If "name" is not found, "value" is not modified.

========
Contact ]
========
If you find any bugs, need help, or have any suggestions, please e-mail me at
rapidq.basic.c45207@spamgourmet.com


Appendix A: QCHART

QChart Documentation by Michael Zito (c) 2003-2004
         Appendix A: QChart

QChart Component

=============================================================================================
                           QChart:  A Charting Class for Rapid-Q
                          Copyright (c) 2003-2004  Michael J. Zito
                              Released under the LPGL License
=============================================================================================

QChart provides a rich set of 2-D charting routines for Rapid-Q programmers.
It generates histograms, bar charts, XY-scatter plots, line graphs, pie charts
and box plots.  Each charting routine will calculate an appropriate scale and plot
the data contained in the .Data or .XYData property of the object.  The user may
optionally specify the scaling as well as fonts, grids or other properties
(see code and HTML documentation). Once the data is formatted graphs can be called
with a few lines of simple code.

----> To create an instance and call QChart:

                $INCLUDE "QChart.inc"
                CREATE YourInstanceName AS QChart
                  Parent = QForm, QTabControl or QPanel
                  Set any other desired properties of a QCanvas
                END CREATE
                WITH YourInstanceName
                   .Initialize
                   .ChartType = ctXXXX
                   .ChartStyle = csXXXX
              ---->Change Any Desired Properties (See code or HTML Documentation)
              ---->REDIM .Data array property (See below)
              ---->Load Data Into .LabelList, .LegendList and .Data Array
                   .DrawChart (Overlay T or F)
                END WITH

NOTE: There is little error checking in this class.  It is up to the user
      to insure that the data is formatted properly before calling each routine.

LegendList and LabelList are implemented as QStringLists.
     *Use the .AddItems Method of each property to add text to the lists.
     *LegendList contains legend text and usually refers to the Cols (i.e. Series)
     *LabelList contains text used to label the X Axis and usually refers to Rows
      (i.e. Categories).  LabelList items are NOT USED by XY Charts

The .Data property is a 2 dimensional array of DOUBLE which must be REDIMd by the user
    prior to filling the grid with data.  The first dim is Cols and the second is Rows.
    Each Col represents a series to be plotted.  The Rows represent the data values
    within each series. Use the .Data property for all charts EXCEPT XY Charts.

XY Charts have their own data array.
    The .XYData property is a 3 dimensional array of DOUBLE. The first dim is Cols
    and the second is Rows. The third dim is ALWAYS 2. Each Col represents a series
    to be plotted. The Rows represent the number of XY data pairs within each
    series. The third dimension refers to the X and Y data values for each
    point to be plotted: 1 = X and 2 = Y values

----> To REDIM the .Data or .XYData array property:

You MUST set the .Cols and .Rows properties before calling QChart.  These values are used
throughout the QChart class as loop counters. Set .Cols to number of series to be plotted
and set .Rows to number of values in each series. REDIM the array using .Cols and .Rows.

NOTE:  To REDIM you MUST EXPLICITLY REFERENCE your QChart instance by name (even inside a
       WITH block) or RapidQ will not find and REDIM the array.  (A RapidQuirk?!?)
          WITH YourInstanceName
            .Cols = 2                                     <-- Num series
            .Rows = 2                                     <-- Num values in each series
            REDIM YourInstanceName.Data(.Cols, .Rows)     <-- for all EXCEPT XY Charts
            REDIM YourInstanceName.XYData(.Cols, .Rows, 2)<-- for XY Charts
          END WITH

   ----> Sample Data Formats (given the DIMs above):

              XY Charts                                All Other Charts
         =====================                         ================
         Series  NumPts Values                          Series  Values
         (Col)   (Row)  (dim 3)                         (Col)   (Row)
           1       1      1 <-- X                         1     val 11
           1       1      2 <-- Y                         1     val 12
           1       2      1                               2     val 21
           1       2      2                               2     val 22
           2       1      1
           2       1      2
           2       2      1
           2       2      2

   Box Plots         HiLo Plots        Pie Charts      BarLine Plots
  (5 rows only)     (3 rows only)     (1 Col only)     (2 Cols only)
================  =================  ==============   ===============
 Row  1 = Max      Row   1 = Hi        Col     Row     Col 1    Col 2
      2 = Q3             2 = Close    =====   =====    =====    =====
      3 = Median         3 = Lo         1       1       Bar      Line
      4 = Q1                            1       2       Data     Data
      5 = Min                           1       n

See QChartEx.rqb for more examples of setting up and calling each chart type.
See QChart.inc for named CONSTs used for ChartType, ChartStyle, HatchStyle and LineStyle

QChart Properties (Inherited from QCanvas)
Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
ClientHeight INTEGER RW
W
ClientWidth INTEGER RW
W
Color INTEGER RW
WXG
CopyMode | INTEGER | RW | cmBlackness | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WXG
Font QFONT W
W
Height INTEGER RW
WXG
Hint STRING RW
W
Left | INTEGER | RW | 0 | WXG
Parent QFORM/QPANEL/QTABCONTROL W
WXG
Pixel 2D ARRAY of INTEGER RW
WXG
PopupMenu QPOPUPMENU W
W
ShowHint | INTEGER | RW | False | W
Tag INTEGER RW
WXG
Top | INTEGER | RW | 0 | WXG
Width INTEGER RW
WXG
Visible | INTEGER | RW | True | WXG

QChart Specific Properties
Field Type Description RW Default
AxisBorder
         BYTE
Draws border around plot
RW
True
ChartBorder
BYTE Draws border around entire chart RW True
Colors()
ARRAY of LONG
Array of predefined colors
RW
bgColor
LONG
Chart background color
RW
fgColor
LONG Chart foreground color RW
PlotAreaColor
LONG Color of plot area
RW
GridColor
LONG Color of gridlines
RW
BW
BYTE Plots in Black and White
RW False
GreyScale
BYTE Plots in GreyScale RW False
DoLegend
BYTE Draw a legend to right of chart
RW True
MarkerSize
SINGLE
Size of markers for XY and Line charts
RW 3
Viewport
INTEGER
Specifies Viewport width for Real Time Graphs
RW 100
ChartType
INTEGER
Sets type of Chart to plot
RW ctXY

ctBar, ctLine, ctXY, ctPie, ctHiLo, ctBox, ctBarLine, ctReal

ChartStyle
INTEGER Sets style of Chart Type to plot
RW csPoints

Bar           Line and XY      Pie        HiLo
==================================================
csBar          csPoints     csPisPct    csAntenna
csHisto        csLines      csPieVal    csHiLoBox
csStacked      csBoth
csPctStacked
Missing
DOUBLE
Value used to represent missing data
RW -9.999E-45
Data
2D ARRAY of DOUBLE
Data used in plotting all Charts EXCEPT XY
RW

Series   Values
(Col)    (Row)
  1      val 11
  1      val 12
  2      val 21
  2      val 22
XYData
3D ARRAY of DOUBLE Data used to plot XY Charts ONLY
RW

Series  NumPts Values
(Col)   (Row)  (dim 3)
  1       1       1 <-- X
  1       1       2 <-- Y
  1       2       1
  1       2       2
  2       1       1
  2       1       2
  2       2       1
  2       2       2
Cols
INTEGER
Number of series to plot
RW 1
Rows
INTEGER
Number of data values in each series
RW 1

To REDIM the .Data or .XYData array property:

You MUST set the .Cols and .Rows properties before calling QChart. These values are used throughout the QChart class as loop counters. Set .Cols to number of series to be plotted and set .Rows to number of values in each series. REDIM the array using .Cols and .Rows.

NOTE:  To REDIM you MUST EXPLICITLY REFERENCE your QChart instance by name (even inside a WITH block) or RapidQ will not find and REDIM the array.  (A RapidQuirk?!?)

WITH YourInstanceName
  .Cols = 2                                    <-- Num series
  .Rows = 2                                    <-- Num values
   REDIM YourInstanceName.XYData(.Cols, .Rows, 2) <-- XY Only
   REDIM YourInstanceName.Data(.Cols, .Rows)   <-- All Others
END WITH
MainFont
QFONT
Font used to draw the Main Title
RW Times
MainTitle.Text
STRING

RW ""
SubFont
QFONT Font used to draw the Sub Title RW Times
SubTitle.Text
STRING
RW ""
LegendFont
QFONT Font used to draw the Legend RW Times
LegendList
QSTRINGLIST Legend text items; usually one for each series
RW ""

Use the .AddItems Method to add text to the lists.
LegendList contains legend text and usually refers to the Cols
(i.e. Series)
AxisFont
QFONT Font used to draw the Axis Labels RW Times
LabelList
QSTRINGLIST Axis label text items; usually one for each category RW ""

Use the .AddItems Method to add text to the lists.
LabelList contains text used to label the X Axis and usually refers to Rows (i.e. Categories).  LabelList items are NOT USED by XY Charts
XTitle.Text
STRING
RW ""
YTitle.Text
STRING
RW ""
XAxis / YAxis
UDTs (Elements Below)
There is 1 UDT for the XAxis and 1 for the YAxis
RW
.AutoScale
BYTE
QChart scales the axes
RW True
.Color
LONG
Color of axis line
RW
.Div
INTEGER
Number of divisions on the axis
RW 10
.DrawZero
BYTE Draw a zero line if data spans origin
RW True
.ZeroColor
LONG
Color of Zero line
RW
.Grid
BYTE Draw gridlines for the axis
RW True
.Labeled
BYTE Label the axis at tic intervals
RW True
.LogScale
BYTE TRUE = Log Scale, FALSE = Linear Scale
RW False
.Min
DOUBLE
Data Minimum. Must be set if AutoScale = FALSE
RW
.Max
DOUBLE
Data Maximum. Must be set if AutoScale = FALSE RW
.Tics
BYTE Draw tic marks on the axis
RW True
.MnrTics
BYTE Draw minor tic marks on the axis RW True
Series()
UDT ARRAY (Elements Below)
Contains format inforamtion for each series plotted
RW
.AutoColor
BYTE
Cycle through 18 available colors
RW True
.AutoMark
BYTE Cycle through 8 available marker styles RW True
.Color
LONG
Color used in plotting the series
RW
.HatchStyle
LONG Hatch style used in plotting the series RW hsSolid
.LineStyle
LONG Line style used in plotting the series RW lsSolid
.LineWidth
LONG LineWidth used in plotting the series RW 1
.Marker
BYTE
Marker style used in plotting the series RW msFilledCircle

QChart Methods
Method Type Description Params
Initialize
SUB
Sets all values to default
0
ClearAll
         SUB
Clears drawing buffer and paints blank canvas
0
PaintChart
         SUB Draws Chart on Canvas. Assign this method to your OnPaint event 0
DrawChart
SUB (Overlay%) Draws the currently defined chart to screen
1
RedrawChart
SUB
Redraws chart at new size. Call from Resize event
0
CopyToClipboard
SUB (Wid%, Hgt%) Copies at specified width and height
2
SaveChart
SUB (SaveAs%) SaveAs = 0:No dialog if previously saved; 1:Always shows dialog
1
PrintChart
SUB (Prn%, Orient%, Margin%, Copies%, Color%) Uses CopyRect method to print chart. May not work with all printers
5

QChart Events (Inherited from QCanvas)
Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on canvas | 0 | WXG
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WXG
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | WXG
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WXG
OnPaint | VOID | Receives WM_PAINT message | 0 | WXG

QChart Example

$OPTIMIZE ON
$TYPECHECK ON
$INCLUDE "QChart.inc" '<--- change path to point to file on your system

'----- Form Event SUB Declarations
Declare Sub btnOnClick (SENDER As QBUTTON)
Declare Sub frmMainResize (SENDER As QFORM)
Declare Sub frmMainClose (SENDER As QFORM)

'----- Define the main form
Create frmMain As QFORM
  Center
  Width = 640
  Height = 480
  Caption = "QChart Example"
  OnResize = frmMainResize
  OnClose = frmMainClose
    Create drwBar1 As QBUTTON
      Caption = "Bar Graph"
      OnClick = btnOnClick
    End Create
    Create btnPie As QBUTTON
      Caption = "Pie Chart"
      Top = 25
      OnClick = btnOnClick
    End Create
    Create drwXYboth As QBUTTON
      Caption = "XY Both"
      Top = 50
      OnClick = btnOnClick
    End Create
    Create drwBox As QBUTTON
      Caption = "Box Plot"
      Top = 75
      OnClick = btnOnClick
    End Create
    Create drwHiLo1 As QBUTTON
      Caption = "HLC Style 1"
      Top = 100
      OnClick = btnOnClick
    End Create
    Create Graph As QCHART                        	'Create a copy of the new object
      Align = 4                                   	'alRight
      Width = frmMain.ClientWidth - btnPie.Width
      Height = frmMain.ClientHeight
      OnPaint = Graph.PaintChart                        'This line REQUIRED to process Repaints
    End Create'Graph
End Create'frmMain

Graph.ClearAll
frmMain.Showmodal

Sub btnOnClick (SENDER As QBUTTON)

  Dim i  As Integer                                     'Loop counters...
  Dim j  As Integer
  Dim k  As Single                                      'A Scratch Variable

  Select Case Sender.Caption
    Case "Bar Graph"
      With Graph
        .Initialize                                     'Set defaults
        .ChartType = ctBar                              'Bar Chart
        .ChartStyle = csBar                             'Grouped Bars
        .MainTitle.Text = "Bar Graph Example 1"         'change desired options
        .SubTitle.Text = "Standard Bar Graph"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .Cols = 6                                       '<- Set Num Series
        .Rows = 3                                       '<- Set Num Groups
        REDIM Graph.Data(.Cols,.Rows)                   '<- REDIM the Data Array
        k = 75
        Randomize
        For j = 1 To .Rows                              'Do this outside data loop
          .LabelList.AddItems "Treatment " + Str$(j)    'to avoid duplication of entries
        Next j
        For i = 1 To .Cols        'Load the data
         .LegendList.AddItems "Grp " + Str$(i)
          For j = 1 To .Rows
             .Data(i,j) = Rnd * k
          Next j
        Next i
        .DrawChart (FALSE)                              'Draw it!
      End With

    Case "Pie Chart"
      With Graph
        .Initialize                                     'Always call this first
        .ChartType = ctPie
        .ChartStyle = csPiePct                          'Show % at wedges (csPieVal shows Values)
        .AxisFont.Size = 12
        .LegendFont.Size = 12
        .MainTitle.Text = "Pie Chart"
        .SubTitle.Text = "Click Again For New Data"
        .Cols = 1                                       'Only 1 col for pie data
        .Rows = 6                                       'Set Num data points
        REDIM Graph.Data(.Cols,.Rows)                   'Redim the Data Array
        k = 100                                         'Load the data
        Randomize
        For i = 1 To .Rows
          .Series(i).AutoColor = FALSE
          .Series(i).Color = .Colors(i + 12)
          .LegendList.AddItems "Group " + Str$(i)
          .Data(1,i) = Rnd * k ' * i
        Next
        .DrawChart(FALSE)                               'Always call this last
      End With

    Case "XY Both"
      With Graph
        .Initialize                                     'Set defaults
        .ChartType = ctXY                               'XY Scatter Chart
        .ChartStyle = csBoth                            'Lines and Points
        .MainTitle.Text = "Scatter Plot With Lines"     'change desired options
        .SubTitle.Text = "Double Width Lines"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .MarkerSize = .MarkerSize * 1.5
        .Cols = 3                                       'Number of series
        .Rows = 11                                      'Number of data points per series
        REDIM Graph.XYData(.Cols,.Rows,2)               'Redim XYData.  Note 3rd dim always 2
        k = 132                                         'Load the data
        Randomize
        For i = 1 To .Cols
          .LegendList.AddItems "Group " + Str$(i)
          .Series(i).LineWidth = 2
          For j = 1 To .Rows
            .XYData(i,j,1) = Str$(j)                    'X Values (3rd dim 1)
            .XYData(i,j,2) = Str$(Rnd * k)              'Y Values (3rd dim 2)
          Next j
        Next i
        .DrawChart (FALSE)                              'Draw it!
      End With

    Case "Box Plot"
      With Graph
        .Initialize                                     'Set defaults
        .ChartType = ctBox                              'Box and Whisker Plot
        .MainTitle.Text = "Box and Whisker Plot"        'change desired options
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .XAxis.Grid = FALSE
        .DoLegend = FALSE
        .Cols = 6                                       'Number of series
        .Rows = 5                                       'Always 5 for Box Plots
        REDIM Graph.Data(.Cols,.Rows)                   'Redim the data array
        k = 20                                          'Load the data
        Randomize
        For i = 1 To .Cols                              'for each col
          .Series(i).AutoColor = FALSE
          .Series(i).Color = .Colors(2)
          .LabelList.AddItems "Group " + Str$(i)
          .Data(i , 1) = Str$(Rnd * k + 100)            'Max Values
          .Data(i , 2) = Str$(Rnd * k + 75)             'Q3 Values
          .Data(i , 3) = Str$(Rnd * k + 50)             'Q2 Values
          .Data(i , 4) = Str$(Rnd * k + 25)             'Q1 Values
          .Data(i , 5) = Str$(Rnd * k)                  'Min Values
        Next i
        .DrawChart (FALSE)                              'Draw it!
      End With

    Case "HLC Style 1"
      With Graph
        .Initialize                                     'Set defaults
        .ChartType = ctHiLo                             'Hi-Lo-Close Plot
        .ChartStyle = csAntenna
        .MainTitle.Text = "Hi-Lo-Close Plot"            'change desired options
        .SubTitle.Text = "Antenna Style"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .XAxis.Grid = FALSE
        .Cols = 12                                      'Number of series
        .Rows = 3                                       'Always 3 for HiLo charts
        REDIM Graph.Data(.Cols,.Rows)                   'Redim the data array
        k = 10                                          'Load the data
        Randomize
        For i = 1 To .Cols                              'for each col
          .LabelList.AddItems "Group " + Str$(i)
          .Data(i , 1) = Rnd * k + 100                  'Hi Value
          .Data(i , 2) = Rnd * k + 75                   'Close Value
          .Data(i , 3) = Rnd * k + 50                   'Lo Value
        Next i
        .DrawChart (FALSE)                              'Draw it!
      End With
  End Select
End Sub
'-------------------------------------------------------------------------------------------
Sub frmMainResize (SENDER As QFORM)
  With Graph
    .Width = frmMain.ClientWidth - btnPie.Width       'Calculate new sizes
    .Height = frmMain.ClientHeight
    .RedrawChart                                       'Redraw the QChart Object
  End With
End Sub
'-------------------------------------------------------------------------------------------
Sub frmMainClose (SENDER As QFORM)
  Application.Terminate
End Sub
'-------------------------------------------------------------------------------------------


QChartEx.rqb

'----- Compiler Directives
$OPTIMIZE ON
$TYPECHECK ON

'----- Code modules (Change path to point to the correct directory on your system)
$INCLUDE "QChart.obj"

'----- Form Event SUB Declarations
DECLARE SUB btnOnClick (SENDER AS QButton)
DECLARE SUB frmMainResize (SENDER AS QForm)

'----- API Constants and Functions
CONST GWL_HWNDPARENT = (-8)                         'Minimize to task bar
CONST HWND_DESKTOP = 0
DECLARE FUNCTION SetWindowLong LIB "user32" ALIAS "SetWindowLongA"_
                 (hwnd AS LONG, nIndex AS LONG, dwNewLong AS LONG) AS LONG

'----- Rapid-Q Constants
CONST alRight = 4
CONST poLandscape = 1

CREATE frmMain AS QForm

  Center
  Width = 640
  Height = 480
  Caption = "QChart Example"
  OnResize = frmMainResize

    CREATE drwHisto1 AS QButton
      Caption = "Histogram"
      OnClick = btnOnClick
    END CREATE

    CREATE drwBar1 AS QButton
      Caption = "Bar Graph 1"
      Top = 25
      OnClick = btnOnClick
    END CREATE

    CREATE drwBar2 AS QButton
      Caption = "Bar Graph 2"
      Top = 50
      OnClick = btnOnClick
    END CREATE

    CREATE drwBar3 AS QButton
      Caption = "Bar Graph 3"
      Top = 75
      OnClick = btnOnClick
    END CREATE

    CREATE drwXYpt AS QButton
      Caption = "XY Points"
      Top = 100
      OnClick = btnOnClick
    END CREATE

    CREATE drwXYln AS QButton
      Caption = "XY Lines"
      Top = 125
      OnClick = btnOnClick
    END CREATE

    CREATE drwXYboth AS QButton
      Caption = "XY Both"
      Top = 150
      OnClick = btnOnClick
    END CREATE

    CREATE drwXYlog AS QButton
      Caption = "XY Logs"
      Top = 175
      OnClick = btnOnClick
    END CREATE

    CREATE drwLine AS QButton
      Caption = "Line Graph"
      Top = 200
      OnClick = btnOnClick
    END CREATE

    CREATE drwLinePts AS QButton
      Caption = "Line w/Points"
      Top = 225
      OnClick = btnOnClick
    END CREATE

    CREATE drwBox AS QButton
      Caption = "Box Plot"
      Top = 250
      OnClick = btnOnClick
    END CREATE

    CREATE drwHiLo1 AS QButton
      Caption = "HLC Style 1"
      Top = 275
      OnClick = btnOnClick
    END CREATE

    CREATE drwHiLo2 AS QButton
      Caption = "HLC Style 2"
      Top = 300
      OnClick = btnOnClick
    END CREATE

    CREATE btnRedraw AS QButton
      Caption = "Redraw"
      Top = 325
      OnClick = btnOnClick
    END CREATE

    CREATE btnClear AS QButton
      Caption = "Clear"
      Top = 350
      OnClick = btnOnClick
    END CREATE

    CREATE btnSave AS QButton
      Caption = "Save"
      Top = 375
      OnClick = btnOnClick
    END CREATE

    CREATE btnPrint AS QButton
      Caption = "Print"
      Top = 400
      OnClick = btnOnClick
    END CREATE

    CREATE btnExit AS QButton
      Caption = "Exit"
      Top = 425
      OnClick = btnOnClick
    END CREATE

    CREATE Graph AS QChart                              'Create a copy of the new object
      Align = alRight
      Width = frmMain.ClientWidth - btnClear.Width
      Height = frmMain.ClientHeight
      Image.OnPaint = Graph.ImagePaint                  'This line REQUIRED to process Repaints
    END CREATE'Graph

END CREATE'frmMain

'API Call that lets RapidQ programs minimize to the task bar
setwindowlong(frmMain.handle, GWL_HWNDPARENT, HWND_DESKTOP)
setwindowlong(application.handle, GWL_HWNDPARENT, frmMain.handle)

WITH Graph
  .Initialize                                           'Set default values
  .ClearBuffer                                          'Start with a clean slate
  .ImagePaint                                           'Paint the blank Canvas
END WITH
frmMain.ShowModal

'----- Event SUBs

SUB btnOnClick (SENDER AS QButton)

  DIM i  AS INTEGER                                     'Loop counters...
  DIM j  AS INTEGER
  DIM k  AS SINGLE                                      'A Scratch Variable

  SELECT CASE Sender.Caption

    CASE "Histogram"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Histogram Example"           'Change desired options
        .SubTitle.Text = "No Grid, No Border"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .DoLegend = False
        .AxisBorder = False
        .XAxis.Grid = False
        .YAxis.Grid = False
        .Data.ColCount = 1                              'Set .Data Grid dimensions
        .Data.RowCount = 10
        j = 25                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.RowCount
          .Data.Cell(0,i) = "Class " + STR$(i)
          .Data.Cell(1,i) = STR$(RND * j)
        NEXT i
        .ChartType = ctBar                              'Bar Chart
        .ChartStyle = csHisto                           'Histogram
        .DrawBar (False)                                'Draw it!
      END WITH

    CASE "Bar Graph 1"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Bar Graph Example 1"         'change desired options
        .SubTitle.Text = "Positive Values"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .XAxis.Grid = False
        .Data.ColCount = 5                              'Set .Data Grid dimensions
        .Data.RowCount = 2
        k = 25                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount
          .Data.Cell(i , 0) = STR$(i)                   'Legend in Row 0 of each Col
          FOR j = 1 TO .Data.RowCount
            .Data.Cell(i,j) = STR$(RND * k)
          NEXT j
        NEXT i
        FOR j = 1 TO .Data.RowCount
          .Data.Cell(0,j) = "Treatment " + STR$(j)      'X Labels in Col 0 of each Row
        NEXT j
        .ChartType = ctBar                              'Bar Chart
        .ChartStyle = csBar                             'Grouped Bars
        .DrawBar (False)                                'Draw it!
      END WITH

    CASE "Bar Graph 2"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Bar Graph Example 2"         'change desired options
        .SubTitle.Text = "Negative Values"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .Data.ColCount = 8                              'Set .Data Grid dimensions
        .Data.RowCount = 1
        k = 25                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount
          .Data.Cell(i , 0) = "Group " + STR$(i)        'Legend in Row 0 of each Col
          FOR j = 1 TO .Data.RowCount
            .Data.Cell(i,j) = STR$((RND) * -k)
          NEXT j
        NEXT i
        FOR j = 1 TO .Data.RowCount
          .Data.Cell(0,j) = "Level " + STR$(j)          'X Labels in Col 0 of each Row
        NEXT j
        .ChartType = ctBar                              'Bar Chart
        .ChartStyle = csBar                             'Grouped Bars
        .DrawBar (False)                                'Draw it!
      END WITH

    CASE "Bar Graph 3"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Bar Graph Example 3"         'change desired options
        .SubTitle.Text = "Positive and Negative Values"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .Data.ColCount = 4                              'Set .Data Grid dimensions
        .Data.RowCount = 3
        k = 20                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount
          .Data.Cell(i , 0) = "Long Legend Title " + STR$(i)'Legend in Row 0 of each Col
          FOR j = 1 TO .Data.RowCount
            .Data.Cell(i,j) = STR$((RND - RND) * k)
          NEXT j
        NEXT i
        FOR j = 1 TO .Data.RowCount
          .Data.Cell(0,j) = "Level " + STR$(j)          'X Labels in Col 0 of each Row
        NEXT j
        .ChartType = ctBar                              'Bar Chart
        .ChartStyle = csBar                             'Grouped Bars
        .DrawBar (False)                                'Draw it!
      END WITH

    CASE "XY Points"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Scatter Plot Example"        'change desired options
        .SubTitle.Text = "Data in All Four Quadrants"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .Data.ColCount = 16                             'Set .Data Grid dimensions
        .Data.RowCount = 5
        k = .00100                                    '<-- change k for large and small values
        RANDOMIZE                                       'Load the data
        FOR i = 2 to .Data.ColCount STEP 2              'for each col pair
          .Data.Cell(i , 0) = "Group " + STR$(i \ 2)    'Legend in 2nd Col (Y) of Pair, Row 0
          FOR j = 1 to .Data.RowCount                   'add data to each row
            .Data.Cell(i - 1 , j) = STR$(k * (RND - RND))'X Values in Col 1
            .Data.Cell(i , j) = STR$(k * (RND - RND))   'Y Values in Col 2
          NEXT j
        NEXT i
        .ChartType = ctXY                               'XY Scatter Chart
        .ChartStyle = csPointsOnly                      'Just the Points
        .DrawXY (False)                                 'Draw it!
      END WITH

    CASE "XY Lines"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Two Sine Curves"             'change desired options
        .SubTitle.Text = "Out of Phase"
        .XTitle.Text = "Radians"
        .YTitle.Text = "Sine of X"
        .BW = True
        .YAxis.Div = 6
        .XAxis.AutoScale = False                        'Manually Scale
          .XAxis.Max = 2                                'Set Max Manually
          .XAxis.Min = 0                                'Set Min Manually
        .YAxis.AutoScale = False                        'Manually Scale
          .YAxis.Max = 1.5                              'Set Max Manually
          .YAxis.Min = -1.5                             'Set Min Manually
        .Data.ColCount = 4                              'Set .Data Grid dimensions
        .Data.RowCount = 21                             'Load the data
        FOR i = 2 to .Data.ColCount STEP 2              'for each col pair
          .Data.Cell(i , 0) = "Group " + STR$(i \ 2)    'Legend in 2nd Col of Pair, Row 0
          .Series(i\2).LineStyle = (i\2-1) MOD 5        'Cycle line styles
          FOR j = 1 to .Data.RowCount                   'add data to each row
            .Data.Cell(i - 1 , j) = STR$((j-1)/10)      'X Values in 1st Col of Pair
             k = ((j-1)/10 + [(i-2) * 4.75])* 3.141592
            .Data.Cell(i , j) = STR$(SIN(k))            'Y Values in 2nd Col of Pair
          NEXT j
        NEXT i
        .ChartType = ctXY                               'XY Scatter Chart
        .ChartStyle = csLinesOnly                       'Just the Lines
        .DrawXY (False)                                 'Draw it!
      END WITH

    CASE "XY Both"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Scatter Plot With Lines"     'change desired options
        .SubTitle.Text = "All options set to default"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .Data.ColCount = 4                              'Set .Data Grid dimensions
        .Data.RowCount = 11
        k = 100                                         'Load the data
        RANDOMIZE
        FOR i = 2 to .Data.ColCount STEP 2              'for each col pair
          .Data.Cell(i , 0) = "Group " + STR$(i \ 2)    'Legend in 2nd Col of Pair, Row 0
          FOR j = 1 to .Data.RowCount                   'add data to each row
            .Data.Cell(i - 1 , j) = STR$(j)             'X Values in 1st Col of Pair
            .Data.Cell(i , j) = STR$(RND * k)           'Y Values in 2nd Col of Pair
          NEXT j
        NEXT i
'        .Data.Cell(1,4) = ""                            'Uncomment to see how QChart
'        .Data.Cell(4,8) = ""                            'handles missing data
        .ChartType = ctXY                               'XY Scatter Chart
        .ChartStyle = csBoth                            'Lines and Points
        .DrawXY (True)                                  'Draw it as an Overlay

      END WITH

    CASE "XY Logs"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Log - Log Scaling"           'change desired options
        .SubTitle.Text = "Grid with no Tics"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .YAxis.Tics = False
        .YAxis.LogScale = True
        .XAxis.Tics = False
        .XAxis.LogScale = True
        .DoLegend = False
        .Data.ColCount = 2                              'Set .Data Grid dimensions
        .Data.RowCount = 10
        RANDOMIZE                                       'Load the data
        FOR i = 2 to .Data.ColCount STEP 2              'for each col pair
          .Data.Cell(i , 0) = "Group " + STR$(i \ 2)    'Legend in 2nd Col of Pair, Row 0
          FOR j = 1 to .Data.RowCount                   'add data to each row
            .Data.Cell(i - 1 , j) = STR$(j)             'X Values in 1st Col of Pair
            .Data.Cell(i , j) = STR$(RND * 10^ (j/5))   'Y Values in 2nd Col of Pair
          NEXT j
        NEXT i
        .ChartType = ctXY                               'XY Scatter Chart
        .ChartStyle = csBoth                            'Points and Lines
        .DrawXY (True)                                  'Draw it!
      END WITH

    CASE "Line Graph"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Simple Line Graph"           'change desired options
        .SubTitle.Text = "X Labels Alternate Up and Down for Room"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .Data.ColCount = 5                              'Set .Data Grid dimensions
        .Data.RowCount = 12
        k = 18                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount                     'for each col
          .Series(i).LineStyle = (i-1) MOD 5            'Cycle line styles
          .Data.Cell(i , 0) = "Group " + STR$(i)        'Legend in Row 0 of Each Col
          FOR j = 1 to .Data.RowCount                   'add data to each row
            .Data.Cell(0 , j) = "Label " + STR$(j)      'X Labels
            .Data.Cell(i , j) = STR$(RND * k)           'Y Values
          NEXT j
        NEXT i
        .ChartType = ctLine                             'Line Chart
        .ChartStyle = csLinesOnly                       'Lines only
        .DrawLine (False)                               'Draw it!
      END WITH

    CASE "Line w/Points"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Line Graph With Points"      'change desired options
        .SubTitle.Text = "Tics Only, No Grid"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .BW = True
        .XAxis.Grid = False                             'Tics only
        .YAxis.Grid = False
        .Data.ColCount = 4                              'Set .Data Grid dimensions
        .Data.RowCount = 6
        k = 18                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount                     'for each col
          .Data.Cell(i , 0) = "Group " + STR$(i)        'Legend in Row 0 of Each Col
          FOR j = 1 to .Data.RowCount                   'add data to each row
            .Data.Cell(0 , j) = "Lbl " + STR$(j)        'X Labels
            .Data.Cell(i , j) = STR$(RND * k)           'Y Values
          NEXT j
        NEXT i
'        .Data.Cell(1,4) = ""                            'Uncomment to see QChart handle missing data
        .ChartType = ctLine                             'Line Chart
        .ChartStyle = csBoth                            'Points and Lines
        .DrawLine (False)                               'Draw it!
      END WITH

    CASE "Box Plot"
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Box and Whisker Plot"        'change desired options
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .XAxis.Grid = False
        .XAxis.Tics = False
        .YAxis.AutoScale = False
          .YAxis.Min = 0
          .YAxis.Max = 50
        .Data.ColCount = 16                             'Set .Data Grid dimensions
        .Data.RowCount = 5
        k = 10                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount                     'for each col
          .Data.Cell(i , 0) = "Group " + STR$(i)        'Legend in Row 0 of Each Col
          .Data.Cell(i , 1) = STR$(RND * k + 40)        'Max Values
          .Data.Cell(i , 2) = STR$(RND * k + 30)        'Q3 Values
          .Data.Cell(i , 3) = STR$(RND * k + 20)        'Q2 Values
          .Data.Cell(i , 4) = STR$(RND * k + 10)        'Q1 Values
          .Data.Cell(i , 5) = STR$(RND * k)             'Min Values
        NEXT i
        .ChartType = ctBox                              'Box and Whisker Plot
        .ChartStyle = csWhisker
        .DrawBox (False)                                'Draw it!
      END WITH

    CASE "HLC Style 1"
      'NOTE: If values for .Data.Cells 2, 3 and 4 are set equal,
      'Box routine will draw a Hi-Lo-Close antenna style graph
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Hi-Lo-Close Plot"            'change desired options
        .SubTitle.Text = "Antenna Style"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .XAxis.Grid = False
        .XAxis.Tics = False
        .Data.ColCount = 8                             'Set .Data Grid dimensions
        .Data.RowCount = 5
        k = 10                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount                     'for each col
          .Data.Cell(i , 0) = "Group " + STR$(i)        'Legend in Row 0 of Each Col
          .Data.Cell(i , 1) = STR$(RND * k + 50)        'Hi Value
          .Data.Cell(i , 2) = STR$(RND * k + 37)        '<-- Set all Three to
          .Data.Cell(i , 3) = .Data.Cell(i , 2)         '<-- the mid or "Close"
          .Data.Cell(i , 4) = .Data.Cell(i , 2)         '<-- Value
          .Data.Cell(i , 5) = STR$(RND * k + 25)        'Lo Value
        NEXT i
        .ChartType = ctBox                              'Hi-Lo-Close Plot
        .ChartStyle = csHiLo
        .DrawBox (False)                                'Draw it!
      END WITH

    CASE "HLC Style 2"
      'NOTE: If values for .Data.Cells 1 & 2 and 4 & 5 are set equal,
      'Box routine will draw a Hi-Lo-Close box style graph
      WITH Graph
        .Initialize                                     'Set defaults
        .MainTitle.Text = "Hi-Lo-Close Plot"            'change desired options
        .SubTitle.Text = "Box Style"
        .XTitle.Text = "X Axis"
        .YTitle.Text = "Y Axis"
        .XAxis.Grid = False
        .XAxis.Tics = False
        .Data.ColCount = 8                              'Set .Data Grid dimensions
        .Data.RowCount = 5
        k = 10                                          'Load the data
        RANDOMIZE
        FOR i = 1 to .Data.ColCount                     'for each col
          .Data.Cell(i , 0) = "Group " + STR$(i)        'Legend in Row 0 of Each Col
          .Data.Cell(i , 1) = STR$(RND * k + 50)        'Hi Value
          .Data.Cell(i , 2) = .Data.Cell(i , 1)         '<-- Set = to Hi Value
          .Data.Cell(i , 3) = STR$(RND * k + 35)        'Close Value
          .Data.Cell(i , 4) = STR$(RND * k + 20)        'Lo Value
          .Data.Cell(i , 5) = .Data.Cell(i , 4)         '<-- Set = Lo Value
        NEXT i
        .ChartType = ctBox                              'Hi-Lo-Close Plot
        .ChartStyle = csWhisker                         'Whiskers are hidden :)
        .DrawBox (False)                                'Draw it!
      END WITH

    CASE "Redraw"
      WITH Graph
        .MainFont.Name =  "Times New Roman"              'Change some options
        .SubFont.Name =   "Times New Roman"              'on the currently defined chart
        .PlotAreaColr = .Colors(15)
        SELECT CASE .SubFont.Size
          CASE .MainFont.Size
            .SubFont.Size = 12
          CASE ELSE
            .SubFont.Size = .MainFont.Size
        END SELECT
        SELECT CASE .DoLegend
         CASE TRUE
           .DoLegend = False
         CASE FALSE
           .DoLegend = True
       END SELECT
       SELECT CASE .GreyScale
         CASE TRUE
           .GreyScale = False
         CASE FALSE
           .GreyScale = True
       END SELECT
       .RedrawChart                                     'and redraw the chart
     END WITH

    CASE "Clear"
      Graph.ClearBuffer                                 'Start with a clean slate
      Graph.ImagePaint                                  'Paint the blank Canvas

    CASE "Save"
      Graph.SaveChart ("")

    CASE "Print"
      Graph.PrintChart (Printer.PrinterIndex, poLandscape, 40, 1)

    CASE "Exit"
      Application.Terminate

  END SELECT

END SUB
'-------------------------------------------------------------------------------------------

SUB frmMainResize (SENDER AS QForm)

  WITH Graph
    .Width = frmMain.ClientWidth - btnClear.Width       'Calculate new sizes
    .Height = frmMain.ClientHeight
    .RedrawChart                                        'Redraw the QChart Object
  END WITH
  'Plus anything else that needs doing in your form resize

END SUB


QCursor

Documentation component by D.Glodt (c)2003 Appendix A: QCursor

QCursor Component

QCursor is component used to load cursor from resource or file.
After loading , the cursors are using by set value(1 to n) to Cursor property of each component.

QCursor Properties
Field | Type | R/W | Défault
Count | INTEGER | R | 0
 | Number of cursor loaded by the component. |  |
Visible | BOOLEAN | R/W | True

QCursor Methods
Method | Type | Description | Params
LoadFromResource | SUB(Resource&) | Load cursor from resource, Resource parameter is the resource number(0 to n) | 1
LoadFromFile | SUB(FileName$) | Load cursor from file | 1
Move | SUB(X&,Y&) | Move cursor at position x, y of screen. | 2

QCursor Events
Event | Type | Occurs when... | Params

QCursor Example
$TypeCheck On
$include "Object/QCursor.inc"

$resource cur1 as "Pen.cur"
$resource cur2 as "Paint.cur"

dim curseur asQCursor
curseur.loadfromResource(0) 'loading cursor cur1
curseur.loadfromResource(1) 'loading cursor cur2
curseur.loadfromfile("M_Busy.ani") 'loading from file

CREATE Form ASQFORM
Center
caption=str$(curseur.count)
Cursor=2 'using cursor cur2
ShowModal
END CREATE


QDIGDISPLAY

Rapid-Q Documentation by Peter Molloy (c) 2001

Appendix A: QDIGDISPLAY

QDIGDISPLAY Component

QDigDisplay simulates a seven segment LED display.

QDigDisplay Properties

Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
 | Align determines how the control aligns within its parent control.
ClientHeight | INTEGER | RW |  | W
ClientWidth | INTEGER | RW |  | W
Color | INTEGER | RW |  | WXG
CopyMode | INTEGER | RW | cmBlackness | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WXG
Font | QFONT | W |  | W
Height | INTEGER | RW | 24 | WXG
Hint | STRING | RW |  | W
Left | INTEGER | RW | 0 | WXG
Parent | QFORM/QPANEL/QTABCONTROL | W |  | WXG
Pixel | 2D ARRAY of INTEGER | RW |  | WXG
PopupMenu | QPOPUPMENU | W |  | W
ShowHint | INTEGER | RW | False | W
Tag | INTEGER | RW |  | WXG
Top | INTEGER | RW | 0 | WXG
Width | INTEGER | RW | 12 | WXG
Visible | INTEGER | RW | True | WXG
Display | STRING | RW | “0” | W

QDigDisplay Events

Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on canvas | 0 | WXG
OnDblClick | VOID | User double clicked on canvas | 0 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | WXG
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves | 3 | WXG
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | WXG
OnPaint | VOID | Receives WM_PAINT message | 0 | WXG

QDigDisplay Example

'  Count from 0 to 100

$INCLUDE “RAPIDQ.INC”
$INCLUDE “QDIGDISPLAY.INC”

DECLARE SUB CountLoop

CREATE Form AS QFORM
CREATE Button AS QBUTTON
        Left = 100
        Top = 120
        Caption = “Start Count”
        OnClick = CountLoop
END CREATE
CREATE Counter AS QDIGDISPLAY
        Left = 20
        Top = 80
        Display = “000”
END CREATE
END CREATE
Form.ShowModal

SUB CountLoop
FOR Loop1 = 0 TO 100
        Counter.Display = RIGHT$ (“000”+ STR$(Loop1),3)
        Form.Repaint
        SLEEP 1
NEXT
END SUB


QDIRLISTVIEW Component

QDirListView extends QListView Component. It Beheves like QFileListBox, but is a bit more "pretty"...

QDirListView Internal Types
   TYPE ItemType            '' ie. DirListView.Item(0).Caption
     Caption AS STRING
     Checked AS INTEGER     '' If CheckBoxes is enabled and item is checked
     Handle AS INTEGER      '' Read-only
     ImageIndex AS INTEGER
     Index AS INTEGER       '' Read-only
     Selected AS INTEGER
     StateIndex AS INTEGER
   END TYPE

   TYPE ColumnType          '' ie. DirListView.Column(0).Width
     Caption AS STRING
     Width AS INTEGER
   END TYPE
QDirListView Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
BorderStyle | INTEGER | RW | bsSingle
CheckBoxes | INTEGER | RW | False
Color | INTEGER | RW
Column | ARRAY of ColumnType | RW
ColumnClick | INTEGER | RW | True
ColumnsCount | INTEGER | RW
Cursor INTEGER RW

crDefault

Directory | STRING | RW | Application path
Directory is the directory that contains all the files listed in the listview.
dlw_PopupMenu | QPOPUPMENU | RW
NB! If you need to add an PopUpMenu to the QDirListView, then add your MenuItems to dlw_PopupMenu.
Enabled | INTEGER | RW | True
ExtensionsList | QSTRINGLIST | RW
ExtensionsList contains list of fileextensions. If file with extension listed in ExtensionsList is listed in ListBox, then an icon, which is specified in SmallImageList and LargeImageList is assigned to it.
First two items in ExtensionsList are reserved:
Item(0) for folders,
Item(1) for all other filetypes.
Filename | STRING | R
FileName is the name of the selected file in the listview, including the pathname.
Font | QFONT | W
GridLines | INTEGER | RW | False
Handle | INTEGER | R
Height | INTEGER | RW | 138
HideSelection | INTEGER | RW | False
Hint | STRING | RW
HotTrack | INTEGER | RW | False
Item | ARRAY of ItemType | RW
ItemCount | INTEGER | RW
ItemIndex | INTEGER | RW
LargeImageList | QIMAGELIST | RW
Same as SmallImageList but icons are in 32x32 size.
LargeImages | QIMAGELIST | W | LargeImageList
By Default an internal ImageList is already assigned.
Left | INTEGER | RW | 0
Mask STRING RW *.*
Mask is string that contains filter, which specifies which files are displayed in listview. By default all files are shown.
NB! At the moment only one filter is valid. i.e. "*.exe; *.com" is invalid.
MultiSelect | INTEGER | RW | False
Parent | QFORM/QPANEL/QTABCONTROL | W
PopupMenu | QPOPUPMENU | W | dlw_PopUpMenu
ReadOnly | INTEGER | RW | True
Even if You change ReadOnly to False, you can't change actual filenames through the ListView :(
RowSelect | INTEGER | RW | False
SelCount | INTEGER | RW
Selected | ARRAY of INTEGER | RW
ShowColumnHeaders | INTEGER | RW | True
ShowHint | INTEGER | RW | False
ShowRoot | INTEGER | RW | False
If True, the ".." directory will be shown.
SmallImageList | QIMAGELIST | RW
SmallImageList contains list of FileIcons. If file with extension listed in ExtensionsList is listed in ListBox, then an icon, which is specified in SmallImageList and LargeImageList is assigned to it.
First two items in SmallImageList are reserved:
Item(0) for folders,
Item(1) for all other filetypes.

... Icons are in 16x16 size.
SmallImages | QIMAGELIST | W | SmallImageList
By Default an internal ImageList is already assigned.
SortType | INTEGER | RW | stNone
StateImages | QIMAGELIST | W
SubItem | 2D ARRAY of STRING | RW
TabOrder | INTEGER | RW
Tag | INTEGER | RW
Top | INTEGER | RW | 0
Width | INTEGER | RW | 400
ViewStyle | INTEGER | RW | vsIcon
Visible | INTEGER | RW | True

QDirListView Methods
Method | Type | Description | Params
AddColumns | SUBI | Add column headers to listview | STRING, Infinite
AddItems | SUBI | Add items to listview | STRING, Infinite
AddSubItem | SUB (Index%, String$) | Add sub item to Index% | 2
ChangeDirUp | SUB | Steps one directory higher in directory-tree | 0
Clear | SUB | Clear all items in listview | 0
ClearColumns | SUB | Clear all columns in listview | 0
DelItems | SUBI | Delete items from listview | INTEGER, Infinite
DelSubItem | SUB (Index%, SubIndex%) | Delete subitem from listview | 2
InsertItem | SUB (Index%, String$) | Insert item at Index% | 2
InsertSubItem | SUB (Index%, SubIndex%, String$) | Insert subitem | 3
Refresh | SUB | Refreshes ListView Items | 3
SwapItem | SUB (Index1%, Index2%) | Swap items | 2

QDirListView Events
Event | Type | Occurs when... | Params
OnClick | VOID | Item was clicked on | 0
OnChange SUB (Index%, Change AS BYTE) Item changed (text, image, or state)
NB! Inside SUB use .InheritOnChange 		2
OnColumnClick | SUB (Column%) | Column header was clicked | 1
OnDblClick VOID Selection was double clicked on
NB! Inside SUB use .InheritOnDblClick 		0
OnFileSelect | VOID | File was double clicked on or ENTER was pressed | 0
OnKeyPress | SUB (Key AS BYTE) | Key was pressed | 1

QDirListView Examples
' An form, that displais contents of folders and
' has special icons for image-files.

$include "rapidq.inc"  'Important!

$include "QDirListView.inc"

' Custom iconResources for ImageFiles
$Resource ICO_JPEG_SMALL as "jpeg_small.ico"
$Resource ICO_JPEG_LARGE as "jpeg_large.ico"
$Resource ICO_GIF_SMALL as "gif_small.ico"
$Resource ICO_GIF_LARGE as "gif_large.ico"
$Resource ICO_BMP_SMALL as "bmp_small.ico"
$Resource ICO_BMP_LARGE as "bmp_large.ico"

declare sub DirListChange
declare sub DirListFileSelect(Tag as integer)

CREATE Form AS QFORM
    Width = 500
    Height = 300
    Center
    create DirList as QDirListView
      Align = alClient
      ShowRoot = True
      ViewStyle = vsList
      OnChange = DirListChange
      OnFileSelect = DirListFileSelect

      'in lowercase please!
      ExtensionsList.AddItems ("jpg", "jpe", "jpeg", "gif", "bmp")

      SmallImageList.AddIcoHandle(ICO_JPEG_SMALL)
      LargeImageList.AddIcoHandle(ICO_JPEG_LARGE)
      SmallImageList.AddIcoHandle(ICO_JPEG_SMALL)
      LargeImageList.AddIcoHandle(ICO_JPEG_LARGE)
      SmallImageList.AddIcoHandle(ICO_JPEG_SMALL)
      LargeImageList.AddIcoHandle(ICO_JPEG_LARGE)
      SmallImageList.AddIcoHandle(ICO_GIF_SMALL)
      LargeImageList.AddIcoHandle(ICO_GIF_LARGE)
      SmallImageList.AddIcoHandle(ICO_BMP_SMALL)
      LargeImageList.AddIcoHandle(ICO_BMP_LARGE)
    end create
end create

Form.ShowModal

'------------------------------------------------------
sub DirListChange
  DirList.InheritOnChange 'Important!
  Form.Caption = DirList.Directory
end sub

sub DirListFileSelect(Tag as integer) 'It Just needs one empty parameter to work
  ShowMessage("File '" + DirList.FileName + "' was selected.")
end sub
QDirListView SourceCode
'-----------------------------------------------------------------
'
'  QDirListView
'
'  An Customized QListView For Displaing Files and Folders
'
'  by Rene Saarsoo
'
'-----------------------------------------------------------------
' not well-commented and needs some work, but is fully-functional :)
' All Suggestions and Bug-Reports are welcome to  nene@hot.ee
'
' Long live the Rapid-Q!
'

' Icons for folders and unidentified files
$resource ICO_DIR_SMALL as "dir_XP_small.ico"
$resource ICO_DIR_LARGE as "dir_XP_large.ico"
$resource ICO_DEFAULTFILE_SMALL as "default_small.ico"
$resource ICO_DEFAULTFILE_LARGE as "default_large.ico"

' exclude it, if you have already declared this API-function
declare function SetFocus LIB "USER32" ALIAS "SetFocus" (Handle as long) as long

declare sub FileSelect_EventTemplate(Tag as integer)

type QDirListView extends QListView
  Directory as string property set Set_Directory
  Filename as string
  Mask as string property set Set_Mask
  ShowRoot as integer property set Set_ShowRoot
  LargeImageList as QImageList
  SmallImageList as QImageList
  ExtensionsList as QStringList
  dlw_PopupMenu as QPopupMenu
  dlw_Enter as QMenuItem
  dlw_BackSpace as QMenuItem
  OnFileSelect as event (FileSelect_EventTemplate)
  ColumnsInitialized as integer

  sub SetItemImage (Extension as string)
    QDirListView.Item(QDirListView.ItemCount - 1).ImageIndex = 1
    for i = 2 to QDirListView.ExtensionsList.ItemCount - 1
      if lcase$(Extension) = QDirListView.ExtensionsList.Item(i) then
        QDirListView.Item(QDirListView.ItemCount - 1).ImageIndex = i
        exit for
      end if
    next i
  end sub

  sub AddFileProperties (Extension as string)
    dim SizeString as string
    if FileRec.Size/1024 >= 1 then
      SizeString = str$(int(FileRec.Size / 1024)) + " KB"
    else
      SizeString = "1 KB"
    end if
    QDirListView.AddSubItem (QDirListView.ItemCount - 1, SizeString )
    QDirListView.AddSubItem (QDirListView.ItemCount - 1, ucase$(Extension) + " File")
    dim FirstSplitter as integer
    dim Month as string
    FirstSplitter = instr(FileRec.Date, "-", 0)
    Month = left$(FileRec.Date, FirstSplitter - 1)
    if len(Month) = 1 then Month = "0" + Month
    dim Day as string
    Day = left$(right$(FileRec.Date, len(FileRec.Date) - FirstSplitter), _
            instr(right$(FileRec.Date, len(FileRec.Date) - FirstSplitter), "-", 0) - 1)
    dim Year as string
    Year = right$(FileRec.Date, 4)
    QDirListView.AddSubItem (QDirListView.ItemCount - 1, Day+"."+Month+"."+Year + " " +FileRec.Time)
  end sub

  sub LoadDirectories
    dim File as string
    File = ""
    File = Dir$(QDirListView.Directory + "*.*", faDirectory)
    do
    File = Dir$
    if File = "" then
      exit do
    else
      if File = ".." and QDirListView.ShowRoot = FALSE then
      else
        if DirExists(QDirListView.Directory + File) then
          QDirListView.AddItems File
        end if
      end if
    end if
    loop
  end sub

  sub LoadFiles
    dim File as string
    dim i as integer
    File = ""
    i = 0

    do
    i = i + 1
    if i = 1 then
      File = Dir$(QDirListView.Directory + QDirListView.Mask, 0)
    else
      File = Dir$
    end if

    if File = "" then
      exit do
    else
      dim Extension as string
      Extension = ""
      dim PontPlace as integer

      QDirListView.AddItems File

      PointPlace = instr(File, ".", 0)
      if PointPlace > 0 then
        Extension = right$( File, instr(reverse$(File), ".", 0) - 1 )
        QDirListView.SetItemImage (Extension)
      else
        QDirListView.Item(QDirListView.ItemCount - 1).ImageIndex = 1
      end if
      QDirListView.AddFileProperties (Extension)
    end if
    loop
  end sub

  sub Refresh
    QDirListView.Clear
    QDirListView.LoadDirectories
    QDirListView.LoadFiles
    QDirListView.ViewStyle = QDirListView.ViewStyle + 1   ' SomeHow we manage with
    QDirListView.ViewStyle = QDirListView.ViewStyle - 1   ' changing the style
                                                          ' to make items fully wisible
                                                          ' ( without "..." at the end )
    if ColumnsInitialized = FALSE then
      QDirListView.ClearColumns
      QDirListView.AddColumns "Name", "Size", "Type", "Date Modified"
      QDirListView.Column(0).Width = 150
      QDirListView.Column(1).Width = 60
      QDirListView.Column(2).Width = 60
      QDirListView.Column(3).Width = 100
      ColumnsInitialized = TRUE
    end if
    QDirListView.Visible = false     ' Whith this we manage to repaint the control.
    QDirListView.Visible = true      ' Otherwise it would stay messed-up ( You can Try :) )
    SetFocus(QDirListView.Handle)    ' Focus was lost on hiding, so we set it back.
  end sub

  sub ChangeDirUp
    QDirListView.Directory = left$(QDirListView.Directory, _
            len(QDirListView.Directory) - _
            instr(mid$(reverse$(QDirListView.Directory), 2), "\", 0)  )
    QDirListView.refresh
  end sub

  sub ChangeDir
    if QDirListView.Item(QDirListView.ItemIndex).Caption = ".." then
      QDirListView.ChangeDirUp
    else
      QDirListView.Directory = QDirListView.FileName + "\"
      QDirListView.refresh
    end if
  end sub

  sub TryToChangeDirOrMakeEvent
    if QDirListView.FileName > "" then
      if DirExists(QDirListView.FileName) then
        QDirListView.ChangeDir
      else
        CallFunc(QDirListView.OnFileSelect, 0)
      end if
    end if
  end sub

  event OnChange
    if QDirListView.ItemIndex >= 0 then
    QDirListView.FileName = QDirListView.Directory + QDirListView.Item(QDirListView.ItemIndex).Caption
    else
    QDirListView.FileName = ""
    end if
  end event

  event OnDblClick
    QDirListView.TryToChangeDirOrMakeEvent
  end event

  event dlw_Enter.OnClick
    QDirListView.TryToChangeDirOrMakeEvent
  end event

  event dlw_BackSpace.OnClick
    QDirListView.ChangeDirUp
  end event

  property set Set_Directory (Dir as string)
    if right$(Dir, 1) = "\" then
      QDirListView.Directory = Dir
    else
      QDirListView.Directory = Dir + "\"
    end if
    QDirListView.Refresh
  end property

  property set Set_ShowRoot (RootSet as integer)
    QDirListView.ShowRoot = RootSet
    QDirListView.Refresh
  end property

  property set Set_Mask (MaskSet as string)
    QDirListView.Mask = MaskSet
    QDirListView.Refresh
  end property

  constructor
    Width = 400
    Height = 138
    Directory = left$(Command$(0), len(Command$(0)) - len(APPLICATION.ExeName) )
    Filename = ""
    Mask = "*.*"
    ShowRoot = FALSE
    ReadOnly = TRUE
    ColumnsInitialized = FALSE
    LargeImageList.Width = 32
    LargeImageList.Height = 32
    ExtensionsList.AddItems "<dir>"
    SmallImageList.AddICOHandle ICO_DIR_SMALL
    LargeImageList.AddICOHandle ICO_DIR_LARGE
    ExtensionsList.AddItems "<dir>"
    SmallImageList.AddICOHandle ICO_DEFAULTFILE_SMALL
    LargeImageList.AddICOHandle ICO_DEFAULTFILE_LARGE
    LargeImages = QDirListView.LargeImageList
    SmallImages = QDirListView.SmallImageList
    dlw_Enter.ShortCut = "Enter"
    dlw_Enter.Visible = FALSE
    dlw_BackSpace.ShortCut = "BkSp"
    dlw_BackSpace.Visible = FALSE
    dlw_PopupMenu.AddItems(QDirListView.dlw_Enter, QDirListView.dlw_BackSpace)
    PopUpMenu = QDirListView.dlw_PopUpMenu
  end constructor
end type


QDownload

Rapid-Q Documentation by Andreas Fink (c)2000 Appendix A: QDownload

QDownload Component

Offers an interface to download files from HTTP-Servers, either in the background or apparently, it has a sophisticated error diagnostic interface

QDownload Properties
Field | Type | R/W | Default | Support
Server | STRING | RW |  | W
Port | INTEGER | RW | 80 | W
File | STRING | RW |  | W
Outfile | STRING | RW |  | W
Outvar | STRING | R |  | W
Outdevice | INTEGER | RW | 1 | W
Statedevice | INTEGER | RW | 1 | W
State | INTEGER | R |  | W
Size | INTEGER | R |  | W
LastError | INTEGER | R |  | W
LastStringError | STRING | R |  | W
StateGauge | QGAUGE | RW | .height=20; .width=200 |

QDownload Methods
Method | Type | Description | Params | Support
Leechfile | FUNCTION | Performs the Download, needs all settings to be made | 0 | W
Check | FUNCTION | Checks for an Internet Connection | 0 | W
Percent | FUNCTION | Calculates the current State in Percent | 2 | W

QDownload Events
Event | Type | Occurs when... | Params | Support
None |  |  |  |

QDownload Examples

'Example for Qdownload usage

$TYPECHECK ON                           'Use these !!!!
$include "rapidq.inc"
$include "qdownload.inc"

dim download as qdownload               ' You should create an instance here
declare sub test

'That's all well known

create form as qform
 width = 220
 height = 260
 caption = "QDownload Example"
  create button as qbutton
   top = 10
   width = 80
   left = (form.clientwidth/2)-button.width/2
   Caption = "Download!"
   onclick  = test
  end create
  create edit1 as qedit
   top = 50
   text ="Server.com"
   left = (form.clientwidth/2)-edit1.width/2
  end create
  create edit2 as qedit
   top = 80
   text ="Path/Filename"
   left = (form.clientwidth/2)-edit2.width/2
  end create
  create edit3 as qedit
   top = 110
   text ="LocalDrive:/Localpath/Filename"
   left = (form.clientwidth/2)-edit2.width/2
  end create
  create checkbox1 as qcheckbox
   top = 140
   width = 160
   left = (form.clientwidth/2)-checkbox1.width/2
   caption = "Show Status in Gauge"
  end create
  create checkbox2 as qcheckbox
   top = 170
   width = 200
   left = (form.clientwidth/2)-checkbox2.width/2
   caption = "Save to file (X) or show using word ()"
   end create
end create

'Here you should determine the qgauge's appearance
download.stategauge.parent = form
download.stategauge.left = (form.clientwidth/2)-t.stategauge.width/2
download.stategauge.top = 200

form.showmodal

sub test
DIM Object AS QOLEOBJECT                  'This one is just for demonstrative issues

download.server =edit1.text               'The Server property is to be set, assuming the port is 80
download.file=edit2.text                  'The File property is set, i.e. the name of the file to be gotten
download.outfile=edit3.text               'The Outfile property is set, i.e. the file the downloaded file
                                          'will be saved in

select case checkbox2.checked
case True
  download.outdevice = 2                  'The Outdevice property is set, i.e. 1 = qdownload.outvar
end select                                '                                    2 = qdownload.outfile

select case checkbox1.checked
case True
  download.statedevice=2                  'The Statedevice property is set, i.e. 1 = qdownload.state
end select                                '                                      2 = qdownload.stategauge

if download.leechfile then                'And do it, if all works well leechfile returns True
 select case checkbox2.checked
 case False
   Object.CreateObject("word.basic")
   Object.AppShow
   Object.FileNew
   Object.Insert(t.outvar)
   Object.Free
 end select
else
 showmessage (download.laststringerror)   'and if not False, then qdownload.lasterror, .laststringerror are
end if                                    'interesting
end sub


QDrawFocus

Documentation component by D.Glodt (c)2000-2001 Appendix A: QDrawFocus

QDrawFocus Component

QDrawFocus is a focus to use as selection in graphic components.

QDrawFocus Properties
Field | Type | R/W | Défault
Left | SHORT | R |
 | Position x of focus when it is visible |  |
Top | SHORT | R |
 | Position y of focus when it is visible |  |
Width | SHORT | R |
 | Width of focus when it is visible |  |
Height | SHORT | R |
 | Height of focus when it is visible |  |
Move | BOOLEAN | R | FALSE
 | At true if focus has moved. |  |
Visible | BOOLEAN | RW | FALSE
 | At true if focus is visible |  |
Inside | BOOLEAN | R | FALSE
 | At true if cursor is inside the focus |  |
NoResize | BOOLEAN | RW | FALSE
 | No resize when the value is true |  |
ShowCursor | BOOLEAN | RW | TRUE
 | Change the cursor state following the actions on focus |  |

QDrawFocus Methods
Method | Type | Description | Params
Remove | SUB(handle&) | Remove the focus | 1
Start | SUB(handle&,x%,y%) | Start the drawing of focus | 3
Draw | SUB(handle&,x%,y%,flagDraw%) | Draw the focus | 4
Stop | SUB(handle&,flagRemove%) | Stop the drawing of focus | 2

QDrawFocus Events
Event | Type | Occurs when... | Params

QDrawFocus Examples
'==============================================================================================
' the Start method gives the starting point of focus
' the Draw method draws the focus , moves it or the resize if this one is already visible and if flagDraw is at true,
' if flagDraw is at false only the state of the cursor changes
' the Stop method gives the cursor at its state of origin after action on the focus and removes the focus if the flagRemove is at true.
'===============================================================================================
$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\QDrawFocus.inc"

declare sub StartFocus(button as short,x as short,y as short)
declare sub StopFocus(x as short,y as short)
declare sub DrawFocus(x as short,y as short)
declare sub paint
declare sub resize
dim focus as QDrawFocus
dim flag as byte

CREATE Form AS QFORM
Caption = "Form1"
Width = 686
Height = 452
Center
OnResize=resize
CREATE Canvas1 AS QCANVAS
Left = 0
Top = 0
Width = 678
Height = 425
OnPaint=paint
OnMouseDown=StartFocus
OnMouseUp=StopFocus
OnMouseMove=DrawFocus
END CREATE
END CREATE

Form.ShowModal

Sub StartFocus(button as short,x as short,y as short)
focus.start(Canvas1.handle,x,y)
flag=true
End Sub

Sub DrawFocus(x as short,y as short)
focus.draw(Canvas1.handle,x,y,flag)
End Sub

Sub StopFocus(x as short,y as short)
focus.stop(Canvas1.handle,false)
flag=false
End Sub

Sub paint
if focus.visible then
focus.visible=false
Canvas1.fillrect(0,0,1000,1000,&HFFFFFF)
focus.start(Canvas1.handle,focus.left,focus.top)
focus.draw(Canvas1.handle,focus.left+focus.width,focus.top+focus.height,true)
else
Canvas1.fillrect(0,0,1000,1000,&HFFFFFF)
end if
end sub

sub resize
canvas1.repaint
end sub


QDrive

Documentation component by D.Glodt (c)2000-2001 Appendix A: QDrive

QDrive Component

QDrive is a component no visible of infos drivers.

QDrive Properties
Field | Type | R/W | Default
Name | ARRAY OF STRING | R |
 | Name of présent drivers |  |
Count | INTEGER | R |
 | Number of présent drivers |  |

QDrive Methods
Method | Type | Description | Params
GetType | FUNCTION(index&) as long | return the type of driver. | 1
Possible values:DRIVE_REMOVABLE (2)
DRIVE_FIXED(3)
DRIVE_REMOTE(4)
DRIVE_CDROM(5)
DRIVE_RAMDISK(6)
GetFreeSpace | FUNCTION(index&) as long | return free space in octet of driver | 1
GetSize | FUNCTION(index&) as long | return the size in octet from driver | 1

QDrive Events
Event | Type | Occurs when... | Params

QDrive Examples

$INCLUDE "Object\QDrive.inc"

dim drive as QDrive
declare sub show

CREATE Form AS QFORM
Caption = "Proprietés disque dur"
Width = 320
Height = 240
Center
OnShow=show
CREATE Label1 AS QLABEL
Caption = ""
Left = 22
Top = 22
END CREATE
END CREATE

Form.ShowModal

sub show
dim i as integer
dim number as integer

    For i=1 to drive.Count
if drive.GetType(i)=DRIVE_FIXED then
number=i
next i
label1.caption="Nom lecteur: "+drive.name(number)+chr$(13)+
_
"Capacité: "+str$(drive.GetSize(number))+" octets"+chr$(13)+ _
"Espace libre: "+str$(drive.GetFreeSpace(number))+" octets"
end sub


QFlashLabel

Documentation component by D.Glodt (c)2003 Appendix A: QFlashLabel

QFlashLabel Component

QFlashLabel is a flashing label component.

QFlashLabel Properties
Field | Type | R/W | Défault
LightColor | LONG | R/W | 0
 | Label light color. |  |
DarkColor | LONG | R/W | 0
 | Label dark color. |  |
Flash | BOOLEAN | R/W | FALSE
 | Activate flashing |  |
State | SHORT | R/W | 0
 | state lighted or extinct |  |
Speed | LONG | R/W | 1000
 | Flashing speed |  |
Parent | QFORM,QPANEL,QTABCONTROL | W |
Left | INTEGER | R/W | 0
Top | INTEGER | R/W | 0

QFlashLabel Methods
Method | Type | Description | Params

QFlashLabel Events
Event | Type | Occurs when... | Params

QFlashLabel Example
$typecheck on
$optimize on
$include "Rapidq.inc"
$include "QFuncLib.inc"
$include "Object\QSkin.inc"
$include "Object\QSkinBtn.inc"
$include "Object\QTextBtn.inc"
$include "Object\QFlashLabel.inc"
$include "Object\QVuMeter.inc"
$include "Object\QVideo.inc"

$resource img as "skin3.bmp"
$resource play1 as "play1.bmp"
$resource play2 as "play2.bmp"
$resource stop1 as "stop1.bmp"
$resource stop2 as "stop2.bmp"
$resource pause1 as "pause1.bmp"
$resource pause2 as "pause2.bmp"
$resource back1 as "back1.bmp"
$resource back2 as "back2.bmp"
$resource fwd1 as "foreward1.bmp"
$resource fwd2 as "foreward2.bmp"
$resource power1 as "power1.bmp"
$resource power2 as "power2.bmp"

declare sub quit
declare sub volume
declare sub SetVolume
declare sub open
declare sub play
declare sub stop
declare sub foreward
declare sub backward
declare sub pause
Declare Sub ShowTime(Position as long,timePos aslong)

const color1=&h660000
const color2=&hff9900
const color3=&h88FF66
const RazClock="00:00"

Dim OpenDialog asQOpenDialog
OpenDialog.Filter="Fichier vidéo(tout type)|*.avi;*.mpg;*.mpeg;*.mov|Fichier avi|*.avi|Fichier MPEG|*.mpg;*.mpeg|Fichier MOV|*.mov|"
OpenDialog.Caption= "Selectionner une vidéo"

CREATE Form ASQSkin
Center
skin.bmpHandle=img
skin.top=-1
skin.left=-1
caption="Player"
OffsWidth=-5
create display asqpanel
top=20
left=16
width=311
height=72
bevelinner=0
bevelouter=0
color=&h994400
create bar asqpanel
top=50
left=0
width=display.width
height=2
bevelinner=0
bevelouter=0
color=color1
end create
create FlashPlay
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=2
caption="Play"
end create
create FlashStop
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=16
caption="Stop"
state=true
end create
create FlashPause
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=30
caption="Pause"
end create
create FlashTime
asQFlashlabel
DarkColor=color1
LightColor=color2
left=150
top=6
font.size=24
caption=RazClock
State=true
end create
create vu asQVuMeter
top=1
left=290
width=10
height=45
DarkColor=color1
LightColor=color2
value=50
end create
create btOpen
asQTextBtn
UpColor=color1
DownColor=color2
left=5
top=55
font.bold=true
caption="Open"
OnClick=open
end create
create btVol
asQTextBtn
UpColor=color1
DownColor=color2
left=265
top=55
font.bold=true
caption="Volume"
OnClick=Volume
end create
end create
create btPlay asQskinBtn
btUp.bmphandle=play1
btDown.bmphandle=play2
top=110
left=12
mode=1
OnClick=play
end create
create btStop asQskinBtn
btUp.bmphandle=stop1
btDown.bmphandle=stop2
top=110
left=44
OnClick=stop
end create
create btPause asQskinBtn
btUp.bmphandle=pause1
btDown.bmphandle=pause2
top=110
left=76
mode=1
OnClick=pause
end create
create btBack asQskinBtn
btUp.bmphandle=back1
btDown.bmphandle=back2
top=110
left=108
OnClick=backward
end create
create btFwd asQskinBtn
btUp.bmphandle=fwd1
btDown.bmphandle=fwd2
top=110
left=140
OnClick=foreward
end create
create btPower asQskinBtn
btUp.bmphandle=power1
btDown.bmphandle=power2
top=110
left=300
OnClick=quit
end create
END CREATE

CREATE Form2 ASQFORM
Caption="Volume"
Width=60
Height=190
Center
borderStyle=bsToolWindow
CREATE TbVol ASQTRACKBAR
cursor=crHandPoint
Orientation=tbVertical
Frequency=5
TickMarks=tmBoth
TickStyle=tsAuto
Left=5
Top=5
Max=0
Min=-100
Width=45
Height=150
position=-50
OnChange=SetVolume
END CREATE
END CREATE

CREATE video ASQVideo
Parent=0
volume=50
OnChange=ShowTime
timer.interval=200
BorderStyle=bsSizeable
END CREATE

form.shapeform(img,&hffffff)
form.setdeskbar
Form.ShowModal

Sub quit
video.close
form2.close
application.terminate
End Sub

Sub volume
form2.show
End Sub

Sub SetVolume
vu.value=Abs(TbVol.position)
video.volume=Abs(TbVol.position)
End Sub

Sub open
If OpenDialog.Execute Then
video.close
if video.open(OpenDialog.FileName)then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
video.caption=GetFileName(OpenDialog.FileName)
else
showmessage
video.error
end if
end if
End Sub

Sub play
if video.FileOpen=false
then
btPlay.Down=false
else
FlashPause.flash=false
FlashStop.state=false
FlashPlay.state=true
btPause.Down=false
video.play
end if
End Sub

Sub stop
video.stop
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
End Sub

Function GetMinutes(seconds aslong)asstring
dim min asinteger
dim sec asinteger
dim sMin asstring
dim sSec asstring

min=seconds/60
sec=seconds mod 60
if min<10 then
sMin="0"+str$(min)
else
sMin=str$(min)
end if
if sec<10 then
sSec="0"+str$(sec)
else
sSec=str$(sec)
end if
result=sMin+":"+sSec
End Function

Sub ShowTime(Position aslong,timePos
aslong)
FlashTime.caption=GetMinutes(timePos)
If Video.State=VD_STOP then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
end if
End Sub

Sub pause
if video.state=VD_PLAY then
video.pause
btPlay.down=false
FlashPlay.state=false
FlashPause.flash=true
else
if video.FileOpen=false
then
btPause.Down=false
end if
End Sub

Sub foreward
if (video.currentFrame+1)<video.lenght
then
video.currentFrame=video.currentFrame+1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub

Sub backward
if video.currentFrame>0 then
video.currentFrame=video.currentFrame-1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub


QLineGraph
Copyright (c) Jonathan Boles 2002

PROPERTIES

Height AS Integer | self explanatory
Width AS Integer |
Top AS Integer |
Left AS Integer |
ExtrapolateToZero AS Boolean | whether the graph should start at 0,0
AxisColour AS Integer | Colour for axes
TextColour AS Integer | Colour for text
BackColour AS Integer | Colour for background
LineColour AS Integer | Colour for plotted line
XTitle AS String | X axis title
YTitle AS String | Y axis title
Title AS String | Title for graph
Data AS QStringGrid | Graph data, stored in form
 | x=Data.Cell(0,i) y=Data.Cell(1,i) where i is an integer
TextFont AS QFont | Font for graph text
Visible AS Boolean |
Hint AS String |
ShowHint AS Boolean |
Cursor AS Integer | Cursor for the graph

METHODS

SUB Initialise | Initialise graphsystem
SUB SaveToFile | save graph to .bmp (can't get this 2 work


QHTML

'************************************************************************
'* Class QHTML Version 1.0 L Pascal Delcombel-2003-2008 *
'************************************************************************
' Class to show (readonly) simplified HTML pages. *
' Principle: no API no DLL *
' (in order to be switchable to Linux version) *
'************************************************************************
' LIMITS *
' > just a few of the tags supported (ie TABLE not included so far...) *
' > no frame so far *
' > maximum of 200 000 elements (because no way to do dynamically redim *
' arrays from within a QObj) *
' you may change that number to smaller or greater one (and smaller *
' or greater html pages) through constant htmlMaxElements, here below* *
' > no formulaire (button, field, ...) *
' > no download !! *
' > see OnLoadImage to use external routine in order to load pictures *
' like jpeg , GIF and other image files *
'************************************************************************
' Events *
' ****** *
' OnHover(TypeObject as String, URL as String, x as long, y as long _*
' , shift as long) *
' -- TypeObject HREF or Tag Type *
' -- URL URL/Filename (if HREF) or hovered text/tag *
' ****** *
' OnTagClick(URL as String, x as long, y as long, shift as long) *
' -- URL HREF (URL or FileName) *
' ****** *
' OnLoadImage(Image as QImage, FileName as String) *
' -- Image QImage in which loading the FileName image *
' -- FileName FileName of the image to be loaded *
'************************************************************************
' Properties *
' ********** *
' HTMLTExt as String RW get/set HTMLText *
' DefaultFontName RW get/set default font name *
' DefaultFontSize RW get/set default font size *
' DocumentTitle R get html page title *
' PopUpMenu RW get/set popupmenu (heritage) *
'************************************************************************
' Methods *
' ******* *
' OpenFile(FileName as String) *
' -- FileName (not URL so far) *
' ******* *
' Repaint *
' ******* *
' PrintPreview *
' ******* *
' SearchText(Text as String,Popupwindow as Integer) *
' -- Text Text to be searched *
' -- Popupwindow True to open popup window / false otherwise *
'************************************************************************


Last Updated

Last Updated: September 21, 2002

'''''QICMP.INC'''''Copyright 2002 Global Services

This package contains Qicmp.inc, QPing.bas and Qicmp.doc (this file).
Qicmp.inc creates an object for use in RapidQ basic programs to send
and receive icmp echo requests (pings) and replies using Window's
icmp.dll, which implements a few functions in internet control message
protocol (icmp).

QPing.bas illustrates use of the Qicmp.inc file in a ping program.
If the user program sets the TTL value in echo requests, a tracer
route program could be implemented.

RFCs 792, 1122, 1346 and 1812, among others, provide background.

THE QICMP OBJECT provides RapidQ program use of icmp.dll

PROPERTIES (Echo Request) Readable, Writable

Value Type Description
EchoString String Echo data to send (defaults to "Echo This")
Timout Long Echo time out (defaults to 3500 msec)
ReqOpt(0) Byte Time-to-live (TTL) see RFC 792 (defaults to 255)
ReqOpt(1) Byte Type of Service (TOS) see RFC 1346 (usually zero)
ReqOpt(2) Byte Flags see RFC 792 (usually zero)
ReqOpt(3) Byte Number of Options see RFC 792 (usually zero)
ReqOpt(4) Long Pointer to Options list (usually zero)

PROPERTIES (ICMP Reply) Readable, Writable (but why would you?)

Value Type Description
Reply(0) Long Address that replied
Reply(1) Long Status (0 = OK)
Reply(2) Long Round Trip Time in msec
Reply(3) Long Data Length (lower 16 bits); Reserved (upper 16 bits)
Reply(4) Long Pointer to Data
Reply(5) Long Options (lower byte is TTL of reply)
Reply(6) Long Pointer to Options Data
Reply(7-70) Long Data

METHODS Arguments Returns

Ping(ip$) IP address LONG msec for reply or -1 for Ping error.
ReplyStatus None Reply status as string.
ReplyAddress None String (a.b.c.d) of Reply(0), or null if = 0.
ReplyData None Reply data as string; should = EchoString.
ReplyTTL None TTL of reply packet.
CloseHandle None Closes Icmp handle, do before program exit.

Greater flexibility will be found in a raw sockets implementation of
icmp and other protocols.

IF all the files in this zip are put in one directory AND your
RapidQ stuff is in C:\rapidq, then "rc qping" will compile the
program. You will have to edit RC.BAT if C:\rapidq is not the
home directory for RapidQ.


QICON

Documentation component by D.Glodt (c)2000-2004 Appendix A: QICON

QICON Component

QICON is a component no visible with icons extraction from exe,dll,icl,ico files or associated files and save file to icon format.

QICON Properties
Field | Type | R/W | Default
FileName | STRING | RW |
 | Name of icon file including the path, the files type are *.ico,*.exe,*.dll,*.icl or other files associated to an exé.a empty string delete the current icon in mémory.
Count | INTEGER | R |
 | Number of icons in the file.
Handle | LONG | R |
 | Icon handle.
Index | INTEGER | RW | 0
 | Icon index ,for selection of icon from file if it has many icons.
Associated | BOOLEAN | RW | FALSE
 | Icon associated to a exe file if the value is true. |  |

QICON Methods
Method | Type | Description | Params
SaveToFile | Sub(FileName$,pixelFormat%,mask%) | Save to icon format FileName is the file name,PixelFormat can be pf4bit(16 colors) or pf8bit(256 colors , mask is transparence(true or false) | 3
SaveBmpToFile | Sub(QBitmap,FileName$,pixelFormat%,mask%) | Save a bitmap to icon format. | 4
ConvertAsCursor | Sub(FileName$,XHotSpot?,YHotSpot?) | Convert icon filename$ as cursor, parameters XHotSpot and YHotSpot are cursor coordinates | 3

QICON Events
Event | Type | Occurs when... | Params

QICON Examples

$TYPECHECK ON
$Option ICON "IconLib.ico"
$Include "Rapidq.inc"
$Include "QFuncLib.inc"
$Include "Object\QICON.inc"
$Include "Object\QCanvasEx.inc"
$INCLUDE "Object\QCOLORDIALOG.INC"
$INCLUDE "Object\QDrawFocus.INC"
$INCLUDE "Object\QFileListView.inc"
$INCLUDE "Object\QFormEx.inc"
$include "Object\QAbout.inc"

$Resource CODE as "IconLib.ico"
$Resource ICO_DEFAUT as "defaut.ico"
$Resource ICO_EXE as "exe.ico"
$Resource ICO_DLL as "dll.ico"
$Resource ICO_IMG as "img.ico"

$Resource ICO_SMALL_DEFAUT as "SmallDefaut.ico"
$Resource ICO_SMALL_EXE as "SmallExe.ico"
$Resource ICO_SMALL_DLL as "SmallDll.ico"
$Resource ICO_SMALL_IMG as "SmallImg.ico"

declare Sub open(file as string)
declare Sub draw
declare sub ChangeDirectory
declare sub ShowFiles
declare sub ShowIco
declare sub ShowIcl
declare sub ShowDll
declare sub ShowExe
declare sub ShowCur
declare sub showColor
declare sub SaveAs
declare sub MenuMask
declare sub SelectIco(button as long,x as long,y as long,shift as long)
declare Sub ShowList(sender as QMenuItem)
declare sub ResizeImage
declare sub OnAbout
declare sub DrawCursor
declare sub GridCursor
declare sub InfoGrid(x as short,y as short)
declare sub CloseGrid(Button as short,x as short,y as short)
declare sub OpenGrid
declare sub CheckIco

const Offset=38
dim bitmap as QBITMAP
bitmap.PixelFormat=pf24bit
bitmap.width=32
bitmap.height=32
dim rect as QRECT
dim dest as QRECT
dim icon as Qicon
dim Dial as QColorDialog
dim ImageColor as long
ImageColor=&HFFFFFF
Dim SaveDialog as QSaveDialog
SaveDialog.Filter="icones 16 couleurs(*.ico)|*.ico|icones 256 couleurs(*.ico)|*.ico|bitmap 24 bits(*.bmp)|*.bmp|"
SaveDialog.Caption= "Sauver sous"
dim popup as QPOPUPMENU
dim pop1 as QMENUITEM
pop1.caption="&Sauver sous..."
pop1.OnClick=SaveAs
popup.addItems(pop1)
popup.autoPopup=true
dim IconSelect as integer
dim focus as QDrawFocus
    focus.noresize=true
    focus.showcursor=false
dim about as QAbout
const AppTitle="Icon viewer"
const AppVersion="1.2"

CREATE Form AS QFormEx
    Caption=AppTitle
    Width=640
    Height=500
    Center
    DeskBar=true
    CREATE Menu as QMAINMENU
      CREATE Menu1 as QMENUITEM
        caption="&Fichier"
        OnClick=CheckIco
        CREATE item11 as QMENUITEM
          caption="&Sauver sous..."
          OnClick=SaveAs
        END CREATE
        CREATE item12 as QMENUITEM
          caption="&Mode transparent"
          checked=true
          OnClick=MenuMask
        END CREATE
        CREATE item13 as QMENUITEM
          caption="-"
        END CREATE
        CREATE item14 as QMENUITEM
          caption="&Conversion curseur"
          OnClick=OpenGrid
        END CREATE
      END CREATE
      CREATE Menu2 as QMENUITEM
        caption="&Affichage"
        CREATE item1 as QMENUITEM
          caption="&Couleur de fond"
          OnClick=ShowColor
        END CREATE
        CREATE item2 as QMENUITEM
          caption="-"
        END CREATE
        CREATE item3 as QMENUITEM
          caption="&Fichiers ico"
          checked=true
          OnClick=ShowIco
        END CREATE
        CREATE item4 as QMENUITEM
          caption="&Fichiers icl"
          checked=true
          OnClick=ShowIcl
        END CREATE
        CREATE item5 as QMENUITEM
          caption="&Fichiers dll"
          checked=true
          OnClick=ShowDll
        END CREATE
        CREATE item6 as QMENUITEM
          caption="&Fichiers exe"
          checked=true
          OnClick=ShowExe
        END CREATE
        CREATE item7 as QMENUITEM
          caption="&Fichiers cur"
          checked=true
          OnClick=ShowCur
        END CREATE
        CREATE item8 as QMENUITEM
          caption="-"
        END CREATE
        CREATE item21 as QMENUITEM
          caption="&Grandes icones"
          Tag=1
          OnClick=ShowList
        END CREATE
        CREATE item22 as QMENUITEM
          caption="&Petites icones"
          Tag=2
          OnClick=ShowList
        END CREATE
        CREATE item23 as QMENUITEM
          caption="&Liste"
          Tag=3
          OnClick=ShowList
        END CREATE
        CREATE item24 as QMENUITEM
          caption="&Détails"
          Tag=4
          checked=true
          OnClick=ShowList
        END CREATE
      END CREATE
      CREATE Menu3 as QMENUITEM
        caption="&?"
        CREATE item31 as QMENUITEM
          caption="&A Propos..."
          OnClick=OnAbout
        END CREATE
      END CREATE
    END CREATE
    CREATE Splitter1 AS QSPLITTER
      Align=alLeft
      width=5
    END CREATE
    CREATE DirTree AS QDirTree
      Align=alLeft
      InitialDir = CURDIR$
      Width =300
      OnChange=ChangeDirectory
    END CREATE
    CREATE EXEList AS QFileListView
      Align=alClient
      Width = 325
      ViewStyle=vsReport
      ExtensionsList.AddItems ("exe","dll","icl","ico","cur","ani")
      SmallImageList.AddIcoHandle(ICO_SMALL_DEFAUT)
      LargeImageList.AddIcoHandle(ICO_DEFAUT)
      SmallImageList.AddIcoHandle(ICO_SMALL_EXE)
      LargeImageList.AddIcoHandle(ICO_EXE)
      SmallImageList.AddIcoHandle(ICO_SMALL_DLL)
      LargeImageList.AddIcoHandle(ICO_DLL)
      SmallImageList.AddIcoHandle(ICO_SMALL_IMG)
      LargeImageList.AddIcoHandle(ICO_IMG)
      SmallImageList.AddIcoHandle(ICO_SMALL_IMG)
      LargeImageList.AddIcoHandle(ICO_IMG)
      SmallImageList.AddIcoHandle(ICO_SMALL_IMG)
      LargeImageList.AddIcoHandle(ICO_IMG)
      SmallImageList.AddIcoHandle(ICO_SMALL_IMG)
      LargeImageList.AddIcoHandle(ICO_IMG)
      ColumnCaption(1)="Nom"
      ColumnCaption(2)="Taille"
      ColumnCaption(3)="Type"
      ColumnCaption(4)="Modifié"
      Mask = "*.dll;*.exe;*.icl;*.ico;*.cur;*.ani"
      OnFileChange=Open
    END CREATE
    CREATE Splitter2 AS QSPLITTER
      Align=alBottom
      cursor=crVSplit
      width=5
    END CREATE
    CREATE box as QSCROLLBOX
      Align=alBottom
      height=150
      OnResize=ResizeImage
      CREATE image as QCanvasEx
        top=0
        left=0
        width=box.width-4
        height=box.height-4
        fillrect(0,0,image.width,image.height,&HFFFFFF)
        PopupMenu=Popup
        OnPaint=Draw
        OnMouseDown=SelectIco
      END CREATE
    END CREATE
    CREATE Infos AS QSTATUSBAR
       SizeGrip=false
       AddPanels "Nombre d'icons:","selection:"
       Panel(0).width=200
    END CREATE
END CREATE

'========================================================
' boite dialogue coordonnées x,y curseur
'========================================================
CREATE Form2 as QFORM
  width=300
  height=340
  caption="Coordonnées curseur"
  center
  borderstyle=4
  CREATE SpotInfo as QLABEL
    top=10
    left=15
    autosize=true
    caption="X:"+space$(3)+"Y:"
    transparent=true
  END CREATE
  CREATE BoxIco AS QSCROLLBOX
    top=40
    left=15
    width=260
    height=260
    CREATE ImgIco AS QCANVASEX
      left=0
      top=0
      width=256
      height=256
      OnPaint=DrawCursor
      OnMouseMove=InfoGrid
      OnMouseDown=CloseGrid
    END CREATE
  END CREATE
END CREATE

Form.ShowModal

sub OpenGrid
  Dim msgButton as integer

  msgButton=MessageBox("Convertir "+GetFileName(icon.filename)+" en curseur?",application.title,36)
  if msgButton=mrYes then form2.show
end sub

sub CheckIco
  if instr(lcase$(icon.filename),".ico")>0 then
    item14.enabled=true
  else
    item14.enabled=false
  end if
end sub

sub DrawCursor
  ImgIco.fillrect(0,0,256,256,&hffffff)
  ImgIco.DrawIco(0,0,256,256,Icon.handle)
  GridCursor
end sub

'============================
' Affichage grille zoom
'============================
Sub GridCursor
  dim ptHorz as integer
  dim ptVert as integer
  dim i as integer

  ptHorz=0
  ptVert=0
  ImgIco.pensize=1
  for i=1 to int(ImgIco.height/8)
    ptHorz=ptHorz+8
    ImgIco.line(0,ptHorz,ImgIco.width,ptHorz,&h0)
  next i
  for i=1 to int(ImgIco.width/8)
    ptVert=ptVert+8
    ImgIco.line(ptVert,0,ptVert,ImgIco.height,&h0)
  next i
End Sub

Sub InfoGrid(x as short,y as short)
  SpotInfo.caption="X:"+str$(int(x/8)+1)+" Y:"+str$(int(y/8)+1)
End Sub

Sub CloseGrid(Button as short,x as short,y as short)
  Form2.close
  icon.ConvertAsCursor(icon.filename,(x/8)+1,(y/8)+1)
  icon.filename=FullPathNoExt(icon.filename)+".cur"
  EXEList.Refresh
End Sub

Sub Open(file as string)
  icon.filename=file
  image.repaint
  infos.panel(0).caption="Nombre d'icons:"+str$(icon.count)
  infos.panel(1).caption="Selection:"
End Sub

Sub ResizeImage
 image.width=box.width-4
End Sub

Sub Draw()
  dim i as integer
  dim col as integer
  dim x as integer
  dim y as integer

  x=0
  y=0
  focus.remove(image.handle)
  image.fillrect(0,0,image.width,image.height,ImageColor)
  if icon.count>1 then
    if icon.count*Offset>(image.width-Offset) then
      col=icon.count/((image.width-Offset)/Offset)
      if box.height<(Offset*col+Offset) then
        image.height=Offset*col+Offset
      else
        image.height=box.height-4
      end if
    else
      image.height=box.height-4
    end if
    for i=0 to icon.count
      if x+Offset>image.width then
        x=0
        y=y+Offset
      end if
      icon.index=i
      image.DrawIco(x,y,0,0,Icon.handle)
      x=x+Offset
    next i
  else
    image.height=box.height-4
    image.DrawIco(0,0,0,0,Icon.handle)
  end if
End Sub

SUB ChangeDirectory
  EXEList.Directory =DirTree.Directory
END SUB

Sub ShowFiles
  EXElist.Mask=""
  if item3.checked then
    if EXElist.Mask="" then
      EXElist.Mask=EXElist.Mask+"*.ico"
    else
      EXElist.Mask=EXElist.Mask+";*.ico"
    end if
  end if
  if item4.checked then
    if EXElist.Mask="" then
      EXElist.Mask=EXElist.Mask+"*.icl"
    else
      EXElist.Mask=EXElist.Mask+";*.icl"
    end if
  end if
  if item5.checked then
    if EXElist.Mask="" then
      EXElist.Mask=EXElist.Mask+"*.dll"
    else
      EXElist.Mask=EXElist.Mask+";*.dll"
    end if
  end if
  if item6.checked then
    if EXElist.Mask="" then
      EXElist.Mask=EXElist.Mask+"*.exe"
    else
      EXElist.Mask=EXElist.Mask+";*.exe"
    end if
  end if
  if item7.checked then
    if EXElist.Mask="" then
      EXElist.Mask=EXElist.Mask+"*.cur;*.ani"
    else
      EXElist.Mask=EXElist.Mask+";*.cur;*.ani"
    end if
  end if
End Sub

Sub ShowIco
  if item3.checked then
    item3.checked=false
  else
    item3.checked=true
  end if
  ShowFiles
End Sub

Sub ShowIcl
  if item4.checked then
    item4.checked=false
  else
    item4.checked=true
  end if
  ShowFiles
End Sub

Sub ShowDll
  if item5.checked then
    item5.checked=false
  else
    item5.checked=true
  end if
  ShowFiles
End Sub

Sub ShowExe
  if item6.checked then
    item6.checked=false
  else
    item6.checked=true
  end if
  ShowFiles
End Sub

Sub ShowCur
  if item7.checked then
    item7.checked=false
  else
    item7.checked=true
  end if
  ShowFiles
End Sub

Sub ShowColor
  Dial.style=cdNormal
  if Dial.Execute then
    ImageColor=Dial.Color
    image.repaint
  end if
End Sub

Function Selection(x as long,y as long)as integer
  dim left as integer
  dim top as integer
  dim i as integer

  left=0
  top=0
  for i=1 to icon.count
    if left+Offset>image.width then
      left=0
      top=top+Offset
    end if
    if x>left and x<(left+32) and y>top and y<(top+32) then
      Selection=i
      IconSelect=i-1
      rect.left=left
      rect.top=top
      rect.right=left+32
      rect.bottom=top+32
      focus.start(image.handle,left-1,top-1)
      focus.draw(image.handle,left+34,top+34,true)
    end if
    left=left+Offset
  next i
End function

Sub SelectIco(button as long,x as long,y as long,shift as long)
  if Selection(x,y)=0 then focus.remove(image.handle)
  infos.panel(1).caption="Selection:icon"+str$(Selection(x,y))
End Sub

Sub MenuMask
  if item12.checked then
    item12.checked=false
  else
    item12.checked=true
  end if
End Sub

Sub ShowList(sender as QmenuItem)
  item21.checked=false
  item22.checked=false
  item23.checked=false
  item24.checked=false
  sender.checked=true
  Select Case sender.tag
  Case 1
    ExeList.ViewStyle=vsIcon
  Case 2
    ExeList.ViewStyle=vsSmallIcon
  Case 3
    ExeList.ViewStyle=vsList
  Case 4
    ExeList.ViewStyle=vsReport
  End Select
End Sub

Sub SaveAs
  If SaveDialog.Execute Then
    Select case SaveDialog.FilterIndex
    case 1
      icon.index=IconSelect
      if instr(lcase$(SaveDialog.filename),".ico")=0 then
        icon.saveToFile(SaveDialog.filename+".ico",pf4bit,item12.checked)
      else
        icon.saveToFile(SaveDialog.filename,pf4bit,item12.checked)
      end if
    case 2
      icon.index=IconSelect
      if instr(lcase$(SaveDialog.filename),".ico")=0 then
        icon.saveToFile(SaveDialog.filename+".ico",pf8bit,item12.checked)
      else
        icon.saveToFile(SaveDialog.filename,pf8bit,item12.checked)
      end if
    case 3
      dest.left=0
      dest.top=0
      dest.right=32
      dest.bottom=32
      bitmap.fillrect(0,0,32,32,&HFFFFFF)
      Bitmap.copyRect(Dest,image,rect)
      if instr(lcase$(SaveDialog.filename),".bmp")=0 then
        Bitmap.saveToFile(SaveDialog.FileName+".bmp")
      else
        Bitmap.saveToFile(SaveDialog.FileName)
      end if
    end Select
  end if
End Sub

Sub OnAbout
  about.AppName=AppTitle
  about.AppVersion=AppVersion
  about.Caption="A propos"
  about.text="Auteur:Glodt dominique"+chr$(13)+"License libre"
  about.image.icohandle=Code
  about.EmailFont.color=&hff0000
  about.email="dominique.glodt@libertysurf.fr"
  about.show
End Sub


Qid3Tag Component

With this component you can read / write id3 tags ver 1.x . It offers a combobox for genre selection too.

Qid3Tag Methods

Field | Type | R/W | Notes | Support
Filename | STRING | RW |  | W
Title | STRING | RW |  | W
Artist | STRING | RW |  | W
Album | STRING | RW |  | W
Year | STRING | RW |  | W
Comment | STRING | RW |  | W
Track | BYTE | RW |  | W
Genre | STRING | RW |  | W
Genreid | BYTE | RW |  | W
GenresList | QSTRINGLIST | R | Used internally (do not touch if you don't know what you're doing) | W
GenresCB | QCOMBOBOX | RW | Be sure it has a parent before any action !! | W

Qid3Tag Methods

Method | Type | Description | Params | Support
ReadTags | SUB | Reads id3 Tags | 0 | W
WriteTags | SUB | Writes id3 Tags | 0 | W
Loadlist | SUB | Loads genres list into GenresCB. Be careful... you MUST assign a parent to GenresCB before you use this function. |  |
Fitlength | FUNCTION (FitTag$, FitLen%) | External. Adds null characters to a text string until it reaches specified length. Cuts the string if the string length exceeds the specified length. | 2 | W

Qid3Tag Events

Event | Type | Occurs when... | Params | Support
None |  |  |  |

Qid3Tag Examples

$include "Qid3tag.inc"

declare sub ReadClickedFile
declare sub UpdateTags

CREATE Form AS QFORM
Caption = "Qid3Tag example"
Width = 381
Height = 244
Center
CREATE Label1 AS QLABEL
Caption = "Title"
Left = 176
Top = 24
Transparent = 1
END CREATE
CREATE Label2 AS QLABEL
Caption = "Artist"
Left = 176
Top = 56
Transparent = 1
END CREATE
CREATE Label3 AS QLABEL
Caption = "Album"
Left = 176
Top = 88
Transparent = 1
END CREATE
CREATE Label4 AS QLABEL
Caption = "Year"
Left = 176
Top = 120
Transparent = 1
END CREATE
create tnlabel as qlabel
caption = "Track"
left = 292
top = 120
transparent = 1
end create
CREATE Label5 AS QLABEL
Caption = "Comment"
Left = 176
Top = 152
Width = 48
Transparent = 1
END CREATE
CREATE Label6 AS QLABEL
Caption = "Genre"
Left = 176
Top = 184
Transparent = 1
END CREATE
CREATE FileListBox AS QFILELISTBOX
Left = 6
Top = 13
Height = 137
Directory = ".\"
onclick = ReadClickedFile
END CREATE
CREATE ed_title AS QEDIT
Left = 232
Top = 16
END CREATE
CREATE ed_artist AS QEDIT
Left = 232
Top = 48
END CREATE
CREATE ed_album AS QEDIT
Left = 232
Top = 80
END CREATE
CREATE ed_year AS QEDIT
Left = 232
Top = 112
width = 40
END CREATE
create ed_track as qedit
left = 332
top = 112
width = 20
end create
CREATE ed_comment AS QEDIT
Left = 232
Top = 144
END CREATE
CREATE ed_genre AS QEDIT
Left = 232
Top = 176
END CREATE
CREATE Button1 AS QBUTTON
Caption = "Write"
Left = 5
Top = 160
Width = 147
onclick = UpdateTags
END CREATE
END CREATE

dim mp3 as qid3tag
'The following code adds the GenresCB. It's optional
mp3.genrescb.parent = form
mp3.genrescb.top = 190
mp3.genrescb.left = 6
mp3.loadlist
  'use this one to load genres list into GenresCB

Form.ShowModal

sub ReadClickedFile
mp3.filename = Filelistbox.filename
mp3.readtags
mp3.genrescb.itemindex = mp3.genreid
ed_title.text = mp3.title
ed_artist.text = mp3.artist
ed_album.text = mp3.album
ed_year.text = mp3.year
ed_comment.text = mp3.comment
ed_track.text = str$(mp3.track)
ed_genre.text = mp3.genre
end sub

Sub UpdateTags
mp3.title = ed_title.text
mp3.artist = ed_artist.text
mp3.album = ed_album.text
mp3.year = ed_year.text
mp3.comment = ed_comment.text
mp3.track = val(ed_track.text)
mp3.genreid = mp3.genrescb.itemindex     'Pay attention,
  you have to give a valid genre id (BYTE),
'so you cannot pass mp3.genre (which is a STRING)
mp3.writetags
end sub


QImageDialog

Documentation component by D.Glodt (c)2004 Appendix A: QImageDialog

QImageDialog Component

QImageDialog is dialog box selection of files with visualization of the graphic types.

This component requires DLL NVIEWLIB for the visualization of the jig , gif, jpg, pcx, tga, dib, rle types ,
if this one is not present in the system or in the directory of executable, only the bmp, ico, cur, ani types will be
visualized.

QImageDialog Properties
Field | Type | R/W | Défault
Caption | STRING | R/W |
 | Title of dialog box |  |
FileName | STRING | R/W |
 | File name with path. |  |
Filter | STRING | R/W |
 | Filter for file type. |  |
FilterIndex | INTEGER | R/W |
 | Filter index for file type. |  |
InitialDir | STRING | R/W |
 | Set the initial directory |  |
DlgCaption | ARRAY OF STRING | R/W |
 | Label of controls of dialog box,in english by default item 1 is label of file name item 2 is label of file type item 3 is caption of open button item 4 is caption of cancel button |  |
ErrorLanguage | STRING | R/W |
 | Error language for dll. (French,English,German,Dutch,Portuguese,Spanish,Japanese,Italian) |  |
MultiSelect | BOOLEAN | R/W | FALSE
SelCount | INTEGER | R |
 | Number of file selected |  |
Selected | QSTRINGLIST | R/W |
 | Files selected with path |  |

QImageDialog Methods
Method | Type | Description | Params
Execute | FUNCTION AS BOOLEAN | Show the dialog box | 0

QImageDialog Events
Event | Type | Occurs when... | Params

QImageDialog Examples

$typecheck on
$include "object\QImageDialog.inc"

dim a as
QimageDialog
a.filter="Tous format(*.bmp;*.ico;*.ani;*.cur*.gif;*.jpg;*.dib;*.rle;*.tga;*.pcx)|*.bmp;*.ico;*.ani;*.cur*.gif;*.jpg;*.dib;*.rle;*.tga;*.pcx|Fichiers
bitmap(*.bmp)|*.bmp|Fichiers gif(*.gif)|*.gif|Fichiers jpg(*.jpg)|*.jpg|Fichiers
ico(*.ico)|*.ico|Fichiers curseur(*.cur;*.ani)|*.cur;*.ani"
a.caption="Ouvrir"
a.DlgCaption(1)="Nom
du fichier:"
a.DlgCaption(2)="Type
du fichier:"
a.DlgCaption(3)="Ouvrir"
a.DlgCaption(4)="Annuler"
a.errorLanguage="french"
a.MultiSelect=true
a.execute
end


QINI

Documentation component by D.Glodt (c)2000-2001 Appendix A: QINII

QINI Component

QINI is a component no visible to read and write init files for application.

QINI Properties
Field | Type | R/W | Default
FileName | STRING | RW |
 | Init file name (*.ini)
Exist | INTEGER | R | FALSE
 | TRUE if file exist
Section | STRING | LE |
 | Name of parameters section from file
WinDir | STRING | R |
 | Path of window dir
SystemDir | STRING | R |
 | Path of directory system window |  |
TempDir | STRING | R |
 | Path of directory temp window |  |

QINI Methods
Method | Type | Description | Params
Get | FUNCTION(Key$,Default$) AS STRING | Return the value of Key$ parameter | 2
Write | FUNCTION(Key$,Value$) AS LONG | Write value of Key$ parameter in the init file | 2

QINI Events
Event | Type | Occurs when... | Params

QINI Examples

$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\QINI.inc"

dim ini as QINI
ini.FileName="c:\Temp\test.ini"
ini.Section="Parametres"
ini.write("par1","1")
ini.write("par2","2")

CREATE Form AS QFORM
  Caption="init"
  Width=300
  Height=110
  Center
END CREATE
if ini.exist then form.caption=ini.get("par1","no param")
Form.ShowModal


QLine

Documentation component by Glodt dominique (c)2003 Appendix A: QLINE

QLINE Component

QLine is a line for separator of toolbar.

QLine Properties
Field | Type | R/W | Default
Align | INTEGER | RW | alNone
 | Align determines how the control aligns within its parent control.
Color | INTEGER | RW |
Cursor | INTEGER | RW | crDefault
Enabled | INTEGER | RW | True
Height | INTEGER | RW |
Hint | STRING | RW |
Left | INTEGER | RW | 0
Parent | QFORM/QPANEL/QTABCONTROL | W |
ShowHint | INTEGER | RW | False
Top | INTEGER | RW | 0
Width | INTEGER | RW |
Visible | INTEGER | RW | True

QLine Methods
Method | Type | Description | Params

QLine Events
Event | Type | Occurs when... | Params
OnClick | VOID | User clicked on line | 0
OnDblClick | VOID | User double clicked on line | 0

QLine Example

$TypeCheck on
$Include "Object\QLine.inc"

CREATE Form AS QFORM
Caption = "Line"
Width = 320
Height = 240
Center
CREATE Menu as QMainMenu
CREATE Menu1 as QMenuItem
caption="Fichier"
END CREATE
END CREATE
Create Line as QLine
Align=1
Left = 10
Top = 10
End Create
END CREATE

Form.ShowModal


'================= QMAXSPLITTER ==================
'
' This one's a doozy. A splitter control that emulates all of Delphi 6's splitter styles.
' It's based on a QPanel rather than QCanvas ' like the original for two reasons:
' 1. To get a handle
' 2. To improve drawing and aligning
' There are still some issues with this component, and they are:
' 1. Mouse trapping - if you move the mouse too fast, you leave the splitter behind. SetCapture
' doesn't seem to solve the problem, maybe sub-classing in the next version...
' 2. Setting MinSize to 0 sometimes causes resizing problems, I'm sure this is an oversight
' in the math, but I can live with it for now.
' 3. There are stil problems with CREATE, most notably the order in which ALIGNed components
' are created, as well as the order in which properties are assigned to sibling windows
' (Uncomment the "Color" in Rich3 and run. See what I mean? Now place the code for Rich3 AFTER
' the code for Split3. Problem solved!)
' Anyway, I had fun with it, I hope you will too.
' Psyclops )
' P.S. Sorry for the lack of comments, maybe in the
' next release...

'====================================================
'            Sample program
'====================================================

$include  "QMaxSplitter.inc"

CREATE Form AS QFORM
    Caption = "Normal QSPLITTER - Blah!"
    Visible = 1
    Visible = 0
    CREATE Splitter AS QSPLITTER
        Align = 3
        Width  = 10
        Beveled = 1
    END CREATE
        CREATE RichEd1 AS QRichEdit
        Align = 3
    END CREATE
    CREATE RichEd2 AS QRICHEDIT
        Align = 5
    END CREATE
END CREATE

CREATE Form2 AS QFORM
    Center
    Caption = "QMAXSPLITTER - Cool!"
    CREATE Pnl1 AS QPANEL
        Align = 1
        BevelOuter = 0
         CREATE Rich3 AS QRICHEDIT
            'Color = &HFF0000
            Align = 3
        END CREATE
        CREATE Split3 AS QMAXSPLITTER
            Style = rsNone
            Beveled = 1
            Align = 3
            Cursor = -14
            Hint = "Style: rsNone"
            ShowHint = 1
        END CREATE
        CREATE Rich5 AS QRICHEDIT
            Align = 5
        END CREATE
     END CREATE
     CREATE Split1 AS QMAXSPLITTER
        Align = 1
        Style = rsSolid
        Hint = "Style: rsSolid"
        ShowHint = 1
        MinSize = 0
     END CREATE
     CREATE Pnl5 AS QPANEL
        Align = 5
        BevelOuter = 0
        CREATE Rich4 AS QRICHEDIT
            Align = 4
        END CREATE
        CREATE Split4 AS QMAXSPLITTER
            Align = 4
            Cursor = -21
            Width = 20
            Style = rsUpdate
            MinSize = 0
            Hint = "Style: rsUpdate"
            Beveled = 1
            ShowHint = 1
        END CREATE
        CREATE Panel55 AS QPANEL
            Align = 5
            BevelOuter = 0
            CREATE Rich55 AS QRICHEDIT
                Align = 5
            END CREATE
            CREATE Split2 AS QMAXSPLITTER
                Align = 2
                Hint = "Style: rsPattern"
                ShowHint = 1
                Height = 5
                MinSize = 0
            END CREATE
            CREATE Rich2 AS QRICHEDIT
                Align = 2
            END CREATE
        END CREATE
    END CREATE
END CREATE

Form.Show
Form2.Show

DO
    DoEvents
LOOP UNTIL Form2.Visible = 0


QDrawMenu

Documentation component by D.Glodt (c)2001-2003 Appendix A: QDrawMenu

QDrawMenu Component

QDrawMenu is used to draw bitmap in an item of menu. Cannot make arrays of QDrawMenu and it must be declared at the GLOBAL level. Probably only Windows.

QDrawMenu Properties
Field | Type | R/W | Défault

QDrawMenu Methods
Method | Type | Description | Params
AddBitmap | SUB(SubMenu as QMenuItem,Item as QMenuItem,Picture as Qbitmap,Button as boolean,Backcolor as long) | Add a bitmap to item menu | 5
 | The Button parameter determines if it is necessary to reveal a button has the selection, the Backcolor parameter determines the color of transparency of the bitmap |  |
DelBitmap | SUB(SubMenu as QMenuItem,Item as QMenuItem) | Delete a bitmap from item menu | 2
MenuProc | SUB(hwnd&,uMsg&,wParam&,lParam&) | Procédure de menu | 4
 | This méthod must be set to event WndProc from QForm component |  |

QDrawMenu Events
Event | Type | Occurs when... | Params

QDrawMenu Examples

$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
$INCLUDE "QDrawMenu.inc"
$RESOURCE New_bmp as "New.bmp"
$RESOURCE Open_bmp as "Open.bmp"
$RESOURCE Save_bmp as "Save.bmp"
$RESOURCE Exit_bmp as "Exit.bmp"
$RESOURCE Cut_bmp as "Cut.bmp"
$RESOURCE Copy_bmp as "Copy.bmp"
$RESOURCE Paste_bmp as "Paste.bmp"
$RESOURCE Empty_bmp as "Empty.bmp"
declare SUB MenuItemClick (Sender AS QMENUITEM)
declare SUB Show
dim menu as qdrawmenu
dim picture as qbitmap
CREATE Form AS QForm
  Center
  Caption = "Ownerdraw Menus"
  OnShow=show
  WndProc=menu.MenuProc
 CREATE MainMenu AS QMainMenu
    CREATE FileMenu AS QMenuItem
      Caption = "&File"
      CREATE OpenItem AS QMenuItem
       Caption = "&Open"
       OnClick=MenuItemClick
      END CREATE
      CREATE NewItem AS QMenuItem
        Caption = "&New"
        OnClick=MenuItemClick
      END CREATE
      CREATE BreakItem AS QMenuItem
        Caption = "-"
      END CREATE
      CREATE ExitItem AS QMenuItem
        Caption = "E&xit"
        OnClick=MenuItemClick
      END CREATE
    END CREATE
    CREATE EditMenu AS QMenuItem
      Caption = "&Edit"
      CREATE CutItem AS QMenuItem
        Caption = "&Cut           Ctrl+X"
        OnClick=MenuItemClick
        ShortCut="CTRL+X"
      END CREATE
      CREATE CopyItem AS QMenuItem
        Caption = "&Copy        Ctrl+C"
        OnClick=MenuItemClick
        ShortCut="CTRL+C"
      END CREATE
      CREATE PasteItem AS QMenuItem
        Caption = "&Paste       Ctrl+V"
        OnClick=MenuItemClick
        ShortCut="CTRL+V"
      END CREATE
      CREATE SelectItem AS QMenuItem
        Caption = "&Select all  Ctrl+A"
        OnClick=MenuItemClick
        ShortCut="CTRL+A"
      END CREATE
    END CREATE
    CREATE Aff AS QMenuItem
      caption="show"
    END CREATE
  END CREATE
END CREATE
Form.ShowModal
Sub Show
  picture.bmpHandle=Open_bmp
  menu.AddBitmap(FileMenu,OpenItem,picture,true,&hC0C0C0)
  picture.bmpHandle=New_bmp
  menu.AddBitmap(FileMenu,NewItem,picture,true,&hC0C0C0)
  picture.bmpHandle=Exit_bmp
  menu.AddBitmap(FileMenu,ExitItem,picture,true,&hC0C0C0)
  picture.bmpHandle=cut_bmp
  menu.AddBitmap(EditMenu,CutItem,picture,true,&hC0C0C0)
  picture.bmpHandle=copy_bmp
  menu.AddBitmap(EditMenu,copyItem,picture,true,&hC0C0C0)
  picture.bmpHandle=paste_bmp
  menu.AddBitmap(EditMenu,pasteItem,picture,true,&hC0C0C0)
  picture.bmpHandle=empty_bmp
  menu.AddBitmap(EditMenu,SelectItem,picture,false,&hFFFFFF)
End Sub
SUB MenuItemClick (Sender AS QMENUITEM)
  ShowMessage("Thanks for clicking " + Sender.Caption)
END SUB

Contents


QMIDI

Documentation component by D.Glodt (c)2000-2002 Appendix A: QMIDI

QMIDI Component

QMIDI is a media component used to play midi sequences.

QMIDI Properties
Field | Type | R/W | Default
Timer | QTIMER | RW |
 | Control the fréquency of event OnChange.
Lenght | LONG | R |
 | Lenght of midi sequence.
State | INTEGER | R | VD_CLOSE
 | State of sequencer,can be MD_PLAY,MD_STOP,MD_PAUSE.
FileOpen | BOOLEAN | R | False
 | True if a midi file is open.
CurrentFrame | LONG | RW |
 | Position of midi sequence.
Error | STRING | R |
 | Text error if the OPEN méthod return FALSE |  |
Volume | INTEGER | RW | 0

QMIDI Methods
Method | Type | Description | Params
Close | SUB | Close the midi file | 0
Open | FUNCTION(FileName as string) | Open the midi file and return True if no error | 1
Play | SUB | Play the midi sequence | 0
Stop | SUB | Stop the midi sequence | 0
Pause | SUB | Set the player in mode pause | 0

QMIDI Events
Event | Type | Occurs when... | Params
OnChange | (position as long) | Sequence position in mode play | 1

QMIDI Examples

'**************************************************************************
'* application:player midi                                               *
'* auteur:D.Glodt                                                         *
'* date:7-4-2001                                                          *
'**************************************************************************
$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\QMidi.inc"

$RESOURCE PLAYBMP as "play.bmp"
$RESOURCE STOPBMP as "Stop.bmp"
$RESOURCE PAUSEBMP as "Pause.bmp"
$RESOURCE MIDIICO as "midi.ico"

Declare Sub Play
Declare Sub Stop
Declare Sub Pause
Declare Sub Open
Declare Sub Close
Declare Sub Quitter
Declare Sub TrackBarChange
Declare Sub PostimerOnTimer(Position as long)

Dim OpenDialog as QOpenDialog
OpenDialog.Filter="Fichier midi|*.mid"
OpenDialog.Caption= "Selectionner une séquence"
Dim midi as QMidi
midi.OnChange=PostimerOnTimer
midi.timer.interval=200

CREATE Form AS QFORM
    Caption="Midi"
    Width=288
    Height=110
    Center
    BorderStyle=bsSingle
    icoHandle=MIDIICO
    OnClose=Quitter
    CREATE MENU AS QMAINMENU
      CREATE FileMenu AS QMENUITEM
        Caption="&Fichier"
        CREATE Item1 AS QMENUITEM
          Caption="&Ouvrir"
          OnClick=Open
        END CREATE
        CREATE Item2 AS QMENUITEM
          Caption="&Fermer"
          OnClick=Close
        END CREATE
        CREATE Item3 AS QMENUITEM
          Caption="-"
        END CREATE
        CREATE Item4 AS QMENUITEM
          Caption="&Quitter"
          OnClick=Quitter
        END CREATE
      END CREATE
    END CREATE
    CREATE Panel1 AS QPANEL
        Left=0
        Top=0
        Width=281
        Height=60
        BevelOuter=bvNone
        CREATE BtPlay AS QCOOLBTN
            BMPHandle=PLAYBMP
            Left=8
            Top=6
            Width=28
            Height=28
            Flat=true
            Hint="Play"
            ShowHint=true
            GroupIndex=1
            OnClick=Play
        END CREATE
        CREATE BtStop AS QCOOLBTN
            BMPHandle=STOPBMP
            Left=46
            Top=6
            Width=28
            Height=28
            Down=true
            Flat=true
            Hint="Stop"
            ShowHint=true
            GroupIndex=1
            OnClick=Stop
        END CREATE
        CREATE BtPause AS QCOOLBTN
            BMPHandle=PAUSEBMP
            Left=84
            Top=6
            Width=28
            Height=28
            Flat=true
            GroupIndex=1
            Hint="Pause"
            ShowHint=true
            OnClick=Pause
        END CREATE
        CREATE TrackBar1 AS QTRACKBAR
            TickMarks=tmBoth
            TickStyle=tsNone
            Left=2
            Top=36
            LineSize=0
            Width=272
            Height=21
            OnChange=TrackBarChange
        END CREATE
    END CREATE
END CREATE

Form.ShowModal

Sub Open
  If OpenDialog.Execute Then
   midi.close
   if midi.open(OpenDialog.FileName) then
     TrackBar1.Max=midi.lenght
     TrackBar1.Position=0
   end if
  end if
End Sub

Sub Close
  midi.close
End Sub

Sub Play
  midi.play
End Sub

Sub Stop
  midi.stop
  TrackBar1.Position=0
End Sub

Sub Pause
  midi.pause
End Sub

Sub TrackBarChange
  midi.currentFrame=TrackBar1.Position
End Sub

Sub PostimerOnTimer(Position as long)
  TrackBar1.Position=Position
  If midi.state=MD_STOP then
    midi.stop
    TrackBar1.Position=0
    BtStop.Down=True
  end if
End Sub

Sub Quitter
  midi.close
  form.close
End Sub


QPageSetup

Documentation component by D.Glodt (c)2000-2002 Appendix A: QPageSetup

QPageSetup Component

INCLUDED IN RAPIDQ2.INC
QPageSetup is a printer dialog box with other additions. If you have RapidQ2.inc then the
Caption property should work with another WndProc command, otherwise don't use the
Caption property.

QPageSetup Properties
Field | Type | R/W | Défault
DisablePrinter | BOOLEAN | R/W | False
 | Printer configuration. |  |
DisablePaper | BOOLEAN | R/W | False
 | Choice of paper. |  |
DisableOrient | BOOLEAN | R/W | False
 | Selection paper orientation. |  |
DisableMargins | BOOLEAN | R/W | False
 | Margins paper |  |
Orinetation | BOOLEAN | R | FALSE
 | Orientation paper ,true value is landscape?false is portrait |  |
MarginLeft | LONG | R/W | 0
 | Margin left in mm |  |
MarginTop | LONG | R/W | 0
 | Margin top in mm |  |
MarginRight | LONG | R/W | 0
 | Margin right in mm |  |
MarginBottom | LONG | R/W | 0
 | Margin bottom in mm |  |
PageWidth | LONG | R |
 | Page width in mm |  |
PageHeight | LONG | R |
 | Page height in mm |  |
Caption | STRING | RW |
 | Title dialog box |  |

QPageSetup Methods
Method | Type | Description | Params
Execute | SUB | Show printer dialog box |

QPageSetup Events
Event | Type | Occurs when... | Params

QPageSetup Examples
$TYPECHECK ON
$Include "Rapidq2.inc"
Declare Sub PageDlg

Dim Setup as QPageSetup
CREATE Form AS QFORM
Caption = "Mise en page"
Width = 300
Height =200
Center
CREATE Label1 AS QLABEL
Caption = ""
Left=12
Top=14
Width=200
Height=100
END CREATE
CREATE Button1 AS QBUTTON
Caption="Setup"
Left=100
Top=120
OnClick=PageDlg
END CREATE
END CREATE
Setup.MarginLeft=25
Setup.MarginTop=25
Setup.MarginRight=25
Setup.MarginBottom=25
Setup.Caption="Mise en page"
Form.ShowModal

Sub PageDlg
If Setup.Execute then
label1.caption="MarginLeft:"+str$(setup.marginLeft)+chr$(13)+ _
"MarginTop:"+str$(setup.marginTop)+chr$(13)+ _
"MarginRight:"+str$(setup.marginRight)+chr$(13)+ _
"MarginBottom:"+str$(setup.marginBottom)+chr$(13)+ _
"PageWidth:"+str$(setup.pageWidth)+chr$(13)+ _
"PageHeight:"+str$(setup.pageHeight)+chr$(13)+ _
"Orinetation:"+str$(setup.orientation)
end if
End Sub


QPrinterInfo

Documentation component by D.Glodt (c)2002-2003 Appendix A: QPrinterInfo

QPrinterInfo Component

QPrinterInfo is a component with more information about défault printer.

QPrinterInfo Properties
Field | Type | R/W | Default

QPrinterInfo Methods
Method | Type | Description | Params
Scale | FUNCTION AS DOUBLE | return the printer scale for image bitmap | 0
Dpi | FUNCTION AS INTEGER | return number of points by inch | 0
Ppm | FUNCTION AS DOUBLE | return number of pixels by millimeter | 0
MetricToPixel | FUNCTION(mm as double) AS INTEGER | return convert millimeters to pixels | 1
PixelToMetric | FUNCTION(pixel&) AS DOUBLE | return convert pixels en millimeters | 1
HorzPageSize | FUNCTION AS INTEGER | return page width to millimeters | 0
VertPageSize | FUNCTION AS INTEGER | return page height to millimeters | 0
PageWidth | FUNCTION AS INTEGER | return page width to pixels | 0
PageHeight | FUNCTION AS INTEGER | return page height to pixels | 0
PhWidth | FUNCTION AS INTEGER | return physical page width to pixels | 0
PhHeight | FUNCTION AS INTEGER | return physical page height to pixels | 0
PhHorz | FUNCTION AS INTEGER | return physical page width to millimeters |
PhVert | FUNCTION AS INTEGER | return physical page height to millimeters | 0
PhMarginX | FUNCTION AS DOUBLE | return physical margin x to millimeters | 0
PhMarginY | FUNCTION AS DOUBLE | return physical margin y to millimetres | 0
PhLeftMargin | FUNCTION AS INTEGER | return physical margin x to pixels | 0
PhTopMargin | FUNCTION AS INTEGER | return physical margin y to pixels | 0

QPrinterInfo Events
Event | Type | Occurs when... | Params

QPrinterInfo Exemples


QProcess

Documentation component by D.Glodt (c)2003 Appendix A: QProcess

QProcess Component

QProcess is a no visible component, it function is to execute process background via a user routine.

QProcess Properties
Priority | LONG | R/W | 0
 | Process priority with following values: ProcessLow=-2 ProcessBelowNormal=-1 ProcessNormal=0 ProcessHight=2 ProcessAboveNormal=1 ProcessTimeCritical=15 ProcessIdle=-15 |  |

QProcess Methods
Method | Type | Description | Params
Open | SUB | execute process | 0
Close | SUB | Stop process | 0

QProcess Events
Event | Type | Occurs when... | Params
OnProcess |  | Process execution | 0

QProgress Example

$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
$include "Object\QProcess.inc"
'Subs internal
declare sub rout1
DECLARE SUB OpenClick
DECLARE SUB SendClick
DECLARE SUB fin
'Variables globales
dim num as long
dim process as QProcess
process.OnProcess=rout1 'process routine
CREATE Form ASQFORM
Caption = "Test process"
Width=200
Height=200
Center
CREATE OpenButton ASQBUTTON
Caption="&Open"
Left=20
Top=50
height=20
OnClick=OpenClick
END CREATE
CREATE butexit ASQBUTTON
Caption="Close"
Left=20
Top=75
height=20
Enabled=0
OnClick=fin
END CREATE
CREATE ED ASQEDIT
left=10
top=10
width=100
END CREATE
END CREATE
Form.ShowModal

SUB fin
process.close
OpenButton.enabled=1
end sub

SUB OpenClick
OpenButton.enabled=0
butexit.enabled=1
process.priority=ProcessNormal
process.open
END SUB

sub rout1 ' process routine
while true
sleep 0.1
num++
ed.text="Count"+str$(num)
wend
end sub


QProgress

Documentation component by D.Glodt (c)2000-2001 Appendix A: QProgress

QProgress Component

QProgressBar is a progress bar.Used visually to give users the progress of an operation.

QProgress Properties
Field | Type | R/W | Défault
Handle | INTEGER | RW |
Height | INTEGER | RW |
Left | INTEGER | RW | 0
Parent | Handle QFORM/QPANEL/QTABCONTROL | RW |
Top | INTEGER | RW | 0
Width | INTEGER | RW |
Visible | INTEGER | RW | True
Value | INTEGER | RW |
 | Progress value.

QProgress Methods
Method | Type | Description | Params

QProgress Events
Event | Type | Occurs when... | Params

QProgress Examples

$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\QProgress.inc"

Declare Sub Start
Declare Sub Display

dim pourcent as integer
dim tempo as QTIMER
tempo.interval=100
tempo.enabled=False
tempo.OnTimer=Display
dim Bar as QProgress

CREATE Form AS QFORM
Caption = "Progress Bar"
Width = 350
Height = 180
Center
CREATE Button1 AS QBUTTON
Caption = "Start"
Left = 125
Top = 100
OnClick=Start
END CREATE
END CREATE
Bar.parent=form.handle
Bar.left=10
Bar.Top=40
Bar.Width=305
Bar.Height=25
Form.ShowModal

Sub Display
if pourcent<100 then
pourcent=pourcent+1
Bar.Value=pourcent
else
tempo.enabled=False
end if
End Sub

Sub Start
pourcent=0
Bar.Value=0
tempo.enabled=True
End Sub


QREDEX.htm

'
' --------------------------------------------------------------------
' QREDEX OBJECT               2002-2005            By Jacques Philippe
'
' EXTENDS QRICHEDIT with  COPY, CUT, PASTE, DELETE, SELECT ALL, UNDO,
'        SEARCH,  REPLACE,  SAVEPOSITION,  RESTOREPOSITION,
'        SETMAXTEXTSIZE(Size), EXTENDSIZELIMIT, CHANGEFONT,
'        CHANGEFONTCOLOR, CHANGEBGCOLOR, TOPLINEINDEX, BOTTOLINEINDEX
'
' DOCUMENTATION : TEXT FORMAT
'
' V 0.0.3  2002 : major modification nearly a copy of Psyclops420 work.
'          See Yahoo RapidQ Group message #9414
' V 1.0.0  April 2005 added Search, Replace, SavePosition,
'          RestorePosition, ChangeFont, ChangeFontColor, ChangeBgColor,
'          SetMaxTextSize, ExtendSizeLimit
' V 1.1.0  June 2005 added TopLineIndex, BottomLineIndex
' --------------------------------------------------------------------
'
'  $INCLUDE "QREDEX.INC"     ' Will be the new QRichEdit
'
'  Example :
'       Create QRED As QRICHEDIT
'           Align = alClient
'           Font.Name = "courier"
'           Font.Size = 8
'           Font.Color = &H80FFFF
'           Color = &H800000
'           ReadOnly =  False
'           WordWrap = False
'           ScrollBars = ssBoth
'           HideSelection = False
'           PlainText = True
'           ExtendSizeLimit
'           SetMaxTextSize (4E6)
'       End Create
'
'       Create mnuChangeFontAndColor AS QMENUITEM
'           Caption = "&FONT and COLORS    "
'           Create mnuChangeFont AS QMENUITEM
'               Caption = "&CHANGE FONT    "
'               OnClick = OnClic_AnyMenu
'           End Create
'           Create mnuChangeFontColor AS QMENUITEM
'               Caption = "&CHANGE FONT COLOR    "
'               OnClick = OnClic_AnyMenu
'           End Create
'           Create mnuChangeBgColor AS QMENUITEM
'               Caption = "&CHANGE BG_COLOR    "
'               OnClick = OnClic_AnyMenu
'           End Create
'       End Create
'
'       Case mnuChangeFont.Handle
'           .ChangeFont
'       Case mnuChangeBgColor.Handle
'           .ChangeBgcolor
'       Case mnuChangeFontColor.Handle
'           .ChangeFontcolor
'       Case mnuGetTopBottomLinesIndex.Handle
'           ShowMessage ("   TOP VISIBLE LINE INDEX = " & Str$(.TopLineIndex) _
'                  & "\n\nBOTTOM VISIBLE LINE INDEX = " & Str$(.BottomLineIndex))
'
' --------------------------------------------------------------------
'  DOCUMENTATION
'  =============
'      - This Extends QRichEdit so See Component QRichEdit of RapidQ.
'        Only Property PopUpMenu Is Involved/Changed
'      - After Including the QREDEX.INC file, your QRichEdit will have
'        Undo, Copy, Cut, Paste, Delete, Select All, Search, Replace
'        in it's Popupmenu. New methods opening DialogBox: ChangeFont,
'        ChangeBgColor, ChangeFontColor and SavePosition, RestorePosition,
'        TopLineIndex, BottomLineIndex, SetMaxTextSize, ExtendSizeLimit.
'
'   IN POPUPMENU :  COPY , CUT , PASTE , DELETE , SELECT ALL, UNDO,
'        SEARCH,  REPLACE .
'        Due to RapidQ CodePtr limitation, it was not possible to use
'        the  Windows Search and Replace tool.
'
'   NEW PROPERITIES and METHODS
'   ---------------------------
'   USEPOPUP   allows menu to PopUp when Right Clicking   R/W  Default = True
'
'   TOPLINEINDEX returns the index of the top visible line
'
'   BOTTOMLINEINDEX returns the index of the bottom visible line
'
'   SAVEPOSITION, RESTOREPOSITION save the index of top_left character
'        in the RichEdit and restore it. The Caret position if set,
'        is saved and restored too.
'
'        If you want to save the position and restore the position by
'        your own mean, save the two Public properties
'        QRedEx.SavedTopLeft As long and QRedEx.SavedCaretPosition As Long
'        somewhere, then restore them before to call the
'        QRedEx.RestorePosition method.
'
'        Ex : DefInt mySavedTopLeft = QRedEx.SavedTopLeft
'             DefInt mySavedCaretPosition = QRedEx.SavedCaretPosition
'             ' ...
'             QRedEx.SavedTopLeft = mySavedTopLeft
'             QRedEx.SavedCaretPosition = mySavedCaretPosition
'             QRedEx.RestorePosition
'
'   SETMAXTEXTSIZE(Size)  method that set the maximum RichEdit text size
'
'   EXTENDSIZELIMIT       method that sets the maximum RichEdit text size
'             to the value of the public property QRedEx.RichTextSizeLimit.
'             QRedEx.RichTextLimitSize is initialised at 1 MegaByte.
'
'   CHANGEFONT, CHANGEFONTCOLOR, CHANGEBGCOLOR
'             Method that will call a DialogBox that will set the
'             QRedEx.Font, QRedEx.Font.color and QRedEx BackGroundColor
'
'   OTHER PUBLIC PROPERTIES OF QREDEX
'        UsePopup AS LONG PROPERTY SET Set_Popup
'        RichTextSizeLimit As Long
'        SavedTopLeft As Long
'        SavedBottomRight As Long
'        SavedCaretPosition As Long
'        ptPoint As String * 20         ' Used with Window Message EM_GETRECT, EM_CHARFROMPOS
'     ' Search Form
'        frmSearch As QForm
'        edtSearchFor As QEdit
'        lblSearchFor AS QLabel
'        btnSearch As QButton
'        chkSearchCaseS As QCheckBox
'        chkSearchWholeWordsOnly As QCheckBox
'     ' Replace Form
'        frmReplace As QForm
'        lblToBeReplaced AS QLabel
'        edtToBeReplaced As QEdit
'        lblReplacedBy AS QLabel
'        edtReplacedBy As QEdit
'        btnReplace As QButton
'        btnFindNext As QButton
'        btnReplaceAll As QButton
'        chkReplaceCaseS As QCheckBox
'        chkReplaceWholeWordsOnly As QCheckBox
'        chkReplaceUp As QCheckBox
'
'    The search and replace forms are public so you can modify any of
'    their components properties or call any of their Methods.
' --------------------------------------------------------------------
'


QrPanel

Rapid-Q Custom Component - 2004

-

QrPanel Component

QrPanel implements a generic container for your components just like QPanel, but this one has
round corners if you like. QrPanel can however completely replace QPanel since you can toggle
on and off the value which makes QrPanel have round corners.

QrPanel Properties

Field | Type | R/W | Default | Support
Align | INTEGER | RW | alNone | W
Alignment | INTEGER | RW | taCenter | W
BevelInner | INTEGER | RW | bvNone | W
BevelOuter | INTEGER | RW | bvRaised | W
BevelWidth | INTEGER | RW | 1 | W
BorderStyle | INTEGER | RW | bsNone | W
Caption | STRING | RW |  | W
ClientHeight | INTEGER | RW |  | WX
ClientWidth | INTEGER | RW |  | WX
Color | INTEGER | RW |  | W
Cursor | INTEGER | RW | crDefault | W
Enabled | INTEGER | RW | True | WX
Font | QFONT | W |  | W
Height | INTEGER | RW |  | WX
Hint | STRING | RW |  | W
Left | INTEGER | RW | 0 | WX
Parent | QFORM/QPANEL/QTABCONTROL | W |  | WX
RBorder | BYTE | RW | 0 | W ( X ? )
RndX | LONG | RW | 20 | W ( X ? )
RndY | LONG | RW | 20 | W ( X ? )
ShowHint | INTEGER | RW | False | W
TabOrder | INTEGER | RW |  | W
Tag | INTEGER | RW |  | WXG
Top | INTEGER | RW | 0 | WX
Width | INTEGER | RW |  | WX
Visible | INTEGER | RW | True | WX

QrPanel Methods

Method | Type | Description | Params | Support
Repaint | SUB | Refreshes panel and all contents | 0 | W

QrPanel Events

Event | Type | Occurs when... | Params | Support
OnClick | VOID | User clicked on open area of panel | 0 | WX
OnDblClick | VOID | User double clicked panel | 0 | W
OnMouseDown | SUB (Button%, X%, Y%, Shift%) | Mouse button held down | 4 | W
OnMouseMove | SUB (X%, Y%, Shift%) | Mouse moves over panel | 3 | W
OnMouseUp | SUB (Button%, X%, Y%, Shift%) | Mouse button is released | 4 | W

QrPanel Example

$INCLUDE "QRPANEL.INC"

$INCLUDE "RAPIDQ.INC"

CREATE Form AS QFORM

Caption = "QPANEL vs. QRPANEL"

Width = 401

Height = 233

Center

Borderstyle = 4

CREATE Panel1 AS QPANEL

Left = 5

Top = 5

Caption = "Corned Panel"

Height = 193

Width = 185

Color = &hFF0000

END CREATE

CREATE Panel2 AS QRPANEL

Left = 197

Top = 5

Caption = "Round Corner Panel"

Height = 193

Width = 185

TabOrder = 1

rBorder = 1

RndX = 25

RndY = 25

Color = &h0000FF

END CREATE

END CREATE

Form.ShowModal


QRun

Documentation component by D.Glodt (c)2001-2002

Appendix A: QRun

QRun Component

QRun is a coponent no visible to execute applications or associated files.it can find all desktop application and take their control.

QRun Properties

Field | Type | R/W | Default

QRun Methods

Method | Type | Description | Params
FindApplication | FUNCTION(FileName$) AS STRING | Return the name and path of associated application. | 1
FileRun | SUB(FileName$,cmdShow%) | Run a associated file or an exe file. cmdShow can be SW_HIDE SW_SHOWNORMAL SW_NORMAL SW_SHOWMINIMIZED SW_SHOWMAXIMIZED SW_MAXIMIZE SW_SHOWNOACTIVATE SW_SHOW SW_MINIMIZE SW_SHOWMINNOACTIVE SW_SHOWNA SW_RESTORE SW_SHOWDEFAULT SW_MAX | 2
ExeRun | SUB(ExeName$,Param$,cmdShow%) | Run an exe file with parameters. | 3
EnumWindow | FUNCTION(All&) As Boolean | The desktop windows will be returned by event OnEnumWindows if the parameter All is at false , only visibles windows will be returned.The method return true if there is find windows | 1
FindChild | FUNCTION(handle&,class$,name$) As Boolean | Return handle of children control by arguments following: handle& is the parent handle , class$ is the class name of search control , name$ is the title of control. | 3
EnumFromPoint | FUNCTION(X&,Y&) As Boolean | Return the window at the position x,y by event OnEnumFromPoint. The method return true if there is a find window. | 2
Close | SUB(handle&) | Close window identify by handle parameter. | 1
Minimize | SUB(handle&) | Minimize window identify by handle parameter. | 1
Maximize | SUB(handle&) | Maximize window identify by handle parameter. | 1
Restore | SUB(handle&) | Restore window state identify by handle parameter. | 1
SetFocus | SUB(handle&) | Set focus on control identify by handle parameter. | 1
SetTopMost | SUB(handle&,flag&) | Put the window identify by handle parameter to the top level of Z order if parameter flag is at true | 2

QRun Events

Event | Type | Occurs when... | Params
OnEnumWindows | (handle&,name$,ClassName$) | On execution of the method EnumWindow | 3
OnEnumFromPoint | (handle&,name$,ClassName$) | On execution of the method EnumFromPoint | 3

QRun Examples

QRun Exemple 1

$typecheck on
$INCLUDE "Rapidq.inc"
$INCLUDE "Object\QRun.inc"

declare sub OuvrirClick
declare sub QuitterClick

dim App as QRun

CREATE Form AS QFORM
  Caption ="Execute"
  Width = 200
  Height = 200
  Center
  CREATE Menu AS QMAINMENU
    CREATE item1 AS QMENUITEM
      Caption="&Fichier"
      CREATE item2 AS QMENUITEM
        Caption="&Ouvrir"
        OnClick=OuvrirClick
      END CREATE
      CREATE item5 AS QMENUITEM
        Caption="-"
      END CREATE
      CREATE item6 AS QMENUITEM
        Caption="&Quitter"
        OnClick=QuitterClick
      END CREATE
   END CREATE
 END CREATE
END CREATE

Form.ShowModal

sub OuvrirClick
 dim file as QOPENDIALOG

 file.Filter="Fichiers(*.*)|*.*"
 file.InitialDir=CurDir$
 if file.Execute then
 if App.FindApplication(file.fileName)<>"" then
 App.fileRun(file.fileName,SW_SHOW)
 end if
 end if
end sub

sub QuitterClick
 Form.Close
end sub

QRun Exemple 2

$typecheck on
$include "rapidq.inc"
$include "QFuncLib.inc"
$include "Object\QRun.inc"

declare sub rout1
declare sub rout2(handle as Long,name as string,ClassName as string)

dim app as QRun
    app.OnEnumWindows=rout2

create form as qform
  center
  caption="Enum windows"
  width=600
  height=400
  create lb as qlistbox
    width=300
    height=200
  end create
  create bt as qbutton
    caption="Enum"
    onclick=rout1
    left=340
  end create
end create

form.showmodal

sub rout1
  lb.clear
  app.enumWindow false
end sub

sub rout2(handle as Long,name as string,ClassName as string)
  if handle<>form.handle and handle<>application.handle then
    lb.additems name
    lb.additems ClassName
  end if
end sub


QSHFILEOperation

' ============================================================== '
' QSHFileOperation component - version 1 January 2002 '
' Marcin Szafran '
' Implemented API SHFileOperation function. '
' Allows copy, rename, delete and move files and folders '
' with wildcard and recursivly... and much more! '
' ***** BE CAREFULL WITH DELETE AND RECURSE! ***** '
' Thanks for Jacques Philippe for his help '
' ============================================================== '
'= QSHFileOperation methods description ==================

'--- Copying ---
' .CopyEx: Copying with extended attributes
' .Copy: Simple copying
' Usage ObjName.CopyEx("ExistingFileName(s)","SourceFileName(s)",flags,handle)
' ObjName.Copy("ExistingFileName(s)","SourceFileName(s)")
' RQ keyword: - (none)

'--- Moving and Renaming ---
' .MoveEx: Moving with extended attributes
' .Move: Simple moving
' .RenameEx: Renaming with extended attributes
' .Rename: Simple renaming
' Usage ObjName.MoveEx("ExistingFileName(s)","SourceFileName(s)",flags,handle)
' ObjName.Move("ExistingFileName(s)","SourceFileName(s)")
' ObjName.RenameEx("ExistingFileName(s)","SourceFileName(s)",flags,handle)
' ObjName.Rename("ExistingFileName(s)","SourceFileName(s)")
' RQ keyword: RENAME (does not work with dirs)

'--- Deleting ---
' .DeleteEx: Deleting with deleting confirmation on/off and other extended attributes - enables delete to Recycle Bin
' .Delete: Simple deleting with deleting confirmation on/off - enables delete to Recycle Bin
' Usage ObjName.DeleteEx("FileName(s)",to_Bin_on/off,confirm_on/off,flags,handle)
' ObjName.Delete("FileName(s)",to_Bin_on/off,confirm_on/off)
' RQ keyword: KILL (does not work with dirs)

'= QSHFileOperation properties description ===============

' .DefaultFlagsEx: Setting default flags for methods with extended attributes (.MethodNameEx) - now = 0
' .DefaultFlags: Setting default flags for simple methods (.MethodName)

' I hope that parameters names are clear

Function CopyEx (dSHfoFrom As String, dSHfoTo As String, _
SHfoFlags As Integer, SHfoHandle As Long) As Long

Function Copy (dSHfoFrom As String, dSHfoTo As String) As Long

Function MoveEx (dSHfoFrom As String, dSHfoTo As String, _
SHfoFlags As Integer, SHfoHandle As Long) As Long

Function Move (dSHfoFrom As String, dSHfoTo As String) As Long

Function RenameEx (dSHfoFrom As String, dSHfoTo As String, _
SHfoFlags As Integer, SHfoHandle As Long) As Long

Function Rename (dSHfoFrom As String, dSHfoTo As String) As Long

Function DeleteEx (dSHfoFrom As String, SHfoToBin As Integer, SHConfirm As Integer, _
SHfoFlags As Integer, SHfoHandle As Long) As Long

Function Delete (dSHfoFrom As String, SHfoToBin As Integer, SHConfirm As Integer) As Long

'= CONSTANTS =============================================

'--- Operations ---

Const foMove = &H1 ' Move the files specified in pFrom to the location specified in pTo
Const foCopy = &H2 ' Copy the files specified in the pFrom member to the location specified in the pTo member
Const foDelete = &H3 ' Delete the files specified in pFrom
Const foRename = &H4 ' Rename the file specified in pFrom. You cannot use this flag to rename multiple files with a single function call. Use FO_MOVE instead

'--- Flags - should be set with OR operator if used more than one ---
'--- Constants names were changed to RapidQ kind --------------------

Const fofAllowUndo = &H40 ' Preserve Undo information, if possible. If pFrom does not contain fully qualified path and file names, this flag is ignored
Const fofConfirmMouse = &H2 ' Not currently used
Const fofFilesOnly = &H80 ' Perform the operation on files only if a wildcard file name (*.*) is specified
Const fofMultiDestFiles = &H1 ' The pTo member specifies multiple destination files (one for each source file) rather than one directory where all source files are to be depos
Const fofNoConnectedElements = &H2000 ' Do not move connected files as a group. Only move the specified files
Const fofNoConfirmation = &H10 ' Respond with "Yes to All" for any dialog box that is displayed
Const fofNoConfirmMkDir = &H200 ' Do not confirm the creation of a new directory if the operation requires one to be created
Const fofNoCopySecurityAttribs = &H800 ' Do not copy the security attributes of the file
Const fofNoErrorUI = &H400 ' Do not display a user interface if an error occurs
'Const fof_RecurseReparse = ' Recurse into reparse points. The default is to not recurse
'Const fof_NoRecurseReparse = ' Treat reparse points as objects, not containers. You must set _WIN32_WINNT to 5.01 or later to use this flag
Const fofNoRecursion = &H1000 ' Only operate in the local directory. Don't operate recursively into subdirectories
Const fofRenameOnCollision = &H8 ' Give the file being operated on a new name in a move, copy, or rename operation if a file with the target name already exists
Const fofSilent = &H4 ' Do not display a progress dialog box
Const fofSimpleProgress = &H100 ' Display a progress dialog box but do not show the file names
'Const fofWantMappingHandle = &H20 ' If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name mapping object containing their old and new names to the hNameMappings member
Const fofWantNukeWarning = &H4000 ' Send a warning if a file is being destroyed during a delete operation rather than recycled. This flag partially overrides FOF_NOCONFIRMATION


QShutDown

Documentation by John Kelly QShutDown

QSHUTDOWN Component

A small component for Logging off or shutting down Windows.

QLine Methods
Field | Type | R/W | Default
Logoff | VOID | W | *
 | Immediate Logoff, you should prompt the user before executing
Reboot | VOID | W |
 | Restart Windows
ShutDown | VOID | W |
 | Should prompt the user before executing
ShutDownForce | VOID | W |
 | Causes immediate logOff and shutdown

QLine Events
Event | Type | Occurs when... | Params

None

QLine Example

$TypeCheck on
$Include <QShutDown.inc>
DIM MyShutDown AS QShutDown

MyShutdown.LogOff


QSkin

Documentation component by D.Glodt (c)2003 Appendix A: QSkin

QSkin Component

QSkin is component inherited from QForm used to have the shapes and skins of file bitmap.

QSkin has all the properties, methods and events of QForm.
Dimensions of QSkin are those of the size of the affected bitmap to its Skin property.

QSkin Properties
Field | Type | R/W | Défault
Skin | QIMAGE | R/W |
 | Bitmap Image to the skin of window |  |
OffsWidth | SHORT | R/W |
 | Offset width form |  |
OffsHeight | SHORT | R/W |
 | Offset height form |  |

QSkin Methods
Method | Type | Description | Params
SetDeskBar | SUB | The application will be in the task bar during its reduction | 0
Resize | SUB | Resize window after a skin change | 0

QSkin Events
Event | Type | Occurs when... | Params

QSkin Example
$typecheck on
$optimize on
$include "Object\QSkin.inc"
$resource img as "clock.bmp" ' skin bitmap file
declare sub showTime
dim tim as qtimer
tim.interval=1000
tim.OnTimer=ShowTime

CREATE Form AS QSkin
Center
skin.bmpHandle=img ' using skin bitmap
skin.top=-1 ' offset position of bitmap
OffsWidth=-5 'offset width form
caption="Clock"
create clock as qlabel
top=60
left=80
font.bold=true
font.size=24
font.color=&hff0000
caption=Time$
labelStyle=2
transparent=true
end create
Create b1 as qbutton
top=140
left=120
kind=6
end create
END CREATE
form.shapeform(img,&hffffff) ' define the shape with the same skin bitmap
form.setdeskbar
Form.ShowModal

sub showTime
clock.caption=Time$
end sub


QSkinBtn

Documentation component by D.Glodt (c)2003 Appendix A: QSkinBtn

QSkinBtn Component

QSkinBtn is button component of skin type.

QSkinBtn Properties
Field | Type | R/W | Défault
btUp | QBITMAP | R/W |
 | Bitmap Image for up state. |  |
btDown | QBITMAP | R/W |
 | Bitmap image for down state. |  |
btEnable | QBITMAP | R/W |
 | Bitmap image for disable state. |  |
mode | SHORT | R/W | 0
 | Run mode button Mode to 0:same to a QButton Mode to 1:button stay a the down state after click. Mode to 2:button change state after each click. |  |
down | BOOLEAN | R/W | FALSE
 | down state of button |  |
Enabled | BOOLEAN | R/W | TRUE
Parent | QFORM,QPANEL,QTABCONTROL | W |
Left | INTEGER | R/W | 0
Top | INTEGER | R/W | 0

QSkinBtn Methods
Method | Type | Description | Params

QSkinBtn Events
Event | Type | Occurs when... | Params
OnClick |  | Click on button | 0

QSkinBtn Example
$typecheck on
$optimize on
$include "Rapidq.inc"
$include "QFuncLib.inc"
$include "Object\QSkin.inc"
$include "Object\QSkinBtn.inc"
$include "Object\QTextBtn.inc"
$include "Object\QFlashLabel.inc"
$include "Object\QVuMeter.inc"
$include "Object\QVideo.inc"

$resource img as "skin3.bmp"
$resource play1 as "play1.bmp"
$resource play2 as "play2.bmp"
$resource stop1 as "stop1.bmp"
$resource stop2 as "stop2.bmp"
$resource pause1 as "pause1.bmp"
$resource pause2 as "pause2.bmp"
$resource back1 as "back1.bmp"
$resource back2 as "back2.bmp"
$resource fwd1 as "foreward1.bmp"
$resource fwd2 as "foreward2.bmp"
$resource power1 as "power1.bmp"
$resource power2 as "power2.bmp"

declare sub quit
declare sub volume
declare sub SetVolume
declare sub open
declare sub play
declare sub stop
declare sub foreward
declare sub backward
declare sub pause
Declare Sub ShowTime(Position as long,timePos aslong)

const color1=&h660000
const color2=&hff9900
const color3=&h88FF66
const RazClock="00:00"

Dim OpenDialog asQOpenDialog
OpenDialog.Filter="Fichier vidéo(tout type)|*.avi;*.mpg;*.mpeg;*.mov|Fichier avi|*.avi|Fichier MPEG|*.mpg;*.mpeg|Fichier MOV|*.mov|"
OpenDialog.Caption= "Selectionner une vidéo"

CREATE Form ASQSkin
Center
skin.bmpHandle=img
skin.top=-1
skin.left=-1
caption="Player"
OffsWidth=-5
create display asqpanel
top=20
left=16
width=311
height=72
bevelinner=0
bevelouter=0
color=&h994400
create bar asqpanel
top=50
left=0
width=display.width
height=2
bevelinner=0
bevelouter=0
color=color1
end create
create FlashPlay
as
QFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=2
caption="Play"
end create
create FlashStop
as
QFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=16
caption="Stop"
state=true
end create
create FlashPause
as
QFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=30
caption="Pause"
end create
create FlashTime
as
QFlashlabel
DarkColor=color1
LightColor=color2
left=150
top=6
font.size=24
caption=RazClock
State=true
end create
create vu asQVuMeter
top=1
left=290
width=10
height=45
DarkColor=color1
LightColor=color2
value=50
end create
create btOpen
as
QTextBtn
UpColor=color1
DownColor=color2
left=5
top=55
font.bold=true
caption="Open"
OnClick=open
end create
create btVol
as
QTextBtn
UpColor=color1
DownColor=color2
left=265
top=55
font.bold=true
caption="Volume"
OnClick=Volume
end create
end create
create btPlay asQskinBtn
btUp.bmphandle=play1
btDown.bmphandle=play2
top=110
left=12
mode=1
OnClick=play
end create
create btStop asQskinBtn
btUp.bmphandle=stop1
btDown.bmphandle=stop2
top=110
left=44
OnClick=stop
end create
create btPause asQskinBtn
btUp.bmphandle=pause1
btDown.bmphandle=pause2
top=110
left=76
mode=1
OnClick=pause
end create
create btBack asQskinBtn
btUp.bmphandle=back1
btDown.bmphandle=back2
top=110
left=108
OnClick=backward
end create
create btFwd asQskinBtn
btUp.bmphandle=fwd1
btDown.bmphandle=fwd2
top=110
left=140
OnClick=foreward
end create
create btPower asQskinBtn
btUp.bmphandle=power1
btDown.bmphandle=power2
top=110
left=300
OnClick=quit
end create
END CREATE

CREATE Form2 ASQFORM
Caption="Volume"
Width=60
Height=190
Center
borderStyle=bsToolWindow
CREATE TbVol ASQTRACKBAR
cursor=crHandPoint
Orientation=tbVertical
Frequency=5
TickMarks=tmBoth
TickStyle=tsAuto
Left=5
Top=5
Max=0
Min=-100
Width=45
Height=150
position=-50
OnChange=SetVolume
END CREATE
END CREATE

CREATE video ASQVideo
Parent=0
volume=50
OnChange=ShowTime
timer.interval=200
BorderStyle=bsSizeable
END CREATE

form.shapeform(img,&hffffff)
form.setdeskbar
Form.ShowModal

Sub quit
video.close
form2.close
application.terminate
End Sub

Sub volume
form2.show
End Sub

Sub SetVolume
vu.value=Abs(TbVol.position)
video.volume=Abs(TbVol.position)
End Sub

Sub open
If OpenDialog.Execute Then
video.close
if video.open(OpenDialog.FileName)then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
video.caption=GetFileName(OpenDialog.FileName)
else
showmessage
video.error
end if
end if
End Sub

Sub play
if video.FileOpen=false
then
btPlay.Down=false
else
FlashPause.flash=false
FlashStop.state=false
FlashPlay.state=true
btPause.Down=false
video.play
end if
End Sub

Sub stop
video.stop
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
End Sub

Function GetMinutes(seconds aslong) asstring
dim min asinteger
dim sec asinteger
dim sMin asstring
dim sSec asstring

min=seconds/60
sec=seconds mod 60
if min<10 then
sMin="0"+str$(min)
else
sMin=str$(min)
end if
if sec<10 then
sSec="0"+str$(sec)
else
sSec=str$(sec)
end if
result=sMin+":"+sSec
End Function

Sub ShowTime(Position aslong,timePos
aslong)
FlashTime.caption=GetMinutes(timePos)
If Video.State=VD_STOP then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
end if
End Sub

Sub pause
if video.state=VD_PLAY then
video.pause
btPlay.down=false
FlashPlay.state=false
FlashPause.flash=true
else
if video.FileOpen=false
then
btPause.Down=false
end if
End Sub

Sub foreward
if (video.currentFrame+1)<video.lenght
then
video.currentFrame=video.currentFrame+1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub

Sub backward
if video.currentFrame>0 then
video.currentFrame=video.currentFrame-1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub


QSplash

Documentation component by D.Glodt (c)2003 Appendix A: QSplash

QSplash Component

QSplash is used for showing banner during a time before the opening of application.

A descriptive text of application can be added below the image or on the image.

QSplash Properties
Champs | Type | R/W | Défault
Image | QIMAGE | R/W |
 | Image to show |  |
Text | STRING | R/W |
 | Text about application |  |
TextFont | QFONT | R/W |
TextTransparent | BOOLEAN | R/W | False
 | Display text on image |  |
TextCenter | BOOLEAN | R/W | False
 | Text centered horizontal |  |
TextLeft | SHORT | R/W |
TextTop | SHORT | R/W |
 | Actif if property TextTransparent at True |  |

QSplash Methods
Method | Type | Description | Params
Show | SUB(Time%) | Show banner | 1

QSplash Events
Event | Type | Occurs when... | Params

QSplash Example
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
$INCLUDE "Object\QSplash.inc"
DECLARE SUB DisplaySplashForm
$resource banner as "banner.bmp"

Dim splash as QSplash
splash.image.bmphandle=banner
splash.TextCenter=True
splash.TextFont.size=10
splash.Text="Version 1.0 Copyright(c) D.Glodt"

CREATE MainForm AS QFORM
Caption = "MainForm"
Width = 520
Height = 340
Center
OnShow=DisplaySplashForm
END CREATE

SUB DisplaySplashForm
Splash.Show(3)
End Sub
MainForm.ShowModal


QStatusBarEx

Documentation component by D.Glodt (c)2003 Appendix A: QStatusBarEx

QStatusBarEx Component

QStatusBarEx is identical as QStatusBar with addition of QPanel components in order to be able to post images or other components.
It is necessary to use the AddPanel method before adding a QPanel component.

QStatusBarEx Property
Field | Type | R/W | Défault

QStatusBarEx Methods
Method | Type | Description | Params
AddOptPanel | SUB(QPANEL,index&) | Add a QPanel component in an existing panel, the parameter index& determines the position in the bar when several panel were added, a value 0 corresponds to the first panel of the bar. The Height property of the QPanel component must be lower at the Height property of the bar. | 2

QStatusBarEx Events
Event | Type | Occurs when... | Params

QStatusBarEx Examples
$TYPECHECK ON
$resource BM_OPEN as "open.bmp"
$include "Object\QStatusBarEx.inc"
CREATE Form AS QFORM
Caption="Form1"
Width=400
Height=240
Center
CREATE Panel as QPANEL
CREATE img as QIMAGE
bmpHandle=BM_OPEN
END CREATE
END CREATE
CREATE StatusBar1 AS QSTATUSBAREX
height=20
AddPanels "","","",""
Panel(0).Width=100
Panel(1).Width=100
Panel(2).Width=100
AddOptPanel Panel,1
END CREATE
END CREATE

Form.ShowModal


QStringGridEx

Documentation component by D.Glodt (c)2003 Appendix A: QStringGridExt

QStringGridEx Component

QStringGridEx is identical as QStringGrid allowing the use of the style of the lines identical to the columns.

This component uses a template parameter to define the number of row used.(dim grid have QStringGridEx<Size >)
The use of events OnSelectCell and OnDrawCell requires the use of the key word < inherit >.

QStringGridEx Properties
Field | Type | R/W | Défault
RowStyle | ARRAY OF INTEGER | R/W |
 | RowStyle determines the style of each row. 2 = grsList -- Row with a drop-down list for each item 1 = grsEllipsis -- Row with an ellipsis button for each item 0 = grsNone -- Normal row |  | grsNone
RowList | ARRAY OF STRING | R/W |
 | RowList maintains a list of strings deliminated by LF for use in Row lists. |  |

QStringGridEx Methods
Method | Type | Description | Params

QStringGridEx Events
Event | Type | Occurs when... | Params

QStringGridEx Example
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
$INCLUDE "Object\QStringGridEx.inc"
$ESCAPECHARS ON

CONST AgeList = "10\n11\n12\n13\n14\n15\n16\n17\n18\n19"

SUB EllipsisClick (Col AS LONG, Row AS LONG, Sender AS QSTRINGGRID)
Sender.Cell(Col, Row) = "Comments"+STR$(Row)
END SUB

CREATE Form AS QFORM
CREATE Grid AS QStringGridEx<1000> '1000 row
Align=alClient
AddOptions(goEditing,goColSizing)
FixedRows=1
FixedCols=1
ColCount=3
RowCount=5
DefaultRowHeight=20
DefaultColWidth=100
RowList(1)=AgeList
RowStyle(1)=grsList
RowStyle(2)=grsEllipsis
Cell(0,0)="Age"
Cell(1,0)="Comments"
OnEllipsisClick=EllipsisClick
END CREATE
Caption="Dropdown list example"
Center
END CREATE
form.ShowModal


QTextBtn

Documentation component by D.Glodt (c)2003 Appendix A: QTextBtn

QTextBtn Component

QTextBtn is button component of text type.

QTextBtn Properties
Field | Type | R/W | Défault
DownColor | LONG | R/W | 0
 | Down state color. |  |
UpColor | LONG | R/W |
 | Up state color. |  |
mode | SHORT | R/W | 0
 | Run mode button Mode to 0:same to a QButton Mode to 1:button stay a the down state after click. Mode to 2:button change state after each click. |  |
down | BOOLEAN | R/W | FALSE
 | down state of button |  |
Enabled | BOOLEAN | R/W | TRUE
Parent | QFORM,QPANEL,QTABCONTROL | W |
Left | INTEGER | R/W | 0
Top | INTEGER | R/W | 0

QTextBtn Methods
Method | Type | Description | Params

QTextBtn Events
Event | Type | Occurs when... | Params
OnClick |  | Click on button | 0

QTextBtn Example
$typecheck on
$optimize on
$include "Rapidq.inc"
$include "QFuncLib.inc"
$include "Object\QSkin.inc"
$include "Object\QSkinBtn.inc"
$include "Object\QTextBtn.inc"
$include "Object\QFlashLabel.inc"
$include "Object\QVuMeter.inc"
$include "Object\QVideo.inc"

$resource img as "skin3.bmp"
$resource play1 as "play1.bmp"
$resource play2 as "play2.bmp"
$resource stop1 as "stop1.bmp"
$resource stop2 as "stop2.bmp"
$resource pause1 as "pause1.bmp"
$resource pause2 as "pause2.bmp"
$resource back1 as "back1.bmp"
$resource back2 as "back2.bmp"
$resource fwd1 as "foreward1.bmp"
$resource fwd2 as "foreward2.bmp"
$resource power1 as "power1.bmp"
$resource power2 as "power2.bmp"

declare sub quit
declare sub volume
declare sub SetVolume
declare sub open
declare sub play
declare sub stop
declare sub foreward
declare sub backward
declare sub pause
Declare Sub ShowTime(Position as long,timePos aslong)

const color1=&h660000
const color2=&hff9900
const color3=&h88FF66
const RazClock="00:00"

Dim OpenDialog asQOpenDialog
OpenDialog.Filter="Fichier vidéo(tout type)|*.avi;*.mpg;*.mpeg;*.mov|Fichier avi|*.avi|Fichier MPEG|*.mpg;*.mpeg|Fichier MOV|*.mov|"
OpenDialog.Caption= "Selectionner une vidéo"

CREATE Form ASQSkin
Center
skin.bmpHandle=img
skin.top=-1
skin.left=-1
caption="Player"
OffsWidth=-5
create display asqpanel
top=20
left=16
width=311
height=72
bevelinner=0
bevelouter=0
color=&h994400
create bar asqpanel
top=50
left=0
width=display.width
height=2
bevelinner=0
bevelouter=0
color=color1
end create
create FlashPlay
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=2
caption="Play"
end create
create FlashStop
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=16
caption="Stop"
state=true
end create
create FlashPause
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=30
caption="Pause"
end create
create FlashTime
asQFlashlabel
DarkColor=color1
LightColor=color2
left=150
top=6
font.size=24
caption=RazClock
State=true
end create
create vu asQVuMeter
top=1
left=290
width=10
height=45
DarkColor=color1
LightColor=color2
value=50
end create
create btOpen
asQTextBtn
UpColor=color1
DownColor=color2
left=5
top=55
font.bold=true
caption="Open"
OnClick=open
end create
create btVol
asQTextBtn
UpColor=color1
DownColor=color2
left=265
top=55
font.bold=true
caption="Volume"
OnClick=Volume
end create
end create
create btPlay asQskinBtn
btUp.bmphandle=play1
btDown.bmphandle=play2
top=110
left=12
mode=1
OnClick=play
end create
create btStop asQskinBtn
btUp.bmphandle=stop1
btDown.bmphandle=stop2
top=110
left=44
OnClick=stop
end create
create btPause asQskinBtn
btUp.bmphandle=pause1
btDown.bmphandle=pause2
top=110
left=76
mode=1
OnClick=pause
end create
create btBack asQskinBtn
btUp.bmphandle=back1
btDown.bmphandle=back2
top=110
left=108
OnClick=backward
end create
create btFwd asQskinBtn
btUp.bmphandle=fwd1
btDown.bmphandle=fwd2
top=110
left=140
OnClick=foreward
end create
create btPower asQskinBtn
btUp.bmphandle=power1
btDown.bmphandle=power2
top=110
left=300
OnClick=quit
end create
END CREATE

CREATE Form2 ASQFORM
Caption="Volume"
Width=60
Height=190
Center
borderStyle=bsToolWindow
CREATE TbVol ASQTRACKBAR
cursor=crHandPoint
Orientation=tbVertical
Frequency=5
TickMarks=tmBoth
TickStyle=tsAuto
Left=5
Top=5
Max=0
Min=-100
Width=45
Height=150
position=-50
OnChange=SetVolume
END CREATE
END CREATE

CREATE video ASQVideo
Parent=0
volume=50
OnChange=ShowTime
timer.interval=200
BorderStyle=bsSizeable
END CREATE

form.shapeform(img,&hffffff)
form.setdeskbar
Form.ShowModal

Sub quit
video.close
form2.close
application.terminate
End Sub

Sub volume
form2.show
End Sub

Sub SetVolume
vu.value=Abs(TbVol.position)
video.volume=Abs(TbVol.position)
End Sub

Sub open
If OpenDialog.Execute Then
video.close
if video.open(OpenDialog.FileName)then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
video.caption=GetFileName(OpenDialog.FileName)
else
showmessage
video.error
end if
end if
End Sub

Sub play
if video.FileOpen=false
then
btPlay.Down=false
else
FlashPause.flash=false
FlashStop.state=false
FlashPlay.state=true
btPause.Down=false
video.play
end if
End Sub

Sub stop
video.stop
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
End Sub

Function GetMinutes(seconds aslong)asstring
dim min asinteger
dim sec asinteger
dim sMin asstring
dim sSec asstring

min=seconds/60
sec=seconds mod 60
if min<10 then
sMin="0"+str$(min)
else
sMin=str$(min)
end if
if sec<10 then
sSec="0"+str$(sec)
else
sSec=str$(sec)
end if
result=sMin+":"+sSec
End Function

Sub ShowTime(Position aslong,timePos
aslong)
FlashTime.caption=GetMinutes(timePos)
If Video.State=VD_STOP then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
end if
End Sub

Sub pause
if video.state=VD_PLAY then
video.pause
btPlay.down=false
FlashPlay.state=false
FlashPause.flash=true
else
if video.FileOpen=false
then
btPause.Down=false
end if
End Sub

Sub foreward
if (video.currentFrame+1)<video.lenght
then
video.currentFrame=video.currentFrame+1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub

Sub backward
if video.currentFrame>0 then
video.currentFrame=video.currentFrame-1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub


QTextEdit

Documentation component by D.Glodt (c)2000-2001 Appendix A: QTextEdit

QTextEdit Component

QTextEdit is an extension of QRichEdit component with more functions.

QTextEdit Properties
Field | Type | R/W | Default
UsePopup | BOOLEAN | RW | True
 | To use a popup menu with the right mouse button. |  |
UndoCaption | STRING | RW | Undo
 | Label of item Undo of popup menu.
CutCaption | STRING | RW | Cut
 | Label of item Cut of popup menu.
CopyCaption | STRING | RW | Copy
 | Label of item Copy of popup menu.
PasteCaption | STRING | RW | Paste
 | Label of item Paste of popup menu. |  |
SelectAllCaption | STRING | RW | SelectAll
 | Label of item SelectAll of popup menu. |  |

QTextEdit Methods
Method | Type | Description | Params
Undo | SUB | Undo command. |
Cut | SUB | Cut command |
Copy | SUB | Copy to clipboard. |
Paste | SUB | Paste from clipboard. |
Limit | SUB(Value%) | Limit the size text (number of char) | 1
ReplaceSell | SUB(Text$) | Replace the selection by the Text$ parameter. | 1
Find | FUNCTION(start%,text$,case%) AS BOOLEAN | Search the string into the text,start is the start of search,case is to respect the format of char (upper,lower) | 3
LinesScroll | SUB(Number) | Place the cursor to the line number | 1
CanUndo | FUNCTION AS BOOLEAN | Return if undo is possible |

QTextEdit Events
Event | Type | Occurs when... | Params

QTextEdit Examples

$OPTION ICON "edit.ico"
$TYPECHECK ON
$INCLUDE "Rapidq.inc"
$INCLUDE "Object/QTextEdit.inc"
$INCLUDE "Object/QColorDialog.inc"
$INCLUDE "Object/QFormEx.inc"

declare sub menuEdit
declare sub menuAnnul
declare sub menuCouper
declare sub menuCopier
declare sub menuColler
declare sub menuSelection
declare sub menuNouveau
declare sub menuOuvrir
declare sub menuSauver
declare sub menuSauverSous
declare sub menuQuitter
declare sub menuRecherche
declare sub menuPoursuivre
declare sub menuRemplacer
declare sub ShowLC
declare sub ChangePolice
declare sub ChangeFond
declare sub ChangeTextRecherche
declare sub ChangeTextRemplacer
declare sub AnnulerRecherche
declare sub AnnulerRemplacer
declare sub PoursuivreRecherche
declare sub PoursuivreRemplacer
declare sub Remplacer
declare sub RemplacerTout
declare sub Show

dim FontDialog as QFONTDIALOG
dim cd as QcolorDialog
cd.caption="Couleur de fond"
dim FileName as string
FileName="Sans Titre"
dim start as long

CREATE Form AS QFORMEX
Caption=Application.title+" - "+FileName
Width=715
Height=508
Center
OnClose=MenuQuitter
OnShow=Show
CREATE Menu as QMAINMENU
CREATE Fichier as QMENUITEM
Caption="&Fichier"
CREATE Nouveau as QMENUITEM
Caption="&Nouveau"
OnClick=MenuNouveau
END CREATE
CREATE Ouvrir as QMENUITEM
Caption="&Ouvrir"
OnClick=MenuOuvrir
END CREATE
CREATE Sauver as QMENUITEM
Caption="&Sauver"
OnClick=MenuSauver
END CREATE
CREATE SauverSous as QMENUITEM
Caption="&Sauver Sous..."
OnClick=MenuSauverSous
END CREATE
CREATE Sep3 as QMENUITEM
Caption="-"
END CREATE
CREATE Quitter as QMENUITEM
Caption="&Quitter"
OnClick=MenuQuitter
END CREATE
END CREATE
CREATE Edition as QMENUITEM
Caption="&Edition"
OnClick=menuEdit
CREATE Annul as QMENUITEM
Caption="&Annuler"
Enabled=false
ShortCut="CTRL+Z"
OnClick=MenuAnnul
END CREATE
CREATE Sep1 as QMENUITEM
Caption="-"
END CREATE
CREATE Couper as QMENUITEM
Caption="&Couper"
Enabled=false
ShortCut="CTRL+X"
OnClick=MenuCouper
END CREATE
CREATE Copier as QMENUITEM
Caption="&Copier"
Enabled=false
ShortCut="CTRL+C"
OnClick=MenuCopier
END CREATE
CREATE Coller as QMENUITEM
Caption="&Coller"
Enabled=false
ShortCut="CTRL+V"
OnClick=MenuColler
END CREATE
CREATE Sep2 as QMENUITEM
Caption="-"
END CREATE
CREATE Selection as QMENUITEM
Caption="&Selectionner tout"
Enabled=false
ShortCut="CTRL+A"
OnClick=MenuSelection
END CREATE
END CREATE
CREATE Recherche as QMENUITEM
Caption="&Recherche"
CREATE Rechercher as QMENUITEM
Caption="&Rechercher"
OnClick=MenuRecherche
END CREATE
CREATE Poursuivre as QMENUITEM
Caption="&Poursuivre la recherche"
OnClick=MenuPoursuivre
END CREATE
CREATE Remplace as QMENUITEM
Caption="&Remplacer"
OnClick=MenuRemplacer
END CREATE
END CREATE
CREATE Format as QMENUITEM
Caption="&Format"
CREATE Police as QMENUITEM
Caption="&Police"
OnClick=ChangePolice
END CREATE
CREATE CouleurFond as QMENUITEM
Caption="&Couleur fond"
OnClick=ChangeFond
END CREATE
END CREATE
END CREATE
CREATE infos AS QSTATUSBAR
AddPanels "Li:","Col:","Taille:"
Panel(0).width=80
Panel(1).width=80
END CREATE
CREATE Edit AS QTEXTEDIT
Align=5
PlainText=1
ScrollBars=3
WordWrap=false
UndoCaption="&Annuler"
CutCaption="&Couper"
CopyCaption="&Copier"
PasteCaption="&Coller"
SelectAllCaption="&Selectionner tout"
OnMouseDown=ShowLC
OnKeyUp=ShowLC
END CREATE
END CREATE

CREATE Form2 AS QFORM
Caption="Rechercher"
Width=326
Height=119
borderStyle=bsDialog
Center
CREATE LabRech AS QLABEL
Caption="Rechercher:"
Left=8
Top=12
Width=64
Height=21
END CREATE
CREATE EditRech AS QEDIT
Left=74
Top=9
Width=145
ShowHint=1
Hint="Mot recherché"
OnChange=ChangeTextRecherche
TabOrder=1
END CREATE
CREATE BtRech1 AS QBUTTON
Caption="Poursuivre"
Left=229
Top=9
Width=80
TabOrder=2
Enabled=false
OnClick=PoursuivreRecherche
END CREATE
CREATE BtRech2 AS QBUTTON
Caption="Annuler"
Left=229
Top=41
Width=80
TabOrder=3
OnClick=AnnulerRecherche
END CREATE
CREATE CheckRech AS QCHECKBOX
Caption="Respecter la casse"
Left=8
Top=57
Width=113
ShowHint=1
Hint="Respect majuscule
et minuscule si coché"
TabOrder=4
END CREATE
END CREATE

CREATE Form3 AS QFORM
Caption="Remplacer"
Width=362
Height=177
borderStyle=bsDialog
Center
CREATE Lab1Repl AS QLABEL
Caption="Rechercher:"
Left=8
Top=11
Width=64
END CREATE
CREATE Lab2Repl AS QLABEL
Caption="Remplacer par:"
Left=8
Top=43
Width=75
END CREATE
CREATE Edit1Repl AS QEDIT
Left=82
Top=8
Width=145
TabOrder=1
OnChange=ChangeTextRemplacer
END CREATE
CREATE Edit2Repl AS QEDIT
Left=82
Top=40
Width=145
TabOrder=2
END CREATE
CREATE Bt1Repl AS QBUTTON
Caption="Poursuivre"
Left=237
Top=8
Width=107
TabOrder=3
Enabled=false
OnClick=PoursuivreRemplacer
END CREATE
CREATE Bt2Repl AS QBUTTON
Caption="Remplacer"
Left=237
Top=40
Width=107
TabOrder=4
Enabled=false
OnClick=Remplacer
END CREATE
CREATE Bt3Repl AS QBUTTON
Caption="Remplacer tout"
Left=237
Top=72
Width=107
TabOrder=5
Enabled=false
OnClick=RemplacerTout
END CREATE
CREATE Bt4Repl AS QBUTTON
Caption="Annuler"
Left=237
Top=104
Width=107
TabOrder=6
OnClick=AnnulerRemplacer
END CREATE
CREATE CheckRepl AS QCHECKBOX
Caption="Respecter la casse"
Left=8
Top=114
Width=121
TabOrder=7
END CREATE
END CREATE

form.DeskBar=true

Form.ShowModal

sub Show
dim font as Qfont

edit.limit(100000)
font.Name="Courier New"
font.size=10
edit.font=font
FontDialog.GetFont(font)
end sub

sub menuEdit
Annul.Enabled=Edit.CanUndo
if LEN(ClipBoard.Text)>0 then
Coller.Enabled=true
else
Coller.Enabled=false
end if
if len(edit.text)>0 then
selection.enabled=true
else
selection.enabled=false
end if
if len(edit.seltext)>0 then
couper.enabled=true
copier.enabled=true
else
couper.enabled=false
copier.enabled=false
end if
end sub

sub menuAnnul
edit.undo
ShowLC
end sub

sub menuCouper
edit.cut
ShowLC
end sub

sub menuCopier
edit.copy
end sub

sub menuColler
edit.paste
ShowLC
end sub

sub menuSelection
edit.selectAll
end sub

sub ShowLC
infos.panel(0).caption="Li:"+str$(edit.wherey+1)
infos.panel(1).caption="Col:"+str$(edit.wherex+1)
infos.panel(2).caption="Taille:"+str$(len(edit.text))
end sub

sub ChangePolice
dim font as qfont

if FontDialog.execute then
FontDialog.SetFont(font)
edit.font=font
end if
end sub

sub changeFond
if cd.execute then
edit.color=cd.color
end if
end sub

sub menuNouveau
Dim msgButton as integer

if edit.modified then
msgButton=MessageBox("Sauver fichier?",application.title,35)
if msgButton<>mrCancel then
if msgButton=mrYes then
menuSauver
end if
edit.Modified=false
edit.clear
filename="Sans Titre"
form.caption=application.title+" - "+filename
end if
else
edit.clear
filename="Sans Titre"
form.caption=application.title+" - "+filename
end if
ShowLC
end sub

sub menuOuvrir
Dim OpenDialog as QOpenDialog
Dim msgButton as integer

  OpenDialog.Filter="Fichier texte|*.txt|"
OpenDialog.Caption= "Ouvrir fichier"
if edit.modified then
msgButton=MessageBox("Sauver fichier?",application.title,35)
if msgButton<>mrCancel then
if msgButton=mrYes then
menuSauver
end if
OpenDialog.InitialDir=CurDir$
if openDialog.execute then
FileName=OpenDialog.fileName
screen.cursor=crHourGlass
edit.loadfromfile(filename)
screen.cursor=crDefault
edit.modified=false
form.caption=application.title+"
- "+right$(FileName,Len(FileName)-RINSTR(FileName,"\"))
end if
end if
else
OpenDialog.InitialDir=CurDir$
if openDialog.execute then
FileName=OpenDialog.fileName
screen.cursor=crHourGlass
edit.loadfromfile(filename)
screen.cursor=crDefault
edit.modified=false
form.caption=application.title+" - "+right$(FileName,Len(FileName)-RINSTR(FileName,"\"))
end if
end if
ShowLC
end sub

sub menuSauver
if FileName="Sans Titre" then
menuSauverSous
else
screen.cursor=crHourGlass
edit.SaveToFile(filename)
screen.cursor=crDefault
end if
end sub

sub menuSauverSous
Dim SaveDialog as QSaveDialog

SaveDialog.Filter="Fichier texte|*.txt|"
SaveDialog.Caption= "Sauver fichier"
SaveDialog.InitialDir=CurDir$
if saveDialog.execute then
FileName=SaveDialog.FileName
if instr(LCASE$(FileName),".txt")=0 then
FileName=FileName+".txt"
end if
form.caption=application.title+" - "+right$(FileName,Len(FileName)-RINSTR(FileName,"\"))
screen.cursor=crHourGlass
edit.SaveToFile(filename)
screen.cursor=crDefault
end if
end sub

sub menuQuitter
Dim msgButton as integer

if edit.modified then
msgButton=MessageBox("Sauver fichier?",application.title,35)
if msgButton<>mrCancel then
if msgButton=mrYes then
menuSauver
end if
edit.clear
application.terminate
end if
else
edit.clear
application.terminate
end if
end sub

sub ChangeTextRecherche
if len(editRech.text)>0 then
BtRech1.enabled=true
else
BtRech1.enabled=false
end if
end sub

sub menuRecherche
form2.show
end sub

sub menuRemplacer
form3.show
end sub

sub AnnulerRecherche
form2.close
end sub

sub PoursuivreRecherche
dim flag as integer

flag=checkRech.checked
if edit.seltext="" then start=edit.selstart
if edit.find(start,editRech.text,flag)>0 then
form.show
start=edit.find(start,editRech.text,flag)
start=start+len(editRech.text)
else
messageDlg("Impossible de trouver "+chr$(34)+editRech.text+chr$(34),mtInformation,mbOk,0)
end if
end sub

sub MenuPoursuivre
dim flag as integer

flag=checkRech.checked
if edit.seltext="" then start=edit.selstart
if edit.find(start,editRech.text,flag)>0 then
start=edit.find(start,editRech.text,flag)
start=start+len(editRech.text)
else
messageDlg("Impossible de trouver "+chr$(34)+editRech.text+chr$(34),mtInformation,mbOk,0)
end if
end sub

sub ChangeTextRemplacer
if len(edit1Repl.text)>0 then
Bt1Repl.enabled=true
Bt2Repl.enabled=true
Bt3Repl.enabled=true
else
Bt1Repl.enabled=false
Bt2Repl.enabled=false
Bt3Repl.enabled=false
end if
end sub

sub AnnulerRemplacer
form3.close
end sub

sub PoursuivreRemplacer
dim flag as integer

flag=checkRepl.checked
if edit.seltext="" then start=edit.selstart
if edit.find(start,edit1Repl.text,flag)>0 then
form.show
start=edit.find(start,edit1Repl.text,flag)
start=start+len(edit1Repl.text)
else
messageDlg("Impossible de trouver "+chr$(34)+edit1Repl.text+chr$(34),mtInformation,mbOk,0)
end if
end sub

sub Remplacer
if edit.sellength>0 then
edit.seltext=edit2repl.text
end if
PoursuivreRemplacer
end sub

sub RemplacerTout
dim flag as integer

form3.close
flag=checkRepl.checked
if edit.seltext="" then start=edit.selstart
while edit.find(start,edit1Repl.text,flag)>0
start=edit.find(start,edit1Repl.text,flag)
start=start+len(edit1Repl.text)
edit.seltext=edit2repl.text
wend
end sub


QVIDEO

Documentation component by D.Glodt (c)2000-2004 Appended by JohnK Appendix A: QVIDEO

QVIDEO Component

QVIDEO is a media component used to play a video file, such as AVI, MEPG, etc. using Windows multimedia support. See limitations.

QVIDEO Properties
Field | Type | R/W | Default
Timer | QTIMER | RW |
 | Control the fréquency of checking OnChange event,
Lenght | LONG | R |
 | Length of video file (images number) (** note spelling left in for compatibility**)
LenghtTime | LONG | R |
 | Length of video file (seconds) (** note spelling left in for compatibility**) |  |
State | INTEGER | R | VD_CLOSE
 | State of media video player,can be VD_PLAY,VD_STOP,VD_PAUSE.
Handle | LONG | R |
 | Handle of control.
Parent | LONG | RW |
 | Needs a QFORM Handle, or set to 0 for the media player window |  |
FileOpen | BOOLEAN | R | False
 | If true then a video file is open.
Left | SHORT | RW |
Top | SHORT | RW |
Width | SHORT | RW |
Height | SHORT | RW |
ImgWidth | SHORT | R |
 | Image width of vidéo file |  |
ImgHeight | SHORT | R |
 | Image height of vidéo file |  |
CurrentFrame | LONG | RW |
 | Current position of player.
AudioOff | BOOLEAN | RW | False
 | If true then the sound is turned off |  |
Error | STRING | R |
 | Text error if the OPEN method returns FALSE. |  |
Caption | STRING | RW |
 | Title window média player |  |
BorderStyle | INTEGER | RW | bsSizeable
 | Window style of media player if the PARENT is the desktop,can be bsNone or bsSizeable |  |
WindowState | INTEGER | RW | wsNormal
 | Window state of media player when his parent is the desk,can be wsNormal or wsMinimized or wsMaximized |  |
Volume | INTEGER | RW | 0

QVIDEO Methods
Method | Type | Description | Params
Close | SUB | Close the media player. | 0
Open | FUNCTION (FileName as string) | Open video file. | 2
Show | SUB | Show video. | 0
Play | SUB | Play the video file. | 0
Stop | SUB | Stop the player. | 0
Pause | SUB | Set the player in pause mode. | 0

QVIDEO Events
Event | Type | Occurs when... | Params
OnChange | (position as long, timePos as long) | Position of player in mode play. position is the frame number, and timePos is the position by seconds. | 2

QVIDEO Examples

'**************************************************************************
'* application:player video                                               *
'* auteur:D.Glodt                                                         *
'* date:17-1-2004                                                         *
'**************************************************************************
$OPTION ICON "video.ico"
$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\QVideo.inc"

$RESOURCE PLAYBMP as "play.bmp"
$RESOURCE STOPBMP as "Stop.bmp"
$RESOURCE PAUSEBMP as "Pause.bmp"
$RESOURCE SPEAKERBMP as "Speaker.bmp"
$RESOURCE SPEAKEROFFBMP as "SpeakerOff.bmp"

Declare Sub PaintForm
Declare Sub ResizeForm
Declare Sub Play
Declare Sub Stop
Declare Sub Pause
Declare Sub Open
Declare Sub Close
Declare Sub Quitter
Declare Sub TrackBarChange
Declare Sub PostimerOnTimer(Position as long,timePos as long)
Declare Sub Zoom1
Declare Sub Zoom2
Declare Sub Zoom3
Declare Sub Zoom4
Declare Sub FullScreen
Declare Sub Speaker
Declare Sub EditSeq
Declare Sub PlaySeq
Declare Sub AddSeq
Declare Sub DelSeq
Declare Sub DelAllSeq
Declare Sub CloseSeq
Declare Sub VolumeChange

const FormWidth=288
const FormHeight=290
Dim OpenDialog as QOpenDialog
OpenDialog.Filter="Fichier vidéo(tout type)|*.avi;*.mpg;*.mpeg;*.mov|Fichier avi|*.avi|Fichier MPEG|*.mpg;*.mpeg|Fichier MOV|*.mov|"
OpenDialog.Caption= "Selectionner une vidéo"
Dim video as QVideo
video.DeviceType="MpegVideo"
video.OnChange=PostimerOnTimer
video.timer.interval=200
Dim Counter as integer
Dim flagSeq as integer
Dim flagSpeaker as integer
flagSpeaker=false
Dim FileName as string

CREATE Form2 AS QFORM
    Caption="Selection séquence"
    Width=430
    Height=230
    Center
    BorderStyle=bsDialog
    CREATE ListSeq AS QLISTBOX
        Left=10
        Top=10
        Width=400
        Height=150
    END CREATE
    CREATE BtAdd AS QBUTTON
        Caption="Ajouter"
        Left=10
        Top=170
        TabOrder=2
        OnClick=AddSeq
    END CREATE
    CREATE BtDel AS QBUTTON
        Caption="Supprimer"
        Left=93
        Top=170
        TabOrder=3
        OnClick=DelSeq
    END CREATE
    CREATE BtDelAll AS QBUTTON
        Caption="Nouveau"
        Left=175
        Top=170
        TabOrder=4
        OnClick=DelAllSeq
    END CREATE
    CREATE BtQuit AS QBUTTON
        Caption="Fermer"
        Left=335
        Top=170
        TabOrder=1
        OnClick=CloseSeq
    END CREATE
END CREATE

CREATE Form3 AS QFORM
  BorderStyle=bsNone
  left=0
  top=0
  width=Screen.width
  height=Screen.height
  color=&H0
  cursor=crnone
  OnKeyPress=Stop
END CREATE

CREATE Form AS QFORM
    Caption="Vidéo"
    Width=FormWidth
    Height=FormHeight
    Center
    BorderStyle=bsSingle
    DelBorderIcons 2
    OnPaint=PaintForm
    OnResize=ResizeForm
    OnClose=Quitter
    CREATE MENU AS QMAINMENU
      CREATE FileMenu AS QMENUITEM
        Caption="&Fichier"
        CREATE Item1 AS QMENUITEM
          Caption="&Ouvrir"
          OnClick=Open
        END CREATE
        CREATE Item2 AS QMENUITEM
          Caption="&Fermer"
          OnClick=Close
        END CREATE
        CREATE Item3 AS QMENUITEM
          Caption="-"
        END CREATE
        CREATE Item4 AS QMENUITEM
          Caption="&Quitter"
          OnClick=Quitter
        END CREATE
      END CREATE
      CREATE Display AS QMENUITEM
        Caption="&Affichage"
        CREATE Item11 AS QMENUITEM
          Caption="&Zoom"
          Enabled=false
          CREATE Item21 AS QMENUITEM
            Caption="&Zoom 50%"
            OnClick=Zoom1
          END CREATE
          CREATE Item22 AS QMENUITEM
            Caption="&Zoom 100%"
            Checked=true
            OnClick=Zoom2
          END CREATE
          CREATE Item23 AS QMENUITEM
            Caption="&Zoom 150%"
            OnClick=Zoom3
          END CREATE
          CREATE Item24 AS QMENUITEM
            Caption="&Zoom 200%"
            OnClick=Zoom4
          END CREATE
        END CREATE
        CREATE Item25 AS QMENUITEM
          Caption="&Plein écran"
          OnClick=FullScreen
        END CREATE
      END CREATE
      CREATE Sequence AS QMENUITEM
        Caption="&Séquence"
        CREATE Item13 AS QMENUITEM
          Caption="&Edition"
          OnClick=EditSeq
        END CREATE
        CREATE Item14 AS QMENUITEM
          Caption="&Lancer séquence"
          OnClick=PlaySeq
          Enabled=false
        END CREATE
      END CREATE
    END CREATE
    CREATE Panel1 AS QPANEL
        Left=0
        Top=171
        Width=281
        Height=80
        BevelOuter=bvNone
        CREATE BtPlay AS QCOOLBTN
            BMPHandle=PLAYBMP
            Left=8
            Top=6
            Width=26
            Height=26
            Flat=true
            Hint="Play"
            ShowHint=true
            GroupIndex=1
            OnClick=Play
            Enabled=false
        END CREATE
        CREATE BtStop AS QCOOLBTN
            BMPHandle=STOPBMP
            Left=46
            Top=6
            Width=26
            Height=26
            Flat=true
            Hint="Stop"
            ShowHint=true
            GroupIndex=1
            OnClick=Stop
            Enabled=false
        END CREATE
        CREATE BtPause AS QCOOLBTN
            BMPHandle=PAUSEBMP
            Left=84
            Top=6
            Width=26
            Height=26
            Flat=true
            GroupIndex=1
            Hint="Pause"
            ShowHint=true
            OnClick=Pause
            Enabled=false
        END CREATE
        CREATE BtSpeaker AS QCOOLBTN
            BMPHandle=SPEAKERBMP
            Left=122
            Top=6
            Width=26
            Height=26
            Flat=true
            Hint="Son"
            ShowHint=true
            OnClick=Speaker
            Enabled=false
        END CREATE
        CREATE TrackBar1 AS QTRACKBAR
            TickMarks=tmBoth
            TickStyle=tsNone
            Left=2
            Top=36
            LineSize=0
            Width=272
            Height=21
            Hint="Position"
            ShowHint=true
            OnChange=TrackBarChange
            Enabled=false
        END CREATE
        CREATE TrackBar2 AS QTRACKBAR
            TickMarks=tmTopLeft
            TickStyle=tsnone
            Left=173
            Top=10
            LineSize=0
            Width=100
            Height=21
            Hint="Volume"
            ShowHint=true
            OnChange=VolumeChange
            Enabled=false
            Min=0
            Max=100
        END CREATE
        CREATE infos AS QSTATUSBAR
          SizeGrip=false
          AddPanels "Format:","Durée:",""
          Panel(0).width=100
          Panel(1).width=100
        END CREATE
    END CREATE
END CREATE
video.parent=form.handle
Form.ShowModal

Sub PaintForm
  form.FillRect(0,0,form.clientWidth,(form.clientHeight-panel1.height),&H0)
End Sub

Sub ResizeForm
  Panel1.Top=form.ClientHeight-Panel1.Height
  Panel1.Width=form.ClientWidth
  TrackBar1.width=Panel1.width-10
End Sub

Function GetMinutes(seconds as long) as string
  dim min as integer
  dim sec as integer

  min=seconds/60
  sec=seconds mod 60
  if sec<10 then
    result=str$(min)+":0"+str$(sec)
  else
    result=str$(min)+":"+str$(sec)
  end if
End Function

Sub Open
  If OpenDialog.Execute Then
   video.close
   if video.open(OpenDialog.FileName) then
     FileName=OpenDialog.FileName
     form.Width=video.width+(form.width-form.clientWidth)+2
     form.Height=video.height+panel1.height+(form.height-form.clientHeight)
     ResizeForm
     TrackBar1.Enabled=true
     TrackBar2.Enabled=true
     TrackBar1.Max=video.lenght
     TrackBar1.Position=0
     if item21.checked then zoom1
     if item23.checked then zoom3
     if item24.checked then zoom4
     BtStop.Enabled=true
     BtPlay.Enabled=true
     BtPause.Enabled=true
     BtSpeaker.Enabled=true
     BtStop.Down=True
     Item11.Enabled=true
     video.show
     form.caption="Vidéo - "+right$(OpenDialog.FileName,Len(OpenDialog.FileName)-RINSTR(OpenDialog.FileName,"\"))
     infos.Panel(0).caption="Format:"+str$(video.ImgWidth)+"*"+str$(video.ImgHeight)
     infos.Panel(1).caption="Durée:"+GetMinutes(video.LenghtTime)
     infos.Panel(2).caption=""
   else
     showmessage video.error
   end if
  end if
End Sub

Sub Close
  if flagSpeaker then
    flagSpeaker=false
    video.AudioOff=false
    btSpeaker.bmpHandle=SPEAKERBMP
  end if
  video.close
  TrackBar1.Position=0
  Item11.Enabled=false
  TrackBar1.Enabled=false
  TrackBar2.Enabled=false
  Form.width=FormWidth
  Form.Height=FormHeight
  BtStop.Enabled=false
  BtPlay.Enabled=false
  BtPause.Enabled=false
  BtSpeaker.Enabled=false
  form.caption="Vidéo"
  flagSeq=false
  infos.Panel(0).caption="Format:"
  infos.Panel(1).caption="Durée:"
  infos.Panel(2).caption=""
End Sub

Sub Play
  if video.FileOpen=false then BtStop.Down=True
  if item25.checked then
    video.close
    video.parent=form3.handle
    form3.show
    video.open(Filename)
    video.width=form3.width
    video.height=form3.height
  end if
  video.play
End Sub

Sub Stop
  video.stop
  TrackBar1.Position=0
  if item25.checked then
    video.close
    form3.close
    video.parent=form.handle
    video.open(Filename)
    if item21.checked then zoom1
    if item22.checked then zoom2
    if item23.checked then zoom3
    if item24.checked then zoom4
    BtStop.Down=True
    video.show
  end if
End Sub

Sub Pause
  if video.FileOpen=false then BtStop.Down=True
  video.pause
End Sub

Sub TrackBarChange
  video.currentFrame=TrackBar1.Position
End Sub

Sub PostimerOnTimer(Position as long,timePos as long)
  TrackBar1.Position=Position
  infos.Panel(2).caption=GetMinutes(timePos)
  If Video.State=VD_STOP and flagSeq=false then
    TrackBar1.Position=0
    BtStop.Down=True
    if item25.checked then
      video.close
      form3.close
      video.parent=form.handle
      video.open(Filename)
      if item21.checked then zoom1
      if item22.checked then zoom2
      if item23.checked then zoom3
      if item24.checked then zoom4
      video.show
    end if
  end if
  If Video.State=VD_STOP and flagSeq=true then
    TrackBar1.Position=0
    video.close
    counter=counter+1
    if (counter+1)<=listSeq.itemCount then
      if video.open(listSeq.item(counter)) then
        FileName=listSeq.item(counter)
        if item25.checked then
          video.width=form3.width
          video.height=form3.height
        else
          form.Width=video.width+(form.width-form.clientWidth)+2
          form.Height=video.height+panel1.height+(form.height-form.clientHeight)
          if item21.checked then zoom1
          if item23.checked then zoom3
          if item24.checked then zoom4
        end if
        TrackBar1.Max=video.lenght
        video.play
        form.caption="Vidéo - "+right$(listSeq.item(counter),Len(listSeq.item(counter))-RINSTR(listSeq.item(counter),"\"))
        infos.Panel(0).caption="Format:"+str$(video.ImgWidth)+"*"+str$(video.ImgHeight)
        infos.Panel(1).caption="Durée:"+GetMinutes(video.LenghtTime)
      else
        showmessage video.error
      end if
    else
      if item25.checked then
        form3.close
        video.parent=form.handle
      end if
      BtPlay.Down=False
      BtStop.Down=True
      Close
    end if
  end if
End Sub

Sub Quitter
  video.close
  form.close
End Sub

Sub Zoom1
  if video.FileOpen then
    Item21.checked=true
    Item22.checked=false
    Item23.checked=false
    Item24.checked=false
    video.width=video.ImgWidth*(50/100)
    video.height=video.ImgHeight*(50/100)
    form.Width=video.width+(form.width-form.clientWidth)+2
    form.Height=video.height+panel1.height+(form.height-form.clientHeight)
  end if
End Sub

Sub Zoom2
  if video.FileOpen then
    Item21.checked=false
    Item22.checked=true
    Item23.checked=false
    Item24.checked=false
    video.width=video.ImgWidth*(100/100)
    video.height=video.ImgHeight*(100/100)
    form.Width=video.width+(form.width-form.clientWidth)+2
    form.Height=video.height+panel1.height+(form.height-form.clientHeight)
  end if
End Sub

Sub Zoom3
  if video.FileOpen then
    Item21.checked=false
    Item22.checked=false
    Item23.checked=true
    Item24.checked=false
    video.width=video.ImgWidth*(150/100)
    video.height=video.ImgHeight*(150/100)
    form.Width=video.width+(form.width-form.clientWidth)+2
    form.Height=video.height+panel1.height+(form.height-form.clientHeight)
  end if
End Sub

Sub Zoom4
  if video.FileOpen then
    Item21.checked=false
    Item22.checked=false
    Item23.checked=false
    Item24.checked=true
    video.width=video.ImgWidth*(200/100)
    video.height=video.ImgHeight*(200/100)
    form.Width=video.width+(form.width-form.clientWidth)+2
    form.Height=video.height+panel1.height+(form.height-form.clientHeight)
  end if
End Sub

Sub Speaker
  if flagSpeaker then
    video.AudioOff=false
    btSpeaker.bmpHandle=SPEAKERBMP
    flagSpeaker=false
  else
    video.AudioOff=true
    btSpeaker.bmpHandle=SPEAKEROFFBMP
    flagSpeaker=true
  end if
End Sub

Sub EditSeq
  Form2.showmodal
End Sub

Sub AddSeq
  If OpenDialog.Execute Then
    listSeq.additems(OpenDialog.fileName)
  end if
End Sub

Sub DelSeq
  if listSeq.itemIndex>-1 then
    listSeq.delItems(listSeq.itemIndex)
  end if
End Sub

Sub DelAllSeq
  listSeq.clear
End Sub

Sub CloseSeq
  form2.close
  if listSeq.itemCount>0 then
    item14.enabled=true
  else
    item14.enabled=false
  end if
End Sub

Sub PlaySeq
  if listSeq.itemCount>0 then
    video.close
    flagSeq=true
    counter=0
    if item25.checked then
      video.parent=form3.handle
      form3.show
    end if
    if video.open(listSeq.item(counter)) then
      FileName=listSeq.item(counter)
      if item25.checked then
        video.width=form3.width
        video.height=form3.height
      else
        form.Width=video.width+(form.width-form.clientWidth)+2
        form.Height=video.height+panel1.height+(form.height-form.clientHeight)
        if item21.checked then zoom1
        if item23.checked then zoom3
        if item24.checked then zoom4
      end if
      TrackBar1.Enabled=true
      TrackBar2.Enabled=true
      TrackBar1.Max=video.lenght
      TrackBar1.Position=0
      BtStop.Enabled=true
      BtPlay.Enabled=true
      BtPause.Enabled=true
      BtSpeaker.Enabled=true
      BtPlay.Down=True
      Item11.Enabled=true
      video.play
      form.caption="Vidéo - "+right$(listSeq.item(counter),Len(listSeq.item(counter))-RINSTR(listSeq.item(counter),"\"))
      infos.Panel(0).caption="Format:"+str$(video.ImgWidth)+"*"+str$(video.ImgHeight)
      infos.Panel(1).caption="Durée:"+GetMinutes(video.LenghtTime)
    else
      showmessage video.error
    end if
  end if
End Sub

Sub FullScreen
  if item25.checked then
    item25.checked=false
  else
    If Video.State=VD_PLAY then
      video.stop
      video.close
      video.parent=form3.handle
      form3.show
      video.open(Filename)
      video.width=form3.width
      video.height=form3.height
      video.play
    end if
    item25.checked=true
  end if
End Sub

Sub VolumeChange
  video.volume=TrackBar2.position
End Sub


QVuMeter

Documentation component by D.Glodt (c)2003 Appendix A: QVuMeter

QVuMeter Component

QVuMeter is a vu meter component.

QVuMeter Properties
Field | Type | R/W | Défault
LightColor | LONG | R/W | 0
 | Vu meter light color. |  |
DarkColor | LONG | R/W | 0
 | Vu meter dark color. |  |
Max | INTEGER | R/W | 100
 | Maximum value for vu meter |  |
Min | INTEGER | R/W | 0
 | Minimum value for vu meter |  |
Thickness | SHORT | R/W | 2
 | line thickness from vu meter in pixels |  |
Interval | SHORT | R/W | 1
 | Interval between line from vu meter in pixels |  |
Value | LONG | R/W | 0
 | Value from vu meter |  |
Parent | QFORM,QPANEL,QTABCONTROL | W |
Left | INTEGER | R/W | 0
Top | INTEGER | R/W | 0
Width | INTEGER | R/W |
Height | INTEGER | R/W |

QVuMeter Methods
Method | Type | Description | Params

QVuMeter Events
Event | Type | Occurs when... | Params

QVuMeter Example
$typecheck on
$optimize on
$include "Rapidq.inc"
$include "QFuncLib.inc"
$include "Object\QSkin.inc"
$include "Object\QSkinBtn.inc"
$include "Object\QTextBtn.inc"
$include "Object\QFlashLabel.inc"
$include "Object\QVuMeter.inc"
$include "Object\QVideo.inc"

$resource img as "skin3.bmp"
$resource play1 as "play1.bmp"
$resource play2 as "play2.bmp"
$resource stop1 as "stop1.bmp"
$resource stop2 as "stop2.bmp"
$resource pause1 as "pause1.bmp"
$resource pause2 as "pause2.bmp"
$resource back1 as "back1.bmp"
$resource back2 as "back2.bmp"
$resource fwd1 as "foreward1.bmp"
$resource fwd2 as "foreward2.bmp"
$resource power1 as "power1.bmp"
$resource power2 as "power2.bmp"

declare sub quit
declare sub volume
declare sub SetVolume
declare sub open
declare sub play
declare sub stop
declare sub foreward
declare sub backward
declare sub pause
Declare Sub ShowTime(Position as long,timePos aslong)

const color1=&h660000
const color2=&hff9900
const color3=&h88FF66
const RazClock="00:00"

Dim OpenDialog asQOpenDialog
OpenDialog.Filter="Fichier vidéo(tout type)|*.avi;*.mpg;*.mpeg;*.mov|Fichier avi|*.avi|Fichier MPEG|*.mpg;*.mpeg|Fichier MOV|*.mov|"
OpenDialog.Caption= "Selectionner une vidéo"

CREATE Form ASQSkin
Center
skin.bmpHandle=img
skin.top=-1
skin.left=-1
caption="Player"
OffsWidth=-5
create display asqpanel
top=20
left=16
width=311
height=72
bevelinner=0
bevelouter=0
color=&h994400
create bar asqpanel
top=50
left=0
width=display.width
height=2
bevelinner=0
bevelouter=0
color=color1
end create
create FlashPlay
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=2
caption="Play"
end create
create FlashStop
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=16
caption="Stop"
state=true
end create
create FlashPause
asQFlashlabel
DarkColor=color1
LightColor=color3
left=5
top=30
caption="Pause"
end create
create FlashTime
asQFlashlabel
DarkColor=color1
LightColor=color2
left=150
top=6
font.size=24
caption=RazClock
State=true
end create
create vu asQVuMeter
top=1
left=290
width=10
height=45
DarkColor=color1
LightColor=color2
value=50
end create
create btOpen
asQTextBtn
UpColor=color1
DownColor=color2
left=5
top=55
font.bold=true
caption="Open"
OnClick=open
end create
create btVol
asQTextBtn
UpColor=color1
DownColor=color2
left=265
top=55
font.bold=true
caption="Volume"
OnClick=Volume
end create
end create
create btPlay asQskinBtn
btUp.bmphandle=play1
btDown.bmphandle=play2
top=110
left=12
mode=1
OnClick=play
end create
create btStop asQskinBtn
btUp.bmphandle=stop1
btDown.bmphandle=stop2
top=110
left=44
OnClick=stop
end create
create btPause asQskinBtn
btUp.bmphandle=pause1
btDown.bmphandle=pause2
top=110
left=76
mode=1
OnClick=pause
end create
create btBack asQskinBtn
btUp.bmphandle=back1
btDown.bmphandle=back2
top=110
left=108
OnClick=backward
end create
create btFwd asQskinBtn
btUp.bmphandle=fwd1
btDown.bmphandle=fwd2
top=110
left=140
OnClick=foreward
end create
create btPower asQskinBtn
btUp.bmphandle=power1
btDown.bmphandle=power2
top=110
left=300
OnClick=quit
end create
END CREATE

CREATE Form2 ASQFORM
Caption="Volume"
Width=60
Height=190
Center
borderStyle=bsToolWindow
CREATE TbVol ASQTRACKBAR
cursor=crHandPoint
Orientation=tbVertical
Frequency=5
TickMarks=tmBoth
TickStyle=tsAuto
Left=5
Top=5
Max=0
Min=-100
Width=45
Height=150
position=-50
OnChange=SetVolume
END CREATE
END CREATE

CREATE video ASQVideo
Parent=0
volume=50
OnChange=ShowTime
timer.interval=200
BorderStyle=bsSizeable
END CREATE

form.shapeform(img,&hffffff)
form.setdeskbar
Form.ShowModal

Sub quit
video.close
form2.close
application.terminate
End Sub

Sub volume
form2.show
End Sub

Sub SetVolume
vu.value=Abs(TbVol.position)
video.volume=Abs(TbVol.position)
End Sub

Sub open
If OpenDialog.Execute Then
video.close
if video.open(OpenDialog.FileName)then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
video.caption=GetFileName(OpenDialog.FileName)
else
showmessage
video.error
end if
end if
End Sub

Sub play
if video.FileOpen=false
then
btPlay.Down=false
else
FlashPause.flash=false
FlashStop.state=false
FlashPlay.state=true
btPause.Down=false
video.play
end if
End Sub

Sub stop
video.stop
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
btPause.Down=false
FlashPause.flash=false
FlashTime.caption=RazClock
End Sub

Function GetMinutes(seconds aslong)asstring
dim min asinteger
dim sec asinteger
dim sMin asstring
dim sSec asstring

min=seconds/60
sec=seconds mod 60
if min<10 then
sMin="0"+str$(min)
else
sMin=str$(min)
end if
if sec<10 then
sSec="0"+str$(sec)
else
sSec=str$(sec)
end if
result=sMin+":"+sSec
End Function

Sub ShowTime(Position aslong,timePos
aslong)
FlashTime.caption=GetMinutes(timePos)
If Video.State=VD_STOP then
btPlay.down=false
FlashPlay.state=false
FlashStop.state=true
end if
End Sub

Sub pause
if video.state=VD_PLAY then
video.pause
btPlay.down=false
FlashPlay.state=false
FlashPause.flash=true
else
if video.FileOpen=false
then
btPause.Down=false
end if
End Sub

Sub foreward
if (video.currentFrame+1)<video.lenght
then
video.currentFrame=video.currentFrame+1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub

Sub backward
if video.currentFrame>0 then
video.currentFrame=video.currentFrame-1
FlashTime.caption=str$(video.currentFrame)
end if
End Sub


QWAVE

Documentation component by D.Glodt (c)2000-2004 Appendix A: QWAVE

QWAVE Component

QWAVE is a media component used to play or record wave files.

QWAVE Properties
Field | Type | R/W | Default
Timer | QTIMER | RW |
 | Controle the fréquency of évent OnChange.
Lenght | LONG | R |
 | Lenght of wave file or record time.
State | INTEGER | R | VD_CLOSE
 | State of player,can be WV_PLAY,WV_STOP,WV_PAUSE,WV_RECORD.
FileOpen | BOOLEAN | R | False
 | It's at true if a wave file is open to play or record.
CurrentPos | LONG | RW |
 | Position of wave file in milliseconds.
Bits | INTEGER | RW |
 | Bit number by sample of wave,can be WV_BIT8 ou WV_BIT16.
Frequence | INTEGER | RW |
 | Sample frequency of wave,can be WV_KHZ8,WV_KHZ11,WV_KHZ44.
Mode | SHORT | RW |
 | Output mode,can be WV_STEREO ou WV_MONO.
Error | STRING | R |
 | Text error if OPEN method return FALSE |  |
Volume | INTEGER | RW | 0
DeviceType | STRING | RW |
 | Codec type ,example for mp3:MpegVideo |  |

QWAVE Methods
Method | Type | Description | Params
Close | SUB | Close the wave file | 0
Open | FUNCTION(FileName as string) | Open a wave file and return True if no error. | 1
Play | SUB | Play the wave file. | 0
Stop | SUB | Stop the player. | 0
Pause | SUB | Set the player to mode pause | 0
New | SUB | Create a new wave | 0
Record | SUB | Set the player to record,if the wave is new,his record time is define by the Lenght property. | 0
Save | FUNCTION(FileName as string) | Save the wave file and return True | 1
Delete | Sub(Pos1 as long,Pos2 as long) | Delete some sample data from wave file from position pos1 to pos2 in milliseconds | 2

QWAVE Events
Event | Type | Occurs when... | Params
OnChange | (position as long) | Position of player in mode play or mode record. | 1

QWAVE Examples

'**************************************************************************
'* application:player Wave                                                *
'* auteur:D.Glodt                                                         *
'* date:17-1-2004                                                         *
'**************************************************************************
$OPTION ICON "wave.ico"
$TYPECHECK ON
$Include "Rapidq.inc"
$include "Object\QWave.inc"

$RESOURCE PLAYBMP as "play.bmp"
$RESOURCE STOPBMP as "Stop.bmp"
$RESOURCE PAUSEBMP as "Pause.bmp"
$RESOURCE RECORDBMP as "record.bmp"
$RESOURCE SCREENBMP as "gramo.bmp"

Declare Sub Play
Declare Sub Stop
Declare Sub Pause
Declare Sub Open
Declare Sub Close
Declare Sub Quitter
Declare Sub SaveAs
Declare Sub New
Declare Sub Record
Declare Sub TrackBarChange
Declare Sub PostimerOnTimer(Position as long)
Declare Sub Mono
Declare Sub Stereo
Declare Sub Bit8
Declare Sub Bit16
Declare Sub Khz8
Declare Sub Khz11
Declare Sub Khz44
Declare Sub DeleteStart
Declare Sub DeleteEnd
Declare Sub ShowParam
Declare Sub TimeRecordChange
Declare Sub Init

Dim OpenDialog as QOpenDialog
OpenDialog.Filter="Fichier Wave|*.wav|Fichier Mp3|*.mp3"
OpenDialog.Caption= "Selectionner une onde"
Dim SaveDialog as QSaveDialog
SaveDialog.Filter="Fichier Wave|*.wav"
SaveDialog.Caption= "Sauver une onde"
Dim Wave as QWave
Wave.DeviceType="MpegVideo"
Wave.OnChange=PostimerOnTimer
Wave.timer.interval=200

CREATE Form2 AS QFORM
    Caption="Parametres d'enregistrement"
    Width=288
    Height=180
    Center
    BorderStyle=bsDialog
    CREATE groupe1 AS QGROUPBOX
      Top=10
      Left=2
      Width=70
      Height=60
      Caption="Mode"
      CREATE MonoBt AS QRADIOBUTTON
        Top=15
        Left=5
        width=50
        Caption="Mono"
        OnClick=Mono
      END CREATE
      CREATE StereoBt AS QRADIOBUTTON
        Top=35
        Left=5
        width=50
        Caption="Stereo"
        OnClick=Stereo
      END CREATE
    END CREATE
    CREATE groupe2 AS QGROUPBOX
      Top=10
      Left=82
      Width=70
      Height=60
      Caption="Bits"
      CREATE Bit8Bt AS QRADIOBUTTON
        Top=15
        Left=5
        width=50
        Caption="8bits"
        OnClick=Bit8
      END CREATE
      CREATE Bit16Bt AS QRADIOBUTTON
        Top=35
        Left=5
        width=50
        Caption="16bits"
        OnClick=Bit16
      END CREATE
  END CREATE
  CREATE groupe3 AS QGROUPBOX
    Top=10
    Left=162
    Width=70
    Height=80
    Caption="Freq"
    CREATE Freq8Bt AS QRADIOBUTTON
      Top=15
      Left=5
      width=50
      Caption="8Khz"
      OnClick=Khz8
    END CREATE
    CREATE Freq11Bt AS QRADIOBUTTON
      Top=35
      Left=5
      width=50
      Caption="11Khz"
      OnClick=Khz11
    END CREATE
    CREATE Freq44Bt AS QRADIOBUTTON
      Top=55
      Left=5
      width=50
      Caption="44Khz"
      OnClick=Khz44
    END CREATE
  END CREATE
  CREATE label1 AS QLABEL
    Caption="Temps enregistrement(s):10"
    top=100
    left=2
  END CREATE
  CREATE TrackBar2 AS QTRACKBAR
    TickMarks=tmTopLeft
    TickStyle=tsNone
    Left=2
    Top=130
    Max=300
    LineSize=0
    Width=272
    Height=22
    Position=10
    OnChange=TimeRecordChange
  END CREATE
END CREATE

CREATE Form AS QFORM
    Caption="Wave"
    Width=288
    Height=180
    Center
    BorderStyle=bsSingle
    DelBorderIcons 2
    OnClose=Quitter
    OnShow=Init
    CREATE MENU AS QMAINMENU
      CREATE FileMenu AS QMENUITEM
        Caption="&Fichier"
        CREATE Item1 AS QMENUITEM
          Caption="&Nouveau"
          OnClick=New
        END CREATE
        CREATE Item2 AS QMENUITEM
          Caption="&Ouvrir"
          OnClick=Open
        END CREATE
        CREATE Item3 AS QMENUITEM
          Caption="&Fermer"
          OnClick=Close
        END CREATE
        CREATE Item4 AS QMENUITEM
          Caption="&Sauver sous"
          OnClick=SaveAs
        END CREATE
        CREATE Item5 AS QMENUITEM
          Caption="-"
        END CREATE
        CREATE Item6 AS QMENUITEM
          Caption="&Quitter"
          OnClick=Quitter
        END CREATE
      END CREATE
      CREATE EditMenu AS QMENUITEM
        Caption="&Edition"
        CREATE Item11 AS QMENUITEM
          Caption="&Supprimer depuis le debut"
          OnClick=DeleteStart
        END CREATE
        CREATE Item12 AS QMENUITEM
          Caption="&Supprimer depuis la fin"
          OnClick=DeleteEnd
        END CREATE
        CREATE Item13 AS QMENUITEM
          Caption="-"
        END CREATE
        CREATE Item14 AS QMENUITEM
          Caption="Parametres"
          OnClick=ShowParam
        END CREATE
      END CREATE
    END CREATE
    CREATE Panel1 AS QPANEL
        Left=0
        Top=0
        Width=281
        Height=130
        BevelOuter=bvNone
        CREATE image as QIMAGE
           width=100
           height=70
           BmpHandle=SCREENBMP
        END CREATE
        CREATE BtPlay AS QCOOLBTN
            BMPHandle=PLAYBMP
            Left=88
            Top=26
            Width=28
            Height=28
            Hint="Play"
            ShowHint=true
            GroupIndex=1
            Enabled=false
            OnClick=Play
        END CREATE
        CREATE BtStop AS QCOOLBTN
            BMPHandle=STOPBMP
            Left=116
            Top=26
            Width=28
            Height=28
            Down=true
            Hint="Stop"
            ShowHint=true
            GroupIndex=1
            Enabled=false
            OnClick=Stop
        END CREATE
        CREATE BtPause AS QCOOLBTN
            BMPHandle=PAUSEBMP
            Left=144
            Top=26
            Width=28
            Height=28
            GroupIndex=1
            Hint="Pause"
            ShowHint=true
            Enabled=false
            OnClick=Pause
        END CREATE
        CREATE BtRecord AS QCOOLBTN
            BMPHandle=RECORDBMP
            Left=172
            Top=26
            Width=28
            Height=28
            Down=true
            Hint="Record"
            ShowHint=true
            GroupIndex=1
            OnClick=Record
        END CREATE
        CREATE TrackBar1 AS QTRACKBAR
            TickMarks=tmBoth
            TickStyle=tsNone
            Left=2
            Top=76
            LineSize=0
            Hint="Position"
            ShowHint=true
            Width=272
            Height=21
            OnChange=TrackBarChange
        END CREATE
        CREATE Infos AS QSTATUSBAR
          AddPanels "Temps:","position:"
          Panel(0).width=100
        END CREATE
    END CREATE
END CREATE

Form.ShowModal

Sub Open
  If OpenDialog.Execute Then
   Wave.close
   if Wave.open(OpenDialog.FileName) then
     EditMenu.Enabled=true
     TrackBar1.Max=Wave.lenght
     TrackBar1.Position=0
     infos.panel(0).caption="Temps:"+str$(wave.lenght/1000)+"s"
     infos.panel(1).caption="Position:0"
     BtPlay.Enabled=true
     BtStop.Enabled=true
     BtPause.Enabled=true
     item4.Enabled=true
     item3.Enabled=true
     if wave.mode=WV_MONO then
       MonoBt.checked=true
     else
       StereoBt.checked=true
     end if
     if wave.bits=WV_BIT8 then
       Bit8Bt.checked=true
     else
       Bit16Bt.checked=true
     end if
     if wave.frequence=WV_KHZ8 then
       Freq8Bt.checked=true
     elseif wave.frequence=WV_KHZ11 then
       Freq11Bt.checked=true
     elseif wave.frequence=WV_KHZ44 then
       Freq44Bt.checked=true
     end if
   else
     showmessage wave.error
   end if
  end if
End Sub

Sub Close
  Wave.close
  BtPlay.Enabled=false
  BtStop.Enabled=false
  BtPause.Enabled=false
  EditMenu.Enabled=false
  item4.Enabled=false
  item3.Enabled=false
  infos.panel(0).caption="Temps:"
  infos.panel(1).caption="Position:"
End Sub

Sub Play
  if wave.FileOpen=false then BtStop.Down=True
  TrackBar1.Max=Wave.lenght
  Wave.play
End Sub

Sub Stop
  Wave.stop
  TrackBar1.Position=0
  infos.panel(0).caption="Temps:"+str$(wave.lenght/1000)+"s"
  infos.panel(1).caption="Position:0"
End Sub

Sub Pause
  if wave.FileOpen=false then BtStop.Down=True
  Wave.pause
End Sub

Sub TrackBarChange
  Wave.currentPos=TrackBar1.Position
  infos.panel(1).caption="Position:"+str$(TrackBar1.Position/1000)
End Sub

Sub PostimerOnTimer(Position as long)
  TrackBar1.Position=Position
  infos.panel(1).caption="Position:"+str$(Position/1000)
  If Wave.state=WV_STOP then
    Wave.stop
    TrackBar1.Position=0
    BtStop.Down=True
  end if
End Sub

Sub Quitter
  Wave.close
  form2.close
  form.close
End Sub

Sub Mono
  wave.mode=WV_MONO
End Sub

Sub Stereo
  wave.mode=WV_STEREO
End Sub

Sub Bit8
  wave.bits=WV_BIT8
End Sub

Sub Bit16
  wave.bits=WV_BIT16
End Sub

Sub Khz8
  wave.frequence=WV_KHZ8
End Sub

Sub Khz11
  wave.frequence=WV_KHZ11
End Sub

Sub Khz44
  wave.frequence=WV_KHZ44
End Sub

Sub New
  wave.close
  wave.new
  infos.panel(0).caption="Temps:"+str$(TrackBar2.Position)+"s"
  infos.panel(1).caption="Position:0"
  EditMenu.Enabled=true
  BtPlay.Enabled=true
  BtStop.Enabled=true
  BtPause.Enabled=true
  item4.Enabled=true
  item3.Enabled=true
  if wave.mode=WV_MONO then
    MonoBt.checked=true
  else
    StereoBt.checked=true
  end if
  if wave.bits=WV_BIT8 then
    Bit8Bt.checked=true
  else
    Bit16Bt.checked=true
  end if
  if wave.frequence=WV_KHZ8 then
    Freq8Bt.checked=true
  elseif wave.frequence=WV_KHZ11 then
    Freq11Bt.checked=true
  elseif wave.frequence=WV_KHZ44 then
    Freq44Bt.checked=true
  end if
End Sub

Sub SaveAs
  If SaveDialog.Execute Then
    form.cursor=crHourglass
    if instr(lcase$(SaveDialog.FileName),".wav")>0 then
      wave.save(SaveDialog.FileName)
    else
      wave.save(SaveDialog.FileName+".wav")
    end if
    form.cursor=crDefault
  end if
End Sub

Sub Record
  if wave.FileOpen=false then BtStop.Down=True
  wave.lenght=Trackbar2.Position*1000
  TrackBar1.Max=Wave.lenght
  wave.record
End Sub

Sub DeleteStart
  wave.Delete(0,wave.currentPos)
  infos.panel(0).caption="Temps:"+str$(wave.lenght/1000)
End Sub

Sub DeleteEnd
  wave.Delete(wave.currentPos,wave.lenght)
  infos.panel(0).caption="Temps:"+str$(wave.lenght/1000)+"s"
End Sub

Sub ShowParam
  form2.show
End Sub

Sub TimeRecordChange
  label1.caption="Temps enregistrement(s):"+str$(TrackBar2.Position)
  infos.panel(0).caption="Temps:"+str$(TrackBar2.Position)
End Sub

Sub Init
  New
  infos.panel(0).caption="Temps:"+str$(TrackBar2.Position)+"s"
End Sub


Last Updated

Last Updated: June 6, 2003
>>variable/constant type matching added in source code.

''''''RSOCKET.INC''''''Copyright 2002 Global Services

RSocket Extends QSocket (RSocket.inc) with a proof-of-concept program
(RSocket.bas). RSocket.inc contains functions used by getname.bas and
by raw_sock.bas. RSocket requires the free RapidQ Basic compiler and
adds nine new functions to RapidQ's QSocket object:

1. New .S function with ability to create an array of sockets!

Substitute a dimensioned Socket(n) for S. With several arrays storing data
on n socket operations, such as Socket(n), time(n), Host(n), Port(n),
Status(n), etc, -- whatever you need, you can be communicating with dozens
of computers in the same time interval. You just go 1 to n, check status,
update time(n) at .Connect time or whenever, to later check how much time has
passed (IF Timer - time(n) > MaxSecToWait THEN Goto ActionTimedOut), take
appropriate action depending on Status(n) and connection status, etc.
Be sure to include a DoEvents statement as you loop from socket to socket.
A short Sleep 0.1 doesn't hurt either. This is the concept of writing
a multiple socket connection program.

2. New .NonBlock funtion sets socket S to non-blocking mode.

3. New .Block function sets socket S to blocking mode.

These functions may be used to set any socket S (or Socket(n)) to blocking
or nonblocking mode at a particular time.

4. New .Connect function is similar to the QSocket .Connect except *you* have
to create the socket first (see RSocket.bas) and the first argument is S,
the socket number returned by the .S function. At present, .Connect only
accepts dotted IP addresses (like in scanner applications) -- a.b.c.d
(use new .AddrByName function to get the IP address).

[Note: The regular QSocket .Connect returns an error (-1) or a socket number
(S), if the connection was successful, if you can wait that long to find out!]

5. NEW .IsConnected function returns 1 if connected! In actual fact, the
function tests if a connection is ready for writing. Whether or not you plan
to write to the socket, this determination is basically synonymous with an
established TCP connection.
Three return values are 1 = connected, -1 = error, 0 = neither.

6. NEW .LastError function returns a string with both WSA last socket error
code and a text description of the error code. See usage in RSocket.bas.

7. NEW .AddrByName function takes a host name string and resolves it to a
dotted IP address string (or null string if failure). This can be used before
calling .Connect if you need the IP address string. Tip: If you don't know
whether the remote host string is a name or a dotted IP address, try this:

IF inet_addr(host$)=&HFFFFFFFF THEN
ip$ = Sock.AddrByName(host$)
IF ip$ <> "" THEN Goto DoConnect ELSE Goto BadHostString
ELSE
ip$=host$
END IF
DoConnect:
ret = Sock.Connect(S,ip$,port%)

.AddrByName is called "DNS lookup."

8. NEW .NameByAddr function takes an IP address string like a.b.c.d and returns
the Host Name associated with that address. A sample program in this package,
getname.bas, shows how it works. To compile, type "rc getname" and then run it.

.NameByAddr is called "reverse DNS lookup."

9. NEW .EndConnection function implements the socket shutdown API by stopping
both send and receive of data over the socket. The regular .Close function
completely disables a socket and frees system resources. The .EndConnection
function does a mode 2 shutdown and sends a FIN packet to indicate the program
will send no more data.

10. .WriteLine replaces the QSocket .WriteLine. These append <cr><lf> or
only <lf> respectively to the string sent. This replacement is necessary
since some servers require the full <cr><lf> syntax, instead of just <lf>.
This replacement .WriteLine returns error or number of bytes written.

11. .GetPeerName replaces the QSocket .GetPeerName which did not work. Usage
is the same.

=====USAGE (see examples in RSocket.bas & getname.bas):

Dim Sock As RSocket 'creates Sock object
S = Sock.S 'creates socket handle & puts it in S
ret = Sock.NonBlock(S) 'sets socket S to non-blocking mode
ret = Sock.Block(S) 'sets socket S to default blocking mode
ret = Sock.Connect(S,ip$,port%) 'initiates connection
ret = Sock.IsConnected(S,Secs) 'returns 1 if you are connected.
Error$ = Sock.LastError 'gets WSA last error code & description
ip$ = Sock.AddrByName(host$) 'resolves host name to IP address
host$= Sock.NameByAddr(ip$) 'finds host name for an IP address
ret = Sock.EndConnection(S) 'stops socket I/O to free up socket
ret = Sock.Writeline(S,m$) 'returns bytes written or error
ip$ = Sock.GetPeerName(S) 'returns IP address of server client

=====CONNECT DETAILS:

RSocket .Connect works in either blocking or non-blocking mode depending on
calls to .Block or .NonBlock beforehand (.Block is default if no prior call
is made before a .Connect. With Blocking (the default), .Connect in RSocket
returns error (-1) or zero (connected).

The "proof of concept" (RSocket.bas) prints out lots of stuff including timer
values to prove to you that the .Connect call *does not* block!!
The only essential PRINT statement is for the Sock.Read at the end.

This "victory" in extending QSocket allows the writing of truly professional
and fast scanning programs and other applications. As far as I know, every
regular QSocket operation that requires a socknum argument (S) works. Please
email me with any problems you find or other extensions you might want.... ;-)

Now the .AddrByName function is done, so you can use a host name and get the
IP address in the form a.b.c.d.

[.GetPeerName returns an IP address but requires a connection first, as in a
server application where one wants to know the IP address of the client
computer connected to the server.]

=====MORE ABOUT USAGE:

Dim Sock as Rsocket
Dim S as long, ret as long
S=Sock.S 'This creates socket
ret=Sock.NonBlock(S) 'ret = 0 if nonblocking worked
ret=Sock.Connect(S,ip$,Port%) 'ret = -1 is error; ret = 0 is connected

'In non-blocking mode, ret above is always -1 (it's non-blocking, right?)

IF WSAGetLastError <> 10035 THEN Goto SomethingIsWrong

The above test after a .Connect attempt is important. If something is wrong,
it may be a good idea to do a Sock.Close(S) to terminate the socket, and start
fresh with a new socket handle (Sock.S).

=====MONITORING CONNECTION STATUS:

How to test if you are connected in non-blocking mode:

Of course, you have to wait some time (several hundred msec or more). Use the
DoEvents statement especially if you are initiating multiple socket connect
calls in a short interval.

1. IF Sock.IsConnected(S, Secs) > 0 THEN Goto ThisSocketIsConnected

where S is the socket handle and Secs is the timeout in seconds and fractional
quantities are not implemented (i.e., Secs is an integer).

Note: When Secs = 0, the Sock.IsConnected(S, 0) function returns with an answer
immediately (is non-blocking). However, if Secs is greater than 0, then
.IsConnected will block until a connection outcome occurs or until the timeout
has expired. Generally, speaking, multi-socket applications will use a timeout
of zero.

The new twist on the .IsConnected function is that now it will return -1 if an
error occurs. Depending on your environment, the error return will indicate
"connection refused" if sufficient time has passed (similar to what a regular
TCP connection might require). This is an important point since it means that
the remote host has replied with an ACK and RST flag TCP packet indicating it
is there, up and running. Thus, this usage of the .IsConnected function acts
as a sort of TCP ping which can reveal the presence of hosts behind firewalls
that do not respond to ICMP pings. Neat!

2. The following code also works:
ret=Sock.Connect(S,ip$,Port%) 'Do the original call again!!
ret=WSAGetLastError 'if ret = 10056, you are connected!
IF ret = 10056 THEN Goto Connected Else Goto ConnectFailed

WSAError 10056 indicates a call failed *because* the socket is connected.
In this context, IF WSAGetLastError = 10056, S is presently connected.

On the other hand, if you are trying to establish a *new* connection with
socket S and you get error 10056 in the above code, it means the *previous*
connection is still established. Either you did not do the .EndConnection
and .Close OR wait long enough OR use DoEvents to allow the network layer to
close the previous connection. It is usually best to .Close the socket,
create a new one and then proceed to the next connection.

You can test for connection status at any time. Some servers will drop
connections. Common sense suggests other methods. E.g., if an attempt to
write to the socket (Sock.Write...) returns an error, you may not have, or
have lost, a connection.

3. Just wait a little and go straight to your socket read/writes! If they
succeed, jeepers, you must be connected. If not, well, guess!

=====BE CAREFUL WITH READS (Remote computers can do funny stuff!):

Always do this for Sock.Read or Sock.ReadLine if S is in Blocking mode:

Time(n)=timer 'n is the index for S = Socket(n)
ReadData:
IF Sock.IsServerReady(S) > 0 THEN
....Sock.Read .... etc.
END IF
IF timer - Time(n) < MaxSecToWait THEN Goto ReadData

If you do not do the above, a server that maintains the connection but sends
nothing will cause your program to hang and there is NO graceful exit. Do not
assume that the protocol says the server should send something and therefore
it will. Since most will behave themselves, you will have a program that
appears to work just fine and then later just stops. If you do a netstat -a -n
you find there is an established connection there and your program is waiting
for data that the particular server will not send. Maybe after a long time,
the remote host will close it for you.

Be careful with use of any other Sock.Method with no S argument because it may
not know what to do. E.g., Sock.MySocket cannot be relied on unless you
experiment with a specific context. However, .GetHostName and .GetHostIP work
(they do not require the S argument). Just experiment to see what works.

ALWAYS do Sock.EndConnection(S) when you are done with a connected S. This is
a graceful manner to shutdown a TCP connection. Reads and writes are disabled
and a FIN packet is sent to the peer indicating the inpending closure of the
connection.

To free system resources, do .Close(S) when you are done with a particular
attempt to connect, whether or not a connection occurs. This means another
Sock.S will be done to get a new S handle. Reliable sockets programming uses
this procedure to insure that events in the last connect operation do not
affect the results of a subsequent connection.

For example, for n sockets in an array Socket(n), one can start a loop:

DIM Socket(1 to MaxSockets) As LONG
n = 1
NextSock:
IF Socket(n) <= 0 THEN Socket(n)=Sock.S: Flag(n) = 0
S = Socket(n): Sleep 0.05

'.Connect or .IsConnected depending on Flag(n), Timer-Time(n), status of S, etc
'free the socket if you are done with it, else go to LoopSock
Sock.EndConnection(S): Sock.Close(S): Socket(n) = 0

LoopSock:
IF n < MaxSockets THEN n = n + 1 ELSE n = 1
DoEvents: Goto NextSock

IF all the files in this zip are put in one directory AND your RapidQ stuff is
in C:\rapidq, then "rc rsocket" will compile the demo program. You will have to
edit RC.BAT if C:\rapidq is not the home directory for RapidQ.


Web Objects

' ----------------------------------------------
' Web.Objects Collection for CGI Development
'
' Absolutely royalty free for any kind of use
'
' Version: 2.1
' July 27, 2002.
'
' arahnoWare Inc. [c] 2002
'
' http://www.arahnoware.com
'
' ----------------------------------------------


IDE reviews

RqWork 4.9.8.100. Jul 2004.
  • Visual form editor
  • Fast syntax hilight
  • Project tree
  • Object inspector

    Nastase Eodor, Galati, A.Saligny 34, 6200, Romania

http://home.planet.nl/~water793/
A free IDE for the rapidq compiler

Last update August 2004

mailto:byteshaper@hotmail.com
easyrq.zip Size screenshot

Features:
Syntax highlighting
Objecttree & search
Search at remark,object and sub
Some trace obtions
Reverse engeneering of forms using the formeditor
Statusbar with firstvisible line counter
Preserving unknown objects (extended types) during the form editing process.

CodeEdit - v1.2

"CodeEdit started out as a semi-visual editor entitled “RapidQWorks” but was changed after downloading the CodeSense.bas program written by Dreadsoft® Corporation dreadsoft@yahoo.it that laid the groundwork for CodeEdit.

In this version you can create RapidQ objects from Forms to Sockets and just about everything else. Many of the methods listed for each object were designed for use in Subs and Functions, but for reasons of clarity were included in the design phase."

Created by Danny Jackson
With special thanks to my good friend: Dreadsoftо Corporation (manco un diritto riservato) dreadsoft@yahoo.it
Without whoose help and friendship this program would not have happened

Jens' File Editor -The Ultimate Editor for programmers
Very much thanks to L. and A. Oppenheim at School of IT, Swinburne University, Australia for the work of translating from German to English.

JFE was always quite usable. Without any documentation however, it was commonly found that it was not possible to make use of the inexhaustible possibilities provided by the editor. Now finally a remedy is at hand. However, only the important things which differentiate this editor from others will be described.

The current version here V 3.81 To Jens' Home page
  • Editing Blocks
  • Colour Management
  • Syntax Highlighting
  • Printing
  • Search Functions
  • Bookmarks
  • Special Settings
  • Tool Menu
  • Autobrowser
  • Special Operations
  • HTML Project file
  • A typical template for an HTML project
  • Work areas (Projects)
  • The Context Menu
  • Macros
  • Function keys
  • Other
RQ Debugger IDE v.04b b.178
01.2005 Andrew Shelkovenko
1. It's beta version! No warranties!.. as is .. etc.
2. Debugger not working, Form designer not working.

Main features:
- multiwindow (pseudo ;-).
Open 32 files and switch to one using "Windows" menu item.
- named bookmarks. You can set 32 bookmarks in every window
- Projects
You can save collection of Windows and bookmarks as Project.
- Subs\Function list
***********************
* BASIC IDE 0.2.6.8 *
***********************
Contact Information
Taj Morton (programmer): tmorton@linuxmail.org
Webpage: http://basic-ide.sourceforge.net
Sourceforge homepage: http://sourceforge.net/projects/basic-ide
Source code in Pascal is available.
Eduardo is freeware.
Copyright (c) 2004
Achilles B. Mina
Eduardo is a source-code editor written in Rapid-Q, a compiler-interpreter developed by William Yu.

Eduardo was designed specifically for Rapid-Q and HotBasic, the former's super-duper hermano.
RAPID-Q Basic IDE version 0.01
Author : Pairat MSU Thailand
This project can.

1. Support files : 100 files
2. Object component
3 Object is born Label , Edit , Button2
4. Object can be move and resize
5. properties not active
6. Maximum form = 100
7. Code generate not active.
8. other ..... Look VIDE source

future................ you should be developed it, and post
Source files: http://groups.yahoo.com/group/rapidq/files/Vide.zip
it is begining to develope. not complete ,but you con modifies and add othores object.
pairat.
Hellionor IDE
http://www.rapidq.it/
Scarica la Hellionor IDE 1.5.0 (ALPHA) - 2.7 Mb
 Not complete. Sorce code available
Serban Stanescu IDE
Not complete. Sorce code available 		sserbanro 07/13/2003

RQ Project

RQ Project allows the creation and the compilation of a project.
A project consists of a source program BASIC, of an icone of application, options of compilation, files BASIC included and files resource.
The application compiled can be execute with or without debugage console.


ABS

ABS MATH Function Windows/Unix
A math function that returns the absolute value of a numeric expression.

Syntax: ABS(numeric-expression)
A% = ABS(-123)

Details:
The absolute value of function returns the unsigned magnitude of its argument. So, ABS(-1) and ABS(1) are both 1.


ACOS

ACOS MATH Function Windows/Unix
A math function that returns the arccosine of a numeric expression.

Syntax: ACOS(numeric-expression)
D# = ACOS(0.55)

Details:
Numeric-expression is in the range -1 to 1.


ASC

ASC STRING Function Windows/Unix
A string processing function that returns a numeric value that is the ASCII code for the first character in a string expression.

Syntax: ASC(string-expression)
A% = ASC("A")


ASIN

ASIN MATH Function Windows/Unix
A math function that returns the arcsine of a numeric expression.

Syntax: ASIN(numeric-expression)
D# = ASIN(0.55)

Details:
Numeric-expression is in the range -1 to 1.


ATN

ATN/ATAN MATH Function Windows/Unix
A math function that returns the arctangent of a numeric expression.

Syntax: ATN(numeric-expression)
D# = ATN(0.9)

Details:
Numeric-expression is the angle expressed in radians.


BIN$

BIN$ CONVERSION Function Windows/Unix
A binary conversion function which will convert any positive INTEGER number to its binary representation.

Syntax: BIN$(numeric-expression)
S$ = BIN$(123)

Details:
Negative numbers are not supported, and so results are not defined.


BIND

BIND POINTER Function Windows/Unix
BIND will bind a variable as a function pointer.

Syntax: BIND variable TO function
DECLARE SUB MyFunc(X AS INTEGER)
BIND A% TO MyFunc

Details:
To invoke this function pointer, use CALLFUNC. Cannot be set to a a virtual Sub/Function address like a virtual table in C/C++. An alternative is to use RQASM utilities.


Bug List

List of known bugs as of November, 2005
Thanks to Andrew's Bug List

  1. ARRAYS There is no checking for limits on data arrays. You can "read" an array value outside that used in DIM, giving unpredictable results. Sometimes it is best to DIM your array with at least one more element than you need. especially if you use the array inside a SUB / FUNCTION.

  2. UBOUND/LBOUND do not work properly with array passed to a FUNCTION as parameter (returns the UBOUND/LBOUND of first DIMensioned array, may work ok in a SUB. Also UBOUND/LBOUND does not work properly with array's names ended by
    %, ! etc. Just keep track of your array bounds in separate variables.
    DIM A%(-50 TO 100) AS INTEGER
    L% = UBOUND(A%) '-- Returns 0

  3. BYTE, SHORT, WORD, SINGLE, and DOUBLE must be stored in a 32-bit long if passing ByVal to a DLL.
    Basically always try to pass a 32-bit variable such as INTEGER, DWORD, or LONG. If your DLL needs less than 2 SINGLE or more than 2 DOUBLE variables, these will not be passed correctly! The safest way to pass these variables ByRef, if possible. If you must pass them ByVal then you should just state them as INTEGERS or LONG, in the DECLARE statement.

    'here is the actual API call
    SUB gluPerspective(fovy as Double, aspect as Double, zNear as Double, zFar as Double)
    'here is how to implement it
    DECLARE SUB gluPerspective_API LIB "glu32.dll" ALIAS "gluPerspective" _
       (fovy1 as long,fovy2 as long, aspect1 as long, aspect2 as long, _
       zNear1 as long, zNear2 as long, zFar1 as long, zFar2 as long)
       DEFDBL d: DEFINT i(7)
       d = fovy: MemCpy (VarPtr(i(0)), VarPtr(d), 8)
       d = aspect: MemCpy (VarPtr(i(2)), VarPtr(d), 8)
       d = zNear: MemCpy (VarPtr(i(4)), VarPtr(d), 8)
       d = zFar: MemCpy (VarPtr(i(6)), VarPtr(d), 8)
       gluPerspective_API(i(0), i(1), i(2), i(3), i(4), i(5), i(6), i(7))
    END SUB

    'here is another example of BYTE
    Declare Sub keybd_event Lib "user32" Alias "keybd_event" _
    (bVk As BYTE, bScan As Long, dwFlags As Long, dwExtraInfo As Long)

    'all you have to do is change BYTE to LONG, and it will work fine
    Declare Sub keybd_event Lib "user32" Alias "keybd_event" _
    (bVk As Long, bScan As Long, dwFlags As Long, dwExtraInfo As Long)

  4. IF you make RapidQ component array, one more instance is created.
     dim form as qform
    dim edit(1) as qedit
    for i = 0 to 2
    edit(i).parent = form
    edit(i).top = (40 * i)
    edit(i).text = "Edit_" + str$(i)
    next i
    form.showmodal

  5. VARPTR and QUICKSORT do not work for arrays passed to a SUB/FUNCTION :
        SUB MySub (MyArray () AS INTEGER)
            addr = VARPTR(MyArray(0)) ' doesn't recognize MyArray !
       END SUB
    -- Be sure to pass the address of the array if you want to use MEMCPY, etc or QUICKSORT

  6. The $MACRO command is unstable and should be avoided completely. $DEFINE should be used for simple number replacement only
    .

  7. MEMORY LEAKS:
    1 - each call to a SUB/ FUNCTION will cause a memory leak.
     2 - EXIT SUB and EXIT FUNCTION will cause a memory leak.
    Your program may crash after many (~ 1791999) calls to a SUB /FUNCTION
    This is caused by a minor problem in the rapidQ .LIB files. Replace the .LIB files with the "Fixed libraries" ("fixed SnakeDile Libs" dated October, 2005 or later). For EXIT SUB/FUNCTION you can also just use a GOTO

    FUNCTION  Foo() AS INTEGER
      IF i > Max THEN GOTO ExitFunction
         ' do calculations here
    ExitFunction:
    END FUNCTION

  8. RapidQ can only use one CODEPTR for functions with the same number of arguments in each application,
    i.e., you can use CODEPTR( FuncA) and CODEPTR(FuncB) only if FuncA and FuncB have different number of parameters, and so on.

  9. The RIGHT$ function doesn't work properly with >32k strings.

  10. QLISTVIEW - ColumnsCount returns the wrong number on Read
    QLISTVIEW -     OnColumnClick (SUB (Column%)) - Always returns 0 in Column%
    Try QListViewEx instead (get QlistViewEx.INC or the newer RapidQ2.INC).

  11. QFILESTREAM.ReadStr(n) does not give correct result. An additional space character is added to the end of the string read, which made the string comparisons to fail.

  12. QFileStream is not a SUB as stated in the RQ HTML Documentation, it's a FUNCTION which returns ZERO when the file has an Open
    Failure. Probably many of the RapidQ objects/methods are also functions that return values.

  13. QOpenDialog modifies the current directory - This really isn't a bug, it can be an unwanted side effect.

  14. The original QCOMPORT was too buggy and removed from rapidq5.lib by the author. Use the QCOMPORT component in RAPIDQ2.INC. It uses Win32API calls so Windows only. If you use the new QCOMPORT the name of the object cannot have the word "Comport" in it:
    DIM myComport AS QCOMPORT 'compiler gives an error
    DIM myCmprt AS QCOMPORT ' should work

  15. QCANVAS OnDblClick event doesn't respond.

  16. Logical NOT operation is same as bitwise NOT.
    For RapidQ you should compare a boolean expression for (IF xx = False OR yy = True) etc.

  17. Original QTIMER document is wrong, should be OnTimer(Sender as QTimer), i.e. one parameter, not zero.
    Many other QObjects also have a SENDER parameter that is not documented.

  18. Only one QDXTimer at a time can run in a program, otherwise the program will not run.

  19. "OnEnter" event doesn't work on QLISTBOX. Instead could use the Form's OnKeyUp event to call a routine that traps the Enter key with the Form's KeyPreview property set to 1 or True
    .

  20. QTABCONTROL.DelTabs doesn't work

  21. QStringGrid.Color only works correctly in displays with 32-bit color.

  22. Custom components created using CreateWindows API function can generate runtime error 216 when form closing.
    To prevent this, use Application.Terminate in Form.OnClose event handler.

  23. Use QRichEdit to get around the 64k limit in QEDIT (this problem exists in earlier versions of Windows only):
    'Place SendMessage after you create the richedit
'and before your show your main form.
     CREATE form AS QFORM
      CREATE richedit AS QRICHEDIT
      END CREATE
     END CREATE
SendMessage RichEdit.Handle, &HC5, 0, 1048576
form.ShowModal

  24. In "For i=n0 To n1...Next" statement, sometimes i will always equal to n0 throughout the whole loop though the cycle number is right.

  25. CONVBASE$() only accepts upper-case hex string and takes an argument less than "FFFFFFFF" . This is fixed in RapidQ2.inc and is improved by CONVBASEx$()

  26. QCheckBox cannot be passed as an argument even declared "ByRef".

  27. BYTE cannot be returned correctly from a FUNCTION.

  28. QD3DFrame -- FOG methods do not work, and may hang your computer.

  29. QD3DFrame -- SetTexture does not work, use QD3DMeshBuilder.SetTexure instead

  30. QD3DVector is actually a UNION -- members x = dvx, y = dvy, and z = dvz

  31. The "Cannot focus a disabled or invisible window" problem. See Chapter 1 in the new Docs.
    Simply put the older richedit dll (dated 3/2003) into the rapidQ directory.

  32. Be sure to use the correct EXIT statement:
    Sub test()
    Dim j As Integer
        For j=1 To 2
         ' test=1 ' When 2 or more, only one loop i.
          Exit Sub
        Next j
    End Sub

     And in both cases, when Exit Function/Sub is replaced by Exit For
    everything is OK ! Always use EXIT FOR inside a For-next loop.

  33. If you use QListview.Clear, QListBox.Clear, QComboBox.Clear, QStringGrid.Clear,
    and find that it's really very Slow, do this :
    Object.Visible = False
    Object.Clear
    Object.Visible = True

  34. If you don't have a sub for your onClose event (but declare it) then there is no way to close the form.
    $TYPECHECK ON
    DECLARE SUB Strange
    CREATE Form AS QFORM
      Caption = "12345"
      OnClose = Strange
      ShowModal
    END CREATE

  35. Avoid REM for comments, especially with comments containing "\\" or "\"
    rem c:\werwer\\ 'causes error
    a=5 rem fkfkl :not working.

  36. Nested UDTs are not supported. You must recode them manually.

  37. TYPE ... END TYPE, appears to allocate at least 32k memory for each DIM xx AS TYPE:

create form as qform
caption = "Memory test"
end create

TYPE SecInfoWarp
warps AS BYTE      'Number of warps \/\/\/
warp1 AS WORD
warp2 AS WORD
warp3 AS WORD
warp4 AS WORD
warp5 AS WORD
warp6 AS WORD
END TYPE

DIM SecInfo(1000) AS SecInfoWarp
form.showmodal
'end here
In two trials i got 32Mb, and 36Mb for the second... Now i know that includes what ever DLL's the rapidq uses, which is approx 9Mb (or maybe4.??Mb???) of those values... But that still means that for an array of 1000 of my UDT equals approx. 23 - 27 Mb's... The UDT should be like about 13 bytes, so

1000 times that should only equal 13,000 bytes!!! Im running Win98SE with 96Mb RAM, and a 330Mb swap file, and while i could compile that routine at10,000, it caused such a drag on my system that Norton System Info wouldn't run! Means that pretty much all availible memory PLUS swap file was used!!! That means that on my system it must have used somewhere between 350Mb and 400Mb for my UDT array of only 10,000!!! So what is going on here?!?!?!?

I even removed the warp AS BYTE/WORD and replaced them with a single "warps AS STRING*13", and it still tells me that it is useing 36Mb!!!
If i removed the UDT, and dimension the array like so...

DIM SecInfo(1000) AS WORD
... then the program only use 4.7Mb(total including DLL's)!!! So it must be a bug with UDT's!

Be carefully with Arrays of UDT.

TYPE TTest
S AS STRING*8
N AS INTEGER
na(5) as integer
END TYPE

DIM Test AS TTest
Dim Testa (10) as TTest

CREATE Form AS QFORM
    Caption = "Test UDT": Center
    CREATE RichEdit1 AS QRICHEDIT
        BorderStyle = 0:
    END CREATE
END CREATE

Test.s="qwerty"
Test.n=12345
for j%=1 to 5 : Test.na(j%)=j%: next
RichEdit1.AddStrings "Test.na(1)="+ str$(Test.na(1))
Testa(2)=Test '
RichEdit1.AddStrings Testa(2).s+" "+str$(Testa(2).n)+" "+str$(Testa(2).na(1)) '------- 1'

Testa(2).na(1)=Test.na(1) ' ----- It doesn't work ! Why??
RichEdit1.AddStrings Testa(2).s+" "+str$(Testa(2).n)+" "+str$(Testa(2).na(1)) '---------2'

d=Test.na(1):Testa(2).na(1)=d '----- Wow! It works
RichEdit1.AddStrings Testa(2).s+" "+str$(Testa(2).n)+" "+str$(Testa(2).na(1)) '----------3'

Testa(2).na(1)=1'Test.na(1) '-------- It's simply ;-)
RichEdit1.AddStrings Testa(2).s+" "+str$(Testa(2).n)+" "+str$(Testa(2).na(1)) '----------4'

Form.ShowModal

Testa(2)=Test ' be careful setting equal to one UDT to another may not work!!


CALLBACK

CALLBACK/CODEPTR ADDRESS Function Windows
CODEPTR (or CALLBACK) will return the absolute address of a SUB or FUNCTION.

Syntax: CODEPTR(MySUB)

SUB MySUB
END SUB
A& = CODEPTR(MySUB)

Details:
Use this function for CALLBACK routines, i.e., when your program responds to Windows messages and calls your function). Note - there is only ONE CALLBACK/CODEPTR allowed for each function that uses the same number of parameters. So not all cases may be implemented unless you use caution. It cannot be set to a a virtual Sub/Function address like a virtual table in C/C++.

Examples:
FUNCTION One (A as LONG) AS LONG
....
END FUNCTION

FUNCTION Two (A as LONG, B as LONG) AS LONG
....
END FUNCTION

FUNCTION Two2 (A as LONG, B as LONG) AS LONG
....
END FUNCTION
In this case CODEPTR(One) is different from CODEPTR(Two)
BUT, CODEPTR(Two) is the same as CODEPTR(Two2) and only the last function declared is called! Since WndProc uses four parameters you can only have one WndProc per application:
pOldProc = SetWindowLong(Myhandle,GWL_WNDPROC, CODEPTR(Form.WndProc).

There is a fix using the Callback forwarder code by Jacques Philip.
See the function gRQ2_SetNewCallBack in RapidQ2 for examples on how to do this


CALLFUNC

CALLFUNC POINTER Function Windows/Unix
CALLFUNC will execute the function pointer that was bound by using BIND.

Syntax: CALLFUNC(fptr, param1, param2, ...)
CALLFUNC(FPtr, 10, 20)
PRINT CALLFUNC(FPtr2, 10, 20)

Details:
Depending on how you BIND your function pointer, you can either call CALLFUNC as a statement or a function. Make sure to supply the necessary number of parameters, else you will receive a compile error. Passing function pointers as parameters is not yet implemented, but you can read up on Chapter 11 to see how to emulate this.


CEIL

CEIL MATH Function Windows/Unix
A math function that rounds a numeric expression up toward positive infinity.

Syntax: CEIL(numeric-expression)
A% = CEIL(66.2) '-- Returns 67


CHDIR

CHDIR SYSTEM Statement Windows/Unix
CHDIR will change the current working directory for your application.

Syntax: CHDIR string-expression
CHDIR "c:\windows"


CHR$

CHR$ STRING Function Windows/Unix
A string processing function that returns a one-character string whose ASCII code is the argument.

Syntax: CHR$(numeric-expression)
A$ = CHR$(66)

Details:
Numeric-expression should be in the range 0-255.


CINT

CINT CONVERSION Function Windows/Unix
A conversion function that converts a numeric expression to an integer by rounding the fractional part of the expression.

Syntax: CINT(numeric-expression)
A% = CINT(66.7)

Details:
Implemented for compatibility with QBasic, you can use the more logical function, ROUND, instead.


CLNG

CLNG CONVERSION Function Windows/Unix
A conversion function that converts a numeric expression to an integer by rounding the fractional part of the expression.

Syntax: CLNG(numeric-expression)
A% = CLNG(66.7) '-- equals 67

Details:
Implemented for compatibility with QBasic, you can use the more logical function, ROUND, instead.


Tutorial on COM and DirectX interface

At one point it was thought that DirectX under RapidQ might be improved by custom programming. However, because of the inability to RapidQ to properly handle function pointers, this is not recommended. The easier way to do write DirectX code in FreeBasic and make it into a DLL. With that said, here is the Quick but Lame Tutorial on COM interface and RapidQ

First make sure you know the abbreviations:

API – application programming interface. How you talk with the operating system to get it to do what you program asks.

DLL - Dynamic Link Library an EXTERNAL file that contains machine code. Your program can use DLL to run Windows API. DLLs load in the same process space (memory area) as your program. You cannot compile a DLL into your program.

GUID - Globally Unique identifier. A 16-bye code that identifies a specific COM object. That is DirectDraw (one little piece of DirectX) has a GUID that is for a DirectDraw version. That way all new versions are known from old ones and other pieces of DirectX. You might remember the QOLEOBJECT example in which

Microsoft Word has a GUID "{000209FE-0000-0000-C000-000000000046}" that thing has 16 bytes of hexadecimal codes.

POINTER – a variable that holds the memory address (location in computer memory) of a variable, User defined TYPE, a SUB, Func, etc. etc. RapidQ does not give you all pointers (see below)

DIM a AS INTEGER
DIM lp AS LONG
A = 5
Lp = VARPTR(a)        ‘lp is now the pointer, it does not = 5!!! But a memory address.
lp =@a                      'the @ symbol also says get the address of the variable

COM - Component Object Model. You never get a straight answer from M$. Basically, this is an advanced way to improve a DLL. Once a COM is made it is standard and new versions will work with older programs. They are suited for C++ coding. It kind of turns DLLs into object oriented programming.

Instead of using API functions like this:

A = GetWidth (myObject)

B = GetHeight (myObject)

You would have a DLL with an object oriented programming interface:

A = NewObject.Width (myObject)

A = NewObject.Height (myObject)

It’s just cleaner coding but it is a hassle to get it working in RapidQ.

The BASICs of DirectX

___________________

DirectX uses the COM interface. It is not the same as “OLE automation”, which also uses a COM interface but with a different format.

Instead of calling one or many individual SUB/Func like this:

Declare Function GetForegroundWindow Lib "user32" Alias "GetForegroundWindow" () As Long

Declare Function GetDC Lib "user32" Alias "GetDC" (hwnd As Long) As Long

….. on and on

You are going to have one a (or few) simple calls Here is the only call you need to start DirectDraw:

Declare Function DirectDrawCreate Lib "ddraw.dll" ALIAS "DirectDrawCreate" (ByVal lpGUID As Long, ByVal lplpDD As Long, ByVal pUnkOuter As Long) As Long

Wow, that was easy! Wrong….

What happens is this Function returns a POINTER TO A STRUCTURE, that can be used to IMPLEMENT the INTERFACE. This is explained later. Here is how you run it:

$DEFINE LPDIRECTDRAW LONG ‘ variables of “LPxxxx” are pointers

$DEFINE LPDIRECTDRAWSURFACE LONG ‘use LONG for 32-bit windows

$DEFINE IDirectDraw LPDIRECTDRAW

$DEFINE HRESULT LONG ‘handle for a return value

$DEFINE DD_OK 0 ‘this checks if it ran OK

‘The API to create our DirectDraw “OBJECT”

Declare Function DirectDrawCreate Lib "ddraw.dll" ALIAS "DirectDrawCreate"_

(ByVal lpGUID As Long, ByVal lplpDD As Long, ByVal pUnkOuter As Long) As Long

DIM result AS HRESULT

DIM lpDD AS LPDIRECTDRAW ‘our pointer

lpDD = 0 ‘null it out

result = DirectDrawCreate(0, @lpDD,0) ‘get the pointer to the interface

‘first parameter is 0, which is the default active display, second parm passes the Pointer of lpDD using the ‘@’ symbol to the FUNCTION

‘last parameter must be 0 for ‘future expansion’ by windows

IF result <> DD_OK THEN

ShowMessage "Create direct draw Failed"

ELSE

ShowMessage STR$(lpDD)

END IF

‘end of program…………………………

This program actually runs and returns a large number in lpDD. This is the starting address of the INTERFACE. IF you run it, you cannot close down the directDraw interface because you are supposed to RELEASE it, so windows can use the memory

Here is the c code:

lpDD ->Release();

You can’t do it in RapidQ, yet. So if you run the program you just used up some memory…

With the line

result = DirectDrawCreate(0, @lpDD,0)

We now have a pointer to a pointer that points to a structure, the pointer is lpDD !! But how do we start calling the DirectDraw functions? You need to declare the structure and then use that pointer to the stucture. You know what a structure is (use TYPE or STRUCT)

TYPE MyType

A AS LONG

B AS INTEGER

END TYPE

Then what does the DirectDraw structure look like?

The code for a SUB or FUNCTION sits in some memory address space in the computer. The program knows where that code is by a pointer. Pointers are only numbers, and for Windows 32-bit, the pointer is of a LONG type. The pointer holds the memory address of the starting location of the code. So if you know the value of the pointer, you can "jump" that memory location and run the code in that "process space." Before you can run that code, the program must know how many, and what type of parameters there are to run the code

SUB Add(a as integer, b as integer)

CODEPTR(Add)-- will be the memory where start code of Add SUBroutine. Now you need to call the sub so the computer knows there are two parameters (a and b), which are both integers

In RapidQ, you must first BIND the SUB/Func to a LONG

DIM fptr AS LONG

BIND fptr TO Add

*** in C you don't do this

now you can run the code so the computer knows the right number and type of parameters

CALLFUNC(fptr(a,b))

NOW FOR DIRECTX, DIRECT3D, DIRECT Play, etc--

When you start DirectX, it GIVES YOU the memory address of its code in a pointer!! That is you have no idea where the CODEPTR is!! So if

CALLFUNC(CreateDirect3D, my3Ddisplay, etc., etc) you know that "CreateDirect3D" is the starting memory address and "my3Ddisplay, etc., etc..." are the parameters to pass to that SUB/FUNC. How does the program know the correct number and type of parameters for DirectX? From those HUGE, HUGE, C header files!

Since CALLFUNC uses some internal table for memory addresses (in the sample program it returns "1", NOT a real memory address) then I can't see how to develop DirectX, DirectPlay, DirectMusic in RapidQ .
The bottom line, you will need a C-like programming language such as BCX or FreeBasic to program in DirectX


CONST

CONST Statement Windows/Unix
A non-executable statement that declares symbolic constants to use in place of numeric or string values.

Syntax: CONST constantname [ as Datatype ]= expression
CONST False = 0
CONST True AS LONG = NOT False
CONST A$ = "Hi world!"
CONST Char = CHR$(66)
CONST Combine = A$ + Char

Details:
Expression can be any value, numeric or string. Rapid-Q will decipher what the constant value will be bound to (ie. a string or a numeric variable) if the constantname is not followed by a type-declaration character (%. &, !, #, $, etc...).


CONVBASE$

CONVBASE$ CONVERSION Function Windows/Unix
A conversion function which takes the string expression represented in a specified base to be converted to another specified base determined by the arguments passed.

Syntax: CONVBASE$(string-expression, frombase, tobase)
S$ = CONVBASE$("FFD", 16, 2) '-- Convert from base 16 to 2
S$ = CONVBASE$("287", 10, 16) '-- Convert from base 10 to 16

Details:
Negative numbers are not supported.

All Strings should be in UPPERCASE and an exception Fault occurs if
string-expression =  "FFFFFFFF"

These errors have been fixed in RapidQ2.INC
Also see CONVBASEx$ for numbers up to 53 bits.


CONVBASEx$

CONVBASEx$ CONVERSION Function Windows/Unix
A conversion function like CONVBASE$ that takes the string expression and converts it to another specified base determined by the arguments passed. However, this handles numbers up to 53 bits long.

Syntax: CONVBASEx$(string-expression, frombase, tobase)
'-- Convert from base 16 to 2
PRINT CONVBASEx$("1FFFFFFFFFFFFF", 16, 2)

Details:
included in RapidQ2.INC
Also see CONVBASEx$ for numbers up to 53 bits.


COS

COS MATH Function Windows/Unix
A math function that returns the cosine of an angle given in radians.

Syntax: COS(numeric-expression)
PI = 3.14153
C# = COS(PI)

Details:
Numeric-expression is the angle expressed in radians.


D3D Details

D3D detailed document by John Kelly D3D Details

Detailed information about Direct3D for Rapid-Q

Near-professional 3D applications can be made in RapidQ. Although RapidQ is a byte-coded interpreter, the 3D rendering is done via Microsoft's DirectX 6.0 and Direct3D (version 2.0?) library. That's good because the speed is not greatly affected by the byte-code interpreter, and your program may run quite fast! DirectX and Direct3D is an API (application programming interface) that uses the "COM interface" (Windows only). It appears that RapidQ uses an older package called DelphiX, which was written of course in Delph (Pascal). All this happens behind the scenes for you. Direct3D Retained Mode should continue to work with newer versions of DirectX, as Microsoft claims it will be backward compatible. Since Direct3D Retained Mode uses immediate mode API code, RapidQ may even improve with updates in DirectX - but don’t count on it. If you want RapidQ to upgrade 3D, this must be done outside RapidQ with external DLLs. Another option is to create an OpenGL DLL from FreeBasic (www.freebasic.net).

About the D3D interface:
RapidQ must use DirectX to access Direct3D (directX creates a " DirectDraw screen", which is the same as QDXSCREEN). So the reason why you must do all 3D with a QDXSCREEN is because of Microsoft's API. Direct 3D (D3D) uses "Retained mode" - or D3DRM. All that retained mode means is that the program keeps track of the 3D objects for you, which makes programming it a lot simpler than OpenGL (which requires you to draw each object point every time it changes rotation, position, etc.). There is some documentation available via g.slyip.com or on the web (win32_2.hlp). The documentation talks about the IUnknown interface.This is complicated and is NOT the same COM interface used for OLE automation (like Word, Excel, etc). The doc calls the interface like this: “IDirect3DRMObjects"

I = "Interface"
  (the API)
Direct3D = you know this
RM = retained mode
Objects = like objects in Rapidq or QDXSCREEN

For example, if you want to know about the RapidQ mesh builder, William Yu documents that "QD3DMeshBuilder implements “Direct3DRMMeshBuilder" So in the WIN32_2.HLP file search for IDirect3DRMMeshBuilder and that will be the best information you can get about QD3DmeshBuilder.

All documentation is for C++ programming but don't let that stop you. In C++ coding you separate the Object from the class by the “::”
Example in C++ :
IDirect3DRMMeshBuilder::AddFace (LPDIRECT3DRMFACE lpD3DRMFace)

In RapidQ it is simpler:
QD3DmeshBuilder.AddFace(Face AS QD3Dface)
--------------------------------------------------------------------.

Since Visual Basic uses DirectX9 why can’t RapidQ just use those include files?

In Visual Basic the programmer loads a “table file” with a .tbl extension. This is a binary file that sets up the API calls, CLASSES, procedures, constants, etc to program in Direct 3D. You can look at them with Microsoft visual studio. The COM interface QOLEOBJECT part of RapidQ will probably never work because it is too complicated. Therefore, Rapidq will not be a 3D clone of visual basic. In fact, I don’t see how RapidQ can improve in 3D without an external 3D engine that can be called by standard DLL. This is a shame because 3D in Rapidq 3D is a LOT easier to learn than C++, and even Visual Basic NET.

STARTING D3D in RapidQ is easier than you think!

RapidQ does a LOT of things for you to program in 3D. When you start with
** NOTE numbers in RapidQ D3D are usually of type DOUBLE !!!

CREATE DXScreen AS QDXSCREEN
BitCount = 32 '8, 16,24 32 bits/pixel
Use3D = True 'load Direct3D Retained mode Object
UseHardware = 1 ‘does the hardware abstraction layer
…. Etc
END CREATE

Here are some of the things that RapidQ does for you (and just this simple code would be about 40 lines of C++ code). Here’s what I think happens:
1) Creates a DirectX Device,
2) Creates a IDirect3DRMDevice from DirectX (Windows uses the DirectDraw screen and Direct3D draws to the DirectDraw screen),
3) Sets a viewport with the IDirect3DRM::CreateViewport (for sizing the view),
4) Sets a Clipper object with IDirect3DRM::CreateDeviceFromClipper(), which sets the limits of rendering in 3D space. A clipper function keep objects clipped to the window.
5) sets up a color ramp model and sets the shading for lights, color ramps, the number of texture colors
6) Sets up a camera to be attached to a FRAME (see below)
7) Sets the number of off-screen buffers (memory buffers that are drawn to before you FLIP them to the DXscreen
8) Creates a ROOT FRAME that defines your position and orientations (and others) in your 3D world. You will see this in RapidQ as DXScreen.SetCameraPosition(X, Y, Z) and DXScreen.SetCameraOrientation(0.35, -0.65, 1.0, -0.15, 1.0, 0.5),
9) AND RapidQ takes care of the callbacks for you (like WM_PAINT and WM_ACTIVATE). This is the beauty of RapidQ because it is really ugly in C/C++ .

OK so how does RapidQ make 3D graphics?

1) There are a minimum of 3 main 3D objects that must be DIM and then Created 1) a Meshbuilder for holding the 3D data points, 2) a Frame for rotating, sizing, and positioning the 3D objects relative to the camera, and 3) a Light that illuminates the scene. This is discussed in more detail below.

Thinking in 3D- Meshes

Representing an object in 3D by computers takes a little thought. We know a rock is solid but for 3D graphics the surface is all that matters. A visual object is made up of a set of polygons (usually a triangle) defined by one or more end points (1 = vertex, 2 or more = vertices). For DirectX a vertex is a point in x,y,z dimensions. Three points, or two points and a line, define a polygon, which looks like a flat triangle. Keep adding more triangles to this one, all at different angles and you eventually form a mesh in 3D space that represents the surface of the object. When the object is only defined by vertices, then it of course, will look like a wireframe model. The computer needs to fill in the wireframe with a shaded surface that has a color, bitmap texture, and a reflectance property.

In Direct3DRM objects can be made up of a mesh. The mesh is a set of vertices that define polygon (triangle) faces. You add FACES to a MESH via MESHBUILDER. The easiest way to do this is load a X model (e.g., MeshBuilder.Load("egg.x") but more on this later) The “normal” of each faces is the direction in x,y,z that is perpendicular to the face (also called orthogonal or 90 degrees from the face). You should see why this is important for lighting and reflectance. Changing a vertex or normal that is used by several faces will change the appearance of all faces connected to it. The vertices can also be used to define two-dimensional coordinates within a texture map.

QD3DMeshBuilder ( IDirect3DRMMeshBuilder)

QD3DMESHBUILDER will make up a visual object defined by a set of polygon faces with vertices and normals. You can think of the flat polygons as “faces.” They are on the surface of the object. You make up each face with QD3Dface (IDirect3DRMFace), which contains the vertices. Keep adding the FACES to MESHBUILDER until you make up the whole mesh of the object. MESHBUILDER will calculate the normals of each face for you. In RapidQ, you can only set the color of the whole face (normally you could set the color of each vertex, set a texture to those vertices, and reflectance(e.g., a shiny versus a dull material for a single face or all faces in a mesh by using the SetColor, SetTexture, and SetMaterial functions. RapidQ only supports SetRGBcolor. Textures are discussed below.

QD3DmeshBuilder the heart of RapidQ 3D objects

In RapidQ there are only two properties in a QD3DMESH minY and maxY. So William Wu set up QD3DMESHBUILDER (IDirect3DRMMeshBuilder) to do all of the work with 3D objects. QD3DMESHBUILDER will load and maintain your meshes. You can individually add VERTICES, FACES, and .X model Meshes (a large collection of vertices, etc) to your MESHBUILDER

QDXScreenr.CreateFace(Face AS QD3Dface) ' create an empty face
QD3DMeshBuilder.CreateFace(Face AS QD3Dface) 'also this to create an empty face , untested?
QD3DmeshBuilder.AddVertex (X#, Y#, Z#)
QD3DmeshBuilder.AddFace (Face AS QD3DFace)
QD3DmeshBuilder.Load (S AS String) 'load a .x model file defining a mesh of vertices.

So to create a mesh yourself by adding each face (a polygon defined by vertices) to the mesh individually. Your code might look like this:
DXscreen.CreateFace(Face)
Face.AddVertex(x,y,z)
Meshbuilder.AddFace(Face)

First you make the face, then add data points to it (this must be done at least two times on the same face), then you add the face to the mesh via MeshBuilder. If you do it yourself, you need to add each vertex to a face in clockwise order if you want the normal to come out towards you as you look at the face. The opposite order makes the normal point away from you AND WILL NOT BE RENDERED, because of “face culling.” This makes the render faster by not showing both sides. I don’t know how to turn CULLING off… ** NOTE This process can be really slow. There is a more efficient IDirect3DRMMeshBuilder::AddFaces but RapidQ (RC.EXE) will not recognize it even if variables were correctly declared. ***

Obviously unless you are making an object yourself (like a terrain), making faces is difficult, the easiest thing to do is load an .X file with
QD3DMeshBuilder.Load(My_X_file.x).

The file already has a mesh made up of faces in 3-D. Wu mentions making meshes with Anim8tor, but my favorite is Open FX (www.openfx.org) – a free and very powerful modeler. Then you convert these files (3DS, etc) to a .x file:

CONV3ds –m My_3DS.3ds --- be sure to add the –m
Or use another .x file compatible program.

QD3DMesh (IDirect3DRMMesh)

The QD3DMesh object really doesn't work in RapidQ. It must have been left unfinished. So this statement has no real purpose:
QD3DmeshBuilder.CreateMesh (Mesh AS QD3DMesh)

That is too bad because QD3DMESHBUILDER is slower than QD3DMESH when changing the shape of the mesh, such as morphing (e.g., MeshBuilder.Scale(xx, yy,zz). This is because QD3DMESHBUILDER is built on top of QD3DMESH and the system must convert a MeshBuilder object into a Mesh object before rendering it. Both allow faces with more than three sides. They also automatically handle a mesh in memory if the video card has a limited memory. Unfortunately, RapidQ did not build upon QD3DMESH, which (as IDirect3DRMMesh object) which normally assigns characteristics such as materials, textures and grouping of vertices (C/C++ code:)
IDirect3DRMMesh::SetGroupColour,
IDirect3DRMMesh::SetGroupTexture
IDirect3DRMMesh::SetGroupMaterial.

Changing 3D objects - Frames
A Frame simply put is a 4 x 4 matrix. That is not complicated, it is just 4 x 4 = 16 numbers. But the order of these numbers is crucial. All you need to know is that a Frame lets you SCALE, MOVE, and ROTATE your 3D object that you just made with a MeshBuilder. In RapidQ you use QD3DFrame (the IDirect3DRMFrame). Basically the vertices of the mesh are multiplied by the 4 x 4 matrix and out comes the newly changed 3D object.

PUTTING IT TOGETHER IN RAPIDQ 3D

After 3D objects in your scene are made (vertices, faces, and meshes in a MeshBuilder, you need to create one or more lights. The light is also a 3D object. Next you need to create some FRAMEs for your whole scene. All 3D shapes, and even lights, must be stored in a frame before it can be added to the world and manipulated. The camera has a frame too, but RapidQ does not let you work with a Camera frame. It is hidden from you. A FRAME is a “frame of reference.” Frames are located in space, and they can have a rotation, a velocity, and they can be moved, or "transformed". QD3DFRAME provides a frame of reference that objects can be placed in. Visual objects are placed in a scene by taking their positions and orientations from the QD3DFRAME. So, if you have a set of 3D objects (visuals) that you want to move together around a scene, you would call IDirect3DRMFrame::AddVisual to add the visuals to the frame. There is a parent frame that defines the whole scene. All the other frames are “children” to this frame. If you move a parent frame, then all the child frames move with it. For instance if the parent frame moves then the 3D Objects, lights, and camera move with it. Alternatively, you move the object itself by just moving it’s frame. You create the frames before you can use them. When you create a frame, this apparently loads the API into memory, allocates resources, etc. So your initialization should include some important calls

QDXSCREEN.OnInitialization = DXInitialize(Sender AS QDXScreen).
SUB DXInitialize
DXScreen.CreateFrame(MeshFrame AS QD3DFRAME) ‘probably the parent frame
DXScreen.CreateFrame(LightFrame AS QD3DFRAME)
DXScreen.CreateMeshBuilder(MeshBuilder AS QD3DMeshBuilder)
DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, QD3Dlight)

‘ There is no CreateFrame for the camera -- RapidQ must do it for you ….
….

The FRAMES are sorted into a hierarchy. RapidQ takes care of this for you but there is a parent frame that determines the whole scene. I don’t know if the order of creation is important for the parent frame. You can make a “child frame” relative to another Frame so that the second 3D object will move with the parent frame:

DIM ParentFrame AS QD3DFRAME
DIM ChildFrame AS QD3DFRAME
DXscreen.CreateFrame(ParentFrame)
ParentFrame.AddFrame(ChildFrame)

Frames added to the parent frame are connected to it and also move along with it when you move the parent frame. In the above example ChildFrame.Rotate(x,y,z,a) will do nothing you must do ParentFrame.Rotate(x,y,z,a) and both move together.

Remember a QD3DFRAME is not really visible, it just does the moving translation, orienting for you. To render a mesh, you could load (or create) a mesh, then create a QD3DFRAME and then add the MeshBuilder to the frame as a visual object with AddVisual():

QD3Dframe.AddVisual (Visual AS QD3DMeshBuilder/QD3DMesh)

One mesh can be added to multiple frames to create more than one of the same mesh.

There is a “QD3Dvisual” but documentation must be found in the API documentation for IDirect3DRMVisual

Now we increase the flow of operation (order not important?)

1) create a frame of reference

CREATE MESH FRAME -> CREATE MESHBUILDER

2) make a light

CREATE LIGHT FRAME -> CREATE LIGHT

3) make a 3D object

VERTEX -> FACE -> MESHBUILDER -> ADDVISUAL to FRAME

(repeat for more objects)

4) Orient your camera’s viewpoint

DXscreen.SetCameraPosition SUB (X#, Y#, Z#)
DXscreen.SetCameraOrientation SUB (DX#, DY#, DZ#, UX#, UY#, UZ#)

In IDirect3DRM the FRAME can have a velocity with a SetVelocity function (which actually is implemented in RapidQ! But we need to figure out how to use it) and frame rotation is set with a SetRotation function. The frame's objects will move to their new locations and will rotate correspondingly before each scene is rendered. If you do not want your objects to move or rotate, then these values should be set to zero (the default value). A frame will keep on rotating and moving as long as these values are nonzero. You call QD3Dframe.AddVisual to add a frame as a visual to another frame. This way, you can use a given hierarchy of frames many different times throughout a scene.

Moving 3D objects in Space

The default the Origin is at the bottom left corner of your screen. In 3D space the positive x-axis points to the right and the positive y-axis points up. Z gets larger as you move away from the viewer, into the screen (see the figure above).

Moving a 3D object in space is a translation by changing POSITION.

Turning a 3D object is a ROTATION or ORIENTATION

Changing the size of a 3D object is a SCALE

You can move, or rotate by the FRAME that the 3Dobject is added to:

QD3Dframe.SetPosition (X#, Y#, Z#)
QD3Dframe.SetOrientation (DX#, DY#, DZ#, UX#, UY#, UZ#)
QD3Dframe.SetRotation (X#, Y#, Z#, Theta#)
QD3Dframe.AddScale (CombineType%, X#, Y#, Z#)

Because a light is added to a frame you can move the light around too by its frame.

Or move the position of the Object itself with

QD3DmeshBuilder.Translate (TX#, TY#, TZ#)

(normally there are many functions in IDirect3DMMeshBuilder that are not supported by RapidQ)

Textures in Retained Mode

IDirect3DRMTexture is used for texture mapping and is an interface to the DirectDrawSurface object. The texture used can be a 2D image, either in the .bmp format or the .ppm format. It should be kept in mind that the image data in a bitmap (.bmp) file is upside down, while a .ppm file is correct side up. This object just manages the texture to be used for texture mapping. To actually do texture mapping, the Direct3DRMWrap object has to be used, to specify the wrapping function, alongwith this object.

With a texture, you can map patterns, such as bitmap pictures, onto the surfaces of objects, such as faces and meshes. You can add a texture to a mesh with QD3DmeshBuilder.SetTexture.

In C++ you can add one to a face in a mesh with IDirect3DRMFace::SetTexture. If you have a mesh in a file in the .PPM file format, you can load it with the IDirect3DTexture::Load function.

You can set the number of colors used to render a texture using the IDirect3DRMTexture::SetColors function.

You will want to use the CreateWrap and Wrap.Apply to create and assign a wrapping function that can be used to assign texture coordinates to faces and/or meshes. You can move your textures by changing the U,V or scaling coordinates!

Texture Wrapping in Retained Mode

Used to calculate the texture coordinates for an object. To create a wrapping function for an object, we need to specify the type of wrapping used, the reference frame and origin, the direction vector, the up vector, a pair of scaling factors and the origin for the texture coordinates. The wrapping function determines how the rasterizer module interprets the texture coordinates.

The different types of wrapping functions that can be specifie are:

Flat

- 2D image is mapped to a 2D object

Cylindrical

- the object is placed inside a hollow cylinder with the texture on the innder side of the cylinder. The cylinder is then collapsed onto the object

Spherical

- the object is placed inside a hollow sphere with the texture on the innder side of the sphere. The sphere is then collapsed onto the object

Chrome

- also called environment mapping. It is similar to spherical mapping. Here the reflected ray of light is used to select the texture to be specified at a point on the object

Lighting and Shadows in Retained Mode

IDirectD3DRM supports five types of light: directional, ambient, point, point-parallel and spotlight. Lights are used to illuminate the 3D objects based on the mesh’s orientation to the light sources in the scene. An AMBIENT light illuminates an entire scene but creates a very flat look. A POINT light emanates in all directions from one location. A DIRECTIONAL light come from one direction, but has no set origin. A SPOT light produces light in the shape of cone. Lights can be combined for rich illumination of the shape. First you must attach lights to a frame in order for it to illuminate 3D objects in a scene. Because the frame provides both orientation and position for the light, you can move and redirect a light simply by moving and reorienting the frame the light is attached to.

The vertex normals are used when lighting in Flat, Gouraud and Phong (going from worse to better but slower) shading models to give a smooth look to a polygonal object. RapidQ does rendering without allowing you special operations to generate or change normals.

Direct3DRMLights

Represents a light source in a scene. A light source on creation, has to be added to a frame. A light source can be any one of the following types:

Ambient

- the amount of light present at each point in the scene

Directional

- light rays have a direction and are parallel. Light is considered to be placed at an infinite distance. Can be used to model a Sun-like light source

Parallel Point

- similar to Directional light, but light is placed at specified point

Point

- light is placed at specified point. Light emits equally in all directions

Spotlight

- light is placed at specified point. Light is emitted as a cone, with the apex being at the specified point

Shadows are created with the IDirect3DRM::CreateShadow function. Before creating and using a shadow, you will first want to define a light source to produce light. After you have added a light source to your scene the shadow is handled by the IDirect3DRM::CreateShadow function.

Examples in other languages:

Create a direct3d device in Delphi :

D3DrmAPI.CreateObject(CLSID_CDirect3DRMDevice, nil , IID_IDirect3DRMDevice, dev1);

dev1.InitfromClipper(DDClipper, IID_IDirect3DRMDevice, r.right, r.bottom);

dev1.QueryInterface(IID_IDirect3DRMWinDevice, dev2);

A piece of code to create a Direct3D device in BCX

DIM lpD3DRM AS LPDIRECT3DRM ' Direct3DRM object
DIM lpDDClipper AS LPDIRECTDRAWCLIPPER ' DirectDrawClipper object
DIM dev AS LPDIRECT3DRMDEVICE ' Direct3DRM device
DIM view AS LPDIRECT3DRMVIEWPORT ' Direct3DRM viewport
DIM scene AS LPDIRECT3DRMFRAME ‘same as QD3Dframe?
DIM camera AS LPDIRECT3DRMFRAME ‘same as QD3Dframe?
DIM myGUID AS GUID ' GUIDs of available D3D drivers

' Create the D3DRM object and the D3DRM window object.

lpD3DRM = NULL
Direct3DRMCreate(&lpD3DRM) ‘send the address of the object

' Create the master scene frame and camera frame.
lpD3DRM->lpVtbl->CreateFrame(lpD3DRM, NULL, &scene)
lpD3DRM->lpVtbl->CreateFrame(lpD3DRM, scene, &camera)

' Create a DirectDrawClipper object and associate the window with it.
DirectDrawCreateClipper(0, &lpDDClipper, NULL)
lpDDClipper->lpVtbl->SetHWnd(lpDDClipper, 0, Form1) ‘attach to form handle

' Create the D3DRM device by using the selected D3D driver.
GetClientRect(Form1, &rc)
lpD3DRM->lpVtbl->CreateDeviceFromClipper(lpD3DRM, lpDDClipper, GUID, Width, Height, & dev)
rval = lpD3DRM->lpVtbl->CreateViewport(lpD3DRM, dev, camera, 0, 0, W, H, & view)

… etc

So think RapidQ is hard?

There are many more options in D3D, RapidQ only uses part of them. For more information about D3DRM you will need to read the Microsoft documenation of the COM interface a IDirect3DRMObject, IUnknown) interface.

Object

Description

Direct3DRMAnimation

Allows access to the keys and frame of an animation. Defines how a transformation will be modified, often in reference to a Direct3DRMFrame3 object. Use it to animate position, orientation, and scaling of Direct3DRMVisual, Direct3DRMLight, and Direct3DRMViewport2 objects.

Direct3DRMAnimationArray

Retrieves the number of animations in the array and an interface to the requested animation.

Direct3DRMAnimationSet

Allows Direct3DRMAnimation2 objects to be grouped together.

Direct3DRMClippedVisual

Allows clipping visuals to arbitrary planes before rendering.

Direct3DRMDevice3

Represents the visual display destination for the renderer. Enables you to set and retrieve materials.

Direct3DRMFace2

Represents a single polygon in a mesh.

Direct3DRMFrame3

Positions objects within a scene and defines the positions and orientations of visual objects. Enables access to frame axes, bounding boxes, and materials. Supports ray picking. Adds transform, traversal, and fogging capabilities.

Direct3DRMInterpolator

Stores actions and applies the actions to objects with automatic calculation of in-between values.

Direct3DRMLight

Defines one of five types of lights that are used to illuminate the visual objects in a scene.

Direct3DRMMaterial2

Defines how a surface reflects light. Allows finer control over material properties than previous versions.

Direct3DRMMesh

A set of polygonal faces that can be used to manipulate groups of faces and vertices.

Direct3DRMMeshBuilder3

Allows you to work with individual vertices and faces in a mesh. Provides greater control over normals and allows retrieval of a face on a mesh. Uses the Direct3D Immediate Mode DrawPrimitive interface when created with IDirect3DRM.

Direct3DRMObject

A base class used by all other Direct3D Retained Mode objects; it has characteristics that are common to all objects.

Direct3DRMObject2

Enhances Direct3DRMObject by allowing more flexible data association with an object.

Direct3DRMPickedArray

Identifies a visual object that corresponds to a given 2-D point.

Direct3DRMPicked2Array

Identifies a visual object corresponding to a given ray intersection.

Direct3DRMProgressiveMesh

A coarse base mesh, together with records describing how to incrementally refine the mesh, allows a generalized level of detail to be set on the mesh as well as progressive download of the mesh from a remote source.

Direct3DRMShadow2

Defines a shadow. Shadow properties can now be set and retrieved after creation.

Direct3DRMTexture3

A rectangular array of colored pixels. Enables loading resources from files other than the currently executing file, textures creating from images in memory, and generating MIP maps. Allows finer control over texture management than previous versions.

Direct3DRMUserVisual

Defined by an application to provide functionality not otherwise available in the system.

Direct3DRMViewport2

Defines how the 3-D scene is rendered into a 2-D window. Allows you to specify what should be cleared.

Direct3DRMVisual

Anything that can be rendered in a scene. Visual objects need not be visible; for example, a frame can be added as a visual.

Direct3DRMWrap

Calculates texture coordinates for a face or mesh.

You can see how RapidQ uses similar names.
For more information search the C/C++ header file “d3drmobj.h”


DATA

DATA Statement Windows/Unix
A non-executable statement that stores the numeric and string constants used by a program's READ statements.

Syntax: DATA {constant|EXECUTE(...)}[,...]
DATA my dog ate my homework, "oh, boy!", 34.4
DATA EXECUTE(LEFT$("Hello", 2, 3))

Details:
Constant is any valid numeric or string constant. If a string constant contains commas, colons, or leading or trailing spaces you want to preserve in your program, you must enclose the string in double quotes. You can also execute code by using the EXECUTE keyword. The return value of this executed code will be the value returned to your READ statement.


DATE$

DATE$ SYSTEM Function Windows/Unix
A function that returns a string containing the current date formatted as MM-DD-YYYY. Where MM = month (1-12), DD = day (1-31) and YY = year (1980-2099)

Syntax: DATE$
PRINT DATE$

Details:
Unlike QBasic where you can set the current date using the DATE$ statement, you cannot do this under Rapid-Q.


DEC

DEC Statement Windows/Unix
Decrements numeric variable by one, or by the amount specified.

Syntax: DEC(variable [, amount])
DEC(I)
DEC(I, 10)

Details:
You can also use the minus minus C-like statement :
DIM i as INTEGER
i = 5
i--
PRINT i


DEF...

DEF... Statement Windows/Unix
DEFBYTE, DEFDBL, DEFDWORD, DEFINT, DEFLNG, DEFSHORT, DEFSNG, DEFSTR, DEFWORD are declaration statement that names one or more variables and allocates storage space for them.

Syntax: DEFINT variable[(subscripts)] [, ...]
DEFSTR A, B, C="Hello", D, E
DEFINT I=99, J(100,10), K

Details:
You cannot specify a range of variables, for example: DEFINT A-Z works fine under QBasic, but not Rapid-Q. You can initialize each variable as demonstrated above. DEF... statements are equivalent to calling DIM, but can save you a lot of typing. To initialize an array, wrap the values around curly braces {...}. For Example,
DEFINT A(1 TO 10) = {1,2,3,4,5,6,7,8,9,10}
Initializes elements 1 through 10 with the values 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10 respectively.


DELETE$

DELETE$ STRING Function Windows/Unix
A function that deletes part of a string.

Syntax: DELETE$(string-expression, start, length)
A$ = DELETE$("Hello world", 2, 3) '-- Result: Ho world


DIM

DIM Statement Windows/Unix
Declaration statement that names one or more variables and allocates storage space for them. There is no checking for limits on arrays. You can "read" an array value outside that used in DIM, giving unpredictable results. Always keep track of your array start and end instead of LBOUND and UBOUND for the best results.

Syntax: DIM variable[(subscripts)] AS type
DIM A AS INTEGER, B(2,5,3,9,2) AS INTEGER
DIM S AS STRING
DIM Form AS QFORM

Details:
Use the optional (subscripts) to declare the size of arrays, up to 5 dimensions. Here are some rules to remember:
OK:
DIM a AS INTEGER, b AS INTEGER, c AS INTEGER

NOT RECOGNIZED CORRECTLY:
DIM a, b, c AS INTEGER
(In this case, a and b will be VARIANTs, and only c is INTEGER)

OK:
DIM (a, b, c) AS INTEGER

NOT RECOGNIZED CORRECTLY:
DIM (a = 1, b = 2) AS INTEGER ' error!
(try this instead if you want to write your code compactly)
DIM a AS INTEGER = 1, b AS INTEGER = 2

Also, you cannot have one of the variables be an array, while others aren't:
 DIM (a, b(5), c) AS INTEGER ' incorrect!
DIM (a, b, c)(5) AS INTEGER ' correct: a, b and c are arrays


DIR$

DIR$ SYSTEM Function Windows
A system function used to obtain the first/next file corresponding to a specified filespec.

Syntax: DIR$[(file-spec, attribute)]
FileName$ = DIR$("*.*", 0) '-- Get first file
FileName$ = DIR$ '-- Get next file

Details:
File-spec specifies a filename or path (which can include wildcards characters).
Calling DIR$ with no parameters return additional filename matches. If no matches exist (or all matches have been exhausted), DIR$ returns an empty string. DIR$ returns all regular files as well as any special files specified in the attribute parameter.
Here are some valid file attributes, you can combine
them by using OR (ie. faReadOnly OR faDirectory)

&H1 = faReadOnly       &H8 = faVolumeID
&H2 = faHidden        &H10 = faDirectory
&H4 = faSysFile       &H20 = faArchive
                      &H3F = faAnyFile
To obtain additional information on the currently matched file, use the FileRec properties.
FileRec.FileName    - Returns Windows long file name
FileRec.ShortName   - Returns the short file name
FileRec.Date        - Returns the file date as a string
FileRec.Time        - Returns the file time as a string
FileRec.Size        - Returns the file size
FileRec.FileTime    - Returns the file time as an integer
You can use FileRec.FileTime to compare file times. So a newer file will have a FileTime greater than an older file.


DIREXISTS

DIREXISTS SYSTEM Function Windows
A function that returns 0 if directory does not exist, non-zero otherwise.

Syntax: DIREXISTS(string-expression)
A = DIREXISTS("c:\windows")


DOEVENTS

DOEVENTS RAPID-Q Specific Windows
Returns control to the operating system to process the events in its queue, and returns back control to the program once done.

Syntax: DOEVENTS
DO
DOEVENTS
LOOP

Details:
DoEvents should normally be used for long-running processes (ie. long loops or anything else that eats up the CPU), so that the user can abort the process if necessary. DoEvents can also be used to handle multiple forms.


END

END Statement Windows/Unix
Terminates your program.

Syntax: END
END

Details:
Call END to terminate your application, but if there are any Windows still opened, you should close them first. In some cases you may have to use Application.Terminate instead if you get an error with END


ENVIRON

ENVIRON SYSTEM Statement Windows/Unix
A statement used to set or modify an environment variable.

Syntax: ENVIRON string-expression
ENVIRON "PATH=c:\windows"
ENVIRON "TEST what"

Details:
String-expression must have the form
parametername=text
or
parametername text
Everything to the left of the equal sign or space is assumed to be a parameter, and everything to the right, text. If the parametername has not previously existed in the environment string table, it is appended to the end of the table. If a pametername already exists, it gets deleted and the new parametername is appended to the end of the table.


ENVIRON$

ENVIRON$ SYSTEM Function Windows/Unix
A function that returns an environment string.

Syntax: ENVIRON$(environment-string)
A$ = ENVIRON$("PATH")

Details:
It is not possible, at this time, to retrieve an environment string by its index.


RESTORE

EXIT SUB
/FUNCTION
/DO
/FOR 		control flow Statement Windows/Unix
Allows you to break out of a SUB or FUNCTION before the END SUB or END FUNCTION
or exit early out of a loop.

Syntax: EXIT {SUB} {FUNCTION} {DO} {FOR}

Details:
In RapidQ EXIT SUB and EXIT FUNCTION cause a large memory leak. Avoid using EXIT SUB or EXIT FUNCTION inside any loops. This bug occurs with or without the "Fixed Libraries." It is very easy to avoid EXIT SUB and EXIT FUNCTION:
SUB test
  IF b < 1 THEN GOTO EXIT_SUB
  FOR a = 1 TO b
    c = c + 1
  NEXT a
EXIT_SUB:
END SUB
** note the sub is exited early the loop will not run if b < 1


EXP

EXP MATH Function Windows/Unix
A math function that returns the exponential function (e raised to the power of n).

Syntax: EXP(numeric-expression)
A# = EXP(1)


EXTRACTRESOURCE

EXTRACTRESOURCE RESOURCE Statement Windows/Unix
A statement that extracts a resource, from the current program, to a file.

Syntax: EXTRACTRESOURCE resource-value, filename
EXTRACTRESOURCE Resource(0), "test.bmp"

Details:
The resource-value is the absolute position of the resource within the current program. To find the absolute position of the resource, see also RESOURCE(), and RESOURCECOUNT.


FIELD$

FIELD$ STRING Function Windows/Unix
A function that returns a field (or token) separated by deliminators.

Syntax: FIELD$(Source-string, deliminator-string, field-number)
A$ = FIELD$("John&Doe&555-1234", "&", 2) '-- Returns Doe
A$ = FIELD$("John&&Doe&&555-1234", "&&", 3) '-- Returns 555-1234


FILEEXISTS

FILEEXISTS SYSTEM Function Windows/Unix
A function that returns 0 if file does not exist, non-zero otherwise. The current working directory is searched for the file if no path is specified.

Syntax: FILEEXISTS(string-expression)
A = FILEEXISTS("rapidq.exe")


FIX

FIX MATH Function Windows/Unix
A function that removes the fractional part of a number.

Syntax: FIX(numeric-expression)
A% = FIX(342.97)


FLOOR

FLOOR MATH Function Windows/Unix
A math function that rounds a numeric expression down toward negative infinity.

Syntax: FLOOR(numeric-expression)
A% = FLOOR(66.7) '-- Returns 66


FORMAT$

FORMAT$ STRING Function Windows/Unix
A function that returns a formatted string assembled from a Pascal style format string and a series of arguments. The Pascal style format string closely resembles C style format strings, but definitely not VB compatible.

Syntax: FORMAT$(Format-string, arg1, arg2, ...)
A$ = FORMAT$("Location: %s %4d %-10.4g", "Any", 1234, 55.39) '-- Returns Location: Any 1234 55.39
Details:
Format strings passed to the string formatting routines contain two types of objects--plain characters and format specifiers. Plain characters are copied verbatim to the resulting string. Format specifiers fetch arguments from the argument list and apply formatting to them. Format specifiers have the following form:
"%" [index ":"] ["-"] [width] ["." prec] type
A format specifier begins with a % character. After the % come the following, in this order:
An optional argument index specifier, [index ":"]
An optional left justification indicator, ["-"]
An optional width specifier, [width]
An optional precision specifier, ["." prec]
The conversion type character, type
The following table summarizes the possible values for type:
d | Decimal. The argument should be an integer value. The value is converted to a string of decimal digits. If the format string contains a precision specifier, it indicates that the resulting string must contain at least the specified number of digits; if the value has less digits, the resulting string is left-padded with zeros.
e | Scientific. The argument should be a floating-point value. The value is converted to a string of the form "-d.ddd...E+ddd". The resulting string starts with a minus sign if the number is negative. One digit always precedes the decimal point. The total number of digits in the resulting string (including the one before the decimal point) is given by the precision specifier in the format string--a default precision of 15 is assumed if no precision specifier is present. The "E" exponent character in the resulting string is always followed by a plus or minus sign and at least three digits.
f | Fixed. The argument should be a floating-point value. The value is converted to a string of the form "-ddd.ddd...". The resulting string starts with a minus sign if the number is negative. The number of digits after the decimal point is given by the precision specifier in the format string--a default of 2 decimal digits is assumed if no precision specifier is present.
g | General. The argument should be a floating-point value. The value is converted to the shortest possible decimal string using fixed or scientific format. The number of significant digits in the resulting string is given by the precision specifier in the format string--a default precision of 15 is assumed if no precision specifier is present. Trailing zeros are removed from the resulting string, and a decimal point appears only if necessary. The resulting string uses fixed point format if the number of digits to the left of the decimal point in the value is less than or equal to the specified precision, and if the value is greater than or equal to 0.00001. Otherwise the resulting string uses scientific format.
n | Number. The argument should be a floating-point value. The value is converted to a string of the form "-d,ddd,ddd.ddd...". The "n" format corresponds to the "f" format, except that the resulting string contains thousand separators.
m | Money. The argument should be a floating-point value. The value is converted to a string that represents a currency amount.
s | String. The argument must be a string. The string or character is inserted in place of the format specifier. The precision specifier, if present in the format string, specifies the maximum length of the resulting string. If the argument is a string that is longer than this maximum, the string is truncated.
x | Hexadecimal. The argument should be an integer value. The value is converted to a string of hexadecimal digits. If the format string contains a precision specifier, it indicates that the resulting string must contain at least the specified number of digits; if the value has fewer digits, the resulting string is left-padded with zeros.

Conversion characters may be specified in uppercase as well as in lowercase--both produce the same results.
An index specifier sets the current argument list index to the specified value. The index of the first argument in the argument list is 0. Using index specifiers, it is possible to format the same argument multiple times. For example Format$("%d %d %0:d %d", 10, 20) produces the string "10 20 10 20".


FRAC

FRAC MATH Function Windows/Unix
A function that returns the fractional part of a number.

Syntax: FRAC(numeric-expression)
A# = FRAC(342.97)


GETCAPTURE Windows API Call in RapidQ2.INC Windows
Windows API that retrieves the handle of the window (if any) that has captured the mouse. Only one window at a time can capture the mouse; this window receives mouse input whether or not the cursor is within its borders. This is a keyword in RAPIDQ2.INC

Syntax: Handle = GETCAPTURE
DIM theHandle AS LONG
theHandle = GETCAPTURE
IF theHandle = Canvas.Handle THEN SHOWMESSAGE "Button is inside picture"

Details:
A value of 0 means the current program has not captured the mouse. Use the ReleaseCapture function to releases the mouse capture from a window in the current program and restore normal mouse input processing. A window that has captured the mouse receives all mouse input, regardless of the position of the cursor, except when a mouse button is clicked while the cursor hot spot is in the window of another thread.


GETFOCUS Windows API Call in RapidQ2.INC Windows
A WinAPI call that gets the handle to the control that receives the keyboard output. This is a keyword in RAPIDQ2.INC

Syntax: hWnd = GETFOCUS()
IF MyButton.Handle = GETFOCUS () THEN '...do code for the keyboard focus on button

Details:
You can set which control gets the focus with SETFOCUS.GetFocus only gets the window associated with your program (calling thread’s message queue). GetFocus will return 0 if another program has the keyboard focus


HEX$

HEX$ CONVERSION Function Windows/Unix
A function that returns the hexidecimal (base 16) representation of the (base 10) numeric expression.

Syntax: HEX$(numeric-expression)
A$ = HEX$(123)

Details:
Negative numbers are supported. In the Windows version, the string is pre-padded with 0's to fit the string length of 8.


HEXtoDEC

HEXTODEC CONVERSION Function in RapidQ2.INC Windows/Unix
A function that returns a LONG integer from a string of a hexidecimal (base 16) number. Use this to convert HEX$ to a LONG integer (base 10). This function is only included in the RAPIDQ2.INC file.

Syntax: HexToDec(HexNum$)
DIM A AS LONG
A = HexToDec(HEX$(123))

Details:
A signed number will be returned, so if the highest order bit is set, the number will be negative.


IIF

IIF Function Windows/Unix
The immediate IF function returns one of two parts depending on the evaluation of an expression. Notice that both parts are evaluated, whether the expression returned true or false, so watch for undesirable side effects.

Syntax: IIF(expression, true-expr, false-expr)
A$ = IIF(6 > 5, "TRUE", "FALSE") '-- returns TRUE


INC

INC Statement Windows/Unix
Increments numeric variable by one, or by the amount specified.

Syntax: INC(variable [, amount])
INC(I)
INC(I, 10)

Details:
You can also use the plus plus C-like statement :
DIM i as INTEGER
i = 5
i++
PRINT i


Rapid-Q Documentation by William Yu

  • Rapid-Q is a multi-platform, multi-purpose BASIC compiler/interpreter.
  • Rapid-Q is created by William Yu
  • Rapid-Q is free for commercial or non-commercial use.
  • Rapid-Q comes with no warranties, or guarantees.
  • Rapid-Q is currently in a beta stage, but is fully functional.

Contents Up Next page


INITARRAY

INITARRAY ARRAY Statement Windows/Unix
Initializes an array with the corresponding values. (POSSIBLE BUG,use MEMSET instead)

Syntax: INITARRAY(Array, value [, ...])
DIM A(1 TO 100) AS INTEGER
INITARRAY(A, 55, 234, 45, 99)

Details:
Equivalently:
DEFINT A(1 TO 100) = {55, 234, 45, 99}

Initializing arrays as opposed to looping through each one saves a bit of time.


INP

INP I/O Function Windows/Unix
A device I/O function that returns the byte value read from an I/O port.

Syntax: INP(port)
A% = INP(&H3C9)

Details:
Port is any word value between 0 and 65535. Return value is in the range 0 to 255. This keyword is stable for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, tryutilities like PorkTalk or io.dll instead.


INPW

INPW I/O Function Windows/Unix
A device I/O function that returns the word value read from an I/O port.

Syntax: INPW(port)
A = INPW(&H3C9)

Details:
Port is any word value between 0 and 65535. Return value is also in the range 0 to 65535. This keyword is stable for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, tryutilities like PorkTalk or io.dll instead.


INSERT$

INSERT$ STRING Function Windows/Unix
A function that returns a string with an inserted substring beginning at a specified index.

Syntax: INSERT$(insert-string, source-string, index-number)
A$ = INSERT$("hi", "Hello", 3) '-- returns Hehillo


INSTR

INSTR STRING Function Windows/Unix
A function that compares 2 strings and returns the position of the find-string with respect to the search-string. If found, INSTR returns the index position of the find-string, 0 otherwise.

Syntax: INSTR([start,] search-string, find-string)
A% = INSTR("Hello", "ll") '-- returns 3
A% = INSTR(4, "hehe they", "he") '-- returns 7


INT

INT MATH Function Windows/Unix
A function that returns the largest integer less than or equal to a numeric-expression. Fractional part is truncated.

Syntax: INT(numeric-expression)
A& = INT(342.97)


KILL

KILL SYSTEM Statement Windows/Unix
A statement that removes a disk file.

Syntax: KILL filespec
KILL "mydocuments.txt"
KILL "*.c"


KILLMESSAGE

KILLMESSAGE RAPID-Q Specific Windows
A statement that removes a message from the queue.

Syntax: KILLMESSAGE hWnd, Message
KILLMESSAGE form.handle, WM_CHAR

Details:
Ideally, KillMessage should be used inside an event, such as OnKeyDown, to remove any messages you don't want processed further.


LBOUND

LBOUND ARRAY Function Windows/Unix
A function that returns the lower bound of the array.

Syntax: LBOUND(arrayname [,dimension])
DIM A(-50 TO 100) AS INTEGER
L% = LBOUND(A) '-- Returns -50

Details:
If the array has multiple dimensions, you can use the optional dimension argument to check the lower bound of each one.

NOTE:
You might find this keyword unreliable in a SUB/FUNCTION. Just in case you should always keep track of the lower and upper bounds of an array since RapidQ does not check to see if you reference an array out of bounds!

Do not use variable names with a variable symbol with %, !, #, etc.,
DIM A%(-50 TO 100) AS INTEGER
L% = UBOUND(A%) '-- Returns 0


LCASE$

LCASE$ STRING Function Windows/Unix
A string function that returns a string expression with all letters lower-case.

Syntax: LCASE$(string-expression)
A$ = LCASE$("HELLO") '-- returns hello


LEFT$

LEFT$ STRING Function Windows/Unix
A string function that returns a string consisting of the leftmost n characters of a string.

Syntax: LEFT$(string-expression, n)
A$ = LEFT$("Hello",2) '-- returns he


LEN

LEN STRING Function Windows/Unix
A function that returns the number of characters in a string.

Syntax: LEN(string-expression)
A% = LEN("HELLO") '-- returns 5

Details:
LEN will not return the number of bytes required by a variable. This option is available under QBasic.


LFLUSH

LFLUSH PRINTER Statement Windows
A statement used to begin a print job.

Syntax: LFLUSH
LPRINT "print this line"
LFLUSH '-- call this to start printing

Details:
You should call LFLUSH after you're satisfied that you want to start printing. If you don't call LFLUSH, then whenever your application terminates is when your document will start its print job.


LIBRARYINST

LIBRARYINST DLL Function Windows
Returns the handle to the DLL module. If the DLL hasn't been loaded yet or is not found, this
function returns 0.

Syntax: LIBRARYINST(DLLName)
DECLARE FUNCTION UpdateWindow LIB "USER32" ALIAS _
"UpdateWindow" (hWnd AS LONG) AS LONG
UpdateWindow(0) '-- Using function will load DLL
hInst& = LIBRARYINST("USER32")

Details:
This command has a bug. If possible use theWindows API "loadLibrary" instead.

Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"_
(ByVal lpLibFileName As String) As Long
hDll& = LoadLibrary("nviewlib.dll") 'returns DLL handle if available

Declaring a function as a DLL function does not automatically load the DLL. The DLL is loaded once the function is used. Please note that library names should match, so in your declaration for LIB "USER32" ... to find this library, you must match that same name. ie. LIBRARYINST("USER32.DLL") returns 0, it must be "USER32" in this particular case. See also UNLOADLIBRARY.

RapidQ does not support compile-time linking with another .lib file. Use FreeBasic or other compilers (BCX, FreeBasic, etc) to create your own DLL files.


Limitations
-Windows 32 only.
-Cannot make arrays of this component, each must have a separate name.
- Must be DIM or CREATED at the global level (not inside a SUB/FUNCTION)


Links

Rapid-Q related discussion groups
 Rapid-Q
rapidq_works
RapidQProjects
Rq-ide
bpp-translator
codemax
envelopbasic
ezboard-rapidqbasic

 useful examples
 RQDP more_examples
asm.zip - 260 k
aYliteBeta.zip - 23 k
bpp.zip - 1000 k
Database.zip - 1800 k
Internet.zip - 140 k
more_examples.zip - 700 k
rqdlls.zip - 650 k
RQTiny.zip - 45 k
Win32API_Rel.zip - 70 k
editor.zip - 230 k
media.zip - 115 k
ole.zip - 120 k
reminder.zip - 62 k

Guidance Laboratory Inc
- (mirror, seems faster)

  • examples

  • Documentation

  • External Libraries

  • Rapid-Q Introduction

  • Resource & Utility

  • Tutorial

Links from Guidance's Rapid-Q Resource Site (dead links cleaned)
 Guidance's Rapid-Q Resource Site:
 g.yi.org or a.2myip.com
g.slyip.com or citymap.126.com
  • Yahoo! Groups RapidQ
  • RapidQ Ezboard Discussion Forum
  • RapidQ Reference, Source Code
  • Italian RapidQ Page
  • RapidQ ...Or XBasic?

    other links
    http://home.planet.nl/~water793/
    http://j.lypstenger.free.fr/

    Examples and snippets

    Yahoo rapidQ Files
    Yahoo rapid-Q Files

    http://home.planet.nl/~water793/ - more examples


LOG

LOG MATH Function Windows/Unix
A math function that returns the natural logarithm of a numeric expression.

Syntax: LOG(numeric-expression)
A# = LOG(10)


LPRINT

LPRINT PRINTER Statement Windows
A statement just like PRINT except all output is directed to the default printer. Make sure to call LFLUSH to start the print job.

Syntax: LPRINT [expressions][{;|,}][...]
LPRINT "print this line"
LFLUSH

Details:
You should call LFLUSH after you're satisfied that you want to start printing. If you don't call LFLUSH, then whenever your application terminates is when your document will start its print job.


LTRIM$

LTRIM$ STRING Function Windows/Unix
A string function that returns a string with leading spaces removed.

Syntax: LTRIM$(string-expression)
A$ = LTRIM$(" Hello") '-- returns Hello


MATH (RTL Math lib>

'------------------------------------------------------------------
'>>>>>>   rq-math.inc   Version 1.1 (09-2000)<<<<<<<<<<<<<<<<<<<<
'------------------------------------------------------------------
'                Rapid-Q Mathematics $Includes
'   written by Bruno Schäfer <bup.schaefer@planet-interkom.de>
'------------------------------------------------------------------
'  !!!!    All angles are in radiant !!!   ... but not in function DEG2RAD  :-)
' If an ERROR occurs in some functions there will be a Messagebox
' and the returned value is ZERO !!!!!
'
' Rapid-Q - http://www.basicguru.com/abc/rapidq/
'           http://www.egroups.com/group/rapidq
' This .inc.-file  contains additional commonly used mathematical functions
' and utilities (in addition to the standard mathematical functions
' supported in William Yu's Rapid-Q)
' This is a work in progress, so don't expect too much.
' Many thanks for ideas and remarks:
' send an e-mail to (bup.schaefer@planet-interkom.de) or the egroup.
' planned functions in next versions:
' better trapping of ERRORs and of undefined values  ...and more functions:
' different round methods,' vectoroperations, derivation, integral-functions,
' more natural constants,scientific function,' arithmetical and statistical
' functions (perhaps in own $includes ???)...
'==============================================================================
CONST rqPI = 3.141592654 '(This is PI)
CONST rqE = 2.718281828  '(This is e)
CONST rqh = 6.62620 * 10 ^ (-34)   '(J*S: Planck const.)
CONST rqc = 2.997925 * 10 ^ 8      '(m/s: velocity of light in vacuum)
'-------------------------------------------------------------------------------
'   ACOSH() returns the hyperbolic areacosine of x
'-------------------------------------------------------------------------------
Function ACOSH(value AS DOUBLE) AS DOUBLE
  SELECT CASE value
   CASE IS < 1
    MessageBox("Invalid Argument !!!", "ACOSH - Error", 0)
   CASE IS >= 1
    ACOSH =  ( LOG (value + SQR( value ^ 2 - 1 )))
  END SELECT
End Function
'-------------------------------------------------------------------------------
'   ACOT() returns the arccotangent of x
'-------------------------------------------------------------------------------
Function ACOT(value AS DOUBLE) AS DOUBLE
 ACOT = ((rqPI / 2) - ATAN (value))
End Function
'-------------------------------------------------------------------------------
'   ACOTH() returns the hyperbolic areacotangent of x
'-------------------------------------------------------------------------------
Function ACOTH(value AS DOUBLE) AS DOUBLE
 SELECT CASE ABS (value)
  CASE IS > 1
   ACOTH =  (LOG((value + 1) / (value - 1)) * 0.5)
  CASE ELSE
   MessageBox("ERROR: Invalid Argument !!!", "ACOTH - Error", 0)
 END SELECT
End Function
'-------------------------------------------------------------------------------
'   ACOSEC() returns the arccosecans of x
'-------------------------------------------------------------------------------
Function ACOSEC(value AS DOUBLE) AS DOUBLE
 SELECT CASE ABS (value)
  CASE IS < 1
   MessageBox("Invalid Argument !!!", "ACOSEC - Error", 0)
  CASE ELSE
   ACOSEC =  (ASIN(1/value))
  END SELECT
End Function
'-------------------------------------------------------------------------------
'   ACOSECH() returns the hyperbolic arccosecans of x
'-------------------------------------------------------------------------------
Function ACOSECH(value AS DOUBLE) AS DOUBLE
 SELECT CASE ABS(value)
  CASE = 0
   MessageBox("Invalid Argument !!!", "ACOSECH - Error", 0)
  CASE ELSE
   ACOSECH =  (ASINH(1 / value))
 END SELECT
End Function
'-------------------------------------------------------------------------------
'   ADDZ() returns the sum of two complex numbers
'-------------------------------------------------------------------------------
Function ADDZ(Z()AS DOUBLE ) AS DOUBLE
    re1 = Z(0): im1 = Z(1) : re2 = Z(2) : im2 = Z(3)
    Z(0) = re1 + re2
    Z(1) = im1 + im2
    Z(2) = 0
    Z(3) = 0
    ADDZ = Z()
End Function
'-------------------------------------------------------------------------------
'   ASINH() returns the hyperbolic areasine of x
'-------------------------------------------------------------------------------
Function ASINH(value AS DOUBLE) AS DOUBLE
 ASINH = LOG (value + (SQR(value * value + 1)))
End Function
'-------------------------------------------------------------------------------
'   ASEC() returns the arccosecans of x
'-------------------------------------------------------------------------------
Function ASEC(value AS DOUBLE) AS DOUBLE
 SELECT CASE ABS (value)
  CASE IS < 1
    MessageBox("ERROR:Invalid Argument !!!", "ASEC - Error", 0)
  CASE ELSE
   ASEC =  (rqPI / 2 - ASIN( 1 / value))
 END SELECT
End Function
'-------------------------------------------------------------------------------
'   ASECH() returns the hyperbolic arccosecans of x
'-------------------------------------------------------------------------------
Function ASECH(value AS DOUBLE) AS DOUBLE
 SELECT CASE ABS (value)
  CASE IS > 1
   MessageBox("ERROR:Invalid Argument !!!", "ASECH - Error", 0)
  CASE IS <= 0
   MessageBox("ERROR:Invalid Argument !!!", "ASECH - Error", 0)
  CASE ELSE
   ASECH = (ACOSH(1 / value))
 END SELECT
End Function
'-------------------------------------------------------------------------------
'   ATANH() returns the hyperbolic areatangent of x
'-------------------------------------------------------------------------------
Function ATANH(value AS DOUBLE) AS DOUBLE
 SELECT CASE ABS(value)
  CASE IS < 1
   ATANH = (LOG((1 + value) / (1 - value)) * 0.5)
  CASE 0
   ATANH = 1
  CASE ELSE
   MessageBox("ERROR:Invalid Argument !!!", "ATANH - Error", 0)
 END SELECT
End Function
'--------------------------------------------------------------------------------
'   CONJZ() returns the conjugated complex number of a complex number
'--------------------------------------------------------------------------------
Function CONJZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(1) = im * (-1)
    CONJZ = Z()
End Function
'-------------------------------------------------------------------------------
'   COSEC() returns the cosecans of x
'-------------------------------------------------------------------------------
Function COSEC(value AS DOUBLE) AS DOUBLE
 COSEC = 1 / SIN(value)
End Function
'-------------------------------------------------------------------------------
'   COSECH() returns the hyperbolic cosecans of x
'-------------------------------------------------------------------------------
Function COSECH(value AS DOUBLE) AS DOUBLE
 COSECH = (2 / (EXP(value) - EXP(value * -1)))
End Function
'-------------------------------------------------------------------------------
'   COSH() returns the hyperbolic cosine of x
'-------------------------------------------------------------------------------
Function COSH(value AS DOUBLE) AS DOUBLE
 COSH = (0.5 * (EXP(value) + EXP(value * -1)))
 IF value = 0 THEN COSH = 1
End Function
'--------------------------------------------------------------------------------
'   COSZ() returns the cosine of a complex number
'--------------------------------------------------------------------------------
Function COSZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = COS(re) * COSH(im)
    Z(1) = SIN(re) * SINH(im)
    COSZ = Z()
End Function
'--------------------------------------------------------------------------------
'   COSHZ() sine of a complex number
'--------------------------------------------------------------------------------
Function COSHZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = COSH(re) * COS(im)
    Z(1) = SINH(re) * SIN(im)
    COSHZ = Z()
End Function
'-------------------------------------------------------------------------------
'   COT() returns the cotangent of x
'-------------------------------------------------------------------------------
Function COT(value AS DOUBLE) AS DOUBLE
 COT = 1 / TAN(value)
End Function
'-------------------------------------------------------------------------------
'   COTH() returns the hyperbolic cotangent of x
'-------------------------------------------------------------------------------
Function COTH(value AS DOUBLE) AS DOUBLE
 SELECT CASE value
  CASE 0
   MessageBox("ERROR: Invalid Argument !!!", "COTH - Error", 0)
  CASE ELSE
   COTH = COSH(value) / SINH(value)
  END SELECT
End Function
'-------------------------------------------------------------------------------
'   DEG2RAD() returns radians instead of degrees
'-------------------------------------------------------------------------------
Function DEG2RAD(value AS DOUBLE) AS DOUBLE
 DEG2RAD = value * 0.017453
End Function
'--------------------------------------------------------------------------------
'   DIVZ() returns the quotient of two complex numbers
'--------------------------------------------------------------------------------
'   DIVZ() = Z1 / Z2
Function DIVZ(Z()AS DOUBLE ) AS DOUBLE
    re1 = Z(0): im1 = Z(1) : re2 = Z(2) : im2 = Z(3)
    Z(0) = (req * re2 + im1 * im2) / (re2*re2 + im2*im2)
    Z(1) = (-re1 * im2 + re2 * im1) / (re2 * re2 + im2 * im2)
    Z(2) = 0
    Z(3) = 0
    DIVZ = Z()
End Function
'--------------------------------------------------------------------------------
'   EVEN() returns "1" (= true) if a number is even, else "0"
'--------------------------------------------------------------------------------
Function EVEN(value AS INTEGER ) AS INTEGER
   IF FRAC(value / 2) = 0 THEN
    EVEN = 1
   ELSE
    EVEN = 0
   END IF
End Function
'--------------------------------------------------------------------------------
'    EXPZ() returns the exponential value of a complex number (= e^z)
'--------------------------------------------------------------------------------
Function EXPZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1) : a = Z(3)
    Z(0) = EXP(re) * COS (im)
    Z(1) = EXP(re) * SIN (im)
    EXPZ = Z()
End Function
'-------------------------------------------------------------------------------
'   FAC() returns the factorial of the integer x
'-------------------------------------------------------------------------------
Function FAC(value AS LONG) AS LONG
 SELECT CASE value
  CASE IS < 13
   N = value
   value = 1
    For I = 1 to N
     value = value * I
    NEXT I
   FAC = value
  CASE IS > 12
   MessageBox("ERROR: Invalid Argument !!! Argument must <= 12!", "FAC - Error", 0)
 END SELECT
End Function
'--------------------------------------------------------------------------------
'   FIX() truncates the argument to closest integer value towards zero
'--------------------------------------------------------------------------------

'-------------------------------------------------------------------------------
'   GCD() returns the greatest common denominator of two integers
'   based on the Euclidean algorithm
'-------------------------------------------------------------------------------
Function GCD(value1 AS DOUBLE, value2 AS DOUBLE ) AS LONG
  ERROR% = 0
  SELECT CASE value1
   CASE IS <> INT(value1) 'Integer check
    ERROR% = 1
   CASE 0                 'ZERO check
    ERROR% = 2
  END SELECT
  SELECT CASE value2
   CASE IS <> INT(value2) 'Integer check
    ERROR% = 1
   CASE 0                 'ZERO Check
    ERROR% = 2
  END SELECT
  SELECT CASE ERROR%
   CASE 0
    value1 = ABS(value1) : value2 = ABS(value2)    'Euclidean algorithm
     DO
      Res = value1 - value2 * INT(value1/value2)
      IF Res = 0 THEN GCD = value2
      value1 = value2
      value2 = Res
     LOOP UNTIL Res = 0
   CASE 1
     GCD = 0
     MessageBox("Invalid Argument (no INTEGER)!!!", "GCD - Error", 0)
   CASE 2
     GCD = 0
     MessageBox("Invalid Argument (ZERO)!!!", "GCD - Error", 0)
  END SELECT
End Function
'--------------------------------------------------------------------------------
'   INVZ() returns the reciprocal value of a complex number
'--------------------------------------------------------------------------------
' INVZ(Z) = 1/Z
Function INVZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) =  re / ( re * re + im * im)
    Z(1) =  im / ( re * re + im * im)
    INVZ = Z()
End Function
'--------------------------------------------------------------------------------
'     LOGZ() returns the natural logarithm of a complex number
'--------------------------------------------------------------------------------
Function LOGZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) =  LOG (re / ( re * re + im * im))
    Z(1) =  im / ( re * re + im * im)
    LOGZ = Z()
End Function
'--------------------------------------------------------------------------------
'    LOG10() returns the base 10 log of x
'--------------------------------------------------------------------------------
 Function LOG10(value AS DOUBLE) AS DOUBLE
  LOG10 = (LOG (value) * LOG(10 * rqE))
 End Function
'--------------------------------------------------------------------------------
'     LOG10Z() returns the 10-th logarithm of z (base is 10)
'--------------------------------------------------------------------------------
Function LOG10Z(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) =  LOG (re / ( re * re + im * im))/ LOG (10)
    Z(1) =  im / ( re * re + im * im) / LOG (10)
    LOG10Z = Z()
End Function
'--------------------------------------------------------------------------------
'     LOGAZ() returns the a-th logarithm of z (base is a)
'--------------------------------------------------------------------------------
Function LOGAZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1) : a = Z(3)
    Z(0) =  LOG (re / ( re * re + im * im))/ LOG (a)
    Z(1) =  im / ( re * re + im * im) / LOG (a)
    LOGAZ = Z()
End Function
'--------------------------------------------------------------------------------
'    MAGZ() returns the absolute value of a complex number
'--------------------------------------------------------------------------------
Function MAGZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = SQR( re * re + im * im)   '= |Z|
    Z(1) = 0
    MAGZ = Z()
End Function
'--------------------------------------------------------------------------------
'    MULZ() returns the product of two complex numbers
'--------------------------------------------------------------------------------
Function MULZ(Z()AS DOUBLE ) AS DOUBLE
    re1 = Z(0): im1 = Z(1) : re2 = Z(2) : im2 = Z(3)
    Z(0) = re1 * re2 - im1 * im2
    Z(1) = re1 * im2 + re2 * im1
    Z(2) = 0
    Z(3) = 0
    MULZ = Z()
End Function
'--------------------------------------------------------------------------------
'    NORZ() returns the normal form of a complex value
'--------------------------------------------------------------------------------
' Z = x + iy = re + i*im   =   r*e^i*theta
Function NORZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = SQR( re * re + im * im)    ' = r = value
    Z(1) = ATAN (im / re)             ' = theta = argument
    NORZ = Z()                        'Z() = (r,theta)
End Function
'--------------------------------------------------------------------------------
'   ODD() returns "1" (=true) if a number(INTEGER) is odd
'--------------------------------------------------------------------------------
Function ODD(value AS INTEGER ) AS INTEGER
   IF FRAC( value / 2 ) <> 0 THEN
      ODD = 1
    ELSE
      ODD = 0
   END IF
End Function
'--------------------------------------------------------------------------------
'   POLZ() returns Z IN the polar coordinate system
'--------------------------------------------------------------------------------
' Transformation from    z = x + iy     to     z = r*cos((phi) + r*i*sin(phi)
Function POLZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = SQR( re * re + im * im) * COS(ATAN (im / re))
    Z(1) = SQR( re * re + im * im) * SIN(ATAN (im / re))
    POLZ = Z()
End Function
'--------------------------------------------------------------------------------
'    POWZ() returns the power n  of a complex number = (x+iy)^n = z^n
'--------------------------------------------------------------------------------
 Function POWZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1) : expo = Z(2)
     Z(0) =(SQR( re * re + im * im)) ^ expo * COS(expo * ATAN (im / re) )
     Z(1) =(SQR( re * re + im * im)) ^ expo * SIN(expo * ATAN (im / re) )
     Z(2) = 0
    POWZ = Z()
End Function
'--------------------------------------------------------------------------------
'   RAD2DEG() returns degrees instead of radians
'--------------------------------------------------------------------------------
Function RAD2DEG(value AS DOUBLE) AS DOUBLE
 RAD2DEG = value / 0.017453
End Function
'--------------------------------------------------------------------------------
'   SEC() returns the secans of x
'--------------------------------------------------------------------------------
Function SEC(value AS DOUBLE) AS DOUBLE
 SEC = 1 / COS(value)
End Function
'--------------------------------------------------------------------------------
'   SECH() returns the hyperbolic secans of x
'--------------------------------------------------------------------------------
Function SECH(value AS DOUBLE) AS DOUBLE
 SECH = (2 / (EXP(value) + EXP(value * -1)))
' SECH = 1/ COSH (value)
End Function
'--------------------------------------------------------------------------------
'   SINH() returns the hyperbolic sine of x
'--------------------------------------------------------------------------------
Function SINH(value AS DOUBLE) AS DOUBLE
 SINH = (0.5 * (EXP(value) - EXP(value * -1)))
  IF value = 0 THEN SINH = 0
End Function
'--------------------------------------------------------------------------------
'   SINZ() sine of a complex number
'--------------------------------------------------------------------------------
Function SINZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = SIN(re) * COSH(im)
    Z(1) = COS(re) * SINH(im)
    SINZ = Z()
End Function
'--------------------------------------------------------------------------------
'   SINHZ() sine of a complex number
'--------------------------------------------------------------------------------
Function SINHZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = SINH(re) * COS(im)
    Z(1) = COSH(re) * SIN(im)
    SINHZ = Z()
End Function
'--------------------------------------------------------------------------------
'   SQRZ() returns the square root of acomplex number
'--------------------------------------------------------------------------------
Function SQRZ(Z()AS DOUBLE ) AS DOUBLE
    re = Z(0): im = Z(1)
    Z(0) = ((re + SQR(re * re + im * im)) * 0.5) ^ 0.5
    Z(1) = (((re * -1) + SQR(re * re + im * im)) * 0.5) ^ 0.5
    SQRZ = Z()
End Function
'-------------------------------------------------------------------------------
'   SUBZ() returns the difference of two complex numbers
'-------------------------------------------------------------------------------
Function SUBZ(Z()AS DOUBLE ) AS DOUBLE
    re1 = Z(0): im1 = Z(1) : re2 = Z(2) : im2 = Z(3)
    Z(0) = re1 - re2
    Z(1) = im1 - im2
    Z(2) = 0
    Z(3) = 0
    SUBZ = Z()
End Function
'--------------------------------------------------------------------------------
'   TANH() returns the hyperbolic tangent of x
'--------------------------------------------------------------------------------
Function TANH(value AS DOUBLE) AS DOUBLE
    TANH = SINH(value) / COSH(value)
    IF value = 0 THEN TANH = 0
End Function
'--------------------------------------------------------------------------------
'   TANZ() returns the tangent of a complex number
'--------------------------------------------------------------------------------
Function TANZ(Z()AS DOUBLE ) AS DOUBLE
    re1 = Z(0): im1 = Z(1)
    Z(0) =  SIN(2 * re) / (COS(2 * re) + COSH(2 * im))
    Z(1) =  SINH(2 * im) / (COS(2 * re) + COSH(2 * im))
    TANZ = Z()
End Function

'=====================================================================================
'      >>>>> reserved words  <<<<<<
'=====================================================================================
'ACOSH, ACOT, ACOSEC, ACOSECH, ADDZ*, ASEC, ASECH, ATANH,CONJZ*, COSEC, COSECH, COSH,
'COSZ*, COSHZ*, COT, COTH, DEG2RAD, DIVZ*,EVEN*,EXPZ*, FAC, GCD*, INVZ*  LOG10,LOG10Z*,
'LOGAZ*, LOGZ*, MAGZ*, MULZ*, NORZ*,ODD*, POLZ*, POWZ*, RAD2DEG, RQE, RQPI, SEC, SECH,
'SINH, SINZ*,SINHZ*, SQRZ*, SUBZ*,TANH, TANZ*
'*: new functions in this version


MEMCMP

MEMCMP MEMORY Function Windows/Unix
A memory function that compares 2 memory addresses and returns 0 if the memory contents do not match, or non-zero otherwise.

Syntax: MEMCMP(ptr1, ptr2, count)
DEFINT I=10, J=10
A% = MEMCMP(VARPTR(I), VARPTR(J), SIZEOF(INTEGER))


MEMCPY

MEMCPY MEMORY Function Windows/Unix
A memory function that copies n bytes of memory from source to destination.

Syntax: MEMCPY(destination, source, n)
DEFINT I=90, J=10
'-- After MEMCPY, I should equal 10
MEMCPY(VARPTR(I), VARPTR(J), SIZEOF(INTEGER))

Details
This is similar to the Windows API function call RtlMoveMemory or CopyMemory. The keyword WITH will not work on this, you must fully write out the component name:
' In this example Form.Caption will not be recognized
WITH Form
.left =0
MEMCPY (VARPTR(myString), VARPTR(.caption), SIZEOF(.caption)
END WITH


MEMSET

MEMSET MEMORY Function Windows/Unix
A memory function that initializes a memory blocks.

Syntax: MEMSET(ptr, char, size)
DIM IntArray(1 TO 10) AS INTEGER
MEMSET(VARPTR(I(1)), 0, 10*SIZEOF(INTEGER))

Details:
Use this instead of INITARRAY


MESSAGEBOX RAPID-Q Specific Windows
Displays a simple message box with prompts. This implements Window's MessageBox API function.

Syntax: MESSAGEBOX(message, title, flags%)
IF MessageBox("Close this form?", "Close", 1) = 1 THEN
'-- Close form
END IF

Details:
Some Windows API valid flag for MessageBox() Flags
Public Const MB_OK = &H0&
Public Const MB_OKCANCEL = &H1&
Public Const MB_ABORTRETRYIGNORE = &H2&
Public Const MB_YESNOCANCEL = &H3&
Public Const MB_YESNO = &H4&
Public Const MB_RETRYCANCEL = &H5&

Public Const MB_ICONHAND = &H10&
Public Const MB_ICONQUESTION = &H20&
Public Const MB_ICONEXCLAMATION = &H30&
Public Const MB_ICONASTERISK = &H40&

Public Const MB_ICONINFORMATION = MB_ICONASTERISK
Public Const MB_ICONSTOP = MB_ICONHAND

Public Const MB_DEFBUTTON1 = &H0&
Public Const MB_DEFBUTTON2 = &H100&
Public Const MB_DEFBUTTON3 = &H200&

Public Const MB_APPLMODAL = &H0&
Public Const MB_SYSTEMMODAL = &H1000&
Public Const MB_TASKMODAL = &H2000&

Public Const MB_NOFOCUS = &H8000&
Public Const MB_SETFOREGROUND = &H10000
Public Const MB_DEFAULT_DESKTOP_ONLY = &H20000

Public Const MB_TYPEMASK = &HF&
Public Const MB_ICONMASK = &HF0&
Public Const MB_DEFMASK = &HF00&
Public Const MB_MODEMASK = &H3000&
Public Const MB_MISCMASK = &HC000&

Declare Function MessageBox Lib "user32" Alias "MessageBoxA" _
(ByVal hwnd As Long, ByVal lpText As String, ByVal lpCaption As String, ByVal wType As Long) As Long

· hWnd
Identifies the owner window of the message box to be created. If this parameter is NULL, the message box has no owner window.
· lpText
Points to a null-terminated string containing the message to be displayed.
· lpCaption
Points to a null-terminated string used for the dialog box title. If this parameter is NULL, the default title Error is used.
· uType
Specifies a set of bit flags that determine the contents and behavior of the dialog box. This parameter can be a combination of flags from the following groups of flags.

Specify one of the following flags toindicate the buttons contained in the message box:
MB_ABORTRETRYIGNORE The message box contains three push buttons: Abort, Retry, and Ignore.
MB_OK The message box contains one push button: OK. This is the default.
MB_OKCANCEL The message box contains two push buttons: OK and Cancel.
MB_RETRYCANCEL The message box contains two push buttons: Retry and Cancel.
MB_YESNO The message box contains two push buttons: Yes and No.
MB_YESNOCANCEL The message box contains three push buttons: Yes, No, and Cancel.

Specify one of the following flags to displayan icon in the message box:
MB_ICONEXCLAMATION, MB_ICONWARNING
An exclamation-point icon appears in the message box.

MB_ICONINFORMATION, MB_ICONASTERISK
An icon consisting of a lowercase letter i in a circle appears in the message box.
MB_ICONQUESTION A question-mark icon appears in the message box.
MB_ICONSTOP,
MB_ICONERROR,
MB_ICONHAND
A stop-sign icon appears in the message box.

Specify one of the following flagsto indicate the default button:
MB_DEFBUTTON1 The first button isthe default button.
MB_DEFBUTTON1 is the default unless MB_DEFBUTTON2, MB_DEFBUTTON3, or MB_DEFBUTTON4 is specified.
MB_DEFBUTTON2 The second button isthe default button.
MB_DEFBUTTON3 The third button isthe default button.
MB_DEFBUTTON4 The fourth button isthe default button.

Specify one of the following flagsto indicate the modality of the dialog box:
MB_APPLMODAL
The user must respond to the message box before continuing work in the window identified by the hWnd parameter. However, the user can move to the windows of other applications and work in those windows.
Depending on the hierarchy of windows in the application, the user may be able to move to other windows within the application. All child windows of the parent of the message box are automatically disabled, but popup windows are not.
MB_APPLMODAL is the default if neither MB_SYSTEMMODAL nor MB_TASKMODAL is specified.
MB_SYSTEMMODAL
Same as MB_APPLMODAL except that the message box has the WS_EX_TOPMOST style. Use system-modal message boxes to notify the user of serious, potentially damaging errors that require immediate attention (for example, running out of memory). This flag has no effect on the user's ability to interact with windows other than those associated with hWnd.
MB_TASKMODAL
Same as MB_APPLMODAL except that all the top-level windows belonging to the current task are disabled if the hWnd parameter is NULL. Use this flag when the calling application or library does not have a window handle available but still needs to prevent input to other windows in the current application without suspending other applications.

In addition, you can specify the following flags:
MB_DEFAULT_DESKTOP_ONLY
The desktop currently receiving input must be a default desktop; otherwise, the function fails. A default desktop is one an application runs on after the user has logged on.
MB_HELP
Adds a Help button to the message box. Choosing the Help button or pressing F1 generates a Help event.
MB_RIGHT
The text is right-justified.
MB_RTLREADING
Displays message and caption text using right-to-left reading order on Hebrew and Arabic systems.
MB_SETFOREGROUND
The message box becomes the foreground window. IWindows calls the SetForegroundWindow function for the message box.
MB_TOPMOST
The message box is created with the WS_EX_TOPMOST window style.
MB_SERVICE_NOTIFICATION
Windows NT only: The caller is a service notifying the user of an event. The function displays a message box on the current active desktop, even if there is no user logged on to the computer.If this flag is set, the hWnd parameter must be NULL. This is so the message box can appear on a desktop other than the desktop corresponding to the hWnd.For Windows NT version 4.0, the value of MB_SERVICE_NOTIFICATION has changed. See WINUSER.H for the old and new values. Windows NT 4.0 provides backward compatibility for pre-existing services by mapping the old value to the new value in the implementation of MessageBox and MessageBoxEx. This mapping is only done for executables that have a version number, as set by the linker, less than 4.0.
To build a service that uses MB_SERVICE_NOTIFICATION, and can run on both Windows NT 3.x and Windows NT 4.0, you have two choices. 1. At link-time, specify a version number less than 4.0; or2. At link-time, specify version 4.0. At run-time, use the GetVersionEx function to check the system version. Then when running on Windows NT 3.x, use MB_SERVICE_NOTIFICATION_NT3X; and on Windows NT 4.0, use MB_SERVICE_NOTIFICATION.
MB_SERVICE_NOTIFICATION_NT3XWindows NT only: This value corresponds to the value defined for MB_SERVICE_NOTIFICATION for Windows NT version 3.51.


MESSAGEDLG

MESSAGEDLG RAPID-Q Specific Windows
Displays a message box with an icon and a user defined caption. This implements Window's MessageBoxEx API function.

Syntax: MESSAGEDLG(string-expression, msgType, msgButtons, helpContext)
IF MessageDlg("Close this form?", mtWarning, mbYes OR mbNo, 0) = mrNo THEN
'-- Don't close form
END IF

Details:
msgType is used to display the type of icon that will be displayed in your message box.

0 = mtWarning 3 = mtConfirmation
1 = mtError 4 = mtCustom
2 = mtInformation

msgButtons is used to display custom dialog buttons. To display more than one message button, just OR them.

1 = mbYes       32 = mbAbort
2 = mbNo        64 = mbRetry
4 = mbOK       128 = mbIgnore
8 = mbCancel   256 = mbAll
16 = mbHelp
helpContext is ignored for now.


TIMER

microTIMER INCLUDE FILE Windows
Unlike TIMER that is slower than about 15 milliseconds, microTIMER is a fast timer that uses the Windows high performance QueryPerformanceCounter. It returns a relative timer value with a resolution of about 10 to 7 microseconds. It must be called at least once before using so it can be initialized.

Syntax: microTIMER
T! = microTIMER

Details:
Do not use microTIMER with QDXSCREEN.
          'sample code
          $INCLUDE <microTIMER.inc>
          DIM a as double
          a = microTimer   'always call at least once to initialize
          'wait for 3.5 milliseconds
          DO
          LOOP UNTILE (microTimer - a) > 0.00350

          'Sample #2 see speed of timer
          $INCLUDE <RapidQ2.inc>
          $INCLUDE <microTIMER.inc>
          dim debug as Qdebug
          for a = 1 to 25
             debug.Print microTimer
          next a


MID$

MID$ STRING Function Windows/Unix
A string function that returns a substring with n chracters starting from i of string-expression.

Syntax: MID$(string-expression, i, n)
A$ = MID$("Hello",3,2) '-- returns ll

Details:
You cannot use MID$ in this way:
MID$(A$, 1, 1) = "G"
Under QBasic, this valid statement replaces the first character from A$ with "G". To acheive the same effect under Rapid-Q, please use the REPLACE$ string function.


MKDIR

MKDIR SYSTEM Statement Windows/Unix
A statement that creates a new directory.

Syntax: MKDIR pathspec
MKDIR "abc"

mkdir "C:\BAS\RAPIDQ\help2\1234" - without last slash
or
mkdir "C:\BAS\RAPIDQ\help2\1234\" - with last slash,All variants are working

Details:
MKDIR will not rewrite a directory if one already exists, if no path is specified, the directory is created in the current working directory.


OUT

OUT I/O Statement Windows/Unix
A device I/O statement that sends a byte value to a machine I/O port.

Syntax: OUT port, value
OUT &H3C9, 128

Details:
  • Port is any word value between 0 and 65535.
  • Value is any byte value between 0 and 255.

    This keyword is stable only for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, tryutilities like PorkTalk or io.dll instead.


OUTW

OUTW I/O Statement Windows/Unix
A device I/O statement that sends a word value to a machine I/O port.

Syntax: OUTW port, value
OUTW &H378, 128

Details:
  • Port is any word value between 0 and 65535.
  • Value is any byte value between 0 and 65535.

    This keyword is stable only for Windows 95 and Win 98 only. Can give you a memory protection fault on later versions of Windows. For later windows versions, tryutilities like PorkTalk or io.dll instead.


PLAYWAV

PLAYWAV RAPID-Q Specific Windows
Plays a .WAV file or a .WAV resource.

Syntax: PLAYWAV wavfilename|wavresource, sndOptions
$RESOURCE Welcome_WAV AS "welcome.wav"
PLAYWAV "welcome.wav", SND_ASYNC OR SND_LOOP
PLAYWAV Welcome_WAV, SND_ASYNC OR SND_LOOP

Details:
sndOptions determine how the wav file is played back.
0 = SND_SYNC     '-- waits for wav to finish
1 = SND_ASYNC    '-- background play
3 = SND_LOOP     '-- Loop wav once finished playing
You can combine SYNC or ASYNC with LOOP by OR'ing them. If your WAV file is not finished playing when you close your application, you will receive an access violation. You can stop the .WAV by passing an empty string as a filename.


POINTERS in Rapid-Q
Documentation by John Kelly

POINTERS

What is a pointer?
When you declare a variable, its must have a memory location to store it's value. A pointer is simply a variable that "points" to a memory location. That is, a pointer knows "where it is" not the value. For example, if you do DIM a AS INTEGER, then what do you think happens? The program must allocate a 4 byte location in memory to store the values you assign to variable a. There will be a pointer for variable a and it will hold the address of the variable. For example:
DIM a AS INTEGER
DIM lpVar AS LONG  ' the lp prefix helps you remember it is a LONG POINTER
a = 5
lpVar = VARPTR(a)

Now lpVar holds a large number that is the ADDRESS in memory of the variable. When passing variables to a DLL, SUB, FUNCTION, etc. the program normally figures out whether you gave it a Pointer to a variable, or the value of the variable.
Why are pointers important?
When you make a call to a SUB, FUNCTION, or DLL, you may want it to change the contents of the variable. Also, it is faster and easier to send the address if you want the SUB to have a large chunk of data. That way the SUB know where the large chunk of data is located. That is easier than copying all the data to some location in memory (i.e., the stack) and then copy it back after the DLL is done.

When you use a UDT in a call to a SUB, FUNCTION, or DLL RapidQ automatically passes the address of the UDT for you, so you don't need to find the pointer for a UDT. If you need the pointer for some reason, VARPTR won't work. Use RapidQ2.INC and use UDTPTR instead.

Often, if you are using a DLL written in another language (preferably C), that DLL might require you send pointers for some variables and values for others. You can pass a pointer two ways:

If you know the type of variable that is needed you can just send the usual BYREF method
DECLARE SUB MyFunc(BYREF Data AS DOUBLE)    'send the pointer to an 8-bit DOUBLE
DIM MyVariable As Double
MyVariable = 1.00323
MyFunc(MyVariable)

Alternatively, you can just send the value of the pointer
DECLARE SUB MyFunc(BYVAL lpData AS LONG)    'send the value of the pointer
DIM MyVariable As Double
MyVariable = 1.00323
lpVar = VarPtr(myVariable)
MyFunc(lpVar)

IF you need the address of members in the UDT, then define your UDT as EXTENDS QOBJECT! Here is an example:

type NewT extends QOBJECT
  a as integer
  b as long
  c as string * 24
end type

dim NewObj as NewT
NewObj.a = 2   'give it a value if you want
Showmessage STR$(VARPTR(NewObj.a)) 'now you get the address
'but look what happens with the string:
Showmessage STR$(VARPTR(NewObj.c)) 'now you a very different address
ShowMessage STR$(UDTPTR(NewObj))   'note UDTPTR only works on basic UDT

PORTING C/C++ code to RapidQ
When you try to port code from C/C++ or Visual basic you are going to run into some limitations in RapidQ. Some can be avoided with re-coding, and others can't be fixed.
Problem: DLL requires a complex structure but you can't nest types within a type
TYPE SubType
  x as integer
  y as integer
  zz(1 to 3) as single  'RapidQ only allocates four bytes here for a pointer
  r as RECT             'this won't work, compiles but will crash code
END TYPE
DIM MySubType as SubType

Problem: Memory may not be "packed" together in a UDT defined by STRUCT or TYPE
Fix: Use QmemoryStream to get the pointer
TYPE MyType
  a as integer
  b as single
  c as byte
  d(5) as integer    'only four bytes allocated
  z as SubType       'this compiles, and adds sizeof(subtype)
END TYPE

DIM MyUDT AS MyType
DIM Mem AS QMemoryStream
Mem.WriteUDT(MyUDT)

'Again, there will be limits to getting pointers
ShowMessage str$(Mem.Pointer) 'works
ShowMessage str$(sizeof(MyUDT)) 'works
'if subType is added then the UDT is bigger by sizeof(subType)
ShowMessage str$(sizeof(MySubType)) 'works
MyUDT.z.y = 8 'won't work Compiler doesn't recognize nested type
MyUDT.z.zz(1) = 2.23451 'doesn't work!!
showmessage str$(@MyUDT.c) 'works to get the value of the variable
showmessage str$(varptr(MyUDT.a)) 'doesn't work!!

'work around by adding offsets
ShowMessage str$(Mem.Pointer + Sizeof(XX)+ ... +SizeOf(SubType))

Another work around is to add the individual part of SubType --
'*** these 3 lines are added instead of z...
x as integer
y as integer
zz(1 to 3) as single
but they can't have the same name. This of course is a lot of work.

Let's take another look at why pointers are so important. I wanted to develop Direct 3D on rapidQ but I am sure it is impossible. After you create a Direct X, Direct 3D and other COM interfaces, it passes the address of a structure in memory. You then
access the SUB/Function by using a pointer to a member in a STRUCT

Here is some code that shows you this is not possible without A LOT
of work in translation. Also, C/C++ uses pointers in lots of ways.

' attempt at making com object compile with RapidQ
$TYPECHECK ON 'this really doesn't matter
DECLARE FUNCTION DumbFunc(x AS INTEGER) AS INTEGER
FUNCTION DumbFunc(x AS INTEGER) AS INTEGER
ShowMessage str$(x)
DumbFunc = 1
END FUNCTION
DIM DummyPtr AS LONG

STRUCT COMobjectUDT
Ptr1 AS LONG
Ptr2 AS LONG
END STRUCT
DIM ComObject AS COMobjectUDT 'sizeof(ComObject) = 8

ComObject.Ptr1 = 1 'set it to something
BIND ComObject.Ptr1 TO DumbFunc 'won't work 'undeclared...'
CALLFUNC(ComObject.Ptr1, 2) 'can't get here, WON'T WORK

BIND DummyPtr TO DumbFunc 'works
CALLFUNC(DummyPtr, 2) 'of course this works!

DIM Mem AS QMemoryStream
Mem.WriteUDT(ComObject)
BIND Mem.Pointer TO DumbFunc 'wont work
MEMCPY(Mem.Pointer, VARPTR(DummyPtr), SIZEOF(LONG)) 'works
CALLFUNC(Mem.Pointer, 2) 'won't work

'next line won't work -- access violation
MEMCPY(ComObject.Ptr1, VARPTR(DummyPtr), SIZEOF(LONG))
ComObject.Ptr1 = VARPTR(DummyPtr) 'works
CALLFUNC(ComObject.Ptr1, 2) 'error NOT bound yet

''ALSO'*** can't get pointers within QOBJECTS
DIM DxScreen AS QDXSCREEN
ShowMessage str$(sizeof(DxScreen)) 'can't interpret

DIM MyBmp AS QBITMAP
MyBmp.Width = 100
MyBmp.Height = 100
ShowMessage str$(sizeof(MyBmp)) 'won't work
DummyPtr = VARPTR(MyBmp.Pixel(0,0)) 'won't work


POSTMESSAGE

POSTMESSAGE RAPID-Q Specific Windows
A WinAPI call to PostMessage, does not block.

Syntax: POSTMESSAGE hWnd, uMsg, wParam, lParam
POSTMESSAGE Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0

Details:
PostMessage is a WinAPI call so instead of filling this entire page with information you can look up this function in your WinAPI manual/help file.


RESULT

PRIVATE Custom Component Keyword Windows/Unix
Use inside a TYPE ... EXTENDS {QOBJECT} ... END TYPE block

When you write
PRIVATE:
{all methods and properties only accessed within the TYPE...END TYPE block }

PUBLIC:
{all methods and properties now can be accessed outside TYPE...END TYPE block }

for details see chapter10.html, creating custom components

The reason you have PUBLIC and PRIVATE members is mainly for your end-user's sake. Obviously you'll know what members shouldn't be used outside its scope, but by defining PRIVATE members you tell your end-users not to touch these in your program since they are used "internally."


PROPERTY SET

PROPERTY SET Custom Component Keyword Windows/Unix
Use inside a TYPE ... EXTENDS {QOBJECT} ... END TYPE block
A property set is just a collection of properties, with one major difference, you can do special processing when a user sets the property. We will start with a somewhat useless example
    TYPE TForm EXTENDS QFORM
        Focus AS LONG PROPERTY SET Set_Focus

        PROPERTY SET Set_Focus (Handle AS LONG)
            WITH TForm
                .Focus = Handle
                IF .Focus THEN
                    SetFocus(Handle)
                END IF
            END WITH
        END PROPERTY
    END TYPE

    CREATE Form AS TForm
        CREATE Edit AS QEDIT
        END CREATE
        Focus = Edit.Handle
    END CREATE

for details see chapter10.html, creating custom components


RESULT

PUBLIC Custom Component Keyword Windows/Unix
Use inside a TYPE ... EXTENDS {QOBJECT} ... END TYPE block

When you write
PRIVATE:
{all methods and properties only accessed within the TYPE...END TYPE block }

PUBLIC:
{all methods and properties now can be accessed outside TYPE...END TYPE block }

for details see chapter10.html, creating custom components

The reason you have PUBLIC and PRIVATE members is mainly for your end-user's sake. Obviously you'll know what members shouldn't be used outside its scope, but by defining PRIVATE members you tell your end-users not to touch these in your program since they are used "internally."


QAbout

Documentation component by D.Glodt (c)2002-2003 Appendix A: QAbout

QAbout Component

INCLUDED IN RAPIDQ2.INC
QAbout is a dialog box "About" showing the name,version,author of an application,email link and web link. See limitations.

QAbout Properties
Field | Type | R/W | Défault
Caption | STRING | R/W |
 | Title of dialog box |  |
Name | STRING | R/W |
 | Application name |  |
AppVersion | STRING | R/W |
 | Version and révision of application |  |
Image | QIMAGE | R/W |
 | Icone or image of application |  |
Text | STRING | R/W |
 | Text of application for copyright and other |  |
Email | STRING | R/W |
 | Link e-mail adress , example:"dominique.glodt@libertysurf.fr" |  |
Web | STRING | R/W |
 | Link web page ,example:"www.allapi.net" |  |
AppFont | QFONT | R/W |
TextFont | QFONT | R/W |
EmailFont | QFONT | R/W |
WebFont | QFONT | R/W |

QAbout Methods
Method | Type | Description | Params
Show | SUB | Show the dialog box |

QAbout Events
Event | Type | Occurs when... | Params

QAbout Examples
$TYPECHECK ON
$include "RAPIDQ2.INC"
 $resource ico as "icone.ico"
declare sub routine1
dim about as QAbout
create form as QFORM
  width=300
  height=200
  center
  onclick=routine1
end create
form.showmodal
sub routine1
  about.AppFont.color=&h007700
  about.AppFont.bold=1
  about.Appname="Platforme"
  about.Appversion="1.02"
  about.caption="A propos de "+about.Appname
  about.text="Auteur:Glodt dominique"+chr$(13)+"Copyright(c)software 2000-2002  "
  about.image.icohandle=ico
  about.email="dominique.glodt@libertysurf.fr"
  about.web="www.allapi.net"
  about.show
end sub


QAVI

Documentation by JohnK Appendix A: QVIDEO

QAVI Component

This is a custom component that lets you read and create AVI movie files. AVI stands for audio-video interlace format. Currently it only supports creating 24 bit graphics. If you get a bitmap from an 8-bit video file then the palette will need to be read from the file. There is no support for audio yet. See limitations.
QAVI Properties
Field | Type | R/W | Default
BPP | LONG | R/W | 24
 | Color depth in Bits per Pixel, only 24-bit color is supported for creating AVI files
BytesWritten | LONG | R |
 | amount of memory written in each frame (equals bitmap size if completed) |  |
Error | STRING | R |
 | If an error occurs, this will provide a user friendly message..
FileType | STRING | R |
 | string showing AVI file type header
FirstFrame | LONG | R/W | 0
 | Frame number of first video frame, usually is 0 |  |
FPS | LONG | R/W |
 | Frames per second. This is the play-back speed. For MPEG conversion, FPS must be either 10, 12, 15, 24, 25, or 30
FramesWritten | LONG | R |
 | when creating an AVI file this keeps track of total output in bytes |  |
Left | LONG | RW | 0
Top | LONG | RW | 0
Right | LONG | RW |
Bottom | LONG 'sets the location of the video in the parent frame. It defaults to QBITMAP for writing. | RW |
FramesWritten | SHORT | R |
 | Image width of vidéo file |  |
Height | LONG | R |
 | Image height of video images, all images should be the same size. |  |
NumFrames | LONG | R/W |
 | Number of video frames
Quality | LONG | R/W | 10000
 | image compression quality from 0 (lowest) to 10000 (highest), only 10000 is currently supported for creating AVI files. |  |
SampleSize | LONG | R |
 | Frame size in bytes |  |
ShowDialog | INTEGER | R/W |
 | show windows compression, options dialog box |  |
ShowError | INTEGER | RW | false
 | If True error messages will appear with a dialog box automatically |  |

QAVI Methods
Method | Type | Description | Params
CreateAVIFile | FUNCTION (FileName$, Width%, Height%, FramesPerSecond%) | Create an AVI file to write | 4
Example:
DIM Vid AS QAVI
Vid.CreateAVIFile("Custom.AVI",myBMP.Width,myBMP.Height, 15)
If sucessful, then the function returns TRUE,
and QAVI properties .Width, .Height, .FPS will be reset by the passed parameters
BMPtoAVIFile | FUNCTION (TheBMP AS QBITMAP) | Write bitmap to file, 24 bit only | 1
Serially stores the bitmap in the AVI file. All bitmaps must be the same size. Returns TRUE on success
GetAVIFileInfo | SUB (FileName$) | Close AVI file after writing | 0
Read the AVI file and set Properties. Returns TRUE on success
CloseAVIFile | FUNCTION | Close AVI file after writing | 0
Closes all AVI handles and releases the AVI library memory. Returns TRUE on success

QAVI Events
Event | Type | Occurs when... | Params
none |  |  |

QAVI Examples

'**************************************************************************
'  Example 1  Read the format of an AVI file
'**************************************************************************
$INCLUDE <rapidq.inc>
$INCLUDE <QAVI.inc>

DIM myAVI AS QAVI
    myAVI.ShowError = True
    myAVI.GetAVIFileInfo("Test.avi")
    myAVI.CloseAVIFile	'be sure to do this when done

 Showmessage "the file is " + _
         str$(MyAVI.Height) + _
 " x " + str$(MyAVI.Width)  + _
 " , fps = " + str$(MyAVI.fps) + _
 " ,  File type of: " + myAVI.FileType
Application.Terminate

'**************************************************************************
'  Example 2  Draw your own AVI file
'**************************************************************************
$INCLUDE <rapidq.inc>
$INCLUDE <QAVI.inc>

DECLARE SUB PaintForm
DIM  i as integer

CREATE TheBMP AS QBITMAP
    Width = 160         'must be on a DWORD (32 bit) boundary
    Height =120
    PixelFormat = pf24bit
END CREATE

CREATE Form AS QFORM
    ClientWidth = TheBMP.Width
    ClientHeight = TheBMP.Height
    OnPaint=PaintForm
END CREATE

CREATE myAVI AS QAVI
    ShowError = True
    NumFrames = 10
END CREATE

' create a new one at 10 frames per second
'properties .Width, .height, .fps will be reset after this function
myAVI.CreateAVIFile("Test.avi", TheBMP.Width, TheBMP.Height, 24, 10)
Form.Show

for i=1 to myAVI.NumFrames
    WITH TheBMP
      .FillRect(0,0, .width, .height, 0)
      .Line(0,0, .width*Rnd, .height*Rnd, &Hff00)
    END WITH
    myAVI.BMPtoAVIFile(TheBMP)
   Form.Repaint
next i
myAVI.CloseAVIFile
Application.Terminate

SUB PaintForm
    Form.Draw(0,0, TheBMP.BMP)
END SUB


QBITMAPex

Rapid-Q Documentation by William Yu (c)1999, appended by D.Glodt (c)2000-2004, John Kelly Appendix A: QBITMAPex

QBITMAPEX Component

INCLUDED IN RAPIDQ2.INC
QBitmapEx is just like a QBITMAP except it supports other goodies like Clipboard paste and copy, alphablending, loading of other graphic formats (JPG, GIF, TGA, etc.) and saving to JPG format if the free NviewLib.DLL is present in the system directory or the directory of application.
See limitations.

QBitmapEx Properties
Field | Type | R/W | Default | Support

PenSize | Long | RW | 1 | W
 | Pen size for draw line,rectangle and circle |  |  |
PenStyle | Long | RW | PS_SOLID_BMP | W
 | Pen style , the others values are: PS_SOLID_BMP=0 PS_DASH_BMP=1 PS_DOT_BMP=2 PS_DASHDOT_BMP=3 PS_DASHDOTDOT_BMP=4 PS_NULL_BMP=5 PS_INSIDEFRAME_BMP=6 |  |  |

QBitmapEx Methods
Method | Type | Description | Params | Support

AlphaBlend | SUB(Dest AS QBITMAP, Source AS QBITMAP, PercentBlend AS SINGLE) | Blend together two bitmaps (Win98 or higher) | 3
 | PercentBlend is from 0.0 to 1.0. If PercentBlend = -1 Then alphaBlending is determined by the Alpha values in Source Bitmap and Pixelformat must be pf32bit (32 bpp). The output Bitmap will be replaced by the new alpha-blended bitmap. If the sizes of the two bitmaps are not equal the smaller will be stretched to equal the larger one
CopyToClipboard | SUB | Copy image to clipboard | 0
PasteFromClipboard | SUB(x%,y%) | Paste the image of clipboard | 2
GetWidthClipboard | FUNCTION as INTEGER | Return the image width of clipboard | 0
GetHeightClipboard | FUNCTION as INTEGER | Return the image height of clipboard | 0
CanPaste | FUNCTON as BOOLEAN | Return true if image présent in the clipboard | 0
CircleFilled | SUB(x1%,y1%,x2%,y2%,c%,Fill%) | Draw a circle filled | 6
DrawIco | SUB(left%,top%,width%,height%,handle%) | Draw an icon | 3
 | If the width and height parameters are 0,the icon will show with his dimensions by défault. |  |
FillSurface | SUB(x%,y%,c%) | Fill the surface pointed by the color of pixel x,y | 3
Flip | SUB(x%,y%,width%,height%) | Make a miror y | 4
InvertColor | SUB(x%,y%,width%,height%) | Invert color | 4
Mirror | SUB(x%,y%,width%,height%) | Make a miror x | 4
Pointer | LONG | R |
 | Returns the memory location of the pixel data: myBMP.loadFromFile "\RapidQ\Test.bmp" Showmessage STR$(myBMP.Pointer)
RectangleFilled | SUB(x1%,y1%,x2%,y2%,c%,Fill%) | Draw a rectangle filled | 6
RoundRectFilled | SUB(x1%,y1%,x2%,y2%,x3%,y3%,c%,Fill%) | Draw a round rectangle filled | 8
LoadOtherImage | SUB(FileName$,Progress&,Language$) | Auto load graphics files using either jpeg.dll or Nviewlib format | 3
 | Automatically loads a file of type *.ICO; *.JPG; *.GIF; *.DIB; *.TGA;*.PCX and others. Progress displays a progression bar during loading of file.(true or false) Language corresponds to the language supported by DLL (i.e. "Japanese") (Check the internal variable: NViewLibPresent = 1 then Nviewlib.DLL is available NViewLibPresent = 2 then jpeg.DLL is available.
SaveAsJpg | SUB(FileName$,Quality&) | Save image to jpg format | 2
"Quality" parameter corresponds to the storage quality.
1 = lowest, 99 = highest
QBitmapEx Example

$TYPECHECK ON
$INCLUDE "RapidQ2.inc"
DECLARE SUB LoadImage

IF NViewLibPresent = 0 THEN
  ShowMessage "NviewLib.DLL not found"
  Application.Terminate
END IF
DIM TmpBMP AS QBITMAPex
DIM fDialog as QOPENDIALOG

create form as QFORM
  Caption = "click me"
  width = Screen.Width
  height = Screen.Height - 28
  OnClick = LoadImage

 create canvas as QCanvas
  Top = 24
  width = Form.ClientWidth
  height = Form.ClientHeight - 45
  OnClick = LoadImage
 end create
end create
Form.ShowModal

SUB LoadImage
  fDialog.Caption = "Open files"
'if jpeg.dll is present then all jpeg files will be handled by jpeg.dll
'this dll doesn't have loading errors on some jpeg images
  fDialog.filter =  "Picture files|*.BMP;*.ICO;*.JPG;*.GIF;*.DIB;*.RLE;*.TGA;*.PCX"
  fDialog.FileName= ""
  IF fDialog.Execute THEN
    TmpBMP.LoadOtherImage(fDialog.FileName, 0,"")
    Canvas.Draw(0,0, TmpBMP.BMP)
  END IF
END SUB

QBitmapEx Example 2

$INCLUDE "rapidQ2.inc"
$TYPECHECK ON
DECLARE SUB LoadImages
DIM TmpBMP AS QBITMAPex
DIM Src1 AS QBITMAPex 'source 1 for bitmap
DIM Src2 AS QBITMAPex 'source 2 for bmp blending
DIM fDialog as QFILEDIALOG

CREATE form as QFORM
  width = Screen.Width
  height = Screen.Height - 28
  OnClick = LoadImages

create canvas as QCanvas
  Top = 24
  width = Form.ClientWidth
  height = Form.ClientHeight - 45
  OnClick = LoadImages
end create
end create
Form.ShowModal

SUB LoadImages
  fDialog.Caption = "Open two image files"
  IF NviewLibPresent THEN
      fDialog.filter = "Picture files|*.BMP;*.ICO;*.JPG;*.GIF;*.TGA;*.PCX"
  ELSE
      fDialog.filter = "*.bmp (bitmap files)|*.BMP"
  END IF
  fDialog.FileName= ""
  fDialog.MultiSelect = True
  IF fDialog.Execute THEN

  IF NviewLibPresent THEN
    Src1.LoadOtherImage(fDialog.Files(0) + fDialog.Files(1), 0, "")
    Src2.LoadOtherImage(fDialog.Files(0) + fDialog.Files(2), 0, "")
  ELSE		'just bitmaps
    Src1.LoadFromFile(fDialog.Files(0) + fDialog.Files(1))
    Src2.LoadFromFile(fDialog.Files(0) + fDialog.Files(2))
  END IF
    TmpBMP.AlphaBlend(Src1, Src2, 0.5) 'mix 50-50%
'	TmpBMP.TransparentMode = tmAlpha
'    TmpBMP.AlphaBlend(Src1, Src2, -0.5) 'use alpha channel
    Canvas.Draw(0,0, TmpBMP.BMP)
  END IF
END SUB


QCanvasEx

Documentation component by D.Glodt (c)2000-2002 Appendix A: QCanvasEx

QCanvasEx Component

INCLUDED IN RAPIDQ2.INC
QCanvasEx is just like Qcanvas but with added options for drawing, icon, and clipboard options. See limitations.
(Note Constants were made to be compatible with Windows CONST).

QCanvasEx Properties

Field | Type | R/W | Default
MixMode | Long | RW | R2_COPYPEN
 | Set the foreground mix mode The differents values are: R2_BLACK=1 R2_NOTMERGEPEN=2 R2_MASKNOTPEN=3 R2_NOTCOPYPEN=4 R2_MASKPENNOT=5 R2_NOT=6 R2_XORPEN=7 R2_NOTMASKPEN=8 R2_MASKPEN=9 R2_NOTXORPEN=10 R2_NOP=11 R2_MERGENOTPEN=12 R2_COPYPEN=13 R2_MERGEPENNOT=14 R2_MERGEPEN=15 R2_WHITE=16 |  |
PenSize | Long | RW | 1
 | Pen size for draw line,rectangle and circle | RW |
PenStyle | Long | RW | PS_SOLID
 | Pen style , the others values are: PS_SOLID=0 PS_DASH=1 PS_DOT=2 PS_DASHDOT=3 PS_DASHDOTDOT=4 PS_NULL=5 PS_INSIDEFRAME=6 |  |

QCanvasEx Methods
Method | Type | Description | Params
DrawIco | SUB(left%,top%,width%,height%,handle%) | Draw an icon | 3
 | If parameters width and height are 0, the icon will show with default dimensions
CopyToClipboard | SUB(rect as QRECT) | Copy the image in the clipboard | 1
PasteFromClipboard | SUB(x%,y%) | Paste the image from clipboard | 2
GetWidthClipboard | FUNCTION as INTEGER | Return the image wiith from clipboard | 0
GetHeightClipboard | FUNCTION as INTEGER | Return the image height from clipboard | 0
CanPaste | FUNCTON as BOOLEAN | Return true if image présent in the clipboard | 0
Circle | SUB(x1%,y1%,x2%,y2%,c%) | Draw a circle | 5
CircleFilled | SUB(x1%,y1%,x2%,y2%,c%,Fill%) | Draw a circle filled | 6
Rectangle | SUB(x1%,y1%,x2%,y2%,c%) | Draw a rectangle | 5
RectangleFilled | SUB(x1%,y1%,x2%,y2%,c%,Fill%) | Draw a rectangle filled | 6
RoundRect | SUB(x1%,y1%,x2%,y2%,x3%,y3%,c%) | Draw a round rectangle | 7
RoundRectFilled | SUB(x1%,y1%,x2%,y2%,x3%,y3%,c%,Fill%) | Draw a round rectangle filled | 8
Line | SUB(x1%,y1%,x2%,y2%,c%) | Draw a line | 5
FillSurface | SUB(x%,y%,c%) | Fill the surface pointed by the color of pixel x,y | 3
TextOut | SUB(x%,y%,s$,fc%,bc%) | Draw text | 5
InvertColor | SUB(x%,y%,width%,height%) | Invert color | 4
Mirror | SUB(x%,y%,width%,height%) | Make a miror x | 4
Flip | SUB(x%,y%,width%,height%) | Make a miror y | 4

QCanvasEx Events
Event | Type | Occurs when... | Params

QCanvasEx Example 1

'original code by D.Glodt
 $typecheck on
 $INCLUDE "Rapidq2.inc"
 declare sub OuvrirClick
 declare sub FermerClick
 declare sub QuitterClick
 declare sub Copier
 declare sub Coller
 declare sub Present
 const title="Viewer picture"
 dim bitmap as QBITMAP
 dim source as QRECT
 CREATE Form AS QFORM
   Caption =title
   Width = 600
   Height = 600
   Center
   CREATE Menu AS QMAINMENU
     CREATE item1 AS QMENUITEM
       Caption="&Fichier"
       CREATE item2 AS QMENUITEM
         Caption="&Ouvrir"
         OnClick=OuvrirClick
       END CREATE
       CREATE item4 AS QMENUITEM
         Caption="&Fermer"
         OnClick=FermerClick
       END CREATE
       CREATE item5 AS QMENUITEM
         Caption="-"
       END CREATE
       CREATE item6 AS QMENUITEM
         Caption="&Quitter"
         OnClick=QuitterClick
       END CREATE
     END CREATE
     CREATE item11 as QMENUITEM
       Caption="&Edition"
       OnClick=Present
       CREATE item12 as QMENUITEM
         Caption="&Copier"
         OnClick=Copier
       END CREATE
       CREATE item13 as QMENUITEM
         Caption="&Coller"
         OnClick=Coller
         Enabled=false
        END CREATE
      END CREATE
    END CREATE
    CREATE ScrollBox1 AS QSCROLLBOX
      AutoScroll = 1
      Align=5
      Color = &HFFFFFF
      CREATE image AS QCanvasEx
        width=1000
        height=1000
      END CREATE
    END CREATE
  END CREATE
  bitmap.PixelFormat=6
  Form.ShowModal

  sub OuvrirClick
    dim file as QOPENDIALOG

    file.Filter="Fichiers bitmap(*.bmp)|*.bmp"
    file.InitialDir=CurDir$
    if file.Execute then
      bitmap.Bmp=file.FileName
      image.draw(0,0,bitmap.bmp)
      Form.Caption=title+"-"+file.FileName
    end if
  end sub

  sub FermerClick
     image.repaint
     Form.Caption=title
  end sub

  sub QuitterClick
    Form.Close
  end sub

  sub Copier
    source.left=0
    source.top=0
    source.right=bitmap.width
    source.bottom=bitmap.height
    image.copyToClipboard(source)
  end sub

  sub coller
    image.pasteFromClipboard(20,20)
    form.caption=str$(image.GetWidthClipboard)+"*"+str$(image.GetHeightClipboard)
  end sub

  Sub Present
    if image.canpaste then
      item13.enabled=true
    else
      item13.enabled=false
    end if
  End Sub

QCanvasEx Example 2
'original code by D.Glodt
$typecheck on
$INCLUDE <Rapidq2.inc>

declare sub selectdrawing(sender as qmenuitem)
declare sub selectSize(sender as qmenuitem)
declare sub move(x as integer,y as integer)
declare sub start(bt as integer,x as integer,y as integer)
declare sub stop
declare sub ResetMenuDrawing
declare sub ResetMenuSize
declare sub SelectPenColor
declare sub SelectBackColor
declare sub New
declare sub Quit

dim TypeDraw as integer
TypeDraw=1
dim flag as integer
dim orx as integer
dim ory as integer
dim ox as integer
dim oy as integer
dim pencolor as long
dim backcolor as long
dim Dial as QColorDialog

CREATE Form AS QFORM
'  Caption="Paint"
  Width = 690
  Height=503
  Center
  CREATE MainMenu AS QMAINMENU
    CREATE MenuFile AS QMENUITEM
      Caption="&File"
      CREATE MenuNew AS QMENUITEM
        Caption="&New"
        OnClick=New
      END CREATE
      CREATE separator AS QMENUITEM
        Caption="-"
      END CREATE
      CREATE MenuExit AS QMENUITEM
        Caption="&Exit"
        OnClick=Quit
      END CREATE
    END CREATE
    CREATE MenuTool AS QMENUITEM
      Caption="&Tools"
      CREATE MenuPenColor AS QMENUITEM
        Caption="&Pen color"
        OnClick=SelectPenColor
      END CREATE
      CREATE MenuPenSize AS QMENUITEM
        Caption="&Pen size"
        CREATE MenuSize1 AS QMENUITEM
          Caption="&Size 1"
          Tag=1
          Checked=true
          OnClick=SelectSize
        END CREATE
        CREATE MenuSize2 AS QMENUITEM
          Caption="&Size 2"
          Tag=2
          OnClick=SelectSize
        END CREATE
        CREATE MenuSize4 AS QMENUITEM
          Caption="&Size 4"
          Tag=3
          OnClick=SelectSize
        END CREATE
        CREATE MenuSize8 AS QMENUITEM
          Caption="&Size 8"
          Tag=4
          OnClick=SelectSize
        END CREATE
      END CREATE
      CREATE MenuBackcolor AS QMENUITEM
        Caption="&Back color"
        OnClick=SelectBackColor
      END CREATE
    END CREATE
    CREATE MenuDrawing AS QMENUITEM
      caption="&Drawing"
      CREATE MenuDraw AS QMENUITEM
        Caption="&Draw"
        tag=1
        Checked=true
        OnClick=SelectDrawing
      END CREATE
      CREATE MenuLine AS QMENUITEM
        Caption="&Line"
        tag=2
        OnClick=SelectDrawing
      END CREATE
      CREATE MenuRect AS QMENUITEM
        Caption="&Rectangle"
        tag=3
        OnClick=SelectDrawing
      END CREATE
      CREATE MenuRectFilled AS QMENUITEM
        Caption="&Rectangle filled"
        tag=4
        OnClick=SelectDrawing
      END CREATE
      CREATE MenuCircle AS QMENUITEM
        Caption="&Circle"
        tag=5
        OnClick=SelectDrawing
      END CREATE
      CREATE MenuCircleFilled AS QMENUITEM
        Caption="&Circle filled"
        tag=6
        OnClick=SelectDrawing
      END CREATE
      CREATE MenuFill AS QMENUITEM
        Caption="&Fill"
        tag=7
        OnClick=SelectDrawing
      END CREATE
    END CREATE
  END CREATE
  CREATE ScrollBox1 AS QSCROLLBOX
    Align=alClient
    color=&hffffff
    CREATE image AS QCanvasEx
      Align=alClient
      OnMouseMove=move
      OnMouseDown=start
      OnMouseUp=stop
    END CREATE
  END CREATE
END CREATE

Form.ShowModal

sub New
  image.repaint
end sub

sub Quit
  Form.close
  Application.terminate
end sub

sub SelectDrawing(sender as qmenuitem)
  TypeDraw=sender.tag
  ResetMenuDrawing
  sender.checked=true
end sub

sub SelectSize(sender as qmenuitem)
  Select case sender.tag
  case 1
    image.pensize=1
  case 2
    image.pensize=2
  case 3
    image.pensize=4
  case 4
    image.pensize=8
  end select
  ResetMenuSize
  sender.checked=true
end sub

sub Start(bt as integer,x as integer,y as integer)
  flag=true
  orx=x
  ory=y
  ox=x
  oy=y
  select case typeDraw
  case 1
    image.line(x,y,x,y,PenColor)
  case 2
    image.mixmode=R2_NOTXORPEN
    image.line(x,y,x,y,PenColor)
  case 3
    image.mixmode=R2_NOTXORPEN
    image.rectangle(x,y,x,y,PenColor)
  case 4
    image.mixmode=R2_NOTXORPEN
    image.rectangleFilled(x,y,x,y,PenColor,backcolor)
  case 5
    image.mixmode=R2_NOTXORPEN
    image.circle(x,y,x,y,PenColor)
  case 6
    image.mixmode=R2_NOTXORPEN
    image.circleFilled(x,y,x,y,PenColor,backcolor)
  case 7
    image.fillSurface(x,y,pencolor)
  end select
end sub

sub Move(x as integer,y as integer)
  if flag then
    select case typeDraw
    case 1
      image.line(ox,oy,x,y,PenColor)
    case 2
      image.line(orx,ory,ox,oy,PenColor)
      image.line(orx,ory,x,y,PenColor)
    case 3
      image.rectangle(orx,ory,ox,oy,PenColor)
      image.rectangle(orx,ory,x,y,PenColor)
    case 4
      image.rectangleFilled(orx,ory,ox,oy,PenColor,backcolor)
      image.rectangleFilled(orx,ory,x,y,PenColor,backcolor)
    case 5
      image.circle(orx,ory,ox,oy,PenColor)
      image.circle(orx,ory,x,y,PenColor)
    case 6
      image.circleFilled(orx,ory,ox,oy,PenColor,backcolor)
      image.circleFilled(orx,ory,x,y,PenColor,backcolor)
    end select
    ox=x
    oy=y
  end if
end sub

sub Stop
 if  flag then
   image.mixmode=R2_COPYPEN
   flag=0
 end if
 select case typeDraw
 case 2
   image.line(orx,ory,ox,oy,PenColor)
 case 3
   image.rectangle(orx,ory,ox,oy,PenColor)
 case 4
   image.rectangleFilled(orx,ory,ox,oy,PenColor,backcolor)
 case 5
   image.circle(orx,ory,ox,oy,PenColor)
 case 6
   image.circleFilled(orx,ory,ox,oy,PenColor,backcolor)
 end select
end sub

sub ResetMenuDrawing
  MenuDraw.checked=false
  MenuLine.checked=false
  MenuRect.checked=false
  MenuRectFilled.checked=false
  MenuCircle.checked=false
  MenuCircleFilled.checked=false
  MenuFill.checked=false
end sub

sub ResetMenuSize
  MenuSize1.checked=false
  MenuSize2.checked=false
  MenuSize4.checked=false
  MenuSize8.checked=false
end sub

sub SelectPenColor
  Dial.caption="Select pen color"
  if Dial.Execute then
    PenColor=Dial.Color
  end if
end sub

sub SelectBackColor
  Dial.caption="Select backcolor"
  if Dial.Execute then
    BackColor=Dial.Color
  end if
end sub


QColorDialog

Documentation component by D.Glodt (c) 2000-2001, & John Kelly QColorDialog

QColorDialog Component

INCLUDED IN RAPIDQ2.INC
QColorDialog is a dialogue box used to select a color. See limitations.
WARNING: don't use Caption, top, or left properties with another component that uses a WndProc method. This is because CODEPTR only returns one WndProc address per application.

QColorDialog Properties
Field | Type | R/W | Default
Caption | STRING | RW |
Colors | Array of LONG | RW |
 | Define the value of 16 colors.
Color | LONG | R |
 | Value color selected.
Left | LONG | RW | center
Top | LONG | RW | center
 | Value color selected.
Style | INTEGER | RW | cdNormal
 | Style dialog box, can be cdFullOpen or cdNoFullOpen

QColorDialog Methods
Method | Type | Description | Params
Execute | FUNCTION | Open the dialog box , return True if color selection |

QColorDialog Events
Event | Type | Occurs when... | Params

QColorDialog Examples

' Color chooser dialog example

$TYPECHECK ON
$INCLUDE "RAPIDQ2.INC"
DECLARE SUB ButtonClick (Sender AS QBUTTON)
dim Dial as QColorDialog
    Dial.Style=cdNoFullOpen
    Dial.left = 12
    Dial.Top = 50

CREATE Form AS QFORM
Caption = "test colors"
    CREATE Button AS QBUTTON
        Width = 100
        Caption = "Choose color"
        OnClick = ButtonClick
    END CREATE
    Center
END CREATE
form.ShowModal

SUB ButtonClick (Sender AS BUTTON)
    Dial.Style = cdFullOpen
    Dial.Caption = "select color"
    if Dial.Execute then
      Form.Color=Dial.Color
    end if
END SUB


QD3DMESHBUILDER

Rapid-Q Direct3D Component by John Kelly Appendix B: QD3DCamera

QD3DCamera Component

INCLUDED IN RAPIDQ_D3D.INC
QD3DCamera helps to render your 3D scene with a "camera." This is a viewport to render what you see.. See limitations.

QD3DCamera Properties

Field | Type | R/W | Default
Pos | QD3DVECTOR | R/W
Orient QD3DOrientVector R/W
Height SINGLE R/W
ZoomFactor SINGLE R/W
MouseZooming SINGLE R/W

QD3DCamera Methods
Method | Type | Description | Params
GetRadius | FUNCTION () | Radius of the camera distance to center of scene | 0
GetXZRadius | FUNCTION () | Radius in x-z plane of the camera | 0
GetXYRadius | FUNCTION () | Radius in x-y plane of the camera | 0
FaceCamera SUB Orient AS QD3DOrientVector,
ObjPosX AS SINGLE, ObjPosY AS SINGLE,
ObjPosZ AS SINGLE)

Finds the angles required to orientation a mesh
with the camera. Known as "Billboarding"

4
Translate | SUB (X#, Y#, Z#) | move camera in 3d space | 3
ZoomXZ | SUB (Mag AS SINGLE) | move forward | 1
Zoom SUB (Mag AS SINGLE) Move by camera orientation
i.e., Cam3d.orient 		1
ResetView | SUB () | Face camera straight down z-axis | 0
Update SUB (DxScrn AS QDXSCREEN)

Always do this before
DXScreen.Render andDXscreen.flip

1

QD3DCamera Events

Event Type Occurs when... Params

QD3DCamera Examples
See the 3DPong_aDelic.Bas example

Prev Component

Contents

Next Component


QD3DCloneMesh

Rapid-Q Direct3D Component by John Kelly Appendix B: QD3DCloneMesh

QD3DCloneMesh Component

INCLUDED IN RAPIDQ_D3D.INC
This will make make multiple copies of objects from the same mesh. Use the Mesh and Frame portions for translating, rotation, color and scaling. There are a maximum of 100 copies for any one QD3DCloneMesh. See limitations.
QD3DCloneMesh Properties
Field | Type | R/W | Default
CloneNum | INTEGER number of copies of the mesh object | R/W |
File | STRING filename of .X or .3DS 3d model | R/W
Mesh | QD3DMESHBUILDER (see other docs) | R/W
Frame Array (0-100) OF QD3DFRAME R/W
Range QRECT Set the range that the objects can be place in the x-z plane R/W
RandPos | INTEGER randomly generate positions | R/W
RandScale | INTEGER randomly generate sizes
Pos Array(0-100) OF QD3DVECTOR each clone can have a unique location, eg.,
box.pos(1).x = -1 : box.pos(2).x = 11
box.pos(1).y = 12 : box.pos(2).y = 2
box.pos(1).z = 10 : box.pos(2).z = -23 		R/W
Orient Array(0-100) OF QD3DOrientVector
set the orientation ('6 element vector) for each clone 		R/W
Visible | INTEGER | R/W

QD3DCloneMesh Methods
Method | Type | Description | Params
The following Methods require passing the QDXScreen as an argument for creation of faces and meshes
Init | SUB (DXscreen AS QDXSCREEN) | Must call this first before rendering |

QD3DCloneMesh Events

Event | Type | Occurs when... | Params
QD3DCloneMesh Examples
See the 3DPong_aDelic.bas example in QD3DPrimative docs.

Prev Component

Contents

Next Component


QD3DPrimitive

Rapid-Q Direct3D Component by John Kelly Appendix B: QD3DPrimitive

QD3DPrimitive Component

INCLUDED IN RAPIDQ_D3D.INC
This will make simple polygon mesh objects that you can add to your scene. Use the Mesh and Frame portions for translating, rotation, color and scaling. See limitations.
QD3DPrimitive Properties
Field | Type | R/W | Default
BoxSides | INTEGER number of sides that a box can have 4 = open box 5 = box with top 6 = fully enclosed box | R/W |
Mesh QD3DMESHBUILDER (see other docs) R/W
Frame QD3DFRAME R/W
DrawCenter QD3DVector to set the center of the drawing coordinates
i.,e.,
Prim.DrawCenter.x = 0.5
Prim.DrawCenter.y = 0.5
Prim.DrawCenter.z = 0.5 		R/W
ViewFromOutside | INTEGER Set this to False if you want to see the inside of the mesh. Otherwise you see the faces outside (backside culling) | R/W
Visible | INTEGER Set this to true if the object has faces (polygons) | R/W

 QD3DPrimitive Methods
Method | Type | Description | Params
The following Methods require passing the QDXScreen as an argument for creation of faces and meshes
LoadTextureFile | SUB() | opens a QOPENDIALOG box and loads the texture | 1
MakeBox | (DXScreen AS QDXSCREEN) | build a 3dbox, number of sides set by BoxSides | 1
MakeCone | (DXScreen AS QDXSCREEN, NumFaces #) | build a cone pointing up, 3dbox, NumFaces will be the total number of faces | 2
MakeHorizPlane | (DXScreen AS QDXSCREEN) | make a flat plane in the horizontal dimension | 1
MakeVertZPlane | (DXScreen AS QDXSCREEN) | simple vertical plane down the z-axis (x = 0) | 2
MakeVertXPlane | (DXScreen AS QDXSCREEN) | simple vertical plane down the x-axis (z = 0) | 1
MakePyramid | (DXScreen AS QDXSCREEN) | Pyramid will be pointing up, 4 sides | 1
MakeSphere | (DXScreen AS QDXSCREEN, NumFaces #) | NumFaces will be the total number of faces in the sphere, good values range from 16 to 120 | 1
MakeCylinder | (DXScreen AS QDXSCREEN, NumFaces #) | Cylinder will be pointing up, NumFaces will be the total number of faces in the sphere, good values range from 6 to 64 | 3

QD3DPrimitive Events

Event | Type | Occurs when... | Params
QD3DPrimitive Examples
'
'3D pong Demo with Grateful Dead inspiration
'  Some minor code sections by Basic4GL
' JohnK
'
DECLARE SUB ChromeWrapThem
DECLARE SUB CloseApp
DECLARE SUB DXInit(Sender AS QDXScreen)
DECLARE SUB DXInitSurface(Sender AS QDXScreen)
DECLARE SUB DXscreen_MouseMove (MousX AS INTEGER, MousY AS INTEGER)
DECLARE SUB Form_Key_Press(TheKey AS WORD, Shift AS INTEGER)
DECLARE SUB Make3DObjects
DECLARE SUB MakeParticles
DECLARE SUB MoveParticles
DECLARE SUB MoveThem
DECLARE SUB New_Psychedelic_Background
DECLARE SUB RenderLoop
DECLARE SUB Reset_New_Ball
DECLARE SUB RotateCamera
DECLARE SUB WrapObjects
DECLARE SUB intro
DECLARE SUB scoreboard
DECLARE SUB updateFPS

$TYPECHECK ON                   'force checking of data types
$INCLUDE <RAPIDQ2.INC>          'objects and constants
$INCLUDE <RapidQ_D3D.INC>       'constants ++
$DEFINE DXWidth 640             'set display window for DxScreen
$DEFINE DXHeight 480
$DEFINE CourtX 20
$DEFINE CourtZ 10
$DEFINE Ceiling 12
$DEFINE PaddleWidth 3
$DEFINE PaddleThick 1
$DEFINE PaddleHeight 2
$DEFINE BallSize 0.8
$DEFINE MaxSpeed 3.5
$DEFINE pSpeed 2.5
$DEFINE InterPlayDelay 0.5  'delay between serves
$DEFINE NumParticles 20
CONST tmpBMPFile = "~~3DPongadelic.bmp"

DIM x AS SINGLE:            x=RND(1)* CourtX    'randomize the starting point of the ball x position
DIM y AS SINGLE:            y=RND(1)* Ceiling   'randomize the starting point of the ball y position
DIM z AS SINGLE:            z=RND(1)* CourtZ    'randomize the starting point of the ball Height
DIM bool_x:                 bool_x = true   'Test to See if the Ball Needs to go Left or Right
DIM bool_y:                 bool_x = true   'Test to See if the Ball Needs to go Up or Down
DIM bool_z:                 bool_z = true   'Test to See if the Ball Needs to go Cross court
DIM player1_y AS SINGLE:    player1_y = 0   'Player 1 height position
DIM player2_y AS SINGLE:    player2_y = 0   'Player 2 height position
DIM player1_z AS SINGLE:    player1_z = 0   'Player 1 lateral position
DIM player2_z AS SINGLE:    player2_z = 0   'Player 2 lateral position
DIM p1_score:               p1_score = 0    'Player 1 score
DIM p2_score:               p2_score = 0    'Player 2 Score
DIM FailRate AS SINGLE:     FailRate =30.0  'Player 2(computer) fails about 30%
DIM FPS AS INTEGER:         FPS = 30        'frames per second
DIM TheSpeed AS SINGLE:     TheSpeed = 0.2  'arbitrary speed for now
DIM RotateMe AS INTEGER:    RotateMe = True 'rotate world
DIM RelX AS SINGLE:         RelX = 0        'camera rotation
DIM RelY AS SINGLE:         RelY = 0        'camera rotation
DIM GameEndFlag AS INTEGER: GameEndFlag = False

DIM WorldFrame          AS QD3DFrame        'Master (parent) frame all 3d objects moving together attached to this frame
DIM AmbientLight        AS QD3DLight        'ambient DXscreen light.. make it dark for dark, daylight handles daytime!!
DIM DayLight            AS QD3DLight        'set the properties of the light, this is for ambient daylight
DIM DayLightFrame       AS QD3DFrame        'allow position & orientation of light
DIM Cam                 AS QD3DCAMERA       'custom camera component
DIM Paddle1             AS QD3DPrimitive    'our player 1 paddle
DIM Paddle2             AS QD3DPrimitive    'our player 1 paddle
DIM TheBall             AS QD3DPrimitive    'Boing ball
DIM FloorObj            AS QD3DPrimitive    'Floor is a reserved keyword
DIM SkyBox              AS QD3DPrimitive    'box around the world frame, texture surround scene on it
DIM wrap                AS QD3DWRAP         'object to hold texture wrapping information
DIM Particles1          AS QD3DCloneMesh    'A clone mesh is a single mesh on many QD3DFrames
DIM Particles2          AS QD3DCloneMesh    'A clone mesh is a single mesh on many QD3DFrames

CREATE MainForm AS QForm
    Caption = "3D Pong"
    BorderStyle =   bsNone
    Width = DXWidth
    Height = DXHeight
    Center
    OnKeyDown = Form_Key_Press
    OnClose = CloseApp

    CREATE DXScreen AS QDXScreen            'really a direct draw surface?
        Top = 0
        Left = 0
        Width = DXWidth
        Height = DXHeight
        Cursor = crNone
        FullScreen = True
        Init(DXWidth, DXHeight)
        BitCount = Screen.GetPixelDepth         'get whatever mode we are in
        Use3D = True                            'load Direct3D Retained mode
        UseHardware = True                      '3D accelerated video cards are cheap, get one!!
        OnInitialize = DXInit                   'load your meshs/faces to the frames, set lights, camera
        OnInitializeSurface = DXInitSurface     'screen is ready to be drawn
        OnMouseMove =   DXscreen_MouseMove      'pass mouse (X%, Y%)
        OnKeyDown = Form_Key_Press
    END CREATE
END CREATE

'DIM DXTimer AS QDXTimer                            'regularly update display
'    DXTimer.Enabled = False
'    DXTimer.Interval = 50
'    DXTimer.OnTimer = updateFPS

SUB updateFPS
'   FPS = DXTimer.FrameRate
'   DXScreen.TextOut(500, 32, "FPS = "+STR$(DXTimer.FrameRate) + "     ",&HFFFFFF, 0)' Print Player 2 Score
'   DXScreen.ForceUpdate(500, 32, 540, 64)
'   DXScreen.Flip
END SUB

'*******************************************************
'*******************************************************
'****     INITIALIZATION CODE FOR DirectX Screen *******
'*******************************************************
'*******************************************************

SUB DXInitSurface(Sender AS QDXScreen)
    DxScreen.setRenderMode(D3DRMRENDERMODE_BLENDEDTRANSPARENCY OR D3DRMRENDERMODE_SORTEDTRANSPARENCY)
    Intro
    RenderLoop
END SUB

SUB DXInit(Sender AS QDXScreen)

    DXScreen.CreateFrame(WorldFrame)    'create the terrain frame, all other frames will be attached to it in heirarchy
    DXScreen.CreateFrame(DayLightFrame) 'probably allocates pointer to COM interface, memory, handles, etc

'       *********  First we create the lights  ******************
    DXScreen.CreateLightRGB(D3DRMLIGHT_AMBIENT, 0.6, 0.6, 0.6, AmbientLight)    'ambient is dark for baseline darkness!!
    DXScreen.AddLight(AmbientLight)                                             'this light moves with root frame
    DXScreen.CreateLightRGB(D3DRMLIGHT_DIRECTIONAL, 0.9, 0.9, 0.9, DayLight)    'point light
    DayLightFrame.AddLight(DayLight)                                            'to a frame so we can remove from scene
    DayLightFrame.SetPosition(0, 8, 0)                                         'x,y,z position, some arbitary value until load a terrain
    DayLightFrame.SetOrientation(0, -1, 0, 0, 1, 0)                             'points straight down
    DXScreen.SetTextureQuality(D3DRMTEXTURE_MIPLINEAR)      'gives a smooth appearance to textures
    WorldFrame.SetPosition(0.0, 0.0, 0.0)           'centered because Heightmap is centered
    Make3DObjects
'   DXScreen.SetCameraPosition(0.0, 2.5 * Ceiling, -4 * CourtZ)
'   DXScreen.SetCameraOrientation(0.0,-0.5, 0.7, 0, 1, 0)
    Cam.Pos.x = 0.0
    Cam.Pos.y = 2.5 * Ceiling
    Cam.Pos.z = -4.5 * CourtZ
    Cam.Orient.x = 0.0
    Cam.Orient.y = -0.5
    Cam.Orient.z = 0.7
    Cam.Update(DXscreen)
    DXScreen.Font.Size = 14
    DXScreen.Font.Bold = True
    MakeParticles
    New_Psychedelic_Background
    ChromeWrapThem
END SUB

SUB RenderLoop

  DO                    ' Main Game Loop
    '----  move BALL and Paddles  -----------------

    TheBall.Frame.SetPosition(x, y, z)
    TheBall.Frame.Move(TheSpeed)                        'rotate it
    Paddle1.Frame.SetPosition(-CourtX, player1_y, player1_z)
    'add some strategy to the computer
    IF (x  > (CourtX/4)) THEN Paddle2.Frame.SetPosition(CourtX, y, z)   ' only hit near its side
    IF RotateMe THEN RotateCamera
    ChromeWrapThem
    MoveParticles
    DXScreen.Render
    scoreboard
    DOEVENTS

    'bounce if player 1 hits(Left Player)-----------------------------------------------------------------
    IF x < (-CourtX + PaddleThick) and (x >-CourtX) THEN
        IF (z <=player1_z + PaddleWidth) AND (z >=player1_z - PaddleWidth) THEN
            IF (y <=player1_y + PaddleHeight) AND (y >=player1_y - PaddleHeight) THEN   bool_x = true
        END IF
    END IF

    IF x <= -CourtX then
        p1_score = p1_score + 1   'If Ball Goes Past the Player then Score Goes
        Reset_New_Ball           'put up a new ball
        New_Psychedelic_Background
    END IF

    'IF 2 player game then bounce if player 2 hits(Right Player)----------------------------------------------------------------
'   Paddle2.Frame.SetPosition(CourtX, player2_y, player2_z)
'   if x >= (CourtX + PaddleThick) and (x < CourtX) and _
'           (y <=player2_z + PaddleWidth) and (y >=player2_z -PaddleWidth) then bool_x = true

    'did computer miss?
    IF (x >= CourtX - PaddleThick) THEN
        IF RND(100) < FailRate THEN             'miss about 30% of the time
            Paddle2.Frame.SetPosition(CourtX, y - PaddleHeight, z + PaddleWidth)' only hit it right 50%
            p2_score = p2_score + 1     ' Up By One Point
            Reset_New_Ball              'put up a new ball
            New_Psychedelic_Background
        ELSE
            bool_x = false              ' Served it back ok
        END IF
    END IF

    if bool_x then x = x + TheSpeed  else x = x - TheSpeed  ' Bool(C++) Value Test Value
    if z <=-CourtZ then bool_z=true         ' Bounce Ball off walls
    if z >=CourtZ then bool_z=false
    if bool_z then INC(z, TheSpeed) else DEC(z, TheSpeed)

    if y <=0 then bool_y=true           'bounce off floor
    if y >= Ceiling then bool_y=false   'bounce off ceiling
    if bool_y then INC(y,TheSpeed)  else DEC(y, TheSpeed)

  LOOP UNTIL GameEndFlag
  CloseApp
END SUB

SUB Reset_New_Ball
    x = RND(1)* CourtX/3 * RND(1)
    y = RND(1) * Ceiling/3
    z = RND(1) * CourtZ/3 * RND(1)

    IF p1_score MOD 6 = 0 THEN
        DXscreen.VIEW.CLEAR
        intro
        DXscreen.VIEW.CLEAR
        IF TheSpeed < MaxSpeed THEN INC(TheSpeed, TheSpeed/6)
    END IF
END SUB

SUB Form_Key_Press(TheKey AS WORD, Shift AS INTEGER)
    SELECT CASE TheKey
    'Player One keyboard control (keeps in bounds)--------------------------------------------------------
    CASE = ASC("q")
        IF player1_z <CourtZ then player1_z =player1_z +TheSpeed
    CASE = ASC("a")
        IF player1_z >-CourtZ then player1_z =player1_z -TheSpeed
    'Player Two keyboard control (keeps in bounds)--------------------------------------------------------
    CASE = 38, 107      'up arrow and "+"
        IF player2_z <2.4 then player2_z =player2_z +TheSpeed
    CASE = 40, 109          'dn arrow "-"
        IF player2_z >-3 then player2_z =player2_z -TheSpeed
    CASE 82 'r
        IF RotateMe THEN RotateMe = False ELSE RotateMe = True
    CASE 27     'esc
        GameEndFlag = True
    END SELECT
END SUB

SUB DXscreen_MouseMove (MousX AS INTEGER, MousY AS INTEGER)
    player1_z = CourtZ - (MouseX/DXScreen.Height) * CourtZ * 2
    player1_y = Ceiling - (MouseY/DXScreen.Width * Ceiling)
END SUB

SUB CloseApp
    WorldFrame.DeleteVisual(SkyBox.Mesh)
    WorldFrame.DeleteVisual(FloorObj.Mesh)
    Application.Terminate
END SUB

SUB intro
    CREATE BMP1 AS QBITMAP
        Width = 32
        Height =32
        pixelFormat = pf24Bit
    END CREATE

    CREATE BMP2 AS QBITMAP
        Width = 32
        Height =32
        Font.Size = 24
        Font.AddStyles(fsBold)
        pixelFormat = pf24Bit
        TransparentMode =  tmFixed
        TransparentColor = 0
    END CREATE

    DIM Scalar As INTEGER
    DIM num AS INTEGER
    DIM R AS QRECT

    For num = 1 to 3        'count down
     BMP1.Width = 32: BMP1.Height = 32
     BMP1.FillRect(0, 0, 32, 32, 0)
     BMP2.FillRect(0, 0, 32, 32, 0)
     BMP2.TextOut(5, 2, STR$(num), &HBBFF, -1)
     For Scalar = 10 TO  DXHeight STEP 10
        BMP1.Width = Scalar: BMP1.Height = Scalar
        R.Left = 0 : R.Top = 0
        R.Right = BMP1.Width : R.Bottom = BMP1.Height
        BMP1.StretchDraw(R, BMP2.BMP)
        DXSCREEN.Draw(DXWidth\2 - BMP1.Width\2, DXHeight\2 - BMP1.Height\2, BMP1.BMP)
        DXscreen.Flip
     Next Scalar
     Next Num
END SUB

SUB scoreboard
    DXScreen.TextOut(10, 10, "Player: "+STR$(p2_score) + "     ",&HFFFFFF, 0)' Print Player 1 Score
    DXScreen.TextOut(170, 10, "r to toggle rotation",&HFFFFFF, 0)' Print Player 1 Score
    DXScreen.TextOut(DXScreen.Width-200, 10, "Computer: "+STR$(p1_score) + "     ",&HFFFFFF, 0)' Print Player 2 Score
    DXScreen.Flip
END SUB

SUB Make3DObjects                                   'make the box, floor and paddles
    DXScreen.CreateMeshBuilder(SkyBox.Mesh)         'Reallocate memory
    WITH SkyBox
     .ViewFromOutside = False                   'view from inside, it is a skybox (dome)
     .BoxSides = 4                              'No ceiling
     .MakeBox (DXScreen)
     .Mesh.Scale(CourtX, Ceiling, CourtZ)
'  .Mesh.SetRGBA(1.0, 1.0, 1.0, 0.85)        'sky color
    END WITH
    WorldFrame.AddVisual(SkyBox.Mesh)               'this object moves on top of world

    DXScreen.CreateMeshBuilder(FloorObj.Mesh)
    WITH FloorObj
        .ViewFromOutside = False                'render the inside of the plane only
        .MakeHorizPlane (DXScreen)              'make a horizontal plane
        .Mesh.Scale(CourtX, 0.0, CourtZ)
'       .Mesh.SetRGB(0.2, 0.65, 1.0)            'floor color
'        .Mesh.LoadTexture("c:\rapidq\Ground.bmp")
    END WITH
    WorldFrame.AddVisual(FloorObj.Mesh)             'add Floor to frame, all will rotate/move together now

    DXScreen.CreateMeshBuilder(Paddle1.Mesh)        'hold vertices
    DXScreen.CreateFrame(Paddle1.Frame)             'holds 3d transformation matrix
    WITH Paddle1
       .DrawCenter.y = -1
       .MakeCylinder (DXScreen, 12)
       .Mesh.Scale(1/PaddleThick, 1, 1/PaddleWidth)
       .DrawCenter.y = 0
       .BoxSides = 5                                   'all sides but the floor
       .ViewFromOutside = True                         'view from outside
       .MakeBox (DXScreen)
       .Mesh.Scale(PaddleThick, PaddleHeight, PaddleWidth)
       .Mesh.SetRGB(0.8, 0.0, 1.0)
       .Frame.AddVisual(Paddle1.Mesh)                  'put paddle on its own frame for movement
    END WITH

    DXScreen.CreateMeshBuilder(Paddle2.Mesh)        'hold vertices
    DXScreen.CreateFrame(Paddle2.Frame)             'holds 3d transformation matrix
    WITH Paddle2
        .DrawCenter.y = -1
        .MakeCylinder (DXScreen, 12)
        .Mesh.Scale(1/PaddleThick, 1, 1/PaddleWidth)
        .DrawCenter.y = 0
        .BoxSides = 5
        .ViewFromOutside = True
        .MakeBox (DXScreen)
        .Mesh.Scale(PaddleThick, PaddleHeight, PaddleWidth)
        .Mesh.SetRGB(0.4, 0.9, 0.2)
        .Frame.AddVisual(Paddle2.Mesh)              'put paddle on its own frame for movement
    END WITH

    DXScreen.CreateMeshBuilder(TheBall.Mesh)
    DXScreen.CreateFrame(TheBall.Frame)
    WITH TheBall
        .BoxSides = 6
        .ViewFromOutside = True
'		 .Mesh.Load("ball.x")
        .MakeSphere (DXScreen, 64)
        .Mesh.Scale(BallSize, BallSize, BallSize)
        .Mesh.SetRGB(1.0, 1.0, 1.0)
        .Frame.SetRotation(0.2,0.8, 0.5, 3 * TheSpeed)
        .Frame.AddVisual(TheBall.Mesh)                      'All objects added to the root frame (WorldFrame)
    END WITH
END SUB

SUB RotateCamera
    DIM tmpRadius AS SINGLE

    tmpRadius = Cam.GetXZRadius         'store it, next calculations affect radius
    Cam.Pos.x = Cos(RelX)*tmpRadius     'move position around circle
'   Cam.Pos.y = Cos(RelY)*tmpRadius     'centered at 0,0
    Cam.Pos.z = Sin(RelX)*tmpRadius
    Cam.Orient.y = -0.5 '-Cos(RelY)
    Cam.Orient.x = -Cos(RelX)
    Cam.Orient.z = -Sin(RelX)
    Cam.Update(DXScreen)
    INC(RelX, TheSpeed/20)
    INC(RelY, TheSpeed/20)
END SUB

SUB New_Psychedelic_Background
     DIM Pong_a_delc AS QBITMAP
     DIM MyTexture AS QD3DTexture
     DIM x As INTEGER, y As INTEGER, r As INTEGER, g As INTEGER, b As INTEGER
     DIM Bitsz As INTEGER
     DIM t AS SINGLE

     t = TIMER
     Bitsz = 2^(RND(3) + 2)
     Pong_a_delc.Width = Bitsz
     Pong_a_delc.Height = Bitsz
     Pong_a_delc.Pixelformat = pf24bit

     For x = 0 TO Bitsz
     For y = 0 TO Bitsz
      IF RND(10) > 5 THEN r = 255 ELSE r = 0
      IF RND(10) > 5 THEN g = 255 ELSE g = 0
      IF RND(10) > 5 THEN b = 255 ELSE b = 0
      Pong_a_delc.Pixel(x,y) = RGB(r,g,b)
     Next x
     Next y
     Pong_a_delc.SaveToFile(tmpBMPFile)
     DXScreen.LoadTexture(tmpBMPFile, MyTexture) 'store it on file in order to load it
     SkyBox.Mesh.SetTexture(MyTexture)
     TheBall.Mesh.SetTexture(MyTexture)
     Pong_a_delc.Line(0, Bitsz\2, Bitsz, Bitsz\2, &HFFFFFF)
     Pong_a_delc.Line(Bitsz\2, 0, Bitsz\2, Bitsz, &HFFFFFF)
     Pong_a_delc.SaveToFile(tmpBMPFile)
     DXScreen.LoadTexture(tmpBMPFile, MyTexture) 'store it on file in order to load it
     FloorObj.Mesh.SetTexture(MyTexture)
     KILL tmpBMPFile        'don't need it anymore
     WrapObjects
     DO: LOOP UNTIL ((TIMER - t) > InterPlayDelay)
END SUB

SUB WrapObjects
    DXScreen.createWrap(D3DRMWRAP_FLAT,_    'type of texture projection
            -CourtX, 0, -CourtZ, _        'origin on the mesh coordinates
            0, 1, 0, _                   'the z-axis direction vector - texture projects down the z-azis
            0, 0, 1, _                 'the up vector - the top of the texture points up the y-axis
            0, 0, _                      'origin coordinates on bitmap
            0.5/CourtX, 0.5/CourtZ, wrap)   'scale so bitmap covers all object 1/maxx, 1/maxy
    wrap.apply(FloorObj.Mesh)

    DXScreen.createWrap(D3DRMWRAP_SPHERE,_    'type of texture projection
            0, 0, 0, _          'origin on the mesh coordinates
            0, 1, 0, _          'the z-axis direction vector - texture projects down the z-azis
            0, 0, 1, _          'the up vector - the top of the texture points up the y-axis
            0, 0, _             'origin coordinates on bitmap
            1, 1, wrap)
    wrap.Apply(SkyBox.Mesh)

    DXScreen.createWrap(D3DRMWRAP_CHROME,_    'type of texture projection
            0, 0, 0, _            'origin on the mesh coordinates
            0, 0, 1, _            'the z-axis direction vector - texture projects down the z-azis
            0, 1, 0, _            'the up vector - the top of the texture points up the y-axis
            0, 0, _               'origin coordinates on bitmap
            2, 2, wrap)
    wrap.apply(TheBall.Mesh)

END SUB

SUB ChromeWrapThem  'hmmm not working
    Wrap.ApplyRelative(TheBall.Frame,TheBall.Mesh) 'for each frame
'    wrap.applyRelative(WorldFrame, TheBall.Mesh)
END SUB

SUB MakeParticles
 DIM Face1 AS QD3DFace
 DIM Face2 AS QD3DFace
 DIM Face3 AS QD3DFace
 DIM i AS INTEGER

 DXScreen.CreateFace(Face1)  'create face instance
 Face1.AddVertex(-1, 0, -1): Face1.AddVertex( 1, 0, -1)  'horiz plane
 Face1.AddVertex( 1, 0, 1): Face1.AddVertex(-1, 0, 1)
 Face1.AddVertex(-1, 0, 1): Face1.AddVertex( 1, 0, 1)
 Face1.AddVertex( 1, 0, -1): Face1.AddVertex(-1, 0, -1)
 DXScreen.CreateFace(Face2)
 Face2.AddVertex(0, -1, -1): Face2.AddVertex( 0, 1, -1)  'vert y-z plane
 Face2.AddVertex( 0, 1, 1): Face2.AddVertex(0, -1, 1)
 Face2.AddVertex(0, -1, 1): Face2.AddVertex( 0, 1, 1)
 Face2.AddVertex( 0, 1, -1): Face2.AddVertex(0, -1, -1)
 DXScreen.CreateFace(Face3)
 Face3.AddVertex(-1, -1, 0): Face3.AddVertex( 1, -1, 0)  'horiz plane
 Face3.AddVertex( 1, 1, 0): Face3.AddVertex(-1, 1, 0)
 Face3.AddVertex(-1, 1, 0): Face3.AddVertex( 1, 1, 0)
 Face3.AddVertex( 1, -1, 0): Face3.AddVertex(-1, -1, 0)

 WITH Particles1
  .CloneNum = NumParticles
  '.File = "YourModel.x"  '3D mesh file in binary .x format
  .Range.Left  = -CourtX
  .Range.Top  = -CourtZ
  .Range.Right = CourtX
  .Range.Bottom = CourtZ
  .RandPos = True
  .RandScale = True
  .Init(DXScreen)    'set properties first, creates frames, meshbuilder COM objects
  .Mesh.AddFace(Face1)   'follows init
  .Mesh.AddFace(Face2)   'follows init
  .Mesh.AddFace(Face3)   'follows init
  .Mesh.SetRGBA(1.0, 1.0, 0.0, 0.25)
  .Mesh.Scale(0.5, 0.5, 0.5)
  FOR i = 1 TO .CloneNum
   WorldFrame.AddFrame(Particles1.Frame(i)) 'now particles move with the whole scene
  NEXT i
 END WITH

 'must do this again for the next Particle system
 DXScreen.CreateFace(Face1)  'create face instance
 Face1.AddVertex(-1, 0, -1): Face1.AddVertex( 1, 0, -1)  'horiz plane
 Face1.AddVertex( 1, 0, 1): Face1.AddVertex(-1, 0, 1)
 Face1.AddVertex(-1, 0, 1): Face1.AddVertex( 1, 0, 1)
 Face1.AddVertex( 1, 0, -1): Face1.AddVertex(-1, 0, -1)
 DXScreen.CreateFace(Face2)
 Face2.AddVertex(0, -1, -1): Face2.AddVertex( 0, 1, -1)  'vert y-z plane
 Face2.AddVertex( 0, 1, 1): Face2.AddVertex(0, -1, 1)
 Face2.AddVertex(0, -1, 1): Face2.AddVertex( 0, 1, 1)
 Face2.AddVertex( 0, 1, -1): Face2.AddVertex(0, -1, -1)
 DXScreen.CreateFace(Face3)
 Face3.AddVertex(-1, -1, 0): Face3.AddVertex( 1, -1, 0)  'horiz plane
 Face3.AddVertex( 1, 1, 0): Face3.AddVertex(-1, 1, 0)
 Face3.AddVertex(-1, 1, 0): Face3.AddVertex( 1, 1, 0)
 Face3.AddVertex( 1, -1, 0): Face3.AddVertex(-1, -1, 0)

 WITH Particles2
  .CloneNum = NumParticles
  '.File = "YourModel.x"  '3D mesh file in binary .x format
  .Range.Left  = -CourtX
  .Range.Top  = -CourtZ
  .Range.Right = CourtX
  .Range.Bottom = CourtZ
  .RandPos = True
  .RandScale = True
  .Init(DXScreen)    'set properties first, creates frames, meshbuilder COM objects
  .Mesh.AddFace(Face1)   'follows init
  .Mesh.AddFace(Face2)   'follows init
  .Mesh.AddFace(Face3)   'follows init
  .Mesh.SetRGBA(1.0, 1.0, 1.0, 0.25)
  .Mesh.Scale(0.5, 0.5, 0.5)
  FOR i = 1 TO .CloneNum
   WorldFrame.AddFrame(Particles2.Frame(i))
  NEXT i
 END WITH
END SUB

SUB MoveParticles
 DIM i AS INTEGER

 WITH Particles1
 FOR i = 1 TO .CloneNum
     .Pos(i).x = .Pos(i).x + pSpeed * (RND - 0.5)
   IF .Pos(i).x < -CourtX THEN .Pos(i).x = -CourtX
   IF .Pos(i).x >  CourtX THEN .Pos(i).x =  CourtX
     .Pos(i).y = .Pos(i).y + pSpeed * (RND - 0.5)
   IF .Pos(i).y < 0 THEN .Pos(i).y = 0
   IF .Pos(i).y > Ceiling THEN .Pos(i).y = Ceiling
  .Pos(i).z = .Pos(i).z + pSpeed * (RND - 0.5)
   IF .Pos(i).z < -CourtZ THEN .Pos(i).z = -CourtZ
   IF .Pos(i).z >  CourtZ THEN .Pos(i).z =  CourtZ
  .Frame(i).SetPosition(.Pos(i).x, .Pos(i).y, .Pos(i).z)
 NEXT i

 END WITH

 WITH Particles2
 FOR i = 1 TO .CloneNum
     .Pos(i).x = .Pos(i).x + pSpeed * (RND - 0.5)
   IF .Pos(i).x < -CourtX THEN .Pos(i).x = -CourtX
   IF .Pos(i).x >  CourtX THEN .Pos(i).x =  CourtX
     .Pos(i).y = .Pos(i).y + pSpeed * (RND - 0.5)
   IF .Pos(i).y < 0 THEN .Pos(i).y = 0
   IF .Pos(i).y > Ceiling THEN .Pos(i).y = Ceiling
  .Pos(i).z = .Pos(i).z + pSpeed * (RND - 0.5)
   IF .Pos(i).z < -CourtZ THEN .Pos(i).z = -CourtZ
   IF .Pos(i).z >  CourtZ THEN .Pos(i).z =  CourtZ
  .Frame(i).SetPosition(.Pos(i).x, .Pos(i).y, .Pos(i).z)
 NEXT i
 END WITH
END SUB

MainForm.ShowModal                                          'get the program running

Prev Component

Contents

Next Component


QDebug

Documentation component by John Kelly
QDEBUG

QDEBUG Component
Included in RAPIDQ2.INC.

QDEBUG is a self-contained form that is handy for debugging loops, and code without interrupting program flow.
Written by John Kelly but based on code from Pete Kleinschmidt and Michael Zito. To close the form while the programming is running use QDEBUG.Visible = False or QDEBUG.Form.Close. To make sure the user doesn't close the form set methods use QDEBUG.Enabled = False or QDEBUG.Visible =False. Use the .SetError(0) to clear out any previous windows error. See limitations.

QDEBUG Properties
 |  | Read/Write | Default
Form | QFORM You can reset the Debug form just like any other form: Debug.Form.Width = 100 Debug.Form.Font = myQFont, etc. | R/W |
Visible | LONG | R/W | True
Enabled | LONG Determines if the form is 0 (or False) = fixed/read-only 1 (or True) = Debug window can be moved by user/closed etc. | R/W | True
TestSockets | INTEGER Allow for checking of Windows Socket errors | R/W | False

QDEBUG Methods
Method | Type | Description | Params
Err$ | FUNCTION () AS STRING | Gets Windows GETLASTERROR API and formats it into a text message. CAREFUL, if your program doesn't create an error, it will report the previous error. | 0
ErrNum | FUNCTION () AS DWORD | Returns the last Windows Error, if you want to see the code for Err$ | 0
Print | SUBI (...) | Print out standard variable types and strings | infinite
PrintStr | SUB (Str AS STRING) | Print out a string or variable converted to string | 1
Bug | SUB (Str AS STRING) | Same as PrintStr, (compatible with previous release) | 1
PrintWrap | SUB (Str AS STRING) | Print a string and wrap it inside the Form | 1
SetError | SUB (NewErr AS LONG) | Generate a windows system error. Use 0& to clear Last Error | 1

QDEBUG Events
Event | Type | Occurs when... | Params
None ...

QDEBUG Example

$TYPECHECK ON
$INCLUDE "RAPIDQ2.INC"
DECLARE SUB btnTestClick
DIM Debug AS QDEBUG         'Should declare as global
CREATE frmTest AS QFORM
Caption = "Debug Test Program"
Center
CREATE btnTest AS QBUTTON
Caption = "OK"
Top = 30
Left = 30
Height = 20
OnClick = btnTestClick
END CREATE
END CREATE

SUB btnTestClick
DIM I AS INTEGER
DIM J AS INTEGER
FOR J = 1 TO 3
FOR I = 1 TO 20
Debug.Print("Run ", I, " through Loop", J) 'strings AND varaibles to debug object
' Debug.ErrNum
' Debug.Err$ 'default output to window
NEXT
NEXT
END SUB

frmTest.ShowModal

QDEBUG Example #2
'create an error
$INCLUDE "RAPIDQ2.INC"
DIM Debug AS QDEBUG 'Should declare as global
Debug.Form.Left = 20
Debug.Form.Top = 120
Debug.Form.Height = 186
Debug.SetError ERROR_BAD_USERNAME
Showmessage "debug error = " + Debug.Err$
Contents


QDir

QDIR Component

' ============================================================================
' QDIR   RAPIDQ EXTENDED COMPONENT       April 2004        By Jacques Philippe
'
'    SEARCH FOR MATCHING FILES IN DIRECTORY AND SUBDIRECTORIES
'    FILTERS ON EXTENSION, MUST_ATTRIBUTES and REJECTED_ATTRIBUTES
'
' DOCUMENTATION       like      "DOS"   DIR   and   DIR /S      Version 1.0.4
' ============================================================================
'
'    $INCLUDE  "QDir.Inc"          cut and paste this  **ON TOP** of your code
'
'    RAPIDQ dont like comments on line containing "\\" or "\", compiler reports
'    an error and there is none. Juste remove the comment and then it will works.
'
'    EXAMPLE 1
'    ---------
'    a simple QDIR.DIR searching matching files without searching in Sub directories
'       ' in directory c:/windows searches the "*.hlp" files, directory not wanted,
'       ' only files with Archive attribute set are accepted
'
'       ' ------ CODE_1 ------
'       Dim myDir As QDir
'       myDir.OnFileFound = OnFileFound_ShowFileParams   '(QDir FileFound Event)
'       myDir.Dir ("c:/windows/*.hlp", "D", "A") ' arg2 rejected, arg3 mustAttributes
'       Print "path    = ";myDir.path
'       Print "EXAMPLE 1          FINISHED"
'
'       ' QDir OnFileFound Event
'       ' ----------------------
'       Sub OnFileFound_ShowFileParams
'           Print myDir.path & myDir.FileName & "   " & myDir.Time & "  " _
'                                                          & myDir.dateAlphaEU
'           ' and ?50+ other properties for each File Found
'       End sub
'       ' ------ END CODE_1 ------
'    EXAMPLE 2
'    ---------
'    a QDIR.DIRS searching matching files with search in all sub directories
'       ' Same Search as In Example 1 but in sub directories too
'
'       ' ------ CODE_2 ------
'       Dim myDir As QDir
'       myDir.OnFileFound = OnFileFound_ShowFileParams   '( FileFound Event)
'       myDir.Dirs ("c:/windows/*.Txt", "D", "A") ' arg2 rejected, arg3 mustAttributes
'       Print "EXAMPLE 2          FINISHED"
'
'       ' QDir OnFileFound Event
'       ' ----------------------
'       Sub OnFileFound_ShowFileParams
'           Print myDir.path & myDir.FileName & "   " & myDir.Time & "  " _
'                                                           & myDir.dateAlphaEU
'           ' and ?50 other properties for each file found
'       End sub
'       ' ------ END CODE_2 ------
'
'    Attributes are refered by their first letter : "A" for archive, "D" for direct
'        "S" for System, "H" for Hidden, "R" for Read only, ...
'    myDir.WithDotsDirs = False  ' to reject \. and \.. directories
'
' ---------------------------------------------------------------------------------
'    STOPPING FILE SCANNING (V 1.0.3)
'    ----------------------
'     With previous QDir, when you started a Dirs on a large number of files, you could
'     not stop it. You had to wait it had finished or stop it with Ctrl Alt Delete. Now
'     you can simply abort the scanning:
'        1 - public property 'flagStop' : when <> 0, scanning stops
'        2 - a form is popup during file scanning, showing a message
'            "CLIC ME TO STOP SCANNING"
'        3 - public property 'flagShowFormStopDir' : when <> 0, the form is
'            poped up while scanning and invisible when scanning is finished.
'            default value is 1 : the form is poped up
'
'     form frmDirStop and it's label lblDirStop are public, so all their properties
'     and methods can be used and modified.
' ---------------------------------------------------------------------------------
'
'    METHODS  part 1
'    -------
'    - DIR   :  File Search without Scanning The Sub Directories
'
'      QDir.Dir (pathfilter$, rejectedAttributes$, mustAttributes$)           a Sub
'
'    - DIRS  :  File Search with Scanning the Sub Directories
'               Dirs chosen to remember the Command Dir /s  ???
'
'      QDir.Dirs (pathfilter$, rejectedAttributes$, mustAttributes$)          a Sub
'
'    - ChangeFileAttributes (sPathFileName$ , sAttributesAsString$) As Long
'           documented further  (returns  0 or 1)
'    - ChangeFileDateAndTime ( ... ) As Long  '   Functioni
'      ChangeFileDateAndTime (pathFileName$, Year%, month%, day%, hour%, _
'                       minute%, second%, optionWhichTimes$) As Long
'           documented further  ( returns 0 or 1)
'
'    Comments about these four methods
'    ---------------------------------
'       - path may be relative or absolute
'          ie : dir2\myfile.Ext or c:\dir1\dir2\myfile.Ext
'       - relative path is relative to APPLICATION directory (where the .EXE is)
'       - in path "\" and "/" are accepted as separator
'       - filter may be any kind of filter using wild card  "*.Txt", "*name.Txt"
'       - attributes are passed as a String, elements of that string are :
'           "A" for Archive
'           "D" for Directory
'           "H" for Hidden
'           "N" for Normal
'           "R" for Read Only
'           "S" for System
'           "T" for Temporary
'           "C" for Compressed
'           "0" for No Attribute Set (?=N?)
'       - You can use multiple attributes in any order ie : "HTCA"
'       - an unknown attribute letter will be ignored.
'       - attributes are not case sensitive
'       - in rejectedAttributes$, if more than one attribute is rejected, all file
'         having one of these rejected attributes set is rejected from the search.
'       - in mustAttributes$, if more than one attibute is present, to be accepted
'         a file must have all these attributes set. ie : no file can match "0A"
'       - Dir and Dirs will only return when ALL the directory job has been done.
'         There is a DoEvents in QDir Loops.
'       - Once a QDir.Dir or QDir.Dirs is Started, a busy flag forbids to start
'         another occurence of QDir.Dir or QDir.Dirs, until the first job is
'         finished. To start more than one QDir.Dir or QDir.Dirs simultneously,
'         you must DECLARE (DIM) two or more  Variables As QDIR.
'
' -----------------------------------------------------------------------------
'    Note : All Properties should be READ ONLY except : OnFileFound (Event),
'              days(0 To 6) and months(1 To 12). You can set them but it's
'              useless, so dont do it.
'    PROPERTIES
'    ---------
'    Once a Matching File Is Found, QDIR gathers, computes and stores a lot of
'    datas about that File.
'
'    PROPERTIES GROUPE 1
'    -------------------
'    Note
'    ----
'    Each file is stored on disk with three times : the CreationTime,
'    the lastAccessTime and the most commonly used the lasWriteTime
'
'    Name, Path, Size
'    ----------------
'    fileName As string          the name of the fileFound
'    dosFileName As string       the dos name of thefile found
'    path As String              the Absolute path to the file  ie : C:\myDir\otherDir\
'    pathFileName As string      the Absolute path + the fileName  ie : c:\Windows\system.dat
'    size As Double              the size as a double (use StrF$(size, ffFixed, 18, 0) to exp
'                                (ffNumber to have thousands separators)
'    WithDotsDirs As Long        Set to False, the "." and ".." are not returned
'    Attributes
'    ----------
'    attributes As Long             the attributes af the file (sum of attributes)
'    attributesAsString As String   the attributes transformed in a string "ADHNRSTC0"
'                          If Instr(myDir.AttributesAsString, "A") Then   ....
'    ' File Times
'    ' ----------
'    dateTime As Double          the lastWriteTime of the file as a double
'    time As String              the lastwriteTime of the file, format HH:MM:SS
'    timems As String            the lastWriteTime of the file + milliseconds, format HH:MM:SS,mmm
'    date As String              the lastWriteTime date, format MM/DD/YYYY
'    dateEU As String            the lastWriteTime date, EU foramt DD/MM/YYYY
'    dateAlpha As String         the lastWriteTime in alphanumeric format "mon dec 24 2001"
'    dateAlphaEU As string       the lastWriteTime in alphanumeric EU format "mon 24 dec 2001"
'    strDayOfWeek As string      the lastWriteTime Day Of The Week : "Mon", "Tue", "Wed", "Thu" ...
'    days(0 To 6) As String      the 7 names of the strDayOfWeek. Source for AlphaNumeric dates
'    strMonthOfYear As String    the lastWriteTime Month Of The Year : "Jan", "Feb", "Mar", "Apr" ...
'    months(1 To 12) As String   the 12 names of strMonthOfYear. Source for AlphaNumeric dates.
'
'    PROPERTIES GROUP 2
'    ------------------
'    All the informations available for lastWriteTime -and more- are available for lastAccessTime
'    and creationTime too, but not directly, you have to get them in their QDIR_SYSTEMTIME TYPE
'
'    Type QDIR_SYSTEMTIME
'        year As Short                 ' the year as a number
'        month As Short                ' the month as a number
'        dayOfWeek As Short            ' number of the day of the week  SUNDAY = 0, MONDAY = 1, ...
'        day As Short                  ' the day in the month  1, 2, 3,...  12, 13, 14, ... 28/30/31
'        hour As Short                 ' the hour as a number
'        minute As Short               ' the minute as a number
'        second As Short               ' the second as a number
'        milliseconds As Short         ' the milliseconds as a number
'        ' Extended                    ' as described in PROPERTIES GROUP 1
'        dateTime As Double            ' The DateTime As A Number
'        date As String * 10           ' Date as a String  mm/dd/yyyy
'        dateEU As String * 10         ' EU date Foramt dd/mm/yyyy
'        dateAlpha As String * 16      ' "ddd" "mmm" DD, yyyy
'        dateAlphaEU As String * 15    ' "ddd" DD "mmm" yyyy
'        time As String * 8            ' without ms  HH:MM:SS
'        timems As String * 12         ' Time As a String  HH:MM:SS.iii
'        strDayOfWeek As String * 3    ' day of the week as in Day(0 To 6) : "Mon", "Tue", "Wed", ... "Sun"
'        nWeekDay As String * 1        ' "0", "1", "2", ... "6"
'        strMonthOfYear As String * 3  ' day of the week as in Months(1 To 12) : "Jan", "Feb", ... "Dec"
'    End Type
'
'    creation As QDIR_SYSTEMTIME    ' the Type contaning informations about the creationTime
'    lastAccess As QDIR_SYSTEMTIME  ' the Type contaning informations about the lastAccessTime
'    lastWrite As QDIR_SYSTEMTIME   ' the Type contaning informations about the lastWriteTime
'
'    The File Time Properties decribed above for lastwriteTime may be found here for all three
'    File Times : ie
'    - QDir.Creation.dateAlphaEU
'    - QDir.lastAccess.dateEU     and even
'    - QDir.lastWrite.timems      (which is equal to QDir.timems)
'
'    These three time TYPES give access to 3 x 18 porpeties (=54), not used every day :)
'
'    To compare dates and times, use dateTime. The dateTimes are DOUBLE precision numbers
'    (64 bit Integer, converted here in DOUBLE) holding a date and time associated with
'    a file. That DOUBLE specifies the number of 100-nanosecond intervals which have
'    passed since January 1, 1601 (10,000,000 for each elapsed second since then).
' ---------------------------------------------------------------------------------
'
'    METHODS    part  2
'    -------
'    - ChangeFileDateAndTime As Integer    a   Functioni
'
'      SYNTAX :
'      ------
'          ChangeFileDateAndTime (pathFileName$, Year%, month%, day%, hour%, _
'                                               minute%, second%, optionWhichTimes$)
'      Return  0 (False) on Failure or 1 (True) on success
'
'      EXAMPLES :
'      --------
'      - ChangeFileDateAndTime ("c:\myDir\myFile", 1983, 6, 21, 17, 22, 33)
'           the LastWriteTime Of MyFile is set to June 21 st 1983 at 17:22:23
'
'      - ChangeFileAndDate ("c:\myDir\myFile", 1983, 6, 21, 17, 22, 33 "Access")
'           the LastAccessTime Of myFile is set to June 21 st 1983 at 17:22:23
'
'      - ChangeFileAndDate ("c:\myDir\myFile", 1983, 6, 21, 17, 22, 33 "ACCESS Write CREATION")
'           the LastAccessTime, CreationTime and LastWriteTime Of myFile are
'           set to June 21 st 1983 at 17:22:23
'
'           Used in the Event OnFileFound with Qdir.pathFilename can change the Date
'           and Time of all matching files.
'      DOC
'      ---
'       A File is Stored on Disk with Three Different Dates and Times Named :
'           - the creationTime
'           - the lastAccesstime
'           - the lastWriteTime   (the one mostly mostly used shown)
'
'       Six NUMERIC Parameters **MUST** be Passed to the Functioni :
'           - the First  is the YEAR   of the new Date Time For the File
'           - the Second is the MONTH  of the new Date Time For the File
'           - the Third  is the DAY    of the new Date Time For the File
'           - the Fourth is the HOUR   of the new Date Time For the File
'           - the Fifth  is the MINUTE of the new Date Time For the File
'           - the Sixth  is the SECOND of the new Date Time For the File'
'
'       The FILENAME With or Without a Path must be Passed as a STRING !
'
'       The optionWhichTimes Parameter is a STRING that Indicates to the Functioni
'           which file Times must be Changed. If that String contains :
'           - "CREATION" the creationTime   will be Changed ("CRE" is enough)
'           - "ACCESS"   the lastAccessTime will be changed ("ACC" is enough)
'           - "WRITE"    the lastWriteTime  will be changed ("WRI" is enough)
'           Not case sensitive
'           If that string is not Passed or is Empty, the lastWriteTime only will
'           be changed
'
'       ERROR : on error a ShowMessage is POPED UP and the Functioni Returns 0 (False)
'
' ----------------------------------------------------------------------------
'
'    - ChangeFileAttributes (pathFilename$ As String, Attributes As String) As Integer
'
'       - attributes are passed as a String, elements of that string are :
'           "A" for Archive
'           "D" for Directory
'           "H" for Hidden
'           "N" for Normal
'           "R" for Read Only
'           "S" for System
'           "T" for Temporary
'           "C" for Compressed
'           "0" for No Attribute Set (?=N?)
'
'      EXAMPLE :
'      -------
'        ChangeFileAttributes ("c:\myDir\myFile","AR")
'           the attributes of myFile are set to Archive and ReadOnly
'
'       The function returns  1 (True)  if attributes have been changed and 0 if
'       an error has occured.
'
'       Used in the Event OnFileFound with Qdir.pathFilename can change the
'       attributes of all matching files.
'
' ----------------------------------------------------------------------------
'

EXAMPLES

'
' ============================================================================
' QDIR   RAPIDQ EXTENDED COMPONENT       April 2004        By Jacques Philippe
'
'    SEARCH FOR MATCHING FILES IN DIRECTORY AND SUBDIRECTORIES
'    FILTERS ON EXTENSION, MUST_ATTRIBUTES and REJECTED_ATTRIBUTES
'
' CONSOLE TEST PROGRAM                                                 V 1.0.4
' ============================================================================
' Code Common To All Examples
' ---------------------------
'
$INCLUDE "QDir.Inc"
'
Declare Sub ShowFileParamsShortList
Declare Sub ShowFileParamsLongList
Declare Sub ChangeAttributes
'
$ESCAPECHARS ON
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
'
'
'$DEFINE EXAMPLE_1             ' UnComment the example to RUN
'$DEFINE EXAMPLE_2
'$DEFINE EXAMPLE_3
'$DEFINE EXAMPLE_4             ' List Only Directories Without "." and ".."
'
' SHORT DOC  valid for ALL 4 Examples
' ---------
'
' path   : relative to the Application Directory and absolute path are accepted
'          directory separator maybe "\" or "/"
' filter : accept Wild Cards like "dir/*.ba?" ...
'
' rejectedAttribites and mustAttributes maybe any of these letters in ANY
' order "ADHNRSTC0"
'
'
Dim myFile As QFileStream
Dim myDir As QDir
DefInt iCount
'
' ---------------------------------------------------------------------------------
$IFDEF EXAMPLE_1
$UNDEF EXAMPLE_2
$UNDEF EXAMPLE_3
$UNDEF EXAMPLE_4
' ---------------------------------------------------------------------------------
'
'    'EXAMPLE 1      SIMPLE DIR with Event myDir.OnFileFound
'    '---------
    myFile.Open ("dirOut.txt", fmCreate)
        myDir.OnFileFound = ShowFileParamsLongList
        myDir.Dir ("C:/Rapid-Q/*", "D", "A")
        ' all files with archive attribute set in this directory
        ' Directories not listed
        ' Attributes : "ADHNRSTC0"
    myFile.Close
    Print "path    = ";myDir.path
    Print "EXAMPLE 1          FINISHED"
'
' ---------------------------------------------------------------------------------
$ENDIF
' ---------------------------------------------------------------------------------
$IFDEF EXAMPLE_2
$UNDEF EXAMPLE_3
$UNDEF EXAMPLE_4
' ---------------------------------------------------------------------------------
'
    ' EXAMPLE 2     RECURSIVE DIR SEARCH with Event  myDir.OnFileFound
    ' ---------
    iCount = 0
    myFile.Open ("dirOut.txt", fmCreate)
        myDir.OnFileFound = ShowFileParamsShortList
        myDir.Dirs ("c:\\Windows\\*.txt", "D", "")
        ' all files with extention ".txt" in directory Windows and sub directories
        ' Directories not listed
        ' Attributes : "ADHNRSTC0"
    myFile.Close
    Print "path    = ";myDir.path
    Print "EXAMPLE 2          FINISHED"
'
' ---------------------------------------------------------------------------------
$ENDIF
' ---------------------------------------------------------------------------------
$IFDEF EXAMPLE_3
$UNDEF EXAMPLE_4
' ---------------------------------------------------------------------------------
'   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
'   !!!!!!!! WARNING : This will change Selected Files dates !!!!!!!!!
'   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
'   To test this, create a directory c:/tmp/  and copy any file in it
    myFile.Open ("dirOut.txt", fmCreate)
        myDir.OnFileFound = ChangeAttributes
        myDir.Dir ("c:/tmp/*", "D", "")
        myDir.OnFileFound = ShowFileParamsLongList
        myDir.Dir ("c:/tmp/*", "D", "")
    myFile.Close
    Print "path    = ";myDir.path
    Print "EXAMPLE 3          FINISHED"
'
' ---------------------------------------------------------------------------------
$ENDIF
' ---------------------------------------------------------------------------------
$IFDEF EXAMPLE_4
' ---------------------------------------------------------------------------------
'
    ' EXAMPLE 4    List Only the Directories Of Windows without "." and ".."
    ' ---------
    iCount = 0
    myFile.Open ("dirOut.txt", fmCreate)
        myDir.OnFileFound = ShowFileParamsShortList
        myDir.WithDotsDirs = False      ' "." and ".." are not returned (only for version 0.0.4)
'        myDir.Dirs ("c:\\Windows\\*", "", "D")
        myDir.Dirs ("C:\\Music\\*.mp3", "D", "")
        ' all files with extention ".txt" in directory Windowsand sub directories
        ' Directories not listed
        ' Attributes : "ADHNRSTC0"
    myFile.Close
    Print "path    = ";myDir.path
    Print "EXAMPLE 2          FINISHED"
'
' ---------------------------------------------------------------------------------
$ENDIF
' ---------------------------------------------------------------------------------
Goto EXITCONSOLE
' ---------------------------------------------------------------------------------
'
' Redate files to Sat  Jan 01/02/1982 01:02:03
' and set the archive, readonly and compressed attributes
Sub ChangeAttributes
        myDir.ChangeFileDateAndTime (myDir.pathFilename, 1982, 1, 2, 1, 2, 3, "cre acc wri")
        myDir.ChangeFileAttributes (myDir.pathFileName, "ARC")
End Sub
'
' Print Routines
' -------------
Sub ShowFileParamsShortList
    DefStr sLine
    sLine = Space$(9)
    With myDir
        sLine = Replace$ (sLine, .AttributesAsString, 1)
        sLine = sLine &  .pathFileName & "  " & StrF$(.Size,ffFixed, 18, 0)
        Print sline
        myFile.WriteLine (sLine)
    End With
End Sub
'
Sub ShowFileParamsLongList
    DefStr sLine
    With myDir
        sLine = ""
        sLine =         "\n          FileName = " & .fileName
        sLine = sLine & "\n           DosName = " & .dosFileName
        sLine = sLine & "\n            path\\ = " & .path
        sLine = sLine & "\n    path\\fileName = " & .pathFileName
        sLine = sLine & "\n              Size = " & Strf$(.Size, ffFixed, 18, 0)
        sLine = sLine & "\n         Attributs = " & Str$(.Attributes)
        sLine = sLine & "\n     Attr_AsString = " & .AttributesAsString
        sLine = sLine & "\n      CreationTime = " & Strf$(.creation.DateTime, ffFixed, 18, 0)
        sLine = sLine & "\n                or = " & .creation.strDayOfWeek & " " & .creation.strMonthOfYear & " " & .creation.date _
                                                        & " " & .creation.time & " WeekDay#=" & .creation.nWeekDay
        sLine = sLine & "\n    LastAccessTime = " & Strf$(.lastAccess.DateTime, ffFixed, 18, 0)
        sLine = sLine & "\n                or = " & .lastAccess.strDayOfWeek & " " & .lastAccess.strMonthOfYear & " " & .lastAccess.date _
                                                        & " " & .lastAccess.time & " WeekDay#=" & .lastAccess.nWeekDay
        sLine = sLine & "\n     LastWriteTime = " & Strf$(.DateTime, ffFixed, 18, 0)
        sLine = sLine & "\n                or = " & .strDayOfWeek & " " & .strMonthOfYear & " " & .date _
                                                        & " " & .time & " WeekDay#=" & .lastWrite.nWeekDay
        sLine = sLine & "\n              Time = " & .Time
        sLine = sLine & "\n              Date = " & .date
        sLine = sLine & "\n            DateEU = " & .dateEU
        sLine = sLine & "\n         DateAlpha = " & .dateAlpha
        sLine = sLine & "\n       DateAlphaEU = " & .dateAlphaEU
        Print sline
        myFile.WriteLine (sLine)
    End With
End sub
' ---------------------------------------------------------------------------------
' EXIT CONSOLE
' ------------
EXITCONSOLE:
DefStr sExit
Input "\n\n                    CR to QUIT \n\n", sExit
Application.Terminate
End
' ---------------------------------------------------------------------------------
'


QDOCKFORM

Rapid-Q Documentation by William Yu (c)1999-2000 - Additional by Ben Laws (c) 2004 Appendix A: QDOCKFORM

QDOCKFORM Component

INCLUDED IN RAPIDQ2.INC
QDockForm is a similar to QForm, however there is one main difference... This one can dock. It is more a QPanel when it is docked (which is what this type extends). Basically, you place this component (better using 'align') on the main form. You will only be able to dock this form in its original location, and using the style property you can tell it to dock wherever it's opposite to, or a location of your choice. Do not use this as your main form - it will not work because this type was derived from QPANEL (And obviously you can't use QPANEL as a main form) Also, (almost) all unused properties, methods and events have been disabled for the main panel, so you wouldn't even know it was a panel. See limitations.

QDockForm Properties
Field | Type | Read/Write | Default Value
Align | INTEGER | RW | 3
You should use this property over the left and top properties
AltAlign | INTEGER | RW | 0
If 'style' is 1 then specify the alignment of the second location the form can dock at.
If AltAlign is 0 then by default, the opposite alignment of the original position is used
(e.g. original = top, alternative = bottom)
AltDock | INTEGER | R | 0
Returns TRUE if the form is docked in the alternative position, otherwise FALSE
AltPanel.Parent | QFORM | RW | This
This must be set to where you would like your form's alternative docking location to be.
CanClose | INTEGER | RW | False
TRUE if the form can close (has a close button at the top right), otherwise FALSE
Canvas | QCANVAS | RW
Use for drawing on the panel - use with the OnPaint event
Caption | STRING | RW
Caption is the text that appears as the title of your dockable form.
It will only appear depending on the docked and undocked styles you use
Client | QPANEL | RW
You should always use this panel for placing components inside the form. e.g.
    CREATE Properties AS QDOCKFORM
        ...
        CREATE PropertiesGrid AS QSTRINGGRID
            'This is where you set the parent to be the properties client panel
            Parent = Properties.Client

        END CREATE
    END CREATE

You can also change the panel, like a regular QPANEL
Closed | INTEGER | R | False
Returns TRUE if the form is closed, otherwise False
Docked | INTEGER | R | True
Returns TRUE if the form is currently docked. The form is always docked on creation
DockStyle | INTEGER | RW | 0
Changes the appearance of the form.
Use styles 0 to 6, and 10. 7 to 9 are not used. They are for making your own toolbar styles. Anything past 10 is for making regular styles
This style is seen when the form is docked
DragCursor | INTEGER | RW | -21
The cursor to be displayed when it is over the draggable section of the form
Font | QFONT | W
Height | INTEGER | RW
Get or set the form's vertical size (in pixels). You should use align instead
Left | INTEGER | RW | 0
Specifies the left edge of the form relative to the desktop screen. You should use align instead
Locked | INTEGER | RW | False
Set to TRUE if the form is locked in its current docking position (i.e. cannot be moved), otherwise FALSE. Locking the form when it is not docked will result in the form not being able to move.
Parent | QFORM | W
Sizeable | INTEGER | RW | False
Specifies whether the form can be resized or not when undocked.
Using this is not advisable as there is no way of setting the minimum size of the form - yet.
ST1_TitleBackground | INTEGER | RW | 0
Color of the form's caption background for DockStyle 1 and UndockStyle 1
Style | INTEGER | RW | 0
0 = The form will dock only where it is placed
1 = The form will dock where it is placed, and in another location specified by 'AltAlign'
TitleColor | INTEGER | RW | 0
Color of the form's caption text (if any)
Top | INTEGER | RW | 0
UndockedForm.Handle | INTEGER | R
Get the form's handle for WinAPI calls.
UndockedForm.Parent | INTEGER | W | This
Set the parent when undocked
UndockedHeight | INTEGER | RW | 400
Height of form when undocked - overridden when sized.
UndockedWidth | INTEGER | RW | 170
UndockStyle | INTEGER | RW | 0
Changes the appearance of the form.
Use styles 1 to 5, and 10. 6 to 9 are not used. They are for making your own toolbar styles. Anything past 10 is for making regular styles
This style is seen when the form is undocked
Width | INTEGER | RW | 320
Visible | INTEGER | RW
Do not use when the form is undocked

QDockForm Methods
Method | Type | Description | Params
Close | SUB | Close the form | 0
Dock SUB (Dock AS INTEGER) 0 = Undock
1 = Dock at original position
2 = Dock at alternative (or original if not possible)

This method is also used to show a closed form. 		1

QDockForm Events
Event | Type | Occurs when... | Params
OnDock | SUB (Docked AS INTEGER, Alt AS INTEGER) | 'Docked' is true if the form was docked, otherwise false. 'Alt' is true if it was docked in the alternative location | 2
OnPaint | VOID | Form requires repainting. Use Canvas for drawing | 0
OnClose | VOID | Form is closing | 0

QDockForm Examples
$INCLUDE "RAPIDQ2.INC"		'from "QDOCKFORM.inc"

DECLARE SUB SortStatusBar (Docked AS INTEGER, Alt AS INTEGER)
DECLARE SUB AddText
DECLARE SUB DockLeft
DECLARE SUB DockRight
DECLARE SUB Undock
DECLARE SUB Selected
DECLARE SUB ShowForm
DECLARE SUB FormClosed

CREATE Form AS QFORM
    Width = 640
    Height = 480
    Center
    Caption = "Docking windows example"
    CREATE MainEdit AS QRICHEDIT
        Align = 5
        Visible = 1
    END CREATE
    CREATE EventsPanel AS QDOCKFORM
        UndockedForm.Parent = Form
        Align = 4
        DockStyle = 10
        UndockedWidth = EventsPanel.Width
        AltPanel.Parent = Form
        Style = 1
        Caption = "Events - Locked"
        Client.BevelOuter = 0
        Canvas.Font.Name = "Tahoma"
        Locked = 1
        CREATE StringGrid AS QSTRINGGRID
            Parent = EventsPanel.Client
            Align = 5
            ColCount = 2
            ColWidths(0) = EventsPanel.Client.Width / 2
            ColWidths(1) = EventsPanel.Client.Width / 2
            RowCount = 10
        END CREATE
    END CREATE
    CREATE ProjPanel AS QDOCKFORM
        AltPanel.Parent = Form
        'AltAlign = 4
        UndockedForm.Parent = Form
        Caption = "Project"
        Align = 3
        DockStyle = 1
        UnDockStyle = 1
        Style = 1
        Client.BevelOuter = 0
        Canvas.Font.Name = "Tahoma"
        UndockedWidth = ProjPanel.Width
        CanClose = 1
        OnClose = FormClosed
        CREATE ComponentsPanel AS QPANEL
            Parent = ProjPanel.Client
            Align = 5
            CREATE AddTextButton AS QBUTTON
                Left = 50
                Top = 150
                Caption = "Add Text"
                OnClick = AddText
            END CREATE
            CREATE DockLeftButton AS QBUTTON
                Top = 30
                Width = 70
                Left = 10
                Caption = "Dock Left"
                OnClick = DockLeft
            END CREATE
            CREATE DockRightButton AS QBUTTON
                Top = 30
                Width = 70
                Left = ComponentsPanel.Width - DockRightButton.Width - 20
                Caption = "Dock Right"
                OnClick = DockRight
            END CREATE
            CREATE UndockButton AS QBUTTON
                Left = (ComponentsPanel.Width - UndockButton.Width) / 2 - 10
                Top = 70
                Caption = "Undock"
                OnClick = Undock
            END CREATE
        END CREATE
    END CREATE
    CREATE ToolbarBox AS QDOCKFORM
        UndockedForm.Parent = Form
        Align = 1
        Height = 31
        DockStyle = 6
        UnDockStyle = 6
        UndockedWidth = 600
        UndockedHeight = 55
        AltPanel.Parent = Form
        Style = 1
        Caption = "Toolbar Example"
        CREATE Label AS QLABEL
            Parent = ToolbarBox.Client
            Caption = "Select a style:"
            Autosize = 1
            Top = 5
        END CREATE
        CREATE List AS QCOMBOBOX
            Parent = ToolbarBox.Client
            Left = 90
            Top = 2
            AddItems("0  - Striped","1  - Office XP","2  - Grips","3  - Striped (toolbar)","4  - Grips (toolbar)","5  - 3D (toolbar)","6  - Striped Horizontal (toolbar)","10 - Regular")
            ItemIndex = 1
            OnChange = Selected
        END CREATE
        CREATE ShowButton AS QBUTTON
            Parent = ToolbarBox.Client
            Top = 0
            Left = 290
            Caption = "Show Form"
            Enabled = 0
            OnClick = ShowForm
        END CREATE
    END CREATE
    CREATE StatusBarBox AS QDOCKFORM
        UndockedForm.Parent = Form
        Align = 2
        Height = 25
        DockStyle = 6
        UnDockStyle = 6
        UndockedWidth = 600
        UndockedHeight = 49
        AltPanel.Parent = Form
        Style = 1
        OnDock = SortStatusBar
        Caption = "Status Bar"
        CREATE SB AS QSTATUSBAR
            Parent = StatusBarBox.Client
            Align = 5
            SizeGrip = 0
            AddPanels("This Statusbar can be moved!", "I'm Docked at the Bottom!")
            Panel(0).Width = 160
        END CREATE
    END CREATE
END CREATE

Form.ShowModal

SUB SortStatusBar (Docked AS INTEGER, Alt AS INTEGER)
    IF Docked = 0 THEN
        SB.Panel(1).Caption = "I'm Not Docked Anywhere!"
        EXIT SUB
    END IF
    IF Docked = 1 THEN
        SB.Panel(1).Caption = "I'm Docked at the " + IIF(Alt = 1, "Top", "Bottom")
    END IF
END SUB

SUB AddText
    MainEdit.AddString("You just added some text")
END SUB

SUB DockLeft
    ProjPanel.Dock(1)
END SUB

SUB DockRight
    ProjPanel.Dock(2)
END SUB

SUB Undock
    ProjPanel.Dock(0)
END SUB

SUB Selected
    ProjPanel.DockStyle = VAL(LEFT$(List.Item(List.ItemIndex), 2))
    ProjPanel.UnDockStyle = VAL(LEFT$(List.Item(List.ItemIndex), 2))
    ProjPanel.Canvas.Repaint
END SUB

SUB ShowForm
    ShowButton.Enabled = 0
    ProjPanel.Dock(ProjPanel.AltDock + 1)

END SUB

SUB FormClosed
    ShowButton.Enabled = 1
END SUB
Contents


QDriveCombobox

Documentation component by D.Glodt (c)2000-2001 Appendix A: QDriveCombobox

QDriveCombobox Component

QDriveCombobox is a component as QCombobox with filling of present drivers.

QDriveCombobox Properties
Field | Type | R/W | Default

QDriveCombobox Methods
Method | Type | Description | Params
GetDrives | SUB | Fill the box of present drivers | 0

QDriveCombobox Events
Event | Type | Occurs when... | Params

QDriveCombobox Examples

$INCLUDE <QDriveComboBox.inc>
DECLARE SUB ChangeDrive

Dim Form as qform
Dim dbox as QDriveComboBox
dbox.parent = Form
dbox.GetDrives
dbox.OnChange = ChangeDrive
Form.ShowModal

SUB ChangeDrive
ChDir(dbox.Item(ItemIndex) - "[" - "]")
END SUB


QFILEDIALOG

Documentation by John Kelly QFILEDIALOG

QFILEDIALOG Component

This is a new custom component in RAPIDQ2.INC. Creates an Open or Save Dialog box that is set by Mode property. The dialog box is sizeable and allows selection of multiple files. If you use it to save a file it will ask if you want to overwrite the existing file. There will be icons for quick links to the desktop, network locations, and myDocuments folder. See limitations.

QFileDialog Properties
Field | Type | R/W | Default
Caption | STRING | RW | "Open"
DefaultExt STRING
Default extension that will be automatically added to filename if user doesn't include it. 		RW
FileName | STRING Returns file name with path information | RW
FileTitle | STRING Returns the file name without path information | R
Files() | Array of STRING If Mode = fdOpen,and MultiSelect = True,then the array has a list of selected files. Files(0) is the directory, Files(1) is the first file name without the path | RW | All Files|*.*
Filter | STRING | RW | All Files|*.*
FilterIndex | INTEGER 1st index is 0 | RW | 1
InitialDir | STRING | RW
Mode INTEGER sets whether the dialog box will be an Open dialog or Save.
Valid arguments:
fdOpen = 0
fdSave = 1 		RW fdOpen
MultiSelect | INTEGER If set to true and Mode = fdOpen, then the user can select up to 256 files | RW | False
NoChangeDir | INTEGER If set to true the QFileDialog will not change the current directory | RW | False
Parent | LONG This is the parent form handle, can be null | RW | Null
SelCount INTEGER
Number of files the user selected when Multiselect = true 		R 0
WarnIfOverWrite INTEGER
Flag for warning if you want to overwrite the file when mode is fdSave 		RW True

QFileDialog Methods
Method | Type | Description | Params
Execute | FUNCTION | Returns TRUE (user picked files) or FALSE (user picked Cancel) | 0

QFileDialog Examples
$INCLUDE "RapidQ2.inc"
DIM i as integer
DIM fDialog as qfiledialog
fDialog.Caption = "QfileDialog test"
fDialog.FileName= "test.txt"
fDialog.InitialDir = "C:\RapidQ"
fDialog.MultiSelect = 1
IF fDialog.Execute THEN
  IF fDialog.MultiSelect THEN
     for i = 0 to fDialog.SelCount
        ShowMessage fDialog.Files(i)	'item #0 is the directory
     next i
  ELSE
     ShowMessage "file name & path =" + fDialog.FileName
     ShowMessage "file name no path =" + fDialog.FileTitle
  END IF
END IF


QFormEX

Rapid-Q Documentation by William Yu (c)1999-2000, Appended by John Kelly QFORMEX

QFormEx Component

INCLUDED IN RAPIDQ2.INC
QFormEx is just like a QForm but adds more functions like placing icons in the application tray, animating tray icons, drag and drop files, auto minimize the task bar, MouseWheel support, and Focus events. See limitations.

QForm Properties
Field | Type | R/W | Default
DragEnable | BOOLEAN | RW | False
Accept drop file in the application window
DragZone | QRECT | RW
Zone of drop file
FormStyle | INTEGER | RW | fsNormal
Style fsStayOnTop is now supported in Win2000/XP, limited in Win98
TrayICO | QIMAGELIST | RW
See Qimagelist documentation. This loads either BMP or ICON files or handles to your tray icons
TrayICOHint | STRING | RW
See Qimagelist documentation. This loads either BMP or ICON files or handles to your tray icons
TrayICOHint | STRING | RW
TrayIconIndex | INTEGER | RW
If you have loaded TrayICO with more than one image, you can set which one should be visible in the tray
TrayIconUpdate | INTEGER | RW
If you have more than one imaged loaded into TrayICO, this will set the time between animation of the trayIcons

QFormEx Methods
Method | Type | Description | Params
AddTrayIcon | SUB | Add application icon to the Desktop tray | 0
DelTrayIcon | SUB | Delete application icon from the Desktop tray. | 0
DeskBar | SUB | Make application minimize to task bar (obsolete ***) | 0
QformEx automatically minimizes to the TaskBar

QFormEx Events (These Events take over the Form.WndProc, but should pass params. You are also allowed one WndProc)
Event | Type | Occurs when... | Params
OnDrag | (File$) | Drop file | 1
OnLostFocus | SUB () | User clicks on other application (form loses focus) | 0
OnGetFocus | SUB () | User clicks on this application (form gets focus) | 0
OnTrayClick | SUB () | Click right button on icon application of tool bar | 0
OnTrayDblClick | SUB () | Double click on left button on icon application of tool bar | 0
OnMinimise | SUB () | Window minimized | 0
OnMouseWheel | SUB (Rotation%, X%, Y%, Shift%) | Mouse wheel is rotated | 4
Details:
Rotation = 1 or -1, at mouse position X,Y on the screen
Shift% = CTRL or SHIFT key , or left, right or center button down
The Form must have the Focus in order for OnMouseWheel to respond,

QFormEx Example 1 (Get / Lost focus)

DECLARE SUB ShowOtherForm
DECLARE SUB CloseOtherForm

DIM Form2 AS QFORMex
    Form2.Caption = "Hey, get back to work!"
    Form2.Width = 500
CREATE Form AS QFORMex
  OnLostFocus = ShowOtherForm
  OnGetFocus = CloseOtherForm
END CREATE
Form.ShowModal

SUB ShowOtherForm
  Form2.Show
END SUB

SUB CloseOtherForm
  Form2.Close
END SUB

QFormEx Example 2 (Tray icon launcher)

$TYPECHECK ON
$INCLUDE "RAPIDQ2.INC"
declare Sub depose(file as string)
declare Sub testWheel(MouseRotation AS INTEGER, Xpos AS LONG, Ypos AS LONG, Shift AS INTEGER)

$RESOURCE myico as "c:\rapidq\icon\icon1.ico"
$RESOURCE myico2 as "c:\rapidq\icon\icon2.ico"
$RESOURCE myico3 as "c:\rapidq\icon\icon3.ico"

CREATE Form AS QFormEx
    width=300
    Height=200
    Caption="Drag and drop files"
    center
    DragEnable=true
    OnDrag=Depose
    OnMouseWheel = testWheel
    TrayIconHint = "RapidQ2 example"
    TrayIco.AddICOHandle myico
    TrayIco.AddICOHandle myico2
    TrayIco.AddICOHandle myico3
    TrayIconUpdate = 2000
'    TrayIco.AddICOFile "c:\rapidq\icon\myother.ico" 'can do this
    AddTrayIcon     'this goes last
  CREATE Listbox as QLISTBOX
    Width=150
    height=100
  END CREATE
  CREATE MyButton as QBUTTON
    Left = 155
    Width=130
    height=30
    Caption="Click here to focus form"
  END CREATE
END CREATE

form.DragZone.Left=listbox.left
form.DragZone.Top=listbox.Top
form.DragZone.Right=listbox.Width
form.DragZone.Bottom=listbox.Height
Form.ShowModal

Sub Depose(file as string)
  ListBox.AddItems(file)
End Sub

Sub testWheel(MouseRotation AS INTEGER, Xpos AS LONG, Ypos AS LONG, Shift AS INTEGER)
  Showmessage "mouse rotated at " + str$(xPos) + "  " + str$(yPos) + "  " + str$(Shift)
end sub

QFormEx Example 3 (Icon menu in Windows Tray)

$TYPECHECK ON
$INCLUDE "RAPIDQ2.INC"
declare sub close
declare sub show
declare sub menu
declare sub hide
CREATE Form AS QFormEx
  OnClose=Close
  OnTrayDblClick=Show
  OnTrayClick=Menu
  OnMinimise=Hide
END CREATE
CREATE PopUpMenu AS QPOPUPMENU
    Alignment = 1
    CREATE Open AS QMENUITEM
        Caption = "&Open"
        OnClick =show
    END CREATE
    CREATE Seperator AS QMENUITEM
        Caption = "-"
    END CREATE
    CREATE MeExit AS QMENUITEM
        Caption = "&Exit"
        OnClick =Close
    END CREATE
END CREATE
form.addtrayicon
form.showmodal
sub close
  form.deltrayicon
  Application.terminate
end sub
sub show
  form.visible=true
end sub
sub Hide
  form.visible=false
end sub
sub menu
  popupmenu.popup(screen.MouseX,screen.MouseY)
end sub

QFormEx Example 4(toggle StayOnTop)

$INCLUDE "rapidq2.inc"
declare SUB ToggleStayOnTop

CREATE Form AS QFORMex
    Top = 100
    Left = 500
    Height = 200
    Width = 120
   CREATE ShowTopWinChk AS QCHECKBOX
     OnClick = ToggleStayOnTop
   END CREATE
END CREATE
Form.ShowModal

SUB ToggleStayOnTop
 If ShowTopWinChk.Checked THEN
     Form.FormStyle = fsStayontop
 else
    Form.FormStyle = fsNormal
 end if
END SUB


QFormMDI

Documentation component by D.Glodt (c)2000-2003, appended by John Kelly Appendix A: QFormMDI

QFormMDI Component

INCLUDED IN RAPIDQ2.INC
QFormMDI is identical to a QForm but with Multi Document Interface (like WORD or EXCEL that has forms inside a form. Each 'child' form can have one RapidQ component (e.g., Qpanel, QRichEdit, QScrollBox...). Before you add the component to the Child Form, first set Visible= False then set the parent property. Separate Menus for each Child form is not supported. The components can be declared as variables array or to be of different type for each window child MDI. See limitations.

QFormMDI Property
Field | Type | R/W | Default
ChildCaption | STRING | R/W |
 | Text of title bar of active child window
ChildHandle | LONG | R |
 | Handle of active child window
ChildLeft | SHORT | R/W |
 | Left position of active child window |  |
ChildTop | SHORT | R/W |
 | Top position of active child window |  |
ChildWidth | SHORT | R/W |
 | Width of active child window |  |
ChildHeight | SHORT | R/W |
 | Height of active child window |  |
ChildMax | INTEGER | R/W | 1024
 | Maximum child window |  |
ChildCount | INTEGER | R |
 | Child window number |  |
ChildIcon | LONG | R/W |
 | Icon handle for child window |  |
ChildState | INTEGER | R/W |
 | State of active child window,could be wsNormal,wsMinimized,wsMaximized |  | wsNormal
MDIMenu | LONG | R/W |
 | Sub menu handle to insert the child window name |  |
ComponentIndex | INTEGER | R |
 | Index of associated component to the active child window |  |
ChildResult | INTEGER | R/W | False
 | Result of the action of closing of a child window, the value is has true during closing and can be put at false at the time of a OnChildClose event to cancel closing if the application requires a safeguard |  |

QFormMDI Methods
Method | Type | Description | Params
AddChild | SUB(handle&,Title$,index&,left%, top%,width%,height%,DefaultSize&) | Add a child window , handle& is the handle component associated the child window , Title$ is the text of the title bar of the child window , index& is the number of the associated component, DefaultSize& indicates if one uses dimensions by default. | 8
CloseChild | SUB | Close the active child window | 0
CloseAllChild | SUB | Close all the child window | 0
CascadeChild | SUB | Resize all the child window on cascade | 0
SetHorzChild | SUB | Resize all the child window on horizontal | 0
SetVertChild | SUB | Resize all the child window on vertical | 0
IconArrangeChild | SUB | Arrange all the child window on icon | 0
MinimizeAllChild | SUB | Minimize all the child window | 0
MaximizeAllChild | SUB | Maximize all the child window | 0
RestoreChild | SUB | Restore the child window |
ActiveNextChild | SUB | Activate the next child window | 0
ActivePreviousChild | SUB | Activate the previous child window | 0
GetChild | FUNCTION(Title$)& | Return the index of child window corresponding to the title Title$ | 1
ChildExist | FUNCTION(Title$)& | Return the existence of a child window by his title | 1
ActiveChild | SUB(Index&) | Activate the child window identified by index& | 1
FreeChild | FUNCTION(handle&)& | Return the state associated from a component to a child window, return True if the component identified by handle& is not associated to a child window | 1
SetDeskBar | SUB | The application will be in the task bar during its reduction | 0

QFormMDI Events
Event | Type | Occurs when... | Params
OnChildClose | (handleChild&,index&,titleChild$) | Closing child window, the parameter index& is the index of the associated component | 3
OnChildActive | (handleChild&,index&,titleChild$) | Activation child window | 3
OnChildResize | (handleChild&,index&,titleChild$) | Resize child window | 3

QFormMDI Example1

$TYPECHECK ON
$include "rapidq2.inc"
DECLARE SUB mnuNew_Click
DECLARE SUB mnuOpen_Click
DECLARE SUB mnuClose_Click
DECLARE SUB mnuCloseAll_Click
DECLARE SUB mnuNext_Click
DECLARE SUB mnuPrevious_Click
DECLARE SUB mnuCascade_Click
DECLARE SUB mnuTileHorz_Click
DECLARE SUB mnuTileVert_Click
DECLARE SUB mnuArrange_Click
DECLARE SUB mnuMinAll_Click
DECLARE SUB mnuMaxAll_Click
DECLARE SUB mnuRestAll_Click
DECLARE SUB mnuCut_Click
DECLARE SUB mnuCopy_Click
DECLARE SUB mnuPaste_Click
DECLARE SUB mnuSelectAll_Click
DECLARE SUB show
DECLARE SUB close
DECLARE SUB KeyDown(Key as word,Shift as integer)
DECLARE SUB infos(handleChild as long,index as integer,titleChild as string)
DECLARE SUB CloseMDI(handleChild as long,index as integer,titleChild as string)
dim j as integer
dim flag as integer
dim UntitledCount as integer
DIM Dumm as QFORMex
Dumm.FormStyle = fsStayOnTop
CREATE Form AS QFormMDI
  Caption = "MDI Parent"
  Center
  Width=Screen.Width/2*1.5
  Height=Screen.Height/2*1.5
  CREATE mnuMain AS QMAINMENU
    CREATE mnuFile AS QMENUITEM
      Caption="&File"
      CREATE mnuNew AS QMENUITEM
        Caption="&New"
        OnClick=mnuNew_Click
      END CREATE
      CREATE mnuOpen AS QMENUITEM
        Caption="&Open"
        OnClick=mnuOpen_Click
      END CREATE
      CREATE mnuClose AS QMENUITEM
        Caption="&Close"
        OnClick=mnuClose_Click
      END CREATE
      CREATE mnuCloseAll AS QMENUITEM
        Caption="Close &All"
        OnClick=mnuCloseAll_Click
      END CREATE
      CREATE mnuNext AS QMENUITEM
        Caption="Next"
        OnClick=mnuNext_Click
      END CREATE
      CREATE mnuPrevious AS QMENUITEM
        Caption="Previous"
        OnClick=mnuPrevious_Click
      END CREATE
    END CREATE
    CREATE mnuEdit as QMENUITEM
      Caption="&Edit"
      CREATE mnuCut as QMENUITEM
        Caption="&Cut"
        ShortCut="CTRL+X"
        OnClick=mnuCut_Click
      END CREATE
      CREATE mnuCopy as QMENUITEM
        Caption="&Copy"
        ShortCut="CTRL+C"
        OnClick=mnuCopy_Click
      END CREATE
      CREATE mnuPaste as QMENUITEM
        Caption="&Paste"
        ShortCut="CTRL+V"
        OnClick=mnuPaste_Click
      END CREATE
      CREATE Sep2 as QMENUITEM
        Caption="-"
      END CREATE
      CREATE mnuSelectAll as QMENUITEM
        Caption="&Select all"
        ShortCut="CTRL+A"
        OnClick=mnuSelectAll_Click
      END CREATE
    END CREATE
    CREATE mnuWindows AS QMENUITEM
      Caption="&Windows"
      CREATE mnuCascade AS QMENUITEM
        Caption="&Cascade"
        OnClick=mnuCascade_Click
      END CREATE
      CREATE mnuTileHorz AS QMENUITEM
        Caption="Tile &Horizontally"
        OnClick=mnuTileHorz_Click
      END CREATE
      CREATE mnuTileVert AS QMENUITEM
        Caption="Tile &Vertically"
        OnClick=mnuTileVert_Click
      END CREATE
      CREATE mnuArrange AS QMENUITEM
        Caption="&Arrange Icons"
        OnClick=mnuArrange_Click
      END CREATE
      CREATE mnuMinAll AS QMENUITEM
        Caption="&Minimize All"
        OnClick=mnuMinAll_Click
      END CREATE
      CREATE mnuMaxAll AS QMENUITEM
        Caption="Ma&ximixe All"
        OnClick=mnuMaxAll_Click
      END CREATE
      CREATE mnuRestAll AS QMENUITEM
        Caption="&Restore All"
        OnClick=mnuRestAll_Click
      END CREATE
    END CREATE
  END CREATE
  CREATE Stat AS QSTATUSBAR
  END CREATE
  KeyPreview=true
  MdiMenu=mnuWindows.handle
  ChildMax=20
  OnChildClose=CloseMDI
  OnChildActive=infos
  OnClose=Close
  OnPaint=Show
  OnKeyDown=KeyDown
END CREATE
' Components for MDI
dim edit(20) as qrichedit
dim handleControl as long
for j=0 to 20
  edit(j).parent=form
  edit(j).visible=false 'must be no visible
  edit(j).ScrollBars=3
  edit(j).WordWrap=false
next j
Form.SetDeskBar
Form.ShowModal
'Find free component for MDI
Function GetCtl() as integer
  dim find as integer
  dim h as integer
  find=0
  for j=0 to 20
    if form.FreeChild(edit(j).handle) and find=0 then
      h=j
      find=1
    end if
  next j
  result=h
End Function
SUB mnuNew_Click
  dim index as integer
dumm.Show
  if form.ChildCount<form.ChildMax then
    index=GetCtl()
    form.AddChild(edit(index).handle,"Untitled "+STR$(UntitledCount+1),index,0,0,0,0,true)
    UntitledCount++
  end if
END SUB
SUB mnuOpen_Click
  dim index as integer
  DIM OD AS QOPENDIALOG
  OD.Filter="Text file(*.txt)|*.txt"
  if form.ChildCount<form.ChildMax then
    IF OD.Execute THEN
      IF form.ChildExist(OD.FileName) THEN
        form.ActiveChild(form.GetChild(OD.FileName))
        EXIT SUB
      END IF
      index=GetCtl()
      edit(index).loadfromfile(OD.FileName)
      edit(index).modified=false
      form.AddChild(edit(index).handle,OD.FileName,index,0,0,0,0,True)
      UntitledCount++
    END IF
  end if
END SUB
SUB CloseMDI(handleChild as long,index as integer,titleChild as string)
  dim msgButton as integer
  if edit(index).modified then
    msgButton=MessageBox("Fermer fenetre?",titleChild,36)
    if msgButton=6 then
      edit(index).modified=false
      edit(index).clear
      form.ChildResult=true
    else
      form.ChildResult=false
    end if
  else
    edit(index).clear
  end if
END SUB
SUB mnuClose_Click
  form.CloseChild
  if form.ChildCount=0 then stat.simpleText=""
END SUB
SUB mnuCloseAll_Click
  form.CloseAllChild
  if form.ChildCount=0 then stat.simpleText=""
END SUB
SUB mnuNext_Click
  form.ActiveNextChild
END SUB
SUB mnuPrevious_Click
  form.ActivePreviousChild
END SUB
SUB mnuCascade_Click
  form.CascadeChild
END SUB
SUB mnuTileHorz_Click
  form.SetHorzChild
END SUB
SUB mnuTileVert_Click
  form.SetVertChild
END SUB
SUB mnuArrange_Click
  form.IconArrangeChild
END SUB
SUB mnuMinAll_Click
  form.MinimizeAllChild
END SUB
SUB mnuMaxAll_Click
  form.MaximizeAllChild
END SUB
SUB mnuRestAll_Click
  form.RestoreChild
END SUB
SUB mnuCut_Click
  if form.ChildCount>0 then
    edit(form.componentIndex).CutToClipBoard
  end if
END SUB
SUB mnuCopy_Click
  if form.ChildCount>0 then
    edit(form.componentIndex).CopyToClipBoard
  end if
END SUB

SUB mnuPaste_Click
  if form.ChildCount>0 then
    edit(form.componentIndex).PasteFromClipBoard
  end if
END SUB

SUB mnuSelectAll_Click
  if form.ChildCount>0 then
    edit(form.componentIndex).SelectAll
  end if
END SUB

SUB infos(handleChild as long,index as integer,titleChild as string)
  stat.simpleText=titleChild
End Sub

SUB show
  dim index as integer
  if flag=false then
    if form.ChildCount<form.ChildMax then
      index=GetCtl()
      form.AddChild(edit(index).handle,"Untitled "+STR$(UntitledCount+1),index,0,0,0,0,true)
      UntitledCount++
    end if
    flag=true
  end if
END SUB

Sub Close
  form.CloseAllChild
  application.terminate
End Sub

Sub KeyDown(key as word,shift as integer)
  'next child with Ctrl+F6
  if shift=CtrlDown and key=VK_F6 then form.ActiveNextChild
end sub

QFormMDI Example2
$TYPECHECK ON
$OPTION ICON "photo.ico"
$include "rapidq2.inc"
$Include "QICON.inc"
DECLARE SUB mnuNew_Click
DECLARE SUB mnuOpen_Click
DECLARE SUB mnuClose_Click
DECLARE SUB mnuCloseAll_Click
DECLARE SUB mnuNext_Click
DECLARE SUB mnuPrevious_Click
DECLARE SUB mnuCascade_Click
DECLARE SUB mnuTileHorz_Click
DECLARE SUB mnuTileVert_Click
DECLARE SUB mnuArrange_Click
DECLARE SUB mnuMinAll_Click
DECLARE SUB mnuMaxAll_Click
DECLARE SUB mnuRestAll_Click
DECLARE SUB show
DECLARE SUB close
DECLARE SUB KeyDown(Key as word,Shift as integer)
DECLARE SUB infos(handleChild as long,index as integer,titleChild as string)
DECLARE SUB CloseMDI(handleChild as long,index as integer,titleChild as string)
dim j as integer
dim flag as integer
dim UntitledCount as integer
dim icon as Qicon
    icon.associated=true
    icon.filename=command$(0)
CREATE Form AS QFormMDI
  Caption="MDI Parent"
  Center
  Width=Screen.Width/2*1.5
  Height=Screen.Height/2*1.5
  ChildIcon=icon.handle
  CREATE panel as QPANEL
    align=1
    height=35
    bevelOuter=0
    CREATE bt1 as QBUTTON
      top=5
      left=5
      width=25
      Hint="Prévious"
      ShowHint=true
      caption="<<"
      OnClick=mnuPrevious_Click
    END CREATE
    CREATE bt2 as QBUTTON
      top=5
      left=35
      width=25
      Hint="Next"
      ShowHint=true
      caption=">>"
      OnClick=mnuNext_Click
    END CREATE
  END CREATE
  CREATE mnuMain AS QMAINMENU
    CREATE mnuFile AS QMENUITEM
      Caption="&File"
      CREATE mnuNew AS QMENUITEM
        Caption="&New"
        OnClick=mnuNew_Click
      END CREATE
      CREATE mnuOpen AS QMENUITEM
        Caption="&Open"
        OnClick=mnuOpen_Click
      END CREATE
      CREATE mnuClose AS QMENUITEM
        Caption="&Close"
        OnClick=mnuClose_Click
      END CREATE
      CREATE mnuCloseAll AS QMENUITEM
        Caption="Close &All"
        OnClick=mnuCloseAll_Click
      END CREATE
      CREATE mnuNext AS QMENUITEM
        Caption="Next"
        OnClick=mnuNext_Click
      END CREATE
      CREATE mnuPrevious AS QMENUITEM
        Caption="Previous"
        OnClick=mnuPrevious_Click
      END CREATE
    END CREATE
    CREATE mnuWindows AS QMENUITEM
      Caption="&Windows"
      CREATE mnuCascade AS QMENUITEM
        Caption="&Cascade"
        OnClick=mnuCascade_Click
      END CREATE
      CREATE mnuTileHorz AS QMENUITEM
        Caption="Tile &Horizontally"
        OnClick=mnuTileHorz_Click
      END CREATE
      CREATE mnuTileVert AS QMENUITEM
        Caption="Tile &Vertically"
        OnClick=mnuTileVert_Click
      END CREATE
      CREATE mnuArrange AS QMENUITEM
        Caption="&Arrange Icons"
        OnClick=mnuArrange_Click
      END CREATE
      CREATE mnuMinAll AS QMENUITEM
        Caption="&Minimize All"
        OnClick=mnuMinAll_Click
      END CREATE
      CREATE mnuMaxAll AS QMENUITEM
        Caption="Ma&ximixe All"
        OnClick=mnuMaxAll_Click
      END CREATE
      CREATE mnuRestAll AS QMENUITEM
        Caption="&Restore All"
        OnClick=mnuRestAll_Click
      END CREATE
    END CREATE
  END CREATE
  CREATE Stat AS QSTATUSBAR
  END CREATE
  KeyPreview=true
  MdiMenu=mnuWindows.handle
  ChildMax=20
  OnChildClose=CloseMDI
  OnChildActive=infos
  OnClose=Close
  OnKeyDown=KeyDown
END CREATE
'components for MDI
dim edit(20) as qpanel
dim img(20) as qimage
for j=0 to 20
  edit(j).parent=form
  edit(j).visible=false 'must be no visible
  edit(j).bevelOuter=0
  edit(j).color=&hffffff
  img(j).AutoSize=1
  img(j).Parent=edit(j)
next j
Form.SetDeskBar
Form.ShowModal
'Find free component for MDI
Function GetCtl() as integer
  dim find as integer
  dim h as integer
  find=0
  for j=0 to 20
    if form.FreeChild(edit(j).handle) and find=0 then
      h=j
      find=1
    end if
  next j
  result=h
End Function
SUB mnuNew_Click
  dim index as integer
  if form.ChildCount<form.ChildMax then
    index=GetCtl()
    form.AddChild(edit(index).handle,"Untitled "+STR$(UntitledCount+1),index,0,0,0,0,true)
    UntitledCount++
  end if
END SUB
SUB mnuOpen_Click
  dim index as integer
  DIM OD AS QOPENDIALOG
  OD.caption="Load image"
  OD.Filter="Bitmap file(*.bmp)|*.bmp"
  if form.ChildCount<form.ChildMax then
    IF OD.Execute THEN
      IF form.ChildExist(OD.FileName) THEN
        form.ActiveChild(form.GetChild(OD.FileName))
        EXIT SUB
      END IF
      index=GetCtl()
      img(index).bmp=OD.FileName
      form.AddChild(edit(index).handle,OD.FileName,index,0,0,img(index).width+8,img(index).height+27,False)
      UntitledCount++
    END IF
  end if
END SUB
SUB CloseMDI(handleChild as long,index as integer,titleChild as string)
  img(index).handle=0
END SUB
SUB mnuClose_Click
  form.CloseChild
  if form.ChildCount=0 then stat.simpleText=""
END SUB
SUB mnuCloseAll_Click
  form.CloseAllChild
  if form.ChildCount=0 then stat.simpleText=""
END SUB
SUB mnuNext_Click
  form.ActiveNextChild
END SUB
SUB mnuPrevious_Click
  form.ActivePreviousChild
END SUB
SUB mnuCascade_Click
  form.CascadeChild
END SUB
SUB mnuTileHorz_Click
  form.SetHorzChild
END SUB
SUB mnuTileVert_Click
  form.SetVertChild
END SUB
SUB mnuArrange_Click
  form.IconArrangeChild
END SUB
SUB mnuMinAll_Click
  form.MinimizeAllChild
END SUB
SUB mnuMaxAll_Click
  form.MaximizeAllChild
END SUB
SUB mnuRestAll_Click
  form.RestoreChild
END SUB
SUB infos(handleChild as long,index as integer,titleChild as string)
  stat.simpleText=titleChild
End Sub
Sub Close
  form.CloseAllChild
  if form.ChildCount>0 then form.modalResult=false
  if form.ChildCount=0 then icon.filename=""
End Sub
Sub KeyDown(key as word,shift as integer)
  'next child with Ctrl+F6
  if shift=CtrlDown and key=VK_F6 then form.ActiveNextChild
end sub


QImageEx

Documentation component by D.Glodt (c)2000-2004 Appendix A: QImageEx

QImageEx Component

INCLUDED IN RAPIDQ2.INC
QImageEx is just like a QImage component but with clipboard functions. Image copy to clipboard is possible if image was loaded with LoadFromFile method. The loading of other graphic formats is possible if Nviewlib.DLL is present in the system or application directory (the global variable NViewLibPresent = True then you can load jpg, gif, etc.) . See limitations.

QImageEx Properties
Field | Type | R/W | Default

QImageEx Methods
Method | Type | Description | Params
CopyToClipboard | SUB(rect as QRECT) | Copy image to clipboard | 1
PasteFromClipboard | SUB | Paste image from clipboard | 0
LoadFromFile | SUB(FileName$,Width%,Height%,Real%) | Load a bitmap file | 4
 | If the parameter Real is at true, the image will load with these dimensions. |  |
CanPaste | FUNCTION | Return TRUE if image présent in the clipboard. | 0
LoadOtherImage | SUB(FileName$,Progress&,Language$) | Load image from dll Nviewlib format | 3
 | The parameter progress is use to display a bar of progression during the loading of file.(true or false) The Language parameter corresponds to the language supported by DLL |  |

QImageEx Events
Event | Type | Occurs when... | Params

QImageEx Examples

  $typecheck on
  $INCLUDE "Rapidq2.inc"

  declare sub OuvrirClick
  declare sub QuitterClick
  declare sub Copier
  declare sub Coller
  declare sub Present

  const title="Viewer picture"
  dim source as QRECT

  CREATE Form AS QFORM
    Caption =title
    Width = 600
    Height = 600
    Center
    CREATE Menu AS QMAINMENU
      CREATE item1 AS QMENUITEM
        Caption="&Fichier"
        CREATE item2 AS QMENUITEM
          Caption="&Ouvrir"
          OnClick=OuvrirClick
        END CREATE
        CREATE item5 AS QMENUITEM
          Caption="-"
        END CREATE
        CREATE item6 AS QMENUITEM
          Caption="&Quitter"
          OnClick=QuitterClick
        END CREATE
      END CREATE
      CREATE item11 as QMENUITEM
        Caption="&Edition"
        OnClick=Present
        CREATE item12 as QMENUITEM
          Caption="&Copier"
          OnClick=Copier
        END CREATE
        CREATE item13 as QMENUITEM
          Caption="&Coller"
          OnClick=Coller
          Enabled=false
        END CREATE
      END CREATE
    END CREATE
    CREATE ScrollBox1 AS QSCROLLBOX
      AutoScroll = 1
      Align=5
      Color = &HFFFFFF
      CREATE image AS QImageEx
        Autosize=1
      END CREATE
    END CREATE
  END CREATE

  Form.ShowModal

  sub OuvrirClick
    dim file as QOPENDIALOG

    file.Filter="Fichiers bitmap(*.bmp)|*.bmp"
    file.InitialDir=CurDir$
    if file.Execute then
      image.loadFromFile(file.fileName,0,0,true)
      Form.Caption=title+"-"+file.FileName
    end if
  end sub

  sub QuitterClick
    Form.Close
  end sub

  sub Copier
    source.left=0
    source.top=0
    source.right=image.width
    source.bottom=image.height
    image.copyToClipboard(source)
  end sub

  sub coller
    image.pasteFromClipboard
  end sub

  Sub Present
    if image.canpaste then
      item13.enabled=true
    else
      item13.enabled=false
    end if
  End Sub


QListviewEx Component
Dreadsoftî Corporation
(manco un diritto riservato)
http://dreadsoft.too.it
dreadsoft@yahoo.it (Andreas Fink)

A bit complex, but with a lot of enhancements. Sorting, filtering, fastclear. Data can be loaded from (and saved to) files, Qmemorystream, Qfilestream. Support for CSV files. Very flexible layout. This component is included in RAPIDQ2.INC. See Limitations

QListViewEx Structure

Above you can see a "section" of the QListviewEx component

QlistviewEx is made by 4 components

- ParentPanel (Blue) is the main container, if you want to resize QlistviewEx you have to resize it. Other components will follow almost automatically
- Header (Red) contains new-style column headers
- QlistviewEx (Green) is the Qlistview component itself
- Colheader (Yellow) array of Qcoolbtn

QListViewEx Properties

Field | Type | R/W | Notes
Parentpanel | QPanel | RW | The panel which contains the listview and its header. The first thing to do is assign a parent to ParentPanel.
Header | Qpanel | RW | Container for column headers
Colheader | Array of Qcoolbtn | RW | Column header
Csv | QSTRINGLIST | RW | Used to store data. It can get data directly from a file, Qmemorystream, Qfilestream (See Qstringlist documentation for details)
CsvFile | STRING | RW | Filename of a CSV file
Separator | STRING |  | Character(or string) used to separate columns in csv
FieldsCount | INTEGER | RW | Number of fields(i.e. possible columns) found in the first string of csv
Columns_Count | INTEGER | RW | Number of columns created with the addcol method (see below)
Flatheaders | INTEGER |  | Determine if column headers have a 3D border

QListviewEx Methods

Method | Type | Description | Params
Draw | void
Load | Void | Loads data from csv, separating each line in columns (using SEPARATOR)
SortBy | Sub (Criterium as String) | See tutorial for details... | 1
LoadFromCsvFile | Void | Loads data directly from csvfile, updating csv. Make sure the CsvFile Property is set
FastClear | Void | Quicker cleaning function (not needed for long lists)
Exclude | sub (Column as integer, Criterium as string) | Removes unwanted items searching for a specific value (Criterium) in the specified column
AddCol sub (ColToAdd as string)

Use this one instead of the addcolumns method. To add columns, pass a single string containing headers captions, separated by "/"

Example:
Qlistviewex.addcol "First Name/Last Name/Address/Phone Number"
UpdateCsv | void | writes QlistviewEx data to csv
Filter | sub(column as integer, criterium as string) | Keeps only specified items (see tutorial)
SaveToCsvFile | void | updates CSV and writes data to csvfile
SaveToFileAs | void | Save CSV to file (discarding QlistviewEx changes)
DirecSaveAs | void | Saves QlistviewEx data without updating CSV

The many ways to read / write data

Not quite clear yet ?  Take a look at the tutorial

QLISTVIEW Example

$INCLUDE "RapidQ2.INC"
DECLARE SUB LoadCSVFile

CREATE form as qform
  center
  Width = 350
  Height = 350
    CREATE list as QLISTVIEWex
    ParentPanel.Parent = Form   'note!!
    Parentpanel.align = alNone	'note!!
    left = 50
    Top = 50 'this should be .Top property, etc.
    Width = 250 'this should be .left property
    Height = 250 'this should be .Top property, etc
    addcol "City/First Name/Last Name"
    ' addcolumns "First Name", "Last Name", "City"
    Separator = "/"
    AddItems "Seattle", "Denver", "Durango", "Providence", _
    "Stony Brook", "Los Angeles", "Hicksville"
    AddSubItem 1, "1sdf"
    AddSubItem 2, "2sdf"
    AddSubItem 3, "3sdf"
    column(0).width = 100
    column(1).width = 100
    column(2).width = 100
    'Colheader(0).bmp = "Star.bmp" '  icon in a column!
    header.bevelinner = 1
    header.color = rgb(20,145,200)
    header.height = 25
    header.font.size = 10
    Draw             'update manually
    END CREATE
  CREATE GoCSVButton AS QBUTTON
    Top = 1
    Caption = "Load CSV file"
    onClick = LoadCSVFile
  END CREATE
END CREATE

SUB LoadCSVFile
  list.csvFile = "database.csv"
  list.loadfromcsvfile
  list.addcol "First Name/Last Name/City"
  list.exclude(1, "red")' Unlike filter and exclude Sortby is CASE SENSITIVE
  list.load
  list.exclude (1, "White")
  list.filter (1, "Red")
  list.sortby ("City")' Unlike filter and exclude Sortby is CASE SENSITIVE
END SUB

form.Showmodal


QListviewEx Tutorial

$include "Qlistviewex.inc"

dim form as qform
with form
.center
end with

' First. We create a new QlistviewEx                  |  - First Steps -
dim list as qlistviewex

' We set the parentpanel Parent window                |
list.Parentpanel.parent = form

' then align the parentpanel to the whole client area |
' (but we could align it in any way)                  |
list.parentpanel.align = 5

' To put other components we use the Draw method.     |
' the draw method is VERY important, because it's used|
' to update the QlistviewEx layout                    |
list.draw

'Ok, now it's time to add some columns. Please note:  |  - Adding Columns -
'if you want the component to run correctly you have  |
'to use this method instead of the normal addcolumns  |
'as this method updates the Columns_Count property too|
list.addcol "First Name/Last Name/City"

' Generally, csv files use ";" as column separator,   |  - Separator -
' but sometimes we need to import files or streams    |
' Which use different separators, like "/" or "," or  |
' strings like "<thisisacolumnseparator>".            |
' this is the purpose of the Separator property:      |
' before loading a file, write this                   |
list.Separator = "/"

'Now we want to load some data in the listview. We    |  - Loading data -
'could use the file included in this package called   |
'database.csv.
list.csvFile = "database.csv"
list.loadfromcsvfile

'You see, columns are a bit narrow, so we would like  |  - Columns width -
'to do something like this :                          |

list.column(0).width = 100
list.column(1).width = 100
list.column(2).width = 100

' And then call the draw method. By the way... have   |
' you already clicked on column headers ?!?  Yes, they|
' start automatic sorting                             |
list.draw

' Maybe we don't want REDs in our list                |  - Excluding items -
list.exclude(1, "red")

' Oh, sorry, we don't want WHITEs                     |  - Reloading data -
list.load
list.exclude (1, "White")

' As long as the program is "alive" (and as long as   |
' you don't change csv) the csv property will keep the|
' original data, so you can use the load method to    |
' reload data from memory                             |

' Now we want to keep only REDs                       |  - Filtering -

list.filter (1, "Red")

' ** NOTE ** Filter and exclude are NOT case sensitive|
' so RED or Red or red or rEd is the same             |

' Now we have to sort items by City. We have 2 ways   |  - Sorting -
' 1 - Click on the "City" column header               |
' 2 - Use the sortby method                           |

list.sortby ("City")

' Unlike filter and exclude Sortby is CASE SENSITIVE  |

' =================================================================|
' Changing layout and other capabilities                           |
' =================================================================|

' You can use QlistviewEx as a common Qlistview       |
' component, so you can add/delete items and subitems |
' as usual

' The "complex" structure of the QlistviewEx component|  - Header -
' allows a lot of extra properties/capabilities. For  |
' Example, if we want to change the header layout we  |
' can treat it as a common Qpanel:                    |

list.header.bevelinner = 1
list.header.color = rgb(20,145,200)
list.header.height = 25
list.header.font.size = 10

' or maybe we don't want to see it...                 |
list.header.visible = 0

' ParentPanel is a Qpanel, so we can do things like   |  - ParentPanel -
list.Parentpanel.align = 1
list.Parentpanel.height = 180

' Column headers are Qcoolbtn, so we can add icons,   |  - Column headers -
' and things like that                                |
list.Colheader(0).bmp = "Star.bmp"
list.draw

' if we don't want flat column headers we just write  |
list.flatheaders = 0
list.draw

' if we want only the first column header to be flat  |
' then:                                               |
list.colheader(0).flat = 1

' ** NOTE ** this property will be overwritten every  |
' time you call the draw method ...                   |

' IMPORTANT. You can change column headers caption    |
' using the .colheader.caption property, but this is  |
' not the correct way. If you want the QlistviewEx to |
' run properly, you must set column width and caption |
' using the QlistviewEx.Column() property and then    |
' call the DRAW method.

' When you manipulate hundreds of items, and you want |  - Fastclear -
' to clear the Qlistview, if you use the clear method |
' you will have to wait some minutes with a slow pc.  |
' in cases like this you can use the Fastclear method |
list.fastclear

' remember: it's not necessary if you have small lists|


QMENUex

Documentation by John Kelly QMENUex

QMenuEx Component

INCLUDED IN RAPIDQ2.INC
 QMenuEx adds bitmaps, descriptions, and fonts to an QMENUITEM. It is not a stand-alone component and must be declared after you define your QMainMenu and QMenuItems. You can add bitmaps or Icons with $RESOURCE handles or by filename. You must be sure to follow the programming example below. Code is based on the QMenu and QDrawMenu by D. Glodt and Jordi Ramos.
See limitations.

QMenuEx Properties
Field | Type | R/W | Default
BackColor | LONG | RW | clMenu
Set the color of the Menu item background
Count | INTEGER | R
Count returns the number of images used
DisabledColor | LONG | RW | system default
Color of a disabled Menu Item
ForeColor | INTEGER | R | system default
Set the color of the Menu item text
HighLightColor | LONG | R | system default
Color when the mouse highlights Menu Item
HighLightTextColor | LONG | R | True
Font | QFONT | R/W
Use the SetFontSize Method for size
FontSize | INTEGER | RW
You will need to set ownerDraw properties to all QMenuItems in order to work consistently
Height | INTEGER | R/W | auto | W
Outline | INTEGER | RW | False
specifies an outline drawn around the Menu image
Transparent | INTEGER | RW | True
Specifies whether the image on the menu contains transparent or non-transparent images.
TransparentColor | INTEGER | RW | 0
The color in the image that will be transparent
Width | INTEGER | RW

QMenuEx Methods
Method | Type | Params
AddBMPFile | SUB (MenuItem AS QMENUITEM, FileName$) | 1
Add BMP file to the menu item
AddICOFile | SUB (MenuItem AS QMENUITEM, FileName$) | 1
Add icon resource handle, must be followed by an AddDescription command
AddDescription | SUB (MenuItem AS QMENUITEM, descript AS STRING) | 1
Give a sub-caption to each QMenuItem, ie, update this string in a status bar in a OnMouseHover event
No bitmap will be assigned.
DelBitmap | SUB (Menuitem as Qmenuitem) | 1
delete an image from the sub-menuitem of the Parent menu
MenuModify | SUB (MenuItem AS QMENUITEM, Image AS QBITMAP, description AS STRING) | 4
Add Subitems to MenuItem
Parent | SUB (TheMenuParent AS QMENUITEM) | 1
Images can only be assigned to sub-menuitems. Use this to specify the Parent menu
Init | SUB (Form AS QFORM) | 1
The parent form. with the menus. You MUST specify the QFORM
Close | VOID stop drawing bitmaps and free up memory | 0

QMenuEx Events
Event | Type | Occurs when... | Params | Support
OnMouseHover | SUB (Xpos&, Ypos&, Descript AS STRING) | Mouse over MenuItem when High lighted. String is the Menu Item Description | 3 | W
REMARKS
there are 2 global structures with this component:
gRQ2_MeasureItem AS TMEASUREITEMSTRUCT
gRQ2_DrawItem AS TDRAWITEMSTRUCT

 QMenuEx Example
$INCLUDE "RapidQ2.inc"

$RESOURCE New_bmp as "\rapidQ\icon\New.bmp"
$RESOURCE Open_bmp as "\rapidQ\icon\Open.bmp"
$RESOURCE Save_bmp as "\rapidQ\icon\Save.bmp"
$RESOURCE Exit_bmp as "\rapidQ\icon\Exit.bmp"
$RESOURCE Cut_bmp as "\rapidQ\icon\Cut.bmp"
$RESOURCE Copy_bmp as "\rapidQ\icon\Copy.bmp"
$RESOURCE Paste_bmp as "\rapidQ\icon\Paste.bmp"
$RESOURCE Empty_bmp as "\rapidQ\icon\Empty.bmp"

Declare Sub FormClose (Action As integer)
Declare Sub NewItemClick (Sender As QMENUITEM)
Declare Sub ExitItemClick (Sender As QMENUITEM)
Declare SUB MnuShowDescription(Xpos AS LONG, Ypos AS LONG, Descript AS STRING)
CREATE Form2 As QFORM
    Caption = "New Form"
    Width = 200
    Height = 100
    Center
END CREATE

CREATE Form As QForm
   Width = 400
   Center
   Caption = "Ownerdraw Menus"
   onClose = FormClose

   CREATE MainMenu As QMainMenu
      CREATE FileMenu As QMenuItem
         Caption = "&File"
         CREATE NewItem As QMenuItem
            Caption = "&New"
            Hint = "New"
            onclick = NewItemClick
         END CREATE
         CREATE OpenItem As QMenuItem
            Caption = "&Open..."
            Hint = "Open"
            ShortCut = "Ctrl+O"
         END CREATE
         CREATE SaveItem As QMenuItem
            Caption = "&Save"
            Hint = "Save"
         END CREATE
         CREATE SaveASItem As QMenuItem
            Caption = "Sa&ve as..."
            Hint = "Save as"
         END CREATE
         CREATE BreakItem As QMenuItem
            Caption = "-"
         END CREATE
         CREATE ExitItem As QMenuItem
            Caption = "E&xit"
            onclick = ExitItemClick
         END CREATE
      END CREATE
      CREATE EditMenu As QMenuItem
         Caption = "&Edit"
         CREATE CutItem As QMenuItem
             Caption = "&Cut           Ctrl+X"
             ShortCut = "Ctrl+X"
         END CREATE
         CREATE CopyItem As QMenuItem
             Caption = "&Copy        Ctrl+C"
         END CREATE
         CREATE PasteItem As QMenuItem
             Caption = "&Paste       Ctrl+V"
             Checked = true   'no effect with bmp
         END CREATE
      END CREATE
      CREATE SearchMenu As QMenuItem
         Caption = "&Search"
         CREATE FindItem As QMenuItem
             Caption = "&Find"
         END CREATE
         CREATE ReplaceItem As QMenuItem
             Caption = "&Replace"
         END CREATE
       END CREATE
    END CREATE

    CREATE StatusBar As QStatusBar
       AddPanels "QMenuEx Demo",""
       panel(0).Width = 170
    END CREATE

END CREATE

DIM pic AS QIMAGE
DIM MenuX as QMenuEx
WITH MenuX
.Transparent = False            'default is True
.Parent(FileMenu)
      pic.bmphandle= New_bmp
      .MenuModify NewItem, pic, "Creates a new document"
      pic.BMPhandle= Open_bmp
      .MenuModify OpenItem, pic, "Opens a Document"
      pic.BMPhandle= Save_bmp
      .MenuModify SaveItem, pic, "Save Document"
      .MenuModify SaveAsItem, pic, "Save Document as"
      pic.BMPhandle= Exit_bmp
      .MenuModify  ExitItem, pic, "Exits Program"
.Parent(EditMenu)
      pic.BMPhandle= Cut_bmp
      .MenuModify CutItem, pic, "Cuts Selection to Clipboard"
      pic.BMPhandle= Copy_bmp
      .MenuModify CopyItem, pic, "Copies Selection to Clipboard"
      pic.BMPhandle= Paste_bmp
      .MenuModify PasteItem, pic, "Pastes Contents of Clipboard"
.Parent (SearchMenu)
      .AddDescription FindItem, "Search for a text string"
      .AddDescription ReplaceItem, "Replace a character string by another"
      .OnMouseHover = MnuShowDescription
    ' ** Add effects, best if all items have a bmp assigned
'     .FontSize = 12
'     .BackColor = RGB(32, 32, 255)
'     .ForeColor = RGB(255, 255, 32)
         'default is to draw transparently, use this for no transparency
     .Init Form                  'must do this to work
END WITH
Form.ShowModal

SUB MnuShowDescription(Xpos AS LONG, Ypos AS LONG, Descript AS STRING)
   StatusBar.Panel(1).Caption = Descript
END SUB

SUB NewItemClick (Sender AS QMENUITEM)
   Form2.ShowModal
end Sub

SUB ExitItemClick (Sender AS QMENUITEM)
   Form.close
end Sub

sub FormClose (Action as integer)
   MenuX.Close
end Sub


QSystem

Documentation component by John Kelly, Thanks to b_j0@yahoo.com, Rudy Elyn, Chris. QSYSTEM

QSYSTEM Component

QSYSTEM is a non-visible component in RAPIDQ2.INC. It allows you to open control panels, get information on the Windows operating system and uses WIN32 API calls like GetSystemMetrics, etc. Most of the properties are really return values from a function that calls the API GetSystemMetrics. Memory return values are in bytes. To get KB divide by 1024 , to get MB divide by 1048576. See limitations.

QSYSTEM Properties
OPERATING SYSTEM
MajorVersion | INTEGER Returns the Windows major version number | R | 0
MinorVersion | INTEGER Returns the Windows minor version number | R | 0
OSname$ | STRING Returns the Name of the Windows operating system (e.g., "Windows 2000") | R | 0
MEMORY
AvailableMemory | DWORD Returns free RAM memory in bytes. Divide by 1024 to get KB, etc. | R | 0
PercentFreeMemory | DWORD Returns percent free RAM as integer in the range 0 - 100 | R | 0
TotalMemory | DWORD Returns total RAM memory in bytes. Divide by 1024 to get KB, etc. | R | 0
UsedMemory | DWORD Returns used RAM memory in bytes. Divide by 1024 to get KB, etc. | R | 0
PageFileMemory | DWORD Returns available page file memory or virtual memory in the system. Value is bytes. If this number is below a few MB, you are in trouble. | R | 0
AvailableMemory | DWORD Returns free RAM memory in bytes. Divide by 1024 to get KB, etc. | R | 0
DiskFreeSpace | FUNCTION (RootPathName AS STRING) AS DOUBLE ie PRINT systm.DiskFreeSpace("C:\") 'dir doesn't matter |  |
SHUTDOWN / LOGOFF
LogOff | SUB () This will cause the user to logoff. Ask before USING! | W | 0
Reboot | SUB () Causes immediate reboot of the system. ASK FIRST! | W | 0
ShutDown | SUB () Shuts down the computer. Ask before USING! | W | 0
ShutDownForce | SUB () This will cause immediate shutdown. Ask before USING! | W | 0
SYSTEM METRICS
ScrollBarWidth | LONG From GetSystemMetrics | R | 0
ScrollBarHeight | LONG "" "" | R | 0
CaptionBarHeight | LONG "" "" | R | 0
WindowBorderWidth | LONG "" "" | R | 0
WindowBorderHeight | LONG | R | 0
IconWidth | LONG | R | 0
IconHeight | LONG | R | 0
MouseWheelPresent | LONG the mouse has a wheel, see QFormEx (in QForm doc). | R | 0
NetworkPresent | LONG Network present flag | R | 0
SlowProcessor | LONG Slow processor flag, in case you need a fast machine | R | 0
MenuBarHeight | LONG | R | 0
MenuBarHeight | LONG | R | 0
POWER SETTINGS
PercentBattery | FUNCTION% An integer returning the remaining battery life in the range 0 - 100 | R | 0
PowerStatus | FUNCTION% Set or Get the power status. | R/W | 0
 | sysHibernateAsk = 1 'dialog box asks before hibernating sysHibernateForce = 2 'immediate force of hibernating sysSleepAsk = 3 'system sleep mode ask with dialog box sysSleepForce = 4 'immediate force system into sleep mode |  |
ACLineStatus | INTEGER return values are | R | 0
 | AC_LINE_OFFLINE = &H0 AC_LINE_ONLINE = &H1 AC_LINE_BACKUP_POWER = &H2 AC_LINE_UNKNOWN = &HFF BATTERY_FLAG_HIGH = &H1 BATTERY_FLAG_LOW = &H2 BATTERY_FLAG_CRITICAL = &H4 return values can be OR e.g, (BATTERY_FLAG_CRITICAL | BATTERY_FLAG_CHARGING) 'both set BATTERY_FLAG_CHARGING = &H8 BATTERY_FLAG_NO_BATTERY = &H80 BATTERY_FLAG_UNKNOWN = &HFF BATTERY_PERCENTAGE_UNKNOWN = &HFF BATTERY_LIFE_UNKNOWN = &HFFFF |  |

QSYSTEM Methods

Method Type Description Params
ShowControlPanel (PanelName AS STRING,index AS INTEGER) AS LONG FUNCTION Open control panel 2

If you want to open a control panel the PanelName is at least the first 4 characters in the control panel title. Example:
ShowControlPanel ("firewall, 1) ' show the firewall dialog box applet
Index is the tab# you want to open (not all cases supported, just leave as 1). Current options are:
accessibility options add new hardware add or remove software
dial-up directx display
firewall font game
internet keyboard mmdevice
modem mouse netsetup
passwords power management printers and faxes
regional settings scanners sounds
system telephone themes
time user

QSYSTEM Events
Event | Type | Occurs when... | Params
None ...

QSYSTEM Example

$INCLUDE "RAPIDQ2.INC"
DEFINT a
DIM systm as QSYSTEM
 ShowMessage "Your operating system name is "+systm.OSName$
 systm.ShowControlPanel("firewall",1)
 systm.ShowControlPanel("sounds",1)

a = systm.PowerStatus
SELECT CASE systm.ACLineStatus
 CASE AC_LINE_OFFLINE
 ShowMessage "AC power not plugged in"
 CASE AC_LINE_ONLINE
 ShowMessage "AC power plugged in"
 CASE AC_LINE_BACKUP_POWER
 ShowMessage "using backup power"
 CASE AC_LINE_UNKNOWN
 ShowMessage "power source unknown"
END SELECT

 ShowMessage str$(systm.PowerStatus)
 ShowMessage "Percent battery life = " + str$(systm.PercentBattery) + "%"
 ShowMessage str$(systm.ACLineStatus)
 systm.powerstatus = sysSleepAsk
 systm.powerstatus = sysHibernateAsk

ShowMessage "memory before Qform= "_
 + str$(systm.PercentFreeMemory) +_
 "% of a total of " + _
str$(systm.AvailableMemory) + " bytes"
DIM Form AS QFORM
Form.Show
ShowMessage "memory after Qform= " + str$(systm.PercentFreeMemory) + "%"
ShowMessage "Page file memory left = " + str$(systm.PageFileMemory)
ShowMessage "Free space on Hard Drive (MB) = " + str$(systm.DiskFreeSpace("C:\"))
Contents


QUICKSORT

QUICKSORT SORTING Statement Windows/Unix
QUICKSORT, aptly named, can be used to sort your arrays of any type, except Objects/UDTs of course. It, obviously, uses the QuickSort algorithm to perform the sort.

Syntax: QUICKSORT(Array-begin, Array-end, ASCEND|DESCEND)
DIM A(1000) AS INTEGER
'-- put stuff in A
QUICKSORT(A(10), A(500), ASCEND) '-- sorts elements 10..500

Details:
The pivot element in the above example is A(10), so if you want randomness, you'll have to replace A(10) with some random element from A(10)..A(500) in the above example. You can also sort multi-dimensional arrays and "span sort" arrays.

Span sorting:
           DIM A(1 TO 100) AS LONG
           DIM B(1 TO 100) AS LONG
           DIM C(1 TO 100) AS LONG

           '--- puts some values into array A, B, C
           RANDOMIZE TIMER
           FOR I = 1 TO 100
               A(I) = RND(50000)
               B(I) = RND(50000)
               C(I) = RND(50000)
           NEXT

           QUICKSORT A(1), C(100), ASCEND
           PRINT A(1)," ",B(1)," ",C(1)
As long as you DIM the arrays "side by side" they will share a contiguous space of memory, this means you can sort from the start of memory address A(1) to the end of memory address C(100). This technique is not recommended, but if you can find a use for it, go ahead.


RANDOMIZE

RANDOMIZE MATH Statement Windows/Unix
Initializes (reseeds) the random-number generator.

Syntax: RANDOMIZE [numeric-expression]
RANDOMIZE TIMER

Details:
If argument is omitted, randomize will default as RANDOMIZE TIMER.


READ

READ Statement Windows/Unix
A statement that reads values from a DATA statement and assigns the values to variables.

Syntax: READ variablelist
READ A%, S$, P(1,2)

Details:
Variablelist is made up of one or more variables, separated by commas, which are to receive the data. The variables may be string or numeric.


REDIM

REDIM Statement Windows/Unix
Declaration statement that changes the space allocated to an array that has already been declared by DIM, preserving as much of the data as possible. Unlike other forms of BASIC this handles memory in contiguous sections. Thus, REDIM might overwrite existing variables in memory if you REDIM a small memory block to a large memory block.

Syntax: REDIM variable[(subscripts)] AS type
DIM B(20) AS INTEGER
REDIM B(100) AS INTEGER

Details:
If the array has not yet been declared by DIM, REDIM will be equivalent to calling DIM (except when dealing with components, in which case you'll receive a compiler error). You cannot change the data type for the array, ie. you cannot redefine array B to be something other than an INTEGER (as in the above example). Combining arrays is a by-product of REDIM.
DIM A(1 to 100) AS INTEGER
DIM B(1 to 100) AS INTEGER
REDIM A(1 to 200) AS INTEGER   '-- Combines A and B together
What the above code does is preserve the data in A as well as combining the array B.so index from 101 to 200 is the data for B and 1 to 100 is the data for A. Clarification: Array Bhas not been modified, it still maintains its own address space and will notoverwrite A's data and vice versa. Note that this by-product does not apply to redimming Fixed Strings, Variants and Components.
Redim table
  DIM Button(1 TO 2, 1 TO 2) AS QBUTTON
  REDIM Button(1 TO 2, 1 TO 4) AS QBUTTON
Note that when dealing with multiple dimensions the elements are shifted to fill each column. So element (2,2) is actually moved to position (1,4).
Some problems to be aware of:
DIM A(1) AS STRING
REDIM A(20) AS STRING    'this redim works fine!

DIM A(1) AS STRING*4
REDIM A(20) AS STRING*4   'this redim causes an error!


RELEASECAPTURE Windows API Call in RapidQ2.INC Windows
Windows API that releases the mouse capture from a window in the current program after a SETCAPTURE function call. Restores normal mouse input processing. A window that has captured the mouse receives all mouse input, regardless of the position of the cursor, except when a mouse button is clicked while the cursor hot spot is in the window of another thread. This is a keyword in RAPIDQ2.INC

Syntax: Return = RELEASECAPTURE
DIM Rtn AS LONG
Rtn = ReleaseCapture 'Rtn is optional

Details:
If the function succeeds, the return value is nonzero. If the function fails, the return value is zero.


REM

REM Comment Windows/Unix
A BASIC declaration that allows explanatory remarks to be inserted in a program. It's suggested that you use ' to start your comments instead.

Syntax: REM remark
REM This is a comment, nothing is executed
' This is another comment, use this one in RapidQ rather than REM:

a=5 rem fkfkl, - not working
a=5 ' fkfkl, - works


RENAME

RENAME SYSTEM Statement Windows/Unix
A statement that renames a file. If file already exists the operation is not executed.

Syntax: RENAME file1, file2
RENAME "abc.txt", "xyz.txt"


REPLACE$

REPLACE$ STRING Function Windows/Unix
A function that replaces a portion of a string with another.

Syntax: REPLACE$(source-string, replace-string, index)
A$ = REPLACE$("Hello", "J", 1) '-- returns Jello


REPLACESUBSTR$

REPLACESUBSTR$ STRING Function Windows/Unix
A function that replaces a substring with another string. All occurrences will be replaced. The length of the replacement string does not need to match the length of the replaced string.

Syntax: REPLACESUBSTR$(source-string, replace-string, replacement-string)
A$ = REPLACESUBSTR$("abcdefgabcdefg", "abc", "99") '-- returns 99defg99defg


RESOURCE

RESOURCE RESOURCE Function Windows/Unix
A function that returns the absolute position of the resource from the current program.

Syntax: RESOURCE(numeric-expression)
EXTRACTRESOURCE Resource(0), "test.bmp"

Details:
RESOURCE() is an array consisting of 0 to RESOURCECOUNT-1 elements. Element 0 corresponds to the first $RESOURCE handle you specify and so on. If numeric-expression is not in the range 0 to RESOURCECOUNT-1, this function returns 0.


RESOURCECOUNT

RESOURCECOUNT RESOURCE Function Windows/Unix
A function that returns the number of resources in the current program.

Syntax: RESOURCECOUNT
A% = RESOURCECOUNT


RESTORE

RESTORE Statement Windows/Unix
A statement that allows DATA statements to be reread from a specified line.

Syntax: RESTORE [{linelabel | linenumber}]
RESTORE

Details:
If the argument is omitted, the next READ statement which executes will read the first item in the first DATA statement in the program. Linelabel or Linenumber identifies the DATA statement you want the next READ statement to use. The first item from that line will be read.


RESULT Function Return Windows/Unix
Use inside a FUNCTION to set the return value. You can set it multiple times. The last value is returned.

Syntax: RESULT = (numeric-expression)

FUNCTION SquareRoot(a AS SINGLE) AS SINGLE
RESULT = SQR(a)
END FUNCTION


REVERSE$

REVERSE$ STRING Function Windows/Unix
A function that reverses (or mirrors) a string.

Syntax: REVERSE$(string-expression)
A$ = REVERSE$("Hello") '-- returns olleH


RGB

RGB CONVERSION Function Windows/Unix
A conversion function that takes the red, green and blue parameters and combines them to form a BGR numeric representation.

Syntax: RGB(redvalue, greenvalue, bluevalue)
C = RGB(255, 0, 255)

Details:
Values range from 0-255. Values outside this range produce undefined results.


RIGHT$

RIGHT$ STRING Function Windows/Unix
A function that returns the rightmost n characters of a string.

Syntax: RIGHT$(string-expression, n)
A$ = RIGHT$("Hello", 3) '-- returns llo

Details
Limited to strings under 32K size.! If your strings are larger than 32K you must break up the string for RIGHT$


RINSTR

RINSTR STRING Function Windows/Unix
Reverse INSTR is a function that compares 2 strings and returns the position of the find-string with respect to the search-string. Instead of starting the search from left to right, like INSTR, RINSTR searches right to left (ie. the reverse of INSTR). If found, RINSTR returns the index position of the find-string, 0 otherwise.

Syntax: RINSTR([start,] search-string, find-string)
A% = RINSTR("Hello World", "l") '-- returns 10
A% = RINSTR(4, "hehe they", "he") '-- returns 3


RMDIR

RMDIR SYSTEM Statement Windows/Unix
A statement that removes a directory.

Syntax: RMDIR directory
RMDIR "abc"
RMDIR "LastCopy\123" for sub..subdirectory in the current directory.
RMDIR "C:\W98\" for full path


RND

RND MATH Function Windows/Unix
A function that returns a random number whose sequence is generated by calling RANDOMIZE.

Syntax: RND[(upper-bound)]
A% = RND(10)

Details:
If no upper-bound is given, RND returns a decimal number in the range 0 to 1.


ROUND

ROUND MATH Function Windows/Unix
A math function that converts a number to an integer by rounding the fractional part of the expression.

Syntax: ROUND(numeric-expression)
A% = ROUND(3.49) '-- Returns 3
A% = ROUND(3.50) '-- Returns 4

Details:
If the argument is negative, then Round always rounds toward zero. I.E. Round(-3.99) returns -3 instead of -4.

To get around this:
DEFBYTE NEG = 0
IF Answer < 0 THEN
NEG = 1
Answer = ABS(Answer)
END IF
Answer = ROUND(Answer)
IF NEG THEN Answer = -Answer
NEG = 0 ' reset Flag


RQASM Function Pointers

RQASM- assembly language programming in RapidQ:
 by Jacques Phillip

RQASM

RQASM is a way to add assembly language programming to RapidQ using the freely available netwide assembler NASM by Jacques Phillip. For demos on how to add and access global and local data in RAPIDQ with NASM code see:
http://erdemal.webhop.org/RapidQ/RqAsm_Demo_API_and_DATAS.zip

RQASM requires a way to execute binary code contained inside an Array. This is done with the Windows API call:
CallWindowProcA this is usually for handling windows messages (like sendmessage) but will do the trick for starting your machine code program. You are limited to 4 parameters but see RQASM_Pointers.html for ways to use more parameters. Note using the CallWindowProcA to call a RqAsm procedure adds a 12000 processor cycles to your NASM routine. So the speed advantage is best for routines that are run a few times rather than over and over. Jacque "I spend a lot of time trying to call these RqAsm routine by a faster way. I failed ! ... but I still hope :)"

For floating point routines
see the EXCELLENT NASM BOOK/TUTORIAL:
http://www.drpaulcarter.com/pcasm (portuguese and french versions available)

It is now 'ported' to RqAsm/Nasm. It's *MUCH* easier with an example :)
You can get that Demos at :
http://erdemal.webhop.org/RapidQ/RqAsm_FPU_Demo.zip


RQASM Function Pointers

BINDING FUNCTION POINTERS in Rapid-Q
Documentation by Jacques Phillip and John Kelly

RQASM Utilities for BINDing function pointers

BIND works for internal function pointers, but does not work if you want to call an function to an absolute memory address. This ability is important for assembly language coding, and COM interfaces such as DirectX. Use the "RqAsmUtils.Inc" file to do special operations with function pointers with absolute addresses, or for pointers in general, such as an alternative to POKE and PEEK.
DECLARE Function CallAddressManyArgs (address As Long, ptrStructArg As Long) As Long
DECLARE Function CallAddressNoArg (address As Long) As Long
DECLARE Function CallAddressOneArg (address As Long, arg1 As Long) As Long
DECLARE Function CallAddressThreeArgs (address As Long, arg1 As Long, arg2 As Long, arg3 As Long) As Long
DECLARE Function CallAddressTwoArgs (address As Long, arg1 As Long, arg2 As Long) As Long
DECLARE Function CallPointerManyArgs (pointer As Long, ptrStructArg As Long) As Long
DECLARE Function CallPointerNoArg (pointer As Long) As Long
DECLARE Function CallPointerOneArg (pointer As Long, arg1 As Long) As Long
DECLARE Function CallPointerThreeArgs (pointer As Long, arg1 As Long, arg2 As Long, arg3 As Long) As Long
DECLARE Function CallPointerTwoArgs (pointer As Long, arg1 As Long, arg2 As Long) As Long
DECLARE Function ReadByteAtAddress (address As Long) As Long
DECLARE Function ReadByteAtPointer (pointer As Long) As Long
DECLARE Function ReadDWordAtAddress (address As Long) As Long
DECLARE Function ReadDWordAtPointer (pointer As Long) As Long
DECLARE Function ReadWordAtAddress (address As Long) As Long
DECLARE Function ReadWordAtPointer (pointer As Long) As Long
DECLARE Function WriteByteAtAddress (address As Long, bData As Long) As Long
DECLARE Function WriteByteAtPointer (pointer As Long, bData As Long) As Long
DECLARE Function WriteDWordAtAddress (address As Long, dwData As Long) As Long
DECLARE Function WriteDWordAtPointer (pointer As Long, dwData As Long) As Long
DECLARE Function WriteWordAtAddress (address As Long, wData As Long) As Long
DECLARE Function WriteWordAtPointer (pointer As Long, wData As Long) As Long

'
' Test RqAsmUtils.Inc July 05nd, 2004
'
$Include "RqAsmUtils.Inc" '
$ESCAPECHARS ON
$TYPECHECK ON
$INCLUDE "RAPIDQ.INC"
'
Declare Function GetTickCount Lib "kernel32" Alias "GetTickCount" () As Long
' -----------------------------------------------
' Function to Be Called by CallAddressManyArgs and CallPointerManyArgs
DefStr sMsgHeader
Sub ShowMsg (A As Long, B As Long, c As Long, D As Long)
ShowMessage ( sMsgHeader & "\nA=" & Hex$(A)& "\nB=" & Hex$(B)& "\nC=" & Hex$(C) & "\nD=" & Hex$(D))
End Sub
'
Sub ShowMsg3Args (A As Long, B As Long, c As Long)
ShowMessage ( sMsgHeader & "\nA=" & Hex$(A)& "\nB=" & Hex$(B)& "\nC=" & Hex$(C))
End Sub
'
Sub ShowMsgNoArg ()
ShowMessage (sMsgHeader)
End Sub
'
' -----------------------------------------------
DefInt iAddress, iPtr, iPtr0, iPtr1, iPtr2, ptrArray, N
'
' The Array that will contain the passed argument
' (see CallAddressManyArgs and CallPointerManyArgs Code in RqAsmUtils.Inc)
Dim myArray(5) As Integer
' The pointer to the Function to be called by CallAddressManyArgs an CallPointerManyArgs
iPtr = CodePtr(ShowMsg)
' set the values of the arguments (used too to test the Reads functions of the RqAsmUtils.Inc)
myArray(0) = 4 ' 4 arguments
myArray(1) = &HFFFF8000 ' Argument 1
myArray(2) = &HFFFFFF40 ' Argument 2
myArray(3) = &H12345678 ' Argument 3
myArray(4) = &H44444444 ' Argument 4
'
ptrArray = VarPtr(myArray(0))
'
iptr0 = VarPtr(myArray(0))
iPtr1 = VarPtr(myArray(1))
iPtr2 = VarPtr(myArray(2))
'
Print "Sub showMsg CodePtr = ";iPtr
Print "myArray(0) ptrArray = ";ptrArray
Print
' Tests The Read at Address functions of the Dll
Print "RqAsmUtils Read DWORD at Address = ";ReadDWordAtAddress(iPtr0)
Print "RqAsmUtils Read WORD at Address = ";ReadWordAtAddress(iPtr1)
Print "RqAsmUtils Read BYTE at Address = ";ReadByteAtAddress(iPtr2)
' Test the read at Pointer functions of the Dll
Print "RqAsmUtils Read DWORD at Pointer = ";ReadDWordAtPointer(VarPtr(iPtr0))
Print "RqAsmUtils Read WORD at Pointer = ";ReadWordAtPointer(VarPtr(iPtr1))
Print "RqAsmUtils Read BYTE at Pointer = ";ReadByteAtPointer(VarPtr(iPtr2))
'
' Calls Sub ShowMsg via CallAddressManyArgs in RqAsmUtils.Inc
sMsgHeader = "Sub Called with CallAddressManyArgs of RqAsmUtils.Inc"
myArray(0) = 4 ' 4 arguments to pass
myArray(1) = &HFFFF8000 ' Argument 1
myArray(2) = &HFFFFFF40 ' Argument 2
myArray(3) = &H12345678 ' Argument 3
myArray(4) = &H44444444 ' Argument 4
CallAddressManyArgs(iPtr, ptrArray)
'
' Calls Sub ShowMsg via CallPointerManyArgs in RqAsmUtils.Inc
sMsgHeader = "Sub Called With CallPointerManyArgs RqAsmUtils.Inc"
myArray(0) = 4 ' 4 arguments to pass
myArray(1) = &H11111111 ' Argument 1
myArray(2) = &H22222222 ' Argument 2
myArray(3) = &H33333333 ' Argument 3
myArray(4) = &H44444444 ' Argument 4
CallPointerManyArgs(VarPtr(iPtr), ptrArray)
'
' Calls Sub ShowMsg via API CallWindowProcA in user32.dll
sMsgHeader = "Sub Called With API CallWindowProcA in user32.dll"
CallAsmProc(iPtr, 111, 222, 333, 444)
'
' Calls Sub ShowMsg via CallAddressThreeArgs in RqAsmUtils.Inc
iPtr = CodePtr(ShowMsg3Args)
sMsgHeader = "Sub Called With CallAddressThreeArgs in RqAsmUtils.Inc"
CallAsmProc(iPtr, 111, 222, 333, 444)
'
' Calls Sub ShowMsg usual way :)
sMsgHeader = "Sub Called as usually in RQ :)"
ShowMsg(111, 222, 333, 444)
'
' call a SUB with no argument via CallAddressNoArg and CallPointerNoArg
iPtr = CodePtr(ShowMsgNoArg)
Print "iptr ShowMsgNoArg = ";iPtr
sMsgHeader = "Sub ShowMsgNoArg with No CallAddressNoArg from RqAsmUtils.Inc "
CallAddressNoArg(iPtr) ' There to OneArg, TwoArgs, ThreArgs for CallAddress... and Call Pointer
'
sMsgHeader = "Sub ShowMsgNoArg with No CallPointerNoArg from RqAsmUtils.Inc "
CallPointerNoArg(VarPtr(iPtr)) ' There to OneArg, TwoArgs, ThreArgs for CallAddress... and Call Pointer
'
' Call sub with no Argument via CallAddressManyArgs with myArray(0) = 0
myArray(0) = 0 ' Zero Arg
sMsgHeader = "Sub No Arg Called with CallAddressManyArgs of RqAsmUtils.Inc"
CallAddressManyArgs(iPtr, ptrArray)
'
' Call sub with no Argument via CallPointerManyArgs with myArray(0) = 0
sMsgHeader = "Sub No Arg Called With CallPointerManyArgs RqAsmUtils.Inc"
CallPointerManyArgs(VarPtr(iPtr), ptrArray)
'
' -------------------------------------------------------------
' EXIT CONSOLE
' ------------
DefStr sExit
Input "\n\n CR to QUIT \n\n", sExit
Application.Terminate
End


RTLMOVEMEMORY MEMORY Function Windows
A memory function that copies n bytes of memory from source to destination.

Syntax: RTLMOVEMEMORY(byref Destination AS LONG, byref Source AS LONG, Length AS LONG)
DEFINT I=90, J=10
'-- After MEMCPY, I should equal 10
RTLMOVEMEMORY(I, J, SIZEOF(INTEGER))

Details
Similar to the MEMCPY command but this may work when MEMCPY doesn't properly align a structure. Examine RapidQ2.INC for the AlphaBlend function showing how this function must be used instead of MEMCPY.


RTRIM$

RTRIM$ STRING Function Windows/Unix
A string function that returns a string with trailing spaces removed.

Syntax: RTRIM$(string-expression)
A$ = RTRIM$("Hello ") '-- returns Hello


RUN

RUN SYSTEM Statement Windows/Unix
A statement that executes a specified program without blocking.

Syntax: RUN filespec
RUN "rapidq.exe"


SCREEN Component

The SCREEN object is global, and need not be created. They are actually internal variables. If you have the RAPIDQ2.INC file then you have added functions for the desktop and mouse under Windows.

SCREEN Properties
Screen.ConsoleX | Windows Unix | INTEGER | Returns maximum column for console screen, useful under Unix.
Screen.ConsoleY | Windows Unix | INTEGER | Returns maximum row for console screen, useful under Unix.
Screen.Cursor | Windows | INTEGER | Change global mouse pointer
Screen.Cursors | Windows | ARRAY of INTEGER | R/W array of cursor handles.
Screen.Height | Windows | INTEGER | Returns Windows screen Height (not to be confused with Form Height)
Screen.MouseX | Windows | INTEGER | Returns X Coordinate of Mouse Pointer relative to your screen.
Screen.MouseY | Windows | INTEGER | Returns Y Coordinate of Mouse Pointer relative to your screen.
Screen.Width | Windows | INTEGER | Returns Windows screen Width
RAPIDQ2.INC extends these Methods and properties
Method | Type | Description | Params
CaptureToBMP | (Rect AS QRECT, CapBitMap AS QBITMAP) | Take a snapshot of the Screen by area defined in Rect. If Rect is NULL, then whole screen is captured. Returns False if failed | 2
CaptureToFile | (Rect AS QRECT, OutFileName AS STRING) | Screen Capture by area defined in Rect. If Rect is NULL, then whole screen is captured Returns False if failed | 2
ClientHeight | LONG | Get actual drawing area of screen | 0
ClientWidth | LONG | Get actual drawing area of screen | 0
EnumResolution | (ListView AS QLISTBOX) AS LONG | possible video modes are stored in a Qlistbox object | 2
GetPixel | (x AS INTEGER, y AS INTEGER) AS LONG | Get the RGB coded color of pixel at x, y on desktop, or active screen. | 2
GetPixelDepth | LONG | Find out the bits/pixel setting of the screen | 0
Monitors | LONG | How many monitors are connected ? | 0
MouseButtons | LONG | Returns how many mouse buttons | 0
MousePresent | LONG | Make sure the mouse is connected or not working | 0
MouseSwap | LONG | Reports if the user has swapped the left for the right mouse button. | 0
SetMouseXY | (X AS LONG, Y AS LONG) AS LONG | Place the mouse cursor at x, y on screen. | 2
SetResolution | (X AS DWORD, Y AS DWORD, bpp AS WORD, Freq AS DWORD) AS LONG | Set the screen resolution, pixel depth and monitor refresh rate. If the mode is not supported, a message box appears informing the Function has failed. Use EnumResolution to find out possible settings. This function should not make a permanent change in the users Registry. Freq (in Hertz) can be set to 0 for no change. Use with caution. | 4

SCREEN Events
Event | Type | Occurs when... | Params
None ...

SCREEN Examples

$INCLUDE "RapidQ2.INC"
ShowMessage "pixel depth of your screen = "+str$(Screen.GetPixelDepth())
ShowMessage "get ready to change your resolution!"
Screen.SetResolution(800,600,16,0)
ShowMessage "pixel depth= "+str$(Screen.GetPixelDepth())

DIM aRect AS QRECT 'if you want to capture the whole screen then don't set any values,
Screen.CaptureToFile(aRect, "C:\temp.bmp")'if you don't define Rect, then whole screen is captured
Screen.SetResolution(1024,768,32,0) 'or whatever you have....

Contents


SENDMESSAGE

SENDMESSAGE RAPID-Q Specific Windows
A WinAPI call to SendMessage, blocks until message is processed.

Syntax: SENDMESSAGE hWnd, uMsg, wParam, lParam
SENDMESSAGE Form.Handle, WM_SYSCOMMAND, SC_MINIMIZE, 0

Details:
SendMessage is a Windows API call so instead of filling this entire page with information you can look up this function in your WinAPI manual/help file. Note, this is not a function. If you need a return value , use the SendMessageAPI call in the RAPIDQ2.INC file:

returnVal = SendMessageAPI hWnd, uMsg, wParam, lParam


SETCAPTURE

SETCAPTURE Windows API Call in RapidQ2.INC Windows
Windows API that sets the mouse capture to the specified window belonging to the current program. Once a window has captured the mouse, all mouse input is directed to that window, regardless of whether the cursor is within the borders of that window. Only one window at a time can capture the mouse. This is a keyword in RAPIDQ2.INC

Syntax: Handle = SETCAPTURE(hWnd)
DIM aHandle AS LONG
aHandle = SETCAPTURE(Canvas.Handle)

Details:
If the function succeeds, the return value is the handle of the window that had previously captured the mouse. If there is no such window, the return value is NULL. See RELEASECAPTURE and GETCAPTURE


SETFOCUS Windows API Call in RapidQ2.INC Windows
A famous WinAPI call that sets the keyboard output to the specified control/component. The window must be associated with the calling program messages. This is a keyword in RAPIDQ2.INC

Syntax: SETFOCUS(hWnd)
SETFOCUS (Button.Handle)

Details:
You can find out which control is currently getting the focus with GETFOCUS.


SGN

SGN MATH Function Windows/Unix
A math function that indicates the sign of a numeric expression.

Syntax: SGN(numeric-expression)
A% = SGN(-123) '-- Returns -1

Details:
If numeric-expression is positive, SGN returns +1.
If numeric-expression is zero, SGN returns 0.
If numeric-expression is negative, SGN returns -1.


SHELL

SHELL SYSTEM Statement/Function Windows
SHELL can be called as a statement or as a function. It has the same functionality as RUN except that it blocks your application until the executed one has ended.

Syntax: SHELL command
SHELL "rapidq.exe"
Syntax: SHELL(command, showCMD)
PID = SHELL("rapidq.exe", SW_SHOWNORMAL)

Details:
If calling SHELL as a function, the return value is the process ID of the executed program, and will not block your program. showCMD can be any of the following:
0 = SW_HIDE              6 = SW_MINIMIZE
1 = SW_SHOWNORMAL        7 = SW_SHOWMINNOACTIVE
2 = SW_SHOWMINIMIZED     8 = SW_SHOWNA
3 = SW_SHOWMAXIMIZED     9 = SW_RESTORE
4 = SW_SHOWNOACTIVATE   10 = SW_SHOWDEFAULT
5 = SW_SHOW

Examples:
Shell "command.com /C copy /b one.txt+two.txt oneandtwo.txt"
x=Shell("Command.com /C echo y| del "+chr$(34) + ".\Original\*.*" +chr$(34) , 0)


SHOWMESSAGE

SHOWMESSAGE RAPID-Q Specific Windows/Unix
A statement used to display a generic popup message box.

Syntax: SHOWMESSAGE string-expression
SHOWMESSAGE "Hello world!"

Details
' to get mulitple lines in a ShowMessage box:
CONST CR = CHR$(13)
CONST LF = CHR$(10)
CONST CRLF = CR + LF
SHOWMESSAGE "This will be on" + CRLF + "two lines!"

OR

$ESCAPECHARS ON
SHOWMESSAGE "This will be on\r\ntwo lines!"


SIN

SIN MATH Function Windows/Unix
A math function that returns the sine of an angle given in radians.

Syntax: SIN(numeric-expression)
PI = 3.14153
C# = SIN(PI)

Details:
Numeric-expression is the angle expressed in radians.


SIZEOF

SIZEOF MEMORY Function Windows/Unix
A function that returns the size, in bytes, of a data type.

Syntax: SIZEOF(datatype|variable)
PRINT SIZEOF(MyUDT)
PRINT SIZEOF(MyVar)
PRINT SIZEOF(INTEGER)

Details:
To calculate the size of a UDT, you must first DIM it.
ie. DIM MyUDT AS TMyUDT
Not all cases are supported, may return 4 bytes for an array (the size of the array pointer since arrays are passed by reference).


SLEEP

SLEEP Keyword in RapidQ Windows/Unix
Pauses the program for a set amount of seconds. Very little or no CPU processing will be used while the program is Sleeping. Use this for keeping a form in the Background without using the CPU..

Example:
SLEEP 1.5 'pause program execution for 1.5 seconds


SLEEP.MS

SLEEP.ms Keyword in RapidQ Windows/Unix
If you have RapidQ2.INC you can also use the Sleep.ms to pause the program in milliseconds:
Sleep.ms(ms AS DWORD)

Sleep.ms 500 'pause program execution for half a second (500 milliseconds).

Remarks:
Specifies the time, in milliseconds, for which to suspend execution. A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. There is a WINDOWS constant
$define INFINITE &HFFFFFFFF
That will cause Sleep.ms to loop indefinitely....


SOUND

SOUND I/O Statement Windows
A device I/O statement that generates sound through the PC Speaker.

Syntax: SOUND frequency, duration
SOUND 4000, 18

Details:
May not be supported in Windows versions later than Win98.
  • Frequency is a numeric expression whose value is between 37 and 32,767. Frequency is measured in cycles/second, or hertz.
  • Duration is a numeric expression whose value is between 0 and 65,535. There are 18.2 clock ticks per second, so 18 is considered 1 second, etc...


SPACE$

SPACE$ STRING Function Windows/Unix
A string function that returns a string of spaces of length n.

Syntax: SPACE$(n)
A$ = SPACE$(5)


SQR

SQR MATH Function Windows/Unix
A math function that returns the square root of a number.

Syntax: SQR(numeric-expression)
A# = SQR(9) '-- returns 3


STATIC

STATIC Statement Windows/Unix
Similar to DIM, this statement names one or more variables and allocates storage space for them. However, declaring STATIC variables means that variable values are preserved between procedure calls. Note that only simple types are affected.

Syntax: STATIC variable[(subscripts)] AS type
STATIC A AS INTEGER, B AS BYTE, S AS STRING

Details:
STATIC has no affect (ie. same as using DIM) when declared in the main module. Use STATIC only inside a SUB/I or FUNCTION/I.

Examples:
    '-- Non static count
    SUB Count (N AS INTEGER)
       DIM B AS LONG

       B = N
       IF N = 10 THEN EXIT SUB
       Count(N+1)
       PRINT B
    END SUB

    Count(1)

    '-- Static count, B retains the same value
    SUB StaticCount (N AS INTEGER)
       STATIC B AS LONG

       B = N
       IF N = 10 THEN EXIT SUB
       StaticCount(N+1)
       PRINT B
    END SUB

    StaticCount(1)


STR$

STR$ CONVERSION Function Windows/Unix
A conversion function that returns a string representation of the value of a numeric expression.

Syntax: STR$(numeric-expression)
A$ = STR$(99)


STRF$

STRF$ CONVERSION Function Windows
A conversion function that returns a formatted string representation of the value of a numeric expression.

Syntax: STRF$(numeric-expression, Format%, Precision%, Digits%)
A$ = STRF$(99.9934, ffGeneral, 4, 4)
A$ = STRF$(12345678, ffNumber, 8, 0)

Details:
Precision% specifies how many decimal places to calculate.
The following are valid Formats:
0 = ffGeneral      2 = ffFixed1 = ffExponent     3 = ffNumber
ffGeneral converts to the shortest possible decimal string, where trailing zeros are removed. Digits% range from values of 0 to 4.
ffExponent converts to scientific notation of the form -d.ddd...E+dddd. Digits% range from values of 0 to 4.
ffFixed converts to fixed point format of the form -ddd.ddd... Digits% range from values of 0 to 18.
ffNumber converts to a number format of the form -d,ddd,ddd.ddd... Where the resulting string contains thousand separators.


STRING$

STRING$ STRING Function Windows/Unix
A string function that returns a string whose characters all have a given ASCII code or whose characters are all the first character of a string expression.

Syntax: STRING$(count, byte)
A$ = STRING$(9, 65) '-- Returns AAAAAAAAA
Syntax: STRING$(count, string-expression)
A$ = STRING$(9, "ABC") '-- Returns AAAAAAAAA

Details:
The first parameter indicates the number of times to repeat the character. The second parameter can either be a string expression, whose first character is used as the repeat character, or a byte number in the range from 0 to 255 representing the ASCII character code.


SUPER

SUPER Custom Component Keyword Windows/Unix
In Rapid-Q custom components, all methods, properties, and events can be overridden. To access the original property or method, you must explicitly call the SUPER class as demonstrated below. Becareful if using WITH Super ... END WITH, since all properties/methods will be referenced as the super class. The concept of overriding properties or methods is simple enough, instead of using the inherited properties, we can just redefine them instead. ALSO SUPER only takes values not variables... (odd bug)
     TYPE QDiamondBox EXTENDS QCanvas
        Left AS STRING
        Top AS BYTE

        SUB Pset
            PRINT Super.Left
        END SUB
     END TYPE


SWAP

SWAP Statement Windows/Unix
An assignment statement that exchanges the values of 2 variables.

Syntax: SWAP variable1, variable2
SWAP A$, B$

Details:
Variable1 and variable2 should be of the same type, but Rapid-Q won't complain. Also, do not swap variants using the SWAP function if their types do not match.


TALLY

TALLY STRING Function Windows/Unix
Tally counts the number of occurrences of MatchString within a SearchString.

Syntax: TALLY(search-string, match-string)
Count& = TALLY("abcdefghijklmnabc", "abc") '-- returns 2


TAN

TAN MATH Function Windows/Unix
A math function that returns the tangent of an angle given in radians.

Syntax: TAN(numeric-expression)
T# = TAN(90)

Details:
Numeric-expression is the angle expressed in radians.


tasklist

ADDRESS
ARRAY
Assembler
Console
CONVERSION
Device input/output
Display graphic images Directories
DLL
Files
Loops
Manage memory
MATH Function
Mouse
Relational Operators
Logical Operators
Functional Operators
POINTER
PRINTER
Procedures, Functions
RESOURCE
SORTING
Strings
fixed-length strings
SYSTEM
Types
Variables
VARIANT

ADDRESS
CALLBACK
VARPTR
VARPTR$
ARRAY
INITARRAY
DEF...
DIM
LBOUND
MEMSET
QUICKSORT
REDIM
UBOUND
CONVERSION
BIN$
RGB
CEIL
CINT
CLNG
CONVBASE$
 FIX
FLOOR
FRAC
HEX$
 INT - Convert NumericExpression to a 32-bit INTEGER, truncating decimals

vidnum$- returns the string representation of a rounded numeric
 Hex2Dec
DecToHex
Add0Before

CONSOLE
Writing Console Applications
GET$
INKEY$
INPUT
LOCATE
PCOPY
PEEK
POKE
PRINT
SETCONSOLETITLE
input/output
INP
INPW
Display graphic images
Directories
 CHDIR
CHDRIVE
CURDIR$
DIREXISTS
DIR$
 MKDIR
QDIRTREE
RMDIR

SYSDIR Retrieves windows shell directories
HOMEDIR The folder where the application is

DLL
LIB
LIBRARYINST
UNLOADLIBRARY
Files
Introduction to streams
FILEEXISTS
 KILL
QFILESTREAM
QFILELISTBOX

 STRIPPATH - Returns file path (without file name)
STIPFILENAME - Returns file name (without path)
STRIPFILEEXT - Returns file extension (like ".exe", ".html" etc.)
FILENAMENOEXT - Returns file name without extension
FULLPATHNOEXT - Returns full path without file extension
C_Style Returns "slashed" path from a "backslashed" one

ChangeFileExt - Changes the extention of FileName to NewExt
 ExtractFileName - Returns only the file name
 ExtractFilePath - returns only the path
ChangeFileName - create string with new filename with the same path
 ChangeFilePath - create string with new path with the same filename
Functions
 SUBI, FUNCTIONI, and DLLs
Rapid-Q Sub & Functions
PARAMSTR$
PARAMSTRCOUNT
Loops
Loops
FOR .. NEXT Loop
 EXIT FOR
WHILE .. WEND
EXIT WHILE
DO .. LOOP
EXIT DO
Math Function
Arithmetic operators
ABS
ACOS
ASIN
ATAN
ATN
COS
DEC
EXP
INC
 INV
 LOG
MOD
RANDOMIZE
RND
ROUND
SGN
SIN
SQR
 TAN

also see CONVERSION
Manage memory
MEMCMP
MEMCMP [2]
MEMCPY
MEMCPY [2]
MEMSET
 MEMSET [2]
Mouse
MOUSEX, MOUSEY
POINTER
BIND
BIND
CALLFUNC
CALLFUNC
PRINTER
LPRINT
LFLUSH
PRINTER
Procedures
RESOURCE
EXTRACTRESOURCE
RESOURCE
RESOURCECOUNT
SORTING
QUICKSORT
Strings

Custom functions
QUOTE - Returns a quoted string
STRIPPATH - Returns file path (without file name)
STIPFILENAME - Returns file name (without path)
STRIPFILEEXT - Returns file extension (like ".exe", ".html" etc.)
FILENAMENOEXT - Returns file name without extension
FULLPATHNOEXT - Returns full path without file extension

ASC
BIN$
CHR$
CONVBASE$ - Bin to Hex, ets.
DATE$ - MM-DD-YYYY
DELETE$
FIELD$
FORMAT$
HEX$
INKEY$
INSERT$
INSTR
LCASE$
LEFT$
LEN
LTRIM$
MID$
REPLACE$
REPLACESUBSTR$
REVERSE$
RIGHT$
RINSTR
RTRIM$
SPACE$
STRING$
STR$
STRF$
TALLY
TIME$
UCASE$

SYSTEM
ENVIRON$

Types
objects
variants
udts
arrays
INITARRAY
DIM Array
Saving/Loading UDTs and Arrays
DEF
Set traps for events and errors
Relational
Functional
Logical
AND
Variables
 Variables and Assignments
BYTE (?)
WORD (??)
DWORD (???)
SHORT (%)
LONG (&) or INTEGER
SINGLE (!)
DOUBLE (#)
STRING ($)
VARIANT


THIS

THIS QOBJECT Function inside EXTENDS Windows/Unix
The keyword THIS is used as a handy reference to the component/object name inside a
TYPE EXTENDS QOBJECT/Q..... END TYPE statement block.
Example: THIS.Height = (numeric-expression)

TYPE MyObj EXTENDS QFORM
   Height as INTEGER

'you can set the Height property by using this line
 SUB SetHeight()
     THIS.Height = 30
END SUB
'
END TYPE

Details:
See extending custom components


TIME$

TIME$ SYSTEM Function Windows/Unix
A function that returns a string containing the current time formatted as HH:MM:SS. Where HH = hour (0-23), MM = minute (0-59) and SS = seconds (0-59)

Syntax: TIME$
PRINT TIME$

Details:
Unlike QBasic where you can set the current date using the TIME$ statement, you cannot do this under Rapid-Q.


TIMER

TIMER SYSTEM Function Windows/Unix
A function that returns the number of seconds elasped since midnight.

Syntax: TIMER
T! = TIMER

Details:
Timer value for Linux/Unix is the number of seconds elasped since your program started.


UBOUND

UBOUND ARRAY Function Windows/Unix
A function that returns the upper bound of the array.

Syntax: UBOUND(arrayname [,dimension])
DIM A(-50 TO 100) AS INTEGER
L% = UBOUND(A) '-- Returns 100

Details:
If the array has multiple dimensions, you can use the optional dimension argument to check the upper bound of each one.

NOTE:
There is no checking for limits on arrays. You can "read" an array value outside that used in DIM, giving unpredictable results. Always keep track of your array start and end instead of LBOUND and UBOUND for the best results.

Do not use variable names with a variable symbol with %, !, #, etc.,
DIM A%(-50 TO 100) AS INTEGER
L% = UBOUND(A%) '-- Returns 0


UCASE$

UCASE$ STRING Function Windows/Unix
A string function that returns a string expression with all letters upper-case.

Syntax: UCASE$(string-expression)
A$ = UCASE$("Hello") '-- returns HELLO


UDTPTR

UDTPTR ADDRESS Function Windows/Unix
A function in RAPIDQ2.INC that returns the address, ie. pointer to, of a user defined type. Return value is a LONG. Use this function to type cast a UDT pointer to a value instead of passing by reference (i.e., BYREF).

Syntax: UDTPTR(variablename)
TYPE Obj
  a AS INTEGER
  b AS INTEGER
END TYPE
Addr& = UDTPTR(myObj)

also works for any variable passed by reference such as Arrays
Addr& = UDTPTR(MyArray(0)) 'be sure to reference the first element of your array

Details:
Unlike C/C++, you cannot get a pointer of a member inside a UDT--
VARPTR(MyRec.NumRecords). You cannot use it to get the address of a QOBJECT, like a QBITMAP, QFORM, etc.


UNLOADLIBRARY

UNLOADLIBRARY DLL Statement Windows
Removes DLL from memory (only those declared in Rapid-Q). If DLL hasn't been loaded or is not found, this statement does nothing.

Syntax: UNLOADLIBRARY(DLLName)
DECLARE FUNCTION UpdateWindow LIB "USER32" ALIAS _
"UpdateWindow" (hWnd AS LONG) AS LONG
UNLOADLIBRARY("USER32") '-- Removes USER32.DLL from memory

Details:
It is not required that you unload a DLL, this is done for you when your Rapid-Q program ends. Unloading a DLL library from memory does not mean the function call that requires the DLL will fail. The DLL is again reloaded into memory before the function call, so you can UnLoad it again if you want. Please note that library names should match, so in your declaration for LIB "USER32" ... to unload this library, you must match that same name. UNLOADLIBRARY("USER32.DLL") does nothing, it must be "USER32" in this particular case. See also LIBRARYINST.


Useful subs/functions

'========================================================================|
' Fileops is a set functions to manipulate file names and paths.         |
' QUOTE - Returns a quoted string                                        |
' STRIPPATH - Returns file path (without file name)                      |
' STIPFILENAME - Returns file name (without path)                        |
' STRIPFILEEXT - Returns file extension (like ".exe", ".html" etc.)      |
' FILENAMENOEXT - Returns file name without extension                    |
' FULLPATHNOEXT - Returns full path without file extension               |
'========================================================================|

Example code:
declare sub file_operations

create form as qform
       center
       width = 500

       create fl as qfilelistbox
       align = 3
       ondblclick = file_operations
       end create

       create re as qrichedit
       align = 5
       font.name = "Courier new"
       wordwrap = 0
       end create
showmodal
end create

sub file_operations
re.clear
dim sta as string
sta = fl.filename
re.addstrings "ORIGINAL FILE NAME" + chr$(9) + sta, _
              "QUOTED FILE NAME" + chr$(9) + quote(sta), _
              "FILE PATH" + chr$(9) + chr$(9) + StripPath(sta), _
              "FILE NAME" + chr$(9) + chr$(9) + stripfilename(sta), _
              "FILE EXTENSION" + chr$(9) + stripfileext(sta), _
              "WITHOUT EXTENSION" + chr$(9) + filenamenoext(sta), _
              "FULL NAME (NO EXT)" + chr$(9) + fullpathnoext(sta)
end sub

Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_ATTRIBUTE_COMPRESSED = &H800

Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type

Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA"_
(ByVal lpFileName As String) As Long
Declare Function SetFileAttributes Lib "kernel32" Alias "SetFileAttributesA"_
(ByVal lpFileName As String, ByVal dwFileAttributes As Long) As Long

Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" _
(ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long

' QUOTE : Returns a quoted string
function Quote (StringToQuote as string) as string
StringToQuote =  chr$(34) + StringToQuote + chr$(34)
result = replacesubstr$(stringtoquote, chr$(34) + chr$(34), chr$(34))
end function

'===============================================================================
' STRIPPATH : Returns file path (without file name)
Function StripPath (fullname as string) as string
result = left$(fullname, rinstr(fullname, "\"))
end function

'===============================================================================
' STRIPFILENAME : Returns file name (without path)
Function StripFileName (fullname as string) as string
result = right$(fullname, len(fullname) - rinstr(fullname, "\"))
end function

'===============================================================================
' STRIPFILEEXT : Returns file extension (like ".exe", ".html" etc.)
Function StripFileExt (fullname as string) as string
result = right$(fullname, len(fullname) - rinstr(fullname, ".") + 1)
end function

'===============================================================================
' FILENAMENOEXT : Returns file name without extension
function FileNameNoExt(fullname as string) as string
fullname = right$(fullname, len(fullname) - rinstr(fullname, "\"))
result = left$(fullname, rinstr(fullname, ".") - 1)
end function

'===============================================================================
' FULLPATHNOEXT : Returns full path without file extension
function FullPathNoExt(fullname as string) as string
result = left$(fullname, rinstr(fullname, ".") - 1)
end function

'===============================================================================
' C_Style : Returns "slashed" path from a "backslashed" one
function C_Style (fullname as string) as string
fullname = replacesubstr$(fullname, "\\", "\")
result = replacesubstr$(fullname, "\", "/")
end function

'===============================================================================
' SYSDIR : Retrieves windows shell directories

'-------------------------|
' Allowed values for dir  |
'-----------------------------------------------------------------------------|
' Desktop                 | Templates               | AppData                 |
' Start Menu              | Programs                | Startup                 |
' Fonts                   | SendTo                  | Recent                  |
' Favorites               | Cache                   | Cookies                 |
' History                 | NetHood                 | Personal                |
' PrintHood               | Local AppData           | My Pictures             |
' Administrative Tools    |                         |                         |
'-----------------------------------------------------------------------------|

function SysDir (dir as string) as string
DIM fo_reg AS QRegistry
fo_reg.RootKey = &H80000001
fo_reg.openkey ("Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", 0)
result = fo_reg.readstring(dir) + "\"
end function

'===============================================================================
' HOMEDIR : The folder where the application is

function homedir() as string
result = left$(command$(0), rinstr(command$(0), "\"))
end function

'===============================================================================
' BROWSEFORFOLDERS : Returns the selected folder

function BrowseForFolders (initialdir as string, wincapt as string) as string
dim bff_form as qform
with bff_form
.height = 400
.center
.caption = wincapt
.delbordericons 2
end with
dim bff_tree as qdirtree
with bff_tree
.parent = bff_form
.align = 5
end with
if bff_form.caption = "" then bff_form.caption = "Select folder"
if direxists(initialdir) then
bff_tree.directory = initialdir
else
bff_tree.directory = curdir$
end if
bff_form.showmodal
result = bff_tree.directory
end function

'===============================================================================
' BROWSEFORFILE : Returns the selected folder

Function BrowseForFile (caption as string, filter as string, _
initialdir as string) as string

dim bff_od as qopendialog
with bff_od
.caption = caption
.filter = filter
.initialdir = initialdir

if .execute then
    result = .filename
end if
end with

end function

$ESCAPECHARS ON

'ChangeFileExt:
'Returns: String
'Parameters:
'FileName (String): Name of file with old extention
'NewExt (String): New extention. This must include the leading ".".

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'Changes the extention of FileName to NewExt. For example:
'ChangeFileExt("File.bas", ".inc")
'returns File.inc. This function does not delete the old string,
'instead, it simply returns a new one with the extention.
'You must include the leading "." for it to be added, as it is not
'done by the function.

FUNCTION ChangeFileExt(FileName as String, NewExt as STRING) as STRING
    DIM Returns as STRING
    DIM CurrentExt as String
    DIM CurrentExtLoc as INTEGER
    DIM FileNoExt as STRING

    CurrentExtLoc = RInStr(FileName, ".")
    CurrentExt = MID$(FileName, CurrentExtLoc, LEN(FileName))
    FileNoExt = DELETE$(FileName, CurrentExtLoc, LEN(FileName))

    Result = INSERT$(NewExt, FileNoExt, LEN(FileName))
    ChangeFileExt = Result
END FUNCTION

'ExtractFileName:
'Returns: String
'Parameters:
'FileName (String): File with full path

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ExtractFileName takes a file name with a path and returns only
'the file name. For example:
'ExtractFileName("C:\\Program Files\\AFile.bas")
'returns AFile.bas. You can use either two back-slashes or a single
'forward slash (/) for folder seperators.
'Both forward and back-slashes are supported by Windows.
'The back-slash takes procedure over the forward slash.
'Note that ExtractFileName does _not_ check the validity of the path passed.
'You must check yourself.

FUNCTION ExtractFileName(FileName as STRING) AS STRING
    DIM Length as INTEGER
    DIM Result as STRING

    Length = RInStr(FileName, "\\") OR RInStr(FileName, "/")
    Result = MID$(FileName, Length+1, LEN(FileName) - Length + 1)
    ExtractFileName = Result
END FUNCTION

'ExtractFilePath
'Returns: String
'Parameters:
'FileName (String): File with full path

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ExtractFilePath takes string with full path and returns a string
'with only the path. For example:
'ExtractFilePath("C:\\Program Files\\AProgram.bas")
'returns C:\Program Files (the \\'s are for RQ and back-slashes).
'ExtractFilePath also takes forward-slashes (/). Window's supports
'these as well.
'The back-slash takes procedure over the forward slash.
'Note that ExtractFilePath does _not_ test the validity
'of the passed name. You must check it yourself. Even if the name is
'invalid, the path will be returned. For example, if C:/ProgramErrorFiles/AFile.txt
'is passed, C:/ProgramErrorFiles will be returned.

FUNCTION ExtractFilePath(FileName as STRING) AS STRING
    DIM Length as INTEGER
    DIM Result as STRING

    Length = RInStr(FileName, "\\") OR RInStr(FileName, "/")
    Result = MID$(FileName, 0, Length)
    ExtractFilePath = Result
END FUNCTION

'ChangeFileName
'Returns: String
'Parameters:
'FileName (String): File with full path
'NewName (String): Text that will replace old file name

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ChangeFileName takes a file name with full path and file and a new name.
'It replaces the current filename (in FileName) and replaces it with NewName.
'ChangeFileName does not actually change FileName, instead it returns a new
'string which contains the new name.
'Note that ChangeFileName does not check the validity of FileName
'or the new result. You must do it yourself (if you want). ChangeFileName
'takes both the back-slash and forward slash to serperate folder and file names.
'You can use either \\ or /. Both are supported by Windows.
'The back-slash takes procedure over the forward slash.

FUNCTION ChangeFileName(FileName as STRING, NewName as STRING) AS STRING
    DIM FileNameLoc as INTEGER
    DIM Result as STRING
    DIM PathNoName AS STRING

    PathNoName = ExtractFilePath(FileName)
    Result = PathNoName+NewName
    ChangeFileName = Result
END FUNCTION

'ChangeFilePath
'Returns: String
'Parameters:
'FileName (String): File with full path
'NewPath (String): New path that will replace the path in FileName

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ChangeFilePath takes FileName and replaces the path with NewPath.
'It does not change FileName to have the new path, instead, it returns
'a string which has the new path. It's up to you to take the correct
'action. Also, old or new path and names' are not checked for validity,
'you must do it yourself.
'You may use either the \\ or the / to seperate your paths. Windows supports
'both.

FUNCTION ChangeFilePath(FileName as STRING, NewPath as STRING) AS STRING
    DIM Result AS STRING
    DIM FileNoPath AS STRING

    FileNoPath = ExtractFileName(FileName)

    Result = NewPath+FileNoPath
    ChangeFilePath = Result
END FUNCTION

Const FILE_ATTRIBUTE_READONLY = &H1
Const FILE_ATTRIBUTE_HIDDEN = &H2
Const FILE_ATTRIBUTE_SYSTEM = &H4
Const FILE_ATTRIBUTE_DIRECTORY = &H10
Const FILE_ATTRIBUTE_ARCHIVE = &H20
Const FILE_ATTRIBUTE_NORMAL = &H80
Const FILE_ATTRIBUTE_TEMPORARY = &H100
Const FILE_ATTRIBUTE_COMPRESSED = &H800

Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Declare Function GetFileAttributes Lib "kernel32" Alias "GetFileAttributesA"_
 (ByVal lpFileName As String) As Long
Declare Function SetFileAttributes Lib "kernel32" Alias "SetFileAttributesA"_
 (ByVal lpFileName As String, ByVal dwFileAttributes As Long) As Long

Declare Function CreateDirectory Lib "kernel32" Alias "CreateDirectoryA" _
(ByVal lpPathName As String, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long

'# QUOTE : Returns a quoted string
function Quote (StringToQuote as string) as string
StringToQuote =  chr$(34) + StringToQuote + chr$(34)
result = replacesubstr$(stringtoquote, chr$(34) + chr$(34), chr$(34))
end function

'===============================================================================
'# STRIPPATH : Returns file path (without file name)
Function StripPath (fullname as string) as string
result = left$(fullname, rinstr(fullname, "\"))
end function

'===============================================================================
'# STRIPFILENAME : Returns file name (without path)
Function StripFileName (fullname as string) as string
result = right$(fullname, len(fullname) - rinstr(fullname, "\"))
end function

'===============================================================================
'# STRIPFILEEXT : Returns file extension (like ".exe", ".html" etc.)
Function StripFileExt (fullname as string) as string
result = right$(fullname, len(fullname) - rinstr(fullname, ".") + 1)
end function

'===============================================================================
'# FILENAMENOEXT : Returns file name without extension
function FileNameNoExt(fullname as string) as string
fullname = right$(fullname, len(fullname) - rinstr(fullname, "\"))
result = left$(fullname, rinstr(fullname, ".") - 1)
end function

'===============================================================================
'# FULLPATHNOEXT : Returns full path without file extension
function FullPathNoExt(fullname as string) as string
result = left$(fullname, rinstr(fullname, ".") - 1)
end function

'===============================================================================
'# C_Style : Returns "slashed" path from a "backslashed" one
function C_Style (fullname as string) as string
fullname = replacesubstr$(fullname, "\\", "\")
result = replacesubstr$(fullname, "\", "/")
end function

'===============================================================================
'# SYSDIR : Retrieves windows shell directories

'-------------------------|
' Allowed values for dir  |
'-----------------------------------------------------------------------------|
' Desktop                 | Templates               | AppData                 |
' Start Menu              | Programs                | Startup                 |
' Fonts                   | SendTo                  | Recent                  |
' Favorites               | Cache                   | Cookies                 |
' History                 | NetHood                 | Personal                |
' PrintHood               | Local AppData           | My Pictures             |
' Administrative Tools    |                         |                         |
'-----------------------------------------------------------------------------|

function SysDir (dir as string) as string
DIM fo_reg AS QRegistry
fo_reg.RootKey = &H80000001
fo_reg.openkey ("Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", 0)
result = fo_reg.readstring(dir) + "\"
end function

'===============================================================================
'# HOMEDIR : The folder where the application is

function homedir() as string
result = left$(command$(0), rinstr(command$(0), "\"))
end function

'===============================================================================
'# BROWSEFORFOLDERS : Returns the selected folder

function BrowseForFolders (initialdir as string, wincapt as string) as string
dim bff_form as qform
with bff_form
.height = 400
.center
.caption = wincapt
.delbordericons 2
end with
dim bff_tree as qdirtree
with bff_tree
.parent = bff_form
.align = 5
end with
if bff_form.caption = "" then bff_form.caption = "Select folder"
if direxists(initialdir) then
bff_tree.directory = initialdir
else
bff_tree.directory = curdir$
end if
bff_form.showmodal
result = bff_tree.directory
end function

'===============================================================================
'# BROWSEFORFILE : Returns the selected folder

Function BrowseForFile (caption as string, filter as string, _
initialdir as string) as string

dim bff_od as qopendialog
with bff_od
.caption = caption
.filter = filter
.initialdir = initialdir

if .execute then
    result = .filename
end if
end with

end function

'_=============================================================================

$ESCAPECHARS ON

'ChangeFileExt:
'Returns: String
'Parameters:
'FileName (String): Name of file with old extention
'NewExt (String): New extention. This must include the leading ".".

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'Changes the extention of FileName to NewExt. For example:
'ChangeFileExt("File.bas", ".inc")
'returns File.inc. This function does not delete the old string,
'instead, it simply returns a new one with the extention.
'You must include the leading "." for it to be added, as it is not
'done by the function.

FUNCTION ChangeFileExt(FileName as String, NewExt as STRING) as STRING
    DIM Returns as STRING
    DIM CurrentExt as String
    DIM CurrentExtLoc as INTEGER
    DIM FileNoExt as STRING

    CurrentExtLoc = RInStr(FileName, ".")
    CurrentExt = MID$(FileName, CurrentExtLoc, LEN(FileName))
    FileNoExt = DELETE$(FileName, CurrentExtLoc, LEN(FileName))

    Result = INSERT$(NewExt, FileNoExt, LEN(FileName))
    ChangeFileExt = Result
END FUNCTION

'ExtractFileName:
'Returns: String
'Parameters:
'FileName (String): File with full path

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ExtractFileName takes a file name with a path and returns only
'the file name. For example:
'ExtractFileName("C:\\Program Files\\AFile.bas")
'returns AFile.bas. You can use either two back-slashes or a single
'forward slash (/) for folder seperators.
'Both forward and back-slashes are supported by Windows.
'The back-slash takes procedure over the forward slash.
'Note that ExtractFileName does _not_ check the validity of the path passed.
'You must check yourself.

FUNCTION ExtractFileName(FileName as STRING) AS STRING
    DIM Length as INTEGER
    DIM Result as STRING

    Length = RInStr(FileName, "\\") OR RInStr(FileName, "/")
    Result = MID$(FileName, Length+1, LEN(FileName) - Length + 1)
    ExtractFileName = Result
END FUNCTION

'ExtractFilePath
'Returns: String
'Parameters:
'FileName (String): File with full path

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ExtractFilePath takes string with full path and returns a string
'with only the path. For example:
'ExtractFilePath("C:\\Program Files\\AProgram.bas")
'returns C:\Program Files (the \\'s are for RQ and back-slashes).
'ExtractFilePath also takes forward-slashes (/). Window's supports
'these as well.
'The back-slash takes procedure over the forward slash.
'Note that ExtractFilePath does _not_ test the validity
'of the passed name. You must check it yourself. Even if the name is
'invalid, the path will be returned. For example, if C:/ProgramErrorFiles/AFile.txt
'is passed, C:/ProgramErrorFiles will be returned.

'-- *****************************************************'
FUNCTION ExtractFilePath(FileName as STRING) AS STRING
    DIM Length as INTEGER
    DIM Result as STRING

    Length = RInStr(FileName, "\\") OR RInStr(FileName, "/")
    Result = MID$(FileName, 0, Length)
    ExtractFilePath = Result
END FUNCTION

'ChangeFileName
'Returns: String
'Parameters:
'FileName (String): File with full path
'NewName (String): Text that will replace old file name

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ChangeFileName takes a file name with full path and file and a new name.
'It replaces the current filename (in FileName) and replaces it with NewName.
'ChangeFileName does not actually change FileName, instead it returns a new
'string which contains the new name.
'Note that ChangeFileName does not check the validity of FileName
'or the new result. You must do it yourself (if you want). ChangeFileName
'takes both the back-slash and forward slash to serperate folder and file names.
'You can use either \\ or /. Both are supported by Windows.
'The back-slash takes procedure over the forward slash.

'-- *****************************************************'
FUNCTION ChangeFileName(FileName as STRING, NewName as STRING) AS STRING
    DIM FileNameLoc as INTEGER
    DIM Result as STRING
    DIM PathNoName AS STRING

    PathNoName = ExtractFilePath(FileName)
    Result = PathNoName+NewName
    ChangeFileName = Result
END FUNCTION

'ChangeFilePath
'Returns: String
'Parameters:
'FileName (String): File with full path
'NewPath (String): New path that will replace the path in FileName

'Information:
'Author: Taj Morton
'Email: tmorton at linuxmail dot org.
'License: Public Domain

'Description:
'ChangeFilePath takes FileName and replaces the path with NewPath.
'It does not change FileName to have the new path, instead, it returns
'a string which has the new path. It's up to you to take the correct
'action. Also, old or new path and names' are not checked for validity,
'you must do it yourself.
'You may use either the \\ or the / to seperate your paths. Windows supports
'both.

'-- *****************************************************'
FUNCTION ChangeFilePath(FileName as STRING, NewPath as STRING) AS STRING
    DIM Result AS STRING
    DIM FileNoPath AS STRING

    FileNoPath = ExtractFileName(FileName)

    Result = NewPath+FileNoPath
    ChangeFilePath = Result
END FUNCTION
$ESCAPECHARS Off

'-- *****************************************************'
FUNCTION FileSize(FileName as STRING) AS integer
DIM fileStr as QFileStream

if fileexists (FileName)>0 then
fileStr.open (FileName,0)
result=	fileStr.size
fileStr.close
else
result=-1
end if

END FUNCTION
'-- *****************************************************'
FUNCTION SaveString(ss$ as STRING ,FileName as STRING  ) AS integer
result=0

if FileName="" then showmessage ("FUNCTION SaveString. Wrong FileName="+FileName):exit function
DIM fileStr as QFileStream
fileStr.open (FileName,65535 ) 'fmCreate'
result=-1
FileStr.WriteStr(ss$, len(ss$))
FileStr.Close
result=1
END FUNCTION

'-- *****************************************************'
FUNCTION SaveStringEx(ss$ as STRING ,FileName as STRING, mode as integer  ) AS integer
' save string SS$ to file FileName.
'Mode=0 - overwrite,
'Mode=1 - append string ss$ to file FileName
'Mode=2 - append  crlf+ss$ to file FileName

result=0

if FileName="" then showmessage ("FUNCTION SaveString. Wrong FileName="+FileName):exit function

DIM fileStr as QFileStream

if mode=0 then
    result=0
    fileStr.open (FileName,65535 ) 'fmCreate'
    result=-1
    FileStr.WriteStr(ss$, len(ss$))
    FileStr.Close
elseif mode=1 or mode=2 then
    if fileexists(FileName)=0 then md=65535:crl="" else md=2:crl$=crlf 'showmessage ("FUNCTION SaveString. Can't open File="+FileName):exit function
    fileStr.open (FileName,md ) 'fmOpenReadWrite = 2
    fileStr.Position=fileStr.size
    result=-1
    if mode=1 then FileStr.WriteStr(ss$, len(ss$)) else FileStr.WriteStr(crl$+ss$, len(crl$+ss$))
    FileStr.Close
else
end if

result=1

END FUNCTION

'-- *****************************************************'
FUNCTION LoadString(FileName as STRING  ) AS string
DIM fileStr as QFileStream
result="0"
'fmOpenRead = 0
if fileStr.open (FileName,0 ) then'fmCreate'
result="-1"
result=FileStr.ReadStr( FileStr.size)
FileStr.Close
'result=1
end if

END FUNCTION

'_==============================================================

'-- *****************************************************'

function MKSubDir (DirDst$) as short
'Andrew Shelkovenko dec 2003, jul 2004
'Create DirDst$ directory with full subdir structure
'----------------------------------------------
'print "MKSubDir DirDst$="; DirDst$
result=0
dim DirDst1$ as string
DirDst1$=string$(len(DirDst$),"a")
'chartooem DirDst$,DirDst1$
DirDst1$=DirDst$

if right$(DirDst1$,1)<>BkSl then DirDst1$=DirDst1$+BkSl
z1=instr(DirDst1$,BkSl)
z2=0
while z1>0
SubDirDst$=left$(DirDst1$,z1 )
if DIREXISTS(SubDirDst$)=0 then MKDIR SubDirDst$ :'print "MKSubDir SubDirDst$=" ,SubDirDst$
z2=z1+1
z1=instr(z2,DirDst1$,BkSl)
wend

result=1
end function

'-- *****************************************************'
sub SubDirCopy (DirSrc$, DirDst$, mask$) '- -----------------------------------'
'Andrew Shelkovenko dec 2003
'Copy DirSrc$ directory with full subdir structure and files (by mask$) to DirDst$
dim FileSrc as QFileStream
dim FileDst as QFileStream

'Index=0
NumFiles=0
defint nsd1, nsd2
defstr mask
nsd1=0:nsd2=0
NumDir=0
ArrNumDir=500
dim SubDir(500) as string

ArrNumFil=500
dim FileNames (500) as string
mask="*.*"
if right$(DirSrc$,1)<> BkSl then DirSrc$=DirSrc$+BkSl
if right$(DirDst$,1)<> BkSl then DirDst$=DirDst$+BkSl
SubDir(0)=DirSrc$

sss1:
for i=NSD1 to Nsd2 'current level sudirs'
'print "374 SubDir(",i,")=",SubDir(i)
SubDirname$=dir$(SubDir(i)+mask, faDirectory)

while    SubDirname$ <>""
  if FileRec.Size =0 and SubDirname$<> "." and SubDirname$<> ".." then ''
    inc adddir
    inc NumDir 'add subdir'
if NumDir=ArrNumDir then ArrNumDir=ArrNumDir+300: redim SubDir(ArrNumDir) as string
    SubDir(NumDir)=SubDir(i)+SubDirname$+"\"
    'print "383 SubDir(", NumDir, ")=",SubDir(NumDir)
else
end if
  SubDirname$=dir$
 doevents:if stops1=1 then stops1=0: exit sub
wend

'search files in current subdirectory
    Fn$=dir$(SubDir(i)+mask$,faAnyFile-faDirectory) ':-)
     while Fn$ <>""
if  Fn$<> "." and Fn$<> ".."  then 'and FileRec.Size <>0'
    inc NumFiles
if NumFiles=ArrNumFil then ArrNumFil=ArrNumFil+300: redim FileNames(ArrNumFil) as string:'print "redim FileNames"
 FileNames(NumFiles)=SubDir(i)+Fn$
 'print "FileNames(",NumFiles,")=" ,FileNames(NumFiles)

else
end if
    Fn$=dir$
     wend
next i

if adddir>0 then
NSD1=NSD2+1
NSD2=NSD2+adddir
adddir=0
goto sss1 'repeat with new sub level
else
end if

' got subdirs list in SubDir(i) array and file list with full path in FileNames(j)
' now create subdirs structure with new path

for i1=0 to i-1
NewSubDir$=SubDir(i1)-DirSrc$
NewSubDir$=DirDst$+NewSubDir$
MKSubDir (NewSubDir$)
next i1

for j=1 to NumFiles
FileSrc.Open(FileNames(j), fmOpenRead)
if FileSrc.size=0 then FileSrc.close: goto nextj1

NewFileName$=FileNames(j)-DirSrc$
NewFileName$=DirDst$+NewFileName$
'print "NewFileName$=" ,NewFileName$
FileDst.Open(NewFileName$, fmCreate)
FileDst.CopyFrom  (FileSrc, 0)''
        FileSrc.close''
        FileDst.close
nextj1:
next j

end sub

'-- *****************************************************'
function fSubDirCopy (DirSrc$, DirDst$, mask$) as long '- -----------------------------------'
'Andrew Shelkovenko dec 2003
'Copy DirSrc$ directory with full subdir structure and files (by mask$) to DirDst$
'DiaMsg$="Начало копирования.."

dim FileSrc as QFileStream
dim FileDst as QFileStream

result=-1
'Index=0
NumFiles=0
defint nsd1, nsd2
defstr mask
nsd1=0:nsd2=0
NumDir=0
ArrNumDir=500
dim SubDir(500) as string

ArrNumFil=500
dim FileNames (500) as string
mask="*.*"
if right$(DirSrc$,1)<> BkSl then DirSrc$=DirSrc$+BkSl
'print "DirSrc$="; DirSrc$
if right$(DirDst$,1)<> BkSl then DirDst$=DirDst$+BkSl
'print "DirDst$="; DirDst$

SubDir(0)=DirSrc$

sss1:
for i=NSD1 to Nsd2 'current level sudirs'
'print "374 SubDir(",i,")=",SubDir(i)
SubDirname$=dir$(SubDir(i)+mask, faDirectory)

while    SubDirname$ <>""
  if FileRec.Size =0 and SubDirname$<> "." and SubDirname$<> ".." then ''
    inc adddir
    inc NumDir 'add subdir'
if NumDir=ArrNumDir then ArrNumDir=ArrNumDir+300: redim SubDir(ArrNumDir) as string:'DiaMsg$="‘Є ЁагҐ¬ Ї®¤¤ЁаҐЄв®аЁЁ "+SubDir(NumDir) 'SubDirname$
    SubDir(NumDir)=SubDir(i)+SubDirname$+"\"
    'print "383 SubDir(", NumDir, ")=",SubDir(NumDir)
'DiaMsg$="Сканируем поддиректории "+SubDir(NumDir) 'SubDirname$
else
end if
  SubDirname$=dir$
 doevents:if stops1=1 then stops1=0: exit function
wend

'DiaMsg$="Всего поддиректорий " +str$(NumDir)

'search files in current subdirectory
    Fn$=dir$(SubDir(i)+mask$,faAnyFile-faDirectory) ':-)
     while Fn$ <>""
if  Fn$<> "." and Fn$<> ".."  then 'and FileRec.Size <>0'
    inc NumFiles
if NumFiles=ArrNumFil then ArrNumFil=ArrNumFil+300: redim FileNames(ArrNumFil) as string:'DiaMsg$=str$(NumFiles)
 FileNames(NumFiles)=SubDir(i)+Fn$
 'print "FileNames(",NumFiles,")=" ,FileNames(NumFiles)
'DiaMsg$="Сканируем файлы "+FileNames(NumFiles)
else
end if
    Fn$=dir$
     wend
next i
result=-2

if adddir>0 then
NSD1=NSD2+1
NSD2=NSD2+adddir
adddir=0
goto sss1 'repeat with new sub level
else
end if

' got subdirs list in SubDir(i) array and file list with full path in FileNames(j)
' now create subdirs structure with new path

'DiaMsg$="Создаем директории... "
for i1=0 to i-1
NewSubDir$=SubDir(i1)-DirSrc$
NewSubDir$=DirDst$+NewSubDir$
MKSubDir (NewSubDir$)
'DiaMsg$="Создали директорию "+NewSubDir$
next i1
result=-3

'DiaMsg$="Копируем файлы..."

for j=1 to NumFiles
'DiaMsg$="Пытаемся открыть файл "+FileNames(j)
'DiaMsg$="Try to open file "+NewFileName$

FileSrc.Open(FileNames(j), fmOpenRead)
'DiaMsg$="Открыли "+FileNames(j) +" размер=" +str$( FileSrc.size)
'print "opened " +FileNames(j)

'print "FileSrc.size=" ,FileSrc.size

if FileSrc.size=0 then
FileSrc.close:
'print "zerosize closed " +FileNames(j):
goto nextj
end if

NewFileName1$=FileNames(j)-DirSrc$
NewFileName$=DirDst$+NewFileName1$

'print "NewFileName$=" ,NewFileName$
'DiaMsg$="Пытаемся создать файл "+NewFileName1$
'DiaMsg$="Try to create file "+NewFileName$

FileDst.Open(NewFileName$, fmCreate)
'DiaMsg$="Пытаемся скопировать файл " +FileNames(j) +" в "+NewFileName1$
'print "DiaMsg$=" ,DiaMsg$
'DiaMsg$="Try to copy "

FileDst.CopyFrom  (FileSrc, 0)''
        FileSrc.close''
        FileDst.close
'DiaMsg$="Copied "+str$(j) + " from "+ str$(NumFiles)+" = "+ NewFileName$
DiaMsg$="Скопировано файлов "+str$(j)'FileNames(j) '+" в "+NewFileName$

nextj:
doevents
next j

result=j-1
'DiaMsg$="Всего скопировано файлов"+ str$(result) + " из "+ str$(NumFiles)

end function

'-- ***********************************************************************'
function DirCopy (DirSrc$, DirDst$, mask$) as long
'print "DirCopy mask$=" ,mask$
'print "DirCopy DirDst$=" ,DirDst$
'print "DirCopy DirSrc$=" ,DirSrc$
'Andrew Shelkovenko dec 2003
'Copy files (by mask$) from DirSrc$ to DirDst$
result=0
dim FileSrc as QFileStream
dim FileDst as QFileStream
defint NumFIles
NumFIles=0
'MKDIR DirDst$
rz=MKSubDir (DirDst$)
if right$(DirSrc$,1)<>"\" then DirSrc$=DirSrc$+"\"

if direxists(DirDst$) =0 then
showmessage ("DirCopy Error: Can't create folder "+DirDst$)
exit function
end if
'print "DirCopy DirSrc$+mask$=" ,DirSrc$+mask$

FileName$ = DIR$(DirSrc$+mask$, 0) '-- Get first file
'print "DirCopy FileName$=" ,FileName$

while    FileName$ <>""
    FileSrc.Open(DirSrc$+filename$, fmOpenRead)
    FileDst.Open(DirDst$ +"\"+filename$, fmCreate)
    FileDst.CopyFrom  (FileSrc, 0)
    FileSrc.close
    FileDst.close
    FileName$ = DIR$ '-- Get next file
    inc NumFIles
wend
'print "DirCopy copied= "+str$(NumFIles) +" files
result=NumFIles
end function

'-- ***********************************************************************'
sub FileCopy (FileSrc$, FileDst$) '- -----------------------------------'
'Andrew Shelkovenko dec 2003
'Copy FileSrc$ to FileDst$
' if path dest is not exists - create it.

dim FileSrc as QFileStream
dim FileDst as QFileStream

dr$=StripPath (FileDst$)
'print "dr$=" ,dr$

'MKDIR dr$ 'StripPath (FileDst$)

if dr$<>"" then
MKSubDir dr$
if DIREXISTS(dr$ ) =0 then showmessage ("FileCopy Can't create directory "+dr$ ): 'exit sub
end if

FileSrc.Open(FileSrc$, fmOpenRead)
FileDst.Open(FileDst$, fmCreate)

FileDst.CopyFrom  (FileSrc, 0)
        FileSrc.close
        FileDst.close
'print "FileCopy (";FileSrc$, FileDst$;") done"
end sub

'-- ***********************************************************************'
sub KillFiles (FileName$)
'Andrew Shelkovenko  diakin@narod.ru  apr 2004
'Kill files in FileName$
' for example KillFiles "C:\BAS\RAPIDQ\tmp\*.tmp"

FName$ =StripPath (FileName$)+ DIR$(FileName$, 0 ) '-- Get first file
'print " -------------------  FName$=" ,FName$

while STRIPFILENAME (FName$) <>""
kill FName$
'print "killed FName$=" ,FName$

if fileexists (StripPath (FileName$)+FName$)>0 then ShowMessage ("KillFiles Can't kill file "+FName$)
'print "Can't kill file "+FName$

FName$ = StripPath (FileName$)+DIR$ '-- Get next file
wend
end sub

'-- *****************************************************'
sub KillSubDir (DirSrc$, mask$) '- -----------------------------------'

'print "-- KillSubDir DirSrc$=",DirSrc$

'Andrew Shelkovenko diakin@narod.ru may 2004
'Kill files by mask$ in all subdirs in DirSrc$ directory and kill all empty subdirs and DirSrc$ (if empty)
'So.. if mask$="*.*" then  kill DirSrc$ with all subdirs and files

dim FileSrc as QFileStream

'Index=0
NumFiles=0
defint nsd1, nsd2
defstr mask
nsd1=0:nsd2=0
NumDir=0
ArrNumDir=500
dim SubDir(500) as string

ArrNumFil=500
dim FileNames (500) as string
mask="*.*"
if right$(DirSrc$,1)<>BkSl then SubDir(0)=DirSrc$+BkSl else SubDir(0)=DirSrc$

'print "BkSl=" ,BkSl

'print "SubDir(0)=" ,SubDir(0)

s1:
for i=NSD1 to Nsd2 'current level sudirs'
    'print "KillSubDir SubDir(",i,")=",SubDir(i)
    SubDirname$=dir$(SubDir(i)+mask, faDirectory)
    'print "-- KillSubDir SubDirname$=",SubDirname$
    while    SubDirname$ <>""
        if FileRec.Size =0 and SubDirname$<> "." and SubDirname$<> ".." then ''
            inc adddir
            inc NumDir 'add subdir'
            if NumDir=ArrNumDir then ArrNumDir=ArrNumDir+300: redim SubDir(ArrNumDir) as string
            subDir(NumDir)=SubDir(i)+SubDirname$+"\"
            'print "--KillSubDir SubDir(", NumDir, ")=",SubDir(NumDir)
        else
        end if
        SubDirname$=dir$
        doevents:if stops1=1 then stops1=0: exit sub
    wend

    'search files in current subdirectory
    Fn$=dir$(SubDir(i)+mask$,faAnyFile-faDirectory) ':-)
    while Fn$ <>""
        if  Fn$<> "." and Fn$<> ".."  then 'and FileRec.Size <>0'
            kill SubDir(i)+Fn$
            'print "-- KillSubDir kill ",SubDir(i)+Fn$
        else
        end if
        Fn$=dir$
    wend
next i

if adddir>0 then
    NSD1=NSD2+1
    NSD2=NSD2+adddir
    adddir=0
    goto s1 'repeat with new sub level
else
end if

for i1=i-1 to 1 step -1
    RMDIR SubDir(i1)
    'print "-- KillSubDir RMDIR SubDir(",i1,")=", SubDir(i1)
next i1

END SUB

'-- ***********************************************************************'
SUB io2Rnd (fsrc$, fdst$)
'--------------------------------
'convert text file with single value strings to binary
' for example
'17.78091
'16.64166

'fsrc$ - source file  fdst$ - dest. file
'data type - single

'CONST fmCreate = 65535
'CONST fmOpenRead = 0
'CONST fmOpenWrite = 1
'CONST fmOpenReadWrite = 2

dim FileSourse as QFileStream
dim FileDest as QFileStream
defsng ValSrc

FileSourse.Open (fsrc$, 2 )'fmOpenReadWrite'
FileDest.Open   (fdst$, 65535 )  'fmOpenReadWrite'

WHILE NOT FileSourse.EOF
ValSrc$=FileSourse.ReadLine : 'print "ValSrc$=" ,ValSrc$
ValSrc=val(ValSrc$) :         'print "ValSrc=" ,ValSrc
FileDest.Write (ValSrc)
wend

FileSourse.CLOSE
FileDest.CLOSE

END SUB

'-- ***********************************************************************'
SUB Rnd2io (fsrc$, fdst$)
'--------------------------------
'convert  binary file with single type value data to  text file with single type value strings
' i.e
'17.78091
'16.64166
'19.87037

'CONST fmCreate = 65535
'CONST fmOpenRead = 0
'CONST fmOpenWrite = 1
'CONST fmOpenReadWrite = 2

'CONST Num_BYTE = 1
'CONST Num_SHORT = 2
'CONST Num_WORD = 3
'CONST Num_LONG = 4
'CONST Num_DWORD = 5
'CONST Num_SINGLE = 6
'CONST Num_DOUBLE = 8

dim FileSourse as QFileStream
dim FileDest as QFileStream

defsng ValSrc

FileSourse.Open (fsrc$, 2 )        'fmOpenReadWrite'
FileDest.Open   (fdst$, 65535 )    'fmOpenCreate'

ie = FileSourse.size/4: 'print "ie=" ,ie

for i=0 to ie-1
ValSrc=FileSourse.ReadNum(6) :'print "ValSrc=" ,ValSrc
ValSrc$=str$(ValSrc):			'print "ValSrc$=" ,ValSrc$
FileDest.WriteLine (ValSrc$)
next i

FileSourse.CLOSE
FileDest.CLOSE

END SUB

'-- ***********************************************************************'
SUB io2RndPV (fsrc$, fdst$)
'--------------------------------
'convert text file with single value strings to binary
' for example
'17.78091
'16.64166

'fsrc$ - source file  fdst$ - dest. file
'data type - single

'CONST fmCreate = 65535
'CONST fmOpenRead = 0
'CONST fmOpenWrite = 1
'CONST fmOpenReadWrite = 2

dim FileSourse as QFileStream
dim FileDest as QFileStream
defsng ValSrc

FileSourse.Open (fsrc$, 2 )'fmOpenReadWrite'
FileDest.Open   (fdst$, 65535 )  'fmOpenReadWrite'

WHILE NOT FileSourse.EOF
ValSrc$=FileSourse.ReadLine : 'print "ValSrc$=" ,ValSrc$
ValSrc=val(ValSrc$) :         'print "ValSrc=" ,ValSrc
FileDest.Write (ValSrc)
wend

FileSourse.CLOSE
FileDest.CLOSE

END SUB

'-- ***********************************************************************'
SUB io2RndInter (io$, rndf$, LostP)
'convert text file with two-fields strings " point,data"
' to binary format with interpolation of loosing points
'---- for example -----
' 0,17.78091
' 1,16.64166
' 4,19.87037  points 2,3 is loosed
' 5,16.64123
'------------------------------------
'io$   - source text file
'rndf$ - destination binary file
'LostP - return number of loosed points (use @LostP )
' call io2RndInter (io$, rndf$, @LostP)
'------------------------------------
dim io2RndFile2 as QfileStream
dim io2Rndtmp as QfileStream
dim io2RndList as QSTRINGLIST
dim ioNumPnt as int
dim i0 as int

defsng pnt

'print "io2RndInter File  "+io$
if fileexists (io$)=0 then showmessage ("io2RndInter File not found "+io$):exit sub

if FileSize(io$)<1 then showmessage ("io2RndInter Zero size file "+io$):LostP=-99:exit sub

io2RndList.LoadFromFile (io$)
ioNumPnt=val(Field$(io2RndList.Item(io2RndList.ItemCount-1),",", 1))
if ioNumPnt=0 then showmessage ("io2RndInter No data "+io$) :exit sub
'print "ioNumPnt=";ioNumPnt

ArgName$=FullPathNoExt(rndf$)+"Arg"+STRIPFILEEXT(rndf$)
'print"ArgName$=";ArgName$

io2RndFile2.Open(rndf$, fmCreate)

'iotmp$=StripPath(rndf$)+"iotmp.txt"
'io2Rndtmp.Open(iotmp$, fmCreate)

io2Rndtmp.Open(ArgName$, fmCreate)

pntOld = 0: AdatOld! = 0: LostP = 1:j=0: i0=0
i0=val(Field$(io2RndList.Item(0),",", 1))

for k=0 to io2RndList.ItemCount-1
    'print "k=";k
    pnt=val(Field$(io2RndList.Item(k),",", 1))
    Adat!=val( Field$(io2RndList.Item(k),",", 2) )
    IF pnt = i0 THEN
        io2RndFile2.WriteNum(Adat!,Num_SINGLE )
        'io2Rndtmp.WriteLine (str$(pnt)+" "+str$(Adat!) )
        io2Rndtmp.WriteNum (pnt,Num_SINGLE)
        'print "pnt=";pnt;"  Adat=";Adat!
        pntOld = pnt: AdatOld! = Adat!
    elseif pnt < i0 then
        io2RndFile2.WriteNum(Adat!,Num_SINGLE )
        'io2Rndtmp.WriteLine (str$(i0)+" "+str$(Adat!) )
        io2Rndtmp.WriteNum (pnt,Num_SINGLE)
        pntOld = i0: AdatOld! = Adat!
    else
        IF pnt <> pntOld THEN ki! = (Adat! - AdatOld!) / (pnt - pntOld) ELSE GOTO ex1
        'print "pnt=";pnt;"  Adat=";Adat!
        FOR j = i0 TO pnt - 1
            'PRINT LostP; " из "; pnt
            LostP = LostP + 1
            Adat1! = AdatOld! + ki!
            'print "j=";j;"  Adat1=";Adat1!
            io2RndFile2.WriteNum(Adat1!,Num_SINGLE )
            'io2Rndtmp.WriteLine (str$(j)+" "+str$(Adat1!) )
            io2Rndtmp.WriteNum (j,Num_SINGLE)
            AdatOld! = Adat1!
        NEXT j
        AdatOld! = Adat!: pntOld = pnt:
        'print "pnt=";pnt;"  Adat=";Adat!
        'io2Rndtmp.WriteLine (str$(pnt)+" "+str$(Adat!) )
        io2Rndtmp.WriteNum (pnt,Num_SINGLE)
        io2RndFile2.WriteNum(Adat!,Num_SINGLE )
        i0 = j
    END IF
ex1:
inc i0
next k
io2RndFile2.close
io2Rndtmp.close
'print "io2Rnd completed"
END SUB

'***********************************************
sub ioAverage (io$, outf$, bpnt as integer)
' процедура обработки файла формата точка, данные, когда на каждую точку приходится несколько отсчетов
dim InputList as QSTRINGLIST
dim OutPutList as QSTRINGLIST
InputList.clear
OutPutList.clear
if fileExists (io$)> 0 and FileSize(io$)>0 then
    InputList.LoadFromFile (io$)
else
    ShowMessage ("File "+io$ +" not found")
    exit sub
end if

if InputList.ItemCount<5 then
    ShowMessage ("Data not found")
    exit sub
end if

pntOld=1
newpnt=1
ep=0

for k=0 to InputList.ItemCount-1
    a$=InputList.item (k)
    pnt=val(Field$(InputList.Item(k),",", 1)):
    Adat!=val( Field$(InputList.Item(k),",", 2)):

    if k=0 then pntOld=pnt:bpnt=pnt

    if pnt=pntOld then
        Aver=Aver+Adat!:'RQDebug("строка 37",0,"k", k, "pnt",pnt,"Adat!",Adat!,"ep",ep,"Aver",Aver)
        inc ep
    else
        if ep=0 then ep=1
        Aver=Aver/ep:'RQDebug("строка 41",0,"k", k, "pnt",pnt,"Adat!",Adat!,"ep",ep,"Aver",Aver)
        OutPutList.AddItems  str$(pntOld)+","+str$(Aver)
        inc newpnt
        'RQDebug("k", k, "pnt",pnt,"Adat!",Adat!,"Aver",Aver)
        Aver=Adat!
        pntOld=pnt
        ep=1
    end if

next k
Aver=Aver/ep:'RQDebug("строка 41",0,"k", k, "pnt",pnt,"Adat!",Adat!,"ep",ep,"Aver",Aver)
OutPutList.AddItems  str$(pntOld)+","+str$(Aver)

OutPutList.SaveToFile (outf$)
end sub

'-------------------------------------------------------------------'
'-- ***********************************************************************'
function ChDirOEM (PathDst$) as short
'print "ChDirOEM PathDst$=" ,PathDst$
result=0
dim PathDst1$ as string
PathDst1$=string$(len(PathDst$),"a")
chartooem PathDst$,PathDst1$
'print "ChDirOEM PathDst$=" ,PathDst$
'print "ChDirOEM PathDst1$=" ,PathDst1$

CHDIR  PathDst1$
result=1
end function

'-------------------------------------------------------------------'
'-- ***********************************************************************'
function MkDirOEM (PathDst$) as short
result=0
dim PathDst1$ as string
'print "MkDirOEM PathDst$=" ,PathDst$
PathDst1$=string$(len(PathDst$),"a")
chartooem PathDst$,PathDst1$
'print "MkDirOEM PathDst$=" ,PathDst$
'print "MkDirOEM PathDst1$=" ,PathDst1$
MkDIR  PathDst1$
result=1
end function

'--------------------------- Custom functions --------------------------
Declare Function CharToOem Lib "user32" Alias "CharToOemA" _
(ByVal lpszSrc As String, ByVal lpszDst As String) as Long

Declare Function OemToChar Lib "user32" Alias "OemToCharA" _
(ByVal lpszSrc As String, ByVal lpszDst As String) As Long

Declare Function CharLower Lib "user32" Alias "CharLowerA" (ByVal lpsz As String) As String
Declare Function CharUpper Lib "user32" Alias "CharUpperA" (ByVal lpsz As String) As String

'-- **************************** **********************************************'
function LCaseApi(  SrcTxt as string ) as string
tmp$=SrcTxt+"-"
l=len(SrcTxt)
result=CharLower(left$(tmp$,l))
end function

'-- **************************************************************************'
function UCaseApi(  SrcTxt as string ) as string
tmp$=SrcTxt+"-"
l=len(SrcTxt)
result=CharUpper(left$(tmp$,l))
end function

'-- **************************************************************************'
FUNCTION vidnum$ (Num, dig%) as string
'Andrew Shelkovenko dec 2003
'A  function that returns the string representation of  of a rounded numeric expression.
'Syntax: vidnum$ (numeric-expression, dig%)
'Num$ = vidnum$ (999999.2366666666, 4)
'Return  999999.2367
'Num$ = vidnum$ (-0.236, 4)
'Return  -0.236
'Num$ =vidnum$ (-12389.236, -2)
'Return -12400
'Details:
'dig% - number of significant digits

Num$=str$(Num)
pntPos=instr(Num$,".")
if pntPos=0 then
digMax=0
else
digMax=Len(Num$)-pntPos
end if

if dig%>digMax then dig%=digMax
vidnum$ = STR$((  CLNG(  abs(Num) * 10 ^ dig%) / 10 ^ dig%)*sgn(Num))
END FUNCTION
'
'-- **************************************************************************'
function   Hex2Dec (HexStr as string) as string

  DEFdbl numb
  defdbl number
  DEFBYTE x,length, y
    number = 0
    length = LEN(HexStr)
    FOR x = 1 TO length
      y = length - x

      digit$ = UCASE$(MID$(HexStr,x,1))
      SELECT CASE digit$
        CASE "A"
          numb = 10 * 16^y
        CASE "B"
          numb = 11 * 16^y
        CASE "C"
          numb = 12 * 16^y
        CASE "D"
          numb = 13 * 16^y
        CASE "E"
         numb = 14 * 16^y
        CASE "F"
          numb = 15 * 16^y
        CASE ELSE
          numb = VAL(LCASE$(digit$)) * 16^y
      END SELECT
      number = number + numb
    qw:
    NEXT

if number>10^6 then
n1=fix(number/1000000)
n2=(number-n1*1000000)
NumNul=6-len(str$(n2))
TrNul$=string$(NumNul, "0")

Dec$ = STR$(n1)+TrNul$+str$(n2)

else
Dec$ = STR$(number)
end if
Hex2Dec=Dec$

END function

'-- **************************************************************************'
function dectoHex (Dec as string) as string
defdbl ost, ch
defstr HexVal$
HexVal$=""
ost=0: ch=0
Dec#=val(Dec)
sign=sgn(Dec#)
Dec#=abs(Dec#)
WHILE  Dec# >= 16#
ch=FIX(Dec# / 16#)
ost = Dec#-ch*16#

Dec#=ch
select case ost
case is <10
Hexdig$=str$(ost)
case 10
Hexdig$="A"
case 11
Hexdig$="B"
case 12
Hexdig$="C"
case 13
Hexdig$="D"
case 14
Hexdig$="E"
case 15
Hexdig$="F"
case 15
Hexdig$="10"

case else
end select

HexVal$ =Hexdig$  + HexVal$:

wend

select case Dec#

case is <10
Hexdig$=str$(Dec#)
case 10
Hexdig$="A"
case 11
Hexdig$="B"
case 12
Hexdig$="C"
case 13
Hexdig$="D"
case 14
Hexdig$="E"
case 15
Hexdig$="F"
case 15
Hexdig$="10"

case else
end select

HexVal$ =Hexdig$  + HexVal$:
if sign=-1 then signn$="-" else signn$=""
if HexVal$="0" then HexVal$="00"
dectoHex=signn$+ HexVal$
END function

'-- **************************************************************************'
function AddChrBefore(NumStr as string , Dlina as int, chr as string) as string
'Andrew Shelkovenko dec 2003
'A function that pre-padd string with chr to required Length
'print AddChrBefore("-387.35" , 10, "=")
'==-0387.35

diM kolvo as int
kolvo =Dlina-Len(NumStr)
if   kolvo<0 theN AddChrBefore="String too long"
if   kolvo=0 theN AddChrBefore=NumStr: exit function
AddChrBefore= STRING$(kolvo, chr)+ NumStr
end function

'-- **************************************************************************'
function Add0Before(NumStr as string , Dlina as int) as string
'Andrew Shelkovenko dec 2003
'A function that pre-padd string with 0's to required Length
'print Add0Before("-387.35" , 8)
'-0387.35

diM kolvo as int
kolvo =Dlina-Len(NumStr)
if   kolvo<0 theN Add0Before="String too long"
if   kolvo=0 theN Add0Before=NumStr: exit function

Add0Before	= STRING$(kolvo, "0")+ NumStr

end function

'-- **************************************************************************'
FUNCTION ByteReOrder (ByteStr$,ReOrder$ ) as string
'Andrew Shelkovenko dec 2003
' A function that reorder bytes in string.
'ByteStr$ - Sourse string
'ReOrder$ - new byte order

'ReOrder$="21342"
'old position - 2, new position - 1
'old position - 1, new position - 2
'old position - 3, new position - 3
'old position - 4, new position - 4
'old position - 2, new position - 5

LenB=Len(ByteStr$)
LenR=Len(ReOrder$)

for i=1 to LenB
poz$=ReOrder$[i]
if val(poz$)> LenB then ShowMessage( "ReOrder index outbound input string"):exit FUNCTION
if i<= LenR then
byt$=ByteStr$[val(poz$)]
else
byt$=ByteStr$[i]
end if
tmp$=tmp$+byt$
next
ByteReOrder=tmp$
end FUNCTION

'-- **************************************************************************'
FUNCTION CByteNum (ByteStr$,Num_Type as short ) as variant
'Andrew Shelkovenko dec 2003
'' converts   number of Num_Type type to bytes sequence.
'Num_Type can be next value:
'const Num_SHORT = 2
'const Num_WORD = 3
'const Num_LONG = 4
'const Num_DWORD = 5
'const Num_SINGLE = 6
'const Num_DOUBLE = 8

DIM M AS QMemoryStream
select case Num_Type
case Num_BYTE
ShowMessage "Can't to write BYTE.Wrong parameter type - Num_BYTE": exit funCTION
case  Num_SHORT: M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_SHORT)
case  Num_WORD:  M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_WORD)
case  Num_LONG:  M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_LONG)
case  Num_DWORD: M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_DWORD)
case  Num_SINGLE:M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_SINGLE)
case  Num_DOUBLE:M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_DOUBLE)

case else
M.Write (ByteStr$):m.Position=0:CByteNum=m.ReadNum(Num_DOUBLE)
end select

M.Close

end funCTION

'-- **************************************************************************'
FUNCTION CNumByte (Num, Num_Type as short) as string
'Andrew Shelkovenko dec 2003

'converts bytes sequence to  number of Num_Type type
'Num_Type can be next value:
'const Num_SHORT = 2
'const Num_WORD = 3
'const Num_LONG = 4
'const Num_DWORD = 5
'const Num_SINGLE = 6
'const Num_DOUBLE = 8

DIM M AS QMemoryStream

select case Num_Type
case Num_BYTE
dim N1 as BYTE
ShowMessage "Can't to write BYTE.Wrong parameter type - Num_BYTE": exit funCTION

case  Num_SHORT: DEFSHORT N2:N2=Num:M.Write(N2):M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N2))
case  Num_WORD:  DEFWORD  N3:N3=Num:M.Write(N3):M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N3))
case  Num_LONG:  DEFLNG   N4:N4=Num:M.Write(N4):M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N4))
case  Num_DWORD: DEFDWORD N5:N5=Num:M.Write(N5):M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N5))
case  Num_SINGLE:DEFSNG   N6:N6=Num:M.Write(N6):M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N6))
case  Num_DOUBLE:DEFDBL   N7:N7=Num:M.Write(N7):M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N7))

case else
dim N8 as DOUBLE:N8=Num:
M.Write(N8):
M.Position=0:CNumByte=M.ReadBinStr(sizeOf(N8)):M.Close
end select
M.Close
end funCTION

'-- **************************************************************************'

' LIKE Function - pattern matching routine for Rapid-Q by William Yu
' This emulates the VB LIKE operator.
' Thanks to Thomas Binder for the original C code
'
' ?   Any single character.
' *   Zero or more characters.
' #   Any single digit (0-9).
' [charlist]  Any single character in charlist.
' [!charlist] Any single character not in charlist.
'
' A group of one or more characters (charlist) enclosed in brackets ([ ])
' can be used to match any single character in string and can include almost
' any character code, including digits.
'
' Note:   To match the special characters left bracket ([), question
' mark (?), number sign (#), and asterisk (*), enclose them in brackets.
' The right bracket (]) can't be used within a group to match itself, but
' it can be used outside a group as an individual character.
'
' By using a hyphen (-) to separate the upper and lower bounds of the range,
' charlist can specify a range of characters. For example, [A-Z] results in
' a match if the corresponding character position in string contains any
' uppercase letters in the range A-Z. Multiple ranges are included within
' the brackets without delimiters.

DECLARE FUNCTION Like(ParseString AS STRING, Pattern AS STRING) AS INTEGER
DECLARE FUNCTION IsDigit(S AS STRING) AS INTEGER

const INVERT = "!"       '-- Some like ^ or ~ instead, whatever you want

'-- **************************************************************************'
FUNCTION IsDigit(S AS STRING) AS INTEGER
  IF S >= "0" AND S <= "9" THEN
    IsDigit = 1
  ELSE
    IsDigit = 0
  END IF
END FUNCTION

'-- **************************************************************************'
FUNCTION Like(ParseString AS STRING, Pattern AS STRING) AS INTEGER
  DIM prev AS INTEGER, matched AS INTEGER, reverse AS INTEGER

  WHILE Pattern <> ""
    SELECT CASE MID$(Pattern, 1, 1)
      CASE "?"
        IF ParseString = "" THEN
           Like = 0
           EXIT FUNCTION
        END IF
      CASE "#"
        IF IsDigit(MID$(ParseString, 1, 1)) = 0 THEN
           Like = 0
           EXIT FUNCTION
        END IF
      CASE "*"
        DO
          Pattern = MID$(Pattern, 2, LEN(Pattern)-1)
        LOOP UNTIL MID$(Pattern, 1, 1) <> "*"
        IF Pattern = "" THEN
           Like = 1
           EXIT FUNCTION
        END IF
        WHILE ParseString <> ""
           IF Like(ParseString, Pattern) THEN
              Like = 1
              EXIT FUNCTION
           END IF
           IF ParseString <> "" THEN
              ParseString = MID$(ParseString, 2, LEN(ParseString)-1)
           END IF
        WEND
        Like = 0
        EXIT FUNCTION
      CASE "["
        reverse = (MID$(Pattern, 2, 1) = INVERT)
        IF reverse THEN
           Pattern = MID$(Pattern, 2, LEN(Pattern)-1)
        END IF
        prev = 256: matched = 0
        DO
           Pattern = MID$(Pattern, 2, LEN(Pattern)-1)
           IF (Pattern <> "") AND (esc <> 0 OR MID$(Pattern, 1, 1) <> "]") THEN
              IF MID$(Pattern, 1, 1) = "-" THEN
                 Pattern = MID$(Pattern, 2, LEN(Pattern)-1)
                 IF Pattern = "" THEN
                    Like = 0
                    EXIT FUNCTION
                 END IF
                 matched = matched OR (MID$(ParseString, 1, 1) <= MID$(Pattern, 1, 1) AND ASC(MID$(ParseString, 1, 1)) >= prev)
              ELSE
                 matched = matched OR (MID$(ParseString, 1, 1) = MID$(Pattern, 1, 1))
              END IF
              prev = ASC(MID$(Pattern, 1, 1))
           ELSE
              EXIT DO
           END IF
           esc = 0
        LOOP
        IF (prev = 256 OR MID$(Pattern, 1, 1) <> "]" OR ABS(matched) = ABS(reverse)) THEN
           Like = 0
           EXIT FUNCTION
        END IF
      CASE ELSE
        IF MID$(ParseString, 1, 1) <> MID$(Pattern, 1, 1) THEN
           Like = 0
           EXIT FUNCTION
        END IF
    END SELECT
    ParseString = MID$(ParseString, 2, LEN(ParseString)-1)
    Pattern = MID$(Pattern, 2, LEN(Pattern)-1)
  WEND

  Like = ABS(LEN(ParseString) = 0)
END FUNCTION

'-- Test code
'print "Like('24','##')=", Like("24","##")

'?"Like(aBBBa, a*a)=", Like("aBBBa","a*a")
'?Like("F","[!A-Z]")
'?Like("a2a","a#a")
'?Like("aM5b","a[A-GL-P]#[!c-e]")
'?Like("BAT123khg","B?T*")
'?Like("CAT123khg","B?T*")

'?Like("Combine(10, 20) = 30", "*(*?,*?)*=*#")
'-- **************************************************************************'
function SecTime (cTime$ as string) as integer
TimeHH=val (field$(cTime$, ":",1))
TimeMM=val (field$(cTime$, ":",2))
TimeSS=val (field$(cTime$, ":",3))
result=TimeHH*3600+TimeMM*60+TimeSS
end function

'-- **************************************************************************'
function DayDate (cDate$ as string) as integer

    MM=val (field$(cDate$, "-",1))
    Day=val (field$(cDate$, "-",2))
    Year=val (field$(cDate$, "-",3))

result=365*(Year)+30*(MM)+(Day)
end function

'-- **************************************************************************'
function TimeString (TimSec as integer) as string

Hr%=TimSec/3600
SecMin=TimSec-Hr%*3600
Min%=(SecMin)/60
Sec%=SecMin-Min%*60

Hr$=Right$("0"+str$(Hr%), 2)
Min$=Right$("0"+str$(Min%), 2)
Sec$=Right$("0"+str$(Sec%), 2)

TimeString=Hr$+":"+Min$+":"+Sec$+"   "

end function

'-- *********************************************************************'
Function GetWord (Oper$ as string, getV$ as string) as long
'return variable  position in checked string
'getV$ - variable name
'Oper$ - checked string
'if getV$ commented,  or quoted (just text, not varname)  - return error code
result=-1 ' error
defstr Lsep$="([=><, :+-*\/;"
defstr Rsep$=")]=><, :'+-*\/;"

Oper$=lcase$(Oper$)
getV$=lcase$(getV$)

Wpos=instr(Oper$,getV$)
'print "Wpos=" ,Wpos
if Wpos=0 then result=0: exit function 'pattern not contained
'check comment and string

while Wpos>0
'print "Wpos=" ,Wpos
'print "Wpos+len(getV$)=" ,Wpos+len(getV$)
'print "len(Oper$)=" ,len(Oper$)

    if (instr(Lsep$,Oper$[Wpos-1])>0 or Wpos=1) and (instr(Rsep$,Oper$[Wpos+len(getV$)])>0  or Wpos+len(getV$)-1=len(Oper$))  then
        'check string
        QPos1=rinstr(Wpos,Oper$,qt) ''1 quote pos
        'print "QPos1=" ,QPos1
        QPos2= instr(Wpos,Oper$,qt) '2 quote pos
        'print "QPos2=" ,QPos2
        CPos=rinstr(Wpos,Oper$,"'") 'comment pos
        'print "CPos=" ,CPos

        if QPos1<Wpos and QPos2 >Wpos and QPos1>0 then 'it's string, not var
        elseif (CPos<Wpos and CPos>0) and  QPos1<CPos    then 'it's comment and QPos2>0
        else
            result=Wpos
            'print "Wpos1=" ,Wpos
            exit while
        end if
    else
    end if
        Wpos=instr(Wpos+1, Oper$,getV$)
        'print "Wpos2=" ,Wpos
    result=-2 'present, but not var
wend

end function


VAL

VAL CONVERSION Function Windows/Unix
A conversion function that returns a numeric representation of the string expression.

Syntax: VAL(string-expression)
A = VAL("995")


VARPTR

VARPTR ADDRESS Function Windows/Unix
A function that returns the address, ie. pointer to, of the given variable name. Variable must be a declared variable, ie. not a component variable such as QForm.Caption

Syntax: VARPTR(variablename)
Addr& = VARPTR(MyString$)
Addr& = VARPTR(MyArray(0)) 'be sure to reference the first element of your array

Details:
You can only get pointers to basic datatypes like INTEGER, SINGLE, DOUBLE. Pointers to Qobjects and components (like OBJPTR in visual basic) are not supported.

Use UDTPTR for User Defined Types. Unlike C/C++, you cannot get a pointer of a member inside a UDT :
VARPTR(MyRec.NumRecords) 'this won't work

Also you cannot access an array pointer once the array is passed to a SUB/FUNCTION

SUB MySub (MyArray () AS INTEGER)
addr = VARPTR(MyArray(0)) ' doesn't recognize MyArray !
END SUB

So if you want to fast copy data to your array using MEMCPY
then you will have to also pass the address of the array


VARPTR$

VARPTR$ ADDRESS Function Windows/Unix
A function that returns the string representation of a given address.

Syntax: VARPTR$(address)
S$ = VARPTR$(279027343)


VARTYPE

VARTYPE VARIANT Function Windows/Unix
A function that returns the data type of the current value stored in the variant.

Syntax: VARTYPE(variant)
DIM myvariant(100) AS VARIANT
myvariant(1) = "G"
VType = VARTYPE(myvariant(1))

Details:
Valid return values are:
0 - Number (includes Byte, Word, Dword, Short, Long/Integer)1 - Float (includes Single, Double)2 - StringExampledim TstNum as variantDEFDBL Number1Number1=77.0 TstNum=Number1VType = VARTYPE(TstNum)print "VType0=" ,VType  ' Return 0Number1=77.01 TstNum=Number1VType = VARTYPE(TstNum)print "VType1=" ,VType  ' Return 1
All undefined variants are initialized as Numbers.


Var types: C to RapidQ conversion

     Type       ID  Size  Range
    --------- ---- ---- -------------
    Byte        ?   1   0..255
    Word       ??   2   0..65535
    Dword     ???   4   Only Linux version for now...
    Short       %   2   -32768..32767
    Integer     &   4   -2147483648..2147483647
    Long        &   4   -2147483648..2147483647
    Single      !   4   1.5 x 1045..3.4 x 1038
    Double      #   8   5.0 x 10324..1.7 x 10308

Rules to remember when porting code written for application
programming interfaces (API)

C data type Visual Basic RapidQ type

ATOM ByVal Var As Integer INTEGER

BOOL ByVal Var As Long LONG

BYTE ByVal Var As Byte BYTE

CHAR ByVal Var As Byte BYTE

COLORREF ByVal Var As Long LONG

DWORD ByVal Var As Long LONG, or DWORD

HWND ByVal Var As Long LONG

HDC ByVal Var As Long LONG

HMENU,etc.

(Windows handles) ByVal Var As Long LONG

HDC ByVal Var As Long LONG

INT, UINT ByVal Var As Long LONG, INTEGER

LONG ByVal Var As Long LONG

LPARAM ByVal Var As Long LONG

LPDWORD ByRef Var As Long LONG

LPINT, LPUINT ByRef Var As Long LONG

LPRECT ByRef Var As type AS QRECT (Pointer to UDT)

LPSTR, LPCSTR ByVal Var As String STRING (converted to pointer)

** RapidQ passes STRING type variable as a pointer (i.e., by reference). When calling
a DLL with a STRING variable type you must have the correct DECLARE statement:

MyAPIFunc(lpstr AS STRING) :e.g., MyAPIFunc(A$)

OR

MyAPIFunc(lpstr AS LONG) :e.g., MyAPIFunc(VARPTR(A$))

you cannot pass a string as an array of chars

LPVOID ByRef Var As Any LONG (Pointer, not STRING)

LPWORD ByRef Var As Integer INTEGER

LRESULT ByVal Var As Long LONG

NULL ByVal Var As Long ByVal 0&

SHORT ByVal Var As Integer SHORT

VOID SUB(vars) SUB(vars) no return var

WORD ByVal Var As Integer WORD

PDWORD ByRef var AS LONG LONG (pointer to a dword)

WPARAM ByVal Var As Long LONG

Many other types exist- the general rule is that if C declares the variable with an “L” or “LP” as the fist characters then it is a pointer of type LONG. RapidQ can accept but does not strictly support the unsigned data types such as DWORD, UINT8, UINT16, UINT32, UINT64,etc.


WITH..END WITH

WITH .. END WITH Compiler DIRECTIVE /block Function Windows/Unix
This Keyword is a shortcut for user defined types, structures, components, or Qobjects. This will save you some typing.

DIM Form AS QFORM
'everything between WITH ...END WITH will substitute "Form" before the period.
WITH Form
.Left = 30
.Top = 50
END WITH

Remarks:
Not all cases of WITH are supported. For instance, WITH will not work inside a MEMCPY, with arrays of components, or inside a custom component using WITH Super ... END WITH, since all properties/methods will be referenced as the super class.


QProcess

Documentation by John Kelly XP_Manifest

XP_MANIFEST.INC

This is a non-visible component that automatically generates a manifest file in the directory as the executable file. The manifest file allows RapidQ programs to have the look of Windows XP buttons and common controls. There is no effect in lower versions of Windows.
Note, if the file does not already exist at run-time then no visual style is applied.

XP_Manifest Methods
Method | Type |  | Params
$XP_MANIFEST | SUB | W | 0
 | Automatically generate the Manifest file if it already does not exist |  |
XPButton | SUB (Handle As LONG [, option])) | W | 2
 | Pass the handle of a QBUTTON to be activated, i.e., XPButton(MyButton.Handle) The optional parameter can be the following: fbmNormal 0 fbmDefault 1 'default XP style fbmFixTo3CheckBox 6 fbmFixToGroupBox 7 fbmLeftAlign &H100 fbmRightAlign &H200 fbmTopAlign &H400 fbmBottomAlign &H800 fbmShowOnClick &HA |  |

XP_Manifest Events
Event | Type | Occurs when... | Params
None

xpGroupBox Component

Standalone component to make a windows XP style group box. It does not need a manifest file. Written by Paul Ludgate.

xpGroupBox Properties
Field | Type | R/W | Default
Caption | STRING | R/W | null
BorderColor | INTEGER | R/W | &HBFD0D0
CaptionColor | INTEGER | R/W | &HD54600
LunaDetect

adjust border color to suit btnface 		INTEGER R/W True

XP_Manifest Example

$INCLUDE <XP_MANIFEST.INC>
$XP_MANIFEST      'on first run it will be generated

CREATE Form AS QFORM
    Width = 300
    Height = 200
    Center
 CREATE button1 AS QBUTTON
     Width = 80
     Caption = "Xp Button"
  END CREATE
 CREATE CheckBox AS QCheckBox
     Top = 50
     Caption = "Xp Check box"
  END CREATE
 CREATE GrpBox as xpGroupBox
    Left = 130
    Width = 90
    Caption ="xp group box"
    CaptionColor = &HFF00FF
    BorderColor = &HFFFFFF
    LunaDetect = 0
 END CREATE
END CREATE
XPButton(button1.handle)  'only buttons, checkboxes need this
Form.ShowModal