⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 layout.pas

📁 这一系列是我平时收集的pascal深入核心变成
💻 PAS
📖 第 1 页 / 共 3 页
字号:
  PtChild.afMetric[Integer(lpHEIGHT)] := UNKNOWN;
  Layout_SolveChild(PtChild);
  Inc(PtChild); // 指向下一个TChild


 // 添加各控件信息到TChild列表
  hWnd := GetTopWindow(hWndParent);
  while IsWindow(hWnd) do
  begin
   // 取控件ID和位置
    PtChild.idc := GetDlgCtrlID(hWnd);
    GetWindowRect(hWnd, PtChild.Rc);
    MapWindowPoints(HWND_DESKTOP, hWndParent, PtChild.Rc, 2);
    for J := 0 to NUMSIDES do PtChild.afMetric[J] := KNOWN;

   // 计算宽度和高度
    PtChild.afMetric[Integer(lpWIDTH)] := UNKNOWN;
    PtChild.afMetric[Integer(lpHEIGHT)] := UNKNOWN;
    Layout_SolveChild(PtChild);

   // 最初都设为'固定的'
    PtChild.fFixed := TRUE;

   // 指向下一个TChild
    Inc(PtChild);

   // 取下一个控件
    hWnd := GetWindow(hWnd, GW_HWNDNEXT);
  end;

 // 最后一个TChild是结束标识
  PtChild.idc := IDC_LASTCHILD;
end;

  // 转换规则长度单位
procedure Layout_ConvertDlgUnits(hWndParent: HWND; pRules: PRule; pChildList: PChild);
var
  Rc: TRect;
  fVertical: BOOL;
  PtRule: PRule;
begin
 // Rc各成员清零
  ZeroMemory(@Rc, SizeOf(TRect));

 // 遍历Rule列表
  PtRule := pRules;
  while (PtRule.Action <> lEND) do
  begin
   // 转换, 对话框单位 ->> 图素单位
    Rc.Right := PtRule.nOffset;
    Rc.Bottom := PtRule.nOffset;
    adgMapDialogRect(hWndParent, Rc);

   // 需要判断当前操作是水平方向还是垂直方向的, 因为两个方向的对话框单位是不相等的
    case (PtRule.Action) of
      lVCENTER: fVertical := TRUE;

      lHCENTER: fVertical := FALSE;
                                                                  // 何时填入? **
      lMOVE, lSTRETCH: fVertical := Layout_MetricIsVertical(lPART(PtRule.ActOn.nMetric));

      else adgFAIL('Invalid action');
    end;

   // 根据动作方向决定正确的转换数值
    if fVertical then
      PtRule.nPixelOffset := Rc.Bottom
    else
      PtRule.nPixelOffset := Rc.Right;

   // 指向下一个 TRule ..
    Inc(PtRule);
  end;
end;

  // 填写未知标识
procedure Layout_MarkUnknowns(hWndParent: HWND; pRules: PRule; pChildList: PChild);
var
  PtRule: PRule;
  pChildActOn: PChild;
  hWnd: LongWord; // HWND
  nOtherUnknown, nOppositeSide, idc, idcFirst, idcLast: Integer;
