[lazarus] HTML Document - Changes made

Shane Miller SMiller1 at stvgb.org
Tue Jan 11 11:43:59 EST 2000


OK, I left Justified everything
I made corrections to the TBUTTON reference
I made spelling and gramatical corrections.

The base question is "Will this help anyone or should we be doing something totally different?"

New file is attached.
Shane



Title: Welcome to the Lazarus Project Information Page

 

 





<IMG SRC="SMLogo/lazarus_sm.jpg"
WIDTH="250" HEIGHT="188">
The Official Source of Lazarus Project Information

<IMG SRC="SMDecors/baroque2J.gif"
ALT="Welcome" WIDTH="480" HEIGHT="52">




Welcome to the Lazarus Project Information Page
This document is designed for the "new" developer to
Lazarus. From this document you will learn how to add code to Lazarus and how
we have setup the components, controls, events, etc inside the Lazarus code.

This page will be updated as changes are made to the componets
and the underlying structure of the LCL (Lazarus Component
Library).
A
brief explaination:Lazarus is built to allow it the be run using many
differnet types of "widget sets". A few examples of "widget
sets" would be the default Win32 widgets (controls) that are used within
the Windows environment. Also, within windows and linux you can use GTK widgets
or QT widgets. This allows Lazarus to be run under Windows and Linux and have
total code compatability.
All the code that determines which widgets to use is found
within a file called Interfaces.pp or one of the files it uses. Within this
file are the "{$Define ???}"'s that specify which widgets the
controls should be built off of.
"{$define GTK}" causes the InterfaceObject class to
become a class of "TGtkObject" and therefore inherit all the gtk
specific commands/methods/properties. This is a quick and easy method of
controlling the "widget set" without making the developer control
which files or directories should be in the search path. This way it's all
controlled by one "Define". Later, this will be a setting within the
IDE itself and will allow the developer to simply choose which widgets to use
by selecting them from a list..
Currently, the GTK widgets are the most complete within Lazarus
and therefore I will start by explaining the files associated with that
"widget set".
Interfaces.pp defines a class TInterfaceObject that inherits
from TGTKObject which is found in GTKInt.pp
GTKInt.PP:Contains the class definition for TGTKObject
The most important method in this class definition is IntSendMessage3
That function is called by the TControl class and is used to send the widgets
messages such as LM_CREATE to create a widget, LM_SETLABEL to change a widget's
caption, LM_SHOWHIDE to set a widget's visible property to true/false, etc.
Each "widget set" (QT, WIN32, GTK) will have it's own IntSendMessage3
function inside their specific class definition (like TWIN32Object or
TQTObject). All code associated with the GTKInt.pp class definition can be
found in GTKObject.inc.
EVENTS: Events are currently assigned by calling a
procedure within TControl called "SetCallback" which then calls each
widget interface object (in GTK's case, it calls TGTKObject") and assigns
an event/signal for that control. For example, in TWinControl.AttachSignals, an
event is assigned for LM_DESTROY. That signal/event is then assigned to that
TWincontrol. The SetCallback function in gtkobject tells the GTK widget to call
a procedure in gtkcallback.inc when it being destroyed and pass it the
SENDER from the initial SetCallBack call. When the control is being destroyed,
gtk fires a "destroy" signal. When that signal occurs, a procedure in
gtkcallback.inc gets called and uses the SENDER property that we told it to
send along when we connected the signal, and we call
TControl(SENDER).WindowProc(Message). Message is a TLMessage (compatable with
TMessage) that we fill with the appropriate information for each event.
As an example of a component, I will explain TButton.

TButton:TButton inherits from TButtonControl. TButton's
Create method's only job is to call the inherited create, then set the
fCompStyle property. Every control has a fCompStyle property. This allows the
"widget set" to know what type of control it is and therefore
create/destroy/click/show/hide/... the correct type of widget. In TButton,
fCompStyle is set to csButton.
TButtonControl does nothing but call the inherited Create.
TButtonControl is used by developers when they add new button types. They can
inherit directly from TButtonControl. TButtoncontrol inherits from TWinControl.

TWinControl is in charge of doing most of the work. It set's
all the call backs for "windowed" controls, creates a list of
controls and their children, and inherits from TControl. TControl has a
TNotifyEvent procedure called ONCLICK that is called whenever a control is
clicked. We use this for the button to determine when the button is clicked.
All the ONCLICK, ONRESIZE, ONMOUSEDOWN, etc is handled by the TCONTROL class
and therefore isn't needed in the declaration of TButton
TControl sends messages back and forth to the interface object
for each widget type. For example, when "caption" is set to some
value, a procedure called SetText is called in the TCONTROL class. This
procedure calls Sendmessage(LM_SETLABEL,Self,nil). SendMessage (defined in
controls.pp) calls the InterfaceObject.IntSendMessage3 and passes it the
message (LM_SETLABEL) and self. .
In the case that GTK is defined in the Inteerfaces.pp file, we
are using GTK widgets. Therfore IntSendMessage3 in gtkObject is called when the
TCONTROL class makes a call to the function InterfaceObject.IntSendMessage3. It
determines that a LM_SETLABEL message was sent and it calls
TgtkObject.SetLabel(Sender) where Sender equals the "Self" that we
sent it. In gtk's SetLabel we call a procedure gtk_label_set_text after
determining that SENDER is a TBUTTON. We pass it the label of the button (which
is actually a child widget of the button widget) and we also pass it the value
of TButton(Sender).Caption.
If we were using WIN32 our IntSendMessage3 in win32interface
would call a SetLabel function that would call a Windows API function to set
the label. In QT widgets we call a QT specific function call.
All other properties/settings for the controls are set the same
way. Each type of property has it's own message and this implementation is
hidden within TControl so most developers will never need to understand this. 

How can I participate?: Let's say you are looking
through the code and notice that we don't have a TCalendar component but GTK
does and you would like to implement it. If Delphi doesn't have this control
already, you will need to create a new unit and include file. The skeleton
files for this can be found in lazarus/lcl/templates. make sure you load these
and save them as Calendar.pp and Calendar.inc in lazarus/lcl.
Create the classes called TCalendar and add a fCompStyle
constant for a calendar into vclglobals.pp. Call it csCalendar and assign it to
the last cs???? +1. In TCalendar's create moethod, call the inherited method,
then set fCompStyle to csCalendar.
In gtkobject.inc, go to IntSendMessage3. If you follow the
message LM_CREATE through this procedure, you will see that it calls
CreateComponent. In the procedure CreateComponent the property fCompStyle is
looked at (the local variable CompStyle is assigned fCompStyle's value) and
this is used to determine how to create the widget. To create a gtk Calendar
widget, the call is gtk_calendar_new() (this can be found at www.gtk.org) so
you create a entry into the CASE statement
csCalendar : begin
p := gtk_calendar_new();
gtk_widget_show(p);
end;Now in your form's code (where you want the Calendar) all
you need to do is add the code 
Calendar1 : TCalendar;
Calendar1 := TCalendar.create(Form1); //Form1 is the owner
Calendar1.Parent := Form1; //Form1 should be the form name
Calendar1.Show;It's basically that simple! Now gtk offers a few
other procedures that you can take advantage of for this control:
gtk_calendar_select_day, gtk_calendar_select_month, etc. These can be used when
you add a Day and Month property to TCalendar. In the SetDay and SetMonth
methods, you simply call SendMessage(LM_SETDAY,Self,nil) or
SendMessage(LM_SETMONTH,Self,Nil). You will need to add LM_SETDAY and
LM_SETMONTH into the LMessage.pp file under the section for messages sent to
the interface. Once you have this, you need to go into gtkobject and add to the
case statement in IntSendMessage3 for those two messages. For each message,
call the appropriate gtk call using either TCalendar's day property or
TCalendar's Month property (which should be set in SetDay and SetMonth in
TCalendar prior to calling the SendMessage).
Of course there are many things that can be done without
modifying any widget specific code. For example, we are currently trying to
create an IDE based on our code. We are close to getting the editor portion
working but we have many TODO's left. If you are interested in getting
involved, this is a great spot to jump in. If you are familiar with the tool
"grep" you can search for the words "TODO" in the source.
Each one marks a spot that needs to be finished. Simply find one you are
interested in, let the mailing list know you will be working on it and go to
it.
A brief map of files: 
Interfaces.pp - Declares a class called InterfaceObject that (depending
on the "define" inherits from GTKInt.pp. InterfaceObject is
created within the Initialization portion of this file.


GTKINT.pp - Declares a class called gtkobject. Code is found in
gtkobject.inc
GTKObject (class) inherits from InterfaceBase which defines functions that are
either specific to the "widget set", or other functions that simply
don't belong in any other class. 
Interfacebase uses the file winapih.inc to define calls that are compatable
with the windows API calls that are required for compatability. If they are
"widget set" dependent (for example gtk) then the calls in
winapih.inc are overridded in a widget dependent file. In GTK's case it's
called gtkwinapih.inc and the actual code for those procedures are found in
gtkwinapi.inc. This allows us to create different definitions for windows API
calls based on the interface.

TControl sends all messages to InterfaceBase.IntSendmessage3 which is overriden
by the widget specific files. Therefore if GTK is defined in Interfaces.pp then
the IntSendMessage3 is called in gtkobject.inc.This may
seem confusing but once you look into it you will get the hang of it. Feel free
to email the mailing list with questions. Any ideas on how to improve this
BRIEF explanation please email the mailing list.








More information about the Lazarus mailing list