2

The two panes located at the bottom of the Obeject Inspector has no use at all, and it's consuming screen estates unnecessarily, as illustrated in the screenshot below. How to disable that two panes even after restarting the IDE? Built-in options or third party plugins would be OK with me. Thanks. enter image description here

Edwin Yip
  • 4,089
  • 4
  • 40
  • 86
  • You can write a plugin to hide the panel. – David Heffernan Jan 06 '17 at 08:06
  • Those all look like entries in the GExperts IDE sub-menu. Have you looked whether it has a configuration option for the Object Inspector? Also, right-click, and in `Show`, uncheck `Quick Action Panel`. – MartynA Jan 06 '17 at 09:04
  • @DavidHeffernan that'll be the final option, if possible. – Edwin Yip Jan 06 '17 at 10:14
  • @MartynA, Just checked GExpert configrations, no such option was found. However, I discovered a new GExperts feature - the 'Go To' dialog enhancement, very handy :D – Edwin Yip Jan 06 '17 at 10:14
  • I never noticed this panel. I wonder where it comes from. The entries disappear when you disable the the corresponding expert, e.g. the "Rename Components ..." entry disappears when you disable the "Rename Components" expert. To see this you must force a redraw by e.g. clicking on a different control. I'm not aware of this being a GExperts feature, but even after playing with the sources for several years I don't know all of them, so it's still possible. – dummzeuch Jan 06 '17 at 16:55
  • You can reduce the height of this panel by drawing the splitter between it ant the property list down so it might be less of a nuisance. This seems to be saved between sessions. – dummzeuch Jan 06 '17 at 16:59
  • It's called the HotCommands panel (of type THotCommands). Must be a new feature of the IDE ("new" as in introduced after Delphi 2007, the IDE I am most familiar with). It's probably possible to hack the IDE to hide that control, but I'm not sure that I will bother. There apparently is an API for this panel: https://community.embarcadero.com/blogs/entry/object-inspector-api-288 – dummzeuch Jan 06 '17 at 17:04
  • 1
    @EdwinYip In case you missed some more GExperts features: I have documented my additions here: https://blog.dummzeuch.de/gexperts-documentation/ – dummzeuch Jan 08 '17 at 16:56
  • @dummzeuch, I appreciate your effort put into GExperts, it's very helpful! – Edwin Yip Jan 09 '17 at 05:56

1 Answers1

5

The XE4 code below shows how to hide the items you want to remove: They are instances of the classes THotCommands and TDescriptionPane.

Update The original version of this answer required a package including an add-in form and a button to refresh the Object Inspector to hide the two unwanted items. In the code below, I've removed the form entirely and the hiding of the items should now be fully automatic. To achieve this, I replaced the previous IDENotifier by a DesignNotification object and use its SelectionChanged event to invoke the code which hides the THotCommands and TDescriptionPane controls. TDesignNotification implements the IDesignNotification interface in DesignIntf.Pas

The other detail which turned out to be critical to getting the hiding process to work automatically is to set the Height of the THotCommands and TDescriptionPane controls to 0, because the IDE seems to reset their Visible property to True after the component selection in the OI is changed. Fortunately, whatever code does that does not also reset their Heights to a non-zero value.

Obviously, to use you add a unit containing the code to a package (.Dpk) file and then compile and install the package in the IDE.

Code:

interface

uses
  [...]ToolsApi, DesignIntf;

type
  TDesignNotification = class(TInterfacedObject, IDesignNotification)
    procedure ItemDeleted(const ADesigner: IDesigner; AItem: TPersistent);
    procedure ItemInserted(const ADesigner: IDesigner; AItem: TPersistent);
    procedure ItemsModified(const ADesigner: IDesigner);
    procedure SelectionChanged(const ADesigner: IDesigner;
      const ASelection: IDesignerSelections);
    procedure DesignerOpened(const ADesigner: IDesigner; AResurrecting: Boolean);
    procedure DesignerClosed(const ADesigner: IDesigner; AGoingDormant: Boolean);
    constructor Create;
    destructor Destroy; override;
  private
    procedure HideItems;
    procedure HideFormItems(Form: TForm);
  end;

