Can I get comments on this file please. I spent a lot of time typing but not much editing it so it's rough.
Please let me know if you guys think it'll be helpful to new developers out there, plus let me know sections that could be added.
Thanks
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">
<IMG SRC="SMDecors/baroque10.gif"
WIDTH="120" HEIGHT="36">
Welcome to the Lazarus Project
Information Page
Welcome to the Lazarus Project Information page.
This document is designed for the "new" developer to Lazaurs. 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 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 widget set 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 widget set 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 widget set to use by selecting them from a list..
Currently, the GTK widget set is 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 IntSendMessage3That function is called by the TControl class and is used to send the widget set 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 a event/signal for that control. For example, in TWinControl.AttachSignals, a event is assigned for LM_DETROY. That signal/event is then assigned to that twincontrol. The SetCallback function in gtkobject tells the GTK widget to call a proceure in gtkcallback 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. All
TButton does is declare a few "message" procedures. These procedures are called automatically when the associated message is dispatched. LM_PRESSED is dispatched when the button is pressed, LM_RELEASED is dispatched when the button is released, etc. All these procedure's do is check to see if the developer assigned the OnPressed or OnReleased events to a procedure. If so, it then calls that procedure.
TButton.Create'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 o 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 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 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 SetCaption is called. 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 and we are using GTK widgets, IntSendMessage3 in gtkObject is called. 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 tham 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 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() 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;
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, 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).
How Can I Help : Chapter 2: 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 send all messages to InterfaceBase.IntSendmessage3 which is overrided 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 idea's on how to improve this BRIEF explanation please email the mailing list.
This
document maintained by <A
HREF="">
Material Copyright � 2000 Lazarus Project