Thursday, February 3, 2011

Delphi MDI Application and the titlebar of the MDI Children

I've got an MDI application written in Delphi 2006 which runs XP with the default theme. Is there a way of controlling the appearance of the MDI Children to avoid the large XP-style title bar on each window? I've tried setting the BorderStyle of the MDIChildren to bsSizeToolWin but they are still rendered as normal Forms.

  • I don't think there is; in my experience, MDI in Delphi is very strictly limited and controlled by its implementation in the VCL (and perhaps also by the Windows API?). For example, don't try hiding an MDI child (you'll get an exception if you try, and you'll have to jump through a couple of API hoops to work around that), or changing the way an MDI child's main menu is merged with the host form's.

    Given these limitations, perhaps you should reconsider why you'd like to have special title bars in the first place? I guess there are also good reasons why this MDI stuff is standardized --- your users might appreciate it :)

    (PS: nice to see a Delphi question around here!)

    From onnodb
  • Thanks onnodb

    Unfortunately the client insists on MDI and the smaller title bar.

    I have worked out one way of doing it which is to hide the title bar by overriding the windows CreateParams and then create my own title bar (simple panel with some Mouse handling for moving). Works well enough so I think I might run it by the client and see if it will do...

    From Marius
  • The way MDI works doesn't gel with what you're trying to do.

    If you need the "MDI" format, you should consider using either the built-in or a commercial docking package, and use the docking setup to mimic the MDI feel.

    In my Delphi apps, I frequently use TFrames and parent them to the main form, and maximizing them so they take up the client area. This gives you something similar to how Outlook looks. It goes a little something like this:

    TMyForm = class(TForm)
    private
      FCurrentModule : TFrame;
    public
      property CurrentModule : TFrame read FModule write SetCurrentModule;
    end;
    
    procedure TMyForm.SetCurrentModule(ACurrentModule : TFrame);
    begin
      if assigned(FCurrentModule) then
        FreeAndNil(FCurrentModule);  // You could cache this if you wanted
      FCurrentModule := ACurrentModule;
      if assigned(FCurrentModule) then
      begin
        FCurrentModule.Parent := Self;
        FCurrentModule.Align := alClient;
      end;
    end;
    

    To use it, you can simply do this:

    MyForm.CurrentModule := TSomeFrame.Create(nil);
    

    There is a good argument that you should use interfaces (creating an IModule interface or something) that you use. I often do that, but it's more complex than needed to explain the concept here.

    HTH

  • All your need - overload procedure CreateWindowHandle, like this:

    unit CHILDWIN;
    interface
    uses Windows, Classes, Graphics, Forms, Controls, StdCtrls;
    
    type
      TMDIChild = class(TForm)
      private
        { Private declarations }
      public
        { Public declarations }
        procedure CreateWindowHandle(const Params: TCreateParams); override;
      end;
    
    implementation
    
    {$R *.dfm}
    procedure TMDIChild.CreateWindowHandle(const Params: TCreateParams);
    begin
      inherited CreateWindowHandle(Params);
      SetWindowLong(Handle, GWL_EXSTYLE, WS_EX_TOOLWINDOW);
    end;
    end.
    
    From CoolMagic
  • Thank you very much from CoolMagic

    From asgarkz

0 comments:

Post a Comment