[Lazarus] LCL + GTK2 + CustomControl : Help needed

dev.dliw at gmail.com dev.dliw at gmail.com
Mon May 13 14:09:54 CEST 2013


Hi,
as I can't describe my problem in 2 sentences, I first try to give an 
overview.

= information you might need =

System: Linux 64bit, fpc 2.6.2 / lazarus 1.0.8
Assumption: LCLGTK2

I have a C library, which creates a custom control. It takes a window 
handle as parent (in my case only gtk -> gtk handle) and adds its 
visual / control to it.
The "plain" way to use it (which works fine) is:

--- snip ---

  gtk_init(nil, nil);  // in my case gtk
  Window := gtk_window_new(GTK_WINDOW_TOPLEVEL); // Create a window

  { do some gtk stuff }

  // add a box to the window
  Box := gtk_vbox_new(False, 0);
  gtk_container_add(GTK_CONTAINER(window), Box);

  { do library init }  
  { pass "Box" to library }
  { -> there's a window with the library's visual in it :) }

--- end ---
Passing "Window" to the library in the above example works, too.

= The actual problem =

Now I created a custom Control for Lazarus: TCVisual = class(TWinControl).
>From what I saw, there are 2 different ways to implement this control in LCL:

1.
Override CreateWnd with *no* inherited and pass Parent.Handle to the library.
Get the childs handle from the library and set my control's handle to it.

To me this seems to be the preferred way, as the hierarchy is as flat as 
possible:

LCL Parent
    |
  TCVisual with library's handle


--- Code : snip --

procedure TCVisual.CreateWnd;
begin
  { make sure parent handle exists, if not: Parent.NeedsHandle etc. }

 // library's parent = control's parent
  parent_widget := Pointer(Parent.Handle);

  { pass "parent_widget" to the library }
  { do library calls }

// getWidget is a replacement for getting the newly created child from the 
library
  Handle := HWND( getWidget() );

  { maybe call inherited now, after handle is set (?) }
end;

-- end --

The problem:
Gtk: Attempting to add a widget with type GtkExpandedContainer to a GtkWindow, 
but as a GtkBin subclass a GtkWindow can only contain one widget at a time; it 
already contains a widget of type GtkVBox


2.
Let LCL create a Handle and pass it to the library as the parent.
Hierarchy then (should) look like this:

LCL Parent
    |
  TCVisual : handle created by LCL (GTK2) via 
  TWSWinControlClass(WidgetSetClass).CreateHandle(Self, Params);
      |
    Library

--- Code : snip --

procedure TCVisual.CreateWnd;
begin
  inherited;

  // library's parent = control's handle
  parent_widget := Pointer(Handle);

  { pass "parent_widget" to the library }
  { do library calls }

  // Handle := HWND( getWidget() );  // library's handle isn't needed
end;

-- end --

The problem:
Gtk: gtk_scrolled_window_add: assertion `bin->child == NULL' failed

Apparently LCL sets bin.child, but the library assumes it to be nil
-> a small hack 'solved' this problem:
  PGtkWindow(Handle)^.bin.child := nil;

Result:
Gtk: gtk_scrolled_window_add(): cannot add non scrollable widget use 
gtk_scrolled_window_add_with_viewport() instead

--------

I also did some other 'tests', but I don't think they have any additional 
valuable infos.
[Apart from: abusing a GroupBox's handle did work after setting bin.child to 
nil, instead of the GroupBox the library's visual appeared, but LCL crashed on 
Form.Destroy :) ]

My question now is:
How does LCL add controls - the parent was the main form - ?
Are there e.g. additional containers somewhere (maybe invisible for the user)?
[I read the LCLGTK sources, but I didn't get too much info out of it... :( ]

How can I get a handle from LCL / create and add a handle which basically 
behaves the same way as a VBox / HBox / Window (= the ones I know to work)?

I tried to create a VBox myself in CreateWnd
- gtk gave a error similar to (1), so I assume there is something more I need 
to know on how LCLGTK2 internally handles all the gtk stuff -
but I really would prefer to do as little direct gtk as possible...

As I actually never did anything with gtk before, any hints may be valuable 
to me.
If something similar was solved already, simply point to it.

Thanks for reading this long message and
Thanks in advance for any help

Regards,
d.l.i.w




More information about the Lazarus mailing list