簡體   English   中英

如何訪問非可視Delphi組件上的設計位置?

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

在IDE中設計表單時,可以自由放置和放置非可視組件(例如TMainMenus,TDatamodules)。 該位置將保持不變,以便在重新加載表單時這些組件會顯示在正確的位置。

但是,TComponent沒有頂部或左側屬性!

那么,我的代碼如何訪問非可視組件的“設計位置”?

可以在運行時訪問它,但這有點不合時宜。 (主要是因為它是作為一種hack實現的。)

將Left和Top屬性設置為Word大小的值,並將它們兩個打包在一起,放入名為TComponent.FDesignInfo的Longint中。 您可以使用DesignInfo屬性獲取其值。 看看TComponent.DefineProperties來了解它的用法。

並且:

  • 如何將DesignInfo設置為(-100,-100)之類的點?

目標:將圖標放在可視區域之外,在設計時將其隱藏。

注意:例如,在創建直接從TComponent派生的簡單視覺組件時,這非常有用,我想到了一個非常簡單的標簽(taht始終與top對齊,allways始終為= 0,top是自動計算的,bla bla bla)僅將其標題屬性存儲到.dfm文件中; 而且任何本地化程序都只會看到該標題屬性。

解決方案是使用如下代碼覆蓋ReadState

procedure TMyComponent.ReadState(Reader:TReader);
var
   NewDesignInfo:LongRec;
begin
     inherited ReadState(Reader);
     NewDesignInfo.Hi:=Word(-100); // Hide design-time icon (top position = -100)
     NewDesignInfo.Lo:=Word(-100); // Hide design-time icon (left position = -100)
     DesignInfo:=Longint(NewDesignInfo); // Set the design-icon position out of visual area
end;

希望對別人有幫助!

這對我有用。 來源: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;

使用樣本:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM