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

📄 layout.pas

📁 这一系列是我平时收集的pascal深入核心变成
💻 PAS
📖 第 1 页 / 共 3 页
字号:
       // adgASSERT(pChildActOn);
        pChildActOn.anMetric[PtRule.ActOn.nMetric] :=
          ChildRelTo.anMetric[PtRule.RelTo.nMetric] + PtRule.nPixelOffset;
        pChildActOn.afMetric[PtRule.ActOn.nMetric] := KNOWN;
        Layout_SolveChild(pChildActOn);
        PtRule.fState := APPLIED;

       // return(TRUE);
        Result := TRUE;
        Exit;
      end;

    lMOVE: // Whole control should be moved
      begin
       // The part being moved must be a side.
       // adgASSERT(ISSIDE(pRule->ActOn.nSide));

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

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

        pChildActOn.anMetric[PtRule.ActOn.nSide] :=
          ChildRelTo.anMetric[PtRule.RelTo.nMetric] + PtRule.nPixelOffset;
        pChildActOn.afMetric[PtRule.ActOn.nSide] := KNOWN;
        Layout_SolveChild(pChildActOn);
        PtRule.fState := APPLIED;

       // return(TRUE);
        Result := TRUE;
        Exit;
      end;

    lVCENTER, // Vertically center a control/group
    lHCENTER: // Horizontally center a control/group
      begin
       // We can only center a group of one or more controls relative to
       // another control (a single control is a 'group' of one control).
       // adgASSERT(pRule->ActOn.nPart == lpGROUP);
       // adgASSERT(pRule->RelTo.nPart == lpGROUP);
       // adgASSERT(pRule->RelTo.idcFirst == pRule->RelTo.idcLast);

       // First id in group must be less than or equal to the last id
        idcFirst := PtRule.ActOn.idcFirst;
        idcLast := PtRule.ActOn.idcLast;
       // adgASSERT(idcFirst <= idcLast);

       // Ensure that the width/height is known for each control in the
       // group before proceeding with any centering.
        hWndFirst := GetTopWindow(hWndParent);
        hWnd := hWndFirst;
        while IsWindow(hWnd) do
        begin
          idc := GetDlgCtrlID(hWnd);
          if adgInRange(idcFirst, idc, idcLast) then
          begin
            pChildActOn := Layout_FindChild(pChildList, idc);
            if (PtRule.Action = lHCENTER) then
            begin
              if (pChildActOn.afMetric[Integer(lpWIDTH)] = UNKNOWN) then
              begin
                Result := FALSE;
                Exit;
              end; // return(FALSE);
            end else
            begin
              if (pChildActOn.afMetric[Integer(lpHEIGHT)] = UNKNOWN) then
              begin
                Result := FALSE;
                Exit;
              end; // return(FALSE);
            end;
          end;
          hWnd := GetWindow(hWnd, GW_HWNDNEXT);
        end;

       // Create a new list of rules which contains the subset of rules
       // which act on controls in the centered group.
        nRules := 0;
        pr := 0;
        while (pr.Action <> lEND) do
        begin
          Inc(pr);
          Inc(nRules);
        end;
        Inc(nRules);

        GetMem(prNew, nRules * Sizeof(TRule));
        prn := prNew;

        pr := pRules;
        while (pr.Action <> lEND) do // Inc(pr)
        begin
          if adgINRANGE(idcFirst, pr.ActOn.idc, idcLast) then
          begin
            if (PtRule.Action = lHCENTER) then
            begin
              if (pr.ActOn.nPart = Integer(lpLEFT)) or
                 (pr.ActOn.nPart = Integer(lpRIGHT)) then
              begin
                Inc(prn);
                prn^ := pr^;
              end;
            end else
            begin
              if (pr.ActOn.nPart = Integer(lpTOP)) or
                 (pr.ActOn.nPart = Integer(lpBOTTOM)) then
              begin
                Inc(prn);
                prn^ := pr^;
              end;
            end;
          end;
        end;
        prn.Action := lEND;

       // Make a local copy of the child list and set everything to KNOWN.
        nChildren := 0;
        PtChild := pChildList;
        while (PtChild.idc <> IDC_LASTCHILD) do
        begin
          Inc(PtChild);
          Inc(nChildren);
        end;
        Inc(nChildren);

        GetMem(pChildListNew, nChildren * SizeOf(TChild));
        MoveMemory(pChildListNew, pChildList, nChildren * SizeOf(TChild));

        PtChild := pChildListNew;
        while (PtChild.idc <> IDC_LASTCHILD) do // ; pChild++)
        begin
          for nMetric := 0 to NUMMETRICS - 1 do PtChild.afMetric[Integer(nMetric)] := KNOWN;
          Inc(PtChild);
        end;

       // Solve for the children being centered as a sub-problem.
        if (Layout_ApplyRules(hWndParent, prNew, pChildListNew) = FALSE) then
        begin
          adgFAIL('Unable to apply rules to centered children');
          Result := FALSE;
        end;

       // Compute the bounding rectangle of the group
        SetRectEmpty(RcBounds);
        hWndFirst := GetTopWindow(hWndParent);
        hWnd := hWndFirst;
        while IsWindow(hWnd) do
        begin
          idc := GetDlgCtrlID(hWnd);
          if adgINRANGE(idcFirst, idc, idcLast) then
          begin
            pChildActOn := Layout_FindChild(pChildListNew, idc);
            UnionRect(rcBounds, rcBounds, pChildActOn.Rc);
          end;
          hWnd := GetWindow(hWnd, GW_HWNDNEXT);
        end;

       // Find the offset required to center the group's bounding rectangle
       // against the control we are relative to.
        if (PtRule.Action = lHCENTER) then
        begin
          nCentered := ChildRelTo.anMetric[Integer(lpLEFT)] +
            ((ChildRelTo.anMetric[Integer(lpWIDTH)] -
            (RcBounds.Right - RcBounds.Left)) div 2);
          nOffset := nCentered - RcBounds.Left;
        end else
        begin
          nCentered := ChildRelTo.anMetric[Integer(lpTOP)] +
            ((ChildRelTo.anMetric[Integer(lpHEIGHT)] -
            (RcBounds.Bottom - RcBounds.Top)) div 2);
          nOffset := nCentered - RcBounds.Top;
        end;

       // Add in any additional offset from the rule.
        Inc(nOffset, PtRule.nPixelOffset);

       // Go through the new child list, moving each control.
       // adgASSERT(pRule->ActOn.idcFirst <= pRule->ActOn.idcLast);
        hWnd := hWndFirst;
        while IsWindow(hWnd) do // hwnd = GetNextSibling(hwnd))
        begin
          idc := GetDlgCtrlID(hWnd);
          if adgInRange(idcFirst, idc, idcLast) then
          begin
            pChildActOn := Layout_FindChild(pChildListNew, idc);
            if (PtRule.Action = lHCENTER) then
            begin
              Inc(pChildActOn.anMetric[Integer(lpLEFT)], nOffset);
              Inc(pChildActOn.anMetric[Integer(lpRIGHT)], nOffset);
            end else
            begin
              Inc(pChildActOn.anMetric[Integer(lpTOP)], nOffset);
              Inc(pChildActOn.anMetric[Integer(lpBOTTOM)], nOffset);
            end;
          end;
          hWnd := GetWindow(hWnd, GW_HWNDNEXT);
        end;

       // Now modify the real child list based on pChildListNew.
        pSrc := pChildListNew;
        pDest := pChildList;
        while (pSrc.idc <> IDC_LASTCHILD) do
        begin
          if adgINRANGE(idcFirst, pSrc.idc, idcLast) then
          begin
            if (PtRule.Action = lHCENTER) then
            begin
              pDest.anMetric[Integer(lpLEFT)] := pSrc.anMetric[Integer(lpLEFT)];
              pDest.anMetric[Integer(lpRIGHT)] := pSrc.anMetric[Integer(lpRIGHT)];
              pDest.afMetric[Integer(lpLEFT)] := KNOWN;
              pDest.afMetric[Integer(lpRIGHT)] := KNOWN;
            end else
            begin
              pDest.anMetric[Integer(lpTOP)] := pSrc.anMetric[Integer(lpTOP)];
              pDest.anMetric[Integer(lpBOTTOM)] := pSrc.anMetric[Integer(lpBOTTOM)];
              pDest.afMetric[Integer(lpTOP)] := KNOWN;
              pDest.afMetric[Integer(lpBOTTOM)] := KNOWN;
            end;
          end;
          Inc(pSrc);
          Inc(pDest);
        end;

        PtRule.fState := APPLIED;

        Result := TRUE;
        Exit;
     end;

     else
       begin
         adgFAIL('Invalid action');
         Result := FALSE;
       end;
  end;
