[RE: [Re: [lazarus] wndproc]]

Samuel Liddicott sam at campbellsci.co.uk
Mon Aug 23 07:13:36 EDT 1999




> -----Original Message-----
> From: Michal Bukovjan [mailto:mbukovjan at netscape.net]
> Sent: 20 August 1999 07:53 PM
> To: lazarus at miraclec.com
> Subject: Re: [RE: [Re: [lazarus] wndproc]]
>
> We are interested (as I understand it) in the possibility to have
> Lazarus for
> both Win32 and Linux, and use any arbitrary widget for visuals.

yes

> This means that we should avoid all Win32 stuff in core components like
> TComponent, TControl, TWinControl, and the basic set of controls,
> so that it
> is possible to write an application (using standard components) once and
> compile under Win32 and Linux without no code change.

Depends on what you mean.  HWND is not Win32 specific.  It looks like it
because of its name but it is actually a generic handle to the widget via
the widget-manager.  Wndproc looks win32 specific because of the name, but
it is not.  It is really a generic virtual message interceptor, the *only*
NON_PLATFORM_SPECIFIC way to intercept messages before they hit the
handlers.  We could call it "PreviewHandler" instead of wndproc, but lets
keep the same name for compatability.  So YES, lets avoid where possible
win32 specifics, but we need to decide on what are actually win32 specific
and what are actually very useful non-specific members with win32 sounding
names that we need to keep.

> I say SHOULD, but if neccessary, we may opt to insert some Win32
> specific code
> and let it become dummy under anything else.

In the end CreateParams will have a different implementation with win32 that
GTK but this is the ONLY difference that needs to exist in the FCL with
regards to instantiating a widget via the widget-manager.

> There was a discussion on that topic recently, including whether
> we should use
> IFDEFs and such, which resulted in those gtkint.pp, win32int.pp
> units and all
> this stuff.

I had thought of this.  Another way is to have a global WidgetManager object
that can be called upon to doo widget-manager specific stuff.

The differing CreateParams implementations for the default controls could
exist either way, although it would result in high-coupling to the
widget-manager as more fancy controls are invented; same problem for
includes as newer controls are implemented.

$IFDEF is really the only way although a $IFDEF could be $IFDEF}{$INCLUDE

Also if I get my way regarding CreateWnd in most cases (apart from the
default control set) no developer will need widget-specific code at all it
will be hidden in the FCL and so yes; and I think you are right, IFDEF's are
the way to go.

> So I think the possibility to use existing Delphi components
> descendants that
> work and use Win32 specific stuff (i.e. Windows messages) will be, ..er..,
> somewhat limited to Windows, and useless under Linux.

I hope that even under linux, if a component moves, a WM_MOVERESIZE or
something message will be sent.

> While this may be valid from Windows point of view (the
> application will not
> be portable, author decides), if such thing would be found in
> core components,
> that would handicap other widget platforms. And the other way
> around, we could
> certainly use some GTK specific stuff in core components, the
> other, including
> Win32 users, would be handicapped instead. Not speaking about
> Motif/Lesstif,
> Qt, or whatever.

I pale with horror.  You just said to start with that:
"We are interested (as I understand it) in the possibility to have Lazarus
for both Win32 and Linux, and use any arbitrary widget for visuals."

and then

"This means that we should avoid all Win32 stuff in core components"

woah!

> Stop. I am not a moron :-)

Well, no!

> I am not the one who decides about
> this in the end,
> anyway (that is the core component maintainer).

Hmmm surely they implement, but the group decides?

> That is just my
> point of view.
> And since you seem to know the Win32 widgets stuff well, it may
> be inevitable
> to have some Win32 support integrated after all, if you say so, be it by
> IFDEFs. IMHO, that is the solution Sibyl chose, as I looked into
> their code.

The win32 model is actually more abstracted than the GTK model; if we follow
the windows/delhi there is no danger of shutting ourselves in.  The
deception is that the names of the win32 abstractions are not abstract names
but names specific to the impementation of the abstraction.  But whats in a
name?  We can certainly live with it.

The mere fact that GTK does not need all of win32 model is evidence of its
abstraction.  The fact that a windows delphi implementation and many many
components cannot be implemented with the GTK model is evidence of it lack
of abstraction.  This is an example of our first difficulty in runnig
lazarus with a non-GTK widget set.  If we want widget-choice we had better
go for abstraction.

