How to access design position on non-visual Delphi components?

When designing a form in the IDE, non-visual components (eg TMainMenus, TDatamodules) can be freely placed and positioned. The position is persisted, so that on reloading the form these components appear in the correct place.

But, TComponent does not have Top or Left properties!

So, how can my code access the 'designed position' of non visual components?

This can be accessed at runtime, but it's sort of a hack. (Mostly because it's implemented as sort of a hack.)

The Left and Top properties are set up as Word-size values, and the two of them are packed together into a Longint called TComponent.FDesignInfo. You can obtain its value with the DesignInfo property. Have a look at TComponent.DefineProperties to get a look into how it's used.

tcomponent, When designing a form in the IDE, non-visual components (eg TMainMenus, TDatamodules) can be freely placed and positioned. The position is persisted,  I don't want to completely hide the non-visual components but I would like to hide the label with their names. It was the default appearance of non visual components in Delphi 2007 designer: delphi ide delphi-xe7

Kylix Developer's Guide, when designing form in ide, non-visual components (eg tmainmenus, tdatamodules) can freely placed , positioned. position persisted, on reloading form these  Database components aren't so easily replaceable as dialog-box components. Nearly everything in Delphi is designed to use descendants of the standard database components. If you don't use the components, then you won't be using any of Delphi's database capabilities at all.

This worked for me. Source: CnPack CnAlignSizeWizard.pas.

procedure SetNonVisualPos(Form: TCustomForm; Component: TComponent; X, Y: Integer);
const
  NonvisualClassNamePattern = 'TContainer';
  csNonVisualSize = 28;
  csNonVisualCaptionSize = 14;
  csNonVisualCaptionV = 30;
var
  P: TSmallPoint;
  H1, H2: HWND;
  Offset: TPoint;

  function HWndIsNonvisualComponent(hWnd: hWnd): Boolean;
  var
    AClassName: array[0..256] of Char;
  begin
    AClassName[GetClassName(hWnd, @AClassName, SizeOf(AClassName) - 1)] := #0;
    Result := string(AClassName) = NonvisualClassNamePattern;
  end;

  procedure GetComponentContainerHandle(AForm: TCustomForm; L, T: Integer; var H1, H2: hWnd; var Offset: TPoint);
  var
    R1, R2: TRect;
    P: TPoint;
    ParentHandle: hWnd;
    AControl: TWinControl;
    I: Integer;
  begin
    ParentHandle := AForm.Handle;
    AControl := AForm;
    if AForm.ClassNameIs('TDataModuleForm') then // ÊÇ DataModule
    begin
      for I := 0 to AForm.ControlCount - 1 do
        if AForm.Controls[I].ClassNameIs('TComponentContainer')
        and (AForm.Controls[I] is TWinControl) then
        begin
          AControl := AForm.Controls[I] as TWinControl;
          ParentHandle := AControl.Handle;
          Break;
        end;
    end;
    H2 := 0;
    H1 := GetWindow(ParentHandle, GW_CHILD);
    H1 := GetWindow(H1, GW_HWNDLAST);
    while H1 <> 0 do
    begin
      if HWndIsNonvisualComponent(H1) and GetWindowRect(H1, R1) then
      begin

        P.x := R1.Left;
        P.y := R1.Top;
        P := AControl.ScreenToClient(P);

        if (P.x = L) and (P.y = T) and (R1.Right - R1.Left = csNonVisualSize)
        and (R1.Bottom - R1.Top = csNonVisualSize) then
        begin
          H2 := GetWindow(ParentHandle, GW_CHILD);
          H2 := GetWindow(H2, GW_HWNDLAST);
          while H2 <> 0 do
          begin
            if HWndIsNonvisualComponent(H2) and GetWindowRect(H2, R2) then
            begin
              if (R2.Top - R1.Top = csNonVisualCaptionV) and (Abs(R2.Left + R2.Right - R1.Left - R1.Right) <= 1)
              and (R2.Bottom - R2.Top = csNonVisualCaptionSize) then
              begin
                Offset.x := R2.Left - R1.Left;
                Offset.y := R2.Top - R1.Top;
                Break;
              end;
            end;
            H2 := GetWindow(H2, GW_HWNDPREV);
          end;
          Exit;
        end;
      end;
      H1 := GetWindow(H1, GW_HWNDPREV);
    end;
  end;

begin
  P := TSmallPoint(Component.DesignInfo);
  GetComponentContainerHandle(Form, P.x, P.y, H1, H2, Offset);
  Component.DesignInfo := Integer(PointToSmallPoint(Point(X, Y)));
  if H1 <> 0 then
    SetWindowPos(H1, 0, X, Y, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
  if H2 <> 0 then
    SetWindowPos(H2, 0, X + Offset.x, Y + Offset.y, 0, 0, SWP_NOSIZE or SWP_NOZORDER);
end;

Use sample:

SetNonVisualPos(TCustomForm(Designer.Root),MyComponent,10,10);

Introduction to Component Building by Ray Konopka, Design. At the time of this writing, the remote connectivity DataSnap!M offers isn't Many early users of Delphi assumed that only database-centric components could be A data module is simply a container for any component that is not a visual various TSQLClientBataSet components for the tables you want to access. This Delphi VCL component to view, edit, move and hide components on VCL form might also be interesting for you. It comes with full source code & has lots of features. It comes with full source code & has lots of features.

LMD Innovative. Delphi components. LMD IDE-Tools, Although the visual design features of Delphi are not used when building a custom It provides access to implementation-specific elements of the component. are not part of the Visual Component Library, as illustrated by the position of  Introduction to Component Building by Ray Konopka. Note: The following paper was presented at the 1999 Inprise/Borland Conference in Philadelphia Pennsylvania. Click on the source code link to download the examples used in this paper. This paper describes the process of building custom Delphi and C++Builder components.

[PDF] Delphi 7 for Windows Component Writer's Guide, LMD IDE-Tools is collection of native VCL components which help you to set up a which specifies for nonvisual controls creation order when a form is loaded. tables, similar to the table relationship diagrams e.g. known from MS Access. in two ways: At first as stand alone control to set a form in "design mode" or used  Delphi provides visual feedback by placing 4 grey handles (4 small grey boxes) on each of the corners of the selected components. The problem is that the control's contents are rendered on top of the handles.

Using Form Components, this document does not give you any license to these patents. COPYRIGHT Declaring the access properties . This chapter provides an overview of component design and the process of writing Delphi's components reside in a component library that includes the Visual and Left that determine its position on the form. Max's Components for Delphi Visit this download page for 11 free Delphi components, each with a complete description of its features. Among others, there's one for inserting a symbol dialog in word processor apps and another that's a debugger tool for Borland Delphi.

Comments
  • @David, well the IDE is just "Runtime code", surely? I'm not expecting it to be easy, but it's got to be possible.
  • For the left postion try LongRec(YourComponent.DesignInfo).Lo and for the top use LongRec(YourComponent.DesignInfo).Hi
  • What's the benefit of your runtime code having access to the left and top properties of non-visual components?
  • That's the hack I needed. Thanks.
  • Thanks! But how can I SET this values? I need to SET the position of some non-visual components.