end;

function Layout_ComputeLayout(hWndParent: HWND; pRules: PRule): BOOL; stdcall;
var
  hdwp: THandle; // HDWP;
  PtChild, pChildList: PChild;
  nChildren: Integer;
  hWndChild: HWND;
begin
 // Check assumptions.
 // adgASSERT(IsWindow(hwndParent));
 // adgASSERT(pRules);

  Result := TRUE;
  
 // Don't do anything to a minimized window.
  if IsIconic(hWndParent) then Exit; // return(TRUE);

 // Enumerate all child windows of the dialog, allocating a CHILD structure
 // for each child, with all six metric flags set to KNOWN. To simplify
 // coding, we also add a special CHILD structure for the parent window with
 // the id lPARENT (defined in layout.h). If there are no children, or
 // memory cannot be allocated for the child list, we do nothing.
  pChildList := Layout_CreateChildList(hWndParent, @nChildren);
  if (pChildList = nil) then begin Result := FALSE; Exit; end; // return(FALSE);
  if (nChildren = 0) then begin Result := TRUE; Exit; end; // return(TRUE);

 // Apply the rules from the rule list to solve for the locations of all the
 // child controls.
  if (Layout_ApplyRules(hWndParent, pRules, pChildList) = FALSE) then
  begin
    adgFAIL('Unable to apply rules');
    Result := FALSE;
    Exit; // return(FALSE);
  end;

 // Simultaneously relocate all the children using DeferWindowPos.
  hdwp := BeginDeferWindowPos(0);
 // adgASSERT(hdwp);

 // Move each child in the CHILD list. We enumerate the child list starting
 // at pChildList + 1, because the first CHILD is lPARENT.
  PtChild := pChildList;
  Inc(PtChild);
  while (PtChild.idc <> IDC_LASTCHILD) do // ; pChild++
  begin
   // Check child for any still-unsolved metrics. You may want to remove or
   // #ifdef out this check once your rules are known to be working.
    if (Layout_CheckChild(PtChild^) = FALSE) then Result := FALSE;

   // Add child to DeferWindowPos list if it is not fixed.
    if (PtChild.fFixed = FALSE) then
    begin
     // HWND hwndChild = GetDlgItem(hwndParent, pChild->idc);
      hWndChild := GetDlgItem(hWndParent, PtChild.idc);
     // adgASSERT(pChild->anMetric[lpWIDTH] >= 0);
     // adgASSERT(pChild->anMetric[lpHEIGHT] >= 0);
      hdwp := DeferWindowPos(hdwp, hWndChild, 0,
        PtChild.anMetric[Integer(lpLEFT)], PtChild.anMetric[Integer(lpTOP)],
        PtChild.anMetric[Integer(lpWIDTH)], PtChild.anMetric[Integer(lpHEIGHT)],
        SWP_NOZORDER);
     // adgASSERT(hdwp);

    // Invalidation is necessary here because some controls (edit
    // controls in particular) don't repaint correctly under Windows NT
    // when they are moved with DeferWindowPos.
      InvalidateRect(hWndChild, nil, TRUE);
    end;
    Inc(PtChild);
  end;

  // It is this function call which actually moves all the windows.
   EndDeferWindowPos(hdwp);

  // Free the allocated list of CHILD structures
   FreeMem(pChildList);
end;

end.

⌨️ 快捷键说明

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