The reason delphi works like this is because they extended the windows
abstraction even further so it can be used in what I am calling the GTK way
(with seperate handlers - much nicer than wndproc WHEN you've got the
choice) as well as via the windows way.

> > > 2) Leave out some Delphi solutions which had to be created/were suited
> for
> > > Windows, and supply our own, more versatile ones (be their
> > > Delphi-incompatible).

Where you say windows, also say "OS/2" + other hitherto unexamined widget
sets.

> > > Again, remember that Delphi is VERY designed for
> > > Windows, and if we want Lazarus for as much platforms as possible, we
> > > definitely will need to abandon some Delphi approaches.
> >
> > If we want Lazarus for as much platforms as possible, we
> definitely do not
> > need to rule out platform approaches.
>
> ??? What do you mean ?

That we don't want to remove things just because windows uses them.  That
doesn't make them win32 specific.  That we don't want to become GTK
specific.

> > > The shiny example of the 2) is Handle, which is rarely found
> > > anywhere beyond
> > > Windows, and since Windows get COMized, not even there in the
> future (my
> > > guess).
> >
> > The handle is "some" reference to the "real" object that is
> managed by the
> > bound GTK.  This is going to be used with whatever gui we bind to.  OK,
> > handle isn't the best name UNDER GTK but its a better name under some
> others
> > (like Win or OS2).
>
> Yes. But while it is an integer under Win32 (32-bit), it is meant to be a
> pointer under GTK (which happens to be 32-bit on IA32). Then, I
> am not sure
> about 64bit platforms. (The compiler might take care about that, though).

The fact that it is a pointer in GTK should be kept "secret".  Are you
really sure it is an integer in win32.  I think it is actually a pointer,
but if it is presented as an integer no-one will mess about without.  I also
think that 16 bit windows handles were near pointers.

> > The only reason for thinking a .wndproc slows things down is if
> you think
> > what's in the wndproc isn't needed - and yes its faster if you do less.
> >
> You are absolutely right on this one. Still I claim that the HUGE case
> statement is NOT effective. In my opinion, it is not the best approach,
> although it is usable.

You are also right, but with Delphi applications, the Case statement is not
huge simply because of the nice event handlers.

> It is true that many components DO use it, as they have no other
> choice under
> Windows, anyway (or do they?).

You are right, in many cases there is no choice (except even worse filthy
hacks that really are win32 specific)

[BTW Once I did some self-modifying code that changed the virtual method
table at runtime to intercept something I needed!. *cough* but thats
Borlands fault!  I'm not proud of it]
[What I am proud of is modifying the sysutils at runtime to intercept the
GetDate GetTime, Now (etc) calls to work round a winNT 16bit bug where the
calendar didn't run at the same rate as the clock!!! True! The date wrapped
round before the lock did, and the calendar got further and further out!)
(My unit meant you could leave your program as-is, merely by linking with
the unit would fix the problem)

> > If you like, let each component have a flag which says whether or not
> > wndproc can be skipped. The GTK callback handler could check
> this flag and
> > only call wndproc if it is not set.
>
> Hmm, that could be a viable solution :-)

It would delay the decision anyway!

> Now, as I remember, intercepting owner's or parent's WndProc (I know that
> trick) is generally considered a dirty hack and should be used with great
> care.

true

> Again, the form designer in Lazarus may use a completely different
> approach, since it has to be Linux-compatible. In Linux, there is
> no Win32 API
> to intercept any WndProc !

There will be a wndproc.  The form designer intercepts nicely:

procedure TControl.WndProc(var Message: TMessage);
var
  Form: TForm;
begin
  if csDesigning in ComponentState then
  begin
    Form := GetParentForm(Self);
    if (Form <> nil) and (Form.Designer <> nil) and
      Form.Designer.IsDesignMsg(Self, Message) then Exit;
  end;

Nice, eh? Yep a slowdown, but only at design time.

> Enough. Just once again - if the WndProc is really inevitable, it may be
> there, after all. But we should double-check the need for any OS
> platform-specific code.

Well, as I keep saying, only the name is os-specific (well, it applys to
OS/2 as well), the abstract concept is a sound one, that may also be needed
by future widget managers, but is certainly needed now as a pre-message
handler interceptor.

In fact the whole wndproc dispatch system is really a direct implementation
of an object-class system in straight C.
Intercepting wndprocs is the way to override methods within this system.
And this system is a neat way of marrying object pascal to any object system
used by any widget set.

Sam






More information about the Lazarus mailing list