Pascal Newsletter #13 - 24-DEC-2000
INDEX
1. A FEW WORDS FROM THE EDITOR
2. NON-RECTANGULAR SHAPES - Part I
3. OPENGL APPLICATIONS WITH DELPHI 5.0 - FIRST STEPS
4. OPENING MICROSOFT ACCESS .MDB DATABASES WITH DELPHI
- ADO
- BDE
- BDE + ODBC
5. LISTING THE TABLES AND QUERIES IN A DATABASE
6. LINKS
________________________________________________________________________
1. A FEW WORDS FROM THE EDITOR
In this issue Alirio Gavidia will be showing us with two examples how
easy is to make non-rectangular forms.
Leopold Minikus, from Minais - Individual Cad Software, submitted us
an article presenting their set of OpenGL components to help you build
3D applications with Delphi 5. You can download the MNOgl component
collection from for free from the minais web site: http://www.minais.at
The download includes sample projects.
If you need help or have questions about the articles presentend in this
newsletter, you can post them to our forum/mailing list. Your problems
and doubts might be the problems and doubts of other members of the
forum that will also benefit from reading the questions and answers. In
order to subscribe, simply send a blank email to
delphi-en-subscribe@yahoogroups.com
This a free service provided by http://www.egroups.com and they don't
spam, although they include a little ad in each message (of which I
don't see a cent, just in case you wonder). If you need more
information, please visit:
http://www.latiumsoftware.com/en/forums.html
Regards,
Ernesto De Spirito
eds2008 @ latiumsoftware.com
________________________________________________________________________
JfControls Library. Multi-language. Multi-appearance. Skins. Privileges.
More than 40 integrated and customizable components. Impressive GUI.
Centralized resources administration. Multiple programming problems
solved. For Delphi 3-2006 & C++ Builder 3-6. http://www.jfactivesoft.com
________________________________________________________________________
2. NON-RECTANGULAR SHAPES - Part I
Copyright (c) 2000 Alirio Gavidia <alirio@gavidia.org>
To see more of my articles visit:
Programación Orientada en Delphi (site in Spanish)
http://www.gavidia.org/pod/
Translated by Ernesto De Spirito
Introduction.
=============
The present essay intends to show the possibilities of use of non-
rectangular shapes under Windows. The use is simple, but the
possibilities look interesting. Additionally, in particular in this
first part, we will make use of two important elements: "Canvas" and
"Timer".
The first example.
==================
In the previous article (see "POST-IT". SIZABLE WINDOWS WITHOUT BORDER
OR TITLE in http://www.latiumsoftware.com/en/pascal/0010.php ) I made
reference to the possibility of creating an analog round clock like the
one of Windows "PowerToys". Making a round form is simple and it is
limited to calling a couple of procedures. The clock must also draw
the hands (which requires certain mathematic calculation) and update
about 60 times per minute (this is what the "TTimer" is for).
Note: Analog Clock in opposition to Digital. The term is NOT
correct because the clock we create here -even if it has hands- is
digital. For the clock to really imitate an actual analog behavior
it would have to have a continuos movement. The one we create here
moves from second to second and therefore it has finite and defined
states and that makes it qualify as digital. It seems a more
adequate term is "hands clock".
Without title.
==============
The clock is based on a simple borderless form, eliminating the title
bar, which results in a bother when we have a round form. This generates
the additional problem of moving the form. For this reason the drag
operation should be attended from the client area of the form. To solve
this inconvenience there are various ways. I choose the one applied in
the previous article (use of wm_Syscommand $f012):
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
ReleaseCapture;
Perform(wm_Syscommand, $f012, 0)
end;
Another technique is responding to "Wm_NcHitTest" and returning
"htCaption" as the result. This is simply telling Windows that the clic
was made in the title area. It seems to me that there is at least
another technique, but it isn't the objective of this essay.
The "timer".
============
In the form we included a "TTimer" control. This control fires an event
approximately at intervals (defined by the "interval" property given in
milliseconds). Its use is well documented in Delphi, but I must add
something: it isn't exact.
The event associated with the timer executes three actions: eliminates
the hands from the previous position, takes the system time, and puts
the hands in a new position.
The "Canvas".
=============
The "Canvas" provides graphical capacities for graphic controls and
forms. I offers possibilities to draw lines, ellipses, polygons, text
and others. Its usage is simple and practical.
We made use of the following elements of the "Canvas":
* "Pen", to set the color and mode of the line draw.
* "MoveTo", to set the initial point of a line draw.
* "LineTo", to draw a line from the last position to the new one.
* "Rectangle", to draw a rectangle according to the given parameters.
Particularly we have to note the property "Canvas.Pen.Mode" that allows
the use of values like "pmXor" or "pmCopy" (among many others).
Note: The use of "Xor" as a logical operator has an interesting
property which is that applied twice you get the original value,
i.e.: "x xor y" results in "z", and if you apply "xor y" again to
"z" it results in "x". This is useful for simple encrypting where
we want to apply a key to encrypt and the same key and the same
algorithm to decrypt. It is also useful when we want to draw
something and then erase it because it is only required to draw
it again applying a "xor" between the background and the pixel to
draw.
The "Paint" event of the form certainly makes use of the Mode and Color
properties of the Pen obtaining a curious effect. The result, at least
for me, wasn't the expected, however it was nice. All this seems to be
the consequence of the way in which a rectangle is created. It is filled
and then the upper and left border are drawn, that under the "Xor"
operator generate a white color and the resulting image generates a 3D
effect. I suggest the reader to comment out the lines "Mode" and "Color"
to draw his own conclusions.
As an additional comment, "Pen.Color" only affects the border of the
rectangle. The filling is defined by the "Brush" property of the
"Canvas" which in this case remains with its default value.
procedure TForm1.FormPaint(Sender: TObject);
Var
X1, Y1, i : integer;
Angle : double;
begin
Canvas.Pen.Mode := pmXor;
Canvas.Pen.Color := clBtnFace;
for i:=1 to 12 do
begin
Angle := i * 2 * Pi / 12;
X1 := trunc(X0 + Len * Sin(Angle));
Y1 := trunc(Y0 - Len * Cos(Angle));
Canvas.Rectangle(X1-4,Y1-4,X1+4,Y1+4)
end;
Canvas.Pen.Mode := pmCopy;
Canvas.Pen.Color := clBlack;
end;
Arithmetic.
===========
The coordinates system has the point zero in the upper-left corner. To
determine the position of the hand we need the center and the ending
point. The center is the half of the width and the height. For the
length of the hands we take a fraction of the minimum between the width
and the height.
Knowing the center and length of the hand, we only need to know the
position of its ending point and for this we determine the angle. Here
we end up turning to trigonometry. The angle is determined with the zero
in 12 o'clock, 90 degrees at 3 o'clock, 180 degrees at 6 and 360 at 12.
The sine of the angle gives us the opening in the "X" coordinate, while
the cosine gives us the opening of the "Y" coordinate. As an additional
remark, the coordinates system in the "Y" axis is inverted with respect
of the usual trigonometric systems. All angles must be expressed in
radians to be used with the sine and cosine functions. The procedure
"DrawWatchHand" makes the calculations (also in "FormPaint")
procedure Tform1.DrawWatchHand;
:
:
// Now draw Second
Canvas.MoveTo(X0, Y0);
Angle := S * 2 * Pi / 60;
X1 := trunc(X0 + 9*Len * Sin(Angle)/10);
Y1 := trunc(Y0 - 9*Len * Cos(Angle)/10);
Canvas.LineTo(X1, Y1);
:
:
Notice that each hand hand uses a proportion of the Len value. For
example the seconds are 9/10 of Len, minutes are 3/4 and hours are
1/2.
Round.
======
Until now we have used the "Canvas" to draw, eliminated the title bar
and substituted its functionality, we have done some arithmetic and we
have made use of a "timer". The central point that gives title to this
article is the creation of a non-rectangular shape. Well, this is
tremendously easy and is solved with two calls to Windows in the
"FormCreate" of the main form:
hRegion := CreateEllipticRgnIndirect(R);
SetWindowRgn(handle, hRegion, true);
"CreateEllipticRgnIndirect" is a version of "CreateEllipticRgn" with the
parameters (a rectangle) packed in only one structure. This routine
returns a "handle" to an elliptic region circumscribed to the given
rectangle. If you want you can define non-circular regions using
"CreatePolygonRgn" for polygons, "CreateRectRgn" for rectangles (without
sense in our case, but it is possible), "CreateRoundRectRgn" for
rectangles with round corners, or "CombineRgn" to combine the results of
other regions.
"SetWindowRgn" defines the area in which a window is visible. It is
interesting that under this concept the rectangular window still exists
and we only defined something like a hole from where we can see it.
A "Bug", a second example.
==========================
My first attempt of a non-rectangular shape was a couple of years ago
with Delphi 3. It was a mischief motivated in that I know people who
terribly hate cockroaches (and here in the tropic there are spectacular
ones). So I created a cockroach that wanders on the Windows desktop. Its
form is elliptic and I fundamentally created some images for different
angles (four: two verticals and two horizontals). The result is a bit
rustic, but I enjoyed creating this "bug". I very well know there are
better ways to do this, but it comes to the case because of the subject
of this article.
The next.
=========
Well, this opens interesting possibilities of use (as I mentioned
before). I think the most adequate seems to be the one of "Skins" like
some applications. For reference you have "Winamp", "NeoPlanet",
"Windows Media Player" (new version). The technique that allows non-
rectangular shapes is applicable to buttons and other controls.
Bibliography:
* Delphi Developer's Handbook,
Marco Cantù, Tim Gooch, John F. Lam
SYBEX
ISBN: 0-7821-1987-5
1.998
* La Biblia de Delphi 5
Marco Cantù
ANAYA
ISBN: 84-415-0994-8
2.000
--------------------------
The source code that accompanies this article can be downloaded from:
http://www.latiumsoftware.com/en/file.php?id=p13
________________________________________________________________________
3. OPENGL APPLICATIONS WITH DELPHI 5.0 - FIRST STEPS
Copyright (c) 2000 Leopold Minikus <info@minais.at>
When you use MNOgl component collection from minais you have two
different ways to build such applications.
First I want to describe the easy way:
First of all be sure to install the MNOgl package file mnogl.bpl under
Delphi (Component menu - Install packages - Add button - search for
MNOgl.bpl and say Open). The result is you have a new component folder
called MNOgl within which you will find a lot of handy components to
design an OpenGL application.
Let us start with a new project. Select a TMNOglControl component and
drop it onto the form. Resize the control as you want it or let it
align. Then select a TMNOglCanvas component and drop it on the form.
Assign the MNOglControl1 to the property named WinControl. Now an OpenGL
rendering context will be generated (the MNOglControl changes to black
backgroundcolor).
Let us now look how we can draw a box in this canvas. Pick a TMNOglScene
component from the MNOgl folder and drop it on the form. Assign the
MNOglCanvas1 to the property MNOglCanvas. Now let us select a TMNOglBox
component and drop it on the form. Assign MNOglScene1 to the property
Scene. Now you see the shape already in design mode. Try to change the
size of the box by changing the properties Length, Width and Height.
If you want to have your shape centered then set the TransformBy
property to (-Length/2, -Width/2, -Height/2).
Second I want to describe the way when you do not want to install the
MNOgl package:
Let us start with a new project. Change the uses list and add the units
_mnoglcanvas, _mnogltools to your list. e.g.
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, _mnoglcanvas, _mnogltools;
Add the following private variables to your form:
TForm1 = class(TForm)
...
private
{ Private declarations }
MNOglControl1: TMNOglControl;
MNOglCanvas1: TMNOglCanvas;
MNOglScene1: TMNOglScene;
MNOglBox1: TMNOglBox;
public
{ Public declarations }
end;
Then enter the FormShow method and we will create the components we will
need:
procedure TForm1.FormShow(Sender: TObject);
begin
// create the WinControl for the OpenGL render context
// herein your shapes will be played
MNOglControl1 := TMNOglControl.Create(Self);
MNOglControl1.Align := alClient;
MNOglControl1.Parent := self;
// create the MNOglCanvas
MNOglCanvas1 := TMNOglCanvas.Create(Self);
// assign the WinControl --> and the render
// context will be created
MNOglCanvas1.WinControl := MNOglControl1;
// create the scene (OpenGL calls it DisplayList)
MNOglScene1 := TMNOglScene.Create(Self);
// and tell the scene in which Canvas it will be played
MNOglScene1.MnOglCanvas := MNOglCanvas1;
// create the box
MNOglBox1 := TMNOglBox.Create(Self);
// ant tell the box to which scene it will belong
MNOglBox1.Scene := MNOglScene1;
// change properties of the box
with MNOglBox1 do begin
Length := 4;
Width := 3;
Height := 2;
end;
end;
If you want the scene to rotate then just add a TMNOglNav (a navigator)
to your form and set the property MNOglCanvas to MNOglCanvas1. When you
start the program you can then press the left mouse button on the
MNOglNav component and move the mouse. With double-click the view will
be reseted.
________________________________________________________________________
4. OPENING MICROSOFT ACCESS .MDB DATABASES WITH DELPHI
ADO
===
If you have Delphi 5 Enterprise or Delphi 5 Professional with ADO
Express, then you can use an ADOTable and in the ConnectionString
property of the associated ADOConnection you can use the property
editor to build the right connection string. For example:
Provider=Microsoft.Jet.OLEDB.4.0;
User ID=Admin;
Data Source=D:\Path\dbname.mdb;
Mode=ReadWrite;
Extended Properties="";
Persist Security Info=False;
Jet OLEDB:System database="";
Jet OLEDB:Registry Path="";
Jet OLEDB:Database Password="";
Jet OLEDB:Engine Type=5;
Jet OLEDB:Database Locking Mode=1;
Jet OLEDB:Global Partial Bulk Ops=2;
Jet OLEDB:Global Bulk Transactions=1;
Jet OLEDB:New Database Password="";
Jet OLEDB:Create System Database=False;
Jet OLEDB:Encrypt Database=False;
Jet OLEDB:Don't Copy Locale on Compact=False;
Jet OLEDB:Compact Without Replica Repair=True;
Jet OLEDB:SFP=False
NOTE: It all goes in the same line.
This would open the database D:\Path\dbname.mdb using the ADO driver for
Access databases (Microsoft.Jet.OLEDB.4.0). The username would be Admin
without password (the default when you create an Access database). If
you have set a password for the database, you should provide it in the
"Jet OLEDB:Database Password" property. If you have set up security,
then you should indicate your workgroups .MDW or .MDA file in the "Jet
OLEDB:System database" property.
BDE
===
If like most of us you don't have ADO, you can use the BDE which
provides a native driver (MSACCESS). In a Database component, set the
following properties:
DatabaseName = any_name (or alias_name)
DriverName = MSACCESS
LoginPrompt = False
Params = PATH=d:\path
DATABASE NAME=d:\path\filename.mdb
TRACE MODE=0
LANGDRIVER=Access General
USER NAME=Admin
PASSWORD=your_password
OPEN/MODE=READ/WRITE
SQLPASSTHRU MODE=NOT SHARED
Value of the DatabaseName property of a Database object is the one you
should use in the DatabaseName property of Table and Query components
that represent tables and queries on this database (this is the way to
"link" them to the Database object).
BDE + ODBC
==========
In the case of Access databases, the BDE provides a native driver, but
there are many database formats for which there insn't a BDE driver,
although maybe you can find an ODBC driver. ODBC offers what I would
call "compatibility access" (for applications with bare minimum database
requirements, or applications that only need to perform import/export
operations), but sometimes it's all we have...
Here is an example of how to use an ODBC driver with the BDE to open an
Access database:
* Create a DSN for your database (using the ODBC Data Sources applet in
Windows's Control Panel).
1) Click the "System DSN" or "User DSN" tabs
2) Click "Add..." button
3) Select the "Microsoft Access Driver (*.mdb)" and press ENTER. The
"ODBC Microsoft Access Setup" dialog will appear.
4) Provide a name in the Data Source Name textbox (no spaces and no
special characters).
5) Click the "Select..." to specify your .MDB database.
6) If you have set up a security scheme you have to select the
"Database" radio button in the "System Database" frame and then
click the "System database..." button to specify your .MDW or .MDA
workgroups file.
7) Click the "Advanced..." button if you want to set a default user
name and password. This is for low-security access because anybody
with access to your machine can see the DSN properties. If you need
higher security, you should provide and username and password when
you open the database (see below).
8) Finally click the "OK" button to save your DSN.
* In Delphi set the properties of the TDatabase component:
1) Set DatabaseName to the name you gave to the DSN.
2) If you want the user to supply a login name and password, then
leave LoginPrompt in True.
3) If you don't like the standard login dialog (or if you want to
provide the user name and password by code) you can set LoginPrompt
to False and use you own dialog box (or have the user name and
password hard-coded in your application) and set the Params
property with the login data:
USER NAME=your_user_name
PASSWORD=your_password
* Associate your TTable or TQuery components to the TDatabase component
mentioned above by simply providing the same DSN name in their
corresponding DatabaseName property.
________________________________________________________________________
5. LISTING THE TABLES AND QUERIES IN A DATABASE
If you need to know the names of all tables and/or queries (views) in a
database opened with the BDE, you can use DbiOpenTableList to create a
cursor* with the table and query names, and then you can read it calling
DbiGetNextRecord as shown in the example below that stores the names in
a ListBox, indicating whether they correspond to a table or query.
(*) A cursor is a "logical table". For example when we open a table
or query, what we get is a cursor, that is, a set of data organized
in rows and columns, independently of whether this data comes from
a physical table, part of table, many tables or any other data
source.
To try the example, simply place a ListBox and a button on a form, and
generate the button's OnClick event handler:
uses db, dbtables, bde;
procedure TForm1.Button1Click(Sender: TObject);
var
db1: TDatabase;
hCursor: hDBICur; // Cursor for table and query names
ListDesc: TBLBaseDesc; // Record of the cursor
begin
ListBox1.Clear;
db1 := nil;
try
db1 := TDatabase.Create(nil);
// Set the neccessary properties to open your database
db1.DatabaseName := 'Access_ODBC_Test';
db1.LoginPrompt := False;
db1.Connected := True;
// Generates a cursor with all table and query names
Check(DbiOpenTableList(db1.Handle, False, False, '*', hCursor));
// Move thru the records of the cursor to get the names
while (DbiGetNextRecord(hCursor, dbiNOLOCK, @ListDesc, nil)
= dbiErr_None) do
if ListDesc.bView then // Is it a query?
ListBox1.Items.Add(ListDesc.szName + ' (Query)')
else
ListBox1.Items.Add(ListDesc.szName + ' (Table)');
// Close the cursor
dbiCloseCursor(hCursor);
db1.Connected := False;
except
db1.Free;
raise;
end;
db1.Free;
end;
Instead of a variable of type TDatabase created for the purpose, you can
use a TDatabase control placed on a form, or the Database property of a
TTable or TQuery control.
________________________________________________________________________
6. LINKS
* Top 100 Borland - Resources for Borland Developers
http://www.top100borland.com
________________________________________________________________________
YOU CAN HELP US
We need your help to keep this newsletter going and growing. You can
help by referring the newsletter to your colleagues:
http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Or you can help by voting for us in some or all of these rankings to
give more visibility to our web site and thus increase the number of
subscriptions to this newsletter:
http://www.programmingpages.com/?r=latiumsoftwarecomenpascal
http://top100borland.com/in.php?who=20
It's just a few seconds for you that REALLY mean a lot to us.
________________________________________________________________________
If you haven't received the full source code examples for this issue,
you can get them from http://www.latiumsoftware.com/en/file.php?id=p13
________________________________________________________________________
This newsletter is provided "AS IS" without warranty of any kind. Its
use implies the acceptance of our licensing terms and disclaimer of
warranty you can read at http://www.latiumsoftware.com/en/legal.php
where you will also find a note about legal trademarks. Articles are
copyright of their respective authors and they are reproduced here with
their permission. You can redistribute this newsletter as long as you do
it in full (including copyright notices), without changes, and gratis.
________________________________________________________________________
Main page: http://www.latiumsoftware.com/en/pascal/delphi-newsletter.php
Group home page: http://groups.yahoo.com/group/pascal-newsletter/
Subscribe/join: pascal-newsletter-subscribe@yahoogroups.com
Unsubscribe/leave: pascal-newsletter-unsubscribe@yahoogroups.com
Problems with your subscription? eds2008 @ latiumsoftware.com
________________________________________________________________________
Latium Software http://www.latiumsoftware.com/en/index.php
Copyright (c) 2000 by Ernesto De Spirito. All rights reserved.
________________________________________________________________________
|