var
  DesignNotification : TDesignNotification;

implementation

procedure SetUp;
begin
  DesignNotification := TDesignNotification.Create;
  RegisterDesignNotification(DesignNotification);
end;

constructor TDesignNotification.Create;
begin
  inherited Create;
end;

procedure TDesignNotification.DesignerClosed(const ADesigner: IDesigner;
  AGoingDormant: Boolean);
begin

end;

procedure TDesignNotification.HideFormItems(Form : TForm);
var
  j,
  l : Integer;
  Panel : TPanel;
  C : TComponent;
  HideCount : Integer;

  procedure HideControl(AControl : TControl);
  begin
    AControl.Height := 0;  //  This is necessary because the IDE seems to reset
    //  Visible to True when the Object Inspector is refreshed.
    AControl.Visible := False;
  end;

begin
  HideCount := 0;
  for j := 0 to Form.ComponentCount - 1 do begin
    C := Form.Components[j];
    if C is TPanel then begin
      Panel := TPanel(C);
      for l := 0 to Panel.ControlCount - 1 do begin
        if CompareText(Panel.Controls[l].ClassName, 'TDescriptionPane') = 0 then begin
          HideControl(Panel.Controls[l]);
          Inc(HideCount);
        end
        else
          if CompareText(Panel.Controls[l].ClassName, 'THotCommands') = 0 then begin
            HideControl(Panel.Controls[l]);
            Inc(HideCount);
          end;
        if HideCount >= 2 then  //  we're done
          exit;
      end;
    end;
  end;
end;

procedure TDesignNotification.HideItems;
var
  i : Integer;
  Form : TForm;
begin
  for i := 0 to Screen.FormCount - 1 do begin
    Form := Screen.Forms[i];
    if CompareText(Form.ClassName, 'TPropertyInspector') = 0 then begin
      HideFormItems(Form);
      Break;
    end;
  end;
end;

procedure TDesignNotification.DesignerOpened(const ADesigner: IDesigner;
  AResurrecting: Boolean);
begin

end;

var
  DestroyCount : Integer;

destructor TDesignNotification.Destroy;
begin
  Inc(DestroyCount);
  inherited;
end;

procedure TDesignNotification.ItemDeleted(const ADesigner: IDesigner;
  AItem: TPersistent);
begin

end;

procedure TDesignNotification.ItemInserted(const ADesigner: IDesigner;
  AItem: TPersistent);
begin

end;

procedure TDesignNotification.ItemsModified(const ADesigner: IDesigner);
begin

end;

procedure TDesignNotification.SelectionChanged(const ADesigner: IDesigner;
  const ASelection: IDesignerSelections);
var
  C : TComponent;
begin
  //  This can get called with ADesigner = Nil
  if ADesigner = Nil then
    exit;
  C := ADesigner.Root;
  if C <> Nil then begin
    HideItems;
  end
end;

initialization
  SetUp;
finalization
  if DesignNotification <> Nil then begin
    UnRegisterDesignNotification(DesignNotification);
  end;
end.
dummzeuch
  • 10,975
  • 4
  • 51
  • 158
MartynA
  • 30,454
  • 4
  • 32
  • 73
  • 1
    I would like to add your code as an IDE enhancement to GExperts. Is that OK with you? – dummzeuch Jan 08 '17 at 17:06
  • @dummzeuch: Yes, that would be great. Thanks for the code-tidying, btw. – MartynA Jan 08 '17 at 17:36
  • I found a cleaner way to hide the panes: Add a hidden TPanel and set their parent to that panel. Unfortunately that leaves the splitters still visible. Changing their parent too solves that problem. But when I make them visible again, the order of the splitters and panes is wrong. I just hate the way Borland implemented the splitters. – dummzeuch Jan 08 '17 at 19:38
  • Thank you two MartynA and dummzeuch! Unbelievable, I just asked the question and received a ready to use solution. Great Delphi community! :) – Edwin Yip Jan 09 '17 at 05:57