begin
 // 根据TRule列表, 向TChild列表填写未知标识
  PtRule := pRules;
  while (PtRule.Action <> lEND) do
  begin
    case (PtRule.Action) of
      lSTRETCH: // Metric should be stretched
        begin
         // 定位ActOn控件TChild地址
          pChildActOn := Layout_FindChild(pChildList, PtRule.ActOn.idc);

         // 该控件设置成需要改变的
          pChildActOn.fFixed := FALSE;

         // The part being acted on must be a metric.
         // adgASSERT(ISMETRIC(pRule.ActOn.nMetric));

         // 需要扩展的属性状态未知
          pChildActOn.afMetric[PtRule.ActOn.nMetric] := UNKNOWN;

         // 如果 Left/Top or Right/Bottom 是未知的, 那么 Width/Height 也是.
         // 如果 Width/Height 是未知的, 那么 Right/Bottom 也是未知的.
          nOtherUnknown := Integer(Layout_GetOtherUnknownMetric(lPART(PtRule.ActOn.nMetric)));
          pChildActOn.afMetric[nOtherUnknown] := UNKNOWN;
        end;

      lMOVE: // 移动控件
        begin
         // 定位ActOn控件TChild地址
          pChildActOn := Layout_FindChild(pChildList, PtRule.ActOn.idc);

         // 该控件设置成需要改变的
          pChildActOn.fFixed := FALSE;

         // The part being acted upon must be a side.
         // adgASSERT(ISSIDE(pRule.ActOn.nSide));

         // 需要移动的边状态未知
          pChildActOn.afMetric[PtRule.ActOn.nSide] := UNKNOWN;

         // 相反的边也变成未知, 但 Width/Height 保持不变
         // (实际上, 这是要有6个metrics的主要原因).
          nOppositeSide := Integer(Layout_GetOppositeSide(lPART(PtRule.ActOn.nSide)));
          pChildActOn.afMetric[nOppositeSide] := UNKNOWN;
        end;

      lVCENTER, // 垂直居中
      lHCENTER: // 水平居中
        begin
         // We must be centering a group of one or more controls.
         // adgASSERT(pRule.ActOn.nPart = lpGROUP);

         // 控件组ID范围
          idcFirst := PtRule.ActOn.idcFirst;
          idcLast := PtRule.ActOn.idcLast;
         // adgASSERT(idcFirst <= idcLast);

          hWnd := GetTopWindow(hWndParent);
          while IsWindow(hWnd) do
          begin
            idc := GetDlgCtrlID(hWnd);
            if adgInRange(idcFirst, idc, idcLast) then
            begin
             // 定位到指定ID控件的TChild处
              pChildActOn := Layout_FindChild(pChildList, idc);

             // 根据动作类型设相应属性未知
              if (PtRule.Action = lHCENTER) then
              begin
                pChildActOn.afMetric[Integer(lpLEFT)] := UNKNOWN;
                pChildActOn.afMetric[Integer(lpRIGHT)] := UNKNOWN;
              end else
              begin
               pChildActOn.afMetric[Integer(lpTOP)] := UNKNOWN;
               pChildActOn.afMetric[Integer(lpBOTTOM)] := UNKNOWN;
              end;

             // Child acted upon is no longer fixed. ??
              pChildActOn.fFixed := FALSE;
            end;
            hWnd := GetWindow(hWnd, GW_HWNDNEXT);
         end;
       end;

       else adgFAIL('Invalid action');
    end;
  end;
end;

function Layout_CheckChild(const pChild: TChild): BOOL;
const
  pszMetric: array[0..5] of PChar = ('left', 'top', 'right', 'bottom', 'width', 'height');
var
  i: Integer;
  sz: array[0..80] of Char;
  L: array[0..1] of DWORD;
