MDIChild in DLL from Centura

I solved the problem, using a MDI-Child in a DLL (Delphi 2.01) with a
MDIForm in Centura.

You have to override three procedures:

procedure CreateParams (var Params: TCreateParams); override;
procedure CreateWindowHandle (const Params: TCreateParams); override;
procedure DestroyWindowHandle; override;

You need the MDIClient-Handle of the MDIForm:

var
  hWndClient: HWND;

And you have to export this three procedures of the dll:

procedure InitDLL (h: HWND); far; stdcall;
procedure ShowMyForm; far; stdcall;
procedure DoneDLL; far; stdcall;

procedure InitDLL (h: HWND);  // h is the window-handle of the MDIForm
begin
  Application.Handle:=h;
  hWndClient:=FindWindowEx(h,0,'MDIClient','');  
  // works on Win95 & NT4
  MyForm:=TMyForm.Create(Application);
end;

procedure ShowMyForm;
begin
  MyForm.Show;
end;

procedure DoneDLL;
begin
  MyForm.Release;
end;

procedure TMyForm.CreateParams (var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  with Params do begin
    Style:=(Style or WS_CHILD);
    WndParent:=hWndClient;
    WindowClass.lpfnWndProc:=@DefMDIChildProc;
  end;
end;

procedure TMyForm.CreateWindowHandle (const Params: TCreateParams);

var
  CreateStruct: TMDICreateStruct;

begin
  with CreateStruct do begin
    szClass:=Params.WinClassName;
    szTitle:=Params.Caption;
    hOwner:=HInstance;
    X:=Params.X;
    Y:=Params.Y;
    cX:=Params.Width;
    cY:=Params.Height;
    style:=Params.Style;
    lParam:=Longint(Params.Param);
  end;

WindowHandle:=SendMessage(hWndClient,WM_MDICREATE,0,Longint(@CreateStruct));
end;

procedure TMyForm.DestroyWindowHandle;
begin
  SendMessage(hWndClient,WM_MDIDESTROY,Handle,0);
end;

BTW FormStyle has to be fsNormal. Do not use fsMDIChild!

Two problems are left:

1) The Window-Menu of the MDIForm is not updated when the child is
opened or closed. I solved this with a timer that fires every second
and the following OnTimer-Procedure:

  if (UpdateNeeded=True) then begin
    SendMessage(hWndClient,WM_MDIREFRESHMENU,0,0);
    UpdateNeeded:=False;
  end;

UpdateNeeded is a boolean value. I set it to True in TMyForm.FormClose
and TMyForm.FormShow.
You cannot send the message in FormShow or FormClose because at this
point the visibility of the form has not changed yet. Better solutions
appreciated...

2) The form gets VK_TABs in OnKeyDown and KeyPress instead of changing
the Focus! I am working on a solution like

  procedure TMyForm.FormKeyDown(Sender: TObject; var Key: Word; Shift:
TShiftState);

  var
    f: Boolean;

  begin
    f:=(ActiveControl<>nil);
    f:=(f and ((ActiveControl as TWinControl).Owner=Self));

    if (f=True) and (Key=VK_TAB) then begin
      Key:=0;
      SelectNext(ActiveControl,(Shift=[]),True);
    end;
  end;

Suggestions welcome!

Josef Hlawaty
*nospawn*hlaw...@gros.co.at
Please remove *nospawn* for e-mails.