Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2000-01

HTML Document - Changes made

1 message · 1 person ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Shane Miller

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 ) 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.

Reply by email