begin
  Result := TRUE;
 // Any unknown metric indicates a problem with the rules, so we 'assert'.
  for i := 0 to NUMMETRICS - 1 do
  begin
    if (pChild.afMetric[i] = UNKNOWN) then
    begin
      L[0] := Integer(pszMetric[i]);
      L[1] := pChild.idc;
      wvsprintf(sz, 'Layout couldn'#$27't find %s of id=%d', @L[0]);
      adgMB(sz);
      Result := FALSE;
    end;
  end;
end;

function Layout_ApplyRules(hWndParent: HWND; pRules: PRule; pChildList: PChild): BOOL;
var
  PtRule: PRule;
  fAppliedAtLeastOneRule: BOOL;
begin
 // fOK = TRUE;
  Result := TRUE;

 // Check assumptions.
 // adgASSERT(IsWindow(hwndParent));
 // adgASSERT(pRules);
 // adgASSERT(pChildList);

 // Based on the list of rules, mark all unknown child metrics as UNKNOWN.
  Layout_MarkUnknowns(hWndParent, pRules, pChildList);

 // Traverse the rule list, converting offsets from dialog units to pixels.
  Layout_ConvertDlgUnits(hWndParent, pRules, pChildList);

 // Mark all the rules as unapplied before attempting to apply them.
  PtRule := pRules;
  while (PtRule.Action <> lEND) do
  begin
    PtRule.fState := UNAPPLIED;
    Inc(PtRule);
  end;

 // Loop through the rule list for as long as we are able to apply at least
 // one rule (if we make a pass through the entire list, and we are unable
 // to apply any rule, we are finished).
  repeat
    fAppliedAtLeastOneRule := FALSE;
    PtRule := pRules;
    while (PtRule.Action <> lEND) do
    begin
      if (PtRule.fState <> APPLIED) then
      begin
        if Layout_ApplyRule(hWndParent, pRules, pChildList, PtRule) then
          fAppliedAtLeastOneRule := TRUE;
      end;
      Inc(PtRule);
    end;
  until (fAppliedAtLeastOneRule = FALSE);

 // Verify that all rules have been successfully applied.
  PtRule := pRules;
  while (PtRule.Action <> lEND) do
  begin
    // adgASSERT(pRule->fState == APPLIED);
    if (PtRule.fState <> APPLIED) then Result := FALSE; // **
    Inc(PtRule);
  end;
end;

function Layout_ApplyRule(hWndParent: HWND; pRules: PRule; pChildList: PChild; PtRule: PRule): BOOL;
var
  pChildRelTo, pChildActOn: PChild;
  ChildRelTo: TChild;
  ptChild, pChildListNew, pSrc, pDest: PChild;
  nRules, nMetric, nChildren, idcFirst, idcLast, nOffset, nCentered: Integer;
  RcBounds: TRect;
  hWnd, hWndFirst: LongWord; // HWND
  pr, prn, prNew: PRule;
  idc: Integer; // **
begin
  Result := FALSE;

 // Find the child and part(s) that we are going to act relative to
  pChildRelTo := Layout_FindChild(pChildList, PtRule.RelTo.idc);

  case lPART(PtRule.RelTo.nPart) of // **
    lpLEFT, lpTOP, lpRIGHT, lpBOTTOM, lpWIDTH, lpHEIGHT:
     // We can't apply a rule relative to a metric that is unknown.
      if (pChildRelTo.afMetric[PtRule.RelTo.nMetric] = UNKNOWN) then Exit;

    lpGROUP:
      begin
       // We can't apply a rule relative to a control unless we know its
       // left/top and right/bottom sides (for centering).
       // adgASSERT(pRule->RelTo.idcFirst == pRule->RelTo.idcLast);
       // adgASSERT((pRule->Action == lHCENTER) || (pRule->Action == lVCENTER));
        if (PtRule.Action = lHCENTER) then
        begin
          if (pChildRelTo.afMetric[Integer(lpLEFT)] = UNKNOWN) or
             (pChildRelTo.afMetric[Integer(lpRIGHT)] = UNKNOWN) then
          Exit;
        end else
        begin
          if (pChildRelTo.afMetric[Integer(lpTOP)] = UNKNOWN) or
             (pChildRelTo.afMetric[Integer(lpBOTTOM)] = UNKNOWN) then
          Exit;
        end;
      end;
  end;

 // Make a local copy of the child we are relative to. We need to do this
 // because we may need to apply a percentage to the width/height metrics
 // and we don't want to modify the actual child list.
  ChildRelTo := pChildRelTo^;

 // Use percentage to modify the width/height of the child we are relative to
  if (PtRule.RelTo.nMetric = Integer(lpWIDTH)) or
     (PtRule.RelTo.nMetric = Integer(lpHEIGHT)) then
  begin
    ChildRelTo.anMetric[PtRule.RelTo.nMetric] := PtRule.RelTo.nPercent * ChildRelTo.anMetric[PtRule.RelTo.nMetric];
    ChildRelTo.anMetric[PtRule.RelTo.nMetric] := ChildRelTo.anMetric[PtRule.RelTo.nMetric] div 100;
    Layout_SolveChild(@ChildRelTo);
  end;

 // Apply our rule based on the action field
  case (PtRule.Action) of
    lSTRETCH: // Metric should be stretched
      begin
       // The part being acted on must be a metric. If it is a width/height
       // metric, it must be 100% of the width/height.
       // adgASSERT(ISMETRIC(pRule->ActOn.nMetric));
       // adgASSERT(ISSIDE(pRule->ActOn.nSide) || (pRule->ActOn.nPercent == 100));

       // The part being acted relative to must be a metric.
       // adgASSERT(ISMETRIC(pRule->RelTo.nMetric));

       // Find the child being acted on and stretch the specified metric.
        pChildActOn := Layout_FindChild(pChildList, PtRule.ActOn.idc);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -